use std::fmt::Write as _;
use crate::schema::{ContractSchema, PropertyKind};
pub fn emit(schema: &ContractSchema, epoch: u32) -> String {
let mut columns = Vec::new();
for property in &schema.properties {
let PropertyKind::String {
max_length,
enum_values,
default,
..
} = &property.kind;
let base_type = match max_length {
Some(max) => format!("VARCHAR({max})"),
None => "TEXT".to_owned(),
};
let mut column = format!(" {} {base_type}", identifier(&property.name));
if property.required || default.is_some() {
column.push_str(" NOT NULL");
}
if let Some(value) = default {
let _ = write!(column, " DEFAULT {}", string_literal(value));
}
if let Some(values) = enum_values {
let list = values
.iter()
.map(|value| string_literal(value))
.collect::<Vec<_>>()
.join(", ");
let _ = write!(
column,
" CHECK ({} IN ({list}))",
identifier(&property.name)
);
}
columns.push(column);
}
format!(
"-- GENERATED by pushkin compile from contract '{name}' — do not hand-edit.\n\
-- pushkin-epoch: {epoch}\n\
CREATE TABLE {table} (\n{columns}\n);\n",
name = schema.contract_name,
table = identifier(&schema.contract_name),
columns = columns.join(",\n"),
)
}
fn identifier(name: &str) -> String {
format!("\"{}\"", name.replace('"', "\"\""))
}
fn string_literal(value: &str) -> String {
format!("'{}'", value.replace('\'', "''"))
}