1use rupg_catalog::RelKind;
4use rupg_common::{Error, Result, SqlState};
5use rupg_pgcatalog::Values;
6use rupg_pgcatalog::builtin::{self, Named};
7use rupg_sql::nodes::{
8 Alias, CoercionForm, ColumnRef, FuncCall, JoinExpr, JoinType, JsonTable, Node, RangeFunction,
9 RangeSubselect, RangeTableSample, RangeVar, SelectStmt,
10};
11use rupg_types::oid;
12
13use crate::Analyzer;
14use crate::agg::Kind;
15use crate::coerce::{AtOpt, Context};
16use crate::colname::figure_colname;
17use crate::cte::{CteItem, CteRef};
18use crate::expr::{CastForm, Expr, ExprKind, JoinRow, Var};
19use crate::insert::WriteKind;
20use crate::perm::{ACL_SELECT, PermInfo};
21use crate::typename::place;
22use crate::types;
23
24const MAX_FUZZY_DISTANCE: usize = 3;
26
27pub const TABLE_OID_ATTNUM: i16 = -6;
29
30const OTHER_SYSTEM_COLUMNS: [(&str, i16, u32); 5] = [
32 ("ctid", -1, oid::TID),
33 ("xmin", -2, oid::XID),
34 ("cmin", -3, oid::CID),
35 ("xmax", -4, oid::XID),
36 ("cmax", -5, oid::CID),
37];
38
39fn is_system_column(name: &str) -> bool {
41 name == "tableoid" || OTHER_SYSTEM_COLUMNS.iter().any(|c| c.0 == name)
42}
43
44pub(crate) fn system_column(name: &str) -> Option<(i16, u32)> {
46 if name == "tableoid" {
47 return Some((TABLE_OID_ATTNUM, oid::OID));
48 }
49 OTHER_SYSTEM_COLUMNS.iter().find(|c| c.0 == name).map(|c| (c.1, c.2))
50}
51
52#[derive(Clone, Debug, PartialEq)]
54pub struct Relation {
55 pub oid: u32,
57 pub columns: Vec<Column>,
59 pub subquery: Option<Box<crate::Query>>,
61 pub function: Option<FromFunction>,
63 pub values: Option<Vec<Vec<Expr>>>,
65 pub name: String,
67 pub alias: Option<Vec<String>>,
69 pub lateral: bool,
71 pub cte: Option<CteRef>,
73 pub tablesample: Option<TableSample>,
75 pub only: bool,
77 pub perm: Option<usize>,
79}
80
81impl Relation {
82 pub(crate) fn new(
84 oid: u32,
85 columns: Vec<Column>,
86 subquery: Option<Box<crate::Query>>,
87 function: Option<FromFunction>,
88 values: Option<Vec<Vec<Expr>>>,
89 ) -> Relation {
90 Relation {
91 oid,
92 columns,
93 subquery,
94 function,
95 values,
96 name: String::new(),
97 alias: None,
98 lateral: false,
99 cte: None,
100 tablesample: None,
101 only: false,
102 perm: None,
103 }
104 }
105
106 pub(crate) fn of_table(&self) -> bool {
108 self.oid != 0 || self.cte.as_ref().is_some_and(|c| c.transition)
109 }
110
111 pub fn json_table(&self) -> Option<&crate::expr::JsonTable> {
113 match self.function.as_ref()?.calls.as_slice() {
114 [(Expr { kind: ExprKind::JsonTable(table), .. }, _)] => Some(table),
115 _ => None,
116 }
117 }
118}
119
120#[derive(Clone, Debug, PartialEq)]
122pub struct TableSample {
123 pub handler: u32,
125 pub args: Vec<Expr>,
127 pub repeatable: Option<Expr>,
129}
130
131type FunctionCall<'n> = (Expr, String, &'n [Option<Node>]);
133
134#[derive(Clone, Debug, PartialEq)]
136pub struct FromFunction {
137 pub calls: Vec<(Expr, usize)>,
139 pub ordinality: bool,
141 pub coldefs: Vec<bool>,
143}
144
145#[derive(Clone, Debug, PartialEq)]
147pub struct Column {
148 pub name: String,
149 pub ty: u32,
150 pub typmod: i32,
151 pub not_null: bool,
153}
154
155impl Column {
156 pub(crate) fn is_dropped(&self) -> bool {
158 self.ty == 0 && self.name.is_empty()
159 }
160}
161
162pub(crate) fn scope_column(c: &rupg_catalog::Column) -> (String, u32, i32) {
164 (if c.dropped { String::new() } else { c.name.clone() }, c.ty, c.typmod)
165}
166
167#[derive(Clone, Debug, PartialEq)]
169pub enum FromItem {
170 Relation(usize),
172 Join(Box<Join>),
173}
174
175#[derive(Clone, Debug, PartialEq)]
177pub struct Join {
178 pub kind: JoinKind,
179 pub left: FromItem,
180 pub right: FromItem,
181 pub on: Option<Expr>,
183 pub using: Vec<String>,
185 pub plain_using: bool,
187 pub alias: Option<String>,
189 pub using_alias: Option<String>,
191 pub merged: Vec<Expr>,
193 pub columns: Vec<(String, Expr)>,
195 pub aliases: Vec<String>,
197 pub sources: Vec<(usize, usize)>,
199}
200
201#[derive(Clone, Copy, Debug, PartialEq, Eq)]
203pub enum JoinKind {
204 Inner,
205 Left,
206 Right,
207 Full,
208 Semi,
210 Anti,
212 RightSemi,
214 RightAnti,
216}
217
218#[derive(Clone, Debug)]
220pub(crate) struct Entry {
221 name: String,
223 aliased: bool,
225 columns: Vec<String>,
227 relation: Option<usize>,
229 oid: u32,
231}
232
233#[derive(Clone, Debug)]
235pub(crate) struct Item {
236 entry: usize,
238 name: String,
240 columns: Vec<(String, Expr)>,
242 rel_visible: bool,
244 cols_visible: bool,
246 hidden: usize,
248 returning: bool,
250}
251
252impl Item {
253 pub(crate) fn set_columns(&mut self, columns: impl Iterator<Item = (String, Expr)>) {
255 self.columns = columns.collect();
256 }
257
258 pub(crate) fn hide_last(&mut self, count: usize) {
260 self.hidden = count;
261 }
262}
263
264#[derive(Clone, Debug, Default)]
266pub(crate) struct Scope {
267 pub(crate) relations: Vec<Relation>,
268 entries: Vec<Entry>,
269 namespace: Vec<Item>,
270 lateral: Vec<(Item, bool)>,
272 lateral_active: bool,
274 pub(crate) ctes: Vec<CteItem>,
276 pub(crate) merge_action: Option<usize>,
278}
279
280impl Scope {
281 fn visible(&self) -> impl Iterator<Item = (&Item, bool)> {
283 let lateral = self.lateral.iter().filter(|_| self.lateral_active);
284 self.namespace.iter().map(|i| (i, true)).chain(lateral.map(|(i, ok)| (i, *ok)))
285 }
286}
287
288fn check_lateral_ok(item: &Item, ok: bool, at: Option<usize>) -> Result<()> {
290 if ok {
291 return Ok(());
292 }
293 Err(Error::new(
294 SqlState::INVALID_COLUMN_REFERENCE,
295 format!("invalid reference to FROM-clause entry for table \"{}\"", item.name),
296 )
297 .with_detail("The combining JOIN type must be INNER or LEFT for a LATERAL reference.")
298 .at_opt(at))
299}
300
301fn levenshtein(a: &str, b: &str) -> usize {
303 let b: Vec<char> = b.chars().collect();
304 let mut row: Vec<usize> = (0..=b.len()).collect();
305 for (i, ca) in a.chars().enumerate() {
306 let mut prev = row[0];
307 row[0] = i + 1;
308 for (j, cb) in b.iter().enumerate() {
309 let cost = usize::from(ca != *cb);
310 let next = (row[j] + 1).min(row[j + 1] + 1).min(prev + cost);
311 prev = row[j + 1];
312 row[j + 1] = next;
313 }
314 }
315 row[b.len()]
316}
317
318struct Fuzzy {
320 distance: usize,
321 first: Option<(Place, usize)>,
322 second: Option<(Place, usize)>,
323 exact: Vec<Place>,
324}
325
326type Place = (usize, usize);
328
329impl Fuzzy {
330 fn update(&mut self, penalty: usize, entry: Place, actual: &str, wanted: &str, column: usize) {
332 if penalty > self.distance || actual.is_empty() {
333 return;
334 }
335 let distance = levenshtein(actual, wanted);
336 if distance > wanted.len() / 2 {
337 return;
338 }
339 let distance = distance + penalty;
340 if distance < self.distance {
341 self.distance = distance;
342 self.first = Some((entry, column));
343 self.second = None;
344 } else if distance == self.distance {
345 if self.second.is_some() {
346 self.first = None;
347 self.second = None;
348 } else if self.first.is_some() {
349 self.second = Some((entry, column));
350 }
351 }
352 }
353}
354
355fn alias_columns(alias: &Alias) -> Vec<String> {
357 alias
358 .colnames
359 .iter()
360 .filter_map(|n| match n {
361 Some(Node::String(s)) => Some(s.to_string()),
362 _ => None,
363 })
364 .collect()
365}
366
367fn fields(list: &[Option<Node>]) -> Vec<Option<&str>> {
369 list.iter()
370 .map(|f| match f {
371 Some(Node::String(s)) => Some(&**s),
372 _ => None,
373 })
374 .collect()
375}
376
377impl Analyzer<'_> {
378 pub(crate) fn transform_from(&mut self, list: &[Option<Node>]) -> Result<Vec<FromItem>> {
380 let mut items = Vec::with_capacity(list.len());
381 for node in list {
382 let node = node.as_ref().ok_or_else(|| Error::internal("an empty FROM item"))?;
383 let (item, _, namespace) = self.transform_from_item(node)?;
384 self.check_conflicts(&self.scope.namespace, &namespace)?;
385 self.scope.namespace.extend(namespace);
386 items.push(item);
387 }
388 Ok(items)
389 }
390
391 fn transform_from_item(&mut self, node: &Node) -> Result<(FromItem, Item, Vec<Item>)> {
393 match node {
394 Node::RangeVar(rv) => {
395 let item = self.relation(rv)?;
396 let index = self.scope.entries[item.entry].relation.unwrap_or_default();
397 Ok((FromItem::Relation(index), item.clone(), vec![item]))
398 }
399 Node::JoinExpr(j) => self.join(j),
400 Node::RangeSubselect(r) if r.subquery.as_ref().is_some_and(crate::rules::is_write) => {
401 self.rule_relation(r)
402 }
403 Node::RangeSubselect(r) => {
404 let item = self.range_subselect(r)?;
405 let index = self.scope.entries[item.entry].relation.unwrap_or_default();
406 Ok((FromItem::Relation(index), item.clone(), vec![item]))
407 }
408 Node::RangeFunction(r) => {
409 let item = self.range_function(r)?;
410 let index = self.scope.entries[item.entry].relation.unwrap_or_default();
411 Ok((FromItem::Relation(index), item.clone(), vec![item]))
412 }
413 Node::RangeTableSample(r) => self.range_table_sample(r),
414 Node::RangeTableFunc(_) => Err(not_yet("XMLTABLE", None)),
415 Node::JsonTable(jt) => {
416 let item = self.range_json_table(jt)?;
417 let index = self.scope.entries[item.entry].relation.unwrap_or_default();
418 Ok((FromItem::Relation(index), item.clone(), vec![item]))
419 }
420 _ => Err(Error::internal("unrecognized node type in FROM")),
421 }
422 }
423
424 fn range_table_sample(&mut self, r: &RangeTableSample) -> Result<(FromItem, Item, Vec<Item>)> {
426 let node =
427 r.relation.as_ref().ok_or_else(|| Error::internal("a TABLESAMPLE with no relation"))?;
428 let (item, top, namespace) = self.transform_from_item(node)?;
429 let index = self.scope.entries[top.entry].relation.unwrap_or_default();
430 let relation = &self.scope.relations[index];
431 if relation.oid == 0
432 || relation.cte.is_some()
433 || !matches!(crate::ddl::relkind(self.env, relation.oid), b'r' | b'm' | b'p')
434 {
435 let at = match node {
436 Node::RangeVar(rv) => place(rv.location),
437 _ => None,
438 };
439 return Err(Error::new(
440 SqlState::FEATURE_NOT_SUPPORTED,
441 "TABLESAMPLE clause can only be applied to tables and materialized views",
442 )
443 .at_opt(at));
444 }
445 let before = self.scope.lateral.len();
447 let hidden = std::mem::take(&mut self.scope.namespace);
448 self.scope.lateral.extend(hidden.into_iter().map(|item| (item, true)));
449 let active = std::mem::replace(&mut self.scope.lateral_active, false);
450 let sample = self.table_sample(r);
451 self.scope.lateral_active = active;
452 self.scope.namespace =
453 self.scope.lateral.split_off(before).into_iter().map(|(item, _)| item).collect();
454 self.scope.relations[index].tablesample = Some(sample?);
455 Ok((item, top, namespace))
456 }
457
458 fn table_sample(&mut self, r: &RangeTableSample) -> Result<TableSample> {
460 let at = place(r.location);
461 let names: Vec<&str> = fields(&r.method).into_iter().flatten().collect();
462 let shown = names.join(".");
463 let missing = || {
464 Error::new(
465 SqlState::UNDEFINED_OBJECT,
466 format!("tablesample method {shown} does not exist"),
467 )
468 .at_opt(at)
469 };
470 let (schema, name) = match names.as_slice() {
471 [schema, name] => (Some(self.schema(schema).ok_or_else(missing)?), *name),
472 _ => self.split_name(&names, None)?,
473 };
474 let schemas = match schema {
475 Some(namespace) => vec![namespace],
476 None => self.path.clone(),
477 };
478 let found = schemas.iter().find_map(|&namespace| {
479 let user = self.env.catalog().and_then(|c| {
480 c.functions()
481 .find(|f| {
482 f.namespace == namespace && f.name == name && f.argtypes == [oid::INTERNAL]
483 })
484 .map(|f| (f.oid, f.rettype))
485 });
486 user.or_else(|| {
487 builtin::procs_named(name)
488 .find(|p| p.namespace == namespace && p.argtypes == [oid::INTERNAL])
489 .map(|p| (p.oid, p.rettype))
490 })
491 });
492 let Some((handler, rettype)) = found else { return Err(missing()) };
493 if rettype != oid::TSM_HANDLER {
494 return Err(Error::new(
495 SqlState::WRONG_OBJECT_TYPE,
496 format!("function {shown} must return type tsm_handler"),
497 )
498 .at_opt(at));
499 }
500 let params = [oid::FLOAT4];
502 if r.args.len() != params.len() {
503 let count = params.len();
504 let noun = if count == 1 { "argument" } else { "arguments" };
505 return Err(Error::new(
506 SqlState::INVALID_TABLESAMPLE_ARGUMENT,
507 format!("tablesample method {shown} requires {count} {noun}, not {}", r.args.len()),
508 )
509 .at_opt(at));
510 }
511 let mut args = Vec::with_capacity(params.len());
512 for (arg, &ty) in r.args.iter().zip(¶ms) {
513 let expr = self.with_kind(Kind::FromFunction, |a| a.transform(arg.as_ref()))?;
514 args.push(self.coerce_to_specific(expr, ty, "TABLESAMPLE")?);
515 }
516 let repeatable = match &r.repeatable {
517 Some(node) => {
518 let expr = self.with_kind(Kind::FromFunction, |a| a.transform(Some(node)))?;
519 Some(self.coerce_to_specific(expr, oid::FLOAT8, "REPEATABLE")?)
520 }
521 None => None,
522 };
523 Ok(TableSample { handler, args, repeatable })
524 }
525
526 fn relation(&mut self, rv: &RangeVar) -> Result<Item> {
528 if let Some(item) = self.cte_reference(rv)? {
529 return Ok(item);
530 }
531 if let Some(item) = self.transition_reference(rv)? {
532 return Ok(item);
533 }
534 self.catalog_relation(rv, false)
535 }
536
537 fn catalog_relation(&mut self, rv: &RangeVar, target: bool) -> Result<Item> {
541 if target && let Some(item) = self.auto_view_item(rv)? {
542 return Ok(item);
543 }
544 let at = place(rv.location);
545 let name = rv.relname.as_deref().unwrap_or_default();
546 let oid = self.lookup_relation(rv)?.ok_or_else(|| {
547 let error = match &rv.schemaname {
548 Some(schema) => Error::new(
549 SqlState::UNDEFINED_TABLE,
550 format!("relation \"{schema}.{name}\" does not exist"),
551 ),
552 None if self.future_cte(name) => Error::new(
553 SqlState::UNDEFINED_TABLE,
554 format!("relation \"{name}\" does not exist"),
555 )
556 .with_detail(format!(
557 "There is a WITH item named \"{name}\", but it cannot be referenced from this part of the query."
558 ))
559 .with_hint(
560 "Use WITH RECURSIVE, or re-order the WITH items to remove forward references.",
561 ),
562 None => Error::new(
563 SqlState::UNDEFINED_TABLE,
564 format!("relation \"{name}\" does not exist"),
565 ),
566 };
567 error.at_opt(at)
568 })?;
569 let columns = self.open_relation(oid, name, at)?;
570 let perm = if target { self.target_perm } else { Some(self.add_perm(oid, ACL_SELECT)) };
571 let subquery = match self.view_query_perms(oid)? {
572 Some((mut query, perms)) => {
574 if target {
575 crate::perm::forget(&mut query);
576 } else {
577 self.add_view_perms(oid, &mut query, perms);
578 }
579 Some(Box::new(query))
580 }
581 None => None,
582 };
583 let alias = rv.alias.as_deref();
584 let refname = alias.and_then(|a| a.aliasname.as_deref()).unwrap_or(name).to_string();
585 let mut relation = Relation::new(oid, columns, subquery, None, None);
586 relation.only = !rv.inh;
587 relation.perm = perm;
588 self.add_relation(relation, refname, alias)
589 }
590
591 pub(crate) fn view_query(&self, oid: u32) -> Result<Option<crate::Query>> {
593 Ok(self.view_query_perms(oid)?.map(|(query, _)| query))
594 }
595
596 fn view_query_perms(&self, oid: u32) -> Result<Option<(crate::Query, Vec<PermInfo>)>> {
598 let Some(rel) = self.env.catalog().and_then(|c| c.relation(oid)) else { return Ok(None) };
599 if rel.kind == RelKind::MatView && self.env.filling() != oid {
600 return Ok(None);
601 }
602 self.stored_query_perms(oid)
603 }
604
605 pub(crate) fn stored_query(&self, oid: u32) -> Result<Option<crate::Query>> {
607 Ok(self.stored_query_perms(oid)?.map(|(query, _)| query))
608 }
609
610 pub(crate) fn stored_query_perms(
612 &self,
613 oid: u32,
614 ) -> Result<Option<(crate::Query, Vec<PermInfo>)>> {
615 let Some(rel) = self.env.catalog().and_then(|c| c.relation(oid)) else { return Ok(None) };
616 let Some(view) = &rel.view else { return Ok(None) };
617 if self.views.contains(&oid) {
618 return Err(Error::new(
619 SqlState::INVALID_OBJECT_DEFINITION,
620 format!("infinite recursion detected in rules for relation \"{}\"", rel.name),
621 ));
622 }
623 let (list, _) = rupg_sql::parse(&view.text).map_err(Error::from)?;
624 let query = list.iter().flatten().find_map(|node| match node {
625 Node::RawStmt(raw) => match raw.stmt.as_ref() {
626 Some(Node::ViewStmt(stmt)) => stmt.query.as_ref(),
627 Some(Node::CreateTableAsStmt(stmt)) => stmt.query.as_ref(),
628 _ => None,
629 },
630 _ => None,
631 });
632 let Some(Node::SelectStmt(select)) = query else {
633 return Err(Error::internal("the query of a view is not a SELECT"));
634 };
635 let mut an = Analyzer::new(self.env, &crate::Params::default());
636 an.set_path(&view.path);
637 an.views.clone_from(&self.views);
638 an.views.push(oid);
639 let mut query = an.select(select).map_err(|error| error.with_position(None))?;
640 query.funcs = an.funcs;
641 Ok(Some((query, an.perms)))
642 }
643
644 fn range_subselect(&mut self, r: &RangeSubselect) -> Result<Item> {
646 let query = self.subquery_in_from(r.subquery.as_ref(), r.lateral)?;
647 let columns = query
648 .targets
649 .iter()
650 .filter(|t| !t.junk)
651 .map(|t| Column {
652 name: t.name.clone(),
653 ty: t.expr.ty,
654 typmod: t.expr.typmod,
655 not_null: false,
656 })
657 .collect();
658 let alias = r.alias.as_deref();
659 let refname = alias.and_then(|a| a.aliasname.as_deref()).unwrap_or("unnamed_subquery");
660 let mut relation = Relation::new(0, columns, Some(Box::new(query)), None, None);
661 relation.lateral = r.lateral;
662 let mut item = self.add_relation(relation, refname.to_string(), alias)?;
663 item.rel_visible = alias.is_some();
664 Ok(item)
665 }
666
667 fn rule_relation(&mut self, r: &RangeSubselect) -> Result<(FromItem, Item, Vec<Item>)> {
669 let Some(stmt) = r.subquery.as_ref() else {
670 return Err(Error::internal("a rule subquery with no statement"));
671 };
672 let perm = self.target_perm;
673 let query = self.sub_level(false, |analyzer| {
674 analyzer.rule.rows = true;
675 let query = match stmt {
676 Node::InsertStmt(s) => analyzer.insert(s),
677 Node::UpdateStmt(s) => analyzer.update(s),
678 Node::DeleteStmt(s) => analyzer.delete(s),
679 _ => Err(Error::internal("a rule subquery that is not a write")),
680 };
681 analyzer.rule.rows = false;
682 query
683 });
684 self.target_perm = perm;
685 let query = query?;
686 let table = std::mem::take(&mut self.rule.columns);
687 let columns = query
688 .targets
689 .iter()
690 .map(|t| Column {
691 name: t.name.clone(),
692 ty: t.expr.ty,
693 typmod: t.expr.typmod,
694 not_null: false,
695 })
696 .collect();
697 let relation = Relation::new(0, columns, Some(Box::new(query)), None, None);
698 let mut top = self.add_relation(relation, "*rule*".to_string(), None)?;
699 top.rel_visible = false;
700 top.cols_visible = false;
701 let index = self.scope.entries[top.entry].relation.unwrap_or_default();
702 let width = table.len();
703 let rows: &[(&str, usize)] = match stmt {
704 Node::InsertStmt(_) => &[("new", 0)],
705 Node::UpdateStmt(_) => &[("old", width), ("new", 0)],
706 _ => &[("old", 0)],
707 };
708 let mut items = Vec::with_capacity(rows.len());
709 for &(name, offset) in rows {
710 let row = crate::rules::relation_row(&table, index, offset);
711 items.push(self.rule_item(name, crate::rules::named_row(&table, row)));
712 }
713 Ok((FromItem::Relation(index), top, items))
714 }
715
716 pub(crate) fn rule_item(&mut self, name: &str, columns: Vec<(String, Expr)>) -> Item {
718 let entry = self.scope.entries.len();
719 self.scope.entries.push(Entry {
720 name: name.to_string(),
721 aliased: true,
722 columns: columns.iter().map(|(n, _)| n.clone()).collect(),
723 relation: None,
724 oid: 0,
725 });
726 Item {
727 entry,
728 name: name.to_string(),
729 columns,
730 rel_visible: true,
731 cols_visible: false,
732 hidden: 0,
733 returning: false,
734 }
735 }
736
737 pub(crate) fn push_item(&mut self, item: Item) {
739 self.scope.namespace.push(item);
740 }
741
742 fn subquery_in_from(&mut self, node: Option<&Node>, lateral: bool) -> Result<crate::Query> {
744 let Some(Node::SelectStmt(stmt)) = node else {
745 return Err(Error::internal("a subquery in FROM that is not SelectStmt"));
746 };
747 self.sub_select(stmt, lateral)
748 }
749
750 pub(crate) fn sub_select(&mut self, stmt: &SelectStmt, lateral: bool) -> Result<crate::Query> {
752 self.sub_level(lateral, |analyzer| analyzer.select(stmt))
753 }
754
755 pub(crate) fn sub_level(
757 &mut self,
758 lateral: bool,
759 f: impl FnOnce(&mut Self) -> Result<crate::Query>,
760 ) -> Result<crate::Query> {
761 let mut scope = std::mem::take(&mut self.scope);
762 let before = scope.lateral.len();
763 let hidden = std::mem::take(&mut scope.namespace);
764 scope.lateral.extend(hidden.into_iter().map(|item| (item, true)));
765 let active = std::mem::replace(&mut scope.lateral_active, lateral);
766 self.outer.push(scope);
767 let kind = std::mem::replace(&mut self.kind, Kind::Other);
768 let has_aggs = std::mem::replace(&mut self.has_aggs, false);
769 self.outer_kinds.push((None, has_aggs));
770 let srfs = self.srfs;
771 let result = f(self);
772 self.srfs = srfs;
773 self.has_aggs = self.outer_kinds.pop().map_or(has_aggs, |(_, has_aggs)| has_aggs);
774 self.kind = kind;
775 let mut scope = self.outer.pop().unwrap_or_default();
776 scope.lateral_active = active;
777 scope.namespace =
778 scope.lateral.split_off(before).into_iter().map(|(item, _)| item).collect();
779 self.scope = scope;
780 result
781 }
782
783 fn range_function(&mut self, r: &RangeFunction) -> Result<Item> {
785 let before = self.scope.lateral.len();
786 let hidden = std::mem::take(&mut self.scope.namespace);
787 self.scope.lateral.extend(hidden.into_iter().map(|item| (item, true)));
788 let active = std::mem::replace(&mut self.scope.lateral_active, true);
789 let calls = self.function_calls(r);
790 self.scope.lateral_active = active;
791 self.scope.namespace =
792 self.scope.lateral.split_off(before).into_iter().map(|(item, _)| item).collect();
793 let mut calls = calls?;
794 if let Some(Some(Node::ColumnDef(first))) = r.coldeflist.first() {
795 let at = place(first.location);
796 if calls.len() != 1 {
797 let (message, hint) = if r.is_rowsfrom {
798 (
799 "ROWS FROM() with multiple functions cannot have a column definition list",
800 "Put a separate column definition list for each function inside ROWS FROM().",
801 )
802 } else {
803 (
804 "UNNEST() with multiple arguments cannot have a column definition list",
805 "Use separate UNNEST() calls inside ROWS FROM(), and attach a column definition list to each one.",
806 )
807 };
808 return Err(Error::new(SqlState::SYNTAX_ERROR, message).with_hint(hint).at_opt(at));
809 }
810 if r.ordinality {
811 return Err(Error::new(
812 SqlState::SYNTAX_ERROR,
813 "WITH ORDINALITY cannot be used with a column definition list",
814 )
815 .with_hint("Put the column definition list inside ROWS FROM().")
816 .at_opt(at));
817 }
818 calls[0].2 = &r.coldeflist;
819 }
820 let alias = r.alias.as_deref();
821 let first = calls.first().map(|c| c.1.clone()).unwrap_or_default();
822 let refname = alias.and_then(|a| a.aliasname.as_deref()).map_or(first, str::to_string);
823 let count = calls.len();
824 let mut columns = Vec::new();
825 let mut out = Vec::with_capacity(count);
826 let mut defined = Vec::with_capacity(count);
827 for (expr, name, coldefs) in calls {
828 let given = self.function_columns(&expr, &name, coldefs, alias, count)?;
829 defined.push(!coldefs.is_empty());
830 out.push((expr, given.len()));
831 columns.extend(given);
832 }
833 if r.ordinality {
834 let name = "ordinality".to_string();
835 columns.push(Column { name, ty: oid::INT8, typmod: -1, not_null: false });
836 }
837 let function = FromFunction { calls: out, ordinality: r.ordinality, coldefs: defined };
838 let mut relation = Relation::new(0, columns, None, Some(function), None);
839 relation.lateral = r.lateral;
840 self.add_relation(relation, refname, alias)
841 }
842
843 fn range_json_table(&mut self, jt: &JsonTable) -> Result<Item> {
845 let before = self.scope.lateral.len();
846 let hidden = std::mem::take(&mut self.scope.namespace);
847 self.scope.lateral.extend(hidden.into_iter().map(|item| (item, true)));
848 let active = std::mem::replace(&mut self.scope.lateral_active, true);
849 let table = self.with_kind(Kind::FromFunction, |a| a.json_table(jt));
850 self.scope.lateral_active = active;
851 self.scope.namespace =
852 self.scope.lateral.split_off(before).into_iter().map(|(item, _)| item).collect();
853 let (call, table_columns) = table?;
854 let alias = jt.alias.as_deref();
855 if let Some(alias) = alias {
856 let given = alias_columns(alias).len();
857 if given > table_columns.len() {
858 return Err(Error::new(
859 SqlState::INVALID_COLUMN_REFERENCE,
860 format!(
861 "JSON_TABLE function has {} columns available but {given} columns specified",
862 table_columns.len()
863 ),
864 ));
865 }
866 }
867 let refname = alias
868 .and_then(|a| a.aliasname.as_deref())
869 .map_or_else(|| "json_table".to_string(), str::to_string);
870 let columns: Vec<Column> = table_columns
871 .into_iter()
872 .map(|c| Column { name: c.name, ty: c.ty, typmod: c.typmod, not_null: false })
873 .collect();
874 let width = columns.len();
875 let function =
876 FromFunction { calls: vec![(call, width)], ordinality: false, coldefs: vec![false] };
877 let mut relation = Relation::new(0, columns, None, Some(function), None);
878 relation.lateral = jt.lateral;
879 self.add_relation(relation, refname, alias)
880 }
881
882 fn function_calls<'n>(&mut self, r: &'n RangeFunction) -> Result<Vec<FunctionCall<'n>>> {
884 let mut out = Vec::with_capacity(r.functions.len());
885 for pair in &r.functions {
886 let Some(Node::List(pair)) = pair else {
887 return Err(Error::internal("a function in FROM that is not a pair"));
888 };
889 let node = pair.first().and_then(Option::as_ref);
890 let coldefs: &[Option<Node>] = match pair.get(1) {
891 Some(Some(Node::List(list))) => list,
892 _ => &[],
893 };
894 if let Some(Node::FuncCall(fc)) = node
895 && fc.funcname.len() == 1
896 && fields(&fc.funcname) == [Some("unnest")]
897 && fc.args.len() > 1
898 && fc.agg_order.is_empty()
899 && fc.agg_filter.is_none()
900 && fc.over.is_none()
901 && !fc.agg_star
902 && !fc.agg_distinct
903 && !fc.func_variadic
904 && coldefs.is_empty()
905 {
906 for arg in &fc.args {
907 let call = FuncCall {
908 funcname: vec![
909 Some(Node::String("pg_catalog".into())),
910 Some(Node::String("unnest".into())),
911 ],
912 args: vec![arg.clone()],
913 funcformat: CoercionForm::COERCE_EXPLICIT_CALL,
914 location: fc.location,
915 ..FuncCall::default()
916 };
917 let call = Node::FuncCall(Box::new(call));
918 let expr = self.function_expr(Some(&call))?;
919 out.push((expr, figure_colname(Some(&call)), &[][..]));
920 }
921 continue;
922 }
923 let expr = self.function_expr(node)?;
924 if !coldefs.is_empty()
925 && let Some(Some(Node::ColumnDef(first))) = r.coldeflist.first()
926 {
927 return Err(Error::new(
928 SqlState::SYNTAX_ERROR,
929 "multiple column definition lists are not allowed for the same function",
930 )
931 .at_opt(place(first.location)));
932 }
933 out.push((expr, figure_colname(node), coldefs));
934 }
935 Ok(out)
936 }
937
938 fn function_expr(&mut self, node: Option<&Node>) -> Result<Expr> {
940 let expr = self.with_kind(Kind::FromFunction, |a| a.transform(node))?;
941 let retset = |e: &Expr| match &e.kind {
942 ExprKind::Func(f) => builtin::proc_by_oid(f.oid).is_some_and(|p| p.retset),
943 _ => false,
944 };
945 let mut nested = |e: &Expr, depth: usize| (depth == 0 && retset(e)).then_some(e.location);
946 let found = match &expr.kind {
947 ExprKind::Func(f) if retset(&expr) => {
948 f.args.iter().find_map(|a| a.find(0, &mut nested))
949 }
950 _ => expr.find(0, &mut nested),
951 };
952 if let Some(at) = found {
953 return Err(Error::new(
954 SqlState::FEATURE_NOT_SUPPORTED,
955 "set-returning functions must appear at top level of FROM",
956 )
957 .at_opt(at));
958 }
959 Ok(expr)
960 }
961
962 fn function_columns(
964 &mut self,
965 expr: &Expr,
966 name: &str,
967 coldefs: &[Option<Node>],
968 alias: Option<&Alias>,
969 count: usize,
970 ) -> Result<Vec<Column>> {
971 let at = coldefs.first().and_then(|c| match c {
972 Some(Node::ColumnDef(def)) => place(def.location),
973 _ => None,
974 });
975 if let ExprKind::Func(f) = &expr.kind
976 && expr.ty == oid::RECORD
977 && let Some(columns) = crate::record::out_columns(f)?
978 {
979 if !coldefs.is_empty() {
980 return Err(Error::new(
981 SqlState::SYNTAX_ERROR,
982 "a column definition list is redundant for a function with OUT parameters",
983 )
984 .at_opt(at));
985 }
986 return Ok(columns);
987 }
988 let proc = match &expr.kind {
989 ExprKind::Func(f) => builtin::proc_by_oid(f.oid),
990 _ => None,
991 };
992 let mut outs: Vec<(Option<&str>, u32)> = Vec::new();
994 if let Some(p) = proc
995 && let (Some(types), Some(modes)) = (p.allargtypes, p.argmodes)
996 {
997 for (i, (ty, mode)) in types.iter().zip(modes).enumerate() {
998 if matches!(mode, b'o' | b'b' | b't') {
999 let named =
1000 p.argnames.and_then(|n| n.get(i)).copied().filter(|n| !n.is_empty());
1001 outs.push((named, *ty));
1002 }
1003 }
1004 }
1005 let row = types::row(expr.ty);
1006 if expr.ty == oid::RECORD {
1007 if coldefs.is_empty() {
1008 return Err(Error::new(
1009 SqlState::SYNTAX_ERROR,
1010 "a column definition list is required for functions returning \"record\"",
1011 )
1012 .at_opt(expr.place()));
1013 }
1014 return self.column_definitions(coldefs);
1015 }
1016 if row.is_some_and(|r| r.kind == b'c') {
1017 if !coldefs.is_empty() {
1018 return Err(Error::new(
1019 SqlState::SYNTAX_ERROR,
1020 "a column definition list is redundant for a function returning a named composite type",
1021 )
1022 .at_opt(at));
1023 }
1024 return self
1026 .row_columns(expr.ty)
1027 .ok_or_else(|| Error::internal("a composite type with no relation"));
1028 }
1029 if !coldefs.is_empty() {
1030 return Err(Error::new(
1031 SqlState::SYNTAX_ERROR,
1032 "a column definition list is only allowed for functions returning \"record\"",
1033 )
1034 .at_opt(at));
1035 }
1036 if row.is_some_and(|r| r.kind == b'p') && !matches!(expr.ty, oid::VOID | oid::CSTRING) {
1037 return Err(Error::new(
1038 SqlState::DATATYPE_MISMATCH,
1039 format!(
1040 "function \"{name}\" in FROM has unsupported return type {}",
1041 types::name(expr.ty)
1042 ),
1043 )
1044 .at_opt(expr.place()));
1045 }
1046 let column = match outs.as_slice() {
1048 [(Some(n), _)] => (*n).to_string(),
1049 _ => match alias.and_then(|a| a.aliasname.as_deref()) {
1050 Some(a) if count == 1 => a.to_string(),
1051 _ => name.to_string(),
1052 },
1053 };
1054 Ok(vec![Column { name: column, ty: expr.ty, typmod: expr.typmod, not_null: false }])
1055 }
1056
1057 fn column_definitions(&mut self, coldefs: &[Option<Node>]) -> Result<Vec<Column>> {
1059 let mut columns: Vec<Column> = Vec::with_capacity(coldefs.len());
1060 for def in coldefs {
1061 let Some(Node::ColumnDef(def)) = def else {
1062 return Err(Error::internal("a column definition that is not ColumnDef"));
1063 };
1064 let name = def.colname.as_deref().unwrap_or_default().to_string();
1065 let type_name =
1066 def.typeName.as_deref().ok_or_else(|| Error::internal("a column with no type"))?;
1067 if type_name.setof {
1068 return Err(Error::new(
1069 SqlState::INVALID_TABLE_DEFINITION,
1070 format!("column \"{name}\" cannot be declared SETOF"),
1071 )
1072 .at_opt(place(def.location)));
1073 }
1074 let (ty, typmod) = self.type_name(type_name)?;
1075 columns.push(Column { name, ty, typmod, not_null: false });
1076 }
1077 for (i, column) in columns.iter().enumerate() {
1078 if columns[..i].iter().any(|c| c.name == column.name) {
1079 return Err(Error::new(
1080 SqlState::DUPLICATE_COLUMN,
1081 format!("column name \"{}\" specified more than once", column.name),
1082 ));
1083 }
1084 }
1085 for column in &columns {
1086 if !matches!(column.ty, oid::RECORD | oid::RECORD_ARRAY) {
1087 crate::ddl::check_attribute_type(&column.name, column.ty, false)?;
1088 }
1089 }
1090 Ok(columns)
1091 }
1092
1093 pub(crate) fn add_relation(
1095 &mut self,
1096 relation: Relation,
1097 refname: String,
1098 alias: Option<&Alias>,
1099 ) -> Result<Item> {
1100 let columns = &relation.columns;
1101 let mut colnames: Vec<String> = columns.iter().map(|c| c.name.clone()).collect();
1102 let dropped: Vec<bool> =
1104 columns.iter().map(|c| relation.of_table() && c.is_dropped()).collect();
1105 if let Some(alias) = alias {
1106 let given = alias_columns(alias);
1107 let live = dropped.iter().filter(|&&d| !d).count();
1108 if given.len() > live {
1109 return Err(Error::new(
1110 SqlState::INVALID_COLUMN_REFERENCE,
1111 format!(
1112 "table \"{refname}\" has {live} columns available but {} columns specified",
1113 given.len()
1114 ),
1115 ));
1116 }
1117 let slots = colnames.iter_mut().zip(&dropped).filter(|(_, d)| !**d);
1118 for ((slot, _), name) in slots.zip(given) {
1119 *slot = name;
1120 }
1121 }
1122 let index = self.scope.relations.len();
1123 let exprs: Vec<(String, Expr)> = colnames
1124 .iter()
1125 .zip(columns)
1126 .enumerate()
1127 .filter(|&(i, _)| !dropped[i])
1128 .map(|(i, (n, c))| {
1129 let attnum = i16::try_from(i + 1).unwrap_or(i16::MAX);
1130 let var = Var { relation: index, attnum, levels_up: 0 };
1131 let mut expr = Expr::new(ExprKind::Var(var), c.ty);
1132 expr.typmod = c.typmod;
1133 (n.clone(), expr)
1134 })
1135 .collect();
1136 let oid = relation.oid;
1137 let mut relation = relation;
1138 relation.name.clone_from(&refname);
1139 relation.alias = alias.map(alias_columns);
1140 self.scope.relations.push(relation);
1141 let entry = self.scope.entries.len();
1142 self.scope.entries.push(Entry {
1143 name: refname.clone(),
1144 aliased: alias.is_some(),
1145 columns: colnames,
1146 relation: Some(index),
1147 oid,
1148 });
1149 Ok(Item {
1150 entry,
1151 name: refname,
1152 columns: exprs,
1153 rel_visible: true,
1154 cols_visible: true,
1155 hidden: 0,
1156 returning: false,
1157 })
1158 }
1159
1160 pub(crate) fn add_values(
1162 &mut self,
1163 relation: Relation,
1164 ) -> Result<(usize, Vec<(String, Expr)>)> {
1165 let item = self.add_relation(relation, "*VALUES*".to_string(), None)?;
1166 let index = self.scope.entries[item.entry].relation.unwrap_or_default();
1167 let columns = item.columns.clone();
1168 self.scope.namespace.push(item);
1169 Ok((index, columns))
1170 }
1171
1172 pub(crate) fn add_columns(&mut self, columns: Vec<(String, Expr)>) -> (usize, usize) {
1174 let before = (self.scope.entries.len(), self.scope.namespace.len());
1175 let names = columns.iter().map(|(n, _)| n.clone()).collect();
1176 let entry = self.scope.entries.len();
1177 self.scope.entries.push(Entry {
1178 name: "unnamed_join".to_string(),
1179 aliased: false,
1180 columns: names,
1181 relation: None,
1182 oid: 0,
1183 });
1184 self.scope.namespace.push(Item {
1185 entry,
1186 name: "unnamed_join".to_string(),
1187 columns,
1188 rel_visible: false,
1189 cols_visible: true,
1190 hidden: 0,
1191 returning: false,
1192 });
1193 before
1194 }
1195
1196 pub(crate) fn remove_columns(&mut self, (entries, items): (usize, usize)) {
1198 self.scope.entries.truncate(entries);
1199 self.scope.namespace.truncate(items);
1200 }
1201
1202 pub(crate) fn add_returning_item(
1204 &mut self,
1205 name: &str,
1206 old: bool,
1207 kind: WriteKind,
1208 ) -> Result<usize> {
1209 let target = self
1210 .scope
1211 .relations
1212 .first()
1213 .ok_or_else(|| Error::internal("RETURNING with no table"))?;
1214 let mut relation = Relation::new(target.oid, target.columns.clone(), None, None, None);
1215 relation.perm = target.perm;
1216 let index = self.scope.relations.len();
1217 let mut item = self.add_relation(relation, name.to_string(), None)?;
1218 item.cols_visible = false;
1219 item.returning = true;
1220 self.auto_view_returning(&mut item, index, Some((kind, old)))?;
1221 self.scope.namespace.push(item);
1222 Ok(index)
1223 }
1224
1225 pub(crate) fn add_excluded(&mut self) -> Result<usize> {
1227 let target = self
1228 .scope
1229 .relations
1230 .first()
1231 .ok_or_else(|| Error::internal("ON CONFLICT with no table"))?;
1232 let relation = Relation::new(target.oid, target.columns.clone(), None, None, None);
1233 let index = self.scope.relations.len();
1234 let mut item = self.add_relation(relation, "excluded".to_string(), None)?;
1235 self.auto_view_returning(&mut item, index, None)?;
1237 self.scope.entries[item.entry].oid = 0;
1238 self.scope.namespace.push(item);
1239 Ok(index)
1240 }
1241
1242 pub(crate) fn entry_relations(&self, oid: u32) -> std::collections::BTreeSet<usize> {
1244 self.scope.entries.iter().filter(|e| e.oid == oid).filter_map(|e| e.relation).collect()
1245 }
1246
1247 pub(crate) fn set_entry_oid(&mut self, item: &Item, oid: u32) {
1249 let entry = &mut self.scope.entries[item.entry];
1250 entry.oid = oid;
1251 entry.columns = item.columns.iter().map(|(name, _)| name.clone()).collect();
1252 }
1253
1254 pub(crate) fn check_target(&self, rv: &RangeVar) -> Result<()> {
1256 let name = rv.relname.as_deref().unwrap_or_default();
1257 if rv.schemaname.is_none() && self.env.transition_table(name).is_some() {
1258 return Err(Error::new(
1259 SqlState::FEATURE_NOT_SUPPORTED,
1260 format!("relation \"{name}\" cannot be the target of a modifying statement"),
1261 ));
1262 }
1263 Ok(())
1264 }
1265
1266 pub(crate) fn target_relation(&mut self, rv: &RangeVar) -> Result<FromItem> {
1268 self.check_target(rv)?;
1269 let item = self.catalog_relation(rv, true)?;
1270 let index = self.scope.entries[item.entry].relation.unwrap_or_default();
1271 self.scope.namespace.push(item);
1272 Ok(FromItem::Relation(index))
1273 }
1274
1275 pub(crate) fn merge_from(&mut self, rv: &RangeVar, source: &Node) -> Result<FromItem> {
1281 self.check_target(rv)?;
1282 let target = self.catalog_relation(rv, true)?;
1283 let (item, _, namespace) = self.transform_from_item(source)?;
1284 if namespace.iter().any(|other| other.name == target.name) {
1285 return Err(Error::new(
1286 SqlState::DUPLICATE_ALIAS,
1287 format!("name \"{}\" specified more than once", target.name),
1288 )
1289 .with_detail("The name is used both as MERGE target table and data source."));
1290 }
1291 self.scope.namespace.extend(namespace);
1292 self.scope.namespace.push(target);
1293 Ok(item)
1294 }
1295
1296 pub(crate) fn merge_namespace(&mut self, target: bool, source: bool) -> Vec<Item> {
1298 let full = self.scope.namespace.clone();
1299 let Some((last, before)) = full.split_last() else { return full };
1300 self.scope.namespace = match (target, source) {
1301 (true, true) => full.clone(),
1302 (false, _) => before.to_vec(),
1303 (true, false) => vec![last.clone()],
1304 };
1305 full
1306 }
1307
1308 pub(crate) fn set_namespace(&mut self, namespace: Vec<Item>) {
1310 self.scope.namespace = namespace;
1311 }
1312
1313 pub(crate) fn hide_last_item(&mut self) {
1315 self.scope.namespace.pop();
1316 }
1317
1318 pub(crate) fn has_refname(&self, name: &str) -> Result<bool> {
1320 Ok(self.item_by_name(None, name, None)?.is_some())
1321 }
1322
1323 pub(crate) fn scope_size(&self) -> (usize, usize, usize) {
1325 (self.scope.relations.len(), self.scope.entries.len(), self.scope.namespace.len())
1326 }
1327
1328 pub(crate) fn truncate_scope(&mut self, (relations, entries, items): (usize, usize, usize)) {
1330 self.scope.relations.truncate(relations);
1331 self.scope.entries.truncate(entries);
1332 self.scope.namespace.truncate(items);
1333 }
1334
1335 pub(crate) fn add_table(
1337 &mut self,
1338 oid: u32,
1339 name: &str,
1340 columns: &[(String, u32, i32)],
1341 row_type: u32,
1342 ) {
1343 if row_type != 0 {
1344 self.row_types.insert(oid, row_type);
1345 }
1346 let index = self.scope.relations.len();
1347 let exprs: Vec<(String, Expr)> = columns
1348 .iter()
1349 .enumerate()
1350 .filter(|(_, (n, ty, _))| !(n.is_empty() && *ty == 0))
1351 .map(|(i, (n, ty, typmod))| {
1352 let attnum = i16::try_from(i + 1).unwrap_or(i16::MAX);
1353 let var = Var { relation: index, attnum, levels_up: 0 };
1354 let mut expr = Expr::new(ExprKind::Var(var), *ty);
1355 expr.typmod = *typmod;
1356 (n.clone(), expr)
1357 })
1358 .collect();
1359 let columns: Vec<Column> = columns
1360 .iter()
1361 .map(|(n, ty, typmod)| Column {
1362 name: n.clone(),
1363 ty: *ty,
1364 typmod: *typmod,
1365 not_null: false,
1366 })
1367 .collect();
1368 let colnames = columns.iter().map(|c| c.name.clone()).collect();
1369 let mut relation = Relation::new(oid, columns, None, None, None);
1370 relation.name = name.to_string();
1371 self.scope.relations.push(relation);
1372 let entry = self.scope.entries.len();
1373 self.scope.entries.push(Entry {
1374 name: name.to_string(),
1375 aliased: false,
1376 columns: colnames,
1377 relation: Some(index),
1378 oid,
1379 });
1380 self.scope.namespace.push(Item {
1381 entry,
1382 name: name.to_string(),
1383 columns: exprs,
1384 rel_visible: true,
1385 cols_visible: true,
1386 hidden: 0,
1387 returning: false,
1388 });
1389 }
1390
1391 pub(crate) fn rule_scope(
1393 &mut self,
1394 oid: u32,
1395 name: &str,
1396 visible: [bool; 2],
1397 columns: bool,
1398 ) -> Result<()> {
1399 self.scope = Scope::default();
1400 for (refname, visible) in ["old", "new"].into_iter().zip(visible) {
1401 let alias = Alias { aliasname: Some(refname.into()), ..Alias::default() };
1402 let relation =
1403 Relation::new(oid, self.open_relation(oid, name, None)?, None, None, None);
1404 let mut item = self.add_relation(relation, refname.to_string(), Some(&alias))?;
1405 item.cols_visible = columns;
1406 if visible {
1407 self.scope.namespace.push(item);
1408 }
1409 }
1410 Ok(())
1411 }
1412
1413 pub(crate) fn lookup_relation(&self, rv: &RangeVar) -> Result<Option<u32>> {
1415 let at = place(rv.location);
1416 let name = rv.relname.as_deref().unwrap_or_default();
1417 if let Some(database) = &rv.catalogname
1418 && **database != self.env.database()
1419 {
1420 return Err(Error::new(
1421 SqlState::FEATURE_NOT_SUPPORTED,
1422 format!(
1423 "cross-database references are not implemented: \"{database}.{}.{name}\"",
1424 rv.schemaname.as_deref().unwrap_or_default()
1425 ),
1426 )
1427 .at_opt(at));
1428 }
1429 let in_schema = |namespace: u32| {
1430 builtin::named(Named::Class)
1431 .iter()
1432 .find(|r| r.namespace == namespace && r.name == name)
1433 .map(|r| r.oid)
1434 .or_else(|| self.env.catalog()?.relation_by_name(namespace, name).map(|r| r.oid))
1435 };
1436 match &rv.schemaname {
1437 Some(schema) => Ok(self.schema(schema).and_then(in_schema)),
1439 None => Ok(self.temp_path.iter().find_map(|&ns| in_schema(ns))),
1440 }
1441 }
1442
1443 pub(crate) fn open_relation(
1445 &self,
1446 oid: u32,
1447 name: &str,
1448 at: Option<usize>,
1449 ) -> Result<Vec<Column>> {
1450 let index_error = || {
1451 Error::new(SqlState::WRONG_OBJECT_TYPE, format!("cannot open relation \"{name}\""))
1452 .with_detail("This operation is not supported for indexes.")
1453 .at_opt(at)
1454 };
1455 if let Some(catalog) = rupg_pgcatalog::catalog_by_oid(oid) {
1456 return Ok(catalog
1457 .columns
1458 .iter()
1459 .map(|c| Column {
1460 name: c.name.to_string(),
1461 ty: c.type_oid,
1462 typmod: -1,
1463 not_null: c.not_null,
1464 })
1465 .collect());
1466 }
1467 if let Some(rel) = self.env.catalog().and_then(|c| c.relation(oid)) {
1468 if matches!(rel.kind, RelKind::Index | RelKind::PartitionedIndex) {
1469 return Err(index_error());
1470 }
1471 return Ok(rel
1472 .columns
1473 .iter()
1474 .map(|c| Column {
1476 name: if c.dropped { String::new() } else { c.name.clone() },
1477 ty: c.ty,
1478 typmod: c.typmod,
1479 not_null: c.not_null && !c.not_null_invalid,
1480 })
1481 .collect());
1482 }
1483 if builtin_relkind(oid) == Some(b'i') {
1484 return Err(index_error());
1485 }
1486 Err(not_yet(&format!("the system relation \"{name}\""), at))
1487 }
1488
1489 fn check_conflicts(&self, first: &[Item], second: &[Item]) -> Result<()> {
1491 for a in first.iter().filter(|i| i.rel_visible) {
1492 for b in second.iter().filter(|i| i.rel_visible) {
1493 if a.name != b.name {
1494 continue;
1495 }
1496 let (ea, eb) = (&self.scope.entries[a.entry], &self.scope.entries[b.entry]);
1497 let plain = |e: &Entry| e.relation.is_some() && !e.aliased;
1498 if plain(ea) && plain(eb) && ea.oid != eb.oid {
1499 continue;
1500 }
1501 return Err(Error::new(
1502 SqlState::DUPLICATE_ALIAS,
1503 format!("table name \"{}\" specified more than once", a.name),
1504 ));
1505 }
1506 }
1507 Ok(())
1508 }
1509
1510 fn join(&mut self, j: &JoinExpr) -> Result<(FromItem, Item, Vec<Item>)> {
1512 let left_node = j.larg.as_ref().ok_or_else(|| Error::internal("a join with no left"))?;
1513 let right_node = j.rarg.as_ref().ok_or_else(|| Error::internal("a join with no right"))?;
1514 let kind = match j.jointype {
1515 JoinType::JOIN_INNER => JoinKind::Inner,
1516 JoinType::JOIN_LEFT => JoinKind::Left,
1517 JoinType::JOIN_RIGHT => JoinKind::Right,
1518 JoinType::JOIN_FULL => JoinKind::Full,
1519 _ => return Err(Error::internal("unrecognized join type")),
1520 };
1521 let (left, l_item, l_namespace) = self.transform_from_item(left_node)?;
1522 let before = self.scope.lateral.len();
1524 let lateral_ok = matches!(kind, JoinKind::Inner | JoinKind::Left);
1525 self.scope.lateral.extend(l_namespace.iter().map(|item| (item.clone(), lateral_ok)));
1526 let right = self.transform_from_item(right_node);
1527 self.scope.lateral.truncate(before);
1528 let (right, r_item, r_namespace) = right?;
1529 self.check_conflicts(&l_namespace, &r_namespace)?;
1530 let mut namespace = l_namespace;
1531 namespace.extend(r_namespace);
1532 let l_names: Vec<&str> = l_item.columns.iter().map(|(n, _)| n.as_str()).collect();
1533 let r_names: Vec<&str> = r_item.columns.iter().map(|(n, _)| n.as_str()).collect();
1534 let using: Vec<String> = if j.isNatural {
1535 l_names.iter().filter(|n| r_names.contains(n)).map(|n| (*n).to_string()).collect()
1536 } else {
1537 fields(&j.usingClause).into_iter().flatten().map(str::to_string).collect()
1538 };
1539 let mut merged: Vec<(String, Expr)> = Vec::new();
1540 let mut l_used = Vec::new();
1541 let mut r_used = Vec::new();
1542 let mut on = None;
1543 if !using.is_empty() {
1544 let mut pairs = Vec::new();
1545 for name in &using {
1546 if merged.iter().any(|(n, _)| n == name) || pairs.iter().any(|(n, _, _)| n == name)
1547 {
1548 return Err(Error::new(
1549 SqlState::DUPLICATE_COLUMN,
1550 format!("column name \"{name}\" appears more than once in USING clause"),
1551 ));
1552 }
1553 let find = |names: &[&str], side: &str| -> Result<usize> {
1554 let mut found = None;
1555 for (i, n) in names.iter().enumerate() {
1556 if n == name {
1557 if found.is_some() {
1558 return Err(Error::new(
1559 SqlState::AMBIGUOUS_COLUMN,
1560 format!(
1561 "common column name \"{name}\" appears more than once in {side} table"
1562 ),
1563 ));
1564 }
1565 found = Some(i);
1566 }
1567 }
1568 found.ok_or_else(|| {
1569 Error::new(
1570 SqlState::UNDEFINED_COLUMN,
1571 format!("column \"{name}\" specified in USING clause does not exist in {side} table"),
1572 )
1573 })
1574 };
1575 let l = find(&l_names, "left")?;
1576 let r = find(&r_names, "right")?;
1577 pairs.push((name.clone(), l, r));
1578 }
1579 let mut conds = Vec::new();
1581 for (_, l, r) in &pairs {
1582 let (lv, rv) = (l_item.columns[*l].1.clone(), r_item.columns[*r].1.clone());
1583 conds.push(self.make_op(&["="], Some(lv), rv, None)?);
1584 }
1585 let cond = if conds.len() == 1 {
1586 conds.remove(0)
1587 } else {
1588 Expr::new(ExprKind::Bool(crate::expr::BoolOp::And, conds), oid::BOOL)
1589 };
1590 self.mark_select(&cond);
1591 on = Some(self.coerce_to_boolean(cond, "JOIN/USING")?);
1592 for (name, l, r) in pairs {
1593 let expr = self.merged_column(
1594 kind,
1595 l_item.columns[l].1.clone(),
1596 r_item.columns[r].1.clone(),
1597 )?;
1598 merged.push((name, expr));
1599 l_used.push(l);
1600 r_used.push(r);
1601 }
1602 } else if let Some(quals) = &j.quals {
1603 let saved = std::mem::replace(&mut self.scope.namespace, namespace.clone());
1605 let lateral = std::mem::take(&mut self.scope.lateral);
1606 let result = self.with_kind(Kind::JoinOn, |a| a.transform(Some(quals)));
1607 self.scope.namespace = saved;
1608 self.scope.lateral = lateral;
1609 on = Some(self.coerce_to_boolean(result?, "JOIN/ON")?);
1610 }
1611 let plain_using = merged.iter().all(|(_, e)| matches!(e.kind, ExprKind::Var(_)));
1612 let merged_values: Vec<Expr> = merged.iter().map(|(_, e)| e.clone()).collect();
1613 let mut columns = merged;
1614 let using_count = columns.len();
1615 let mut sources: Vec<(usize, usize)> =
1616 l_used.iter().zip(&r_used).map(|(l, r)| (l + 1, r + 1)).collect();
1617 for (i, c) in l_item.columns.iter().enumerate() {
1618 if !l_used.contains(&i) {
1619 columns.push(c.clone());
1620 sources.push((i + 1, 0));
1621 }
1622 }
1623 for (i, c) in r_item.columns.iter().enumerate() {
1624 if !r_used.contains(&i) {
1625 columns.push(c.clone());
1626 sources.push((0, i + 1));
1627 }
1628 }
1629 let alias = j.alias.as_deref();
1630 let mut aliases = Vec::new();
1631 if let Some(alias) = alias {
1632 let given = alias_columns(alias);
1633 aliases.clone_from(&given);
1634 let name = alias.aliasname.as_deref().unwrap_or_default();
1635 if given.len() > columns.len() {
1636 return Err(Error::new(
1637 SqlState::INVALID_COLUMN_REFERENCE,
1638 format!(
1639 "join expression \"{name}\" has {} columns available but {} columns specified",
1640 columns.len(),
1641 given.len()
1642 ),
1643 ));
1644 }
1645 for (slot, n) in columns.iter_mut().zip(given) {
1646 slot.0 = n;
1647 }
1648 }
1649 let entry = self.scope.entries.len();
1650 let name = alias.and_then(|a| a.aliasname.as_deref()).unwrap_or("unnamed_join");
1651 self.scope.entries.push(Entry {
1652 name: name.to_string(),
1653 aliased: alias.is_some(),
1654 columns: columns.iter().map(|(n, _)| n.clone()).collect(),
1655 relation: None,
1656 oid: 0,
1657 });
1658 if let Some(using_alias) = j.join_using_alias.as_deref() {
1659 let item = Item {
1660 entry,
1661 name: using_alias.aliasname.as_deref().unwrap_or_default().to_string(),
1662 columns: columns[..using_count].to_vec(),
1663 rel_visible: true,
1664 cols_visible: true,
1665 hidden: 0,
1666 returning: false,
1667 };
1668 self.check_conflicts(std::slice::from_ref(&item), &namespace)?;
1669 namespace.push(item);
1670 }
1671 if alias.is_some() {
1672 namespace.clear();
1673 } else {
1674 for item in &mut namespace {
1675 item.cols_visible = false;
1676 }
1677 }
1678 let item = Item {
1679 entry,
1680 name: name.to_string(),
1681 columns,
1682 rel_visible: alias.is_some(),
1683 cols_visible: true,
1684 hidden: 0,
1685 returning: false,
1686 };
1687 namespace.push(item.clone());
1688 let join = Join {
1689 kind,
1690 left,
1691 right,
1692 on,
1693 plain_using,
1694 using,
1695 alias: alias.and_then(|a| a.aliasname.as_deref()).map(str::to_string),
1696 using_alias: j
1697 .join_using_alias
1698 .as_deref()
1699 .and_then(|a| a.aliasname.as_deref())
1700 .map(str::to_string),
1701 merged: merged_values,
1702 columns: item.columns.clone(),
1703 aliases,
1704 sources,
1705 };
1706 Ok((FromItem::Join(Box::new(join)), item, namespace))
1707 }
1708
1709 fn merged_column(&mut self, kind: JoinKind, l: Expr, r: Expr) -> Result<Expr> {
1711 let pair = [l, r];
1712 let ty = self.common_type(&pair, "JOIN/USING")?;
1713 let [l, r] = pair;
1714 let typmod = if l.typmod == r.typmod { l.typmod } else { -1 };
1715 let mut fix = |e: Expr| -> Result<Expr> {
1716 if e.ty != ty {
1717 self.coerce(e, ty, typmod, Context::Implicit, None)
1718 } else if e.typmod != typmod {
1719 Ok(Expr {
1720 kind: ExprKind::Relabel(Box::new(e), CastForm::Implicit),
1721 ty,
1722 typmod,
1723 location: None,
1724 })
1725 } else {
1726 Ok(e)
1727 }
1728 };
1729 let (l, r) = (fix(l)?, fix(r)?);
1730 let is_var = |e: &Expr| matches!(e.kind, ExprKind::Var(_));
1731 Ok(match kind {
1732 JoinKind::Inner if !is_var(&l) && is_var(&r) => r,
1733 JoinKind::Inner | JoinKind::Left | JoinKind::Semi | JoinKind::Anti => l,
1734 JoinKind::Right | JoinKind::RightSemi | JoinKind::RightAnti => r,
1735 JoinKind::Full => {
1736 Expr { kind: ExprKind::Coalesce(vec![l, r]), ty, typmod: -1, location: None }
1737 }
1738 })
1739 }
1740
1741 pub(crate) fn column_ref(&mut self, c: &ColumnRef) -> Result<Expr> {
1745 let expr = self.resolve_column_ref(c)?;
1746 self.mark_select(&expr);
1747 Ok(expr)
1748 }
1749
1750 fn resolve_column_ref(&mut self, c: &ColumnRef) -> Result<Expr> {
1752 let at = place(c.location);
1753 if self.kind == Kind::ColumnDefault {
1754 return Err(Error::new(
1755 SqlState::FEATURE_NOT_SUPPORTED,
1756 "cannot use column reference in DEFAULT expression",
1757 )
1758 .at_opt(at));
1759 }
1760 if self.kind == Kind::PartitionBound {
1761 return Err(Error::new(
1762 SqlState::FEATURE_NOT_SUPPORTED,
1763 "cannot use column reference in partition bound expression",
1764 )
1765 .at_opt(at));
1766 }
1767 let names = fields(&c.fields);
1768 if let Some((ty, typmod)) = self.domain_value
1770 && names.as_slice() == [Some("value")]
1771 {
1772 return Ok(Expr { kind: ExprKind::DomainValue, ty, typmod, location: at });
1773 }
1774 let (schema, table, column) = match names.as_slice() {
1775 [Some(column)] => {
1776 if let Some(expr) = self.column_by_name(column, at)? {
1777 return Ok(expr);
1778 }
1779 if let Some((level, item)) = self.item_by_name(None, column, at)? {
1780 return self.whole_row(level, &item, at);
1781 }
1782 if let Some(expr) = self.function_argument(&names, at)? {
1783 return Ok(expr);
1784 }
1785 return Err(self.missing_column(None, column, at));
1786 }
1787 [Some(table), None] => {
1788 let Some((level, item)) = self.item_by_name(None, table, at)? else {
1789 return Err(self.missing_entry(None, table, at));
1790 };
1791 return self.whole_row(level, &item, at);
1792 }
1793 [None] => {
1794 return Err(Error::new(
1795 SqlState::SYNTAX_ERROR,
1796 "SELECT * with no tables specified is not valid",
1797 )
1798 .at_opt(at));
1799 }
1800 [Some(table), Some(column)] => (None, *table, *column),
1801 [Some(schema), Some(table), Some(column)] => (Some(*schema), *table, *column),
1802 [Some(database), Some(schema), Some(table), Some(column)] => {
1803 if *database != self.env.database() {
1804 return Err(Error::new(
1805 SqlState::FEATURE_NOT_SUPPORTED,
1806 format!(
1807 "cross-database references are not implemented: {}",
1808 names.iter().map(|n| n.unwrap_or("*")).collect::<Vec<_>>().join(".")
1809 ),
1810 )
1811 .at_opt(at));
1812 }
1813 (Some(*schema), *table, *column)
1814 }
1815 [.., None] if names.len() <= 4 => {
1816 return Err(Error::new(
1817 SqlState::FEATURE_NOT_SUPPORTED,
1818 "a row expansion with * is supported only in the target list",
1819 )
1820 .at_opt(at));
1821 }
1822 _ => {
1823 let text: Vec<&str> = names.iter().map(|f| f.unwrap_or("*")).collect();
1824 return Err(Error::new(
1825 SqlState::SYNTAX_ERROR,
1826 format!("improper qualified name (too many dotted names): {}", text.join(".")),
1827 )
1828 .at_opt(at));
1829 }
1830 };
1831 let Some((level, item)) = self.item_by_name(schema, table, at)? else {
1832 if let Some(expr) = self.function_argument(&names, at)? {
1833 return Ok(expr);
1834 }
1835 return Err(self.missing_entry(schema, table, at));
1836 };
1837 match self.column_in(level, &item, column, at)? {
1838 Some(expr) => Ok(expr),
1839 None => match self.function_argument(&names, at)? {
1840 Some(expr) => Ok(expr),
1841 None => Err(self.missing_column(Some(table), column, at)),
1842 },
1843 }
1844 }
1845
1846 fn function_argument(
1848 &mut self,
1849 names: &[Option<&str>],
1850 at: Option<usize>,
1851 ) -> Result<Option<Expr>> {
1852 let Some((function, args)) = &self.sql_function else { return Ok(None) };
1853 let arg = |name: &str| args.iter().position(|a| a == name);
1854 let found = match names {
1855 [Some(name)] => arg(name).map(|n| (n, None)),
1856 [Some(first), Some(name)] if *first == function.as_str() && arg(name).is_some() => {
1857 arg(name).map(|n| (n, None))
1858 }
1859 [Some(name), Some(field)] => arg(name).map(|n| (n, Some(*field))),
1860 [Some(first), Some(name), Some(field)] if *first == function.as_str() => {
1861 arg(name).map(|n| (n, Some(*field)))
1862 }
1863 _ => None,
1864 };
1865 let Some((n, field)) = found else { return Ok(None) };
1866 let number = i32::try_from(n + 1).map_err(|_| Error::internal("too many arguments"))?;
1867 let param = self.transform_param(number, at)?;
1868 match field {
1869 Some(field) => self.field_select(param, field, at).map(Some),
1870 None => Ok(Some(param)),
1871 }
1872 }
1873
1874 fn whole_row(&self, level: usize, item: &Item, at: Option<usize>) -> Result<Expr> {
1876 let entry = &self.level(level).entries[item.entry];
1877 let base = entry.relation.and_then(|r| self.level(level).relations.get(r));
1879 if entry.oid != 0 && base.is_some_and(|r| r.oid != entry.oid) {
1880 let fields = item.columns.iter().map(|(_, expr)| {
1881 let mut expr = expr.clone();
1882 expr.raise(level);
1883 expr
1884 });
1885 let ty = self
1886 .row_type(entry.oid)
1887 .ok_or_else(|| not_yet("a whole-row reference to this relation", at))?;
1888 let row = ExprKind::Row(fields.collect(), CastForm::Implicit);
1889 return Ok(Expr::new(row, ty).at(at));
1890 }
1891 let Some(relation) = entry.relation else {
1892 let alias = (entry.aliased && item.name == entry.name).then(|| item.name.clone());
1894 let mut fields = Vec::with_capacity(item.columns.len());
1895 let mut names = Vec::with_capacity(item.columns.len());
1896 for (name, expr) in &item.columns {
1897 let mut expr = expr.clone();
1898 expr.raise(level);
1899 fields.push(expr);
1900 names.push(name.clone());
1901 }
1902 let row = JoinRow { alias, names, fields };
1903 return Ok(Expr::new(ExprKind::JoinRow(Box::new(row)), oid::RECORD).at(at));
1904 };
1905 let ty = match entry.oid {
1906 0 => oid::RECORD,
1907 _ if self.kind == Kind::Generated => oid::RECORD,
1909 rel => self
1910 .row_type(rel)
1911 .ok_or_else(|| not_yet("a whole-row reference to this relation", at))?,
1912 };
1913 let var = Var { relation, attnum: 0, levels_up: level };
1914 Ok(Expr::new(ExprKind::Var(var), ty).at(at))
1915 }
1916
1917 fn row_type(&self, rel: u32) -> Option<u32> {
1919 if let Some(catalog) = rupg_pgcatalog::catalog_by_oid(rel) {
1920 return Some(catalog.rowtype_oid).filter(|&ty| ty != 0);
1921 }
1922 if let Some(&ty) = self.row_types.get(&rel) {
1923 return Some(ty);
1924 }
1925 self.env.catalog()?.relation(rel).map(|r| r.row_type).filter(|&ty| ty != 0)
1926 }
1927
1928 pub(crate) fn row_columns(&self, ty: u32) -> Option<Vec<Column>> {
1930 let relid = match types::row(ty) {
1931 Some(row) if row.kind == b'c' => row.relid,
1932 Some(_) => return None,
1933 None => self.env.catalog()?.relations().find(|r| r.row_type == ty)?.oid,
1934 };
1935 let mut columns = self.open_relation(relid, "", None).ok()?;
1936 columns.retain(|c| !c.is_dropped());
1938 Some(columns)
1939 }
1940
1941 pub(crate) fn whole_row_field(&self, var: Var, name: &str, at: Option<usize>) -> Result<Expr> {
1943 let scope = self.level(var.levels_up);
1944 let entry = scope
1945 .entries
1946 .iter()
1947 .find(|e| e.relation == Some(var.relation))
1948 .ok_or_else(|| Error::internal("a whole-row reference has no entry"))?;
1949 let column = entry.columns.iter().position(|c| c == name).and_then(|i| {
1950 let column = scope.relations.get(var.relation)?.columns.get(i)?;
1951 Some((i, column))
1952 });
1953 let Some((i, column)) = column else {
1954 return Err(Error::new(
1955 SqlState::UNDEFINED_COLUMN,
1956 format!("column {}.{name} does not exist", entry.name),
1957 )
1958 .at_opt(at));
1959 };
1960 let attnum = i16::try_from(i + 1).map_err(|_| Error::internal("too many columns"))?;
1961 let var = Var { attnum, ..var };
1962 let mut expr = Expr::new(ExprKind::Var(var), column.ty).at(at);
1963 expr.typmod = column.typmod;
1964 Ok(expr)
1965 }
1966
1967 pub(crate) fn whole_row_columns(
1969 &self,
1970 var: Var,
1971 at: Option<usize>,
1972 ) -> Result<Vec<(String, Expr)>> {
1973 let scope = self.level(var.levels_up);
1974 let entry = scope
1975 .entries
1976 .iter()
1977 .find(|e| e.relation == Some(var.relation))
1978 .ok_or_else(|| Error::internal("a whole-row reference has no entry"))?;
1979 let relation = scope
1980 .relations
1981 .get(var.relation)
1982 .ok_or_else(|| Error::internal("a whole-row reference has no relation"))?;
1983 let mut columns = Vec::with_capacity(entry.columns.len());
1984 for (i, (name, column)) in entry.columns.iter().zip(&relation.columns).enumerate() {
1985 if relation.of_table() && column.is_dropped() {
1986 continue;
1987 }
1988 let attnum = i16::try_from(i + 1).map_err(|_| Error::internal("too many columns"))?;
1989 let mut expr = Expr::new(ExprKind::Var(Var { attnum, ..var }), column.ty).at(at);
1990 expr.typmod = column.typmod;
1991 columns.push((name.clone(), expr));
1992 }
1993 Ok(columns)
1994 }
1995
1996 pub(crate) fn levels(&self) -> impl Iterator<Item = (usize, &Scope)> {
1998 std::iter::once(&self.scope).chain(self.outer.iter().rev()).enumerate()
1999 }
2000
2001 pub(crate) fn level(&self, level: usize) -> &Scope {
2003 self.levels().nth(level).map_or(&self.scope, |(_, scope)| scope)
2004 }
2005
2006 fn column_in(
2008 &self,
2009 level: usize,
2010 item: &Item,
2011 name: &str,
2012 at: Option<usize>,
2013 ) -> Result<Option<Expr>> {
2014 let mut found = None;
2015 for (n, expr) in &item.columns {
2016 if n == name {
2017 if found.is_some() {
2018 return Err(ambiguous(name, at));
2019 }
2020 found = Some(expr);
2021 }
2022 }
2023 if let Some(expr) = found {
2024 let mut expr = expr.clone().at(at);
2025 expr.raise(level);
2026 return Ok(Some(expr));
2027 }
2028 let entry = &self.level(level).entries[item.entry];
2029 let Some(relation) = entry.relation else { return Ok(None) };
2030 let rel = self.level(level).relations.get(relation);
2031 let view = rel.is_some_and(|r| r.subquery.is_some() || r.oid != entry.oid);
2032 let live = rel.map_or(0, |r| r.columns.iter().filter(|c| !c.is_dropped()).count());
2033 if item.columns.len() != live || entry.oid == 0 || view {
2034 return Ok(None);
2036 }
2037 if name == "tableoid" {
2038 let var = Var { relation, attnum: TABLE_OID_ATTNUM, levels_up: level };
2039 return Ok(Some(Expr::new(ExprKind::Var(var), oid::OID).at(at)));
2040 }
2041 let Some(&(_, attnum, type_oid)) = OTHER_SYSTEM_COLUMNS.iter().find(|c| c.0 == name) else {
2042 return Ok(None);
2043 };
2044 if self.kind == Kind::Check {
2045 return Err(Error::new(
2046 SqlState::INVALID_COLUMN_REFERENCE,
2047 format!("system column \"{name}\" reference in check constraint is invalid"),
2048 )
2049 .at_opt(at));
2050 }
2051 if self.kind == Kind::Generated {
2053 return Err(Error::new(
2054 SqlState::INVALID_COLUMN_REFERENCE,
2055 format!("cannot use system column \"{name}\" in column generation expression"),
2056 )
2057 .at_opt(at));
2058 }
2059 if name == "ctid"
2061 && self.kind != Kind::TriggerWhen
2062 && entry.oid < rupg_catalog::FIRST_NORMAL_OID
2063 {
2064 return Err(not_yet("the system column \"ctid\"", at));
2065 }
2066 let var = Var { relation, attnum, levels_up: level };
2067 Ok(Some(Expr::new(ExprKind::Var(var), type_oid).at(at)))
2068 }
2069
2070 pub(crate) fn column_names(&self, var: Var) -> (String, String) {
2072 let scope = self.level(var.levels_up);
2073 let Some(entry) = scope.entries.iter().find(|e| e.relation == Some(var.relation)) else {
2074 return (String::new(), String::new());
2075 };
2076 let column = match usize::try_from(var.attnum) {
2077 Ok(n) if n > 0 => entry.columns.get(n - 1).cloned().unwrap_or_default(),
2078 _ => OTHER_SYSTEM_COLUMNS
2079 .iter()
2080 .find(|c| c.1 == var.attnum)
2081 .map_or("tableoid", |c| c.0)
2082 .to_string(),
2083 };
2084 (entry.name.clone(), column)
2085 }
2086
2087 pub(crate) fn column_by_name(&self, name: &str, at: Option<usize>) -> Result<Option<Expr>> {
2089 for (level, scope) in self.levels() {
2090 let mut result = None;
2091 for (item, ok) in scope.visible().filter(|(i, _)| i.cols_visible) {
2092 if let Some(expr) = self.column_in(level, item, name, at)? {
2093 if result.is_some() {
2094 return Err(ambiguous(name, at));
2095 }
2096 check_lateral_ok(item, ok, at)?;
2097 result = Some(expr);
2098 }
2099 }
2100 if result.is_some() {
2101 return Ok(result);
2102 }
2103 }
2104 Ok(None)
2105 }
2106
2107 fn item_by_name(
2109 &self,
2110 schema: Option<&str>,
2111 name: &str,
2112 at: Option<usize>,
2113 ) -> Result<Option<(usize, Item)>> {
2114 for (level, scope) in self.levels() {
2115 if let Some(item) = self.item_in(scope, schema, name, at)? {
2116 return Ok(Some((level, item)));
2117 }
2118 }
2119 Ok(None)
2120 }
2121
2122 fn item_in(
2124 &self,
2125 scope: &Scope,
2126 schema: Option<&str>,
2127 name: &str,
2128 at: Option<usize>,
2129 ) -> Result<Option<Item>> {
2130 if let Some(schema) = schema {
2131 let rv = RangeVar {
2133 schemaname: Some(schema.into()),
2134 relname: Some(name.into()),
2135 location: at.map_or(-1, |a| i32::try_from(a).unwrap_or(-1)),
2136 ..RangeVar::default()
2137 };
2138 let Some(oid) = self.lookup_relation(&rv)? else { return Ok(None) };
2139 let mut result = None;
2140 for (item, ok) in scope.visible().filter(|(i, _)| i.rel_visible && !i.returning) {
2141 let entry = &scope.entries[item.entry];
2142 if entry.relation.is_some() && !entry.aliased && entry.oid == oid {
2143 if result.is_some() {
2144 return Err(Error::new(
2145 SqlState::AMBIGUOUS_ALIAS,
2146 format!("table reference {oid} is ambiguous"),
2147 )
2148 .at_opt(at));
2149 }
2150 check_lateral_ok(item, ok, at)?;
2151 result = Some(item.clone());
2152 }
2153 }
2154 return Ok(result);
2155 }
2156 let mut result = None;
2157 for (item, ok) in scope.visible().filter(|(i, _)| i.rel_visible) {
2158 if item.name == name {
2159 if result.is_some() {
2160 return Err(Error::new(
2161 SqlState::AMBIGUOUS_ALIAS,
2162 format!("table reference \"{name}\" is ambiguous"),
2163 )
2164 .at_opt(at));
2165 }
2166 check_lateral_ok(item, ok, at)?;
2167 result = Some(item.clone());
2168 }
2169 }
2170 Ok(result)
2171 }
2172
2173 fn missing_entry(&self, schema: Option<&str>, name: &str, at: Option<usize>) -> Error {
2175 let rv = RangeVar {
2177 schemaname: schema.map(Into::into),
2178 relname: Some(name.into()),
2179 ..RangeVar::default()
2180 };
2181 let oid = self.lookup_relation(&rv).ok().flatten();
2182 let found = self.levels().find_map(|(level, scope)| {
2183 let index = scope
2184 .entries
2185 .iter()
2186 .position(|e| (e.relation.is_some() && Some(e.oid) == oid) || e.name == name)?;
2187 Some((level, index))
2188 });
2189 let Some((level, found)) = found else {
2190 return Error::new(
2191 SqlState::UNDEFINED_TABLE,
2192 format!("missing FROM-clause entry for table \"{name}\""),
2193 )
2194 .at_opt(at);
2195 };
2196 let entry = &self.level(level).entries[found];
2197 let error = Error::new(
2198 SqlState::UNDEFINED_TABLE,
2199 format!("invalid reference to FROM-clause entry for table \"{name}\""),
2200 )
2201 .at_opt(at);
2202 if entry.aliased && entry.name != name {
2203 let visible = matches!(
2204 self.item_by_name(None, &entry.name, None),
2205 Ok(Some((l, item))) if l == level && item.entry == found
2206 );
2207 if visible {
2208 return error.with_hint(format!(
2209 "Perhaps you meant to reference the table alias \"{}\".",
2210 entry.name
2211 ));
2212 }
2213 }
2214 let error = error.with_detail(format!(
2215 "There is an entry for table \"{}\", but it cannot be referenced from this part of the query.",
2216 entry.name
2217 ));
2218 if self.visible_if_lateral((level, found)) {
2219 return error
2220 .with_hint("To reference that table, you must mark this subquery with LATERAL.");
2221 }
2222 error
2223 }
2224
2225 fn visible_if_lateral(&self, (level, index): Place) -> bool {
2227 if self.scope.lateral_active {
2228 return false;
2229 }
2230 self.level(level).lateral.iter().any(|(item, ok)| item.entry == index && *ok)
2231 }
2232
2233 fn missing_column(&self, table: Option<&str>, column: &str, at: Option<usize>) -> Error {
2235 let mut fuzzy = Fuzzy {
2236 distance: MAX_FUZZY_DISTANCE + 1,
2237 first: None,
2238 second: None,
2239 exact: Vec::new(),
2240 };
2241 let entries = self.levels().flat_map(|(level, scope)| {
2242 scope.entries.iter().enumerate().map(move |(index, entry)| ((level, index), entry))
2243 });
2244 for (index, entry) in entries {
2245 let Some(relation) = entry.relation else { continue };
2246 let relation = self.level(index.0).relations.get(relation);
2248 let system = entry.oid != 0 && relation.is_none_or(|r| r.oid == entry.oid);
2249 let penalty =
2250 table.map_or(0, |t| levenshtein(t, &entry.name).min(MAX_FUZZY_DISTANCE + 1));
2251 let mut exact = false;
2252 for (i, name) in entry.columns.iter().enumerate() {
2253 if name == column {
2254 exact = true;
2255 }
2256 fuzzy.update(penalty, index, name, column, i);
2257 }
2258 if (exact || (is_system_column(column) && system)) && penalty == 0 {
2259 fuzzy.exact.push(index);
2260 }
2261 }
2262 let message = match table {
2263 Some(t) => format!("column {t}.{column} does not exist"),
2264 None => format!("column \"{column}\" does not exist"),
2265 };
2266 let error = Error::new(SqlState::UNDEFINED_COLUMN, message).at_opt(at);
2267 let entry = |(level, index): Place| &self.level(level).entries[index];
2268 if fuzzy.exact.len() > 1 {
2269 let error = error.with_detail(format!("There are columns named \"{column}\", but they are in tables that cannot be referenced from this part of the query."));
2270 return if table.is_none() {
2271 error.with_hint("Try using a table-qualified name.")
2272 } else {
2273 error
2274 };
2275 }
2276 if let Some(&index) = fuzzy.exact.first() {
2277 let error = error.with_detail(format!("There is a column named \"{column}\" in table \"{}\", but it cannot be referenced from this part of the query.", entry(index).name));
2278 let qualified = self.levels().any(|(level, scope)| {
2280 level == index.0
2281 && scope.namespace.iter().any(|i| i.entry == index.1 && i.rel_visible)
2282 });
2283 return if self.visible_if_lateral(index) {
2284 error.with_hint(
2285 "To reference that column, you must mark this subquery with LATERAL.",
2286 )
2287 } else if table.is_none() && qualified {
2288 error.with_hint("To reference that column, you must use a table-qualified name.")
2289 } else {
2290 error
2291 };
2292 }
2293 let name = |(e, c): (Place, usize)| format!("{}.{}", entry(e).name, entry(e).columns[c]);
2294 match (fuzzy.first, fuzzy.second) {
2295 (Some(first), None) => error.with_hint(format!(
2296 "Perhaps you meant to reference the column \"{}\".",
2297 name(first)
2298 )),
2299 (Some(first), Some(second)) => error.with_hint(format!(
2300 "Perhaps you meant to reference the column \"{}\" or the column \"{}\".",
2301 name(first),
2302 name(second)
2303 )),
2304 _ => error,
2305 }
2306 }
2307
2308 pub(crate) fn expand_star(&mut self, c: &ColumnRef) -> Result<Option<Vec<(String, Expr)>>> {
2310 let at = place(c.location);
2311 let names = fields(&c.fields);
2312 let Some((None, qualifier)) = names.split_last() else { return Ok(None) };
2313 let items: Vec<(usize, Item)> = match qualifier {
2314 [] => {
2315 let visible: Vec<(usize, Item)> = self
2316 .scope
2317 .namespace
2318 .iter()
2319 .filter(|i| i.cols_visible)
2320 .map(|i| (0, i.clone()))
2321 .collect();
2322 if visible.is_empty() {
2323 return Err(Error::new(
2324 SqlState::SYNTAX_ERROR,
2325 "SELECT * with no tables specified is not valid",
2326 )
2327 .at_opt(at));
2328 }
2329 visible
2330 }
2331 [Some(table)] | [Some(_), Some(table)] | [Some(_), Some(_), Some(table)] => {
2332 let schema = match qualifier {
2333 [Some(schema), _] | [_, Some(schema), _] => Some(*schema),
2334 _ => None,
2335 };
2336 if let [Some(database), _, _] = qualifier
2337 && *database != self.env.database()
2338 {
2339 return Err(Error::new(
2340 SqlState::FEATURE_NOT_SUPPORTED,
2341 format!(
2342 "cross-database references are not implemented: {}",
2343 names.iter().map(|n| n.unwrap_or("*")).collect::<Vec<_>>().join(".")
2344 ),
2345 )
2346 .at_opt(at));
2347 }
2348 match self.item_by_name(schema, table, at)? {
2349 Some((level, mut item)) => {
2351 for (_, expr) in &mut item.columns {
2352 expr.raise(level);
2353 }
2354 vec![(level, item)]
2355 }
2356 None if schema.is_none() && qualifier.len() == 1 => {
2357 if let Some(variable) = self.composite_variable(&[*table], at)? {
2359 let expr = self.variable_param(variable, at);
2360 return self.composite_fields(expr).map(Some);
2361 }
2362 return Err(self.missing_entry(schema, table, at));
2363 }
2364 None => return Err(self.missing_entry(schema, table, at)),
2365 }
2366 }
2367 _ => return Ok(None),
2368 };
2369 let mut columns = Vec::new();
2370 for (level, item) in items {
2371 if let Some(relation) = self.level(level).entries[item.entry].relation {
2373 self.mark_relation(level, relation);
2374 }
2375 let shown = item.columns.len() - item.hidden;
2376 for (_, expr) in item.columns.iter().take(shown) {
2377 self.mark_select(expr);
2378 }
2379 for (name, expr) in item.columns.into_iter().take(shown) {
2380 columns.push((name, expr.at(at)));
2381 }
2382 }
2383 Ok(Some(columns))
2384 }
2385}
2386
2387fn ambiguous(name: &str, at: Option<usize>) -> Error {
2389 Error::new(SqlState::AMBIGUOUS_COLUMN, format!("column reference \"{name}\" is ambiguous"))
2390 .at_opt(at)
2391}
2392
2393fn builtin_relkind(oid: u32) -> Option<u8> {
2395 let class = rupg_pgcatalog::catalog("pg_class")?;
2396 let (Values::Oid(oids), Values::Char(kinds)) =
2397 (&class.rows[class.column("oid")?].values, &class.rows[class.column("relkind")?].values)
2398 else {
2399 return None;
2400 };
2401 oids.iter().position(|&o| o == oid).map(|row| kinds[row])
2402}
2403
2404fn not_yet(what: &str, at: Option<usize>) -> Error {
2406 Error::new(SqlState::FEATURE_NOT_SUPPORTED, format!("{what} is not supported yet")).at_opt(at)
2407}
2408
2409#[cfg(test)]
2410mod tests {
2411 use super::levenshtein;
2412
2413 #[test]
2414 fn distances() {
2415 assert_eq!(levenshtein("relname", "relnam"), 1);
2416 assert_eq!(levenshtein("oid", "iod"), 2);
2417 assert_eq!(levenshtein("", "abc"), 3);
2418 assert_eq!(levenshtein("kitten", "sitting"), 3);
2419 }
2420}