///|
pub(all) struct SqlAdvice {
statements : Array[String]
warnings : Array[String]
primary_keys : Array[Array[Int32]]
} derive(Eq, Debug)
///|
fn quote_sql_identifier(name : String) -> String raise DesignError {
if !safe_label(name) {
raise Invalid("SQL identifiers must use validated ASCII labels")
}
"\"" + name + "\""
}
///|
fn sql_columns(
owner : Schema,
attrs : Array[Int32],
) -> String raise DesignError {
let names = []
for a in attrs {
names.push(quote_sql_identifier(owner.labels[a]))
}
names.join(", ")
}
///|
pub fn Schema::sql_advice(
self : Schema,
plan : Plan,
prefix : String,
limits~ : Limits = default_limits(),
) -> SqlAdvice raise DesignError {
if !safe_label(prefix) || prefix.length() > 100 {
raise Invalid("SQL prefix must be a short ASCII identifier")
}
let parts = self.fragments(plan.relations, true)
let budget = meter(limits)
let statements = []
let primary_keys = []
let warnings = [
"Advisory SQL only: no execution, type inference, migration ordering or dialect validation.",
"All columns use TEXT NOT NULL. Literal strings do not model SQL NULL.", "General functional dependencies are NOT enforced by these primary keys.",
"No foreign keys are inferred: repeated attributes alone do not imply referential integrity.",
]
for i in 0.. String {
let out = StringBuilder()
for warning in self.warnings {
out.write_string("-- " + warning + "\n")
}
out.write_string(self.statements.join("\n\n"))
out.write_string("\n")
out.to_string()
}
///|
pub extend SqlAdvice with Eq::{equal, not_equal}
///|
pub extend SqlAdvice with Debug::{to_repr}