use crate::imr::Annotation;
#[derive(Copy, Clone, Default, Debug)]
pub struct Annotations {
pub auto_create_time: bool,
pub auto_update_time: bool,
pub auto_increment: bool,
pub choices: bool,
pub default: bool,
pub index: bool,
pub max_length: bool,
pub not_null: bool,
pub primary_key: bool,
pub unique: bool,
pub foreign_key: bool,
}
impl Annotations {
#[rustfmt::skip]
pub const fn check(self) -> Result<(), &'static str> {
use Annotations as A;
let msg = match self {
A { auto_create_time: true, auto_increment: true, .. } => "AutoCreateTime and AutoIncrement are mutually exclusive",
A { auto_create_time: true, choices: true, .. } => "AutoCreateTime and Choices are mutually exclusive",
A { auto_create_time: true, default: true, .. } => "AutoCreateTime and DefaultValue are mutually exclusive",
A { auto_create_time: true, max_length: true, .. } => "AutoCreateTime and MaxLength are mutually exclusive",
A { auto_create_time: true, primary_key: true, .. } => "AutoCreateTime and PrimaryKey are mutually exclusive",
A { auto_create_time: true, unique: true, .. } => "AutoCreateTime and Unique are mutually exclusive",
A { auto_update_time: true, auto_increment: true, .. } => "AutoUpdateTime and AutoIncrement are mutually exclusive",
A { auto_update_time: true, choices: true, .. } => "AutoUpdateTime and Choices are mutually exclusive",
A { auto_update_time: true, max_length: true, .. } => "AutoUpdateTime and MaxLength are mutually exclusive",
A { auto_update_time: true, primary_key: true, .. } => "AutoUpdateTime and PrimaryKey are mutually exclusive",
A { auto_update_time: true, unique: true, .. } => "AutoUpdateTime and Unique are mutually exclusive",
A { auto_increment: true, choices: true, .. } => "AutoIncrement and Choices are mutually exclusive",
A { auto_increment: true, max_length: true, .. } => "AutoIncrement and MaxLength are mutually exclusive",
A { choices: true, max_length: true, .. } => "Choices and MaxLength are mutually exclusive",
A { choices: true, primary_key: true, .. } => "Choices and PrimaryKey are mutually exclusive",
A { choices: true, unique: true, .. } => "Choices and Unique are mutually exclusive",
A { default: true, auto_update_time: true, .. } => "DefaultValue and AutoUpdateTime are mutually exclusive",
A { default: true, auto_increment: true, .. } => "DefaultValue and AutoIncrement are mutually exclusive",
A { default: true, primary_key: true, .. } => "DefaultValue and PrimaryKey are mutually exclusive",
A { default: true, unique: true, .. } => "DefaultValue and Unique are mutually exclusive",
A { index: true, primary_key: true, .. } => "An unnamed Index and PrimaryKey are mutually exclusive; name the index to span the column as part of a composite index",
A { not_null: true, primary_key: true, .. } => "NotNull and PrimaryKey are mutually exclusive",
A { auto_increment: true, primary_key: false, .. } => "AutoIncrement requires PrimaryKey",
A { auto_update_time: true, not_null: true, auto_create_time: false, default: false, ..} => "AutoUpdateTime in combination with NotNull requires ether DefaultValue or AutoCreateTime",
_ => "",
};
if !msg.is_empty() {
Err(msg)
} else {
Ok(())
}
}
}
impl From<&[Annotation]> for Annotations {
fn from(annotations: &[Annotation]) -> Self {
let mut result = Annotations::default();
for annotation in annotations {
match annotation {
Annotation::AutoCreateTime => result.auto_create_time = true,
Annotation::AutoUpdateTime => result.auto_update_time = true,
Annotation::AutoIncrement => result.auto_increment = true,
Annotation::Choices(_) => result.choices = true,
Annotation::DefaultValue(_) => result.default = true,
Annotation::Index(index) => result.index |= index.is_none(),
Annotation::MaxLength(_) => result.max_length = true,
Annotation::NotNull => result.not_null = true,
Annotation::PrimaryKey => result.primary_key = true,
Annotation::Unique => result.unique = true,
Annotation::ForeignKey(_) => result.foreign_key = true,
}
}
result
}
}
#[cfg(test)]
mod test_index_on_primary_key {
use crate::imr::{Annotation, IndexValue};
use crate::lints::Annotations;
fn check(annotations: &[Annotation]) -> Result<(), &'static str> {
Annotations::from(annotations).check()
}
#[test]
fn unnamed_index_on_primary_key_is_redundant() {
assert!(check(&[Annotation::PrimaryKey, Annotation::Index(None)]).is_err());
}
#[test]
fn named_index_on_primary_key_is_allowed() {
assert!(check(&[
Annotation::PrimaryKey,
Annotation::Index(Some(IndexValue {
name: "collection_uuid".to_string(),
priority: Some(2),
})),
])
.is_ok());
}
#[test]
fn an_unnamed_index_is_still_caught_next_to_a_named_one() {
assert!(check(&[
Annotation::PrimaryKey,
Annotation::Index(Some(IndexValue {
name: "collection_uuid".to_string(),
priority: None,
})),
Annotation::Index(None),
])
.is_err());
}
}