Create new [`ConfigOptions`], taking values from environment variables where possible. For example, to configure `datafusion.execution.batch_size` ([`ExecutionOptions::batch_size`]) you would set the `DATAFUSION_EXECUTION_BATCH_SIZE` environment variable. The name of the environment variable is the option's key, transformed to uppercase and with periods replaced with underscores. Values are par
()
| 1585 | /// warning emitted. Environment variables are read when this method is |
| 1586 | /// called, and are not re-read later. |
| 1587 | pub fn from_env() -> Result<Self> { |
| 1588 | struct Visitor(Vec<String>); |
| 1589 | |
| 1590 | impl Visit for Visitor { |
| 1591 | fn some<V: Display>(&mut self, key: &str, _: V, _: &'static str) { |
| 1592 | self.0.push(key.to_string()) |
| 1593 | } |
| 1594 | |
| 1595 | fn none(&mut self, key: &str, _: &'static str) { |
| 1596 | self.0.push(key.to_string()) |
| 1597 | } |
| 1598 | } |
| 1599 | |
| 1600 | // Extract the names of all fields and then look up the corresponding |
| 1601 | // environment variables. This isn't hugely efficient but avoids |
| 1602 | // ambiguity between `a.b` and `a_b` which would both correspond |
| 1603 | // to an environment variable of `A_B` |
| 1604 | |
| 1605 | let mut keys = Visitor(vec![]); |
| 1606 | let mut ret = Self::default(); |
| 1607 | ret.visit(&mut keys, "datafusion", ""); |
| 1608 | |
| 1609 | for key in keys.0 { |
| 1610 | let env = key.to_uppercase().replace('.', "_"); |
| 1611 | if let Some(var) = std::env::var_os(env) { |
| 1612 | let value = var.to_string_lossy(); |
| 1613 | log::info!("Set {key} to {value} from the environment variable"); |
| 1614 | ret.set(&key, value.as_ref())?; |
| 1615 | } |
| 1616 | } |
| 1617 | |
| 1618 | Ok(ret) |
| 1619 | } |
| 1620 | |
| 1621 | /// Create new ConfigOptions struct, taking values from a string hash map. |
| 1622 | /// |