///|
/// Live-datasource reflection — the pure, all-backend core of `mctl model
/// datasource`. `parse_dsn` reads a SQLite or PostgreSQL DSN into a `DataSource`;
/// the native `reflect` sub-package then reads the running schema into a list of
/// `ReflectedColumn`. Here that list is supplied directly (no live DB), then
/// `tables_from_reflection` folds it into tables — mapping each raw SQL type onto
/// its MoonBit scalar, so `character varying` and `INTEGER` both land right — and
/// `generate_crud_from_reflection` runs it through the same generator the `.sql`
/// front end uses, so a live schema and a `.sql` file yield an identical model.
///
/// moon run src/examples/06-datasource
#coverage.skip
fn main {
for dsn in ["sqlite:shop.db", "postgres://heke1228:qwe@localhost:5432/shop"] {
let target = try {
match @moonctl.parse_dsn(dsn) {
Sqlite(path) => "Sqlite(\{path})"
Postgres(t) => "Postgres(\{t.user}@\{t.host}:\{t.port}/\{t.database})"
}
} catch {
_ => "bad DSN"
}
println("\{dsn} -> \{target}")
}
println("")
// What the reflect sub-package hands back after reading a live schema.
let cols : Array[@moonctl.ReflectedColumn] = [
{
table: "account",
name: "id",
sql_type: "INTEGER",
primary_key: true,
nullable: false,
},
{
table: "account",
name: "handle",
sql_type: "character varying",
primary_key: false,
nullable: false,
},
{
table: "account",
name: "balance",
sql_type: "BIGINT",
primary_key: false,
nullable: true,
},
]
for t in @moonctl.tables_from_reflection(cols) {
let cs = t.columns.map(fn(c) { c.name + ":" + c.type_ })
println("reflected table \{t.name}: \{cs.join(", ")}")
}
println(
"\n==== generate_crud_from_reflection(cols) -> moonorm model + CRUD ====\n",
)
println(@moonctl.generate_crud_from_reflection(cols))
}