use super::*;
use crate::write_int;
impl TableBuilder for SqliteQueryBuilder {
fn prepare_column_def(&self, column_def: &ColumnDef, sql: &mut impl SqlWriter) {
self.prepare_iden(&column_def.name, sql);
if let Some(column_type) = &column_def.types {
sql.write_str(" ").unwrap();
self.prepare_column_type(&column_def.spec, column_type, sql);
}
self.prepare_column_spec(&column_def.spec, sql);
}
fn prepare_column_type(&self, column_type: &ColumnType, sql: &mut impl SqlWriter) {
self.prepare_column_type(&ColumnSpec::default(), column_type, sql)
}
fn column_spec_auto_increment_keyword(&self) -> &str {
" AUTOINCREMENT"
}
fn prepare_table_drop_opt(&self, _drop_opt: &TableDropOpt, _sql: &mut impl SqlWriter) {
}
fn prepare_table_truncate_statement(
&self,
_truncate: &TableTruncateStatement,
_sql: &mut impl SqlWriter,
) {
panic!("Sqlite doesn't support TRUNCATE statement")
}
fn prepare_table_alter_statement(&self, alter: &TableAlterStatement, sql: &mut impl SqlWriter) {
if alter.options.is_empty() {
panic!("No alter option found")
}
if alter.options.len() > 1 {
panic!("Sqlite doesn't support multiple alter options")
}
sql.write_str("ALTER TABLE ").unwrap();
if let Some(table) = &alter.table {
self.prepare_table_ref_table_stmt(table, sql);
sql.write_str(" ").unwrap();
}
match &alter.options[0] {
TableAlterOption::AddColumn(AddColumnOption {
column,
if_not_exists: _,
}) => {
sql.write_str("ADD COLUMN ").unwrap();
self.prepare_column_def(column, sql);
}
TableAlterOption::ModifyColumn(_) => {
panic!("Sqlite not support modifying table column")
}
TableAlterOption::RenameColumn(from_name, to_name) => {
sql.write_str("RENAME COLUMN ").unwrap();
self.prepare_iden(from_name, sql);
sql.write_str(" TO ").unwrap();
self.prepare_iden(to_name, sql);
}
TableAlterOption::DropColumn(DropColumnOption { column_name, .. }) => {
sql.write_str("DROP COLUMN ").unwrap();
self.prepare_iden(column_name, sql);
}
TableAlterOption::DropForeignKey(_) => {
panic!(
"Sqlite does not support modification of foreign key constraints to existing tables"
);
}
TableAlterOption::AddForeignKey(_) => {
panic!(
"Sqlite does not support modification of foreign key constraints to existing tables"
);
}
TableAlterOption::DropConstraint(_) => {
panic!("Sqlite does not support dropping constraints from existing tables");
}
}
}
fn prepare_table_rename_statement(
&self,
rename: &TableRenameStatement,
sql: &mut impl SqlWriter,
) {
sql.write_str("ALTER TABLE ").unwrap();
if let Some(from_name) = &rename.from_name {
self.prepare_table_ref_table_stmt(from_name, sql);
}
sql.write_str(" RENAME TO ").unwrap();
if let Some(to_name) = &rename.to_name {
self.prepare_table_ref_table_stmt(to_name, sql);
}
}
}
impl SqliteQueryBuilder {
fn prepare_column_type(
&self,
_column_specs: &ColumnSpec,
column_type: &ColumnType,
sql: &mut impl SqlWriter,
) {
match column_type {
ColumnType::Char(length) => match length {
Some(length) => {
sql.write_str("char(").unwrap();
write_int(sql, *length);
sql.write_char(')')
}
None => sql.write_str("char"),
},
ColumnType::String(length) => match length {
StringLen::N(length) => {
sql.write_str("varchar(").unwrap();
write_int(sql, *length);
sql.write_char(')')
}
_ => sql.write_str("varchar"),
},
ColumnType::Text => sql.write_str("text"),
ColumnType::TinyInteger | ColumnType::TinyUnsigned => sql.write_str(integer("tinyint")),
ColumnType::SmallInteger | ColumnType::SmallUnsigned => {
sql.write_str(integer("smallint"))
}
ColumnType::Integer | ColumnType::Unsigned => sql.write_str("integer"),
ColumnType::BigInteger | ColumnType::BigUnsigned => sql.write_str("integer"),
ColumnType::Float => sql.write_str("float"),
ColumnType::Double => sql.write_str("double"),
ColumnType::Decimal(precision) => match precision {
Some((precision, scale)) => {
sql.write_str("real(").unwrap();
write_int(sql, *precision);
sql.write_str(", ").unwrap();
write_int(sql, *scale);
sql.write_char(')')
}
None => sql.write_str("real_decimal"),
},
ColumnType::DateTime => sql.write_str("datetime_text"),
ColumnType::Timestamp => sql.write_str("timestamp_text"),
ColumnType::TimestampWithTimeZone => sql.write_str("timestamp_with_timezone_text"),
ColumnType::Time => sql.write_str("time_text"),
ColumnType::Date => sql.write_str("date_text"),
ColumnType::Interval(_, _) => unimplemented!("Interval is not available in Sqlite."),
ColumnType::Binary(length) => {
sql.write_str("blob(").unwrap();
write_int(sql, *length);
sql.write_char(')')
}
ColumnType::VarBinary(length) => match length {
StringLen::N(length) => {
sql.write_str("varbinary_blob(").unwrap();
write_int(sql, *length);
sql.write_char(')')
}
_ => sql.write_str("varbinary_blob"),
},
ColumnType::Blob => sql.write_str("blob"),
ColumnType::Boolean => sql.write_str("boolean"),
ColumnType::Money(precision) => match precision {
Some((precision, scale)) => {
sql.write_str("real_money(").unwrap();
write_int(sql, *precision);
sql.write_str(", ").unwrap();
write_int(sql, *scale);
sql.write_char(')')
}
None => sql.write_str("real_money"),
},
ColumnType::Json => sql.write_str("json_text"),
ColumnType::JsonBinary => sql.write_str("jsonb_text"),
ColumnType::Uuid => sql.write_str("uuid_text"),
ColumnType::Custom(iden) => sql.write_str(&iden.0),
ColumnType::Enum { .. } => sql.write_str("enum_text"),
ColumnType::Array(_) => unimplemented!("Array is not available in Sqlite."),
ColumnType::Vector(_) => unimplemented!("Vector is not available in Sqlite."),
ColumnType::Cidr => unimplemented!("Cidr is not available in Sqlite."),
ColumnType::Inet => unimplemented!("Inet is not available in Sqlite."),
ColumnType::MacAddr => unimplemented!("MacAddr is not available in Sqlite."),
ColumnType::Year => unimplemented!("Year is not available in Sqlite."),
ColumnType::Bit(_) => unimplemented!("Bit is not available in Sqlite."),
ColumnType::VarBit(_) => unimplemented!("VarBit is not available in Sqlite."),
ColumnType::LTree => unimplemented!("LTree is not available in Sqlite."),
}
.unwrap()
}
}
fn integer(ty: &str) -> &str {
if cfg!(feature = "option-sqlite-exact-column-type") {
"integer"
} else {
ty
}
}