Skip to content

Commit aadfa0e

Browse files
authored
fix: quote column name in prom query filter (#1083)
## Rationale PromQL query should be case-sensitive for column name ## Detailed Changes - Use `ident` when construct filter. ## Test Plan Update integration tests and UT
1 parent 37d2dda commit aadfa0e

File tree

2 files changed

+19
-14
lines changed

2 files changed

+19
-14
lines changed

integration_tests/prom/remote-query.py

+11-7
Original file line numberDiff line numberDiff line change
@@ -31,23 +31,23 @@ def prepare_data(ts):
3131
CREATE TABLE if not exists `{}` (
3232
`t` timestamp NOT NULL,
3333
`tag1` string TAG,
34-
`tag2` string TAG,
34+
`TAG2` string TAG,
3535
`value` double NOT NULL,
3636
`VALUE2` double NOT NULL,
3737
timestamp KEY (t)
3838
);
3939
""".format(t))
4040

4141
execute_sql("""
42-
insert into {}(t, tag1, tag2, value, VALUE2)
42+
insert into {}(t, tag1, TAG2, value, VALUE2)
4343
values
4444
({}, "v1", "v2", 1, 2),
4545
({}, "v1", "v2", 11, 22)
4646
;
4747
""".format(table, ts-5000, ts))
4848

4949
execute_sql("""
50-
insert into {}(t, tag1, tag2, value, VALUE2)
50+
insert into {}(t, tag1, TAG2, value, VALUE2)
5151
values
5252
({}, "v1", "v2", 10, 20),
5353
({}, "v1", "v2", 110, 220)
@@ -60,11 +60,15 @@ def remote_query(ts):
6060

6161
r = execute_pql(table + '{tag1="v1"}[5m]')
6262
result = r['data']['result']
63-
assert result == [{'metric': {'__name__': table, 'tag1': 'v1', 'tag2': 'v2'}, 'values': [[ts-5, '1'], [ts, '11']]}]
63+
assert result == [{'metric': {'__name__': table, 'tag1': 'v1', 'TAG2': 'v2'}, 'values': [[ts-5, '1'], [ts, '11']]}]
64+
65+
r = execute_pql(table + '{TAG2="v2"}[5m]')
66+
result = r['data']['result']
67+
assert result == [{'metric': {'__name__': table, 'tag1': 'v1', 'TAG2': 'v2'}, 'values': [[ts-5, '1'], [ts, '11']]}]
6468

6569
r = execute_pql(table + '{tag1=~"v1"}[5m]')
6670
result = r['data']['result']
67-
assert result == [{'metric': {'__name__': table, 'tag1': 'v1', 'tag2': 'v2'}, 'values': [[ts-5, '1'], [ts, '11']]}]
71+
assert result == [{'metric': {'__name__': table, 'tag1': 'v1', 'TAG2': 'v2'}, 'values': [[ts-5, '1'], [ts, '11']]}]
6872

6973
r = execute_pql(table + '{tag1!="v1"}[5m]')
7074
result = r['data']['result']
@@ -77,12 +81,12 @@ def remote_query(ts):
7781
# uppercase field
7882
r = execute_pql(table + '{tag1="v1",__ceresdb_field__="VALUE2"}[5m]')
7983
result = r['data']['result']
80-
assert result == [{'metric': {'__name__': table, 'tag1': 'v1', 'tag2': 'v2'}, 'values': [[ts-5, '2'], [ts, '22']]}]
84+
assert result == [{'metric': {'__name__': table, 'tag1': 'v1', 'TAG2': 'v2'}, 'values': [[ts-5, '2'], [ts, '22']]}]
8185

8286
# uppercase table
8387
r = execute_pql(table2 + '{tag1="v1"}[5m]')
8488
result = r['data']['result']
85-
assert result == [{'metric': {'__name__': table2, 'tag1': 'v1', 'tag2': 'v2'}, 'values': [[ts-5, '10'], [ts, '110']]}]
89+
assert result == [{'metric': {'__name__': table2, 'tag1': 'v1', 'TAG2': 'v2'}, 'values': [[ts-5, '10'], [ts, '110']]}]
8690

8791
def main():
8892
ts = now()

query_frontend/src/promql/remote.rs

+8-7
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@ use common_types::{schema::Schema, time::TimeRange};
88
use datafusion::{
99
logical_expr::LogicalPlanBuilder,
1010
optimizer::utils::conjunction,
11-
prelude::{col, lit, regexp_match, Expr},
11+
prelude::{ident, lit, regexp_match, Expr},
1212
sql::{planner::ContextProvider, TableReference},
1313
};
1414
use prom_remote_api::types::{label_matcher, LabelMatcher, Query};
@@ -95,16 +95,17 @@ fn normalize_matchers(matchers: Vec<LabelMatcher>) -> Result<(String, String, Ve
9595
NAME_LABEL => metric = Some(m.value),
9696
FIELD_LABEL => field = Some(m.value),
9797
_ => {
98+
let col_name = ident(&m.name);
9899
let expr = match m.r#type() {
99-
label_matcher::Type::Eq => col(m.name).eq(lit(m.value)),
100-
label_matcher::Type::Neq => col(m.name).not_eq(lit(m.value)),
100+
label_matcher::Type::Eq => col_name.eq(lit(m.value)),
101+
label_matcher::Type::Neq => col_name.not_eq(lit(m.value)),
101102
// https://github.com/prometheus/prometheus/blob/2ce94ac19673a3f7faf164e9e078a79d4d52b767/model/labels/regexp.go#L29
102103
label_matcher::Type::Re => {
103-
regexp_match(vec![col(m.name), lit(format!("^(?:{})$", m.value))])
104+
regexp_match(vec![col_name, lit(format!("^(?:{})$", m.value))])
104105
.is_not_null()
105106
}
106107
label_matcher::Type::Nre => {
107-
regexp_match(vec![col(m.name), lit(format!("^(?:{})$", m.value))]).is_null()
108+
regexp_match(vec![col_name, lit(format!("^(?:{})$", m.value))]).is_null()
108109
}
109110
};
110111

@@ -215,7 +216,7 @@ Query(QueryPlan { df_plan: Sort: cpu.tsid ASC NULLS FIRST, cpu.time ASC NULLS FI
215216
("a", "1", Type::Eq),
216217
("b", "2", Type::Neq),
217218
("c", "3", Type::Re),
218-
("d", "4", Type::Nre),
219+
("D", "4", Type::Nre),
219220
(NAME_LABEL, "cpu", Type::Eq),
220221
]);
221222

@@ -226,7 +227,7 @@ Query(QueryPlan { df_plan: Sort: cpu.tsid ASC NULLS FIRST, cpu.time ASC NULLS FI
226227
r#"a = Utf8("1")
227228
b != Utf8("2")
228229
regexpmatch(c, Utf8("^(?:3)$")) IS NOT NULL
229-
regexpmatch(d, Utf8("^(?:4)$")) IS NULL"#,
230+
regexpmatch(D, Utf8("^(?:4)$")) IS NULL"#,
230231
filters
231232
.iter()
232233
.map(|f| f.to_string())

0 commit comments

Comments
 (0)