grammar+db: 3i — not_null_missing diagnostic + TableColumn constraints (ADR-0033 §8.3)
Extend SchemaCache TableColumn with not_null + has_default (with a TableColumn::new constructor for the common no-constraint case), populated in build_schema_cache from ColumnDescription (a PK column counts as not-null). New dml_not_null_missing_diagnostics pass: a WARNING when a SQL INSERT's explicit column list omits a column that is NOT NULL with no DEFAULT — advisory (the engine enforces it). serial/shortid (auto-filled) and defaulted columns are excluded. Anchored on the target-table ident (no token for the omitted column). Catalog key diagnostic.not_null_missing (engine-neutral). Tests (+4): fires on omitted required column; silent when included, when defaulted, and for auto-gen serial/shortid. ~24 TableColumn literal sites updated for the two new fields (build clean). 1591 pass / 0 fail / 1 ignored. Clippy clean. All three ADR-0033 §8 DML diagnostics now implemented. Remaining 3i: cross-cut verification + #12 UPSERT DO UPDATE validation.
This commit is contained in:
+33
-5
@@ -55,10 +55,36 @@ pub struct SchemaCache {
|
||||
|
||||
/// One column's user-facing type info, scoped to a table
|
||||
/// (ADR-0024 §Phase D, §WalkContext).
|
||||
///
|
||||
/// `not_null` / `has_default` (ADR-0033 §8.3, sub-phase 3i) let the
|
||||
/// walker pre-flight a `not_null_missing` WARNING — an `INSERT`
|
||||
/// whose column list omits a required column. They default to
|
||||
/// `false`, so callers/tests that don't care construct via
|
||||
/// [`TableColumn::new`].
|
||||
#[derive(Debug, Clone, PartialEq, Eq, Hash)]
|
||||
pub struct TableColumn {
|
||||
pub name: String,
|
||||
pub user_type: crate::dsl::types::Type,
|
||||
/// The column is declared `NOT NULL` (a PK column is also
|
||||
/// effectively not-null; the cache builder records that).
|
||||
pub not_null: bool,
|
||||
/// The column has a `DEFAULT` — so omitting it on `INSERT` is
|
||||
/// fine even when `not_null`.
|
||||
pub has_default: bool,
|
||||
}
|
||||
|
||||
impl TableColumn {
|
||||
/// A column with no NOT-NULL / default info — the common case
|
||||
/// for callers and tests that don't exercise ADR-0033 §8.3.
|
||||
#[must_use]
|
||||
pub fn new(name: impl Into<String>, user_type: crate::dsl::types::Type) -> Self {
|
||||
Self {
|
||||
name: name.into(),
|
||||
user_type,
|
||||
not_null: false,
|
||||
has_default: false,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl SchemaCache {
|
||||
@@ -1453,6 +1479,8 @@ mod tests {
|
||||
.map(|(n, t)| TableColumn {
|
||||
name: (*n).to_string(),
|
||||
user_type: *t,
|
||||
not_null: false,
|
||||
has_default: false,
|
||||
})
|
||||
.collect();
|
||||
for c in &cols {
|
||||
@@ -1479,7 +1507,7 @@ mod tests {
|
||||
cache
|
||||
.table_columns
|
||||
.insert("Orders".to_string(), vec![
|
||||
TableColumn { name: "OrderTotal".to_string(), user_type: Type::Real },
|
||||
TableColumn { name: "OrderTotal".to_string(), user_type: Type::Real, not_null: false, has_default: false },
|
||||
]);
|
||||
cache.tables.push("Orders".to_string());
|
||||
let cs = cands_with("update Customers set ", 21, &cache);
|
||||
@@ -2102,15 +2130,15 @@ mod tests {
|
||||
s.table_columns.insert(
|
||||
"a".to_string(),
|
||||
vec![
|
||||
TableColumn { name: "id".to_string(), user_type: Type::Int },
|
||||
TableColumn { name: "name".to_string(), user_type: Type::Text },
|
||||
TableColumn { name: "id".to_string(), user_type: Type::Int, not_null: false, has_default: false },
|
||||
TableColumn { name: "name".to_string(), user_type: Type::Text, not_null: false, has_default: false },
|
||||
],
|
||||
);
|
||||
s.table_columns.insert(
|
||||
"b".to_string(),
|
||||
vec![
|
||||
TableColumn { name: "id".to_string(), user_type: Type::Int },
|
||||
TableColumn { name: "total".to_string(), user_type: Type::Real },
|
||||
TableColumn { name: "id".to_string(), user_type: Type::Int, not_null: false, has_default: false },
|
||||
TableColumn { name: "total".to_string(), user_type: Type::Real, not_null: false, has_default: false },
|
||||
],
|
||||
);
|
||||
s
|
||||
|
||||
Reference in New Issue
Block a user