From 65e7e245b71a7749cb25de7de4ddb46036fdd7bd Mon Sep 17 00:00:00 2001 From: discord9 <55937128+discord9@users.noreply.github.com> Date: Tue, 29 Sep 2026 19:48:58 +0800 Subject: [PATCH] test(sqlness): cover PromQL metric name output boundary Signed-off-by: discord9 <55937128+discord9@users.noreply.github.com> --- .../promql/native_time_selection.result | 92 ++- .../common/promql/precisions.result | 132 ++-- .../tsid_histogram_quantile_regression.result | 7 +- .../common/tql-explain-analyze/explain.result | 174 +++-- .../common/tql/metric_name_output.result | 70 ++ .../common/tql/metric_name_output.sql | 34 + .../standalone/common/tql/tql-cte.result | 739 +++++++++--------- 7 files changed, 719 insertions(+), 529 deletions(-) create mode 100644 tests/cases/standalone/common/tql/metric_name_output.result create mode 100644 tests/cases/standalone/common/tql/metric_name_output.sql diff --git a/tests/cases/standalone/common/promql/native_time_selection.result b/tests/cases/standalone/common/promql/native_time_selection.result index 945189e68f6..1b969b62109 100644 --- a/tests/cases/standalone/common/promql/native_time_selection.result +++ b/tests/cases/standalone/common/promql/native_time_selection.result @@ -39,21 +39,23 @@ Affected Rows: 18 -- SQLNESS REPLACE native_time_us.__table_id\s*=\s*UInt32\(\d+\) native_time_us.__table_id=UInt32(REDACTED) TQL EXPLAIN (1, 1, '1s', '1ms') native_time_us{series="exact"}; -+---------------+----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+ -| plan_type | plan | -+---------------+----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+ -| logical_plan | MergeScan [is_placeholder=false, remote_input=[ | -| | PromInstantManipulate: range=[1000..1000], lookback=[1], interval=[1000], time index=[ts] | -| | PromSeriesDivide: tags=["series"] | -| | Sort: native_time_us.series ASC NULLS FIRST, native_time_us.ts ASC NULLS FIRST | -| | Projection: native_time_us.val, native_time_us.series, native_time_us.ts | -| | Filter: native_time_us.series = Utf8("exact") AND native_time_us.ts > TimestampMicrosecond(999000, None) AND native_time_us.ts <= TimestampMicrosecond(1000000, None) | -| | TableScan: native_time_us, partial_filters=[native_time_us.series = Utf8("exact"), native_time_us.ts > TimestampMicrosecond(999000, None), native_time_us.ts <= TimestampMicrosecond(1000000, None)] | -| | ]] | -| physical_plan | CooperativeExec | ++---------------+--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+ +| plan_type | plan | ++---------------+--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+ +| logical_plan | MergeScan [is_placeholder=false, remote_input=[ | +| | Projection: native_time_us.val, native_time_us.series, native_time_us.ts | +| | Projection: native_time_us.val, native_time_us.series, native_time_us.ts, Utf8("native_time_us") FieldMetadata { inner: {"greptime:promql:role": "metric_name"} } AS __promql_metric_name | +| | PromInstantManipulate: range=[1000..1000], lookback=[1], interval=[1000], time index=[ts] | +| | PromSeriesDivide: tags=["series"] | +| | Sort: native_time_us.series ASC NULLS FIRST, native_time_us.ts ASC NULLS FIRST | +| | Projection: native_time_us.val, native_time_us.series, native_time_us.ts | +| | Filter: native_time_us.series = Utf8("exact") AND native_time_us.ts > TimestampMicrosecond(999000, None) AND native_time_us.ts <= TimestampMicrosecond(1000000, None) | +| | TableScan: native_time_us, partial_filters=[native_time_us.series = Utf8("exact"), native_time_us.ts > TimestampMicrosecond(999000, None), native_time_us.ts <= TimestampMicrosecond(1000000, None)] | +| | ]] | +| physical_plan | CooperativeExec | | | MergeScanExec: REDACTED -| | | -+---------------+----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+ +| | | ++---------------+--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+ -- The actual memtable scan must use LastRow { after_merge: true } with native -- 1ms-lookback bounds; it must select exact 1s rather than the future tick. @@ -286,21 +288,23 @@ Affected Rows: 18 -- SQLNESS REPLACE native_time_ns.__table_id\s*=\s*UInt32\(\d+\) native_time_ns.__table_id=UInt32(REDACTED) TQL EXPLAIN (1, 1, '1s', '1ms') native_time_ns{series="exact"}; -+---------------+--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+ -| plan_type | plan | -+---------------+--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+ -| logical_plan | MergeScan [is_placeholder=false, remote_input=[ | -| | PromInstantManipulate: range=[1000..1000], lookback=[1], interval=[1000], time index=[ts] | -| | PromSeriesDivide: tags=["series"] | -| | Sort: native_time_ns.series ASC NULLS FIRST, native_time_ns.ts ASC NULLS FIRST | -| | Projection: native_time_ns.val, native_time_ns.series, native_time_ns.ts | -| | Filter: native_time_ns.series = Utf8("exact") AND native_time_ns.ts > TimestampNanosecond(999000000, None) AND native_time_ns.ts <= TimestampNanosecond(1000000000, None) | -| | TableScan: native_time_ns, partial_filters=[native_time_ns.series = Utf8("exact"), native_time_ns.ts > TimestampNanosecond(999000000, None), native_time_ns.ts <= TimestampNanosecond(1000000000, None)] | -| | ]] | -| physical_plan | CooperativeExec | ++---------------+------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+ +| plan_type | plan | ++---------------+------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+ +| logical_plan | MergeScan [is_placeholder=false, remote_input=[ | +| | Projection: native_time_ns.val, native_time_ns.series, native_time_ns.ts | +| | Projection: native_time_ns.val, native_time_ns.series, native_time_ns.ts, Utf8("native_time_ns") FieldMetadata { inner: {"greptime:promql:role": "metric_name"} } AS __promql_metric_name | +| | PromInstantManipulate: range=[1000..1000], lookback=[1], interval=[1000], time index=[ts] | +| | PromSeriesDivide: tags=["series"] | +| | Sort: native_time_ns.series ASC NULLS FIRST, native_time_ns.ts ASC NULLS FIRST | +| | Projection: native_time_ns.val, native_time_ns.series, native_time_ns.ts | +| | Filter: native_time_ns.series = Utf8("exact") AND native_time_ns.ts > TimestampNanosecond(999000000, None) AND native_time_ns.ts <= TimestampNanosecond(1000000000, None) | +| | TableScan: native_time_ns, partial_filters=[native_time_ns.series = Utf8("exact"), native_time_ns.ts > TimestampNanosecond(999000000, None), native_time_ns.ts <= TimestampNanosecond(1000000000, None)] | +| | ]] | +| physical_plan | CooperativeExec | | | MergeScanExec: REDACTED -| | | -+---------------+--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+ +| | | ++---------------+------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+ -- The actual memtable scan must use LastRow { after_merge: true } with native -- 1ms-lookback bounds; it must select exact 1s rather than the future tick. @@ -516,22 +520,24 @@ Affected Rows: 2 -- SQLNESS REPLACE native_time_ns_lower_overflow.__table_id\s*=\s*UInt32\(\d+\) native_time_ns_lower_overflow.__table_id=UInt32(REDACTED) TQL EXPLAIN (0, 0, '1s', '2d') native_time_ns_lower_overflow{series="exact"} offset 106750d; -+---------------+-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+ -| plan_type | plan | -+---------------+-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+ -| logical_plan | MergeScan [is_placeholder=false, remote_input=[ | -| | PromInstantManipulate: range=[0..0], lookback=[172800000], interval=[1000], time index=[ts] | -| | PromSeriesNormalize: offset=[9223200000000], time index=[ts], filter NaN: [false] | -| | PromSeriesDivide: tags=["series"] | -| | Sort: native_time_ns_lower_overflow.series ASC NULLS FIRST, native_time_ns_lower_overflow.ts ASC NULLS FIRST | -| | Projection: native_time_ns_lower_overflow.val, native_time_ns_lower_overflow.series, native_time_ns_lower_overflow.ts | -| | Filter: native_time_ns_lower_overflow.series = Utf8("exact") AND native_time_ns_lower_overflow.ts <= TimestampNanosecond(-9223200000000000000, None) | -| | TableScan: native_time_ns_lower_overflow, partial_filters=[native_time_ns_lower_overflow.series = Utf8("exact"), native_time_ns_lower_overflow.ts <= TimestampNanosecond(-9223200000000000000, None)] | -| | ]] | -| physical_plan | CooperativeExec | ++---------------+---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+ +| plan_type | plan | ++---------------+---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+ +| logical_plan | MergeScan [is_placeholder=false, remote_input=[ | +| | Projection: native_time_ns_lower_overflow.val, native_time_ns_lower_overflow.series, native_time_ns_lower_overflow.ts | +| | Projection: native_time_ns_lower_overflow.val, native_time_ns_lower_overflow.series, native_time_ns_lower_overflow.ts, Utf8("native_time_ns_lower_overflow") FieldMetadata { inner: {"greptime:promql:role": "metric_name"} } AS __promql_metric_name | +| | PromInstantManipulate: range=[0..0], lookback=[172800000], interval=[1000], time index=[ts] | +| | PromSeriesNormalize: offset=[9223200000000], time index=[ts], filter NaN: [false] | +| | PromSeriesDivide: tags=["series"] | +| | Sort: native_time_ns_lower_overflow.series ASC NULLS FIRST, native_time_ns_lower_overflow.ts ASC NULLS FIRST | +| | Projection: native_time_ns_lower_overflow.val, native_time_ns_lower_overflow.series, native_time_ns_lower_overflow.ts | +| | Filter: native_time_ns_lower_overflow.series = Utf8("exact") AND native_time_ns_lower_overflow.ts <= TimestampNanosecond(-9223200000000000000, None) | +| | TableScan: native_time_ns_lower_overflow, partial_filters=[native_time_ns_lower_overflow.series = Utf8("exact"), native_time_ns_lower_overflow.ts <= TimestampNanosecond(-9223200000000000000, None)] | +| | ]] | +| physical_plan | CooperativeExec | | | MergeScanExec: REDACTED -| | | -+---------------+-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+ +| | | ++---------------+---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+ -- SQLNESS REPLACE (RoundRobinBatch.*) REDACTED -- SQLNESS REPLACE (Hash.*) REDACTED diff --git a/tests/cases/standalone/common/promql/precisions.result b/tests/cases/standalone/common/promql/precisions.result index 4026a358322..90b1b128465 100644 --- a/tests/cases/standalone/common/promql/precisions.result +++ b/tests/cases/standalone/common/promql/precisions.result @@ -143,21 +143,23 @@ TQL EVAL (0, 15, '5s') avg_over_time(host_sec{host="host1"}[5s]) + avg_over_time -- SQLNESS REPLACE host_nano.__table_id\s*=\s*UInt32\(\d+\) host_nano.__table_id=UInt32(REDACTED) TQL EXPLAIN (0, 10, '5s') host_micro{host="host1"}; -+---------------+---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+ -| plan_type | plan | -+---------------+---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+ -| logical_plan | MergeScan [is_placeholder=false, remote_input=[ | -| | PromInstantManipulate: range=[0..10000], lookback=[300000], interval=[5000], time index=[ts] | -| | PromSeriesDivide: tags=["host"] | -| | Sort: host_micro.host ASC NULLS FIRST, host_micro.ts ASC NULLS FIRST | -| | Projection: host_micro.val, host_micro.host, host_micro.ts | -| | Filter: host_micro.host = Utf8("host1") AND host_micro.ts > TimestampMicrosecond(-300000000, None) AND host_micro.ts <= TimestampMicrosecond(10000000, None) | -| | TableScan: host_micro, partial_filters=[host_micro.host = Utf8("host1"), host_micro.ts > TimestampMicrosecond(-300000000, None), host_micro.ts <= TimestampMicrosecond(10000000, None)] | -| | ]] | -| physical_plan | CooperativeExec | ++---------------+-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+ +| plan_type | plan | ++---------------+-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+ +| logical_plan | MergeScan [is_placeholder=false, remote_input=[ | +| | Projection: host_micro.val, host_micro.host, host_micro.ts | +| | Projection: host_micro.val, host_micro.host, host_micro.ts, Utf8("host_micro") FieldMetadata { inner: {"greptime:promql:role": "metric_name"} } AS __promql_metric_name | +| | PromInstantManipulate: range=[0..10000], lookback=[300000], interval=[5000], time index=[ts] | +| | PromSeriesDivide: tags=["host"] | +| | Sort: host_micro.host ASC NULLS FIRST, host_micro.ts ASC NULLS FIRST | +| | Projection: host_micro.val, host_micro.host, host_micro.ts | +| | Filter: host_micro.host = Utf8("host1") AND host_micro.ts > TimestampMicrosecond(-300000000, None) AND host_micro.ts <= TimestampMicrosecond(10000000, None) | +| | TableScan: host_micro, partial_filters=[host_micro.host = Utf8("host1"), host_micro.ts > TimestampMicrosecond(-300000000, None), host_micro.ts <= TimestampMicrosecond(10000000, None)] | +| | ]] | +| physical_plan | CooperativeExec | | | MergeScanExec: REDACTED -| | | -+---------------+---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+ +| | | ++---------------+-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+ -- The same exclusive-lower, inclusive-upper window applies to nanosecond indexes. -- Expected native bounds: ts_ns > -300000000000ns AND ts_ns <= 10000000000ns. @@ -168,21 +170,23 @@ TQL EXPLAIN (0, 10, '5s') host_micro{host="host1"}; -- SQLNESS REPLACE host_nano.__table_id\s*=\s*UInt32\(\d+\) host_nano.__table_id=UInt32(REDACTED) TQL EXPLAIN (0, 10, '5s') host_nano{host="host1"}; -+---------------+---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+ -| plan_type | plan | -+---------------+---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+ -| logical_plan | MergeScan [is_placeholder=false, remote_input=[ | -| | PromInstantManipulate: range=[0..10000], lookback=[300000], interval=[5000], time index=[ts] | -| | PromSeriesDivide: tags=["host"] | -| | Sort: host_nano.host ASC NULLS FIRST, host_nano.ts ASC NULLS FIRST | -| | Projection: host_nano.val, host_nano.host, host_nano.ts | -| | Filter: host_nano.host = Utf8("host1") AND host_nano.ts > TimestampNanosecond(-300000000000, None) AND host_nano.ts <= TimestampNanosecond(10000000000, None) | -| | TableScan: host_nano, partial_filters=[host_nano.host = Utf8("host1"), host_nano.ts > TimestampNanosecond(-300000000000, None), host_nano.ts <= TimestampNanosecond(10000000000, None)] | -| | ]] | -| physical_plan | CooperativeExec | ++---------------+-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+ +| plan_type | plan | ++---------------+-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+ +| logical_plan | MergeScan [is_placeholder=false, remote_input=[ | +| | Projection: host_nano.val, host_nano.host, host_nano.ts | +| | Projection: host_nano.val, host_nano.host, host_nano.ts, Utf8("host_nano") FieldMetadata { inner: {"greptime:promql:role": "metric_name"} } AS __promql_metric_name | +| | PromInstantManipulate: range=[0..10000], lookback=[300000], interval=[5000], time index=[ts] | +| | PromSeriesDivide: tags=["host"] | +| | Sort: host_nano.host ASC NULLS FIRST, host_nano.ts ASC NULLS FIRST | +| | Projection: host_nano.val, host_nano.host, host_nano.ts | +| | Filter: host_nano.host = Utf8("host1") AND host_nano.ts > TimestampNanosecond(-300000000000, None) AND host_nano.ts <= TimestampNanosecond(10000000000, None) | +| | TableScan: host_nano, partial_filters=[host_nano.host = Utf8("host1"), host_nano.ts > TimestampNanosecond(-300000000000, None), host_nano.ts <= TimestampNanosecond(10000000000, None)] | +| | ]] | +| physical_plan | CooperativeExec | | | MergeScanExec: REDACTED -| | | -+---------------+---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+ +| | | ++---------------+-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+ -- Range selectors use their range window instead of the default lookback. -- Native range selector filter for [5s]: @@ -194,24 +198,26 @@ TQL EXPLAIN (0, 10, '5s') host_nano{host="host1"}; -- SQLNESS REPLACE host_micro.__table_id\s*=\s*UInt32\(\d+\) host_micro.__table_id=UInt32(REDACTED) TQL EXPLAIN (0, 10, '5s') avg_over_time(host_micro{host="host1"}[5s]); -+---------------+-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+ -| plan_type | plan | -+---------------+-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+ -| logical_plan | MergeScan [is_placeholder=false, remote_input=[ | -| | Filter: prom_avg_over_time(ts_range,val) IS NOT NULL | -| | Projection: host_micro.ts, prom_avg_over_time(ts_range, val) AS prom_avg_over_time(ts_range,val), host_micro.host | -| | PromRangeManipulate: req range=[0..10000], interval=[5000], eval range=[5000], time index=[ts], values=["val"] | -| | PromSeriesNormalize: offset=[0], time index=[ts], filter NaN: [true] | -| | PromSeriesDivide: tags=["host"] | -| | Sort: host_micro.host ASC NULLS FIRST, host_micro.ts ASC NULLS FIRST | -| | Projection: host_micro.val, host_micro.host, host_micro.ts | -| | Filter: host_micro.host = Utf8("host1") AND host_micro.ts > TimestampMicrosecond(-5000000, None) AND host_micro.ts <= TimestampMicrosecond(10000000, None) | -| | TableScan: host_micro, partial_filters=[host_micro.host = Utf8("host1"), host_micro.ts > TimestampMicrosecond(-5000000, None), host_micro.ts <= TimestampMicrosecond(10000000, None)] | -| | ]] | -| physical_plan | CooperativeExec | ++---------------+-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+ +| plan_type | plan | ++---------------+-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+ +| logical_plan | MergeScan [is_placeholder=false, remote_input=[ | +| | Projection: host_micro.ts, prom_avg_over_time(ts_range,val), host_micro.host | +| | Filter: prom_avg_over_time(ts_range,val) IS NOT NULL | +| | Projection: host_micro.ts, prom_avg_over_time(ts_range, val) AS prom_avg_over_time(ts_range,val), host_micro.host, __promql_metric_name | +| | Projection: val, host_micro.host, host_micro.ts, ts_range, Utf8("host_micro") FieldMetadata { inner: {"greptime:promql:role": "metric_name"} } AS __promql_metric_name | +| | PromRangeManipulate: req range=[0..10000], interval=[5000], eval range=[5000], time index=[ts], values=["val"] | +| | PromSeriesNormalize: offset=[0], time index=[ts], filter NaN: [true] | +| | PromSeriesDivide: tags=["host"] | +| | Sort: host_micro.host ASC NULLS FIRST, host_micro.ts ASC NULLS FIRST | +| | Projection: host_micro.val, host_micro.host, host_micro.ts | +| | Filter: host_micro.host = Utf8("host1") AND host_micro.ts > TimestampMicrosecond(-5000000, None) AND host_micro.ts <= TimestampMicrosecond(10000000, None) | +| | TableScan: host_micro, partial_filters=[host_micro.host = Utf8("host1"), host_micro.ts > TimestampMicrosecond(-5000000, None), host_micro.ts <= TimestampMicrosecond(10000000, None)] | +| | ]] | +| physical_plan | CooperativeExec | | | MergeScanExec: REDACTED -| | | -+---------------+-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+ +| | | ++---------------+-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+ -- Range membership also retains nanosecond precision. -- Expected native bounds: ts_ns > -5000000000ns AND ts_ns <= 10000000000ns. @@ -222,24 +228,26 @@ TQL EXPLAIN (0, 10, '5s') avg_over_time(host_micro{host="host1"}[5s]); -- SQLNESS REPLACE host_nano.__table_id\s*=\s*UInt32\(\d+\) host_nano.__table_id=UInt32(REDACTED) TQL EXPLAIN (0, 10, '5s') avg_over_time(host_nano{host="host1"}[5s]); -+---------------+-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+ -| plan_type | plan | -+---------------+-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+ -| logical_plan | MergeScan [is_placeholder=false, remote_input=[ | -| | Filter: prom_avg_over_time(ts_range,val) IS NOT NULL | -| | Projection: host_nano.ts, prom_avg_over_time(ts_range, val) AS prom_avg_over_time(ts_range,val), host_nano.host | -| | PromRangeManipulate: req range=[0..10000], interval=[5000], eval range=[5000], time index=[ts], values=["val"] | -| | PromSeriesNormalize: offset=[0], time index=[ts], filter NaN: [true] | -| | PromSeriesDivide: tags=["host"] | -| | Sort: host_nano.host ASC NULLS FIRST, host_nano.ts ASC NULLS FIRST | -| | Projection: host_nano.val, host_nano.host, host_nano.ts | -| | Filter: host_nano.host = Utf8("host1") AND host_nano.ts > TimestampNanosecond(-5000000000, None) AND host_nano.ts <= TimestampNanosecond(10000000000, None) | -| | TableScan: host_nano, partial_filters=[host_nano.host = Utf8("host1"), host_nano.ts > TimestampNanosecond(-5000000000, None), host_nano.ts <= TimestampNanosecond(10000000000, None)] | -| | ]] | -| physical_plan | CooperativeExec | ++---------------+-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+ +| plan_type | plan | ++---------------+-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+ +| logical_plan | MergeScan [is_placeholder=false, remote_input=[ | +| | Projection: host_nano.ts, prom_avg_over_time(ts_range,val), host_nano.host | +| | Filter: prom_avg_over_time(ts_range,val) IS NOT NULL | +| | Projection: host_nano.ts, prom_avg_over_time(ts_range, val) AS prom_avg_over_time(ts_range,val), host_nano.host, __promql_metric_name | +| | Projection: val, host_nano.host, host_nano.ts, ts_range, Utf8("host_nano") FieldMetadata { inner: {"greptime:promql:role": "metric_name"} } AS __promql_metric_name | +| | PromRangeManipulate: req range=[0..10000], interval=[5000], eval range=[5000], time index=[ts], values=["val"] | +| | PromSeriesNormalize: offset=[0], time index=[ts], filter NaN: [true] | +| | PromSeriesDivide: tags=["host"] | +| | Sort: host_nano.host ASC NULLS FIRST, host_nano.ts ASC NULLS FIRST | +| | Projection: host_nano.val, host_nano.host, host_nano.ts | +| | Filter: host_nano.host = Utf8("host1") AND host_nano.ts > TimestampNanosecond(-5000000000, None) AND host_nano.ts <= TimestampNanosecond(10000000000, None) | +| | TableScan: host_nano, partial_filters=[host_nano.host = Utf8("host1"), host_nano.ts > TimestampNanosecond(-5000000000, None), host_nano.ts <= TimestampNanosecond(10000000000, None)] | +| | ]] | +| physical_plan | CooperativeExec | | | MergeScanExec: REDACTED -| | | -+---------------+-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+ +| | | ++---------------+-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+ DROP TABLE host_sec; diff --git a/tests/cases/standalone/common/promql/tsid_histogram_quantile_regression.result b/tests/cases/standalone/common/promql/tsid_histogram_quantile_regression.result index 10b31cac1e1..864b9b9a6ab 100644 --- a/tests/cases/standalone/common/promql/tsid_histogram_quantile_regression.result +++ b/tests/cases/standalone/common/promql/tsid_histogram_quantile_regression.result @@ -108,12 +108,13 @@ TQL ANALYZE (0, 10, '5s') histogram_quantile(0.5, tsid_no_aggr_histogram_bucket) +-+-+-+ | stage | node | plan_| +-+-+-+ -| 0_| 0_|_HistogramFoldExec: le=@2, field=@0, quantile=0.5 REDACTED +| 0_| 0_|_ProjectionExec: expr=[val@0 as val, job@1 as job, ts@2 as ts] REDACTED +|_|_|_HistogramFoldExec: le=@2, field=@0, quantile=0.5 REDACTED |_|_|_RepartitionExec: partitioning=REDACTED -|_|_|_SortExec: expr=[job@1 ASC NULLS LAST, ts@3 ASC NULLS LAST, TRY_CAST(le@2 AS Float64) ASC NULLS LAST], preserve_partitioning=[false] REDACTED +|_|_|_SortExec: expr=[job@1 ASC NULLS LAST, __promql_metric_name@4 ASC NULLS LAST, ts@3 ASC NULLS LAST, TRY_CAST(le@2 AS Float64) ASC NULLS LAST], preserve_partitioning=[false] REDACTED |_|_|_MergeScanExec: REDACTED |_|_|_| -| 1_| 0_|_ProjectionExec: expr=[val@0 as val, job@1 as job, le@2 as le, ts@4 as ts] REDACTED +| 1_| 0_|_ProjectionExec: expr=[val@0 as val, job@1 as job, le@2 as le, ts@4 as ts, tsid_no_aggr_histogram_bucket as __promql_metric_name] REDACTED |_|_|_PromInstantManipulateExec: range=[0..10000], lookback=[300000], interval=[5000], time index=[ts] REDACTED |_|_|_PromSeriesDivideExec: tags=["__tsid"] REDACTED |_|_|_ProjectionExec: expr=[val@1 as val, job@3 as job, le@4 as le, __tsid@2 as __tsid, ts@0 as ts] REDACTED diff --git a/tests/cases/standalone/common/tql-explain-analyze/explain.result b/tests/cases/standalone/common/tql-explain-analyze/explain.result index 3e8b0ec2133..86a68f6c5d1 100644 --- a/tests/cases/standalone/common/tql-explain-analyze/explain.result +++ b/tests/cases/standalone/common/tql-explain-analyze/explain.result @@ -12,20 +12,22 @@ Affected Rows: 3 -- SQLNESS REPLACE (peers.*) REDACTED TQL EXPLAIN (0, 10, '5s') test; -+---------------+---------------------------------------------------------------------------------------------------------------------------------------+ -| plan_type | plan | -+---------------+---------------------------------------------------------------------------------------------------------------------------------------+ -| logical_plan | MergeScan [is_placeholder=false, remote_input=[ | -| | PromInstantManipulate: range=[0..10000], lookback=[300000], interval=[5000], time index=[j] | -| | PromSeriesDivide: tags=["k"] | -| | Sort: test.k ASC NULLS FIRST, test.j ASC NULLS FIRST | -| | Filter: test.j >= TimestampMillisecond(-299999, None) AND test.j <= TimestampMillisecond(10000, None) | -| | TableScan: test, partial_filters=[test.j >= TimestampMillisecond(-299999, None), test.j <= TimestampMillisecond(10000, None)] | -| | ]] | -| physical_plan | CooperativeExec | ++---------------+---------------------------------------------------------------------------------------------------------------------------------------------+ +| plan_type | plan | ++---------------+---------------------------------------------------------------------------------------------------------------------------------------------+ +| logical_plan | MergeScan [is_placeholder=false, remote_input=[ | +| | Projection: test.i, test.j, test.k | +| | Projection: test.i, test.j, test.k, Utf8("test") FieldMetadata { inner: {"greptime:promql:role": "metric_name"} } AS __promql_metric_name | +| | PromInstantManipulate: range=[0..10000], lookback=[300000], interval=[5000], time index=[j] | +| | PromSeriesDivide: tags=["k"] | +| | Sort: test.k ASC NULLS FIRST, test.j ASC NULLS FIRST | +| | Filter: test.j >= TimestampMillisecond(-299999, None) AND test.j <= TimestampMillisecond(10000, None) | +| | TableScan: test, partial_filters=[test.j >= TimestampMillisecond(-299999, None), test.j <= TimestampMillisecond(10000, None)] | +| | ]] | +| physical_plan | CooperativeExec | | | MergeScanExec: REDACTED -| | | -+---------------+---------------------------------------------------------------------------------------------------------------------------------------+ +| | | ++---------------+---------------------------------------------------------------------------------------------------------------------------------------------+ -- 'lookback' parameter is not fully supported, the test has to be updated -- explain at 0s, 5s and 10s. No point at 0s. @@ -33,40 +35,44 @@ TQL EXPLAIN (0, 10, '5s') test; -- SQLNESS REPLACE (peers.*) REDACTED TQL EXPLAIN (0, 10, '1s', '2s') test; -+---------------+-------------------------------------------------------------------------------------------------------------------------------------+ -| plan_type | plan | -+---------------+-------------------------------------------------------------------------------------------------------------------------------------+ -| logical_plan | MergeScan [is_placeholder=false, remote_input=[ | -| | PromInstantManipulate: range=[0..10000], lookback=[2000], interval=[1000], time index=[j] | -| | PromSeriesDivide: tags=["k"] | -| | Sort: test.k ASC NULLS FIRST, test.j ASC NULLS FIRST | -| | Filter: test.j >= TimestampMillisecond(-1999, None) AND test.j <= TimestampMillisecond(10000, None) | -| | TableScan: test, partial_filters=[test.j >= TimestampMillisecond(-1999, None), test.j <= TimestampMillisecond(10000, None)] | -| | ]] | -| physical_plan | CooperativeExec | ++---------------+---------------------------------------------------------------------------------------------------------------------------------------------+ +| plan_type | plan | ++---------------+---------------------------------------------------------------------------------------------------------------------------------------------+ +| logical_plan | MergeScan [is_placeholder=false, remote_input=[ | +| | Projection: test.i, test.j, test.k | +| | Projection: test.i, test.j, test.k, Utf8("test") FieldMetadata { inner: {"greptime:promql:role": "metric_name"} } AS __promql_metric_name | +| | PromInstantManipulate: range=[0..10000], lookback=[2000], interval=[1000], time index=[j] | +| | PromSeriesDivide: tags=["k"] | +| | Sort: test.k ASC NULLS FIRST, test.j ASC NULLS FIRST | +| | Filter: test.j >= TimestampMillisecond(-1999, None) AND test.j <= TimestampMillisecond(10000, None) | +| | TableScan: test, partial_filters=[test.j >= TimestampMillisecond(-1999, None), test.j <= TimestampMillisecond(10000, None)] | +| | ]] | +| physical_plan | CooperativeExec | | | MergeScanExec: REDACTED -| | | -+---------------+-------------------------------------------------------------------------------------------------------------------------------------+ +| | | ++---------------+---------------------------------------------------------------------------------------------------------------------------------------------+ -- explain at 0s, 5s and 10s. No point at 0s. -- SQLNESS REPLACE (RoundRobinBatch.*) REDACTED -- SQLNESS REPLACE (peers.*) REDACTED TQL EXPLAIN ('1970-01-01T00:00:00'::timestamp, '1970-01-01T00:00:00'::timestamp + '10 seconds'::interval, '5s') test; -+---------------+---------------------------------------------------------------------------------------------------------------------------------------+ -| plan_type | plan | -+---------------+---------------------------------------------------------------------------------------------------------------------------------------+ -| logical_plan | MergeScan [is_placeholder=false, remote_input=[ | -| | PromInstantManipulate: range=[0..10000], lookback=[300000], interval=[5000], time index=[j] | -| | PromSeriesDivide: tags=["k"] | -| | Sort: test.k ASC NULLS FIRST, test.j ASC NULLS FIRST | -| | Filter: test.j >= TimestampMillisecond(-299999, None) AND test.j <= TimestampMillisecond(10000, None) | -| | TableScan: test, partial_filters=[test.j >= TimestampMillisecond(-299999, None), test.j <= TimestampMillisecond(10000, None)] | -| | ]] | -| physical_plan | CooperativeExec | ++---------------+---------------------------------------------------------------------------------------------------------------------------------------------+ +| plan_type | plan | ++---------------+---------------------------------------------------------------------------------------------------------------------------------------------+ +| logical_plan | MergeScan [is_placeholder=false, remote_input=[ | +| | Projection: test.i, test.j, test.k | +| | Projection: test.i, test.j, test.k, Utf8("test") FieldMetadata { inner: {"greptime:promql:role": "metric_name"} } AS __promql_metric_name | +| | PromInstantManipulate: range=[0..10000], lookback=[300000], interval=[5000], time index=[j] | +| | PromSeriesDivide: tags=["k"] | +| | Sort: test.k ASC NULLS FIRST, test.j ASC NULLS FIRST | +| | Filter: test.j >= TimestampMillisecond(-299999, None) AND test.j <= TimestampMillisecond(10000, None) | +| | TableScan: test, partial_filters=[test.j >= TimestampMillisecond(-299999, None), test.j <= TimestampMillisecond(10000, None)] | +| | ]] | +| physical_plan | CooperativeExec | | | MergeScanExec: REDACTED -| | | -+---------------+---------------------------------------------------------------------------------------------------------------------------------------+ +| | | ++---------------+---------------------------------------------------------------------------------------------------------------------------------------------+ -- explain verbose at 0s, 5s and 10s. No point at 0s. -- SQLNESS REPLACE (-+) - @@ -80,7 +86,9 @@ TQL EXPLAIN VERBOSE (0, 10, '5s') test; +-+-+ | plan_type_| plan_| +-+-+ -| initial_logical_plan_| PromInstantManipulate: range=[0..10000], lookback=[300000], interval=[5000], time index=[j]_| +| initial_logical_plan_| Projection: test.i, test.j, test.k_| +|_|_Projection: test.i, test.j, test.k, Utf8("test") AS __promql_metric_name_| +|_|_PromInstantManipulate: range=[0..10000], lookback=[300000], interval=[5000], time index=[j]_| |_|_PromSeriesDivide: tags=["k"]_| |_|_Sort: test.k ASC NULLS FIRST, test.j ASC NULLS FIRST_| |_|_Filter: test.j >= TimestampMillisecond(-299999, None) AND test.j <= TimestampMillisecond(10000, None)_| @@ -94,11 +102,13 @@ TQL EXPLAIN VERBOSE (0, 10, '5s') test; | logical_plan after ConstNormalizationRule_| SAME TEXT AS ABOVE_| | logical_plan after DistPlannerAnalyzer_| Projection: test.i, test.j, test.k_| |_|_MergeScan [is_placeholder=false, remote_input=[_| -|_| PromInstantManipulate: range=[0..10000], lookback=[300000], interval=[5000], time index=[j]_| +|_| Projection: test.i, test.j, test.k_| +|_|_Projection: test.i, test.j, test.k, Utf8("test") FieldMetadata { inner: {"greptime:promql:role": "metric_name"} } AS __promql_metric_name | +|_|_PromInstantManipulate: range=[0..10000], lookback=[300000], interval=[5000], time index=[j]_| |_|_PromSeriesDivide: tags=["k"]_| |_|_Sort: test.k ASC NULLS FIRST, test.j ASC NULLS FIRST_| |_|_Filter: test.j >= TimestampMillisecond(-299999, None) AND test.j <= TimestampMillisecond(10000, None)_| -|_|_TableScan: test, partial_filters=[test.j >= TimestampMillisecond(-299999, None), test.j <= TimestampMillisecond(10000, None)] | +|_|_TableScan: test, partial_filters=[test.j >= TimestampMillisecond(-299999, None), test.j <= TimestampMillisecond(10000, None)]_| |_| ]]_| | logical_plan after JsonSchemaConcretizeRule_| SAME TEXT AS ABOVE_| | logical_plan after FixStateUdafOrderingAnalyzer_| SAME TEXT AS ABOVE_| @@ -128,11 +138,13 @@ TQL EXPLAIN VERBOSE (0, 10, '5s') test; | logical_plan after extract_leaf_expressions_| SAME TEXT AS ABOVE_| | logical_plan after push_down_leaf_projections_| SAME TEXT AS ABOVE_| | logical_plan after optimize_projections_| MergeScan [is_placeholder=false, remote_input=[_| -|_| PromInstantManipulate: range=[0..10000], lookback=[300000], interval=[5000], time index=[j]_| +|_| Projection: test.i, test.j, test.k_| +|_|_Projection: test.i, test.j, test.k, Utf8("test") FieldMetadata { inner: {"greptime:promql:role": "metric_name"} } AS __promql_metric_name | +|_|_PromInstantManipulate: range=[0..10000], lookback=[300000], interval=[5000], time index=[j]_| |_|_PromSeriesDivide: tags=["k"]_| |_|_Sort: test.k ASC NULLS FIRST, test.j ASC NULLS FIRST_| |_|_Filter: test.j >= TimestampMillisecond(-299999, None) AND test.j <= TimestampMillisecond(10000, None)_| -|_|_TableScan: test, partial_filters=[test.j >= TimestampMillisecond(-299999, None), test.j <= TimestampMillisecond(10000, None)] | +|_|_TableScan: test, partial_filters=[test.j >= TimestampMillisecond(-299999, None), test.j <= TimestampMillisecond(10000, None)]_| |_| ]]_| | logical_plan after ScanHintRule_| SAME TEXT AS ABOVE_| | logical_plan after JsonTypeConcretizeRule_| SAME TEXT AS ABOVE_| @@ -164,11 +176,13 @@ TQL EXPLAIN VERBOSE (0, 10, '5s') test; | logical_plan after ScanHintRule_| SAME TEXT AS ABOVE_| | logical_plan after JsonTypeConcretizeRule_| SAME TEXT AS ABOVE_| | logical_plan_| MergeScan [is_placeholder=false, remote_input=[_| -|_| PromInstantManipulate: range=[0..10000], lookback=[300000], interval=[5000], time index=[j]_| +|_| Projection: test.i, test.j, test.k_| +|_|_Projection: test.i, test.j, test.k, Utf8("test") FieldMetadata { inner: {"greptime:promql:role": "metric_name"} } AS __promql_metric_name | +|_|_PromInstantManipulate: range=[0..10000], lookback=[300000], interval=[5000], time index=[j]_| |_|_PromSeriesDivide: tags=["k"]_| |_|_Sort: test.k ASC NULLS FIRST, test.j ASC NULLS FIRST_| |_|_Filter: test.j >= TimestampMillisecond(-299999, None) AND test.j <= TimestampMillisecond(10000, None)_| -|_|_TableScan: test, partial_filters=[test.j >= TimestampMillisecond(-299999, None), test.j <= TimestampMillisecond(10000, None)] | +|_|_TableScan: test, partial_filters=[test.j >= TimestampMillisecond(-299999, None), test.j <= TimestampMillisecond(10000, None)]_| |_| ]]_| | initial_physical_plan_| MergeScanExec: REDACTED |_|_| @@ -232,7 +246,9 @@ TQL EXPLAIN VERBOSE (0, 10, '5s') test AS series; +-+-+ | plan_type_| plan_| +-+-+ -| initial_logical_plan_| Projection: test.i AS series, test.k, test.j_| +| initial_logical_plan_| Projection: series, test.k, test.j_| +|_|_Projection: test.i AS series, test.k, __promql_metric_name, test.j_| +|_|_Projection: test.i, test.j, test.k, Utf8("test") AS __promql_metric_name_| |_|_PromInstantManipulate: range=[0..10000], lookback=[300000], interval=[5000], time index=[j]_| |_|_PromSeriesDivide: tags=["k"]_| |_|_Sort: test.k ASC NULLS FIRST, test.j ASC NULLS FIRST_| @@ -247,12 +263,14 @@ TQL EXPLAIN VERBOSE (0, 10, '5s') test AS series; | logical_plan after ConstNormalizationRule_| SAME TEXT AS ABOVE_| | logical_plan after DistPlannerAnalyzer_| Projection: series, test.k, test.j_| |_|_MergeScan [is_placeholder=false, remote_input=[_| -|_| Projection: test.i AS series, test.k, test.j_| +|_| Projection: series, test.k, test.j_| +|_|_Projection: test.i AS series, test.k, __promql_metric_name, test.j_| +|_|_Projection: test.i, test.j, test.k, Utf8("test") FieldMetadata { inner: {"greptime:promql:role": "metric_name"} } AS __promql_metric_name | |_|_PromInstantManipulate: range=[0..10000], lookback=[300000], interval=[5000], time index=[j]_| |_|_PromSeriesDivide: tags=["k"]_| |_|_Sort: test.k ASC NULLS FIRST, test.j ASC NULLS FIRST_| |_|_Filter: test.j >= TimestampMillisecond(-299999, None) AND test.j <= TimestampMillisecond(10000, None)_| -|_|_TableScan: test, partial_filters=[test.j >= TimestampMillisecond(-299999, None), test.j <= TimestampMillisecond(10000, None)] | +|_|_TableScan: test, partial_filters=[test.j >= TimestampMillisecond(-299999, None), test.j <= TimestampMillisecond(10000, None)]_| |_| ]]_| | logical_plan after JsonSchemaConcretizeRule_| SAME TEXT AS ABOVE_| | logical_plan after FixStateUdafOrderingAnalyzer_| SAME TEXT AS ABOVE_| @@ -282,12 +300,14 @@ TQL EXPLAIN VERBOSE (0, 10, '5s') test AS series; | logical_plan after extract_leaf_expressions_| SAME TEXT AS ABOVE_| | logical_plan after push_down_leaf_projections_| SAME TEXT AS ABOVE_| | logical_plan after optimize_projections_| MergeScan [is_placeholder=false, remote_input=[_| -|_| Projection: test.i AS series, test.k, test.j_| +|_| Projection: series, test.k, test.j_| +|_|_Projection: test.i AS series, test.k, __promql_metric_name, test.j_| +|_|_Projection: test.i, test.j, test.k, Utf8("test") FieldMetadata { inner: {"greptime:promql:role": "metric_name"} } AS __promql_metric_name | |_|_PromInstantManipulate: range=[0..10000], lookback=[300000], interval=[5000], time index=[j]_| |_|_PromSeriesDivide: tags=["k"]_| |_|_Sort: test.k ASC NULLS FIRST, test.j ASC NULLS FIRST_| |_|_Filter: test.j >= TimestampMillisecond(-299999, None) AND test.j <= TimestampMillisecond(10000, None)_| -|_|_TableScan: test, partial_filters=[test.j >= TimestampMillisecond(-299999, None), test.j <= TimestampMillisecond(10000, None)] | +|_|_TableScan: test, partial_filters=[test.j >= TimestampMillisecond(-299999, None), test.j <= TimestampMillisecond(10000, None)]_| |_| ]]_| | logical_plan after ScanHintRule_| SAME TEXT AS ABOVE_| | logical_plan after JsonTypeConcretizeRule_| SAME TEXT AS ABOVE_| @@ -319,12 +339,14 @@ TQL EXPLAIN VERBOSE (0, 10, '5s') test AS series; | logical_plan after ScanHintRule_| SAME TEXT AS ABOVE_| | logical_plan after JsonTypeConcretizeRule_| SAME TEXT AS ABOVE_| | logical_plan_| MergeScan [is_placeholder=false, remote_input=[_| -|_| Projection: test.i AS series, test.k, test.j_| +|_| Projection: series, test.k, test.j_| +|_|_Projection: test.i AS series, test.k, __promql_metric_name, test.j_| +|_|_Projection: test.i, test.j, test.k, Utf8("test") FieldMetadata { inner: {"greptime:promql:role": "metric_name"} } AS __promql_metric_name | |_|_PromInstantManipulate: range=[0..10000], lookback=[300000], interval=[5000], time index=[j]_| |_|_PromSeriesDivide: tags=["k"]_| |_|_Sort: test.k ASC NULLS FIRST, test.j ASC NULLS FIRST_| |_|_Filter: test.j >= TimestampMillisecond(-299999, None) AND test.j <= TimestampMillisecond(10000, None)_| -|_|_TableScan: test, partial_filters=[test.j >= TimestampMillisecond(-299999, None), test.j <= TimestampMillisecond(10000, None)] | +|_|_TableScan: test, partial_filters=[test.j >= TimestampMillisecond(-299999, None), test.j <= TimestampMillisecond(10000, None)]_| |_| ]]_| | initial_physical_plan_| MergeScanExec: REDACTED |_|_| @@ -390,21 +412,23 @@ Affected Rows: 3 -- SQLNESS REPLACE (RepartitionExec:.*) RepartitionExec: REDACTED TQL EXPLAIN (0, 10, '5s') test_nano; -+---------------+-----------------------------------------------------------------------------------------------------------------------------------------------------------------+ -| plan_type | plan | -+---------------+-----------------------------------------------------------------------------------------------------------------------------------------------------------------+ -| logical_plan | MergeScan [is_placeholder=false, remote_input=[ | -| | PromInstantManipulate: range=[0..10000], lookback=[300000], interval=[5000], time index=[j] | -| | PromSeriesDivide: tags=["k"] | -| | Sort: test_nano.k ASC NULLS FIRST, test_nano.j ASC NULLS FIRST | -| | Projection: test_nano.i, test_nano.k, test_nano.j | -| | Filter: test_nano.j > TimestampNanosecond(-300000000000, None) AND test_nano.j <= TimestampNanosecond(10000000000, None) | -| | TableScan: test_nano, partial_filters=[test_nano.j > TimestampNanosecond(-300000000000, None), test_nano.j <= TimestampNanosecond(10000000000, None)] | -| | ]] | -| physical_plan | CooperativeExec | ++---------------+---------------------------------------------------------------------------------------------------------------------------------------------------------------------+ +| plan_type | plan | ++---------------+---------------------------------------------------------------------------------------------------------------------------------------------------------------------+ +| logical_plan | MergeScan [is_placeholder=false, remote_input=[ | +| | Projection: test_nano.i, test_nano.k, test_nano.j | +| | Projection: test_nano.i, test_nano.k, test_nano.j, Utf8("test_nano") FieldMetadata { inner: {"greptime:promql:role": "metric_name"} } AS __promql_metric_name | +| | PromInstantManipulate: range=[0..10000], lookback=[300000], interval=[5000], time index=[j] | +| | PromSeriesDivide: tags=["k"] | +| | Sort: test_nano.k ASC NULLS FIRST, test_nano.j ASC NULLS FIRST | +| | Projection: test_nano.i, test_nano.k, test_nano.j | +| | Filter: test_nano.j > TimestampNanosecond(-300000000000, None) AND test_nano.j <= TimestampNanosecond(10000000000, None) | +| | TableScan: test_nano, partial_filters=[test_nano.j > TimestampNanosecond(-300000000000, None), test_nano.j <= TimestampNanosecond(10000000000, None)] | +| | ]] | +| physical_plan | CooperativeExec | | | MergeScanExec: REDACTED -| | | -+---------------+-----------------------------------------------------------------------------------------------------------------------------------------------------------------+ +| | | ++---------------+---------------------------------------------------------------------------------------------------------------------------------------------------------------------+ -- explain verbose at 0s, 5s and 10s for a nanosecond time index. -- SQLNESS REPLACE (-+) - @@ -418,7 +442,9 @@ TQL EXPLAIN VERBOSE (0, 10, '5s') test_nano; +-+-+ | plan_type_| plan_| +-+-+ -| initial_logical_plan_| PromInstantManipulate: range=[0..10000], lookback=[300000], interval=[5000], time index=[j]_| +| initial_logical_plan_| Projection: test_nano.i, test_nano.k, test_nano.j_| +|_|_Projection: test_nano.i, test_nano.k, test_nano.j, Utf8("test_nano") AS __promql_metric_name_| +|_|_PromInstantManipulate: range=[0..10000], lookback=[300000], interval=[5000], time index=[j]_| |_|_PromSeriesDivide: tags=["k"]_| |_|_Sort: test_nano.k ASC NULLS FIRST, test_nano.j ASC NULLS FIRST_| |_|_Filter: test_nano.j > TimestampNanosecond(-300000000000, None) AND test_nano.j <= TimestampNanosecond(10000000000, None)_| @@ -433,7 +459,9 @@ TQL EXPLAIN VERBOSE (0, 10, '5s') test_nano; | logical_plan after ConstNormalizationRule_| SAME TEXT AS ABOVE_| | logical_plan after DistPlannerAnalyzer_| Projection: test_nano.i, test_nano.k, test_nano.j_| |_|_MergeScan [is_placeholder=false, remote_input=[_| -|_| PromInstantManipulate: range=[0..10000], lookback=[300000], interval=[5000], time index=[j]_| +|_| Projection: test_nano.i, test_nano.k, test_nano.j_| +|_|_Projection: test_nano.i, test_nano.k, test_nano.j, Utf8("test_nano") FieldMetadata { inner: {"greptime:promql:role": "metric_name"} } AS __promql_metric_name_| +|_|_PromInstantManipulate: range=[0..10000], lookback=[300000], interval=[5000], time index=[j]_| |_|_PromSeriesDivide: tags=["k"]_| |_|_Sort: test_nano.k ASC NULLS FIRST, test_nano.j ASC NULLS FIRST_| |_|_Projection: test_nano.i, test_nano.k, test_nano.j_| @@ -468,7 +496,9 @@ TQL EXPLAIN VERBOSE (0, 10, '5s') test_nano; | logical_plan after extract_leaf_expressions_| SAME TEXT AS ABOVE_| | logical_plan after push_down_leaf_projections_| SAME TEXT AS ABOVE_| | logical_plan after optimize_projections_| MergeScan [is_placeholder=false, remote_input=[_| -|_| PromInstantManipulate: range=[0..10000], lookback=[300000], interval=[5000], time index=[j]_| +|_| Projection: test_nano.i, test_nano.k, test_nano.j_| +|_|_Projection: test_nano.i, test_nano.k, test_nano.j, Utf8("test_nano") FieldMetadata { inner: {"greptime:promql:role": "metric_name"} } AS __promql_metric_name_| +|_|_PromInstantManipulate: range=[0..10000], lookback=[300000], interval=[5000], time index=[j]_| |_|_PromSeriesDivide: tags=["k"]_| |_|_Sort: test_nano.k ASC NULLS FIRST, test_nano.j ASC NULLS FIRST_| |_|_Projection: test_nano.i, test_nano.k, test_nano.j_| @@ -505,7 +535,9 @@ TQL EXPLAIN VERBOSE (0, 10, '5s') test_nano; | logical_plan after ScanHintRule_| SAME TEXT AS ABOVE_| | logical_plan after JsonTypeConcretizeRule_| SAME TEXT AS ABOVE_| | logical_plan_| MergeScan [is_placeholder=false, remote_input=[_| -|_| PromInstantManipulate: range=[0..10000], lookback=[300000], interval=[5000], time index=[j]_| +|_| Projection: test_nano.i, test_nano.k, test_nano.j_| +|_|_Projection: test_nano.i, test_nano.k, test_nano.j, Utf8("test_nano") FieldMetadata { inner: {"greptime:promql:role": "metric_name"} } AS __promql_metric_name_| +|_|_PromInstantManipulate: range=[0..10000], lookback=[300000], interval=[5000], time index=[j]_| |_|_PromSeriesDivide: tags=["k"]_| |_|_Sort: test_nano.k ASC NULLS FIRST, test_nano.j ASC NULLS FIRST_| |_|_Projection: test_nano.i, test_nano.k, test_nano.j_| diff --git a/tests/cases/standalone/common/tql/metric_name_output.result b/tests/cases/standalone/common/tql/metric_name_output.result new file mode 100644 index 00000000000..badfd779cda --- /dev/null +++ b/tests/cases/standalone/common/tql/metric_name_output.result @@ -0,0 +1,70 @@ +-- The PromQL metric-name identity is an internal column. A TQL statement is tabular, so the +-- identity must not be exposed in a direct TQL result, and a TQL CTE must expose the same +-- tabular schema, while the visible columns stay exactly as before. +CREATE TABLE metric_name_output ( + ts TIMESTAMP(3) TIME INDEX, + host STRING PRIMARY KEY, + val DOUBLE, +); + +Affected Rows: 0 + +INSERT INTO metric_name_output VALUES + (0, 'host1', 1.0), + (10000, 'host2', 2.0), + (20000, 'host1', 3.0); + +Affected Rows: 3 + +-- Direct TQL: the selector keeps its visible columns only. +-- SQLNESS SORT_RESULT 2 1 +TQL EVAL (0, 20, '10s') metric_name_output; + ++---------------------+-------+-----+ +| ts | host | val | ++---------------------+-------+-----+ +| 1970-01-01T00:00:00 | host1 | 1.0 | +| 1970-01-01T00:00:10 | host1 | 1.0 | +| 1970-01-01T00:00:10 | host2 | 2.0 | +| 1970-01-01T00:00:20 | host1 | 3.0 | +| 1970-01-01T00:00:20 | host2 | 2.0 | ++---------------------+-------+-----+ + +-- A TQL CTE is tabular too: `SELECT *` exposes the same columns as the direct result. +-- SQLNESS SORT_RESULT 2 1 +WITH tql AS ( + TQL EVAL (0, 20, '10s') metric_name_output +) +SELECT * FROM tql; + ++---------------------+-------+-----+ +| ts | host | val | ++---------------------+-------+-----+ +| 1970-01-01T00:00:00 | host1 | 1.0 | +| 1970-01-01T00:00:10 | host1 | 1.0 | +| 1970-01-01T00:00:10 | host2 | 2.0 | +| 1970-01-01T00:00:20 | host1 | 3.0 | +| 1970-01-01T00:00:20 | host2 | 2.0 | ++---------------------+-------+-----+ + +-- The CTE column arity check operates on the identity-free schema as well. +-- SQLNESS SORT_RESULT 2 1 +WITH tql (the_ts, the_host, the_val) AS ( + TQL EVAL (0, 20, '10s') metric_name_output +) +SELECT * FROM tql; + ++---------------------+----------+---------+ +| the_ts | the_host | the_val | ++---------------------+----------+---------+ +| 1970-01-01T00:00:00 | host1 | 1.0 | +| 1970-01-01T00:00:10 | host1 | 1.0 | +| 1970-01-01T00:00:10 | host2 | 2.0 | +| 1970-01-01T00:00:20 | host1 | 3.0 | +| 1970-01-01T00:00:20 | host2 | 2.0 | ++---------------------+----------+---------+ + +DROP TABLE metric_name_output; + +Affected Rows: 0 + diff --git a/tests/cases/standalone/common/tql/metric_name_output.sql b/tests/cases/standalone/common/tql/metric_name_output.sql new file mode 100644 index 00000000000..eb9775f5be0 --- /dev/null +++ b/tests/cases/standalone/common/tql/metric_name_output.sql @@ -0,0 +1,34 @@ +-- The PromQL metric-name identity is an internal column. A TQL statement is tabular, so the +-- identity must not be exposed in a direct TQL result, and a TQL CTE must expose the same +-- tabular schema, while the visible columns stay exactly as before. + +CREATE TABLE metric_name_output ( + ts TIMESTAMP(3) TIME INDEX, + host STRING PRIMARY KEY, + val DOUBLE, +); + +INSERT INTO metric_name_output VALUES + (0, 'host1', 1.0), + (10000, 'host2', 2.0), + (20000, 'host1', 3.0); + +-- Direct TQL: the selector keeps its visible columns only. +-- SQLNESS SORT_RESULT 2 1 +TQL EVAL (0, 20, '10s') metric_name_output; + +-- A TQL CTE is tabular too: `SELECT *` exposes the same columns as the direct result. +-- SQLNESS SORT_RESULT 2 1 +WITH tql AS ( + TQL EVAL (0, 20, '10s') metric_name_output +) +SELECT * FROM tql; + +-- The CTE column arity check operates on the identity-free schema as well. +-- SQLNESS SORT_RESULT 2 1 +WITH tql (the_ts, the_host, the_val) AS ( + TQL EVAL (0, 20, '10s') metric_name_output +) +SELECT * FROM tql; + +DROP TABLE metric_name_output; diff --git a/tests/cases/standalone/common/tql/tql-cte.result b/tests/cases/standalone/common/tql/tql-cte.result index c2bc149e66c..711174a41c8 100644 --- a/tests/cases/standalone/common/tql/tql-cte.result +++ b/tests/cases/standalone/common/tql/tql-cte.result @@ -52,21 +52,23 @@ EXPLAIN WITH tql as ( ) SELECT * FROM tql; -+---------------+-------------------------------------------------------------------------------------------------------------------------------------------------+ -| plan_type | plan | -+---------------+-------------------------------------------------------------------------------------------------------------------------------------------------+ -| logical_plan | MergeScan [is_placeholder=false, remote_input=[ | -| | Projection: tql.ts, tql.val | -| | SubqueryAlias: tql | -| | PromInstantManipulate: range=[0..40000], lookback=[300000], interval=[10000], time index=[ts] | -| | PromSeriesDivide: tags=[] | -| | Filter: metric.ts >= TimestampMillisecond(-299999, None) AND metric.ts <= TimestampMillisecond(40000, None) | -| | TableScan: metric, partial_filters=[metric.ts >= TimestampMillisecond(-299999, None), metric.ts <= TimestampMillisecond(40000, None)] | -| | ]] | -| physical_plan | CooperativeExec | ++---------------+-----------------------------------------------------------------------------------------------------------------------------------------------------+ +| plan_type | plan | ++---------------+-----------------------------------------------------------------------------------------------------------------------------------------------------+ +| logical_plan | MergeScan [is_placeholder=false, remote_input=[ | +| | Projection: tql.ts, tql.val | +| | SubqueryAlias: tql | +| | Projection: metric.ts, metric.val | +| | Projection: metric.ts, metric.val, Utf8("metric") FieldMetadata { inner: {"greptime:promql:role": "metric_name"} } AS __promql_metric_name | +| | PromInstantManipulate: range=[0..40000], lookback=[300000], interval=[10000], time index=[ts] | +| | PromSeriesDivide: tags=[] | +| | Filter: metric.ts >= TimestampMillisecond(-299999, None) AND metric.ts <= TimestampMillisecond(40000, None) | +| | TableScan: metric, partial_filters=[metric.ts >= TimestampMillisecond(-299999, None), metric.ts <= TimestampMillisecond(40000, None)] | +| | ]] | +| physical_plan | CooperativeExec | | | MergeScanExec: REDACTED -| | | -+---------------+-------------------------------------------------------------------------------------------------------------------------------------------------+ +| | | ++---------------+-----------------------------------------------------------------------------------------------------------------------------------------------------+ -- TQL CTE with column aliases WITH tql (the_timestamp, the_value) as ( @@ -91,22 +93,24 @@ EXPLAIN WITH tql (the_timestamp, the_value) as ( ) SELECT * FROM tql; -+---------------+---------------------------------------------------------------------------------------------------------------------------------------------------+ -| plan_type | plan | -+---------------+---------------------------------------------------------------------------------------------------------------------------------------------------+ -| logical_plan | MergeScan [is_placeholder=false, remote_input=[ | -| | Projection: tql.the_timestamp, tql.the_value | -| | SubqueryAlias: tql | -| | Projection: metric.ts AS the_timestamp, metric.val AS the_value | -| | PromInstantManipulate: range=[0..40000], lookback=[300000], interval=[10000], time index=[ts] | -| | PromSeriesDivide: tags=[] | -| | Filter: metric.ts >= TimestampMillisecond(-299999, None) AND metric.ts <= TimestampMillisecond(40000, None) | -| | TableScan: metric, partial_filters=[metric.ts >= TimestampMillisecond(-299999, None), metric.ts <= TimestampMillisecond(40000, None)] | -| | ]] | -| physical_plan | CooperativeExec | ++---------------+-------------------------------------------------------------------------------------------------------------------------------------------------------+ +| plan_type | plan | ++---------------+-------------------------------------------------------------------------------------------------------------------------------------------------------+ +| logical_plan | MergeScan [is_placeholder=false, remote_input=[ | +| | Projection: tql.the_timestamp, tql.the_value | +| | SubqueryAlias: tql | +| | Projection: metric.ts AS the_timestamp, metric.val AS the_value | +| | Projection: metric.ts, metric.val | +| | Projection: metric.ts, metric.val, Utf8("metric") FieldMetadata { inner: {"greptime:promql:role": "metric_name"} } AS __promql_metric_name | +| | PromInstantManipulate: range=[0..40000], lookback=[300000], interval=[10000], time index=[ts] | +| | PromSeriesDivide: tags=[] | +| | Filter: metric.ts >= TimestampMillisecond(-299999, None) AND metric.ts <= TimestampMillisecond(40000, None) | +| | TableScan: metric, partial_filters=[metric.ts >= TimestampMillisecond(-299999, None), metric.ts <= TimestampMillisecond(40000, None)] | +| | ]] | +| physical_plan | CooperativeExec | | | MergeScanExec: REDACTED -| | | -+---------------+---------------------------------------------------------------------------------------------------------------------------------------------------+ +| | | ++---------------+-------------------------------------------------------------------------------------------------------------------------------------------------------+ -- Explain TQL CTE -- SQLNESS REPLACE (peers.*) REDACTED @@ -115,21 +119,23 @@ EXPLAIN WITH tql AS ( TQL EVAL (0, 40, '10s') metric ) SELECT * FROM tql; -+---------------+-------------------------------------------------------------------------------------------------------------------------------------------------+ -| plan_type | plan | -+---------------+-------------------------------------------------------------------------------------------------------------------------------------------------+ -| logical_plan | MergeScan [is_placeholder=false, remote_input=[ | -| | Projection: tql.ts, tql.val | -| | SubqueryAlias: tql | -| | PromInstantManipulate: range=[0..40000], lookback=[300000], interval=[10000], time index=[ts] | -| | PromSeriesDivide: tags=[] | -| | Filter: metric.ts >= TimestampMillisecond(-299999, None) AND metric.ts <= TimestampMillisecond(40000, None) | -| | TableScan: metric, partial_filters=[metric.ts >= TimestampMillisecond(-299999, None), metric.ts <= TimestampMillisecond(40000, None)] | -| | ]] | -| physical_plan | CooperativeExec | ++---------------+-----------------------------------------------------------------------------------------------------------------------------------------------------+ +| plan_type | plan | ++---------------+-----------------------------------------------------------------------------------------------------------------------------------------------------+ +| logical_plan | MergeScan [is_placeholder=false, remote_input=[ | +| | Projection: tql.ts, tql.val | +| | SubqueryAlias: tql | +| | Projection: metric.ts, metric.val | +| | Projection: metric.ts, metric.val, Utf8("metric") FieldMetadata { inner: {"greptime:promql:role": "metric_name"} } AS __promql_metric_name | +| | PromInstantManipulate: range=[0..40000], lookback=[300000], interval=[10000], time index=[ts] | +| | PromSeriesDivide: tags=[] | +| | Filter: metric.ts >= TimestampMillisecond(-299999, None) AND metric.ts <= TimestampMillisecond(40000, None) | +| | TableScan: metric, partial_filters=[metric.ts >= TimestampMillisecond(-299999, None), metric.ts <= TimestampMillisecond(40000, None)] | +| | ]] | +| physical_plan | CooperativeExec | | | MergeScanExec: REDACTED -| | | -+---------------+-------------------------------------------------------------------------------------------------------------------------------------------------+ +| | | ++---------------+-----------------------------------------------------------------------------------------------------------------------------------------------------+ -- Hybrid CTEs (TQL + SQL) WITH @@ -150,26 +156,28 @@ EXPLAIN WITH filtered AS (SELECT * FROM tql_data WHERE val > 5) SELECT count(*) FROM filtered; -+---------------+-----------------------------------------------------------------------------------------------------------------------------------------------------------+ -| plan_type | plan | -+---------------+-----------------------------------------------------------------------------------------------------------------------------------------------------------+ -| logical_plan | MergeScan [is_placeholder=false, remote_input=[ | -| | Projection: count(Int64(1)) AS count(*) | -| | Aggregate: groupBy=[[]], aggr=[[count(filtered.ts) AS count(Int64(1))]] | -| | SubqueryAlias: filtered | -| | Projection: tql_data.ts, tql_data.val | -| | SubqueryAlias: tql_data | -| | Projection: metric.ts AS ts, metric.val AS val | -| | Filter: metric.val > Float64(5) | -| | PromInstantManipulate: range=[0..40000], lookback=[300000], interval=[10000], time index=[ts] | -| | PromSeriesDivide: tags=[] | -| | Filter: metric.ts >= TimestampMillisecond(-299999, None) AND metric.ts <= TimestampMillisecond(40000, None) | -| | TableScan: metric, partial_filters=[metric.ts >= TimestampMillisecond(-299999, None), metric.ts <= TimestampMillisecond(40000, None)] | -| | ]] | -| physical_plan | CooperativeExec | ++---------------+---------------------------------------------------------------------------------------------------------------------------------------------------------------+ +| plan_type | plan | ++---------------+---------------------------------------------------------------------------------------------------------------------------------------------------------------+ +| logical_plan | MergeScan [is_placeholder=false, remote_input=[ | +| | Projection: count(Int64(1)) AS count(*) | +| | Aggregate: groupBy=[[]], aggr=[[count(filtered.ts) AS count(Int64(1))]] | +| | SubqueryAlias: filtered | +| | Projection: tql_data.ts, tql_data.val | +| | SubqueryAlias: tql_data | +| | Projection: metric.ts AS ts, metric.val AS val | +| | Projection: metric.ts, metric.val | +| | Projection: metric.ts, metric.val, Utf8("metric") FieldMetadata { inner: {"greptime:promql:role": "metric_name"} } AS __promql_metric_name | +| | Filter: metric.val > Float64(5) | +| | PromInstantManipulate: range=[0..40000], lookback=[300000], interval=[10000], time index=[ts] | +| | PromSeriesDivide: tags=[] | +| | Filter: metric.ts >= TimestampMillisecond(-299999, None) AND metric.ts <= TimestampMillisecond(40000, None) | +| | TableScan: metric, partial_filters=[metric.ts >= TimestampMillisecond(-299999, None), metric.ts <= TimestampMillisecond(40000, None)] | +| | ]] | +| physical_plan | CooperativeExec | | | MergeScanExec: REDACTED -| | | -+---------------+-----------------------------------------------------------------------------------------------------------------------------------------------------------+ +| | | ++---------------+---------------------------------------------------------------------------------------------------------------------------------------------------------------+ -- TQL CTE with complex PromQL expressions WITH @@ -190,29 +198,31 @@ EXPLAIN WITH filtered (ts, val) AS (SELECT * FROM tql_data WHERE val > 0) SELECT sum(val) FROM filtered; -+---------------+----------------------------------------------------------------------------------------------------------------------------------------------------------------+ -| plan_type | plan | -+---------------+----------------------------------------------------------------------------------------------------------------------------------------------------------------+ -| logical_plan | MergeScan [is_placeholder=false, remote_input=[ | -| | Projection: sum(filtered.val) | -| | Aggregate: groupBy=[[]], aggr=[[sum(filtered.val)]] | -| | SubqueryAlias: filtered | -| | Projection: tql_data.ts AS ts, tql_data.val AS val | -| | Projection: tql_data.ts, tql_data.val | -| | SubqueryAlias: tql_data | -| | Projection: metric.ts AS ts, prom_rate(ts_range,val,ts,Int64(20000)) AS val | -| | Filter: prom_rate(ts_range,val,ts,Int64(20000)) IS NOT NULL AND prom_rate(ts_range,val,ts,Int64(20000)) > Float64(0) | -| | Projection: metric.ts, prom_rate(ts_range, val, metric.ts, Int64(20000)) AS prom_rate(ts_range,val,ts,Int64(20000)) | -| | PromRangeManipulate: req range=[0..40000], interval=[10000], eval range=[20000], time index=[ts], values=["val"] | -| | PromSeriesNormalize: offset=[0], time index=[ts], filter NaN: [true] | -| | PromSeriesDivide: tags=[] | -| | Filter: metric.ts >= TimestampMillisecond(-19999, None) AND metric.ts <= TimestampMillisecond(40000, None) | -| | TableScan: metric, partial_filters=[metric.ts >= TimestampMillisecond(-19999, None), metric.ts <= TimestampMillisecond(40000, None)] | -| | ]] | -| physical_plan | CooperativeExec | ++---------------+--------------------------------------------------------------------------------------------------------------------------------------------------------------------+ +| plan_type | plan | ++---------------+--------------------------------------------------------------------------------------------------------------------------------------------------------------------+ +| logical_plan | MergeScan [is_placeholder=false, remote_input=[ | +| | Projection: sum(filtered.val) | +| | Aggregate: groupBy=[[]], aggr=[[sum(filtered.val)]] | +| | SubqueryAlias: filtered | +| | Projection: tql_data.ts AS ts, tql_data.val AS val | +| | Projection: tql_data.ts, tql_data.val | +| | SubqueryAlias: tql_data | +| | Projection: metric.ts AS ts, prom_rate(ts_range,val,ts,Int64(20000)) AS val | +| | Projection: metric.ts, prom_rate(ts_range,val,ts,Int64(20000)) | +| | Filter: prom_rate(ts_range,val,ts,Int64(20000)) IS NOT NULL AND prom_rate(ts_range,val,ts,Int64(20000)) > Float64(0) | +| | Projection: metric.ts, prom_rate(ts_range, val, metric.ts, Int64(20000)) AS prom_rate(ts_range,val,ts,Int64(20000)), __promql_metric_name | +| | Projection: metric.ts, val, ts_range, Utf8("metric") FieldMetadata { inner: {"greptime:promql:role": "metric_name"} } AS __promql_metric_name | +| | PromRangeManipulate: req range=[0..40000], interval=[10000], eval range=[20000], time index=[ts], values=["val"] | +| | PromSeriesNormalize: offset=[0], time index=[ts], filter NaN: [true] | +| | PromSeriesDivide: tags=[] | +| | Filter: metric.ts >= TimestampMillisecond(-19999, None) AND metric.ts <= TimestampMillisecond(40000, None) | +| | TableScan: metric, partial_filters=[metric.ts >= TimestampMillisecond(-19999, None), metric.ts <= TimestampMillisecond(40000, None)] | +| | ]] | +| physical_plan | CooperativeExec | | | MergeScanExec: REDACTED -| | | -+---------------+----------------------------------------------------------------------------------------------------------------------------------------------------------------+ +| | | ++---------------+--------------------------------------------------------------------------------------------------------------------------------------------------------------------+ -- TQL CTE with aggregation functions WITH tql_agg(ts, summary) AS ( @@ -233,24 +243,25 @@ EXPLAIN WITH tql_agg(ts, summary) AS ( ) SELECT round(avg(summary)) as avg_sum FROM tql_agg; -+---------------+-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+ -| plan_type | plan | -+---------------+-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+ -| logical_plan | MergeScan [is_placeholder=false, remote_input=[ | -| | Projection: round(avg(tql_agg.summary)) AS avg_sum | -| | Aggregate: groupBy=[[]], aggr=[[avg(tql_agg.summary)]] | -| | SubqueryAlias: tql_agg | -| | Projection: labels.ts AS ts, sum(labels.cpu) AS summary | -| | Aggregate: groupBy=[[labels.ts]], aggr=[[sum(labels.cpu)]] | -| | PromInstantManipulate: range=[0..40000], lookback=[300000], interval=[10000], time index=[ts] | -| | PromSeriesDivide: tags=["host"] | -| | Filter: labels.ts >= TimestampMillisecond(-299999, None) AND labels.ts <= TimestampMillisecond(40000, None) AND labels.host ~ Utf8("^(?:host.*)$") | -| | TableScan: labels, partial_filters=[labels.ts >= TimestampMillisecond(-299999, None), labels.ts <= TimestampMillisecond(40000, None), labels.host ~ Utf8("^(?:host.*)$")] | -| | ]] | -| physical_plan | CooperativeExec | ++---------------+---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+ +| plan_type | plan | ++---------------+---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+ +| logical_plan | MergeScan [is_placeholder=false, remote_input=[ | +| | Projection: round(avg(tql_agg.summary)) AS avg_sum | +| | Aggregate: groupBy=[[]], aggr=[[avg(tql_agg.summary)]] | +| | SubqueryAlias: tql_agg | +| | Projection: labels.ts AS ts, sum(labels.cpu) AS summary | +| | Aggregate: groupBy=[[labels.ts]], aggr=[[sum(labels.cpu)]] | +| | Projection: labels.ts, labels.host, labels.cpu, Utf8("labels") FieldMetadata { inner: {"greptime:promql:role": "metric_name"} } AS __promql_metric_name | +| | PromInstantManipulate: range=[0..40000], lookback=[300000], interval=[10000], time index=[ts] | +| | PromSeriesDivide: tags=["host"] | +| | Filter: labels.ts >= TimestampMillisecond(-299999, None) AND labels.ts <= TimestampMillisecond(40000, None) AND labels.host ~ Utf8("^(?:host.*)$") | +| | TableScan: labels, partial_filters=[labels.ts >= TimestampMillisecond(-299999, None), labels.ts <= TimestampMillisecond(40000, None), labels.host ~ Utf8("^(?:host.*)$")] | +| | ]] | +| physical_plan | CooperativeExec | | | MergeScanExec: REDACTED -| | | -+---------------+-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+ +| | | ++---------------+---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+ -- TQL CTE with label selectors WITH host_metrics AS ( @@ -271,22 +282,24 @@ EXPLAIN WITH host_metrics AS ( ) SELECT count(*) as host1_points FROM host_metrics; -+---------------+--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+ -| plan_type | plan | -+---------------+--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+ -| logical_plan | MergeScan [is_placeholder=false, remote_input=[ | -| | Projection: count(Int64(1)) AS count(*) AS host1_points | -| | Aggregate: groupBy=[[]], aggr=[[count(host_metrics.ts) AS count(Int64(1))]] | -| | SubqueryAlias: host_metrics | -| | PromInstantManipulate: range=[0..40000], lookback=[300000], interval=[10000], time index=[ts] | -| | PromSeriesDivide: tags=["host"] | -| | Filter: labels.host = Utf8("host1") AND labels.ts >= TimestampMillisecond(-299999, None) AND labels.ts <= TimestampMillisecond(40000, None) | -| | TableScan: labels, partial_filters=[labels.host = Utf8("host1"), labels.ts >= TimestampMillisecond(-299999, None), labels.ts <= TimestampMillisecond(40000, None)] | -| | ]] | -| physical_plan | CooperativeExec | ++---------------+------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+ +| plan_type | plan | ++---------------+------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+ +| logical_plan | MergeScan [is_placeholder=false, remote_input=[ | +| | Projection: count(Int64(1)) AS count(*) AS host1_points | +| | Aggregate: groupBy=[[]], aggr=[[count(host_metrics.ts) AS count(Int64(1))]] | +| | SubqueryAlias: host_metrics | +| | Projection: labels.ts, labels.host, labels.cpu | +| | Projection: labels.ts, labels.host, labels.cpu, Utf8("labels") FieldMetadata { inner: {"greptime:promql:role": "metric_name"} } AS __promql_metric_name | +| | PromInstantManipulate: range=[0..40000], lookback=[300000], interval=[10000], time index=[ts] | +| | PromSeriesDivide: tags=["host"] | +| | Filter: labels.host = Utf8("host1") AND labels.ts >= TimestampMillisecond(-299999, None) AND labels.ts <= TimestampMillisecond(40000, None) | +| | TableScan: labels, partial_filters=[labels.host = Utf8("host1"), labels.ts >= TimestampMillisecond(-299999, None), labels.ts <= TimestampMillisecond(40000, None)] | +| | ]] | +| physical_plan | CooperativeExec | | | MergeScanExec: REDACTED -| | | -+---------------+--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+ +| | | ++---------------+------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+ -- TQL CTE with column reference WITH host_metrics AS ( @@ -311,21 +324,23 @@ EXPLAIN WITH host_metrics AS ( ) SELECT host_metrics.ts, host_metrics.host FROM host_metrics; -+---------------+------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+ -| plan_type | plan | -+---------------+------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+ -| logical_plan | MergeScan [is_placeholder=false, remote_input=[ | -| | Projection: host_metrics.ts, host_metrics.host | -| | SubqueryAlias: host_metrics | -| | PromInstantManipulate: range=[0..40000], lookback=[300000], interval=[10000], time index=[ts] | -| | PromSeriesDivide: tags=["host"] | -| | Filter: labels.host = Utf8("host1") AND labels.ts >= TimestampMillisecond(-299999, None) AND labels.ts <= TimestampMillisecond(40000, None) | -| | TableScan: labels, partial_filters=[labels.host = Utf8("host1"), labels.ts >= TimestampMillisecond(-299999, None), labels.ts <= TimestampMillisecond(40000, None)] | -| | ]] | -| physical_plan | CooperativeExec | ++---------------+----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+ +| plan_type | plan | ++---------------+----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+ +| logical_plan | MergeScan [is_placeholder=false, remote_input=[ | +| | Projection: host_metrics.ts, host_metrics.host | +| | SubqueryAlias: host_metrics | +| | Projection: labels.ts, labels.host, labels.cpu | +| | Projection: labels.ts, labels.host, labels.cpu, Utf8("labels") FieldMetadata { inner: {"greptime:promql:role": "metric_name"} } AS __promql_metric_name | +| | PromInstantManipulate: range=[0..40000], lookback=[300000], interval=[10000], time index=[ts] | +| | PromSeriesDivide: tags=["host"] | +| | Filter: labels.host = Utf8("host1") AND labels.ts >= TimestampMillisecond(-299999, None) AND labels.ts <= TimestampMillisecond(40000, None) | +| | TableScan: labels, partial_filters=[labels.host = Utf8("host1"), labels.ts >= TimestampMillisecond(-299999, None), labels.ts <= TimestampMillisecond(40000, None)] | +| | ]] | +| physical_plan | CooperativeExec | | | MergeScanExec: REDACTED -| | | -+---------------+------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+ +| | | ++---------------+----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+ -- Multiple TQL CTEs referencing different tables WITH @@ -360,44 +375,48 @@ WHERE m.ts = l.ts ORDER BY m.ts LIMIT 3; -+---------------+--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+ -| plan_type | plan | -+---------------+--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+ -| logical_plan | Projection: metric_val, label_val | -| | Sort: m.ts ASC NULLS LAST, fetch=3 | -| | Projection: m.val AS metric_val, l.cpu AS label_val, m.ts | -| | Inner Join: m.ts = l.ts | -| | MergeScan [is_placeholder=false, remote_input=[ | -| | SubqueryAlias: m | -| | SubqueryAlias: metric_data | -| | Projection: metric.ts AS ts, metric.val AS val | -| | PromInstantManipulate: range=[0..40000], lookback=[300000], interval=[10000], time index=[ts] | -| | PromSeriesDivide: tags=[] | -| | Filter: metric.ts >= TimestampMillisecond(-299999, None) AND metric.ts <= TimestampMillisecond(40000, None) | -| | TableScan: metric, partial_filters=[metric.ts >= TimestampMillisecond(-299999, None), metric.ts <= TimestampMillisecond(40000, None)] | -| | ]] | -| | Projection: l.ts, l.cpu | -| | MergeScan [is_placeholder=false, remote_input=[ | -| | SubqueryAlias: l | -| | SubqueryAlias: label_data | -| | Projection: labels.ts AS ts, labels.host AS host, labels.cpu AS cpu | -| | PromInstantManipulate: range=[0..40000], lookback=[300000], interval=[10000], time index=[ts] | -| | PromSeriesDivide: tags=["host"] | -| | Filter: labels.host = Utf8("host2") AND labels.ts >= TimestampMillisecond(-299999, None) AND labels.ts <= TimestampMillisecond(40000, None) | -| | TableScan: labels, partial_filters=[labels.host = Utf8("host2"), labels.ts >= TimestampMillisecond(-299999, None), labels.ts <= TimestampMillisecond(40000, None)] | -| | ]] | -| physical_plan | ProjectionExec: expr=[metric_val@0 as metric_val, label_val@1 as label_val] | -| | SortPreservingMergeExec: [ts@2 ASC NULLS LAST], fetch=3 | ++---------------+------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+ +| plan_type | plan | ++---------------+------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+ +| logical_plan | Projection: metric_val, label_val | +| | Sort: m.ts ASC NULLS LAST, fetch=3 | +| | Projection: m.val AS metric_val, l.cpu AS label_val, m.ts | +| | Inner Join: m.ts = l.ts | +| | MergeScan [is_placeholder=false, remote_input=[ | +| | SubqueryAlias: m | +| | SubqueryAlias: metric_data | +| | Projection: metric.ts AS ts, metric.val AS val | +| | Projection: metric.ts, metric.val | +| | Projection: metric.ts, metric.val, Utf8("metric") FieldMetadata { inner: {"greptime:promql:role": "metric_name"} } AS __promql_metric_name | +| | PromInstantManipulate: range=[0..40000], lookback=[300000], interval=[10000], time index=[ts] | +| | PromSeriesDivide: tags=[] | +| | Filter: metric.ts >= TimestampMillisecond(-299999, None) AND metric.ts <= TimestampMillisecond(40000, None) | +| | TableScan: metric, partial_filters=[metric.ts >= TimestampMillisecond(-299999, None), metric.ts <= TimestampMillisecond(40000, None)] | +| | ]] | +| | Projection: l.ts, l.cpu | +| | MergeScan [is_placeholder=false, remote_input=[ | +| | SubqueryAlias: l | +| | SubqueryAlias: label_data | +| | Projection: labels.ts AS ts, labels.host AS host, labels.cpu AS cpu | +| | Projection: labels.ts, labels.host, labels.cpu | +| | Projection: labels.ts, labels.host, labels.cpu, Utf8("labels") FieldMetadata { inner: {"greptime:promql:role": "metric_name"} } AS __promql_metric_name | +| | PromInstantManipulate: range=[0..40000], lookback=[300000], interval=[10000], time index=[ts] | +| | PromSeriesDivide: tags=["host"] | +| | Filter: labels.host = Utf8("host2") AND labels.ts >= TimestampMillisecond(-299999, None) AND labels.ts <= TimestampMillisecond(40000, None) | +| | TableScan: labels, partial_filters=[labels.host = Utf8("host2"), labels.ts >= TimestampMillisecond(-299999, None), labels.ts <= TimestampMillisecond(40000, None)] | +| | ]] | +| physical_plan | ProjectionExec: expr=[metric_val@0 as metric_val, label_val@1 as label_val] | +| | SortPreservingMergeExec: [ts@2 ASC NULLS LAST], fetch=3 | | | SortExec: TopK(fetch=3), expr=[ts@2 ASC NULLS LAST], preserve_REDACTED -| | ProjectionExec: expr=[val@0 as metric_val, cpu@1 as label_val, ts@2 as ts] | -| | HashJoinExec: mode=Partitioned, join_type=Inner, on=[(ts@0, ts@0)], projection=[val@1, cpu@3, ts@0] | +| | ProjectionExec: expr=[val@0 as metric_val, cpu@1 as label_val, ts@2 as ts] | +| | HashJoinExec: mode=Partitioned, join_type=Inner, on=[(ts@0, ts@0)], projection=[val@1, cpu@3, ts@0] | | | RepartitionExec: REDACTED | | MergeScanExec: REDACTED | | RepartitionExec: REDACTED -| | ProjectionExec: expr=[ts@0 as ts, cpu@2 as cpu] | +| | ProjectionExec: expr=[ts@0 as ts, cpu@2 as cpu] | | | MergeScanExec: REDACTED -| | | -+---------------+--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+ +| | | ++---------------+------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+ -- TQL CTE with mathematical operations WITH computed(ts, val) AS ( @@ -418,25 +437,27 @@ EXPLAIN WITH computed(ts, val) AS ( ) SELECT min(val) as min_computed, max(val) as max_computed FROM computed; -+---------------+---------------------------------------------------------------------------------------------------------------------------------------------------------+ -| plan_type | plan | -+---------------+---------------------------------------------------------------------------------------------------------------------------------------------------------+ -| logical_plan | MergeScan [is_placeholder=false, remote_input=[ | -| | Projection: min(computed.val) AS min_computed, max(computed.val) AS max_computed | -| | Aggregate: groupBy=[[]], aggr=[[min(computed.val), max(computed.val)]] | -| | SubqueryAlias: computed | -| | Projection: metric.ts AS ts, val * Float64(2) + Float64(1) AS val | -| | Projection: metric.ts, CAST(val * Float64(2) AS Float64) + Float64(1) AS val * Float64(2) + Float64(1) | -| | Projection: metric.ts, CAST(metric.val AS Float64) * Float64(2) AS val * Float64(2) | -| | PromInstantManipulate: range=[0..40000], lookback=[300000], interval=[10000], time index=[ts] | -| | PromSeriesDivide: tags=[] | -| | Filter: metric.ts >= TimestampMillisecond(-299999, None) AND metric.ts <= TimestampMillisecond(40000, None) | -| | TableScan: metric, partial_filters=[metric.ts >= TimestampMillisecond(-299999, None), metric.ts <= TimestampMillisecond(40000, None)] | -| | ]] | -| physical_plan | CooperativeExec | ++---------------+-------------------------------------------------------------------------------------------------------------------------------------------------------------+ +| plan_type | plan | ++---------------+-------------------------------------------------------------------------------------------------------------------------------------------------------------+ +| logical_plan | MergeScan [is_placeholder=false, remote_input=[ | +| | Projection: min(computed.val) AS min_computed, max(computed.val) AS max_computed | +| | Aggregate: groupBy=[[]], aggr=[[min(computed.val), max(computed.val)]] | +| | SubqueryAlias: computed | +| | Projection: metric.ts AS ts, val * Float64(2) + Float64(1) AS val | +| | Projection: metric.ts, CAST(val * Float64(2) AS Float64) + Float64(1) AS val * Float64(2) + Float64(1) | +| | Projection: metric.ts, val * Float64(2) | +| | Projection: __promql_metric_name, metric.ts, CAST(metric.val AS Float64) * Float64(2) AS val * Float64(2) | +| | Projection: metric.ts, metric.val, Utf8("metric") FieldMetadata { inner: {"greptime:promql:role": "metric_name"} } AS __promql_metric_name | +| | PromInstantManipulate: range=[0..40000], lookback=[300000], interval=[10000], time index=[ts] | +| | PromSeriesDivide: tags=[] | +| | Filter: metric.ts >= TimestampMillisecond(-299999, None) AND metric.ts <= TimestampMillisecond(40000, None) | +| | TableScan: metric, partial_filters=[metric.ts >= TimestampMillisecond(-299999, None), metric.ts <= TimestampMillisecond(40000, None)] | +| | ]] | +| physical_plan | CooperativeExec | | | MergeScanExec: REDACTED -| | | -+---------------+---------------------------------------------------------------------------------------------------------------------------------------------------------+ +| | | ++---------------+-------------------------------------------------------------------------------------------------------------------------------------------------------------+ -- TQL CTE with window functions in SQL part WITH tql_base(ts, val) AS ( @@ -480,10 +501,12 @@ ORDER BY ts; | | MergeScan [is_placeholder=false, remote_input=[ | | | SubqueryAlias: tql_base | | | Projection: metric.ts AS ts, metric.val AS val | -| | PromInstantManipulate: range=[0..40000], lookback=[300000], interval=[10000], time index=[ts] | -| | PromSeriesDivide: tags=[] | -| | Filter: metric.ts >= TimestampMillisecond(-299999, None) AND metric.ts <= TimestampMillisecond(40000, None) | -| | TableScan: metric, partial_filters=[metric.ts >= TimestampMillisecond(-299999, None), metric.ts <= TimestampMillisecond(40000, None)] | +| | Projection: metric.ts, metric.val | +| | Projection: metric.ts, metric.val, Utf8("metric") FieldMetadata { inner: {"greptime:promql:role": "metric_name"} } AS __promql_metric_name | +| | PromInstantManipulate: range=[0..40000], lookback=[300000], interval=[10000], time index=[ts] | +| | PromSeriesDivide: tags=[] | +| | Filter: metric.ts >= TimestampMillisecond(-299999, None) AND metric.ts <= TimestampMillisecond(40000, None) | +| | TableScan: metric, partial_filters=[metric.ts >= TimestampMillisecond(-299999, None), metric.ts <= TimestampMillisecond(40000, None)] | | | ]] | | physical_plan | ProjectionExec: expr=[ts@0 as ts, val@1 as val, lag(tql_base.val,Int64(1)) ORDER BY [tql_base.ts ASC NULLS LAST] RANGE BETWEEN UNBOUNDED PRECEDING AND CURRENT ROW@2 as prev_value] | | | BoundedWindowAggExec: wdw=[lag(tql_base.val,Int64(1)) ORDER BY [tql_base.ts ASC NULLS LAST] RANGE BETWEEN UNBOUNDED PRECEDING AND CURRENT ROW: Field { "lag(tql_base.val,Int64(1)) ORDER BY [tql_base.ts ASC NULLS LAST] RANGE BETWEEN UNBOUNDED PRECEDING AND CURRENT ROW": nullable Float64 }, frame: RANGE BETWEEN UNBOUNDED PRECEDING AND CURRENT ROW], mode=[Sorted] | @@ -522,24 +545,26 @@ FROM tql_grouped GROUP BY minute HAVING count(*) > 1; -+---------------+-------------------------------------------------------------------------------------------------------------------------------------------------------+ -| plan_type | plan | -+---------------+-------------------------------------------------------------------------------------------------------------------------------------------------------+ -| logical_plan | MergeScan [is_placeholder=false, remote_input=[ | -| | Projection: date_trunc(Utf8("minute"),tql_grouped.ts) AS minute, count(Int64(1)) AS count(*) AS point_count | -| | Filter: count(Int64(1)) > Int64(1) | -| | Aggregate: groupBy=[[date_trunc(Utf8("minute"), tql_grouped.ts)]], aggr=[[count(tql_grouped.ts) AS count(Int64(1))]] | -| | SubqueryAlias: tql_grouped | -| | Projection: labels.ts AS ts, labels.host AS host, labels.cpu AS cpu | -| | PromInstantManipulate: range=[0..40000], lookback=[300000], interval=[10000], time index=[ts] | -| | PromSeriesDivide: tags=["host"] | -| | Filter: labels.ts >= TimestampMillisecond(-299999, None) AND labels.ts <= TimestampMillisecond(40000, None) | -| | TableScan: labels, partial_filters=[labels.ts >= TimestampMillisecond(-299999, None), labels.ts <= TimestampMillisecond(40000, None)] | -| | ]] | -| physical_plan | CooperativeExec | ++---------------+---------------------------------------------------------------------------------------------------------------------------------------------------------------------+ +| plan_type | plan | ++---------------+---------------------------------------------------------------------------------------------------------------------------------------------------------------------+ +| logical_plan | MergeScan [is_placeholder=false, remote_input=[ | +| | Projection: date_trunc(Utf8("minute"),tql_grouped.ts) AS minute, count(Int64(1)) AS count(*) AS point_count | +| | Filter: count(Int64(1)) > Int64(1) | +| | Aggregate: groupBy=[[date_trunc(Utf8("minute"), tql_grouped.ts)]], aggr=[[count(tql_grouped.ts) AS count(Int64(1))]] | +| | SubqueryAlias: tql_grouped | +| | Projection: labels.ts AS ts, labels.host AS host, labels.cpu AS cpu | +| | Projection: labels.ts, labels.host, labels.cpu | +| | Projection: labels.ts, labels.host, labels.cpu, Utf8("labels") FieldMetadata { inner: {"greptime:promql:role": "metric_name"} } AS __promql_metric_name | +| | PromInstantManipulate: range=[0..40000], lookback=[300000], interval=[10000], time index=[ts] | +| | PromSeriesDivide: tags=["host"] | +| | Filter: labels.ts >= TimestampMillisecond(-299999, None) AND labels.ts <= TimestampMillisecond(40000, None) | +| | TableScan: labels, partial_filters=[labels.ts >= TimestampMillisecond(-299999, None), labels.ts <= TimestampMillisecond(40000, None)] | +| | ]] | +| physical_plan | CooperativeExec | | | MergeScanExec: REDACTED -| | | -+---------------+-------------------------------------------------------------------------------------------------------------------------------------------------------+ +| | | ++---------------+---------------------------------------------------------------------------------------------------------------------------------------------------------------------+ -- TQL CTE with UNION -- SQLNESS SORT_RESULT 3 1 @@ -574,35 +599,39 @@ SELECT 'host1' as source, ts, cpu FROM host1_data UNION ALL SELECT 'host2' as source, ts, cpu FROM host2_data; -+---------------+--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+ -| plan_type | plan | -+---------------+--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+ -| logical_plan | Union | -| | MergeScan [is_placeholder=false, remote_input=[ | -| | Projection: Utf8("host1") AS source, host1_data.ts, host1_data.cpu | -| | SubqueryAlias: host1_data | -| | Projection: labels.ts AS ts, labels.host AS host, labels.cpu AS cpu | -| | PromInstantManipulate: range=[0..40000], lookback=[300000], interval=[10000], time index=[ts] | -| | PromSeriesDivide: tags=["host"] | -| | Filter: labels.host = Utf8("host1") AND labels.ts >= TimestampMillisecond(-299999, None) AND labels.ts <= TimestampMillisecond(40000, None) | -| | TableScan: labels, partial_filters=[labels.host = Utf8("host1"), labels.ts >= TimestampMillisecond(-299999, None), labels.ts <= TimestampMillisecond(40000, None)] | -| | ]] | -| | MergeScan [is_placeholder=false, remote_input=[ | -| | Projection: Utf8("host2") AS source, host2_data.ts, host2_data.cpu | -| | SubqueryAlias: host2_data | -| | Projection: labels.ts AS ts, labels.host AS host, labels.cpu AS cpu | -| | PromInstantManipulate: range=[0..40000], lookback=[300000], interval=[10000], time index=[ts] | -| | PromSeriesDivide: tags=["host"] | -| | Filter: labels.host = Utf8("host2") AND labels.ts >= TimestampMillisecond(-299999, None) AND labels.ts <= TimestampMillisecond(40000, None) | -| | TableScan: labels, partial_filters=[labels.host = Utf8("host2"), labels.ts >= TimestampMillisecond(-299999, None), labels.ts <= TimestampMillisecond(40000, None)] | -| | ]] | -| physical_plan | UnionExec | -| | CooperativeExec | ++---------------+------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+ +| plan_type | plan | ++---------------+------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+ +| logical_plan | Union | +| | MergeScan [is_placeholder=false, remote_input=[ | +| | Projection: Utf8("host1") AS source, host1_data.ts, host1_data.cpu | +| | SubqueryAlias: host1_data | +| | Projection: labels.ts AS ts, labels.host AS host, labels.cpu AS cpu | +| | Projection: labels.ts, labels.host, labels.cpu | +| | Projection: labels.ts, labels.host, labels.cpu, Utf8("labels") FieldMetadata { inner: {"greptime:promql:role": "metric_name"} } AS __promql_metric_name | +| | PromInstantManipulate: range=[0..40000], lookback=[300000], interval=[10000], time index=[ts] | +| | PromSeriesDivide: tags=["host"] | +| | Filter: labels.host = Utf8("host1") AND labels.ts >= TimestampMillisecond(-299999, None) AND labels.ts <= TimestampMillisecond(40000, None) | +| | TableScan: labels, partial_filters=[labels.host = Utf8("host1"), labels.ts >= TimestampMillisecond(-299999, None), labels.ts <= TimestampMillisecond(40000, None)] | +| | ]] | +| | MergeScan [is_placeholder=false, remote_input=[ | +| | Projection: Utf8("host2") AS source, host2_data.ts, host2_data.cpu | +| | SubqueryAlias: host2_data | +| | Projection: labels.ts AS ts, labels.host AS host, labels.cpu AS cpu | +| | Projection: labels.ts, labels.host, labels.cpu | +| | Projection: labels.ts, labels.host, labels.cpu, Utf8("labels") FieldMetadata { inner: {"greptime:promql:role": "metric_name"} } AS __promql_metric_name | +| | PromInstantManipulate: range=[0..40000], lookback=[300000], interval=[10000], time index=[ts] | +| | PromSeriesDivide: tags=["host"] | +| | Filter: labels.host = Utf8("host2") AND labels.ts >= TimestampMillisecond(-299999, None) AND labels.ts <= TimestampMillisecond(40000, None) | +| | TableScan: labels, partial_filters=[labels.host = Utf8("host2"), labels.ts >= TimestampMillisecond(-299999, None), labels.ts <= TimestampMillisecond(40000, None)] | +| | ]] | +| physical_plan | InterleaveExec | +| | CooperativeExec | | | MergeScanExec: REDACTED -| | CooperativeExec | +| | CooperativeExec | | | MergeScanExec: REDACTED -| | | -+---------------+--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+ +| | | ++---------------+------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+ -- Nested CTEs with TQL WITH @@ -637,30 +666,32 @@ EXPLAIN WITH ) SELECT count(*) as high_values FROM final; -+---------------+-------------------------------------------------------------------------------------------------------------------------------------------------------------------+ -| plan_type | plan | -+---------------+-------------------------------------------------------------------------------------------------------------------------------------------------------------------+ -| logical_plan | MergeScan [is_placeholder=false, remote_input=[ | -| | Projection: count(Int64(1)) AS count(*) AS high_values | -| | Aggregate: groupBy=[[]], aggr=[[count(final.ts) AS count(Int64(1))]] | -| | SubqueryAlias: final | -| | Projection: processed.ts AS ts, processed.percent AS percent | -| | Projection: processed.ts, processed.percent | -| | SubqueryAlias: processed | -| | Projection: base_tql.ts AS ts, percent AS percent | -| | Projection: base_tql.ts, base_tql.val * Float64(100) AS percent | -| | SubqueryAlias: base_tql | -| | Projection: metric.ts AS ts, metric.val AS val | -| | Filter: metric.val > Float64(0) AND metric.val * Float64(100) > Float64(200) | -| | PromInstantManipulate: range=[0..40000], lookback=[300000], interval=[10000], time index=[ts] | -| | PromSeriesDivide: tags=[] | -| | Filter: metric.ts >= TimestampMillisecond(-299999, None) AND metric.ts <= TimestampMillisecond(40000, None) | -| | TableScan: metric, partial_filters=[metric.ts >= TimestampMillisecond(-299999, None), metric.ts <= TimestampMillisecond(40000, None)] | -| | ]] | -| physical_plan | CooperativeExec | ++---------------+-----------------------------------------------------------------------------------------------------------------------------------------------------------------------+ +| plan_type | plan | ++---------------+-----------------------------------------------------------------------------------------------------------------------------------------------------------------------+ +| logical_plan | MergeScan [is_placeholder=false, remote_input=[ | +| | Projection: count(Int64(1)) AS count(*) AS high_values | +| | Aggregate: groupBy=[[]], aggr=[[count(final.ts) AS count(Int64(1))]] | +| | SubqueryAlias: final | +| | Projection: processed.ts AS ts, processed.percent AS percent | +| | Projection: processed.ts, processed.percent | +| | SubqueryAlias: processed | +| | Projection: base_tql.ts AS ts, percent AS percent | +| | Projection: base_tql.ts, base_tql.val * Float64(100) AS percent | +| | SubqueryAlias: base_tql | +| | Projection: metric.ts AS ts, metric.val AS val | +| | Projection: metric.ts, metric.val | +| | Projection: metric.ts, metric.val, Utf8("metric") FieldMetadata { inner: {"greptime:promql:role": "metric_name"} } AS __promql_metric_name | +| | Filter: metric.val > Float64(0) AND metric.val * Float64(100) > Float64(200) | +| | PromInstantManipulate: range=[0..40000], lookback=[300000], interval=[10000], time index=[ts] | +| | PromSeriesDivide: tags=[] | +| | Filter: metric.ts >= TimestampMillisecond(-299999, None) AND metric.ts <= TimestampMillisecond(40000, None) | +| | TableScan: metric, partial_filters=[metric.ts >= TimestampMillisecond(-299999, None), metric.ts <= TimestampMillisecond(40000, None)] | +| | ]] | +| physical_plan | CooperativeExec | | | MergeScanExec: REDACTED -| | | -+---------------+-------------------------------------------------------------------------------------------------------------------------------------------------------------------+ +| | | ++---------------+-----------------------------------------------------------------------------------------------------------------------------------------------------------------------+ -- TQL CTE with time-based functions WITH time_shifted AS ( @@ -680,22 +711,24 @@ EXPLAIN WITH time_shifted AS ( ) SELECT * FROM time_shifted; -+---------------+----------------------------------------------------------------------------------------------------------------------------------------------------+ -| plan_type | plan | -+---------------+----------------------------------------------------------------------------------------------------------------------------------------------------+ -| logical_plan | MergeScan [is_placeholder=false, remote_input=[ | -| | Projection: time_shifted.ts, time_shifted.val | -| | SubqueryAlias: time_shifted | -| | PromInstantManipulate: range=[0..40000], lookback=[300000], interval=[10000], time index=[ts] | -| | PromSeriesNormalize: offset=[50000], time index=[ts], filter NaN: [false] | -| | PromSeriesDivide: tags=[] | -| | Filter: metric.ts >= TimestampMillisecond(-349999, None) AND metric.ts <= TimestampMillisecond(-10000, None) | -| | TableScan: metric, partial_filters=[metric.ts >= TimestampMillisecond(-349999, None), metric.ts <= TimestampMillisecond(-10000, None)] | -| | ]] | -| physical_plan | CooperativeExec | ++---------------+--------------------------------------------------------------------------------------------------------------------------------------------------------+ +| plan_type | plan | ++---------------+--------------------------------------------------------------------------------------------------------------------------------------------------------+ +| logical_plan | MergeScan [is_placeholder=false, remote_input=[ | +| | Projection: time_shifted.ts, time_shifted.val | +| | SubqueryAlias: time_shifted | +| | Projection: metric.ts, metric.val | +| | Projection: metric.ts, metric.val, Utf8("metric") FieldMetadata { inner: {"greptime:promql:role": "metric_name"} } AS __promql_metric_name | +| | PromInstantManipulate: range=[0..40000], lookback=[300000], interval=[10000], time index=[ts] | +| | PromSeriesNormalize: offset=[50000], time index=[ts], filter NaN: [false] | +| | PromSeriesDivide: tags=[] | +| | Filter: metric.ts >= TimestampMillisecond(-349999, None) AND metric.ts <= TimestampMillisecond(-10000, None) | +| | TableScan: metric, partial_filters=[metric.ts >= TimestampMillisecond(-349999, None), metric.ts <= TimestampMillisecond(-10000, None)] | +| | ]] | +| physical_plan | CooperativeExec | | | MergeScanExec: REDACTED -| | | -+---------------+----------------------------------------------------------------------------------------------------------------------------------------------------+ +| | | ++---------------+--------------------------------------------------------------------------------------------------------------------------------------------------------+ -- TQL CTE with JOIN between TQL and regular table -- SQLNESS SORT_RESULT 3 1 @@ -737,47 +770,49 @@ WHERE l.host = 'host1' ORDER BY t.ts, l.host, avg_value LIMIT 5; -+---------------+----------------------------------------------------------------------------------------------------------------------------------------------------------------------+ -| plan_type | plan | -+---------------+----------------------------------------------------------------------------------------------------------------------------------------------------------------------+ -| logical_plan | Sort: t.ts ASC NULLS LAST, l.host ASC NULLS LAST, avg_value ASC NULLS LAST, fetch=5 | -| | Projection: t.ts, t.cpu AS avg_value, l.host | -| | Inner Join: date_trunc(Utf8("second"), t.ts) = date_trunc(Utf8("second"), l.ts) | -| | Projection: t.ts, t.cpu | -| | MergeScan [is_placeholder=false, remote_input=[ | -| | SubqueryAlias: t | -| | SubqueryAlias: tql_summary | -| | Projection: labels.ts AS ts, prom_avg_over_time(ts_range,cpu) AS host, labels.host AS cpu | -| | Filter: prom_avg_over_time(ts_range,cpu) IS NOT NULL | -| | Projection: labels.ts, prom_avg_over_time(ts_range, cpu) AS prom_avg_over_time(ts_range,cpu), labels.host | -| | PromRangeManipulate: req range=[0..40000], interval=[10000], eval range=[30000], time index=[ts], values=["cpu"] | -| | PromSeriesNormalize: offset=[0], time index=[ts], filter NaN: [true] | -| | PromSeriesDivide: tags=["host"] | -| | Filter: labels.ts >= TimestampMillisecond(-29999, None) AND labels.ts <= TimestampMillisecond(40000, None) | -| | TableScan: labels, partial_filters=[labels.ts >= TimestampMillisecond(-29999, None), labels.ts <= TimestampMillisecond(40000, None)] | -| | ]] | -| | Projection: l.ts, l.host | -| | MergeScan [is_placeholder=false, remote_input=[ | -| | SubqueryAlias: l | -| | Filter: labels.host = Utf8("host1") | -| | TableScan: labels, partial_filters=[labels.host = Utf8("host1")] | -| | ]] | -| physical_plan | SortPreservingMergeExec: [ts@0 ASC NULLS LAST, host@2 ASC NULLS LAST, avg_value@1 ASC NULLS LAST], fetch=5 | ++---------------+------------------------------------------------------------------------------------------------------------------------------------------------------------------------+ +| plan_type | plan | ++---------------+------------------------------------------------------------------------------------------------------------------------------------------------------------------------+ +| logical_plan | Sort: t.ts ASC NULLS LAST, l.host ASC NULLS LAST, avg_value ASC NULLS LAST, fetch=5 | +| | Projection: t.ts, t.cpu AS avg_value, l.host | +| | Inner Join: date_trunc(Utf8("second"), t.ts) = date_trunc(Utf8("second"), l.ts) | +| | Projection: t.ts, t.cpu | +| | MergeScan [is_placeholder=false, remote_input=[ | +| | SubqueryAlias: t | +| | SubqueryAlias: tql_summary | +| | Projection: labels.ts AS ts, prom_avg_over_time(ts_range,cpu) AS host, labels.host AS cpu | +| | Projection: labels.ts, prom_avg_over_time(ts_range,cpu), labels.host | +| | Filter: prom_avg_over_time(ts_range,cpu) IS NOT NULL | +| | Projection: labels.ts, prom_avg_over_time(ts_range, cpu) AS prom_avg_over_time(ts_range,cpu), labels.host, __promql_metric_name | +| | Projection: labels.ts, labels.host, cpu, ts_range, Utf8("labels") FieldMetadata { inner: {"greptime:promql:role": "metric_name"} } AS __promql_metric_name | +| | PromRangeManipulate: req range=[0..40000], interval=[10000], eval range=[30000], time index=[ts], values=["cpu"] | +| | PromSeriesNormalize: offset=[0], time index=[ts], filter NaN: [true] | +| | PromSeriesDivide: tags=["host"] | +| | Filter: labels.ts >= TimestampMillisecond(-29999, None) AND labels.ts <= TimestampMillisecond(40000, None) | +| | TableScan: labels, partial_filters=[labels.ts >= TimestampMillisecond(-29999, None), labels.ts <= TimestampMillisecond(40000, None)] | +| | ]] | +| | Projection: l.ts, l.host | +| | MergeScan [is_placeholder=false, remote_input=[ | +| | SubqueryAlias: l | +| | Filter: labels.host = Utf8("host1") | +| | TableScan: labels, partial_filters=[labels.host = Utf8("host1")] | +| | ]] | +| physical_plan | SortPreservingMergeExec: [ts@0 ASC NULLS LAST, host@2 ASC NULLS LAST, avg_value@1 ASC NULLS LAST], fetch=5 | | | SortExec: TopK(fetch=5), expr=[ts@0 ASC NULLS LAST, host@2 ASC NULLS LAST, avg_value@1 ASC NULLS LAST], preserve_REDACTED -| | ProjectionExec: expr=[ts@0 as ts, cpu@1 as avg_value, host@2 as host] | -| | HashJoinExec: mode=Partitioned, join_type=Inner, on=[(date_trunc(Utf8("second"),t.ts)@2, date_trunc(Utf8("second"),l.ts)@2)], projection=[ts@0, cpu@1, host@4] | +| | ProjectionExec: expr=[ts@0 as ts, cpu@1 as avg_value, host@2 as host] | +| | HashJoinExec: mode=Partitioned, join_type=Inner, on=[(date_trunc(Utf8("second"),t.ts)@2, date_trunc(Utf8("second"),l.ts)@2)], projection=[ts@0, cpu@1, host@4] | | | RepartitionExec: REDACTED -| | ProjectionExec: expr=[ts@0 as ts, cpu@1 as cpu, date_trunc(second, ts@0) as date_trunc(Utf8("second"),t.ts)] | +| | ProjectionExec: expr=[ts@0 as ts, cpu@1 as cpu, date_trunc(second, ts@0) as date_trunc(Utf8("second"),t.ts)] | | | RepartitionExec: REDACTED -| | ProjectionExec: expr=[ts@0 as ts, cpu@2 as cpu] | +| | ProjectionExec: expr=[ts@0 as ts, cpu@2 as cpu] | | | MergeScanExec: REDACTED | | RepartitionExec: REDACTED -| | ProjectionExec: expr=[ts@0 as ts, host@1 as host, date_trunc(second, ts@0) as date_trunc(Utf8("second"),l.ts)] | +| | ProjectionExec: expr=[ts@0 as ts, host@1 as host, date_trunc(second, ts@0) as date_trunc(Utf8("second"),l.ts)] | | | RepartitionExec: REDACTED -| | ProjectionExec: expr=[ts@0 as ts, host@1 as host] | +| | ProjectionExec: expr=[ts@0 as ts, host@1 as host] | | | MergeScanExec: REDACTED -| | | -+---------------+----------------------------------------------------------------------------------------------------------------------------------------------------------------------+ +| | | ++---------------+------------------------------------------------------------------------------------------------------------------------------------------------------------------------+ -- TQL CTE with JOIN and value aliasing -- SQLNESS SORT_RESULT 3 1 @@ -819,47 +854,49 @@ WHERE l.host = 'host1' ORDER BY t.ts, l.host, avg_value LIMIT 5; -+---------------+----------------------------------------------------------------------------------------------------------------------------------------------------------------------+ -| plan_type | plan | -+---------------+----------------------------------------------------------------------------------------------------------------------------------------------------------------------+ -| logical_plan | Sort: t.ts ASC NULLS LAST, l.host ASC NULLS LAST, avg_value ASC NULLS LAST, fetch=5 | -| | Projection: t.ts, t.cpu AS avg_value, l.host | -| | Inner Join: date_trunc(Utf8("second"), t.ts) = date_trunc(Utf8("second"), l.ts) | -| | Projection: t.cpu, t.ts | -| | MergeScan [is_placeholder=false, remote_input=[ | -| | SubqueryAlias: t | -| | SubqueryAlias: tql_summary | -| | Projection: prom_avg_over_time(ts_range,cpu) AS cpu, labels.host, labels.ts | -| | Filter: prom_avg_over_time(ts_range,cpu) IS NOT NULL | -| | Projection: labels.ts, prom_avg_over_time(ts_range, cpu) AS prom_avg_over_time(ts_range,cpu), labels.host | -| | PromRangeManipulate: req range=[0..40000], interval=[10000], eval range=[30000], time index=[ts], values=["cpu"] | -| | PromSeriesNormalize: offset=[0], time index=[ts], filter NaN: [true] | -| | PromSeriesDivide: tags=["host"] | -| | Filter: labels.ts >= TimestampMillisecond(-29999, None) AND labels.ts <= TimestampMillisecond(40000, None) | -| | TableScan: labels, partial_filters=[labels.ts >= TimestampMillisecond(-29999, None), labels.ts <= TimestampMillisecond(40000, None)] | -| | ]] | -| | Projection: l.ts, l.host | -| | MergeScan [is_placeholder=false, remote_input=[ | -| | SubqueryAlias: l | -| | Filter: labels.host = Utf8("host1") | -| | TableScan: labels, partial_filters=[labels.host = Utf8("host1")] | -| | ]] | -| physical_plan | SortPreservingMergeExec: [ts@0 ASC NULLS LAST, host@2 ASC NULLS LAST, avg_value@1 ASC NULLS LAST], fetch=5 | ++---------------+------------------------------------------------------------------------------------------------------------------------------------------------------------------------+ +| plan_type | plan | ++---------------+------------------------------------------------------------------------------------------------------------------------------------------------------------------------+ +| logical_plan | Sort: t.ts ASC NULLS LAST, l.host ASC NULLS LAST, avg_value ASC NULLS LAST, fetch=5 | +| | Projection: t.ts, t.cpu AS avg_value, l.host | +| | Inner Join: date_trunc(Utf8("second"), t.ts) = date_trunc(Utf8("second"), l.ts) | +| | Projection: t.cpu, t.ts | +| | MergeScan [is_placeholder=false, remote_input=[ | +| | SubqueryAlias: t | +| | SubqueryAlias: tql_summary | +| | Projection: prom_avg_over_time(ts_range,cpu) AS cpu, labels.host, labels.ts | +| | Projection: labels.ts, prom_avg_over_time(ts_range,cpu), labels.host | +| | Filter: prom_avg_over_time(ts_range,cpu) IS NOT NULL | +| | Projection: labels.ts, prom_avg_over_time(ts_range, cpu) AS prom_avg_over_time(ts_range,cpu), labels.host, __promql_metric_name | +| | Projection: labels.ts, labels.host, cpu, ts_range, Utf8("labels") FieldMetadata { inner: {"greptime:promql:role": "metric_name"} } AS __promql_metric_name | +| | PromRangeManipulate: req range=[0..40000], interval=[10000], eval range=[30000], time index=[ts], values=["cpu"] | +| | PromSeriesNormalize: offset=[0], time index=[ts], filter NaN: [true] | +| | PromSeriesDivide: tags=["host"] | +| | Filter: labels.ts >= TimestampMillisecond(-29999, None) AND labels.ts <= TimestampMillisecond(40000, None) | +| | TableScan: labels, partial_filters=[labels.ts >= TimestampMillisecond(-29999, None), labels.ts <= TimestampMillisecond(40000, None)] | +| | ]] | +| | Projection: l.ts, l.host | +| | MergeScan [is_placeholder=false, remote_input=[ | +| | SubqueryAlias: l | +| | Filter: labels.host = Utf8("host1") | +| | TableScan: labels, partial_filters=[labels.host = Utf8("host1")] | +| | ]] | +| physical_plan | SortPreservingMergeExec: [ts@0 ASC NULLS LAST, host@2 ASC NULLS LAST, avg_value@1 ASC NULLS LAST], fetch=5 | | | SortExec: TopK(fetch=5), expr=[ts@0 ASC NULLS LAST, host@2 ASC NULLS LAST, avg_value@1 ASC NULLS LAST], preserve_REDACTED -| | ProjectionExec: expr=[ts@0 as ts, cpu@1 as avg_value, host@2 as host] | -| | HashJoinExec: mode=Partitioned, join_type=Inner, on=[(date_trunc(Utf8("second"),t.ts)@2, date_trunc(Utf8("second"),l.ts)@2)], projection=[ts@1, cpu@0, host@4] | +| | ProjectionExec: expr=[ts@0 as ts, cpu@1 as avg_value, host@2 as host] | +| | HashJoinExec: mode=Partitioned, join_type=Inner, on=[(date_trunc(Utf8("second"),t.ts)@2, date_trunc(Utf8("second"),l.ts)@2)], projection=[ts@1, cpu@0, host@4] | | | RepartitionExec: REDACTED -| | ProjectionExec: expr=[cpu@0 as cpu, ts@1 as ts, date_trunc(second, ts@1) as date_trunc(Utf8("second"),t.ts)] | +| | ProjectionExec: expr=[cpu@0 as cpu, ts@1 as ts, date_trunc(second, ts@1) as date_trunc(Utf8("second"),t.ts)] | | | RepartitionExec: REDACTED -| | ProjectionExec: expr=[cpu@0 as cpu, ts@2 as ts] | +| | ProjectionExec: expr=[cpu@0 as cpu, ts@2 as ts] | | | MergeScanExec: REDACTED | | RepartitionExec: REDACTED -| | ProjectionExec: expr=[ts@0 as ts, host@1 as host, date_trunc(second, ts@0) as date_trunc(Utf8("second"),l.ts)] | +| | ProjectionExec: expr=[ts@0 as ts, host@1 as host, date_trunc(second, ts@0) as date_trunc(Utf8("second"),l.ts)] | | | RepartitionExec: REDACTED -| | ProjectionExec: expr=[ts@0 as ts, host@1 as host] | +| | ProjectionExec: expr=[ts@0 as ts, host@1 as host] | | | MergeScanExec: REDACTED -| | | -+---------------+----------------------------------------------------------------------------------------------------------------------------------------------------------------------+ +| | | ++---------------+------------------------------------------------------------------------------------------------------------------------------------------------------------------------+ -- Error case - TQL ANALYZE should fail WITH tql_analyze AS ( @@ -914,22 +951,24 @@ EXPLAIN WITH tql_lookback AS ( ) SELECT count(*) FROM tql_lookback; -+---------------+--------------------------------------------------------------------------------------------------------------------------------------------------+ -| plan_type | plan | -+---------------+--------------------------------------------------------------------------------------------------------------------------------------------------+ -| logical_plan | MergeScan [is_placeholder=false, remote_input=[ | -| | Projection: count(Int64(1)) AS count(*) | -| | Aggregate: groupBy=[[]], aggr=[[count(tql_lookback.ts) AS count(Int64(1))]] | -| | SubqueryAlias: tql_lookback | -| | PromInstantManipulate: range=[0..40000], lookback=[15000], interval=[10000], time index=[ts] | -| | PromSeriesDivide: tags=[] | -| | Filter: metric.ts >= TimestampMillisecond(-14999, None) AND metric.ts <= TimestampMillisecond(40000, None) | -| | TableScan: metric, partial_filters=[metric.ts >= TimestampMillisecond(-14999, None), metric.ts <= TimestampMillisecond(40000, None)] | -| | ]] | -| physical_plan | CooperativeExec | ++---------------+------------------------------------------------------------------------------------------------------------------------------------------------------+ +| plan_type | plan | ++---------------+------------------------------------------------------------------------------------------------------------------------------------------------------+ +| logical_plan | MergeScan [is_placeholder=false, remote_input=[ | +| | Projection: count(Int64(1)) AS count(*) | +| | Aggregate: groupBy=[[]], aggr=[[count(tql_lookback.ts) AS count(Int64(1))]] | +| | SubqueryAlias: tql_lookback | +| | Projection: metric.ts, metric.val | +| | Projection: metric.ts, metric.val, Utf8("metric") FieldMetadata { inner: {"greptime:promql:role": "metric_name"} } AS __promql_metric_name | +| | PromInstantManipulate: range=[0..40000], lookback=[15000], interval=[10000], time index=[ts] | +| | PromSeriesDivide: tags=[] | +| | Filter: metric.ts >= TimestampMillisecond(-14999, None) AND metric.ts <= TimestampMillisecond(40000, None) | +| | TableScan: metric, partial_filters=[metric.ts >= TimestampMillisecond(-14999, None), metric.ts <= TimestampMillisecond(40000, None)] | +| | ]] | +| physical_plan | CooperativeExec | | | MergeScanExec: REDACTED -| | | -+---------------+--------------------------------------------------------------------------------------------------------------------------------------------------+ +| | | ++---------------+------------------------------------------------------------------------------------------------------------------------------------------------------+ drop table metric;