diff --git a/src/sql/src/session/vars/constraints.rs b/src/sql/src/session/vars/constraints.rs index 83cff166cb8a3..f373fc559c430 100644 --- a/src/sql/src/session/vars/constraints.rs +++ b/src/sql/src/session/vars/constraints.rs @@ -11,6 +11,7 @@ use std::fmt::Debug; use std::ops::{RangeBounds, RangeFrom, RangeInclusive}; +use std::time::Duration; use mz_repr::adt::numeric::Numeric; use mz_repr::bytes::ByteSize; @@ -19,6 +20,8 @@ use super::{Value, Var, VarError}; pub static NUMERIC_NON_NEGATIVE: NumericNonNegNonNan = NumericNonNegNonNan; +pub static NON_ZERO_DURATION: NonZeroDuration = NonZeroDuration; + pub static NUMERIC_BOUNDED_0_1_INCLUSIVE: NumericInRange> = NumericInRange(0.0f64..=1.0); @@ -114,6 +117,25 @@ impl DomainConstraint for NumericNonNegNonNan { } } +#[derive(Debug, Clone, Eq, PartialEq)] +pub struct NonZeroDuration; + +impl DomainConstraint for NonZeroDuration { + type Value = Duration; + + fn check(&self, var: &dyn Var, d: &Duration) -> Result<(), VarError> { + if d.is_zero() { + Err(VarError::InvalidParameterValue { + name: var.name(), + invalid_values: vec![format!("{:?}", d)], + reason: "only supports non-zero durations".to_string(), + }) + } else { + Ok(()) + } + } +} + #[derive(Debug, Clone, Eq, PartialEq)] pub struct NumericInRange(pub R); diff --git a/src/sql/src/session/vars/definitions.rs b/src/sql/src/session/vars/definitions.rs index 479e18037ec27..85f3cd04a9010 100644 --- a/src/sql/src/session/vars/definitions.rs +++ b/src/sql/src/session/vars/definitions.rs @@ -39,8 +39,8 @@ use uncased::UncasedStr; use crate::session::user::{SUPPORT_USER, SYSTEM_USER, User}; use crate::session::vars::constraints::{ - BYTESIZE_AT_LEAST_1MB, DomainConstraint, NUMERIC_BOUNDED_0_1_INCLUSIVE, NUMERIC_NON_NEGATIVE, - ValueConstraint, + BYTESIZE_AT_LEAST_1MB, DomainConstraint, NON_ZERO_DURATION, NUMERIC_BOUNDED_0_1_INCLUSIVE, + NUMERIC_NON_NEGATIVE, ValueConstraint, }; use crate::session::vars::errors::VarError; use crate::session::vars::polyfill::{LazyValueFn, lazy_value, value}; @@ -1441,7 +1441,8 @@ pub static DEFAULT_TIMESTAMP_INTERVAL: VarDefinition = VarDefinition::new( value!(Duration; Duration::from_millis(1000)), "The interval at which timestamps are assigned to data from sources and tables.", false, -); +) +.with_constraint(&NON_ZERO_DURATION); pub static MIN_TIMESTAMP_INTERVAL: VarDefinition = VarDefinition::new( "min_timestamp_interval", diff --git a/test/sqllogictest/alter.slt b/test/sqllogictest/alter.slt index 0aa7e75f6d954..4ac849ae751fb 100644 --- a/test/sqllogictest/alter.slt +++ b/test/sqllogictest/alter.slt @@ -205,6 +205,21 @@ ALTER SYSTEM SET max_timestamp_interval = '10s'; ---- COMPLETE 0 +simple conn=mz_system,user=mz_system +ALTER SYSTEM SET default_timestamp_interval = '1'; +---- +COMPLETE 0 + +simple conn=mz_system,user=mz_system +ALTER SYSTEM SET default_timestamp_interval = '0'; +---- +db error: ERROR: parameter "default_timestamp_interval" cannot have value "0ns": only supports non-zero durations + +simple conn=mz_system,user=mz_system +ALTER SYSTEM SET default_timestamp_interval = '-1'; +---- +db error: ERROR: parameter "default_timestamp_interval" requires a "duration" value + statement ok ALTER SOURCE s SET (TIMESTAMP INTERVAL '2s')