frontend/instance/
promql.rs1use std::time::SystemTime;
16
17use auth::PermissionTableTarget;
18use catalog::information_schema::TABLES;
19use client::OutputData;
20use common_catalog::consts::INFORMATION_SCHEMA_NAME;
21use common_catalog::format_full_table_name;
22use common_recordbatch::util;
23use common_telemetry::tracing;
24use promql_parser::label::{Matcher, Matchers};
25use query::promql;
26use query::promql::planner::PromPlanner;
27use servers::prometheus;
28use session::context::QueryContextRef;
29use snafu::{OptionExt, ResultExt};
30
31use crate::error::{
32 CatalogSnafu, CollectRecordbatchSnafu, ExecLogicalPlanSnafu,
33 PrometheusLabelValuesQueryPlanSnafu, PrometheusMetricNamesQueryPlanSnafu, ReadTableSnafu,
34 Result, TableNotFoundSnafu, TableSnafu,
35};
36use crate::instance::Instance;
37
38impl Instance {
39 #[tracing::instrument(skip_all)]
41 pub(crate) async fn handle_query_metric_names(
42 &self,
43 matchers: Vec<Matcher>,
44 schema: &str,
45 ctx: &QueryContextRef,
46 ) -> Result<Vec<String>> {
47 let _timer = crate::metrics::PROMQL_QUERY_METRICS_ELAPSED
48 .with_label_values(&[ctx.get_db_string().as_str()])
49 .start_timer();
50
51 let table = self
52 .catalog_manager
53 .table(
54 ctx.current_catalog(),
55 INFORMATION_SCHEMA_NAME,
56 TABLES,
57 Some(ctx),
58 )
59 .await
60 .context(CatalogSnafu)?
61 .with_context(|| TableNotFoundSnafu {
62 table_name: "greptime.information_schema.tables",
63 })?;
64
65 let dataframe = self
66 .query_engine
67 .read_table(table)
68 .with_context(|_| ReadTableSnafu {
69 table_name: "greptime.information_schema.tables",
70 })?;
71
72 let logical_plan =
73 prometheus::metric_name_matchers_to_plan(dataframe, matchers, schema, ctx)
74 .context(PrometheusMetricNamesQueryPlanSnafu)?;
75
76 let results = self
77 .query_engine
78 .execute(logical_plan, ctx.clone())
79 .await
80 .context(ExecLogicalPlanSnafu)?;
81
82 let batches = match results.data {
83 OutputData::Stream(stream) => util::collect(stream)
84 .await
85 .context(CollectRecordbatchSnafu)?,
86 OutputData::RecordBatches(rbs) => rbs.take(),
87 _ => unreachable!("should not happen"),
88 };
89
90 let mut results = Vec::with_capacity(batches.iter().map(|b| b.num_rows()).sum());
91
92 for batch in batches {
93 batch
95 .iter_column_as_string(0)
96 .flatten()
97 .for_each(|x| results.push(x))
98 }
99
100 Ok(results)
101 }
102
103 #[tracing::instrument(skip_all)]
105 pub(crate) async fn handle_query_label_values(
106 &self,
107 target: PermissionTableTarget,
108 label_name: String,
109 matchers: Vec<Matcher>,
110 start: SystemTime,
111 end: SystemTime,
112 ctx: &QueryContextRef,
113 ) -> Result<Vec<String>> {
114 let full_table_name =
115 format_full_table_name(&target.catalog, &target.schema, &target.table);
116 let table = self
117 .catalog_manager
118 .table(&target.catalog, &target.schema, &target.table, Some(ctx))
119 .await
120 .context(CatalogSnafu)?
121 .with_context(|| TableNotFoundSnafu {
122 table_name: full_table_name.clone(),
123 })?;
124
125 if table.schema().column_schema_by_name(&label_name).is_none() {
128 return table::error::ColumnNotExistsSnafu {
129 column_name: label_name,
130 table_name: full_table_name,
131 }
132 .fail()
133 .context(TableSnafu);
134 }
135
136 let dataframe = self
137 .query_engine
138 .read_table(table.clone())
139 .with_context(|_| ReadTableSnafu {
140 table_name: full_table_name,
141 })?;
142
143 let scan_plan = dataframe.into_unoptimized_plan();
144 let filter_conditions =
145 PromPlanner::matchers_to_expr(Matchers::new(matchers), scan_plan.schema())
146 .context(PrometheusLabelValuesQueryPlanSnafu)?;
147 let logical_plan = promql::label_values::rewrite_label_values_query(
148 table,
149 scan_plan,
150 filter_conditions,
151 label_name,
152 start,
153 end,
154 )
155 .context(PrometheusLabelValuesQueryPlanSnafu)?;
156
157 let results = self
158 .query_engine
159 .execute(logical_plan, ctx.clone())
160 .await
161 .context(ExecLogicalPlanSnafu)?;
162
163 let batches = match results.data {
164 OutputData::Stream(stream) => util::collect(stream)
165 .await
166 .context(CollectRecordbatchSnafu)?,
167 OutputData::RecordBatches(rbs) => rbs.take(),
168 _ => unreachable!("should not happen"),
169 };
170
171 let mut results = Vec::with_capacity(batches.iter().map(|b| b.num_rows()).sum());
172 for batch in batches {
173 batch
175 .iter_column_as_string(0)
176 .flatten()
177 .for_each(|x| results.push(x))
178 }
179
180 Ok(results)
181 }
182}