mirror of
https://github.com/GreptimeTeam/greptimedb.git
synced 2026-10-22 11:52:33 +00:00
* fix(promql): align timestamp() and label_join with Prometheus semantics
- timestamp() over a selector reports the selected sample's timestamp, without adding the offset.
- timestamp() over any other expression reports the evaluation time instead of the input value.
- label_join that overwrites an existing label rejects duplicate label sets at runtime.
Signed-off-by: Dennis Zhuang <killme2008@gmail.com>
* fix(promql): align label_replace and label_join edge cases with Prometheus
- label_replace leaves non-matching series unchanged instead of copying the source value into the destination label.
- label_replace may overwrite an existing label; duplicate label sets are rejected at runtime like label_join.
- label_join with no source labels removes the destination label, and an empty source label name is rejected.
- Empty label values produced by these functions are NULL, the same as an absent label.
Signed-off-by: Dennis Zhuang <killme2008@gmail.com>
* fix(promql): join absent labels as empty strings in label_join
concat_ws skips NULL arguments together with their separator, so a label that is absent (NULL) dropped its separator, e.g. label_join(label_join(vector(1), "a", "", "missing"), "b", "-", "a", "a") lost b="-". Read every source label as coalesce(label, '') like label_replace does.
Signed-off-by: Dennis Zhuang <killme2008@gmail.com>
* fix(promql): skip rows without a sample in timestamp()
timestamp() replaced the input fields with the timestamp before the empty-value filter ran, so a row whose fields were all NULL got a timestamp, e.g. timestamp(-m) for a NULL sample. Filter such rows before the projection, for both the selector and the evaluation-time paths.
Signed-off-by: Dennis Zhuang <killme2008@gmail.com>
---------
Signed-off-by: Dennis Zhuang <killme2008@gmail.com>
(cherry picked from commit 78a7b93292)
Signed-off-by: WenyXu <wenymedia@gmail.com>
147 lines
4.9 KiB
SQL
147 lines
4.9 KiB
SQL
CREATE TABLE test (
|
|
ts timestamp(3) time index,
|
|
host STRING,
|
|
idc STRING,
|
|
val BIGINT,
|
|
PRIMARY KEY(host, idc),
|
|
);
|
|
|
|
INSERT INTO TABLE test VALUES
|
|
(0, 'host1', 'idc1', 1),
|
|
(0, 'host2', 'idc1', 2),
|
|
(5000, 'host1', 'idc2:zone1',3),
|
|
(5000, 'host2', 'idc2',4),
|
|
(10000, 'host1', 'idc3:zone2',5),
|
|
(10000, 'host2', 'idc3',6),
|
|
(15000, 'host1', 'idc4:zone3',7),
|
|
(15000, 'host2', 'idc4',8);
|
|
|
|
-- Missing source labels --
|
|
-- SQLNESS SORT_RESULT 3 1
|
|
TQL EVAL (0, 15, '5s') label_join(test{host="host1"}, "new_host", "-");
|
|
|
|
-- dst_label is equal to source label --
|
|
-- SQLNESS SORT_RESULT 3 1
|
|
TQL EVAL (0, 15, '5s') label_join(test{host="host1"}, "host", "-", "host");
|
|
|
|
-- dst_label is in source labels --
|
|
-- SQLNESS SORT_RESULT 3 1
|
|
TQL EVAL (0, 15, '5s') label_join(test{host="host1"}, "host", "-", "idc", "host");
|
|
|
|
-- Absent labels join as empty strings and keep their separators --
|
|
TQL EVAL (0, 15, '5s') label_join(label_join(vector(1), "a", "", "missing"), "b", "-", "a", "a");
|
|
|
|
-- An empty source label name is invalid --
|
|
TQL EVAL (0, 15, '5s') label_join(test{host="host1"}, "host", "-", "");
|
|
|
|
-- Both hosts are joined to the same `host` at 0s, leaving two series with the same label set --
|
|
TQL EVAL (0, 15, '5s') label_join(test, "host", "-", "idc");
|
|
|
|
-- SQLNESS SORT_RESULT 3 1
|
|
TQL EVAL (0, 15, '5s') label_join(test{host="host1"}, "new_host", "-", "idc", "host");
|
|
|
|
-- Should return empty result instead of error
|
|
tql eval label_join(demo_num_cpus, "new_label", "-", "instance", "job");
|
|
|
|
-- SQLNESS SORT_RESULT 3 1
|
|
TQL EVAL (0, 15, '5s') label_replace(test{host="host1"}, "new_idc", "$2", "idc", "(.*):(.*)");
|
|
|
|
-- SQLNESS SORT_RESULT 3 1
|
|
TQL EVAL (0, 15, '5s') label_replace(test{host="host1"}, "new_idc", "idc99", "idc", "idc2.*");
|
|
|
|
-- SQLNESS SORT_RESULT 3 1
|
|
TQL EVAL (0, 15, '5s') label_replace(test{host="host2"}, "new_idc", "$2", "idc", "(.*):(.*)");
|
|
|
|
-- dst_label is equal to source label --
|
|
-- SQLNESS SORT_RESULT 3 1
|
|
TQL EVAL (0, 15, '5s') label_replace(test{host="host2"}, "idc", "$2", "idc", "(.*):(.*)");
|
|
|
|
-- SQLNESS SORT_RESULT 3 1
|
|
TQL EVAL (0, 15, '5s') label_replace(test{host="host1"}, "idc", "$2", "idc", "(.*):(.*)");
|
|
|
|
-- Both hosts are rewritten to the same `host`, leaving two series with the same label set --
|
|
TQL EVAL (0, 15, '5s') label_replace(test, "host", "x", "host", ".*");
|
|
|
|
-- test the empty source label --
|
|
-- SQLNESS SORT_RESULT 3 1
|
|
TQL EVAL (0, 15, '5s') label_replace(test{host="host2"}, "idc2", "", "", "");
|
|
|
|
-- Issue 5726 --
|
|
-- SQLNESS SORT_RESULT 3 1
|
|
TQL EVAL(0, 15, '5s') label_replace(vector(1), "host", "host1", "", "");
|
|
|
|
-- SQLNESS SORT_RESULT 3 1
|
|
TQL EVAL(0, 15, '5s') {__name__="test",host="host1"} * label_replace(vector(1), "host", "host1", "", "");
|
|
|
|
-- SQLNESS SORT_RESULT 3 1
|
|
TQL EVAL(0, 15, '5s') {__name__="test",host="host1"} + label_replace(vector(1), "host", "host1", "", "");
|
|
|
|
-- Empty regex with existing source label
|
|
-- SQLNESS SORT_RESULT 3 1
|
|
TQL EVAL(0, 15, '5s') label_replace(test{host="host1"}, "host2", "host2", "host", "");
|
|
|
|
-- Empty regex with not existing source label
|
|
-- SQLNESS SORT_RESULT 3 1
|
|
TQL EVAL(0, 15, '5s') label_replace(test{host="host1"}, "host2", "host2", "instance", "");
|
|
|
|
-- Empty regex with not existing source label, but replacement is empty
|
|
-- SQLNESS SORT_RESULT 3 1
|
|
TQL EVAL(0, 15, '5s') label_replace(test{host="host1"}, "host2", "", "instance", "");
|
|
|
|
-- An empty replacement removes an existing label --
|
|
-- SQLNESS SORT_RESULT 3 1
|
|
TQL EVAL (0, 15, '5s') label_replace(test{idc="idc1"}, "idc", "", "instance", "");
|
|
|
|
-- Empty regex and different label value
|
|
-- SQLNESS SORT_RESULT 3 1
|
|
TQL EVAL(0, 15, '5s') {__name__="test",host="host1"} * label_replace(vector(1), "host", "host2", "host", "");
|
|
|
|
-- Empty regex and not existing label in left expression
|
|
-- SQLNESS SORT_RESULT 3 1
|
|
TQL EVAL(0, 15, '5s') {__name__="test",host="host1"} * label_replace(vector(1), "addr", "host1", "instance", "");
|
|
|
|
TQL EVAL label_replace(demo_num_cpus, "~invalid", "", "src", "(.*)");
|
|
|
|
TQL EVAL label_replace(demo_num_cpus, "job", "value", "src", "(.*");
|
|
|
|
-- Issue 6438 --
|
|
-- SQLNESS SORT_RESULT 3 1
|
|
TQL EVAL (0, 15, '5s') label_replace(test{host="host1"}, "new_idc", "idc99", "idc", "idc2.*") == 1.0;
|
|
|
|
-- SQLNESS SORT_RESULT 3 1
|
|
TQL EVAL (0, 15, '5s') label_join(test{host="host1"}, "new_host", "-", "idc", "host") == 3;
|
|
|
|
-- Issue 8969 --
|
|
-- SQLNESS SORT_RESULT 3 1
|
|
TQL EVAL (0, 15, '5s') sum by (foo) (label_replace(test, "foo", "$1", "host", "(.*)")) * 0.8;
|
|
|
|
DROP TABLE test;
|
|
|
|
CREATE TABLE test (
|
|
ts timestamp(3) time index,
|
|
host STRING,
|
|
val BIGINT,
|
|
PRIMARY KEY(host),
|
|
);
|
|
|
|
INSERT INTO TABLE test VALUES
|
|
(0, 'host1', 1),
|
|
(0, 'host2', 2);
|
|
|
|
SELECT * FROM test;
|
|
|
|
-- test the non-existent matchers --
|
|
TQL EVAL (0, 1, '5s') test{job=~"host1|host3"};
|
|
|
|
-- SQLNESS SORT_RESULT 3 1
|
|
TQL EVAL (0, 1, '5s') test{job=~".*"};
|
|
|
|
TQL EVAL (0, 1, '5s') test{job=~".+"};
|
|
|
|
-- SQLNESS SORT_RESULT 3 1
|
|
TQL EVAL (0, 1, '5s') test{job=""};
|
|
|
|
TQL EVAL (0, 1, '5s') test{job!=""};
|
|
|
|
DROP TABLE test;
|