use enumflags2::BitFlags;
use psl::{Datasource, PreviewFeature};
use quaint::prelude::SqlFamily;
pub struct IntrospectionContext {
pub render_config: bool,
pub composite_type_depth: CompositeTypeDepth,
previous_schema: psl::ValidatedSchema,
namespaces: Option<Vec<String>>,
}
impl IntrospectionContext {
pub fn new(
previous_schema: psl::ValidatedSchema,
composite_type_depth: CompositeTypeDepth,
namespaces: Option<Vec<String>>,
) -> Self {
IntrospectionContext {
previous_schema,
composite_type_depth,
render_config: true,
namespaces,
}
}
pub fn new_config_only(
previous_schema: psl::ValidatedSchema,
composite_type_depth: CompositeTypeDepth,
namespaces: Option<Vec<String>>,
) -> Self {
let mut config_blocks = String::new();
for source in previous_schema.db.ast().sources() {
config_blocks.push_str(&previous_schema.db.source()[source.span.start..source.span.end]);
config_blocks.push('\n');
}
for generator in previous_schema.db.ast().generators() {
config_blocks.push_str(&previous_schema.db.source()[generator.span.start..generator.span.end]);
config_blocks.push('\n');
}
let previous_schema_config_only = psl::parse_schema(config_blocks).unwrap();
Self::new(previous_schema_config_only, composite_type_depth, namespaces)
}
pub fn previous_schema(&self) -> &psl::ValidatedSchema {
&self.previous_schema
}
pub fn datasource(&self) -> &Datasource {
self.previous_schema.configuration.datasources.first().unwrap()
}
pub fn foreign_keys_enabled(&self) -> bool {
self.datasource().relation_mode().uses_foreign_keys()
}
pub fn schema_string(&self) -> &str {
self.previous_schema.db.source()
}
pub fn configuration(&self) -> &psl::Configuration {
&self.previous_schema.configuration
}
pub fn preview_features(&self) -> BitFlags<PreviewFeature> {
self.previous_schema.configuration.preview_features()
}
pub fn namespaces(&self) -> Option<&[String]> {
self.namespaces.as_deref()
}
pub fn sql_family(&self) -> SqlFamily {
match self.datasource().active_provider {
"postgresql" => SqlFamily::Postgres,
"cockroachdb" => SqlFamily::Postgres,
"sqlite" => SqlFamily::Sqlite,
"sqlserver" => SqlFamily::Mssql,
"mysql" => SqlFamily::Mysql,
name => unreachable!("The name `{}` for the datamodel connector is not known", name),
}
}
}
#[derive(Debug, Clone, Copy)]
pub enum CompositeTypeDepth {
Level(usize),
Infinite,
None,
}
impl From<isize> for CompositeTypeDepth {
fn from(size: isize) -> Self {
match size {
size if size < 0 => Self::Infinite,
0 => Self::None,
_ => Self::Level(size as usize),
}
}
}
impl Default for CompositeTypeDepth {
fn default() -> Self {
Self::None
}
}
impl CompositeTypeDepth {
pub fn is_none(self) -> bool {
matches!(self, Self::None)
}
pub fn level_down(self) -> CompositeTypeDepth {
match self {
CompositeTypeDepth::Level(level) if level > 1 => Self::Level(level - 1),
CompositeTypeDepth::Level(_) => Self::None,
CompositeTypeDepth::Infinite => Self::Infinite,
CompositeTypeDepth::None => Self::None,
}
}
}