-
Notifications
You must be signed in to change notification settings - Fork 212
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
intro: Use the pair structure for models, field and indexes
- Loading branch information
Julius de Bruijn
committed
Dec 1, 2022
1 parent
9527a31
commit 8262ad5
Showing
42 changed files
with
2,325 additions
and
1,436 deletions.
There are no files selected for viewing
Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.
Oops, something went wrong.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
235 changes: 72 additions & 163 deletions
235
introspection-engine/connectors/sql-introspection-connector/src/defaults.rs
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,187 +1,96 @@ | ||
use crate::calculate_datamodel::{InputContext, OutputContext}; | ||
use datamodel_renderer::datamodel as renderer; | ||
use introspection_connector::Version; | ||
use psl::{ | ||
builtin_connectors::{MySqlType, PostgresType}, | ||
datamodel_connector::constraint_names::ConstraintNames, | ||
dml, | ||
parser_database::walkers, | ||
use crate::{ | ||
calculate_datamodel::OutputContext, | ||
pair::{DefaultKind, ScalarFieldPair}, | ||
}; | ||
use datamodel_renderer::{ | ||
datamodel as renderer, | ||
value::{Constant, Function, Text, Value}, | ||
}; | ||
use sql_schema_describer::{self as sql, postgres::PostgresSchemaExt}; | ||
|
||
pub(crate) fn render_default<'a>( | ||
column: sql::ColumnWalker<'a>, | ||
existing_field: Option<walkers::ScalarFieldWalker<'a>>, | ||
input: InputContext<'a>, | ||
pub(crate) fn render<'a>( | ||
field: ScalarFieldPair<'a>, | ||
output: &mut OutputContext<'a>, | ||
) -> Option<renderer::DefaultValue<'a>> { | ||
use datamodel_renderer::value::{Constant, Function, Text, Value}; | ||
let mut rendered = match field.default().kind() { | ||
Some(kind) => match kind { | ||
DefaultKind::Sequence(sequence) => { | ||
let mut fun = Function::new("sequence"); | ||
|
||
let mut result = match (column.default().map(|d| d.kind()), column.column_type_family()) { | ||
(Some(sql::DefaultKind::Sequence(name)), _) if input.is_cockroach() => { | ||
let connector_data: &PostgresSchemaExt = input.schema.downcast_connector_data(); | ||
if sequence.min_value != 1 { | ||
fun.push_param(("minValue", Constant::from(sequence.min_value))); | ||
} | ||
|
||
let sequence_idx = connector_data | ||
.sequences | ||
.binary_search_by_key(&name, |s| &s.name) | ||
.unwrap(); | ||
if sequence.max_value != i64::MAX { | ||
fun.push_param(("maxValue", Constant::from(sequence.max_value))); | ||
} | ||
|
||
let sequence = &connector_data.sequences[sequence_idx]; | ||
if sequence.cache_size != 1 { | ||
fun.push_param(("cache", Constant::from(sequence.cache_size))); | ||
} | ||
|
||
let mut fun = Function::new("sequence"); | ||
if sequence.increment_by != 1 { | ||
fun.push_param(("increment", Constant::from(sequence.increment_by))); | ||
} | ||
|
||
if sequence.min_value != 1 { | ||
fun.push_param(("minValue", Constant::from(sequence.min_value))); | ||
} | ||
if sequence.start_value != 1 { | ||
fun.push_param(("start", Constant::from(sequence.start_value))); | ||
} | ||
|
||
if sequence.max_value != i64::MAX { | ||
fun.push_param(("maxValue", Constant::from(sequence.max_value))); | ||
Some(renderer::DefaultValue::function(fun)) | ||
} | ||
DefaultKind::DbGenerated(default_string) => { | ||
let mut fun = Function::new("dbgenerated"); | ||
|
||
if sequence.cache_size != 1 { | ||
fun.push_param(("cache", Constant::from(sequence.cache_size))); | ||
} | ||
if let Some(param) = default_string.filter(|s| !s.trim_matches('\0').is_empty()) { | ||
fun.push_param(Value::from(Text::new(param))); | ||
} | ||
|
||
if sequence.increment_by != 1 { | ||
fun.push_param(("increment", Constant::from(sequence.increment_by))); | ||
Some(renderer::DefaultValue::function(fun)) | ||
} | ||
|
||
if sequence.start_value != 1 { | ||
fun.push_param(("start", Constant::from(sequence.start_value))); | ||
DefaultKind::Autoincrement => Some(renderer::DefaultValue::function(Function::new("autoincrement"))), | ||
DefaultKind::Uuid => Some(renderer::DefaultValue::function(Function::new("uuid"))), | ||
DefaultKind::Cuid => Some(renderer::DefaultValue::function(Function::new("cuid"))), | ||
DefaultKind::Now => Some(renderer::DefaultValue::function(Function::new("now"))), | ||
DefaultKind::String(s) => Some(renderer::DefaultValue::text(s)), | ||
DefaultKind::Constant(c) => Some(renderer::DefaultValue::constant(c)), | ||
DefaultKind::EnumVariant(c) => Some(renderer::DefaultValue::constant(c)), | ||
DefaultKind::Bytes(b) => Some(renderer::DefaultValue::bytes(b)), | ||
DefaultKind::StringList(vals) => { | ||
let vals = vals.into_iter().map(Text::new).collect(); | ||
Some(renderer::DefaultValue::array(vals)) | ||
} | ||
|
||
Some(renderer::DefaultValue::function(fun)) | ||
} | ||
(_, sql::ColumnTypeFamily::Int | sql::ColumnTypeFamily::BigInt) if column.is_autoincrement() => { | ||
Some(renderer::DefaultValue::function(Function::new("autoincrement"))) | ||
} | ||
(_, sql::ColumnTypeFamily::Int | sql::ColumnTypeFamily::BigInt) if is_sequence(column) => { | ||
Some(renderer::DefaultValue::function(Function::new("autoincrement"))) | ||
} | ||
(Some(sql::DefaultKind::Sequence(_)), _) => { | ||
Some(renderer::DefaultValue::function(Function::new("autoincrement"))) | ||
} | ||
(Some(sql::DefaultKind::UniqueRowid), _) => { | ||
Some(renderer::DefaultValue::function(Function::new("autoincrement"))) | ||
} | ||
(Some(sql::DefaultKind::Now), sql::ColumnTypeFamily::DateTime) => { | ||
Some(renderer::DefaultValue::function(Function::new("now"))) | ||
} | ||
(Some(sql::DefaultKind::DbGenerated(default_string)), _) => { | ||
let mut fun = Function::new("dbgenerated"); | ||
|
||
if let Some(param) = default_string.as_ref().filter(|s| !s.trim_matches('\0').is_empty()) { | ||
fun.push_param(Value::from(Text::new(param))); | ||
DefaultKind::ConstantList(vals) => Some(renderer::DefaultValue::array(vals)), | ||
DefaultKind::BytesList(vals) => { | ||
let vals = vals.into_iter().map(Value::from).collect(); | ||
Some(renderer::DefaultValue::array(vals)) | ||
} | ||
|
||
Some(renderer::DefaultValue::function(fun)) | ||
} | ||
(Some(sql::DefaultKind::Value(dml::PrismaValue::Enum(variant))), sql::ColumnTypeFamily::Enum(enum_id)) => { | ||
let variant = input | ||
.schema | ||
.walk(*enum_id) | ||
.variants() | ||
.find(|v| v.name() == variant) | ||
.unwrap(); | ||
|
||
let variant_name = input.enum_variant_name(variant.id).prisma_name(); | ||
Some(renderer::DefaultValue::constant(variant_name)) | ||
} | ||
(Some(sql::DefaultKind::Value(dml::PrismaValue::String(val))), _) => Some(renderer::DefaultValue::text(val)), | ||
(Some(sql::DefaultKind::Value(dml::PrismaValue::List(val))), _) => { | ||
let vals = val | ||
.iter() | ||
.map(|val| match val { | ||
dml::PrismaValue::String(v) => Value::from(Text::new(v)), | ||
dml::PrismaValue::Boolean(v) => Value::from(Constant::from(v)), | ||
dml::PrismaValue::Enum(v) => Value::from(Constant::from(v)), | ||
dml::PrismaValue::Int(v) => Value::from(Constant::from(v)), | ||
dml::PrismaValue::Uuid(v) => Value::from(Constant::from(v)), | ||
dml::PrismaValue::List(_) => unreachable!("Lists of lists are not supported in defaults."), | ||
dml::PrismaValue::Json(v) => Value::from(Text::new(v)), | ||
dml::PrismaValue::Xml(v) => Value::from(Text::new(v)), | ||
dml::PrismaValue::Object(_) => unreachable!("Objects are not supported in defaults."), | ||
dml::PrismaValue::Null => Value::from(Constant::from("null")), | ||
dml::PrismaValue::DateTime(v) => Value::from(Constant::from(v)), | ||
dml::PrismaValue::Float(v) => Value::from(Constant::from(v)), | ||
dml::PrismaValue::BigInt(v) => Value::from(Constant::from(v)), | ||
dml::PrismaValue::Bytes(v) => Value::from(v.clone()), | ||
}) | ||
.collect(); | ||
|
||
Some(renderer::DefaultValue::array(vals)) | ||
} | ||
(Some(sql::DefaultKind::Value(val)), _) => Some(renderer::DefaultValue::constant(val)), | ||
|
||
// Prisma-level defaults. | ||
(None, sql::ColumnTypeFamily::String) => match existing_field.and_then(|f| f.default_value()) { | ||
Some(value) if value.is_cuid() => Some(renderer::DefaultValue::function(Function::new("cuid"))), | ||
Some(value) if value.is_uuid() => Some(renderer::DefaultValue::function(Function::new("uuid"))), | ||
None if matches!(output.version, Version::Prisma1 | Version::Prisma11) => { | ||
maybe_prisma1_default(column, input, output) | ||
DefaultKind::Prisma1Uuid => { | ||
let warn = crate::warnings::ModelAndField { | ||
model: field.model().name().to_string(), | ||
field: field.name().to_string(), | ||
}; | ||
|
||
output.warnings.prisma_1_uuid_defaults.push(warn); | ||
Some(renderer::DefaultValue::function(Function::new("uuid"))) | ||
} | ||
_ => None, | ||
}, | ||
|
||
_ => None, | ||
}; | ||
|
||
if let Some(res) = result.as_mut() { | ||
let default_default_value = | ||
ConstraintNames::default_name(column.table().name(), column.name(), input.active_connector()); | ||
|
||
match column.default().and_then(|def| def.constraint_name()) { | ||
Some(map) if map != default_default_value => { | ||
res.map(map); | ||
DefaultKind::Prisma1Cuid => { | ||
let warn = crate::warnings::ModelAndField { | ||
model: field.model().name().to_string(), | ||
field: field.name().to_string(), | ||
}; | ||
|
||
output.warnings.prisma_1_cuid_defaults.push(warn); | ||
Some(renderer::DefaultValue::function(Function::new("cuid"))) | ||
} | ||
_ => (), | ||
} | ||
} | ||
|
||
result | ||
} | ||
|
||
fn is_sequence(column: sql::ColumnWalker<'_>) -> bool { | ||
column.is_single_primary_key() && matches!(&column.default(), Some(d) if d.is_sequence()) | ||
} | ||
|
||
fn maybe_prisma1_default<'a>( | ||
column: sql::ColumnWalker<'a>, | ||
input: InputContext<'a>, | ||
output: &mut OutputContext<'a>, | ||
) -> Option<renderer::DefaultValue<'a>> { | ||
use datamodel_renderer::value::Function; | ||
|
||
let model_and_field = || crate::warnings::ModelAndField { | ||
model: input.table_prisma_name(column.table().id).prisma_name().into_owned(), | ||
field: input.column_prisma_name(column.id).prisma_name().into_owned(), | ||
}, | ||
None => None, | ||
}; | ||
|
||
if input.sql_family.is_postgres() { | ||
let native_type: &PostgresType = column.column_type().native_type.as_ref()?.downcast_ref(); | ||
|
||
if native_type == &PostgresType::VarChar(Some(25)) { | ||
output.warnings.prisma_1_cuid_defaults.push(model_and_field()); | ||
|
||
return Some(renderer::DefaultValue::function(Function::new("cuid"))); | ||
} else if native_type == &PostgresType::VarChar(Some(36)) { | ||
output.warnings.prisma_1_uuid_defaults.push(model_and_field()); | ||
|
||
return Some(renderer::DefaultValue::function(Function::new("uuid"))); | ||
} | ||
} else if input.sql_family.is_mysql() { | ||
let native_type: &MySqlType = column.column_type().native_type.as_ref()?.downcast_ref(); | ||
|
||
if native_type == &MySqlType::Char(25) { | ||
output.warnings.prisma_1_cuid_defaults.push(model_and_field()); | ||
|
||
return Some(renderer::DefaultValue::function(Function::new("cuid"))); | ||
} else if native_type == &MySqlType::Char(36) { | ||
output.warnings.prisma_1_uuid_defaults.push(model_and_field()); | ||
|
||
return Some(renderer::DefaultValue::function(Function::new("uuid"))); | ||
if let Some(res) = rendered.as_mut() { | ||
if let Some(mapped_name) = field.default().mapped_name() { | ||
res.map(mapped_name); | ||
} | ||
} | ||
|
||
None | ||
rendered | ||
} |
Oops, something went wrong.