Skip to content

Commit dc72f7a

Browse files
committed
refactor
1 parent 5cf7348 commit dc72f7a

3 files changed

Lines changed: 37 additions & 56 deletions

File tree

Cargo.lock

Lines changed: 4 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

datafusion/common/Cargo.toml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -86,6 +86,7 @@ log = { workspace = true }
8686
object_store = { workspace = true, optional = true }
8787
parquet = { workspace = true, optional = true, default-features = true }
8888
recursive = { workspace = true, optional = true }
89+
strum = { workspace = true, features = ["derive"] }
8990
sqlparser = { workspace = true, optional = true }
9091
tokio = { workspace = true }
9192

datafusion/common/src/format.rs

Lines changed: 32 additions & 56 deletions
Original file line numberDiff line numberDiff line change
@@ -15,11 +15,14 @@
1515
// specific language governing permissions and limitations
1616
// under the License.
1717

18+
use std::collections::HashSet;
1819
use std::fmt::{self, Display};
1920
use std::str::FromStr;
2021

2122
use arrow::compute::CastOptions;
2223
use arrow::util::display::{DurationFormat, FormatOptions};
24+
use itertools::Itertools;
25+
use strum::EnumString;
2326

2427
use crate::config::{ConfigField, Visit};
2528
use crate::error::{DataFusionError, Result};
@@ -222,14 +225,26 @@ impl ConfigField for ExplainFormat {
222225
/// (when specified) or aggregated metrics are displayed (when omitted).
223226
/// In contrast, `MetricType` determines which *levels* of metrics are
224227
/// displayed.
225-
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
228+
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, strum::Display, EnumString)]
229+
#[strum(
230+
serialize_all = "lowercase",
231+
ascii_case_insensitive,
232+
parse_err_ty = DataFusionError,
233+
parse_err_fn = metric_type_parse_error
234+
)]
226235
pub enum MetricType {
227236
/// Common metrics for high-level insights (answering which operator is slow)
228237
Summary,
229238
/// For deep operator-level introspection for developers
230239
Dev,
231240
}
232241

242+
fn metric_type_parse_error(s: &str) -> DataFusionError {
243+
DataFusionError::Configuration(format!(
244+
"Invalid explain analyze level '{s}'. Expected 'summary' or 'dev'."
245+
))
246+
}
247+
233248
impl MetricType {
234249
/// Returns the set of metric types that should be shown for this level.
235250
///
@@ -243,36 +258,13 @@ impl MetricType {
243258
}
244259
}
245260

246-
impl FromStr for MetricType {
247-
type Err = DataFusionError;
248-
249-
fn from_str(s: &str) -> Result<Self, Self::Err> {
250-
match s.trim().to_lowercase().as_str() {
251-
"summary" => Ok(Self::Summary),
252-
"dev" => Ok(Self::Dev),
253-
other => Err(DataFusionError::Configuration(format!(
254-
"Invalid explain analyze level. Expected 'summary' or 'dev'. Got '{other}'"
255-
))),
256-
}
257-
}
258-
}
259-
260-
impl Display for MetricType {
261-
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
262-
match self {
263-
Self::Summary => write!(f, "summary"),
264-
Self::Dev => write!(f, "dev"),
265-
}
266-
}
267-
}
268-
269261
impl ConfigField for MetricType {
270262
fn visit<V: Visit>(&self, v: &mut V, key: &str, description: &'static str) {
271263
v.some(key, self, description)
272264
}
273265

274266
fn set(&mut self, _: &str, value: &str) -> Result<()> {
275-
*self = MetricType::from_str(value)?;
267+
*self = value.parse()?;
276268
Ok(())
277269
}
278270
}
@@ -301,7 +293,13 @@ impl ConfigField for MetricType {
301293
/// Metrics that do not declare a category (the default for custom
302294
/// `Count` / `Gauge` metrics) are treated as
303295
/// [`Uncategorized`](Self::Uncategorized) for filtering purposes.
304-
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
296+
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, strum::Display, EnumString)]
297+
#[strum(
298+
serialize_all = "lowercase",
299+
ascii_case_insensitive,
300+
parse_err_ty = DataFusionError,
301+
parse_err_fn = metric_category_parse_error
302+
)]
305303
pub enum MetricCategory {
306304
/// Row counts and related dimensionless counters: `output_rows`,
307305
/// `spilled_rows`, `output_batches`, pruning metrics, ratios, etc.
@@ -333,32 +331,11 @@ pub enum MetricCategory {
333331
Uncategorized,
334332
}
335333

336-
impl FromStr for MetricCategory {
337-
type Err = DataFusionError;
338-
339-
fn from_str(s: &str) -> Result<Self, Self::Err> {
340-
match s.trim().to_lowercase().as_str() {
341-
"rows" => Ok(Self::Rows),
342-
"bytes" => Ok(Self::Bytes),
343-
"timing" => Ok(Self::Timing),
344-
"uncategorized" => Ok(Self::Uncategorized),
345-
other => Err(DataFusionError::Configuration(format!(
346-
"Invalid metric category '{other}'. \
347-
Expected 'rows', 'bytes', 'timing', or 'uncategorized'."
348-
))),
349-
}
350-
}
351-
}
352-
353-
impl Display for MetricCategory {
354-
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
355-
match self {
356-
Self::Rows => write!(f, "rows"),
357-
Self::Bytes => write!(f, "bytes"),
358-
Self::Timing => write!(f, "timing"),
359-
Self::Uncategorized => write!(f, "uncategorized"),
360-
}
361-
}
334+
fn metric_category_parse_error(s: &str) -> DataFusionError {
335+
DataFusionError::Configuration(format!(
336+
"Invalid metric category '{s}'. \
337+
Expected 'rows', 'bytes', 'timing', or 'uncategorized'."
338+
))
362339
}
363340

364341
/// Controls which [`MetricCategory`] values are shown in `EXPLAIN ANALYZE`.
@@ -389,12 +366,11 @@ impl FromStr for ExplainAnalyzeCategories {
389366
"all" => Ok(Self::All),
390367
"none" => Ok(Self::Only(vec![])),
391368
other => {
392-
let mut cats = Vec::new();
369+
let mut cats = HashSet::new();
393370
for part in other.split(',') {
394-
cats.push(part.trim().parse::<MetricCategory>()?);
371+
cats.insert(part.trim().parse::<MetricCategory>()?);
395372
}
396-
cats.dedup();
397-
Ok(Self::Only(cats))
373+
Ok(Self::Only(cats.into_iter().collect_vec()))
398374
}
399375
}
400376
}

0 commit comments

Comments
 (0)