Skip to content

Commit

Permalink
SQLite: fixes BIGINT PRIMARY KEY AUTOINCREMENT #689
Browse files Browse the repository at this point in the history
  • Loading branch information
tyt2y3 committed Nov 21, 2023
1 parent f82ab91 commit 37a30f6
Show file tree
Hide file tree
Showing 3 changed files with 98 additions and 58 deletions.
131 changes: 75 additions & 56 deletions src/backend/sqlite/table.rs
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ impl TableBuilder for SqliteQueryBuilder {

if let Some(column_type) = &column_def.types {
write!(sql, " ").unwrap();
self.prepare_column_type(column_type, sql);
self.prepare_column_type(&column_def.spec, column_type, sql);
}

let mut is_primary_key = false;
Expand Down Expand Up @@ -39,61 +39,7 @@ impl TableBuilder for SqliteQueryBuilder {
}

fn prepare_column_type(&self, column_type: &ColumnType, sql: &mut dyn SqlWriter) {
write!(
sql,
"{}",
match column_type {
ColumnType::Char(length) => match length {
Some(length) => format!("text({length})"),
None => "text".into(),
},
ColumnType::String(length) => match length {
Some(length) => format!("text({length})"),
None => "text".into(),
},
ColumnType::Text => "text".into(),
ColumnType::TinyInteger | ColumnType::TinyUnsigned => "integer".into(),
ColumnType::SmallInteger | ColumnType::SmallUnsigned => "integer".into(),
ColumnType::Integer | ColumnType::Unsigned => "integer".into(),
ColumnType::BigInteger | ColumnType::BigUnsigned => "bigint".into(),
ColumnType::Float => "real".into(),
ColumnType::Double => "real".into(),
ColumnType::Decimal(precision) => match precision {
Some((precision, scale)) => format!("real({precision}, {scale})"),
None => "real".into(),
},
ColumnType::DateTime => "text".into(),
ColumnType::Timestamp => "text".into(),
ColumnType::TimestampWithTimeZone => "text".into(),
ColumnType::Time => "text".into(),
ColumnType::Date => "text".into(),
ColumnType::Interval(_, _) => "unsupported".into(),
ColumnType::Binary(blob_size) => match blob_size {
BlobSize::Blob(Some(length)) => format!("binary({length})"),
_ => "blob".into(),
},
ColumnType::VarBinary(length) => format!("binary({length})"),
ColumnType::Boolean => "boolean".into(),
ColumnType::Money(precision) => match precision {
Some((precision, scale)) => format!("integer({precision}, {scale})"),
None => "integer".into(),
},
ColumnType::Json => "text".into(),
ColumnType::JsonBinary => "text".into(),
ColumnType::Uuid => "text(36)".into(),
ColumnType::Custom(iden) => iden.to_string(),
ColumnType::Enum { .. } => "text".into(),
ColumnType::Array(_) => unimplemented!("Array 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()
self.prepare_column_type(&[], column_type, sql)
}

fn column_spec_auto_increment_keyword(&self) -> &str {
Expand Down Expand Up @@ -169,3 +115,76 @@ impl TableBuilder for SqliteQueryBuilder {
}
}
}

impl SqliteQueryBuilder {
fn prepare_column_type(
&self,
column_specs: &[ColumnSpec],
column_type: &ColumnType,
sql: &mut dyn SqlWriter,
) {
let is_auto_increment = column_specs
.iter()
.any(|s| matches!(s, ColumnSpec::AutoIncrement));
write!(
sql,
"{}",
match column_type {
ColumnType::Char(length) => match length {
Some(length) => format!("text({length})"),
None => "text".into(),
},
ColumnType::String(length) => match length {
Some(length) => format!("text({length})"),
None => "text".into(),
},
ColumnType::Text => "text".into(),
ColumnType::TinyInteger | ColumnType::TinyUnsigned => "integer".into(),
ColumnType::SmallInteger | ColumnType::SmallUnsigned => "integer".into(),
ColumnType::Integer | ColumnType::Unsigned => "integer".into(),
ColumnType::BigInteger | ColumnType::BigUnsigned => if is_auto_increment {
"integer"
} else {
"bigint"
}
.into(),
ColumnType::Float => "real".into(),
ColumnType::Double => "real".into(),
ColumnType::Decimal(precision) => match precision {
Some((precision, scale)) => format!("real({precision}, {scale})"),
None => "real".into(),
},
ColumnType::DateTime => "text".into(),
ColumnType::Timestamp => "text".into(),
ColumnType::TimestampWithTimeZone => "text".into(),
ColumnType::Time => "text".into(),
ColumnType::Date => "text".into(),
ColumnType::Interval(_, _) => "unsupported".into(),
ColumnType::Binary(blob_size) => match blob_size {
BlobSize::Blob(Some(length)) => format!("binary({length})"),
_ => "blob".into(),
},
ColumnType::VarBinary(length) => format!("binary({length})"),
ColumnType::Boolean => "boolean".into(),
ColumnType::Money(precision) => match precision {
Some((precision, scale)) => format!("integer({precision}, {scale})"),
None => "integer".into(),
},
ColumnType::Json => "text".into(),
ColumnType::JsonBinary => "text".into(),
ColumnType::Uuid => "text(36)".into(),
ColumnType::Custom(iden) => iden.to_string(),
ColumnType::Enum { .. } => "text".into(),
ColumnType::Array(_) => unimplemented!("Array 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()
}
}
3 changes: 1 addition & 2 deletions src/query/with.rs
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,6 @@ use crate::SqlWriter;
use crate::SubQueryStatement;
use crate::TableRef;
use crate::{Alias, QueryBuilder};
use std::ops::Deref;

/// A table definition inside a WITH clause ([WithClause]).
///
Expand Down Expand Up @@ -122,7 +121,7 @@ impl CommonTableExpression {
let mut cte = Self::default();
cte.try_set_cols_from_selects(&select.selects);
if let Some(from) = select.from.get(0) {
match from.deref() {
match from {
TableRef::Table(iden) => cte.set_table_name_from_select(iden),
TableRef::SchemaTable(_, iden) => cte.set_table_name_from_select(iden),
TableRef::DatabaseSchemaTable(_, _, iden) => cte.set_table_name_from_select(iden),
Expand Down
22 changes: 22 additions & 0 deletions tests/sqlite/table.rs
Original file line number Diff line number Diff line change
Expand Up @@ -172,6 +172,28 @@ fn create_6() {
);
}

#[test]
fn create_7() {
assert_eq!(
Table::create()
.table(Task::Table)
.col(
ColumnDef::new(Task::Id)
.big_integer()
.not_null()
.auto_increment()
.primary_key()
)
.to_string(SqliteQueryBuilder),
[
r#"CREATE TABLE "task" ("#,
r#""id" integer NOT NULL PRIMARY KEY AUTOINCREMENT"#,
r#")"#,
]
.join(" ")
);
}

#[test]
fn create_with_unique_index() {
assert_eq!(
Expand Down

0 comments on commit 37a30f6

Please sign in to comment.