1use rupg_catalog::{ConKind, RelKind};
6use rupg_common::{Error, Result, SqlState};
7use rupg_pgcatalog::builtin::{self, Named};
8use rupg_sql::nodes::{
9 InsertStmt, List, LockClauseStrength, Node, OnConflictAction, OnConflictClause, OverridingKind,
10 RangeVar, SelectStmt, SortByDir, SortByNulls,
11};
12use rupg_types::{Value, oid};
13
14use crate::Analyzer;
15use crate::agg::Kind;
16use crate::coerce::{AtOpt, Context};
17use crate::expr::{BoolOp, CastForm, Expr, ExprKind, FieldStore, Func, FuncForm, Var};
18use crate::from::{Column, FromItem, Relation, TABLE_OID_ATTNUM};
19use crate::merge::Merge;
20use crate::modify::{carried_targets, column_var, set_columns};
21use crate::perm::{ACL_DELETE, ACL_INSERT, ACL_SELECT, ACL_UPDATE};
22use crate::select::{Query, Target};
23use crate::typename::place;
24use crate::types;
25
26#[derive(Clone, Copy, Debug, PartialEq, Eq)]
28pub enum WriteKind {
29 Insert,
30 Update,
31 Delete,
32 Merge,
33}
34
35impl WriteKind {
36 pub fn name(self) -> &'static str {
38 match self {
39 WriteKind::Insert => "INSERT",
40 WriteKind::Update => "UPDATE",
41 WriteKind::Delete => "DELETE",
42 WriteKind::Merge => "MERGE",
43 }
44 }
45}
46
47#[derive(Clone, Debug, PartialEq)]
51pub struct Write {
52 pub kind: WriteKind,
53 pub table: u32,
55 pub name: String,
57 pub alias: Option<String>,
59 pub width: usize,
61 pub checks: Vec<String>,
63 pub unique: Vec<Unique>,
65 pub returning: Option<Box<Query>>,
67 pub foreign: Vec<Foreign>,
69 pub on_conflict: Option<OnConflict>,
71 pub merge: Option<Merge>,
73 pub recheck: Option<Box<Query>>,
75 pub updated: Vec<i16>,
77 pub instead: bool,
79 pub inherit: bool,
81 pub view_check: Option<ViewCheck>,
83 pub views: usize,
85}
86
87impl Write {
88 #[must_use]
90 pub fn keeps_written(&self) -> bool {
91 self.returning.is_some() || self.view_check.is_some()
92 }
93}
94
95#[derive(Clone, Debug, PartialEq)]
97pub struct ViewCheck {
98 pub query: Box<Query>,
100 pub views: Vec<String>,
102}
103
104#[derive(Clone, Debug, PartialEq)]
106pub struct OnConflict {
107 pub arbiters: Vec<usize>,
109 pub all: bool,
111 pub update: Option<Box<Query>>,
113 pub select: Option<LockClauseStrength>,
115 pub carried: usize,
117 pub foreign: Vec<Foreign>,
119}
120
121impl OnConflict {
122 #[must_use]
124 pub fn locks(&self) -> bool {
125 self.select.is_some_and(|strength| strength != LockClauseStrength::LCS_NONE)
126 }
127
128 #[must_use]
130 pub fn resolution(&self) -> &'static str {
131 match self.select {
132 Some(LockClauseStrength::LCS_NONE) => "SELECT",
133 Some(LockClauseStrength::LCS_FORKEYSHARE) => "SELECT FOR KEY SHARE",
134 Some(LockClauseStrength::LCS_FORSHARE) => "SELECT FOR SHARE",
135 Some(LockClauseStrength::LCS_FORNOKEYUPDATE) => "SELECT FOR NO KEY UPDATE",
136 Some(_) => "SELECT FOR UPDATE",
137 None if self.update.is_some() => "UPDATE",
138 None => "NOTHING",
139 }
140 }
141}
142
143#[derive(Clone, Copy, Debug, PartialEq, Eq)]
145pub enum Action {
146 NoAction,
148 Restrict,
150 Cascade,
152 SetNull,
154 SetDefault,
156}
157
158#[derive(Clone, Debug, PartialEq)]
160pub struct Foreign {
161 pub name: String,
163 pub referencing: bool,
165 pub action: Action,
167 pub query: String,
169 pub full: bool,
171 pub other: u32,
173 pub other_name: String,
175 pub columns: Vec<usize>,
177 pub names: Vec<String>,
179 pub other_columns: Vec<usize>,
181 pub types: Vec<u32>,
183 pub referencing_types: Vec<u32>,
185 pub constraint: u32,
187 pub deferrable: bool,
189 pub deferred: bool,
191 pub cloned: bool,
193}
194
195#[derive(Clone, Debug, PartialEq)]
197pub struct Unique {
198 pub oid: u32,
200 pub name: String,
202 pub columns: Vec<usize>,
204 pub types: Vec<u32>,
206 pub shown: String,
208 pub nulls_not_distinct: bool,
210 pub derived: Option<Box<Derived>>,
212 pub deferrable: Option<Deferrable>,
214}
215
216#[derive(Clone, Copy, Debug, PartialEq, Eq)]
218pub struct Deferrable {
219 pub constraint: u32,
221 pub deferred: bool,
223}
224
225#[derive(Clone, Debug, PartialEq)]
227pub struct Derived {
228 pub table: u32,
230 pub types: Vec<u32>,
232 pub exprs: Vec<Expr>,
234 pub predicate: Vec<Expr>,
236}
237
238fn quote_one(name: &str) -> String {
240 format!("\"{}\"", name.replace('"', "\"\""))
241}
242
243fn action_query(
245 (action, kind): (Action, WriteKind),
246 (table, only): (&str, bool),
247 names: &[&str],
248 foreign: &Foreign,
249) -> String {
250 let columns: Vec<String> = names.iter().map(|name| quote_one(name)).collect();
251 let only = if only { "ONLY " } else { "" };
253 let mut query = match (action, kind) {
254 (Action::Cascade, WriteKind::Delete) => format!("DELETE FROM {only}{table}"),
255 (Action::Cascade, _) => {
256 let set: Vec<String> =
257 columns.iter().enumerate().map(|(at, c)| format!(" {c} = ${}", at + 1)).collect();
258 format!("UPDATE {only}{table} SET{}", set.join(","))
259 }
260 _ => {
261 let value = if action == Action::SetNull { "NULL" } else { "DEFAULT" };
262 let set: Vec<String> = columns.iter().map(|c| format!(" {c} = {value}")).collect();
263 format!("UPDATE {only}{table} SET{}", set.join(","))
264 }
265 };
266 let first =
268 if action == Action::Cascade && kind == WriteKind::Update { names.len() } else { 0 };
269 for (at, column) in columns.iter().enumerate() {
270 let separator = if at == 0 { "WHERE" } else { "AND" };
271 let (pk, fk) = (foreign.types[at], foreign.referencing_types[at]);
272 let (left, right) = operator_types(pk, fk);
273 query.push_str(&format!(" {separator} ${}", first + at + 1));
274 if left != pk {
275 query.push_str(&cast_to(left));
276 }
277 query.push_str(&format!(" OPERATOR(pg_catalog.=) {column}"));
278 if right != fk {
279 query.push_str(&cast_to(right));
280 }
281 }
282 query
283}
284
285fn operator_types(pk: u32, fk: u32) -> (u32, u32) {
287 let class = |ty: u32| match types::base(ty) {
288 oid::VARCHAR => oid::TEXT,
289 ty => ty,
290 };
291 let family = |ty: u32| match ty {
292 oid::INT2 | oid::INT4 | oid::INT8 => 1,
293 oid::FLOAT4 | oid::FLOAT8 => 2,
294 oid::DATE | oid::TIMESTAMP | oid::TIMESTAMPTZ => 3,
295 oid::TEXT | oid::NAME => 4,
296 _ => 0,
297 };
298 let (left, other) = (class(pk), class(fk));
299 let right = if other == left || (family(left) != 0 && family(left) == family(other)) {
300 other
301 } else {
302 left
303 };
304 (left, right)
305}
306
307fn cast_to(ty: u32) -> String {
309 let name = builtin::type_by_oid(ty).map_or("", |row| row.name);
310 format!("::pg_catalog.{}", crate::ddl::quote_identifier(name))
311}
312
313pub(crate) enum Item {
315 Expr(Expr),
316 Default(Option<usize>),
317}
318
319impl Item {
320 fn place(&self) -> Option<usize> {
321 match self {
322 Item::Expr(expr) => expr.place(),
323 Item::Default(at) => *at,
324 }
325 }
326}
327
328pub(crate) type Generated = (usize, Expr, u8);
330
331pub(crate) type Given = (usize, Option<usize>, List);
333
334pub(crate) const INSTEAD_ROW: i16 = rupg_catalog::TRIGGER_ROW | rupg_catalog::TRIGGER_INSTEAD;
336
337pub(crate) fn not_yet(what: &str) -> Error {
339 Error::new(SqlState::FEATURE_NOT_SUPPORTED, format!("{what} is not supported yet"))
340}
341
342fn first_place(items: &[Item]) -> Option<usize> {
344 items.iter().find_map(Item::place)
345}
346
347impl Analyzer<'_> {
348 pub(crate) fn insert(&mut self, s: &InsertStmt) -> Result<Query> {
350 let inverted = std::mem::take(&mut self.rule.inverted);
351 self.write_with(s.withClause.as_deref())?;
352 let rv = s.relation.as_deref().ok_or_else(|| Error::internal("an INSERT with no table"))?;
353 let (table, name, columns) = self.target_table(rv, WriteKind::Insert)?;
354 let rows = std::mem::take(&mut self.rule.rows);
355 if self.auto_view.is_some() && !inverted.is_empty() {
356 return Err(not_yet("a conditional rule DO INSTEAD of an updatable view"));
357 }
358 let given = match self.auto_view_targets(&s.cols, columns.len())? {
359 Some(given) => given,
360 None => self.insert_targets(&s.cols, &name, &columns)?,
361 };
362 let explicit = !s.cols.is_empty();
363 let select = match &s.selectStmt {
364 None => None,
365 Some(Node::SelectStmt(select)) => Some(&**select),
366 Some(_) => return Err(Error::internal("an INSERT source that is not SELECT")),
367 };
368 if select.is_some() {
370 self.mark_inserted(&given);
371 }
372 let mut query = match select {
373 None => {
374 let row = self.full_row(table, &columns, &given, Vec::new())?;
375 row_query(&columns, row)
376 }
377 Some(select) if general_select(select) => {
378 self.insert_select(select, table, &columns, &given, explicit, s.r#override)?
379 }
380 Some(select) if select.valuesLists.len() > 1 => {
381 self.insert_values(select, table, &columns, &given, explicit, s.r#override)?
382 }
383 Some(select) => {
384 let Some(Some(Node::List(list))) = select.valuesLists.first() else {
385 return Err(Error::internal("a VALUES row that is not a list"));
386 };
387 let items = self.value_items(list, Kind::ValuesSingle)?;
388 let exprs =
389 self.insert_row(items, table, &columns, &given, explicit, s.r#override)?;
390 let row = self.full_row(table, &columns, &given, exprs)?;
391 row_query(&columns, row)
392 }
393 };
394 if rows {
395 let generated = self.generated_columns(table)?;
397 let mut query = with_checks(&name, &columns, query, Vec::new(), &generated, &[]);
398 self.end_write_with(&mut query, s.withClause.as_deref())?;
399 self.rule.columns = columns;
400 return Ok(query);
401 }
402 if !inverted.is_empty() {
403 let generated = self.generated_columns(table)?;
404 let mut rows = with_checks(&name, &columns, query, Vec::new(), &[], &[]);
405 let new = crate::rules::relation_row(&columns, 0, 0);
406 let new = crate::rules::with_generated(new, &generated);
407 let new = crate::rules::named_row(&columns, new);
408 let quals = self.inverted_quals(&inverted, None, Some(new))?;
409 rows.filter = crate::rules::and_filter(rows.filter.take(), quals);
410 query = rows;
411 }
412 let checks = if self.is_partitioned(table) { Vec::new() } else { self.checks(table)? };
414 let names = checks.iter().map(|(n, _)| n.clone()).collect();
415 let conflict_set = s
416 .onConflictClause
417 .as_deref()
418 .filter(|c| matches!(c.action, OnConflictAction::ONCONFLICT_UPDATE))
419 .map(|c| &c.targetList);
420 let renamed = conflict_set.and_then(|list| self.auto_view_set(rv, list, &columns));
422 let conflict_set = renamed.as_ref().map(|(list, _, _)| list).or(conflict_set);
423 let generated = self.generated_columns(table)?;
424 let mut recheck =
425 self.recheck(table, WriteKind::Insert, &name, &columns, &checks, &generated);
426 if recheck.is_none() && conflict_set.is_some() {
427 recheck = self.recheck(table, WriteKind::Update, &name, &columns, &checks, &generated);
429 }
430 let updated = conflict_set.map_or_else(Vec::new, |list| set_columns(list, &columns));
431 let locks = s.onConflictClause.as_deref().is_some_and(|c| {
433 c.action == OnConflictAction::ONCONFLICT_SELECT
434 && c.lockStrength != LockClauseStrength::LCS_NONE
435 });
436 if conflict_set.is_some() || locks {
437 self.mark_updated(&updated);
438 }
439 let updated = crate::modify::with_extra_updated(updated, &generated);
440 if !checks.is_empty() || !generated.is_empty() {
441 query = with_checks(&name, &columns, query, checks, &generated, &[]);
442 }
443 let width = columns.len();
444 let unique = self.unique_keys(table, &columns)?;
445 let foreign = self.foreign_keys(table, WriteKind::Insert, &columns)?;
446 let (mut on_conflict, mut returning) = (None, None);
447 if s.onConflictClause.is_some() || s.returningClause.is_some() {
448 let outer = std::mem::take(&mut self.scope);
449 self.scope.ctes.clone_from(&outer.ctes);
451 let result = self.insert_clauses(s, rv, table, &name, &columns, &unique);
452 self.scope = outer;
453 (on_conflict, returning) = result?;
454 }
455 query.write = Some(Write {
456 kind: WriteKind::Insert,
457 table,
458 name,
459 alias: rv.alias.as_ref().and_then(|a| a.aliasname.as_ref()).map(ToString::to_string),
460 width,
461 checks: names,
462 unique,
463 returning,
464 foreign,
465 on_conflict,
466 merge: None,
467 recheck,
468 updated,
469 instead: self.is_view(table),
470 inherit: false,
471 view_check: None,
472 views: 0,
473 });
474 self.end_write_with(&mut query, s.withClause.as_deref())?;
475 Ok(query)
476 }
477
478 fn insert_clauses(
480 &mut self,
481 s: &InsertStmt,
482 rv: &RangeVar,
483 table: u32,
484 name: &str,
485 columns: &[Column],
486 unique: &[Unique],
487 ) -> Result<(Option<OnConflict>, Option<Box<Query>>)> {
488 if let Some(clause) = s.onConflictClause.as_deref()
489 && clause.action == OnConflictAction::ONCONFLICT_SELECT
490 && s.returningClause.is_none()
491 {
492 return Err(Error::new(
493 SqlState::SYNTAX_ERROR,
494 "ON CONFLICT DO SELECT requires a RETURNING clause",
495 )
496 .at_opt(place(clause.location)));
497 }
498 self.target_from(rv, &[])?;
499 let (mut on_conflict, inference) = match s.onConflictClause.as_deref() {
500 None => (None, Inference::All),
501 Some(clause) => {
502 let (on_conflict, inference) =
503 self.on_conflict(clause, rv, table, name, columns)?;
504 (Some(on_conflict), inference)
505 }
506 };
507 let update = on_conflict.as_ref().is_some_and(|c| c.update.is_some());
509 let kind = if update { WriteKind::Update } else { WriteKind::Insert };
510 let (returning, carried) = match s.returningClause.as_deref() {
511 None => (None, Vec::new()),
512 Some(clause) => {
513 let (query, carried) = self.returning(clause, kind)?;
514 (Some(Box::new(query)), carried)
515 }
516 };
517 if let Some(conflict) = &mut on_conflict
518 && let Some(mut query) = conflict.update.take()
519 {
520 let tail: Vec<Column> = carried
521 .iter()
522 .map(|expr| Column {
523 name: String::new(),
524 ty: expr.ty,
525 typmod: expr.typmod,
526 not_null: false,
527 })
528 .collect();
529 conflict.carried = carried.len();
530 query.targets.extend(carried_targets(carried));
531 let write = conflict.select.is_none() && !self.is_partitioned(table);
533 let checks = if write { self.checks(table)? } else { Vec::new() };
534 let generated =
535 if conflict.select.is_none() { self.generated_columns(table)? } else { Vec::new() };
536 if !checks.is_empty() || !generated.is_empty() {
537 query = Box::new(with_checks(name, columns, *query, checks, &generated, &tail));
538 }
539 conflict.update = Some(query);
540 }
541 if let Some(conflict) = &mut on_conflict {
543 conflict.all = matches!(inference, Inference::All);
544 conflict.arbiters = arbiters(inference, unique, self.env.catalog())?;
545 }
546 Ok((on_conflict, returning))
547 }
548
549 fn on_conflict(
551 &mut self,
552 clause: &OnConflictClause,
553 rv: &RangeVar,
554 table: u32,
555 name: &str,
556 columns: &[Column],
557 ) -> Result<(OnConflict, Inference)> {
558 let (update, select) = match clause.action {
559 OnConflictAction::ONCONFLICT_NOTHING => (false, None),
560 OnConflictAction::ONCONFLICT_UPDATE => (true, None),
561 _ => (false, Some(clause.lockStrength)),
562 };
563 let inference = self.inference(clause, update || select.is_some(), table, name, columns)?;
564 let mut on_conflict = OnConflict {
565 arbiters: Vec::new(),
566 all: false,
567 update: None,
568 select,
569 carried: 0,
570 foreign: Vec::new(),
571 };
572 if select.is_some() {
573 let excluded = self.add_excluded()?;
575 let filter = self.target_where(clause.whereClause.as_ref());
576 self.hide_last_item();
577 let row = columns.iter().enumerate().map(|(at, c)| column_var(at, c)).collect();
578 let query = Query {
579 relations: self.scope.relations.clone(),
580 from: vec![FromItem::Relation(0), FromItem::Relation(excluded)],
581 targets: targets(columns, row),
582 filter: filter?,
583 ..Query::default()
584 };
585 on_conflict.update = Some(Box::new(query));
586 return Ok((on_conflict, inference));
587 }
588 if !update {
589 return Ok((on_conflict, inference));
590 }
591 let excluded = self.add_excluded()?;
592 let (renamed, error) = match self.auto_view_set(rv, &clause.targetList, columns) {
594 Some((list, unknown, fixed)) => (Some(list), unknown.or(fixed)),
595 None => (None, None),
596 };
597 let list = renamed.as_ref().unwrap_or(&clause.targetList);
598 let row = match error {
599 Some(error) => self.set_items(list).and(Err(error)),
600 None => self.update_row(rv, table, name, columns, list),
601 };
602 let parts = row.and_then(|row| {
603 let filter = self.target_where(clause.whereClause.as_ref())?;
604 Ok((row, filter))
605 });
606 self.hide_last_item();
607 let (row, filter) = parts?;
608 let query = Query {
609 relations: self.scope.relations.clone(),
610 from: vec![FromItem::Relation(0), FromItem::Relation(excluded)],
611 targets: targets(columns, row),
612 filter,
613 ..Query::default()
614 };
615 on_conflict.update = Some(Box::new(query));
616 on_conflict.foreign = self.foreign_keys(table, WriteKind::Update, columns)?;
617 Ok((on_conflict, inference))
618 }
619
620 fn inference(
622 &mut self,
623 clause: &OnConflictClause,
624 update: bool,
625 table: u32,
626 name: &str,
627 columns: &[Column],
628 ) -> Result<Inference> {
629 let Some(infer) = clause.infer.as_deref() else {
630 if update {
631 let what = if clause.action == OnConflictAction::ONCONFLICT_SELECT {
632 "SELECT"
633 } else {
634 "UPDATE"
635 };
636 return Err(Error::new(
637 SqlState::SYNTAX_ERROR,
638 format!(
639 "ON CONFLICT DO {what} requires inference specification or constraint name"
640 ),
641 )
642 .with_hint("For example, ON CONFLICT (column_name).")
643 .at_opt(place(clause.location)));
644 }
645 return Ok(Inference::All);
646 };
647 if let Some(conname) = infer.conname.as_deref() {
648 let (table, name) = self.auto_view_target().unwrap_or((table, name));
650 let constraint = self
651 .env
652 .catalog()
653 .and_then(|catalog| catalog.constraints_of(table).find(|c| c.name == conname));
654 let Some(constraint) = constraint else {
655 return Err(Error::new(
656 SqlState::UNDEFINED_OBJECT,
657 format!("constraint \"{conname}\" for table \"{name}\" does not exist"),
658 ));
659 };
660 let keys = constraint.keys.clone();
662 let index = constraint.index;
663 if let Some(perm) = self.target_perm_mut() {
664 perm.required |= ACL_SELECT;
665 perm.selected.extend(keys);
666 }
667 return Ok(Inference::Constraint(index));
668 }
669 let mut set = Vec::with_capacity(infer.indexElems.len());
670 let mut exprs = Vec::new();
671 let mut exact = Vec::new();
672 for node in &infer.indexElems {
673 let Some(Node::IndexElem(elem)) = node else {
674 return Err(Error::internal("an inference element that is not IndexElem"));
675 };
676 let at = place(elem.location);
677 let not_allowed = |what: &str| {
678 Error::new(
679 SqlState::INVALID_COLUMN_REFERENCE,
680 format!("{what} is not allowed in ON CONFLICT clause"),
681 )
682 .at_opt(at)
683 };
684 if elem.ordering != SortByDir::SORTBY_DEFAULT {
685 return Err(not_allowed("ASC/DESC"));
686 }
687 if elem.nulls_ordering != SortByNulls::SORTBY_NULLS_DEFAULT {
688 return Err(not_allowed("NULLS FIRST/LAST"));
689 }
690 if !elem.opclassopts.is_empty() {
691 return Err(Error::new(
692 SqlState::INVALID_COLUMN_REFERENCE,
693 "operator class options are not allowed in ON CONFLICT clause",
694 )
695 .at_opt(at));
696 }
697 let collation = match elem.collation.is_empty() {
698 true => 0,
699 false => self.collation_oid(&elem.collation, at)?,
700 };
701 let class = match elem.opclass.is_empty() {
702 true => None,
703 false => Some(self.btree_opclass(&elem.opclass)?),
704 };
705 let mut note = |target: Exact| {
706 if collation != 0 || class.is_some() {
707 exact.push(ExactElem { target, collation, class });
708 }
709 };
710 let Some(column) = elem.name.as_deref() else {
711 let expr =
713 self.with_kind(Kind::IndexExpression, |a| a.transform(elem.expr.as_ref()))?;
714 match expr.kind {
715 ExprKind::Var(var) if var.levels_up == 0 && var.attnum > 0 => {
716 note(Exact::Column(var.attnum));
717 set.extend(usize::try_from(var.attnum - 1).ok());
718 }
719 _ => {
720 note(Exact::Expr(exprs.len()));
721 exprs.push(expr);
722 }
723 }
724 continue;
725 };
726 let index = match self.auto_view_column(column) {
728 None => columns.iter().position(|c| c.name == column),
729 Some(Some(expr)) => match expr.kind {
730 ExprKind::Var(var) if var.attnum > 0 => usize::try_from(var.attnum - 1).ok(),
731 _ => {
732 note(Exact::Expr(exprs.len()));
733 exprs.push(expr);
734 continue;
735 }
736 },
737 Some(None) => None,
738 };
739 let Some(index) = index else {
740 return Err(Error::new(
741 SqlState::UNDEFINED_COLUMN,
742 format!("column \"{column}\" does not exist"),
743 )
744 .at_opt(place(infer.location)));
746 };
747 if let Some(perm) = self.target_perm_mut() {
749 perm.required |= ACL_SELECT;
750 perm.selected.insert(i16::try_from(index + 1).unwrap_or(i16::MAX));
751 }
752 note(Exact::Column(i16::try_from(index + 1).unwrap_or(i16::MAX)));
753 set.push(index);
754 }
755 set.sort_unstable();
756 set.dedup();
757 let mut predicate = Vec::new();
758 if let Some(clause) = infer.whereClause.as_ref() {
759 let expr = self.with_kind(Kind::IndexPredicate, |a| a.transform(Some(clause)))?;
760 let expr = self.coerce_to_boolean(expr, "WHERE")?;
761 match expr.kind {
762 ExprKind::Bool(BoolOp::And, parts) => predicate = parts,
763 _ => predicate.push(expr),
764 }
765 }
766 Ok(Inference::Columns { columns: set, exprs, predicate, exact })
767 }
768
769 fn btree_opclass(&self, list: &[Option<Node>]) -> Result<(u32, u32)> {
771 const BTREE: u32 = 403;
772 let parts = crate::typename::names(list);
773 let (schema, name) = self.split_name(&parts, None)?;
774 let catalog = self.env.catalog();
775 let find = |namespace: u32| {
776 let user = catalog.and_then(|c| {
777 c.opclasses()
778 .find(|c| c.method == BTREE && c.namespace == namespace && c.name == name)
779 .map(|c| (c.family, c.intype))
780 });
781 user.or_else(|| {
782 let row = builtin::named(Named::Opclass)
783 .iter()
784 .find(|r| r.method == BTREE && r.namespace == namespace && r.name == name)?;
785 let class = builtin::opclasses().iter().find(|c| c.oid == row.oid)?;
786 Some((class.family, class.intype))
787 })
788 };
789 let found = match schema {
790 Some(namespace) => find(namespace),
791 None => self.path.iter().find_map(|&namespace| find(namespace)),
792 };
793 found.ok_or_else(|| {
794 Error::new(
795 SqlState::UNDEFINED_OBJECT,
796 format!(
797 "operator class \"{}\" does not exist for access method \"btree\"",
798 parts.join(".")
799 ),
800 )
801 })
802 }
803
804 pub(crate) fn target_table(
806 &mut self,
807 rv: &RangeVar,
808 kind: WriteKind,
809 ) -> Result<(u32, String, Vec<Column>)> {
810 let what = match kind {
811 WriteKind::Insert => "INSERT into",
812 WriteKind::Update => "UPDATE of",
813 WriteKind::Delete => "DELETE from",
814 WriteKind::Merge => "MERGE into",
815 };
816 let at = place(rv.location);
817 let name = rv.relname.as_deref().unwrap_or_default().to_string();
818 self.check_target(rv)?;
819 let Some(oid) = self.lookup_relation(rv)? else {
820 let shown = match &rv.schemaname {
821 Some(schema) => format!("{schema}.{name}"),
822 None => name.clone(),
823 };
824 return Err(Error::new(
825 SqlState::UNDEFINED_TABLE,
826 format!("relation \"{shown}\" does not exist"),
827 )
828 .at_opt(at));
829 };
830 let rel = self.env.catalog().and_then(|c| c.relation(oid));
831 let Some(rel) = rel else {
832 return Err(not_yet(&format!("{what} a system catalog")));
833 };
834 match rel.kind {
835 RelKind::Table => {}
836 RelKind::Sequence => {
837 return Err(Error::new(
838 SqlState::WRONG_OBJECT_TYPE,
839 format!("cannot change sequence \"{name}\""),
840 ));
841 }
842 RelKind::View
844 if kind != WriteKind::Merge
845 && self.user_triggers(oid, INSTEAD_ROW | trigger_event(kind)) => {}
846 RelKind::View if self.rule.rows => {}
848 RelKind::View => {}
850 RelKind::Partitioned => {}
851 RelKind::MatView if self.env.filling() == oid => {}
852 RelKind::MatView => {
853 return Err(Error::new(
854 SqlState::WRONG_OBJECT_TYPE,
855 format!("cannot change materialized view \"{name}\""),
856 ));
857 }
858 _ => {
859 return Err(Error::new(
860 SqlState::WRONG_OBJECT_TYPE,
861 format!("cannot change relation \"{name}\""),
862 ));
863 }
864 }
865 if let Some(catalog) = self.env.catalog() {
866 let mut rules = catalog.rules().filter(|r| r.relation == oid && crate::rules::fires(r));
867 if kind == WriteKind::Merge {
868 if rules.any(|r| r.event != b'1') {
870 return Err(Error::new(
871 SqlState::FEATURE_NOT_SUPPORTED,
872 format!("cannot execute MERGE on relation \"{name}\""),
873 )
874 .with_detail("MERGE is not supported for relations with rules."));
875 }
876 } else {
877 let code = match kind {
878 WriteKind::Insert => b'3',
879 WriteKind::Update => b'2',
880 _ => b'4',
881 };
882 let done = self.rule.rows || self.rule.defining || self.rule.fired == Some(oid);
884 if !done && rules.any(|r| r.event == code) {
885 return Err(not_yet(&format!("{what} a table with rules")));
886 }
887 }
888 }
889 let columns = write_columns(rel);
890 let name = rel.name.clone();
891 let required = match kind {
892 WriteKind::Insert => ACL_INSERT,
893 WriteKind::Update => ACL_UPDATE,
894 WriteKind::Delete => ACL_DELETE,
895 WriteKind::Merge => 0,
896 };
897 self.target_perm = Some(self.add_perm(oid, required));
898 let auto = rel.kind == RelKind::View
900 && !self.rule.rows
901 && !self.view_has_instead_trigger(oid, kind);
902 if !auto {
903 return Ok((oid, name, columns));
904 }
905 let view = self.auto_view(oid, &name, kind)?;
906 let base = view.base_oid();
907 let rel = self.env.catalog().and_then(|c| c.relation(base));
908 let rel = rel.ok_or_else(|| Error::internal("an updatable view with no base relation"))?;
909 let columns = write_columns(rel);
910 let name = rel.name.clone();
911 self.auto_view = Some(view);
912 Ok((base, name, columns))
913 }
914
915 pub(crate) fn user_triggers(&self, table: u32, bits: i16) -> bool {
917 let Some(catalog) = self.env.catalog() else { return false };
918 catalog.triggers().any(|t| user_trigger(t, table) && t.kind & bits == bits)
919 }
920
921 pub(crate) fn is_view(&self, table: u32) -> bool {
923 crate::ddl::relkind(self.env, table) == b'v'
924 }
925
926 pub(crate) fn inherits_target(&self, kind: WriteKind) -> bool {
928 let Some(target) = self.scope.relations.first() else { return false };
929 matches!(kind, WriteKind::Update | WriteKind::Delete | WriteKind::Merge)
930 && !target.only
931 && crate::ddl::relkind(self.env, target.oid) == b'r'
932 && self.env.catalog().is_some_and(|c| !c.children(target.oid).is_empty())
933 }
934
935 pub(crate) fn is_partitioned(&self, table: u32) -> bool {
937 crate::ddl::relkind(self.env, table) == b'p'
938 }
939
940 pub(crate) fn recheck(
942 &self,
943 table: u32,
944 kind: WriteKind,
945 name: &str,
946 columns: &[Column],
947 checks: &[(String, Expr)],
948 generated: &[Generated],
949 ) -> Option<Box<Query>> {
950 let bits = rupg_catalog::TRIGGER_ROW | rupg_catalog::TRIGGER_BEFORE | trigger_event(kind);
951 if self.is_partitioned(table) || !self.user_triggers(table, bits) {
953 return None;
954 }
955 let mut query =
956 with_checks(name, columns, Query::default(), checks.to_vec(), generated, &[]);
957 let mut relation = Relation::new(0, columns.to_vec(), None, None, None);
959 relation.name = name.to_string();
960 query.relations = vec![relation];
961 Some(Box::new(query))
962 }
963
964 pub(crate) fn foreign_keys(
966 &self,
967 table: u32,
968 kind: WriteKind,
969 columns: &[Column],
970 ) -> Result<Vec<Foreign>> {
971 let Some(catalog) = self.env.catalog() else {
972 return Ok(Vec::new());
973 };
974 let partitioned = catalog.relation(table).is_some_and(|r| r.kind == RelKind::Partitioned);
976 if partitioned && kind != WriteKind::Update {
977 return Ok(Vec::new());
978 }
979 let mut triggers: Vec<_> = catalog
980 .triggers()
981 .filter(|t| t.relation == table && t.fires())
982 .filter_map(|t| {
983 let function = rupg_catalog::foreign_key_function(t.function)?;
984 let event = match function {
985 0 => WriteKind::Insert,
986 f if f % 2 == 1 => WriteKind::Update,
987 _ => WriteKind::Delete,
988 };
989 (event == kind && !(partitioned && function < 2)).then_some((t, function))
990 })
991 .collect();
992 triggers.sort_by(|a, b| a.0.name.cmp(&b.0.name));
993 let mut list = Vec::with_capacity(triggers.len());
994 for (trigger, function) in triggers {
995 let constraint = catalog.constraint(trigger.constraint);
996 let Some((constraint, foreign)) =
997 constraint.and_then(|c| c.foreign.as_ref().map(|f| (c, f)))
998 else {
999 return Err(Error::internal("a trigger of a foreign key with no foreign key"));
1000 };
1001 let action = match function {
1002 2 | 3 => Action::Cascade,
1003 4 | 5 => Action::Restrict,
1004 6 | 7 => Action::SetNull,
1005 8 | 9 => Action::SetDefault,
1006 _ => Action::NoAction,
1007 };
1008 let referencing = function < 2;
1009 let (other, mine, theirs) = if referencing {
1010 (foreign.table, &constraint.keys, &foreign.keys)
1011 } else {
1012 (constraint.relation, &foreign.keys, &constraint.keys)
1013 };
1014 let Some(other_rel) = catalog.relation(other) else {
1015 return Err(Error::internal("a foreign key of a table that does not exist"));
1016 };
1017 let place = |attnum: i16| usize::try_from(attnum - 1).ok();
1018 let mut check = Foreign {
1019 name: constraint.name.clone(),
1020 referencing,
1021 action,
1022 query: String::new(),
1023 full: foreign.match_type == 'f',
1024 other,
1025 other_name: other_rel.name.clone(),
1026 columns: Vec::with_capacity(mine.len()),
1027 names: Vec::with_capacity(mine.len()),
1028 other_columns: Vec::with_capacity(mine.len()),
1029 types: Vec::with_capacity(mine.len()),
1030 referencing_types: Vec::with_capacity(mine.len()),
1031 constraint: constraint.oid,
1032 deferrable: trigger.deferrable,
1033 deferred: trigger.deferred,
1034 cloned: trigger.parent != 0,
1035 };
1036 for (&attnum, &other_attnum) in mine.iter().zip(theirs) {
1037 let column = place(attnum).and_then(|at| columns.get(at).map(|c| (at, c)));
1038 let other_column =
1039 place(other_attnum).and_then(|at| other_rel.columns.get(at).map(|c| (at, c)));
1040 let (Some((at, column)), Some((other_at, other_column))) = (column, other_column)
1041 else {
1042 return Err(Error::internal("a foreign key with a key that is not a column"));
1043 };
1044 check.columns.push(at);
1045 check.names.push(column.name.clone());
1046 check.other_columns.push(other_at);
1047 let (key, referencing_key) = if referencing {
1048 (other_column.ty, column.ty)
1049 } else {
1050 (column.ty, other_column.ty)
1051 };
1052 check.types.push(key);
1053 check.referencing_types.push(referencing_key);
1054 }
1055 if matches!(action, Action::Cascade | Action::SetNull | Action::SetDefault) {
1056 let names: Vec<&str> = check
1057 .other_columns
1058 .iter()
1059 .map(|&at| other_rel.columns[at].name.as_str())
1060 .collect();
1061 let schema = match catalog.schema(other_rel.namespace) {
1062 Some(schema) => schema.name.clone(),
1063 None => builtin::named_by_oid(Named::Namespace, other_rel.namespace)
1064 .map_or_else(String::new, |n| n.name.to_string()),
1065 };
1066 let table = format!("{}.{}", quote_one(&schema), quote_one(&other_rel.name));
1067 let only = other_rel.kind != RelKind::Partitioned;
1068 check.query = action_query((action, kind), (&table, only), &names, &check);
1069 }
1070 list.push(check);
1071 }
1072 Ok(list)
1073 }
1074
1075 pub(crate) fn unique_keys(&self, table: u32, columns: &[Column]) -> Result<Vec<Unique>> {
1077 let Some(catalog) = self.env.catalog() else {
1078 return Ok(Vec::new());
1079 };
1080 let mut indexes: Vec<_> = catalog
1081 .relations()
1082 .filter(|rel| matches!(rel.kind, RelKind::Index | RelKind::PartitionedIndex))
1083 .filter_map(|rel| {
1084 rel.index
1085 .as_ref()
1086 .filter(|info| info.table == table && info.unique && info.ready)
1087 .map(|info| (rel, info))
1088 })
1089 .collect();
1090 indexes.sort_by_key(|(rel, _)| rel.oid);
1091 let mut list = Vec::with_capacity(indexes.len());
1092 for (rel, info) in indexes {
1093 let deferrable = if info.immediate {
1094 None
1095 } else {
1096 let constraint = catalog.constraints_of(table).find(|c| c.index == rel.oid);
1097 constraint.map(|c| Deferrable { constraint: c.oid, deferred: c.deferred })
1098 };
1099 let count = usize::try_from(info.key_count).unwrap_or_default();
1100 let mut key = Unique {
1101 oid: rel.oid,
1102 name: rel.name.clone(),
1103 columns: Vec::with_capacity(count),
1104 types: Vec::with_capacity(count),
1105 shown: String::new(),
1106 nulls_not_distinct: info.nulls_not_distinct,
1107 derived: None,
1108 deferrable,
1109 };
1110 if info.exprs.is_some() || info.predicate.is_some() {
1111 let mut exprs = match &info.exprs {
1112 Some(text) => crate::node::read_list(text)?,
1113 None => Vec::new(),
1114 }
1115 .into_iter();
1116 let mut derived = Derived {
1117 table,
1118 types: columns.iter().map(|c| c.ty).collect(),
1119 exprs: Vec::with_capacity(count),
1120 predicate: match &info.predicate {
1121 Some(text) => match crate::node::read(text)? {
1122 Expr { kind: ExprKind::Bool(BoolOp::And, parts), .. } => parts,
1123 part => vec![part],
1124 },
1125 None => Vec::new(),
1126 },
1127 };
1128 for (at, &attnum) in info.keys.iter().take(count).enumerate() {
1129 let expr = if attnum == 0 {
1130 exprs
1131 .next()
1132 .ok_or_else(|| Error::internal("too few entries in indexprs"))?
1133 } else {
1134 let column = usize::try_from(attnum - 1).ok().and_then(|c| columns.get(c));
1135 let Some(column) = column else {
1136 return Err(Error::internal(
1137 "a unique index with a key that is not a column",
1138 ));
1139 };
1140 let var = Var { relation: 0, attnum, levels_up: 0 };
1141 Expr { typmod: column.typmod, ..Expr::new(ExprKind::Var(var), column.ty) }
1142 };
1143 key.columns.push(at);
1144 key.types.push(expr.ty);
1145 derived.exprs.push(expr);
1146 }
1147 key.derived = Some(Box::new(derived));
1148 list.push(key);
1149 continue;
1150 }
1151 for &attnum in info.keys.iter().take(count) {
1152 let column = usize::try_from(attnum - 1)
1153 .ok()
1154 .and_then(|at| columns.get(at).map(|c| (at, c)));
1155 let Some((at, column)) = column else {
1156 return Err(Error::internal("a unique index with a key that is not a column"));
1157 };
1158 if !key.shown.is_empty() {
1159 key.shown.push_str(", ");
1160 }
1161 key.shown.push_str(&crate::ddl::quote_identifier(&column.name));
1162 key.columns.push(at);
1163 key.types.push(column.ty);
1164 }
1165 list.push(key);
1166 }
1167 Ok(list)
1168 }
1169
1170 pub(crate) fn insert_targets(
1172 &self,
1173 cols: &List,
1174 name: &str,
1175 columns: &[Column],
1176 ) -> Result<Vec<Given>> {
1177 if cols.is_empty() {
1178 return Ok((0..columns.len())
1179 .filter(|&i| !columns[i].is_dropped())
1180 .map(|i| (i, None, List::new()))
1181 .collect());
1182 }
1183 let mut given: Vec<Given> = Vec::with_capacity(cols.len());
1184 for col in cols {
1185 let Some(Node::ResTarget(rt)) = col else {
1186 return Err(Error::internal("an INSERT column that is not ResTarget"));
1187 };
1188 let at = place(rt.location);
1189 let col_name = rt.name.as_deref().unwrap_or_default();
1190 let Some(index) = columns.iter().position(|c| c.name == col_name) else {
1191 return Err(Error::new(
1192 SqlState::UNDEFINED_COLUMN,
1193 format!("column \"{col_name}\" of relation \"{name}\" does not exist"),
1194 )
1195 .at_opt(at));
1196 };
1197 let part = !rt.indirection.is_empty();
1199 if given.iter().any(|(i, _, other)| *i == index && (!part || other.is_empty())) {
1200 return Err(Error::new(
1201 SqlState::DUPLICATE_COLUMN,
1202 format!("column \"{col_name}\" specified more than once"),
1203 )
1204 .at_opt(at));
1205 }
1206 given.push((index, at, rt.indirection.clone()));
1207 }
1208 Ok(given)
1209 }
1210
1211 pub(crate) fn value_items(&mut self, list: &List, kind: Kind) -> Result<Vec<Item>> {
1213 let mut items = Vec::with_capacity(list.len());
1214 for node in list {
1215 if let Some(Node::SetToDefault(d)) = node {
1216 items.push(Item::Default(place(d.location)));
1217 continue;
1218 }
1219 items.push(Item::Expr(self.with_kind(kind, |a| a.transform(node.as_ref()))?));
1220 }
1221 Ok(items)
1222 }
1223
1224 pub(crate) fn insert_row(
1226 &mut self,
1227 items: Vec<Item>,
1228 table: u32,
1229 columns: &[Column],
1230 given: &[Given],
1231 explicit: bool,
1232 overriding: OverridingKind,
1233 ) -> Result<Vec<Expr>> {
1234 if items.len() > given.len() {
1235 return Err(Error::new(
1236 SqlState::SYNTAX_ERROR,
1237 "INSERT has more expressions than target columns",
1238 )
1239 .at_opt(items[given.len()].place()));
1240 }
1241 if explicit && items.len() < given.len() {
1242 let mut error = Error::new(
1243 SqlState::SYNTAX_ERROR,
1244 "INSERT has more target columns than expressions",
1245 );
1246 if let [Item::Expr(expr)] = items.as_slice()
1247 && let ExprKind::Row(fields, _) = &expr.kind
1248 && fields.len() == given.len()
1249 {
1250 error = error.with_hint("The insertion source is a row expression containing the same number of columns expected by the INSERT. Did you accidentally use extra parentheses?");
1251 }
1252 return Err(error.at_opt(given[items.len()].1));
1253 }
1254 self.auto_view_given(items.len())?;
1255 let mut row = Vec::with_capacity(items.len());
1256 for (item, (index, at, indirection)) in items.into_iter().zip(given) {
1257 let (index, at) = (*index, *at);
1258 let column = &columns[index];
1259 let identity = self.identity(table, index);
1261 let item = match item {
1262 Item::Expr(_)
1263 if identity != 0 && overriding == OverridingKind::OVERRIDING_USER_VALUE =>
1264 {
1265 Item::Default(None)
1266 }
1267 Item::Expr(_)
1268 if identity == b'a' && overriding == OverridingKind::OVERRIDING_NOT_SET =>
1269 {
1270 return Err(Error::new(
1271 SqlState::GENERATED_ALWAYS,
1272 format!(
1273 "cannot insert a non-DEFAULT value into column \"{}\"",
1274 column.name
1275 ),
1276 )
1277 .with_detail(format!(
1278 "Column \"{}\" is an identity column defined as GENERATED ALWAYS.",
1279 column.name
1280 ))
1281 .with_hint("Use OVERRIDING SYSTEM VALUE to override."));
1282 }
1283 Item::Expr(_) if self.generated(table, index) != 0 => {
1284 return Err(Error::new(
1285 SqlState::GENERATED_ALWAYS,
1286 format!(
1287 "cannot insert a non-DEFAULT value into column \"{}\"",
1288 column.name
1289 ),
1290 )
1291 .with_detail(format!("Column \"{}\" is a generated column.", column.name)));
1292 }
1293 item => item,
1294 };
1295 row.push(match item {
1296 Item::Default(_) if !indirection.is_empty() => {
1297 return Err(default_part(indirection, at));
1298 }
1299 Item::Default(_) => self.column_default(table, index, column)?,
1300 Item::Expr(expr) if indirection.is_empty() => self.assign(expr, column)?,
1301 Item::Expr(expr) => self.assign_part(column, indirection, at, expr, None)?,
1302 });
1303 }
1304 Ok(row)
1305 }
1306
1307 pub(crate) fn assign_part(
1313 &mut self,
1314 column: &Column,
1315 indirection: &List,
1316 at: Option<usize>,
1317 expr: Expr,
1318 old: Option<Expr>,
1319 ) -> Result<Expr> {
1320 let base = old.unwrap_or_else(|| {
1321 let mut null = Expr::new(ExprKind::Const(Value::Null), column.ty);
1322 null.typmod = column.typmod;
1323 null
1324 });
1325 let target = (base, &column.name[..], (column.ty, column.typmod));
1326 self.assignment_indirection(target, indirection, expr, Context::Assignment, at)
1327 }
1328
1329 pub(crate) fn identity(&self, table: u32, index: usize) -> u8 {
1331 let catalog = self.env.catalog();
1332 let relation = catalog.and_then(|c| c.relation(table));
1333 relation.and_then(|r| r.columns.get(index)).map_or(0, |c| c.identity)
1334 }
1335
1336 pub(crate) fn generated(&self, table: u32, index: usize) -> u8 {
1338 let catalog = self.env.catalog();
1339 let relation = catalog.and_then(|c| c.relation(table));
1340 relation.and_then(|r| r.columns.get(index)).map_or(0, |c| c.generated)
1341 }
1342
1343 pub(crate) fn generated_columns(&mut self, table: u32) -> Result<Vec<Generated>> {
1345 let Some(catalog) = self.env.catalog() else { return Ok(Vec::new()) };
1346 let Some(relation) = catalog.relation(table) else { return Ok(Vec::new()) };
1347 if relation.kind == RelKind::Partitioned {
1348 return Ok(Vec::new());
1349 }
1350 let mut out = Vec::new();
1351 for (index, column) in relation.columns.iter().enumerate() {
1352 if column.generated == 0 || column.dropped {
1353 continue;
1354 }
1355 let attnum = i16::try_from(index + 1).unwrap_or(i16::MAX);
1356 if let Some(default) = catalog.default_of(table, attnum) {
1357 let mut expr: Expr = crate::node::read(&default.expr)?;
1358 expr.each_mut(0, &mut |e, depth| {
1360 let ExprKind::Var(var) = e.kind else { return false };
1361 if var.levels_up != depth || var.attnum != TABLE_OID_ATTNUM {
1362 return false;
1363 }
1364 *e = Expr::constant(Value::Oid(table), oid::OID, -1, None);
1365 true
1366 });
1367 self.note_funcs(&expr);
1368 out.push((index, expr, column.generated));
1369 }
1370 }
1371 Ok(out)
1372 }
1373
1374 pub(crate) fn assign(&mut self, expr: Expr, column: &Column) -> Result<Expr> {
1376 let (from, at) = (expr.ty, expr.place());
1377 self.coerce_to_target(expr, column.ty, column.typmod, Context::Assignment, None)?
1378 .ok_or_else(|| {
1379 Error::new(
1380 SqlState::DATATYPE_MISMATCH,
1381 format!(
1382 "column \"{}\" is of type {} but expression is of type {}",
1383 column.name,
1384 types::name(column.ty),
1385 types::name(from)
1386 ),
1387 )
1388 .with_hint("You will need to rewrite or cast the expression.")
1389 .at_opt(at)
1390 })
1391 }
1392
1393 pub(crate) fn column_default(
1395 &mut self,
1396 table: u32,
1397 index: usize,
1398 column: &Column,
1399 ) -> Result<Expr> {
1400 if column.is_dropped() {
1402 return Ok(Expr::new(ExprKind::Const(Value::Null), 0));
1403 }
1404 if self.generated(table, index) != 0 {
1406 if self.auto_view_default(table, index).is_some() {
1408 return Err(Error::new(
1409 SqlState::GENERATED_ALWAYS,
1410 format!("cannot insert a non-DEFAULT value into column \"{}\"", column.name),
1411 )
1412 .with_detail(format!("Column \"{}\" is a generated column.", column.name)));
1413 }
1414 let mut null = Expr::new(ExprKind::Const(Value::Null), column.ty);
1415 null.typmod = column.typmod;
1416 return Ok(null);
1417 }
1418 let attnum = i16::try_from(index + 1).unwrap_or(i16::MAX);
1419 let view_default = self.auto_view_default(table, index);
1421 let sequence = self.env.catalog().and_then(|c| c.root_identity_sequence(table, attnum));
1422 if view_default.is_none()
1423 && self.identity(table, index) != 0
1424 && let Some(sequence) = sequence
1425 {
1426 let mut expr = nextval(sequence)?;
1427 if let ExprKind::Func(func) = &mut expr.kind {
1429 func.args.push(Expr::constant(Value::Bool(true), oid::BOOL, -1, None));
1430 }
1431 return self
1432 .coerce_to_target(expr, column.ty, column.typmod, Context::Assignment, None)?
1433 .ok_or_else(|| {
1434 Error::internal("an identity column of a type that is not an integer")
1435 });
1436 }
1437 let catalog = self.env.catalog();
1438 let (table, attnum) = view_default.unwrap_or((table, attnum));
1439 let text = catalog.and_then(|c| c.default_of(table, attnum)).map(|d| d.expr.clone());
1440 let text = text.or_else(|| {
1441 catalog
1442 .and_then(|c| c.type_by_oid(column.ty))
1443 .and_then(|ty| ty.domain.as_ref())
1444 .and_then(|d| d.default.clone())
1445 });
1446 let Some(text) = text else {
1447 let null = Expr::new(ExprKind::Const(Value::Null), oid::UNKNOWN);
1448 let mut expr = self
1449 .coerce_to_target(null, column.ty, column.typmod, Context::Assignment, None)?
1450 .unwrap_or_else(|| Expr::new(ExprKind::Const(Value::Null), column.ty));
1451 if let ExprKind::Const(_) = expr.kind {
1452 expr.typmod = column.typmod;
1453 }
1454 return Ok(expr);
1455 };
1456 let expr = crate::node::read(&text)?;
1457 self.note_funcs(&expr);
1458 let from = expr.ty;
1459 self.coerce_to_target(expr, column.ty, column.typmod, Context::Assignment, None)?
1460 .ok_or_else(|| {
1461 Error::new(
1462 SqlState::DATATYPE_MISMATCH,
1463 format!(
1464 "column \"{}\" is of type {} but default expression is of type {}",
1465 column.name,
1466 types::name(column.ty),
1467 types::name(from)
1468 ),
1469 )
1470 .with_hint("You will need to rewrite or cast the expression.")
1471 })
1472 }
1473
1474 pub(crate) fn full_row(
1476 &mut self,
1477 table: u32,
1478 columns: &[Column],
1479 given: &[Given],
1480 exprs: Vec<Expr>,
1481 ) -> Result<Vec<Expr>> {
1482 let mut slots: Vec<Option<Expr>> = vec![None; columns.len()];
1483 for (expr, &(index, _, _)) in exprs.into_iter().zip(given) {
1484 slots[index] = Some(match slots[index].take() {
1486 Some(prior) => merge_parts(prior, expr, &columns[index].name)?,
1487 None => expr,
1488 });
1489 }
1490 let mut row = Vec::with_capacity(columns.len());
1491 for (index, slot) in slots.into_iter().enumerate() {
1492 row.push(match slot {
1493 Some(expr) => expr,
1494 None => self.column_default(table, index, &columns[index])?,
1495 });
1496 }
1497 Ok(row)
1498 }
1499
1500 fn insert_select(
1502 &mut self,
1503 select: &SelectStmt,
1504 table: u32,
1505 columns: &[Column],
1506 given: &[Given],
1507 explicit: bool,
1508 overriding: OverridingKind,
1509 ) -> Result<Query> {
1510 self.keep_unknowns = true;
1511 let sub = self.sub_select(select, false);
1512 self.keep_unknowns = false;
1513 let sub = sub?;
1514 let shown: Vec<&Target> = sub.targets.iter().filter(|t| !t.junk).collect();
1515 let items: Vec<Item> = shown
1516 .iter()
1517 .enumerate()
1518 .map(|(i, t)| {
1519 let unknown = t.expr.ty == oid::UNKNOWN
1520 && matches!(t.expr.kind, ExprKind::Const(_) | ExprKind::Param(_));
1521 if unknown {
1522 return Item::Expr(t.expr.clone());
1523 }
1524 let attnum = i16::try_from(i + 1).unwrap_or(i16::MAX);
1525 let var = Var { relation: 0, attnum, levels_up: 0 };
1526 let mut expr = Expr::new(ExprKind::Var(var), t.expr.ty);
1527 expr.typmod = t.expr.typmod;
1528 expr.location = t.expr.place();
1529 Item::Expr(expr)
1530 })
1531 .collect();
1532 let sub_columns: Vec<Column> = shown
1533 .iter()
1534 .map(|t| Column {
1535 name: t.name.clone(),
1536 ty: t.expr.ty,
1537 typmod: t.expr.typmod,
1538 not_null: false,
1539 })
1540 .collect();
1541 let exprs = self.insert_row(items, table, columns, given, explicit, overriding)?;
1542 let row = self.full_row(table, columns, given, exprs)?;
1543 let mut relation = Relation::new(0, sub_columns, Some(Box::new(sub)), None, None);
1544 relation.name = "*SELECT*".to_string();
1545 Ok(Query {
1546 relations: vec![relation],
1547 from: vec![FromItem::Relation(0)],
1548 targets: targets(columns, row),
1549 ..Query::default()
1550 })
1551 }
1552
1553 fn insert_values(
1555 &mut self,
1556 select: &SelectStmt,
1557 table: u32,
1558 columns: &[Column],
1559 given: &[Given],
1560 explicit: bool,
1561 overriding: OverridingKind,
1562 ) -> Result<Query> {
1563 let mut rows: Vec<Vec<Expr>> = Vec::with_capacity(select.valuesLists.len());
1564 let mut length = None;
1565 for list in &select.valuesLists {
1566 let Some(Node::List(list)) = list else {
1567 return Err(Error::internal("a VALUES row that is not a list"));
1568 };
1569 let items = self.value_items(list, Kind::Values)?;
1570 match length {
1571 None => length = Some(items.len()),
1572 Some(n) if n != items.len() => {
1573 return Err(Error::new(
1574 SqlState::SYNTAX_ERROR,
1575 "VALUES lists must all be the same length",
1576 )
1577 .at_opt(first_place(&items)));
1578 }
1579 Some(_) => {}
1580 }
1581 let row = self.insert_row(items, table, columns, given, explicit, overriding)?;
1582 let row = row
1584 .into_iter()
1585 .zip(given)
1586 .map(
1587 |(expr, (_, _, indirection))| {
1588 if indirection.is_empty() { expr } else { strip_part(expr) }
1589 },
1590 )
1591 .collect();
1592 rows.push(row);
1593 }
1594 let width = rows.first().map_or(0, Vec::len);
1595 let value_columns: Vec<Column> = given
1596 .iter()
1597 .take(width)
1598 .enumerate()
1599 .map(|(i, (index, _, indirection))| {
1600 let (ty, typmod) = match rows.first().and_then(|row| row.get(i)) {
1601 Some(expr) if !indirection.is_empty() => (expr.ty, expr.typmod),
1602 _ => (columns[*index].ty, columns[*index].typmod),
1603 };
1604 Column { name: format!("column{}", i + 1), ty, typmod, not_null: false }
1605 })
1606 .collect();
1607 let mut exprs = Vec::with_capacity(value_columns.len());
1608 for (i, (c, (index, at, indirection))) in value_columns.iter().zip(given).enumerate() {
1609 let attnum = i16::try_from(i + 1).unwrap_or(i16::MAX);
1610 let mut expr =
1611 Expr::new(ExprKind::Var(Var { relation: 0, attnum, levels_up: 0 }), c.ty);
1612 expr.typmod = c.typmod;
1613 if !indirection.is_empty() {
1614 expr = self.assign_part(&columns[*index], indirection, *at, expr, None)?;
1615 }
1616 exprs.push(expr);
1617 }
1618 let row = self.full_row(table, columns, given, exprs)?;
1619 let mut relation = Relation::new(0, value_columns, None, None, Some(rows));
1620 relation.name = "*VALUES*".to_string();
1621 Ok(Query {
1622 relations: vec![relation],
1623 from: vec![FromItem::Relation(0)],
1624 targets: targets(columns, row),
1625 ..Query::default()
1626 })
1627 }
1628
1629 pub(crate) fn checks(&mut self, table: u32) -> Result<Vec<(String, Expr)>> {
1631 let Some(catalog) = self.env.catalog() else { return Ok(Vec::new()) };
1632 let mut checks: Vec<(String, &str)> = catalog
1633 .constraints_of(table)
1634 .filter(|c| c.kind == ConKind::Check && c.enforced)
1635 .map(|c| (c.name.clone(), c.expr.as_deref().unwrap_or_default()))
1636 .collect();
1637 checks.sort_by(|a, b| a.0.cmp(&b.0));
1638 let checks: Vec<(String, Expr)> = checks
1639 .into_iter()
1640 .map(|(name, text)| Ok((name, crate::node::read(text)?)))
1641 .collect::<Result<_>>()?;
1642 for (_, expr) in &checks {
1643 self.note_funcs(expr);
1644 }
1645 Ok(checks)
1646 }
1647}
1648
1649pub(crate) fn nextval(sequence: u32) -> Result<Expr> {
1651 let proc = builtin::procs_named("nextval")
1652 .next()
1653 .ok_or_else(|| Error::internal("function nextval does not exist"))?;
1654 let arg = Expr::constant(Value::Oid(sequence), oid::REGCLASS, -1, None);
1655 let func = Func {
1656 oid: proc.oid,
1657 args: vec![arg],
1658 form: FuncForm::Call,
1659 variadic: false,
1660 retset: false,
1661 };
1662 Ok(Expr::new(ExprKind::Func(func), proc.rettype))
1663}
1664
1665fn general_select(s: &SelectStmt) -> bool {
1667 s.valuesLists.is_empty()
1668 || !s.sortClause.is_empty()
1669 || s.limitOffset.is_some()
1670 || s.limitCount.is_some()
1671 || !s.lockingClause.is_empty()
1672 || s.withClause.is_some()
1673}
1674
1675pub(crate) fn targets(columns: &[Column], row: Vec<Expr>) -> Vec<Target> {
1677 columns
1678 .iter()
1679 .zip(row)
1680 .map(|(c, expr)| Target { name: c.name.clone(), expr, origin: None, junk: false })
1681 .collect()
1682}
1683
1684fn row_query(columns: &[Column], row: Vec<Expr>) -> Query {
1686 Query { targets: targets(columns, row), ..Query::default() }
1687}
1688
1689enum Inference {
1691 All,
1693 Columns { columns: Vec<usize>, exprs: Vec<Expr>, predicate: Vec<Expr>, exact: Vec<ExactElem> },
1695 Constraint(u32),
1697}
1698
1699struct ExactElem {
1701 target: Exact,
1702 collation: u32,
1704 class: Option<(u32, u32)>,
1706}
1707
1708#[derive(Clone, Copy)]
1710enum Exact {
1711 Column(i16),
1713 Expr(usize),
1715}
1716
1717fn exact_match(
1719 elem: &ExactElem,
1720 exprs: &[Expr],
1721 key: &Unique,
1722 catalog: Option<&rupg_catalog::Catalog>,
1723) -> bool {
1724 let info = catalog.and_then(|c| c.relation(key.oid)).and_then(|rel| rel.index.as_ref());
1725 let Some(info) = info else { return false };
1726 let count = usize::try_from(info.key_count).unwrap_or_default();
1727 for (natt, &attno) in info.keys.iter().take(count).enumerate() {
1728 if let Some(class) = elem.class {
1729 let oid = info.classes.get(natt).copied().unwrap_or_default();
1730 let user = catalog.and_then(|c| c.opclass(oid)).map(|c| (c.family, c.intype));
1731 let found = user.or_else(|| {
1732 builtin::opclasses().iter().find(|c| c.oid == oid).map(|c| (c.family, c.intype))
1733 });
1734 if found != Some(class) {
1735 continue;
1736 }
1737 }
1738 if elem.collation != 0 && info.collations.get(natt) != Some(&elem.collation) {
1739 continue;
1740 }
1741 match elem.target {
1742 Exact::Column(attnum) if attno == attnum => return true,
1743 Exact::Expr(at) if attno == 0 => {
1744 let indexed = key.derived.as_ref().and_then(|d| d.exprs.get(natt));
1745 if indexed.is_some_and(|i| exprs.get(at).is_some_and(|e| e.same(i))) {
1746 return true;
1747 }
1748 }
1749 _ => {}
1750 }
1751 }
1752 false
1753}
1754
1755fn arbiters(
1757 inference: Inference,
1758 unique: &[Unique],
1759 catalog: Option<&rupg_catalog::Catalog>,
1760) -> Result<Vec<usize>> {
1761 let places: Vec<usize> = match inference {
1762 Inference::All => return Ok((0..unique.len()).collect()),
1763 Inference::Constraint(0) => {
1764 return Err(Error::new(
1765 SqlState::WRONG_OBJECT_TYPE,
1766 "constraint in ON CONFLICT clause has no associated index",
1767 ));
1768 }
1769 Inference::Constraint(index) => {
1770 let places: Vec<usize> = unique
1771 .iter()
1772 .enumerate()
1773 .filter(|(_, key)| key.oid == index)
1774 .map(|(at, _)| at)
1775 .collect();
1776 if places.is_empty() {
1777 return Err(not_yet("an exclusion constraint in ON CONFLICT"));
1778 }
1779 return Ok(places);
1780 }
1781 Inference::Columns { columns: set, exprs, predicate, exact } => unique
1782 .iter()
1783 .enumerate()
1784 .filter(|(_, key)| exact.iter().all(|e| exact_match(e, &exprs, key, catalog)))
1785 .filter(|(_, key)| {
1786 let Some(derived) = &key.derived else {
1787 let mut key = key.columns.clone();
1788 key.sort_unstable();
1789 key.dedup();
1790 return key == set && exprs.is_empty();
1791 };
1792 let mut columns = Vec::new();
1794 let mut indexed = Vec::new();
1795 for expr in &derived.exprs {
1796 match expr.kind {
1797 ExprKind::Var(var) => columns.extend(usize::try_from(var.attnum - 1).ok()),
1798 _ => indexed.push(expr),
1799 }
1800 }
1801 columns.sort_unstable();
1802 columns.dedup();
1803 let checked =
1806 |at: usize| exact.iter().any(|e| matches!(e.target, Exact::Expr(x) if x == at));
1807 columns == set
1808 && exprs
1809 .iter()
1810 .enumerate()
1811 .all(|(at, e)| checked(at) || indexed.iter().any(|i| i.same(e)))
1812 && indexed.iter().all(|i| exprs.iter().any(|e| e.same(i)))
1813 && derived.predicate.iter().all(|p| predicate.iter().any(|e| e.same(p)))
1814 })
1815 .map(|(at, _)| at)
1816 .collect(),
1817 };
1818 if places.is_empty() {
1819 return Err(Error::new(
1820 SqlState::INVALID_COLUMN_REFERENCE,
1821 "there is no unique or exclusion constraint matching the ON CONFLICT specification",
1822 ));
1823 }
1824 Ok(places)
1825}
1826
1827pub(crate) fn write_columns(rel: &rupg_catalog::Relation) -> Vec<Column> {
1829 rel.columns
1830 .iter()
1831 .map(|c| Column {
1832 name: if c.dropped { String::new() } else { c.name.clone() },
1833 ty: c.ty,
1834 typmod: c.typmod,
1835 not_null: c.not_null && !c.not_null_invalid,
1836 })
1837 .collect()
1838}
1839
1840fn user_trigger(t: &rupg_catalog::Trigger, table: u32) -> bool {
1842 t.relation == table && !t.internal && t.fires()
1843}
1844
1845pub(crate) fn trigger_event(kind: WriteKind) -> i16 {
1847 match kind {
1848 WriteKind::Insert => rupg_catalog::TRIGGER_INSERT,
1849 WriteKind::Update => rupg_catalog::TRIGGER_UPDATE,
1850 WriteKind::Delete => rupg_catalog::TRIGGER_DELETE,
1851 WriteKind::Merge => {
1852 rupg_catalog::TRIGGER_INSERT
1853 | rupg_catalog::TRIGGER_UPDATE
1854 | rupg_catalog::TRIGGER_DELETE
1855 }
1856 }
1857}
1858
1859pub(crate) fn with_checks(
1861 name: &str,
1862 columns: &[Column],
1863 rows: Query,
1864 checks: Vec<(String, Expr)>,
1865 generated: &[Generated],
1866 tail: &[Column],
1867) -> Query {
1868 let width = columns.len();
1869 let mut columns = columns.to_vec();
1870 columns.extend_from_slice(tail);
1871 let mut targets: Vec<Target> = columns
1872 .iter()
1873 .enumerate()
1874 .map(|(i, c)| {
1875 let attnum = i16::try_from(i + 1).unwrap_or(i16::MAX);
1876 let mut expr =
1877 Expr::new(ExprKind::Var(Var { relation: 0, attnum, levels_up: 0 }), c.ty);
1878 expr.typmod = c.typmod;
1879 Target { name: c.name.clone(), expr, origin: None, junk: false }
1880 })
1881 .collect();
1882 let tail = targets.split_off(width);
1883 for (index, expr, kind) in generated {
1885 if *kind == b's'
1886 && let Some(target) = targets.get_mut(*index)
1887 {
1888 target.expr = expr.clone();
1889 }
1890 }
1891 targets.extend(checks.into_iter().map(|(n, mut expr)| {
1892 compute_generated(&mut expr, generated, &columns[..width]);
1893 Target { name: n, expr, origin: None, junk: false }
1894 }));
1895 targets.extend(tail);
1896 let mut relation = Relation::new(0, columns, Some(Box::new(rows)), None, None);
1897 relation.name = name.to_string();
1898 Query {
1899 relations: vec![relation],
1900 from: vec![FromItem::Relation(0)],
1901 targets,
1902 ..Query::default()
1903 }
1904}
1905
1906fn compute_generated(expr: &mut Expr, generated: &[Generated], columns: &[Column]) {
1908 if generated.is_empty() {
1909 return;
1910 }
1911 expr.each_mut(0, &mut |e, depth| {
1912 let ExprKind::Var(var) = e.kind else { return false };
1913 if var.levels_up != depth || var.relation != 0 {
1914 return false;
1915 }
1916 if var.attnum == 0 {
1917 let fields = columns.iter().enumerate().filter(|(_, c)| c.ty != 0);
1919 let fields = fields
1920 .map(|(i, c)| match generated.iter().find(|(at, ..)| *at == i) {
1921 Some((_, value, _)) => {
1922 let mut value = value.clone();
1923 value.raise(depth);
1924 value
1925 }
1926 None => {
1927 let attnum = i16::try_from(i + 1).unwrap_or(i16::MAX);
1928 let var = Var { relation: 0, attnum, levels_up: depth };
1929 let mut field = Expr::new(ExprKind::Var(var), c.ty);
1930 field.typmod = c.typmod;
1931 field
1932 }
1933 })
1934 .collect();
1935 e.kind = ExprKind::Row(fields, CastForm::Implicit);
1936 return true;
1937 }
1938 let index = usize::try_from(var.attnum).ok().and_then(|n| n.checked_sub(1));
1939 let Some((_, value, _)) = generated.iter().find(|(i, ..)| Some(*i) == index) else {
1940 return false;
1941 };
1942 let mut value = value.clone();
1943 value.raise(depth);
1944 *e = value;
1945 true
1946 });
1947}
1948
1949pub(crate) fn default_part(indirection: &List, at: Option<usize>) -> Error {
1951 let what = match indirection.first() {
1952 Some(Some(Node::A_Indices(_))) => "an array element",
1953 _ => "a subfield",
1954 };
1955 Error::new(SqlState::FEATURE_NOT_SUPPORTED, format!("cannot set {what} to DEFAULT")).at_opt(at)
1956}
1957
1958fn strip_part(expr: Expr) -> Expr {
1960 match expr.kind {
1961 ExprKind::CoerceToDomain(arg, _) => strip_part(*arg),
1962 ExprKind::Subscript(sub) if sub.assign.is_some() => {
1963 sub.assign.map_or_else(|| Expr::new(ExprKind::Const(Value::Null), 0), strip_part)
1964 }
1965 ExprKind::FieldStore(store) if store.fields.len() == 1 => {
1966 store.fields.into_iter().next().map_or_else(
1967 || Expr::new(ExprKind::Const(Value::Null), 0),
1968 |(_, value)| strip_part(value),
1969 )
1970 }
1971 _ => expr,
1972 }
1973}
1974
1975fn is_part(expr: &Expr) -> bool {
1977 match &expr.kind {
1978 ExprKind::Subscript(sub) => sub.assign.is_some(),
1979 ExprKind::FieldStore(_) => true,
1980 _ => false,
1981 }
1982}
1983
1984pub(crate) fn merge_parts(prior: Expr, mut src: Expr, name: &str) -> Result<Expr> {
1990 let domain = |e: &Expr| matches!(e.kind, ExprKind::CoerceToDomain(..));
1991 if prior.ty == src.ty && domain(&prior) && domain(&src) {
1992 let (ExprKind::CoerceToDomain(prior, _), ExprKind::CoerceToDomain(arg, _)) =
1993 (prior.kind, &mut src.kind)
1994 else {
1995 return Err(Error::internal("an assignment to a domain that is not CoerceToDomain"));
1996 };
1997 let inner = std::mem::replace(&mut **arg, Expr::new(ExprKind::Const(Value::Null), 0));
1998 **arg = merge_parts(*prior, inner, name)?;
1999 return Ok(src);
2000 }
2001 if prior.ty != src.ty || !is_part(&prior) || !is_part(&src) {
2002 return Err(Error::new(
2003 SqlState::SYNTAX_ERROR,
2004 format!("multiple assignments to same column \"{name}\""),
2005 ));
2006 }
2007 match (&mut src.kind, prior.kind) {
2008 (ExprKind::FieldStore(store), ExprKind::FieldStore(old)) => {
2010 let FieldStore { arg, mut fields, .. } = *old;
2011 fields.append(&mut store.fields);
2012 store.fields = fields;
2013 store.arg = arg;
2014 }
2015 (ExprKind::FieldStore(store), kind) => store.arg = Expr { kind, ..prior },
2016 (ExprKind::Subscript(sub), kind) => sub.container = Expr { kind, ..prior },
2017 _ => {}
2018 }
2019 Ok(src)
2020}