uqa_sql/semantics/
mutation_rows.rs1use super::{DOC_ID_COLUMN, TABLE_OID_COLUMN, XMIN_COLUMN};
9use crate::{ast::ColumnDef, ColumnType, RowSchema, SQLError};
10
11pub trait MutationRowCatalog: Sync {
13 fn column_definitions(&self, table: &str) -> Result<Option<Vec<ColumnDef>>, String>;
14 fn column_names(&self, table: &str) -> Result<Vec<String>, String>;
15 fn view_schema(&self, name: &str) -> Result<RowSchema, SQLError>;
16}
17
18pub fn null_target_schema(
19 relations: &dyn MutationRowCatalog,
20 table: &str,
21 qualifier: &str,
22) -> Result<RowSchema, SQLError> {
23 let definitions = relations
24 .column_definitions(table)
25 .map_err(|error| dml_storage_error("DML row schema lookup", error))?
26 .ok_or_else(|| SQLError::UnknownTable(table.to_string()))?;
27 let mut columns = if definitions.is_empty() {
28 relations
29 .column_names(table)
30 .map_err(|error| dml_storage_error("DML row schema lookup", error))?
31 } else {
32 definitions
33 .iter()
34 .map(|definition| definition.name.clone())
35 .collect::<Vec<_>>()
36 };
37 let mut types = columns
38 .iter()
39 .map(|column| {
40 definitions
41 .iter()
42 .find(|definition| definition.name == *column)
43 .map(|definition| definition.ty.clone())
44 })
45 .collect::<Vec<_>>();
46 if !columns.iter().any(|column| column == DOC_ID_COLUMN) {
47 columns.push(DOC_ID_COLUMN.into());
48 types.push(Some(ColumnType::BigInteger));
49 }
50 columns.push(TABLE_OID_COLUMN.into());
51 types.push(Some(ColumnType::Oid));
52 columns.push(XMIN_COLUMN.into());
53 types.push(Some(ColumnType::Xid));
54 Ok(RowSchema::with_qualified_types(qualifier, columns, types))
55}
56
57fn dml_storage_error(action: &str, error: impl std::fmt::Display) -> SQLError {
58 SQLError::Internal(format!("{action} failed in storage backend: {error}"))
59}