///|
/// SQLite storage types understood by moonway.
pub(all) enum ColumnType {
IntT
RealT
TextT
BoolT
} derive(Eq, Debug)
///|
pub extend ColumnType with Eq::{equal, not_equal}
///|
pub extend ColumnType with @debug.Debug::{to_repr}
///|
fn ColumnType::sql(self : ColumnType) -> String {
match self {
IntT => "INTEGER"
RealT => "REAL"
TextT => "TEXT"
BoolT => "INTEGER"
}
}
///|
pub(all) struct Column {
name : String
col_type : ColumnType
primary : Bool
}
///|
pub(all) struct Table {
name : String
columns : Array[Column]
}
///|
/// Declare a table. This description is the source of truth for migrations
/// and the admin UI. Row values flow through the builtin `derive(ToJson,
/// FromJson)` — struct field names are the keys, column types drive the
/// storage conversion.
pub fn table(name : String, columns : Array[Column]) -> Table {
{ name, columns, }
}
///|
pub fn column(
name : String,
col_type : ColumnType,
primary~ : Bool = false,
) -> Column {
{ name, col_type, primary, }
}
///|
/// CREATE TABLE IF NOT EXISTS statement for this table.
pub fn Table::create_sql(self : Table) -> String {
let mut defs = ""
for i, col in self.columns {
if i > 0 {
defs = defs + ", "
}
defs = defs + quote_ident(col.name) + " " + col.col_type.sql()
if col.primary {
defs = defs + " PRIMARY KEY"
}
}
"CREATE TABLE IF NOT EXISTS " + quote_ident(self.name) + " (" + defs + ")"
}
///|
fn quote_ident(name : String) -> String {
"\"" + name + "\""
}