Skip to content

Commit 4bcaf0f

Browse files
refactor: Improve SessionContext::parse_duration API
1 parent 9b7cdda commit 4bcaf0f

File tree

3 files changed

+35
-9
lines changed

3 files changed

+35
-9
lines changed

datafusion/core/src/execution/context/mod.rs

Lines changed: 28 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1184,7 +1184,7 @@ impl SessionContext {
11841184
builder.with_object_list_cache_limit(limit)
11851185
}
11861186
"list_files_cache_ttl" => {
1187-
let duration = Self::parse_duration(value)?;
1187+
let duration = Self::parse_duration(variable, value)?;
11881188
builder.with_object_list_cache_ttl(Some(duration))
11891189
}
11901190
_ => return plan_err!("Unknown runtime configuration: {variable}"),
@@ -1323,21 +1323,27 @@ impl SessionContext {
13231323
}
13241324
}
13251325

1326-
fn parse_duration(duration: &str) -> Result<Duration> {
1326+
fn parse_duration(config_name: &str, duration: &str) -> Result<Duration> {
1327+
if duration.trim().is_empty() {
1328+
return Err(plan_datafusion_err!(
1329+
"Duration should not be empty or blank for '{config_name}'"
1330+
));
1331+
}
1332+
13271333
let mut minutes = None;
13281334
let mut seconds = None;
13291335

13301336
for duration in duration.split_inclusive(&['m', 's']) {
13311337
let (number, unit) = duration.split_at(duration.len() - 1);
13321338
let number: u64 = number.parse().map_err(|_| {
1333-
plan_datafusion_err!("Failed to parse number from duration '{duration}'")
1339+
plan_datafusion_err!("Failed to parse number from duration '{duration}' for '{config_name}'")
13341340
})?;
13351341

13361342
match unit {
13371343
"m" if minutes.is_none() && seconds.is_none() => minutes = Some(number),
13381344
"s" if seconds.is_none() => seconds = Some(number),
13391345
_ => plan_err!(
1340-
"Invalid duration, unit must be either 'm' (minutes), or 's' (seconds), and be in the correct order"
1346+
"Invalid duration, unit must be either 'm' (minutes), or 's' (seconds), and be in the correct order for '{config_name}'"
13411347
)?,
13421348
}
13431349
}
@@ -1347,7 +1353,9 @@ impl SessionContext {
13471353
);
13481354

13491355
if duration.is_zero() {
1350-
return plan_err!("Duration must be greater than 0 seconds");
1356+
return plan_err!(
1357+
"Duration must be greater than 0 seconds for '{config_name}'"
1358+
);
13511359
}
13521360

13531361
Ok(duration)
@@ -2803,21 +2811,33 @@ mod tests {
28032811

28042812
#[test]
28052813
fn test_parse_duration() {
2814+
const LIST_FILES_CACHE_TTL: &str = "datafusion.runtime.list_files_cache_ttl";
2815+
28062816
// Valid durations
28072817
for (duration, want) in [
28082818
("1s", Duration::from_secs(1)),
28092819
("1m", Duration::from_secs(60)),
28102820
("1m0s", Duration::from_secs(60)),
28112821
("1m1s", Duration::from_secs(61)),
28122822
] {
2813-
let have = SessionContext::parse_duration(duration).unwrap();
2823+
let have =
2824+
SessionContext::parse_duration(LIST_FILES_CACHE_TTL, duration).unwrap();
28142825
assert_eq!(want, have);
28152826
}
28162827

28172828
// Invalid durations
2818-
for duration in ["0s", "0m", "1s0m", "1s1m"] {
2819-
let have = SessionContext::parse_duration(duration);
2829+
for duration in [
2830+
"0s", "0m", "1s0m", "1s1m", "XYZ", "1h", "XYZm2s", "", " ", "-1m", "1m 1s",
2831+
"1m1s ", " 1m1s",
2832+
] {
2833+
let have = SessionContext::parse_duration(LIST_FILES_CACHE_TTL, duration);
28202834
assert!(have.is_err());
2835+
assert!(
2836+
have.unwrap_err()
2837+
.message()
2838+
.to_string()
2839+
.contains(LIST_FILES_CACHE_TTL)
2840+
);
28212841
}
28222842
}
28232843

datafusion/sqllogictest/test_files/set_variable.slt

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -450,3 +450,9 @@ datafusion.runtime.temp_directory
450450

451451
statement error DataFusion error: Error during planning: Unsupported value Null
452452
SET datafusion.runtime.memory_limit = NULL
453+
454+
statement error DataFusion error: Error during planning: Unsupported value Null
455+
SET datafusion.runtime.list_files_cache_ttl = NULL
456+
457+
statement error DataFusion error: Error during planning: Duration should not be empty or blank for 'datafusion.runtime.list_files_cache_ttl'
458+
SET datafusion.runtime.list_files_cache_ttl = ' '

docs/source/user-guide/configs.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -210,7 +210,7 @@ The following runtime configuration settings are available:
210210
| key | default | description |
211211
| ------------------------------------------ | ------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
212212
| datafusion.runtime.list_files_cache_limit | 1M | Maximum memory to use for list files cache. Supports suffixes K (kilobytes), M (megabytes), and G (gigabytes). Example: '2G' for 2 gigabytes. |
213-
| datafusion.runtime.list_files_cache_ttl | NULL | TTL (time-to-live) of the entries in the list file cache. Supports units m (minutes), and s (seconds). Example: '2m' for 2 minutes. |
213+
| datafusion.runtime.list_files_cache_ttl | NULL | TTL (time-to-live) of the entries in the list file cache. Supports units m (minutes), and s (seconds). Example: '2m' for 2 minutes or '2m10s' for 2 mins and 10 secs. |
214214
| datafusion.runtime.max_temp_directory_size | 100G | Maximum temporary file directory size. Supports suffixes K (kilobytes), M (megabytes), and G (gigabytes). Example: '2G' for 2 gigabytes. |
215215
| datafusion.runtime.memory_limit | NULL | Maximum memory limit for query execution. Supports suffixes K (kilobytes), M (megabytes), and G (gigabytes). Example: '2G' for 2 gigabytes. |
216216
| datafusion.runtime.metadata_cache_limit | 50M | Maximum memory to use for file metadata cache such as Parquet metadata. Supports suffixes K (kilobytes), M (megabytes), and G (gigabytes). Example: '2G' for 2 gigabytes. |

0 commit comments

Comments
 (0)