#[derive(Debug, Clone, PartialEq, Eq)]
#[allow(clippy::struct_excessive_bools)] pub struct EnvConfig {
pub compute_query_id: ComputeQueryId,
pub explain_no_costs: bool,
pub stats_frozen: bool,
pub plan_deterministic: bool,
pub disable_topk: bool,
pub disable_joinfold: bool,
pub random_seed: Option<u64>,
}
#[derive(Debug, Clone, Copy, PartialEq, Eq, Default)]
pub enum ComputeQueryId {
#[default]
Auto,
Regress,
}
impl Default for EnvConfig {
fn default() -> Self {
Self {
compute_query_id: ComputeQueryId::Auto,
explain_no_costs: false,
stats_frozen: false,
plan_deterministic: false,
disable_topk: false,
disable_joinfold: false,
random_seed: None,
}
}
}
impl EnvConfig {
#[cfg(feature = "std")]
pub fn from_env() -> Self {
extern crate std;
use std::env;
let mut cfg = Self::default();
if let Ok(v) = env::var("SPG_TEST_COMPUTE_QUERY_ID") {
cfg.compute_query_id = if v == "regress" {
ComputeQueryId::Regress
} else {
ComputeQueryId::Auto
};
}
if env_flag("SPG_TEST_EXPLAIN_NO_COSTS") {
cfg.explain_no_costs = true;
}
if env_flag("SPG_TEST_STATS_FROZEN") {
cfg.stats_frozen = true;
}
if env_flag("SPG_TEST_PLAN_DETERMINISTIC") {
cfg.plan_deterministic = true;
}
if env_flag("SPG_TEST_DISABLE_TOPK") {
cfg.disable_topk = true;
}
if env_flag("SPG_TEST_DISABLE_JOINFOLD") {
cfg.disable_joinfold = true;
}
if let Ok(v) = env::var("SPG_TEST_RANDOM_SEED") {
cfg.random_seed = v.parse().ok();
}
cfg
}
#[must_use]
pub fn builder() -> EnvConfigBuilder {
EnvConfigBuilder {
cfg: Self::default(),
}
}
}
#[cfg(feature = "std")]
fn env_flag(name: &str) -> bool {
extern crate std;
std::env::var(name).map(|v| v == "1").unwrap_or(false)
}
#[derive(Debug, Clone, Default)]
pub struct EnvConfigBuilder {
cfg: EnvConfig,
}
impl EnvConfigBuilder {
pub fn compute_query_id(mut self, v: ComputeQueryId) -> Self {
self.cfg.compute_query_id = v;
self
}
pub fn explain_no_costs(mut self, v: bool) -> Self {
self.cfg.explain_no_costs = v;
self
}
pub fn stats_frozen(mut self, v: bool) -> Self {
self.cfg.stats_frozen = v;
self
}
pub fn plan_deterministic(mut self, v: bool) -> Self {
self.cfg.plan_deterministic = v;
self
}
pub fn disable_topk(mut self, v: bool) -> Self {
self.cfg.disable_topk = v;
self
}
pub fn disable_joinfold(mut self, v: bool) -> Self {
self.cfg.disable_joinfold = v;
self
}
pub fn random_seed(mut self, v: u64) -> Self {
self.cfg.random_seed = Some(v);
self
}
pub fn build(self) -> EnvConfig {
self.cfg
}
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn default_is_production() {
let cfg = EnvConfig::default();
assert_eq!(cfg.compute_query_id, ComputeQueryId::Auto);
assert!(!cfg.explain_no_costs);
assert!(!cfg.stats_frozen);
assert!(!cfg.plan_deterministic);
assert!(!cfg.disable_topk);
assert!(!cfg.disable_joinfold);
assert_eq!(cfg.random_seed, None);
}
#[test]
fn builder_roundtrip() {
let cfg = EnvConfig::builder()
.explain_no_costs(true)
.disable_topk(true)
.random_seed(42)
.build();
assert!(cfg.explain_no_costs);
assert!(cfg.disable_topk);
assert_eq!(cfg.random_seed, Some(42));
assert!(!cfg.disable_joinfold);
assert_eq!(cfg.compute_query_id, ComputeQueryId::Auto);
}
}