1use std::borrow::Cow;
13use std::collections::{BTreeMap, BTreeSet};
14use std::fmt;
15use std::str::FromStr;
16use std::sync::LazyLock;
17
18use anyhow::anyhow;
19use mz_controller_types::{ClusterId, ReplicaId};
20use mz_expr::LocalId;
21use mz_ore::assert_none;
22use mz_ore::cast::CastFrom;
23use mz_ore::str::StrExt;
24use mz_repr::network_policy_id::NetworkPolicyId;
25use mz_repr::role_id::RoleId;
26use mz_repr::{CatalogItemId, GlobalId, RelationVersion};
27use mz_repr::{ColumnName, RelationVersionSelector};
28use mz_sql_parser::ast::visit_mut::VisitMutNode;
29use mz_sql_parser::ast::{CreateContinualTaskStatement, Expr, RawNetworkPolicyName, Version};
30use mz_sql_parser::ident;
31use proptest_derive::Arbitrary;
32use serde::{Deserialize, Serialize};
33use uncased::UncasedStr;
34
35use crate::ast::display::{AstDisplay, AstFormatter};
36use crate::ast::fold::{Fold, FoldNode};
37use crate::ast::visit::{Visit, VisitNode};
38use crate::ast::visit_mut::VisitMut;
39use crate::ast::{
40 self, AstInfo, Cte, CteBlock, CteMutRec, DocOnIdentifier, GrantTargetSpecification,
41 GrantTargetSpecificationInner, Ident, MutRecBlock, ObjectType, Query, Raw, RawClusterName,
42 RawDataType, RawItemName, Statement, UnresolvedItemName, UnresolvedObjectName,
43};
44use crate::catalog::{
45 CatalogError, CatalogItem, CatalogItemType, CatalogType, CatalogTypeDetails, SessionCatalog,
46};
47use crate::normalize;
48use crate::plan::PlanError;
49
50#[derive(
59 Debug,
60 Clone,
61 Eq,
62 PartialEq,
63 Hash,
64 Ord,
65 PartialOrd,
66 Serialize,
67 Deserialize
68)]
69pub struct FullItemName {
70 pub database: RawDatabaseSpecifier,
72 pub schema: String,
74 pub item: String,
76}
77
78impl FullItemName {
79 pub fn into_parts(self) -> Vec<String> {
82 let mut parts = vec![];
83 if let RawDatabaseSpecifier::Name(name) = self.database {
84 parts.push(name);
85 }
86 parts.push(self.schema);
87 parts.push(self.item);
88 parts
89 }
90}
91
92impl fmt::Display for FullItemName {
93 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
94 if let RawDatabaseSpecifier::Name(database) = &self.database {
95 write!(f, "{}.", database)?;
96 }
97 write!(f, "{}.{}", self.schema, self.item)
98 }
99}
100
101impl From<FullItemName> for UnresolvedItemName {
102 fn from(full_name: FullItemName) -> UnresolvedItemName {
103 let mut name_parts = Vec::new();
105 if let RawDatabaseSpecifier::Name(database) = full_name.database {
106 name_parts.push(Ident::new_unchecked(database));
107 }
108 name_parts.push(Ident::new_unchecked(full_name.schema));
109 name_parts.push(Ident::new_unchecked(full_name.item));
110 UnresolvedItemName(name_parts)
111 }
112}
113
114#[derive(Debug, Clone, Hash, PartialEq, Eq, Serialize)]
117pub struct QualifiedItemName {
118 pub qualifiers: ItemQualifiers,
119 pub item: String,
120}
121
122static_assertions::assert_not_impl_any!(QualifiedItemName: fmt::Display);
125
126#[derive(
131 Clone,
132 Debug,
133 Serialize,
134 Deserialize,
135 PartialEq,
136 Eq,
137 PartialOrd,
138 Ord,
139 Hash
140)]
141pub struct PartialItemName {
142 pub database: Option<String>,
143 pub schema: Option<String>,
144 pub item: String,
145}
146
147impl PartialItemName {
148 pub fn matches(&self, other: &Self) -> bool {
151 match (&self.database, &other.database) {
152 (Some(d1), Some(d2)) if d1 != d2 => return false,
153 _ => (),
154 }
155 match (&self.schema, &other.schema) {
156 (Some(s1), Some(s2)) if s1 != s2 => return false,
157 _ => (),
158 }
159 self.item == other.item
160 }
161}
162
163impl fmt::Display for PartialItemName {
164 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
165 if let Some(database) = &self.database {
166 write!(f, "{}.", database)?;
167 }
168 if let Some(schema) = &self.schema {
169 write!(f, "{}.", schema)?;
170 }
171 write!(f, "{}", self.item)
172 }
173}
174
175impl From<FullItemName> for PartialItemName {
176 fn from(n: FullItemName) -> PartialItemName {
177 let database = match n.database {
178 RawDatabaseSpecifier::Ambient => None,
179 RawDatabaseSpecifier::Name(name) => Some(name),
180 };
181 PartialItemName {
182 database,
183 schema: Some(n.schema),
184 item: n.item,
185 }
186 }
187}
188
189impl From<String> for PartialItemName {
190 fn from(item: String) -> Self {
191 PartialItemName {
192 database: None,
193 schema: None,
194 item,
195 }
196 }
197}
198
199impl From<PartialItemName> for UnresolvedItemName {
200 fn from(partial_name: PartialItemName) -> UnresolvedItemName {
201 let mut name_parts = Vec::new();
203 if let Some(database) = partial_name.database {
204 name_parts.push(Ident::new_unchecked(database));
205 }
206 if let Some(schema) = partial_name.schema {
207 name_parts.push(Ident::new_unchecked(schema));
208 }
209 name_parts.push(Ident::new_unchecked(partial_name.item));
210 UnresolvedItemName(name_parts)
211 }
212}
213
214#[derive(
216 Debug,
217 Clone,
218 Eq,
219 PartialEq,
220 Hash,
221 PartialOrd,
222 Ord,
223 Serialize,
224 Deserialize
225)]
226pub struct FullSchemaName {
227 pub database: RawDatabaseSpecifier,
229 pub schema: String,
231}
232
233impl fmt::Display for FullSchemaName {
234 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
235 if let RawDatabaseSpecifier::Name(database) = &self.database {
236 write!(f, "{}.", database)?;
237 }
238 write!(f, "{}", self.schema)
239 }
240}
241
242#[derive(Debug, Clone, Eq, PartialEq, Hash, Serialize, Deserialize)]
244pub struct QualifiedSchemaName {
245 pub database: ResolvedDatabaseSpecifier,
246 pub schema: String,
247}
248
249impl fmt::Display for QualifiedSchemaName {
250 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
251 match &self.database {
252 ResolvedDatabaseSpecifier::Ambient => f.write_str(&self.schema),
253 ResolvedDatabaseSpecifier::Id(id) => write!(f, "{}.{}", id, self.schema),
254 }
255 }
256}
257
258#[derive(Clone, Debug, Serialize, Deserialize, PartialEq, Eq, Hash)]
263pub struct PartialSchemaName {
264 pub database: Option<String>,
265 pub schema: String,
266}
267
268impl fmt::Display for PartialSchemaName {
269 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
270 if let Some(database) = &self.database {
271 write!(f, "{}.", database)?;
272 }
273 write!(f, "{}", self.schema)
274 }
275}
276
277#[derive(
279 Debug,
280 Clone,
281 Eq,
282 PartialEq,
283 Ord,
284 PartialOrd,
285 Hash,
286 Serialize,
287 Deserialize
288)]
289pub enum RawDatabaseSpecifier {
290 Ambient,
293 Name(String),
295}
296
297impl fmt::Display for RawDatabaseSpecifier {
298 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
299 match self {
300 Self::Ambient => f.write_str("<none>"),
301 Self::Name(name) => f.write_str(name),
302 }
303 }
304}
305
306impl From<Option<String>> for RawDatabaseSpecifier {
307 fn from(s: Option<String>) -> RawDatabaseSpecifier {
308 match s {
309 None => Self::Ambient,
310 Some(name) => Self::Name(name),
311 }
312 }
313}
314
315#[derive(
317 Debug,
318 Clone,
319 Copy,
320 Eq,
321 PartialEq,
322 Hash,
323 PartialOrd,
324 Ord,
325 Serialize,
326 Deserialize,
327 Arbitrary
328)]
329pub enum ResolvedDatabaseSpecifier {
330 Ambient,
333 Id(DatabaseId),
335}
336
337impl ResolvedDatabaseSpecifier {
338 pub fn id(&self) -> Option<DatabaseId> {
339 match self {
340 ResolvedDatabaseSpecifier::Ambient => None,
341 ResolvedDatabaseSpecifier::Id(id) => Some(*id),
342 }
343 }
344}
345
346impl fmt::Display for ResolvedDatabaseSpecifier {
347 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
348 match self {
349 Self::Ambient => f.write_str("<none>"),
350 Self::Id(id) => write!(f, "{}", id),
351 }
352 }
353}
354
355impl AstDisplay for ResolvedDatabaseSpecifier {
356 fn fmt<W: fmt::Write>(&self, f: &mut AstFormatter<W>) {
357 f.write_str(format!("{}", self));
358 }
359}
360
361impl From<DatabaseId> for ResolvedDatabaseSpecifier {
362 fn from(id: DatabaseId) -> Self {
363 Self::Id(id)
364 }
365}
366
367impl From<Option<DatabaseId>> for ResolvedDatabaseSpecifier {
368 fn from(id: Option<DatabaseId>) -> Self {
369 match id {
370 Some(id) => Self::Id(id),
371 None => Self::Ambient,
372 }
373 }
374}
375
376#[derive(
384 Debug,
385 Clone,
386 Copy,
387 Eq,
388 PartialEq,
389 Hash,
390 PartialOrd,
391 Ord,
392 Serialize,
393 Deserialize
394)]
395pub enum SchemaSpecifier {
396 Temporary,
398 Id(SchemaId),
400}
401
402impl SchemaSpecifier {
403 const TEMPORARY_SCHEMA_ID: u64 = 0;
404
405 pub fn is_system(&self) -> bool {
406 match self {
407 SchemaSpecifier::Temporary => false,
408 SchemaSpecifier::Id(id) => id.is_system(),
409 }
410 }
411
412 pub fn is_user(&self) -> bool {
413 match self {
414 SchemaSpecifier::Temporary => true,
415 SchemaSpecifier::Id(id) => id.is_user(),
416 }
417 }
418
419 pub fn is_temporary(&self) -> bool {
420 matches!(self, SchemaSpecifier::Temporary)
421 }
422}
423
424impl fmt::Display for SchemaSpecifier {
425 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
426 match self {
427 Self::Temporary => f.write_str(format!("{}", Self::TEMPORARY_SCHEMA_ID).as_str()),
428 Self::Id(id) => write!(f, "{}", id),
429 }
430 }
431}
432
433impl AstDisplay for SchemaSpecifier {
434 fn fmt<W: fmt::Write>(&self, f: &mut AstFormatter<W>) {
435 f.write_str(format!("{}", self));
436 }
437}
438
439impl From<SchemaId> for SchemaSpecifier {
440 fn from(id: SchemaId) -> SchemaSpecifier {
441 match id {
442 SchemaId::User(id) if id == SchemaSpecifier::TEMPORARY_SCHEMA_ID => {
443 SchemaSpecifier::Temporary
444 }
445 schema_id => SchemaSpecifier::Id(schema_id),
446 }
447 }
448}
449
450impl From<&SchemaSpecifier> for SchemaId {
451 fn from(schema_spec: &SchemaSpecifier) -> Self {
452 match schema_spec {
453 SchemaSpecifier::Temporary => SchemaId::User(SchemaSpecifier::TEMPORARY_SCHEMA_ID),
454 SchemaSpecifier::Id(id) => id.clone(),
455 }
456 }
457}
458
459impl From<SchemaSpecifier> for SchemaId {
460 fn from(schema_spec: SchemaSpecifier) -> Self {
461 match schema_spec {
462 SchemaSpecifier::Temporary => SchemaId::User(SchemaSpecifier::TEMPORARY_SCHEMA_ID),
463 SchemaSpecifier::Id(id) => id,
464 }
465 }
466}
467
468#[derive(Debug, PartialEq, Eq, Hash, PartialOrd, Ord, Copy, Clone, Default)]
472pub struct Aug;
473
474#[derive(Debug, Clone, Copy, Hash, PartialEq, Eq, PartialOrd, Ord, Serialize)]
475pub struct ItemQualifiers {
476 pub database_spec: ResolvedDatabaseSpecifier,
477 pub schema_spec: SchemaSpecifier,
478}
479
480#[derive(Debug, Clone, Hash, PartialEq, Eq, PartialOrd, Ord)]
481pub enum ResolvedItemName {
482 Item {
483 id: CatalogItemId,
484 qualifiers: ItemQualifiers,
485 full_name: FullItemName,
486 print_id: bool,
490 version: RelationVersionSelector,
491 },
492 Cte {
493 id: LocalId,
494 name: String,
495 },
496 ContinualTask {
497 id: LocalId,
498 name: PartialItemName,
499 },
500 Error,
501}
502
503impl ResolvedItemName {
504 pub fn full_name_str(&self) -> String {
505 match self {
506 ResolvedItemName::Item { full_name, .. } => full_name.to_string(),
507 ResolvedItemName::Cte { name, .. } => name.clone(),
508 ResolvedItemName::ContinualTask { name, .. } => name.to_string(),
509 ResolvedItemName::Error => "error in name resolution".to_string(),
510 }
511 }
512
513 pub fn full_item_name(&self) -> &FullItemName {
514 match self {
515 ResolvedItemName::Item { full_name, .. } => full_name,
516 _ => panic!("cannot call object_full_name on non-object"),
517 }
518 }
519
520 pub fn item_id(&self) -> &CatalogItemId {
521 match self {
522 ResolvedItemName::Item { id, .. } => id,
523 _ => panic!("cannot call item_id on non-object"),
524 }
525 }
526
527 pub fn version(&self) -> &RelationVersionSelector {
528 match self {
529 ResolvedItemName::Item { version, .. } => version,
530 _ => panic!("cannot call version on non-object"),
531 }
532 }
533}
534
535impl AstDisplay for ResolvedItemName {
536 fn fmt<W: fmt::Write>(&self, f: &mut AstFormatter<W>) {
537 match self {
538 ResolvedItemName::Item {
539 id,
540 qualifiers: _,
541 full_name,
542 print_id,
543 version,
544 } => {
545 if *print_id {
546 f.write_str(format!("[{} AS ", id));
547 }
548 if let RawDatabaseSpecifier::Name(database) = &full_name.database {
549 f.write_node(&Ident::new_unchecked(database));
550 f.write_str(".");
551 }
552 f.write_node(&Ident::new_unchecked(&full_name.schema));
553 f.write_str(".");
554 f.write_node(&Ident::new_unchecked(&full_name.item));
555
556 if *print_id {
557 if let RelationVersionSelector::Specific(version) = version {
558 let version: Version = (*version).into();
559 f.write_str(" VERSION ");
560 f.write_node(&version);
561 }
562 }
563
564 if *print_id {
565 f.write_str("]");
566 }
567 }
568 ResolvedItemName::Cte { name, .. } => f.write_node(&Ident::new_unchecked(name)),
569 ResolvedItemName::ContinualTask { name, .. } => {
570 if let Some(database) = name.database.as_ref() {
573 f.write_node(&Ident::new_unchecked(database));
574 f.write_str(".");
575 }
576 if let Some(schema) = name.schema.as_ref() {
577 f.write_node(&Ident::new_unchecked(schema));
578 f.write_str(".");
579 }
580 f.write_node(&Ident::new_unchecked(&name.item));
581 }
582 ResolvedItemName::Error => {}
583 }
584 }
585}
586
587impl std::fmt::Display for ResolvedItemName {
588 fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
589 f.write_str(self.to_ast_string_simple().as_str())
590 }
591}
592
593#[derive(Debug, Clone, Hash, PartialEq, Eq, PartialOrd, Ord)]
594pub enum ResolvedColumnReference {
595 Column { name: ColumnName, index: usize },
596 Error,
597}
598
599impl AstDisplay for ResolvedColumnReference {
600 fn fmt<W: fmt::Write>(&self, f: &mut AstFormatter<W>) {
601 match self {
602 ResolvedColumnReference::Column { name, .. } => {
603 f.write_node(&Ident::new_unchecked(name.as_str()));
604 }
605 ResolvedColumnReference::Error => {}
606 }
607 }
608}
609
610impl std::fmt::Display for ResolvedColumnReference {
611 fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
612 f.write_str(self.to_ast_string_simple().as_str())
613 }
614}
615
616#[derive(Debug, Clone, Hash, PartialEq, Eq, PartialOrd, Ord)]
617pub enum ResolvedSchemaName {
618 Schema {
619 database_spec: ResolvedDatabaseSpecifier,
620 schema_spec: SchemaSpecifier,
621 full_name: FullSchemaName,
622 },
623 Error,
624}
625
626impl ResolvedSchemaName {
627 pub fn database_spec(&self) -> &ResolvedDatabaseSpecifier {
629 match self {
630 ResolvedSchemaName::Schema { database_spec, .. } => database_spec,
631 ResolvedSchemaName::Error => {
632 unreachable!("should have been handled by name resolution")
633 }
634 }
635 }
636
637 pub fn schema_spec(&self) -> &SchemaSpecifier {
639 match self {
640 ResolvedSchemaName::Schema { schema_spec, .. } => schema_spec,
641 ResolvedSchemaName::Error => {
642 unreachable!("should have been handled by name resolution")
643 }
644 }
645 }
646}
647
648impl AstDisplay for ResolvedSchemaName {
649 fn fmt<W: fmt::Write>(&self, f: &mut AstFormatter<W>) {
650 match self {
651 ResolvedSchemaName::Schema { full_name, .. } => {
652 if let RawDatabaseSpecifier::Name(database) = &full_name.database {
653 f.write_node(&Ident::new_unchecked(database));
654 f.write_str(".");
655 }
656 f.write_node(&Ident::new_unchecked(&full_name.schema));
657 }
658 ResolvedSchemaName::Error => {}
659 }
660 }
661}
662
663#[derive(Debug, Clone, Hash, PartialEq, Eq, PartialOrd, Ord)]
664pub enum ResolvedDatabaseName {
665 Database { id: DatabaseId, name: String },
666 Error,
667}
668
669impl ResolvedDatabaseName {
670 pub fn database_id(&self) -> &DatabaseId {
672 match self {
673 ResolvedDatabaseName::Database { id, .. } => id,
674 ResolvedDatabaseName::Error => {
675 unreachable!("should have been handled by name resolution")
676 }
677 }
678 }
679}
680
681impl AstDisplay for ResolvedDatabaseName {
682 fn fmt<W: fmt::Write>(&self, f: &mut AstFormatter<W>) {
683 match self {
684 ResolvedDatabaseName::Database { name, .. } => {
685 f.write_node(&Ident::new_unchecked(name))
686 }
687 ResolvedDatabaseName::Error => {}
688 }
689 }
690}
691
692#[derive(Debug, Clone, Hash, PartialEq, Eq, PartialOrd, Ord)]
693pub struct ResolvedClusterName {
694 pub id: ClusterId,
695 pub print_name: Option<String>,
702}
703
704impl AstDisplay for ResolvedClusterName {
705 fn fmt<W: fmt::Write>(&self, f: &mut AstFormatter<W>) {
706 if let Some(print_name) = &self.print_name {
707 f.write_node(&Ident::new_unchecked(print_name))
708 } else {
709 f.write_str(format!("[{}]", self.id))
710 }
711 }
712}
713
714#[derive(Debug, Clone, Hash, PartialEq, Eq, PartialOrd, Ord)]
715pub struct ResolvedClusterReplicaName {
716 pub cluster_id: ClusterId,
717 pub replica_id: ReplicaId,
718}
719
720impl AstDisplay for ResolvedClusterReplicaName {
721 fn fmt<W: fmt::Write>(&self, f: &mut AstFormatter<W>) {
722 f.write_str(format!("[{}.{}]", self.cluster_id, self.replica_id))
723 }
724}
725
726#[derive(Debug, Clone, Hash, PartialEq, Eq, PartialOrd, Ord)]
727pub enum ResolvedDataType {
728 AnonymousList(Box<ResolvedDataType>),
729 AnonymousMap {
730 key_type: Box<ResolvedDataType>,
731 value_type: Box<ResolvedDataType>,
732 },
733 Named {
734 id: CatalogItemId,
735 qualifiers: ItemQualifiers,
736 full_name: FullItemName,
737 modifiers: Vec<i64>,
738 print_id: bool,
739 },
740 Error,
741}
742
743impl AstDisplay for ResolvedDataType {
744 fn fmt<W: fmt::Write>(&self, f: &mut AstFormatter<W>) {
745 match self {
746 ResolvedDataType::AnonymousList(element_type) => {
747 element_type.fmt(f);
748 f.write_str(" list");
749 }
750 ResolvedDataType::AnonymousMap {
751 key_type,
752 value_type,
753 } => {
754 f.write_str("map[");
755 key_type.fmt(f);
756 f.write_str("=>");
757 value_type.fmt(f);
758 f.write_str("]");
759 }
760 ResolvedDataType::Named {
761 id,
762 full_name,
763 modifiers,
764 print_id,
765 ..
766 } => {
767 if *print_id {
768 f.write_str(format!("[{} AS ", id));
769 }
770 if let RawDatabaseSpecifier::Name(database) = &full_name.database {
771 f.write_node(&Ident::new_unchecked(database));
772 f.write_str(".");
773 }
774
775 f.write_node(&Ident::new_unchecked(&full_name.schema));
776 f.write_str(".");
777
778 f.write_node(&Ident::new_unchecked(&full_name.item));
779 if *print_id {
780 f.write_str("]");
781 }
782 if modifiers.len() > 0 {
783 f.write_str("(");
784 f.write_node(&ast::display::comma_separated(modifiers));
785 f.write_str(")");
786 }
787 }
788 ResolvedDataType::Error => {}
789 }
790 }
791}
792
793impl ResolvedDataType {
794 pub fn unqualified_item_name(&self) -> String {
798 let mut res = String::new();
799 match self {
800 ResolvedDataType::AnonymousList(element_type) => {
801 res += &element_type.unqualified_item_name();
802 res += " list";
803 }
804 ResolvedDataType::AnonymousMap {
805 key_type,
806 value_type,
807 } => {
808 res += "map[";
809 res += &key_type.unqualified_item_name();
810 res += "=>";
811 res += &value_type.unqualified_item_name();
812 res += "]";
813 }
814 ResolvedDataType::Named { full_name, .. } => {
815 res += &full_name.item;
816 }
817 ResolvedDataType::Error => {}
818 }
819 res
820 }
821
822 pub fn human_readable_name(&self) -> String {
826 let mut res = String::new();
827 match self {
828 ResolvedDataType::AnonymousList(element_type) => {
829 res += &element_type.human_readable_name();
830 res += " list";
831 }
832 ResolvedDataType::AnonymousMap {
833 key_type,
834 value_type,
835 } => {
836 res += "map[";
837 res += &key_type.human_readable_name();
838 res += "=>";
839 res += &value_type.human_readable_name();
840 res += "]";
841 }
842 ResolvedDataType::Named { full_name, .. } => {
843 if let RawDatabaseSpecifier::Name(database) = &full_name.database {
844 res += database;
845 res += ".";
846 }
847 res += &full_name.schema;
848 res += ".";
849 res += &full_name.item;
850 }
851 ResolvedDataType::Error => {}
852 }
853 res
854 }
855}
856
857impl fmt::Display for ResolvedDataType {
858 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
859 f.write_str(self.to_ast_string_simple().as_str())
860 }
861}
862
863#[derive(Debug, Clone, Hash, PartialEq, Eq, PartialOrd, Ord)]
864pub struct ResolvedRoleName {
865 pub id: RoleId,
866 pub name: String,
867}
868
869impl AstDisplay for ResolvedRoleName {
870 fn fmt<W: fmt::Write>(&self, f: &mut AstFormatter<W>) {
871 f.write_str(format!("[{} AS {}]", self.id, self.name));
872 }
873}
874
875#[derive(Debug, Clone, Hash, PartialEq, Eq, PartialOrd, Ord)]
876pub struct ResolvedNetworkPolicyName {
877 pub id: NetworkPolicyId,
878 pub name: String,
879}
880
881impl AstDisplay for ResolvedNetworkPolicyName {
882 fn fmt<W: fmt::Write>(&self, f: &mut AstFormatter<W>) {
883 f.write_str(format!("[{} AS {}]", self.id, self.name));
884 }
885}
886
887#[derive(Debug, Clone, Hash, PartialEq, Eq, PartialOrd, Ord)]
888pub enum ResolvedObjectName {
889 Cluster(ResolvedClusterName),
890 ClusterReplica(ResolvedClusterReplicaName),
891 Database(ResolvedDatabaseName),
892 Schema(ResolvedSchemaName),
893 Role(ResolvedRoleName),
894 NetworkPolicy(ResolvedNetworkPolicyName),
895 Item(ResolvedItemName),
896}
897
898impl AstDisplay for ResolvedObjectName {
899 fn fmt<W: fmt::Write>(&self, f: &mut AstFormatter<W>) {
900 match self {
901 ResolvedObjectName::Cluster(n) => f.write_node(n),
902 ResolvedObjectName::ClusterReplica(n) => f.write_node(n),
903 ResolvedObjectName::Database(n) => f.write_node(n),
904 ResolvedObjectName::Schema(n) => f.write_node(n),
905 ResolvedObjectName::Role(n) => f.write_node(n),
906 ResolvedObjectName::Item(n) => f.write_node(n),
907 ResolvedObjectName::NetworkPolicy(n) => f.write_node(n),
908 }
909 }
910}
911
912impl AstInfo for Aug {
913 type NestedStatement = Statement<Raw>;
914 type ItemName = ResolvedItemName;
915 type ColumnReference = ResolvedColumnReference;
916 type SchemaName = ResolvedSchemaName;
917 type DatabaseName = ResolvedDatabaseName;
918 type ClusterName = ResolvedClusterName;
919 type DataType = ResolvedDataType;
920 type CteId = LocalId;
921 type RoleName = ResolvedRoleName;
922 type ObjectName = ResolvedObjectName;
923 type NetworkPolicyName = ResolvedNetworkPolicyName;
924}
925
926#[derive(
928 Clone,
929 Copy,
930 Debug,
931 Eq,
932 PartialEq,
933 Ord,
934 PartialOrd,
935 Hash,
936 Serialize,
937 Deserialize,
938 Arbitrary
939)]
940pub enum SchemaId {
941 User(u64),
942 System(u64),
943}
944
945impl SchemaId {
946 pub fn is_user(&self) -> bool {
947 matches!(self, SchemaId::User(_))
948 }
949
950 pub fn is_system(&self) -> bool {
951 matches!(self, SchemaId::System(_))
952 }
953}
954
955impl fmt::Display for SchemaId {
956 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
957 match self {
958 SchemaId::System(id) => write!(f, "s{}", id),
959 SchemaId::User(id) => write!(f, "u{}", id),
960 }
961 }
962}
963
964impl FromStr for SchemaId {
965 type Err = PlanError;
966
967 fn from_str(s: &str) -> Result<Self, Self::Err> {
968 if s.len() < 2 {
969 return Err(PlanError::Unstructured(format!(
970 "couldn't parse SchemaId {}",
971 s
972 )));
973 }
974 let val: u64 = s[1..].parse()?;
975 match s.chars().next() {
976 Some('s') => Ok(SchemaId::System(val)),
977 Some('u') => Ok(SchemaId::User(val)),
978 _ => Err(PlanError::Unstructured(format!(
979 "couldn't parse SchemaId {}",
980 s
981 ))),
982 }
983 }
984}
985
986#[derive(
988 Clone,
989 Copy,
990 Debug,
991 Eq,
992 PartialEq,
993 Ord,
994 PartialOrd,
995 Hash,
996 Serialize,
997 Deserialize,
998 Arbitrary
999)]
1000pub enum DatabaseId {
1001 User(u64),
1002 System(u64),
1003}
1004
1005impl DatabaseId {
1006 pub fn is_user(&self) -> bool {
1007 matches!(self, DatabaseId::User(_))
1008 }
1009
1010 pub fn is_system(&self) -> bool {
1011 matches!(self, DatabaseId::System(_))
1012 }
1013}
1014
1015impl fmt::Display for DatabaseId {
1016 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
1017 match self {
1018 DatabaseId::System(id) => write!(f, "s{}", id),
1019 DatabaseId::User(id) => write!(f, "u{}", id),
1020 }
1021 }
1022}
1023
1024impl FromStr for DatabaseId {
1025 type Err = PlanError;
1026
1027 fn from_str(s: &str) -> Result<Self, Self::Err> {
1028 if s.len() < 2 {
1029 return Err(PlanError::Unstructured(format!(
1030 "couldn't parse DatabaseId {}",
1031 s
1032 )));
1033 }
1034 let val: u64 = s[1..].parse()?;
1035 match s.chars().next() {
1036 Some('s') => Ok(DatabaseId::System(val)),
1037 Some('u') => Ok(DatabaseId::User(val)),
1038 _ => Err(PlanError::Unstructured(format!(
1039 "couldn't parse DatabaseId {}",
1040 s
1041 ))),
1042 }
1043 }
1044}
1045
1046pub static PUBLIC_ROLE_NAME: LazyLock<&UncasedStr> = LazyLock::new(|| UncasedStr::new("PUBLIC"));
1047
1048#[derive(Clone, Debug, Eq, PartialEq, Ord, PartialOrd, Hash)]
1049pub enum ObjectId {
1050 Cluster(ClusterId),
1051 ClusterReplica((ClusterId, ReplicaId)),
1052 Database(DatabaseId),
1053 Schema((ResolvedDatabaseSpecifier, SchemaSpecifier)),
1054 Role(RoleId),
1055 Item(CatalogItemId),
1056 NetworkPolicy(NetworkPolicyId),
1057}
1058
1059impl ObjectId {
1060 pub fn unwrap_cluster_id(self) -> ClusterId {
1061 match self {
1062 ObjectId::Cluster(id) => id,
1063 _ => panic!("ObjectId::unwrap_cluster_id called on {self:?}"),
1064 }
1065 }
1066 pub fn unwrap_cluster_replica_id(self) -> (ClusterId, ReplicaId) {
1067 match self {
1068 ObjectId::ClusterReplica(id) => id,
1069 _ => panic!("ObjectId::unwrap_cluster_replica_id called on {self:?}"),
1070 }
1071 }
1072 pub fn unwrap_database_id(self) -> DatabaseId {
1073 match self {
1074 ObjectId::Database(id) => id,
1075 _ => panic!("ObjectId::unwrap_database_id called on {self:?}"),
1076 }
1077 }
1078 pub fn unwrap_schema_id(self) -> (ResolvedDatabaseSpecifier, SchemaSpecifier) {
1079 match self {
1080 ObjectId::Schema(id) => id,
1081 _ => panic!("ObjectId::unwrap_schema_id called on {self:?}"),
1082 }
1083 }
1084 pub fn unwrap_role_id(self) -> RoleId {
1085 match self {
1086 ObjectId::Role(id) => id,
1087 _ => panic!("ObjectId::unwrap_role_id called on {self:?}"),
1088 }
1089 }
1090 pub fn unwrap_item_id(self) -> CatalogItemId {
1091 match self {
1092 ObjectId::Item(id) => id,
1093 _ => panic!("ObjectId::unwrap_item_id called on {self:?}"),
1094 }
1095 }
1096
1097 pub fn is_system(&self) -> bool {
1098 match self {
1099 ObjectId::Cluster(cluster_id) => cluster_id.is_system(),
1100 ObjectId::ClusterReplica((_cluster_id, replica_id)) => replica_id.is_system(),
1101 ObjectId::Database(database_id) => database_id.is_system(),
1102 ObjectId::Schema((_database_id, schema_id)) => schema_id.is_system(),
1103 ObjectId::Role(role_id) => role_id.is_system(),
1104 ObjectId::Item(global_id) => global_id.is_system(),
1105 ObjectId::NetworkPolicy(network_policy_id) => network_policy_id.is_system(),
1106 }
1107 }
1108
1109 pub fn is_user(&self) -> bool {
1110 match self {
1111 ObjectId::Cluster(cluster_id) => cluster_id.is_user(),
1112 ObjectId::ClusterReplica((_cluster_id, replica_id)) => replica_id.is_user(),
1113 ObjectId::Database(database_id) => database_id.is_user(),
1114 ObjectId::Schema((_database_id, schema_id)) => schema_id.is_user(),
1115 ObjectId::Role(role_id) => role_id.is_user(),
1116 ObjectId::Item(global_id) => global_id.is_user(),
1117 ObjectId::NetworkPolicy(network_policy_id) => network_policy_id.is_user(),
1118 }
1119 }
1120}
1121
1122impl fmt::Display for ObjectId {
1123 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
1124 match self {
1125 ObjectId::Cluster(cluster_id) => write!(f, "C{cluster_id}"),
1126 ObjectId::ClusterReplica((cluster_id, replica_id)) => {
1127 write!(f, "CR{cluster_id}.{replica_id}")
1128 }
1129 ObjectId::Database(database_id) => write!(f, "D{database_id}"),
1130 ObjectId::Schema((database_spec, schema_spec)) => {
1131 let database_id = match database_spec {
1132 ResolvedDatabaseSpecifier::Ambient => "".to_string(),
1133 ResolvedDatabaseSpecifier::Id(database_id) => format!("{database_id}."),
1134 };
1135 write!(f, "S{database_id}{schema_spec}")
1136 }
1137 ObjectId::Role(role_id) => write!(f, "R{role_id}"),
1138 ObjectId::Item(item_id) => write!(f, "I{item_id}"),
1139 ObjectId::NetworkPolicy(network_policy_id) => write!(f, "NP{network_policy_id}"),
1140 }
1141 }
1142}
1143
1144impl TryFrom<ResolvedObjectName> for ObjectId {
1145 type Error = anyhow::Error;
1146
1147 fn try_from(name: ResolvedObjectName) -> Result<ObjectId, Self::Error> {
1148 match name {
1149 ResolvedObjectName::Cluster(name) => Ok(ObjectId::Cluster(name.id)),
1150 ResolvedObjectName::ClusterReplica(name) => {
1151 Ok(ObjectId::ClusterReplica((name.cluster_id, name.replica_id)))
1152 }
1153 ResolvedObjectName::Database(name) => Ok(ObjectId::Database(*name.database_id())),
1154 ResolvedObjectName::Schema(name) => match name {
1155 ResolvedSchemaName::Schema {
1156 database_spec,
1157 schema_spec,
1158 ..
1159 } => Ok(ObjectId::Schema((database_spec, schema_spec))),
1160 ResolvedSchemaName::Error => Err(anyhow!("error in name resolution")),
1161 },
1162 ResolvedObjectName::Role(name) => Ok(ObjectId::Role(name.id)),
1163 ResolvedObjectName::Item(name) => match name {
1164 ResolvedItemName::Item { id, .. } => Ok(ObjectId::Item(id)),
1165 ResolvedItemName::Cte { .. } => Err(anyhow!("CTE does not correspond to object")),
1166 ResolvedItemName::ContinualTask { .. } => {
1167 Err(anyhow!("ContinualTask does not correspond to object"))
1168 }
1169 ResolvedItemName::Error => Err(anyhow!("error in name resolution")),
1170 },
1171 ResolvedObjectName::NetworkPolicy(name) => Ok(ObjectId::NetworkPolicy(name.id)),
1172 }
1173 }
1174}
1175
1176impl From<ClusterId> for ObjectId {
1177 fn from(id: ClusterId) -> Self {
1178 ObjectId::Cluster(id)
1179 }
1180}
1181
1182impl From<&ClusterId> for ObjectId {
1183 fn from(id: &ClusterId) -> Self {
1184 ObjectId::Cluster(*id)
1185 }
1186}
1187
1188impl From<(ClusterId, ReplicaId)> for ObjectId {
1189 fn from(id: (ClusterId, ReplicaId)) -> Self {
1190 ObjectId::ClusterReplica(id)
1191 }
1192}
1193
1194impl From<&(ClusterId, ReplicaId)> for ObjectId {
1195 fn from(id: &(ClusterId, ReplicaId)) -> Self {
1196 ObjectId::ClusterReplica(*id)
1197 }
1198}
1199
1200impl From<DatabaseId> for ObjectId {
1201 fn from(id: DatabaseId) -> Self {
1202 ObjectId::Database(id)
1203 }
1204}
1205
1206impl From<&DatabaseId> for ObjectId {
1207 fn from(id: &DatabaseId) -> Self {
1208 ObjectId::Database(*id)
1209 }
1210}
1211
1212impl From<ItemQualifiers> for ObjectId {
1213 fn from(qualifiers: ItemQualifiers) -> Self {
1214 ObjectId::Schema((qualifiers.database_spec, qualifiers.schema_spec))
1215 }
1216}
1217
1218impl From<&ItemQualifiers> for ObjectId {
1219 fn from(qualifiers: &ItemQualifiers) -> Self {
1220 ObjectId::Schema((qualifiers.database_spec, qualifiers.schema_spec))
1221 }
1222}
1223
1224impl From<(ResolvedDatabaseSpecifier, SchemaSpecifier)> for ObjectId {
1225 fn from(id: (ResolvedDatabaseSpecifier, SchemaSpecifier)) -> Self {
1226 ObjectId::Schema(id)
1227 }
1228}
1229
1230impl From<&(ResolvedDatabaseSpecifier, SchemaSpecifier)> for ObjectId {
1231 fn from(id: &(ResolvedDatabaseSpecifier, SchemaSpecifier)) -> Self {
1232 ObjectId::Schema(*id)
1233 }
1234}
1235
1236impl From<RoleId> for ObjectId {
1237 fn from(id: RoleId) -> Self {
1238 ObjectId::Role(id)
1239 }
1240}
1241
1242impl From<&RoleId> for ObjectId {
1243 fn from(id: &RoleId) -> Self {
1244 ObjectId::Role(*id)
1245 }
1246}
1247
1248impl From<CatalogItemId> for ObjectId {
1249 fn from(id: CatalogItemId) -> Self {
1250 ObjectId::Item(id)
1251 }
1252}
1253
1254impl From<&CatalogItemId> for ObjectId {
1255 fn from(id: &CatalogItemId) -> Self {
1256 ObjectId::Item(*id)
1257 }
1258}
1259
1260impl From<CommentObjectId> for ObjectId {
1261 fn from(id: CommentObjectId) -> Self {
1262 match id {
1263 CommentObjectId::Table(item_id)
1264 | CommentObjectId::View(item_id)
1265 | CommentObjectId::MaterializedView(item_id)
1266 | CommentObjectId::Source(item_id)
1267 | CommentObjectId::Sink(item_id)
1268 | CommentObjectId::Index(item_id)
1269 | CommentObjectId::Func(item_id)
1270 | CommentObjectId::Connection(item_id)
1271 | CommentObjectId::Type(item_id)
1272 | CommentObjectId::Secret(item_id)
1273 | CommentObjectId::ContinualTask(item_id) => ObjectId::Item(item_id),
1274 CommentObjectId::Role(id) => ObjectId::Role(id),
1275 CommentObjectId::Database(id) => ObjectId::Database(id),
1276 CommentObjectId::Schema(id) => ObjectId::Schema(id),
1277 CommentObjectId::Cluster(id) => ObjectId::Cluster(id),
1278 CommentObjectId::ClusterReplica(id) => ObjectId::ClusterReplica(id),
1279 CommentObjectId::NetworkPolicy(id) => ObjectId::NetworkPolicy(id),
1280 }
1281 }
1282}
1283
1284#[derive(Clone, Debug, Eq, PartialEq, Ord, PartialOrd, Hash)]
1285pub enum SystemObjectId {
1286 Object(ObjectId),
1288 System,
1290}
1291
1292impl SystemObjectId {
1293 pub fn object_id(&self) -> Option<&ObjectId> {
1294 match self {
1295 SystemObjectId::Object(object_id) => Some(object_id),
1296 SystemObjectId::System => None,
1297 }
1298 }
1299
1300 pub fn is_system(&self) -> bool {
1301 matches!(self, SystemObjectId::System)
1302 }
1303}
1304
1305impl From<ObjectId> for SystemObjectId {
1306 fn from(id: ObjectId) -> Self {
1307 SystemObjectId::Object(id)
1308 }
1309}
1310
1311#[derive(Copy, Clone, Debug, Eq, PartialEq, Ord, PartialOrd, Hash, Serialize)]
1317pub enum CommentObjectId {
1318 Table(CatalogItemId),
1319 View(CatalogItemId),
1320 MaterializedView(CatalogItemId),
1321 Source(CatalogItemId),
1322 Sink(CatalogItemId),
1323 Index(CatalogItemId),
1324 Func(CatalogItemId),
1325 Connection(CatalogItemId),
1326 Type(CatalogItemId),
1327 Secret(CatalogItemId),
1328 ContinualTask(CatalogItemId),
1329 Role(RoleId),
1330 Database(DatabaseId),
1331 Schema((ResolvedDatabaseSpecifier, SchemaSpecifier)),
1332 Cluster(ClusterId),
1333 ClusterReplica((ClusterId, ReplicaId)),
1334 NetworkPolicy(NetworkPolicyId),
1335}
1336
1337#[derive(Debug, Clone, Copy)]
1348struct ItemResolutionConfig {
1349 types: bool,
1350 functions: bool,
1351 relations: bool,
1352}
1353
1354#[derive(Debug)]
1355pub struct NameResolver<'a> {
1356 catalog: &'a dyn SessionCatalog,
1357 ctes: BTreeMap<String, LocalId>,
1358 continual_task: Option<(PartialItemName, LocalId)>,
1359 status: Result<(), PlanError>,
1360 ids: BTreeMap<CatalogItemId, BTreeSet<GlobalId>>,
1361}
1362
1363impl<'a> NameResolver<'a> {
1364 fn new(catalog: &'a dyn SessionCatalog) -> NameResolver<'a> {
1365 NameResolver {
1366 catalog,
1367 ctes: BTreeMap::new(),
1368 continual_task: None,
1369 status: Ok(()),
1370 ids: BTreeMap::new(),
1371 }
1372 }
1373
1374 fn resolve_data_type(&mut self, data_type: RawDataType) -> Result<ResolvedDataType, PlanError> {
1375 match data_type {
1376 RawDataType::Array(elem_type) => {
1377 let name = elem_type.to_string();
1378 match self.resolve_data_type(*elem_type)? {
1379 ResolvedDataType::AnonymousList(_) | ResolvedDataType::AnonymousMap { .. } => {
1380 sql_bail!("type \"{}[]\" does not exist", name)
1381 }
1382 ResolvedDataType::Named { id, modifiers, .. } => {
1383 let element_item = self.catalog.get_item(&id);
1384 let array_item = match element_item.type_details() {
1385 Some(CatalogTypeDetails {
1386 array_id: Some(array_id),
1387 ..
1388 }) => self.catalog.get_item(array_id),
1389 Some(_) => sql_bail!("type \"{}[]\" does not exist", name),
1390 None => {
1391 sql_bail!(
1396 "internal error: {} does not refer to a type",
1397 self.catalog
1398 .resolve_full_name(element_item.name())
1399 .to_string()
1400 .quoted()
1401 );
1402 }
1403 };
1404 self.ids.insert(array_item.id(), BTreeSet::new());
1405 Ok(ResolvedDataType::Named {
1406 id: array_item.id(),
1407 qualifiers: array_item.name().qualifiers.clone(),
1408 full_name: self.catalog.resolve_full_name(array_item.name()),
1409 modifiers,
1410 print_id: true,
1411 })
1412 }
1413 ResolvedDataType::Error => sql_bail!("type \"{}[]\" does not exist", name),
1414 }
1415 }
1416 RawDataType::List(elem_type) => {
1417 let elem_type = self.resolve_data_type(*elem_type)?;
1418 Ok(ResolvedDataType::AnonymousList(Box::new(elem_type)))
1419 }
1420 RawDataType::Map {
1421 key_type,
1422 value_type,
1423 } => {
1424 let key_type = self.resolve_data_type(*key_type)?;
1425 let value_type = self.resolve_data_type(*value_type)?;
1426 Ok(ResolvedDataType::AnonymousMap {
1427 key_type: Box::new(key_type),
1428 value_type: Box::new(value_type),
1429 })
1430 }
1431 RawDataType::Other { name, typ_mod } => {
1432 let (full_name, item) = match name {
1433 RawItemName::Name(name) => {
1434 let name = normalize::unresolved_item_name(name)?;
1435 let item = self.catalog.resolve_type(&name)?;
1436 let full_name = self.catalog.resolve_full_name(item.name());
1437 (full_name, item)
1438 }
1439 RawItemName::Id(id, name, version) => {
1440 let id: CatalogItemId = id.parse()?;
1441 let item = self.catalog.get_item(&id);
1442 let full_name = normalize::full_name(name)?;
1443 assert_none!(version, "no support for versioning data types");
1444
1445 (full_name, item)
1446 }
1447 };
1448 self.ids.insert(item.id(), BTreeSet::new());
1449 if let Some(CatalogTypeDetails {
1454 typ: CatalogType::Array { element_reference },
1455 ..
1456 }) = item.type_details()
1457 {
1458 self.ids.insert(*element_reference, BTreeSet::new());
1459 }
1460 Ok(ResolvedDataType::Named {
1461 id: item.id(),
1462 qualifiers: item.name().qualifiers.clone(),
1463 full_name,
1464 modifiers: typ_mod,
1465 print_id: true,
1466 })
1467 }
1468 }
1469 }
1470
1471 fn resolve_item_name(
1472 &mut self,
1473 item_name: RawItemName,
1474 config: ItemResolutionConfig,
1475 ) -> ResolvedItemName {
1476 match item_name {
1477 RawItemName::Name(name) => self.resolve_item_name_name(name, config),
1478 RawItemName::Id(id, raw_name, version) => {
1479 self.resolve_item_name_id(id, raw_name, version)
1480 }
1481 }
1482 }
1483
1484 fn resolve_item_name_name(
1485 &mut self,
1486 raw_name: UnresolvedItemName,
1487 config: ItemResolutionConfig,
1488 ) -> ResolvedItemName {
1489 let raw_name = match normalize::unresolved_item_name(raw_name) {
1490 Ok(raw_name) => raw_name,
1491 Err(e) => {
1492 if self.status.is_ok() {
1493 self.status = Err(e);
1494 }
1495 return ResolvedItemName::Error;
1496 }
1497 };
1498
1499 let mut r: Result<&dyn CatalogItem, CatalogError> =
1500 Err(CatalogError::UnknownItem(raw_name.to_string()));
1501
1502 if r.is_err() && config.types {
1503 r = self.catalog.resolve_type(&raw_name);
1504 }
1505
1506 if r.is_err() && config.functions {
1507 r = self.catalog.resolve_function(&raw_name);
1508 }
1509
1510 if r.is_err() && config.relations {
1511 if raw_name.database.is_none() && raw_name.schema.is_none() {
1516 let norm_name = normalize::ident(Ident::new_unchecked(&raw_name.item));
1517 if let Some(id) = self.ctes.get(&norm_name) {
1518 return ResolvedItemName::Cte {
1519 id: *id,
1520 name: norm_name,
1521 };
1522 }
1523 }
1524 if let Some((ct_name, ct_id)) = self.continual_task.as_ref() {
1525 if *ct_name == raw_name {
1526 return ResolvedItemName::ContinualTask {
1527 id: *ct_id,
1528 name: raw_name,
1529 };
1530 }
1531 }
1532 r = self.catalog.resolve_item(&raw_name);
1533 };
1534
1535 match r {
1536 Ok(item) => {
1537 let item = item.at_version(RelationVersionSelector::Latest);
1539 self.ids
1540 .entry(item.id())
1541 .or_default()
1542 .insert(item.global_id());
1543 let print_id = !matches!(
1544 item.item_type(),
1545 CatalogItemType::Func | CatalogItemType::Type
1546 );
1547 let alter_table_enabled =
1548 self.catalog.system_vars().enable_alter_table_add_column();
1549 let version = match item.latest_version() {
1550 Some(v) if item.id().is_user() && alter_table_enabled => {
1552 RelationVersionSelector::Specific(v)
1553 }
1554 _ => RelationVersionSelector::Latest,
1555 };
1556
1557 ResolvedItemName::Item {
1558 id: item.id(),
1559 qualifiers: item.name().qualifiers.clone(),
1560 full_name: self.catalog.resolve_full_name(item.name()),
1561 print_id,
1562 version,
1563 }
1564 }
1565 Err(mut e) => {
1566 if self.status.is_ok() {
1567 match &mut e {
1568 CatalogError::UnknownFunction {
1569 name: _,
1570 alternative,
1571 } => {
1572 if raw_name.database.is_none()
1575 && (raw_name.schema.is_none()
1576 || raw_name.schema.as_deref() == Some("pg_catalog")
1577 && raw_name.item.starts_with("json_"))
1578 {
1579 let jsonb_name = PartialItemName {
1580 item: raw_name.item.replace("json_", "jsonb_"),
1581 ..raw_name
1582 };
1583 if self.catalog.resolve_function(&jsonb_name).is_ok() {
1584 *alternative = Some(jsonb_name.to_string());
1585 }
1586 }
1587 }
1588 _ => (),
1589 }
1590
1591 self.status = Err(e.into());
1592 }
1593 ResolvedItemName::Error
1594 }
1595 }
1596 }
1597
1598 fn resolve_item_name_id(
1599 &mut self,
1600 id: String,
1601 raw_name: UnresolvedItemName,
1602 version: Option<Version>,
1603 ) -> ResolvedItemName {
1604 let id: CatalogItemId = match id.parse() {
1605 Ok(id) => id,
1606 Err(e) => {
1607 if self.status.is_ok() {
1608 self.status = Err(e.into());
1609 }
1610 return ResolvedItemName::Error;
1611 }
1612 };
1613 let item = match self.catalog.try_get_item(&id) {
1614 Some(item) => item,
1615 None => {
1616 if self.status.is_ok() {
1617 self.status = Err(PlanError::InvalidId(id));
1618 }
1619 return ResolvedItemName::Error;
1620 }
1621 };
1622 let alter_table_enabled = self.catalog.system_vars().enable_alter_table_add_column();
1623 let version = match version {
1624 None => match item.latest_version() {
1627 Some(v) if alter_table_enabled => RelationVersionSelector::Specific(v),
1629 _ => RelationVersionSelector::Latest,
1630 },
1631 Some(v) => {
1633 let specified_version = RelationVersion::from(v);
1634 match item.latest_version() {
1635 Some(latest) if latest >= specified_version => {
1636 RelationVersionSelector::Specific(specified_version)
1637 }
1638 _ => {
1639 if self.status.is_ok() {
1640 self.status = Err(PlanError::InvalidVersion {
1641 name: item.name().item.clone(),
1642 version: v.to_string(),
1643 })
1644 }
1645 return ResolvedItemName::Error;
1646 }
1647 }
1648 }
1649 };
1650 let item = item.at_version(version);
1651 self.ids
1652 .entry(item.id())
1653 .or_default()
1654 .insert(item.global_id());
1655
1656 let full_name = match normalize::full_name(raw_name) {
1657 Ok(full_name) => full_name,
1658 Err(e) => {
1659 if self.status.is_ok() {
1660 self.status = Err(e);
1661 }
1662 return ResolvedItemName::Error;
1663 }
1664 };
1665 ResolvedItemName::Item {
1666 id,
1667 qualifiers: item.name().qualifiers.clone(),
1668 full_name,
1669 print_id: true,
1670 version,
1671 }
1672 }
1673}
1674
1675impl<'a> Fold<Raw, Aug> for NameResolver<'a> {
1676 fn fold_nested_statement(
1677 &mut self,
1678 stmt: <Raw as AstInfo>::NestedStatement,
1679 ) -> <Aug as AstInfo>::NestedStatement {
1680 stmt
1681 }
1682
1683 fn fold_query(&mut self, q: Query<Raw>) -> Query<Aug> {
1684 let mut shadowed_cte_ids = Vec::new();
1687
1688 use itertools::Itertools;
1690 if let Some(ident) = q.ctes.bound_identifiers().duplicates().next() {
1691 self.status = Err(sql_err!(
1692 "WITH query name \"{}\" specified more than once",
1693 normalize::ident_ref(ident),
1694 ));
1695 }
1696
1697 let ctes: CteBlock<Aug> = match q.ctes {
1698 CteBlock::Simple(ctes) => {
1699 let mut result_ctes = Vec::<Cte<Aug>>::new();
1700
1701 let initial_id = self.ctes.len();
1702
1703 for (offset, cte) in ctes.into_iter().enumerate() {
1704 let cte_name = normalize::ident(cte.alias.name.clone());
1705 let local_id = LocalId::new(u64::cast_from(initial_id + offset));
1706
1707 result_ctes.push(Cte {
1708 alias: cte.alias,
1709 id: local_id,
1710 query: self.fold_query(cte.query),
1711 });
1712
1713 let shadowed_id = self.ctes.insert(cte_name.clone(), local_id);
1714 shadowed_cte_ids.push((cte_name, shadowed_id));
1715 }
1716 CteBlock::Simple(result_ctes)
1717 }
1718 CteBlock::MutuallyRecursive(MutRecBlock { options, ctes }) => {
1719 let mut result_ctes = Vec::<CteMutRec<Aug>>::new();
1720
1721 let initial_id = self.ctes.len();
1722
1723 for (offset, cte) in ctes.iter().enumerate() {
1725 let cte_name = normalize::ident(cte.name.clone());
1726 let local_id = LocalId::new(u64::cast_from(initial_id + offset));
1727 let shadowed_id = self.ctes.insert(cte_name.clone(), local_id);
1728 shadowed_cte_ids.push((cte_name, shadowed_id));
1729 }
1730
1731 for (offset, cte) in ctes.into_iter().enumerate() {
1732 let local_id = LocalId::new(u64::cast_from(initial_id + offset));
1733
1734 let columns = cte
1735 .columns
1736 .into_iter()
1737 .map(|column| self.fold_cte_mut_rec_column_def(column))
1738 .collect();
1739 let query = self.fold_query(cte.query);
1740 result_ctes.push(CteMutRec {
1741 name: cte.name,
1742 columns,
1743 id: local_id,
1744 query,
1745 });
1746 }
1747 CteBlock::MutuallyRecursive(MutRecBlock {
1748 options: options
1749 .into_iter()
1750 .map(|option| self.fold_mut_rec_block_option(option))
1751 .collect(),
1752 ctes: result_ctes,
1753 })
1754 }
1755 };
1756
1757 let result = Query {
1758 ctes,
1759 body: mz_ore::stack::maybe_grow(|| self.fold_set_expr(q.body)),
1761 limit: q.limit.map(|l| self.fold_limit(l)),
1762 offset: q.offset.map(|l| self.fold_expr(l)),
1763 order_by: q
1764 .order_by
1765 .into_iter()
1766 .map(|c| self.fold_order_by_expr(c))
1767 .collect(),
1768 };
1769
1770 for (name, value) in shadowed_cte_ids.iter() {
1772 match value {
1773 Some(value) => {
1774 self.ctes.insert(name.to_string(), value.clone());
1775 }
1776 None => {
1777 self.ctes.remove(name);
1778 }
1779 };
1780 }
1781
1782 result
1783 }
1784
1785 fn fold_create_continual_task_statement(
1786 &mut self,
1787 stmt: CreateContinualTaskStatement<Raw>,
1788 ) -> CreateContinualTaskStatement<Aug> {
1789 match normalize::unresolved_item_name(stmt.name.name().clone()) {
1792 Ok(local_name) => {
1793 assert!(self.continual_task.is_none());
1794 self.continual_task = Some((local_name, LocalId::new(0)));
1797 }
1798 Err(err) => {
1799 if self.status.is_ok() {
1800 self.status = Err(err);
1801 }
1802 }
1803 };
1804 mz_sql_parser::ast::fold::fold_create_continual_task_statement(self, stmt)
1805 }
1806
1807 fn fold_cte_id(&mut self, _id: <Raw as AstInfo>::CteId) -> <Aug as AstInfo>::CteId {
1808 panic!("this should have been handled when walking the CTE");
1809 }
1810
1811 fn fold_item_name(
1812 &mut self,
1813 item_name: <Raw as AstInfo>::ItemName,
1814 ) -> <Aug as AstInfo>::ItemName {
1815 self.resolve_item_name(
1816 item_name,
1817 ItemResolutionConfig {
1820 functions: false,
1821 types: false,
1822 relations: true,
1823 },
1824 )
1825 }
1826
1827 fn fold_column_name(&mut self, column_name: ast::ColumnName<Raw>) -> ast::ColumnName<Aug> {
1828 let item_name = self.resolve_item_name(
1829 column_name.relation,
1830 ItemResolutionConfig {
1831 functions: false,
1832 types: true,
1833 relations: true,
1834 },
1835 );
1836
1837 match &item_name {
1838 ResolvedItemName::Item {
1839 id,
1840 full_name,
1841 version,
1842 qualifiers: _,
1843 print_id: _,
1844 } => {
1845 let item = self.catalog.get_item(id).at_version(*version);
1846 let name = normalize::column_name(column_name.column.clone());
1847
1848 let maybe_desc = match item.type_details() {
1849 Some(details) => match details.typ.desc(self.catalog) {
1850 Ok(desc) => desc.map(Cow::Owned),
1851 Err(e) => {
1852 if self.status.is_ok() {
1853 self.status = Err(e);
1854 }
1855 return ast::ColumnName {
1856 relation: ResolvedItemName::Error,
1857 column: ResolvedColumnReference::Error,
1858 };
1859 }
1860 },
1861 None => item.relation_desc(),
1862 };
1863 let Some(desc) = maybe_desc else {
1864 if self.status.is_ok() {
1865 self.status = Err(PlanError::ItemWithoutColumns {
1866 name: full_name.to_string(),
1867 item_type: item.item_type(),
1868 });
1869 }
1870 return ast::ColumnName {
1871 relation: ResolvedItemName::Error,
1872 column: ResolvedColumnReference::Error,
1873 };
1874 };
1875
1876 let Some((index, _typ)) = desc.get_by_name(&name) else {
1877 if self.status.is_ok() {
1878 let similar = desc.iter_similar_names(&name).cloned().collect();
1879 self.status = Err(PlanError::UnknownColumn {
1880 table: Some(full_name.clone().into()),
1881 column: name,
1882 similar,
1883 })
1884 }
1885 return ast::ColumnName {
1886 relation: ResolvedItemName::Error,
1887 column: ResolvedColumnReference::Error,
1888 };
1889 };
1890
1891 ast::ColumnName {
1892 relation: item_name,
1893 column: ResolvedColumnReference::Column { name, index },
1894 }
1895 }
1896 ResolvedItemName::Cte { .. }
1897 | ResolvedItemName::ContinualTask { .. }
1898 | ResolvedItemName::Error => ast::ColumnName {
1899 relation: ResolvedItemName::Error,
1900 column: ResolvedColumnReference::Error,
1901 },
1902 }
1903 }
1904
1905 fn fold_column_reference(
1906 &mut self,
1907 _node: <Raw as AstInfo>::ColumnReference,
1908 ) -> <Aug as AstInfo>::ColumnReference {
1909 ResolvedColumnReference::Error
1911 }
1912
1913 fn fold_data_type(
1914 &mut self,
1915 data_type: <Raw as AstInfo>::DataType,
1916 ) -> <Aug as AstInfo>::DataType {
1917 match self.resolve_data_type(data_type) {
1918 Ok(data_type) => data_type,
1919 Err(e) => {
1920 if self.status.is_ok() {
1921 self.status = Err(e);
1922 }
1923 ResolvedDataType::Error
1924 }
1925 }
1926 }
1927
1928 fn fold_schema_name(
1929 &mut self,
1930 name: <Raw as AstInfo>::SchemaName,
1931 ) -> <Aug as AstInfo>::SchemaName {
1932 let norm_name = match normalize::unresolved_schema_name(name) {
1933 Ok(norm_name) => norm_name,
1934 Err(e) => {
1935 if self.status.is_ok() {
1936 self.status = Err(e);
1937 }
1938 return ResolvedSchemaName::Error;
1939 }
1940 };
1941
1942 if norm_name.database.is_none() && norm_name.schema == mz_repr::namespaces::MZ_TEMP_SCHEMA {
1946 return ResolvedSchemaName::Schema {
1947 database_spec: ResolvedDatabaseSpecifier::Ambient,
1948 schema_spec: SchemaSpecifier::Temporary,
1949 full_name: FullSchemaName {
1950 database: RawDatabaseSpecifier::Ambient,
1951 schema: mz_repr::namespaces::MZ_TEMP_SCHEMA.to_string(),
1952 },
1953 };
1954 }
1955
1956 match self
1957 .catalog
1958 .resolve_schema(norm_name.database.as_deref(), norm_name.schema.as_str())
1959 {
1960 Ok(schema) => {
1961 let raw_database_spec = match schema.database() {
1962 ResolvedDatabaseSpecifier::Ambient => RawDatabaseSpecifier::Ambient,
1963 ResolvedDatabaseSpecifier::Id(id) => {
1964 RawDatabaseSpecifier::Name(self.catalog.get_database(id).name().to_string())
1965 }
1966 };
1967 ResolvedSchemaName::Schema {
1968 database_spec: schema.database().clone(),
1969 schema_spec: schema.id().clone(),
1970 full_name: FullSchemaName {
1971 database: raw_database_spec,
1972 schema: schema.name().schema.clone(),
1973 },
1974 }
1975 }
1976 Err(e) => {
1977 if self.status.is_ok() {
1978 self.status = Err(e.into());
1979 }
1980 ResolvedSchemaName::Error
1981 }
1982 }
1983 }
1984
1985 fn fold_database_name(
1986 &mut self,
1987 database_name: <Raw as AstInfo>::DatabaseName,
1988 ) -> <Aug as AstInfo>::DatabaseName {
1989 match self.catalog.resolve_database(database_name.0.as_str()) {
1990 Ok(database) => ResolvedDatabaseName::Database {
1991 id: database.id(),
1992 name: database_name.0.into_string(),
1993 },
1994 Err(e) => {
1995 if self.status.is_ok() {
1996 self.status = Err(e.into());
1997 }
1998 ResolvedDatabaseName::Error
1999 }
2000 }
2001 }
2002
2003 fn fold_cluster_name(
2004 &mut self,
2005 cluster_name: <Raw as AstInfo>::ClusterName,
2006 ) -> <Aug as AstInfo>::ClusterName {
2007 match cluster_name {
2008 RawClusterName::Unresolved(ident) => {
2009 match self.catalog.resolve_cluster(Some(ident.as_str())) {
2010 Ok(cluster) => ResolvedClusterName {
2011 id: cluster.id(),
2012 print_name: None,
2013 },
2014 Err(e) => {
2015 self.status = Err(e.into());
2016 ResolvedClusterName {
2017 id: ClusterId::system(0).expect("0 is a valid ID"),
2020 print_name: None,
2021 }
2022 }
2023 }
2024 }
2025 RawClusterName::Resolved(ident) => match ident.parse() {
2026 Ok(id) => ResolvedClusterName {
2027 id,
2028 print_name: None,
2029 },
2030 Err(e) => {
2031 self.status = Err(e.into());
2032 ResolvedClusterName {
2033 id: ClusterId::system(0).expect("0 is a valid ID"),
2036 print_name: None,
2037 }
2038 }
2039 },
2040 }
2041 }
2042
2043 fn fold_with_option_value(
2044 &mut self,
2045 node: mz_sql_parser::ast::WithOptionValue<Raw>,
2046 ) -> mz_sql_parser::ast::WithOptionValue<Aug> {
2047 use mz_sql_parser::ast::WithOptionValue::*;
2048 match node {
2049 Sequence(vs) => Sequence(
2050 vs.into_iter()
2051 .map(|v| self.fold_with_option_value(v))
2052 .collect(),
2053 ),
2054 Map(map) => Map(map
2055 .into_iter()
2056 .map(|(k, v)| (k, self.fold_with_option_value(v)))
2057 .collect()),
2058 Value(v) => Value(self.fold_value(v)),
2059 DataType(dt) => DataType(self.fold_data_type(dt)),
2060 Secret(secret) => {
2061 let item_name = self.fold_item_name(secret);
2062 match &item_name {
2063 ResolvedItemName::Item { id, .. } => {
2064 let item = self.catalog.get_item(id);
2065 if item.item_type() != CatalogItemType::Secret {
2066 self.status =
2067 Err(PlanError::InvalidSecret(Box::new(item_name.clone())));
2068 }
2069 }
2070 ResolvedItemName::Cte { .. } | ResolvedItemName::ContinualTask { .. } => {
2071 self.status = Err(PlanError::InvalidSecret(Box::new(item_name.clone())));
2072 }
2073 ResolvedItemName::Error => {}
2074 }
2075 Secret(item_name)
2076 }
2077 Item(obj) => {
2078 let item_name = self.fold_item_name(obj);
2079 match &item_name {
2080 ResolvedItemName::Item { .. } => {}
2081 ResolvedItemName::Cte { .. } | ResolvedItemName::ContinualTask { .. } => {
2082 self.status = Err(PlanError::InvalidObject(Box::new(item_name.clone())));
2083 }
2084 ResolvedItemName::Error => {}
2085 }
2086 Item(item_name)
2087 }
2088 UnresolvedItemName(name) => UnresolvedItemName(self.fold_unresolved_item_name(name)),
2089 Ident(name) => Ident(self.fold_ident(name)),
2090 Expr(e) => Expr(self.fold_expr(e)),
2091 ClusterReplicas(replicas) => ClusterReplicas(
2092 replicas
2093 .into_iter()
2094 .map(|r| self.fold_replica_definition(r))
2095 .collect(),
2096 ),
2097 ConnectionKafkaBroker(broker) => ConnectionKafkaBroker(self.fold_kafka_broker(broker)),
2098 ConnectionAwsPrivatelink(privatelink) => {
2099 ConnectionAwsPrivatelink(self.fold_connection_default_aws_privatelink(privatelink))
2100 }
2101 RetainHistoryFor(value) => RetainHistoryFor(self.fold_value(value)),
2102 Refresh(refresh) => Refresh(self.fold_refresh_option_value(refresh)),
2103 ClusterScheduleOptionValue(value) => ClusterScheduleOptionValue(value),
2104 ClusterAlterStrategy(value) => {
2105 ClusterAlterStrategy(self.fold_cluster_alter_option_value(value))
2106 }
2107 NetworkPolicyRules(rules) => NetworkPolicyRules(
2108 rules
2109 .into_iter()
2110 .map(|r| self.fold_network_policy_rule_definition(r))
2111 .collect(),
2112 ),
2113 }
2114 }
2115
2116 fn fold_role_name(&mut self, name: <Raw as AstInfo>::RoleName) -> <Aug as AstInfo>::RoleName {
2117 match self.catalog.resolve_role(name.as_str()) {
2118 Ok(role) => ResolvedRoleName {
2119 id: role.id(),
2120 name: role.name().to_string(),
2121 },
2122 Err(e) => {
2123 if self.status.is_ok() {
2124 self.status = Err(e.into());
2125 }
2126 ResolvedRoleName {
2128 id: RoleId::User(0),
2129 name: "".to_string(),
2130 }
2131 }
2132 }
2133 }
2134
2135 fn fold_network_policy_name(
2136 &mut self,
2137 name: <Raw as AstInfo>::NetworkPolicyName,
2138 ) -> <Aug as AstInfo>::NetworkPolicyName {
2139 match self.catalog.resolve_network_policy(&name.to_string()) {
2140 Ok(policy) => ResolvedNetworkPolicyName {
2141 id: policy.id(),
2142 name: policy.name().to_string(),
2143 },
2144 Err(e) => {
2145 if self.status.is_ok() {
2146 self.status = Err(e.into());
2147 }
2148 ResolvedNetworkPolicyName {
2150 id: NetworkPolicyId::User(0),
2151 name: "".to_string(),
2152 }
2153 }
2154 }
2155 }
2156
2157 fn fold_object_name(
2158 &mut self,
2159 name: <Raw as AstInfo>::ObjectName,
2160 ) -> <Aug as AstInfo>::ObjectName {
2161 match name {
2162 UnresolvedObjectName::Cluster(name) => ResolvedObjectName::Cluster(
2163 self.fold_cluster_name(RawClusterName::Unresolved(name)),
2164 ),
2165 UnresolvedObjectName::ClusterReplica(name) => {
2166 match self.catalog.resolve_cluster_replica(&name) {
2167 Ok(cluster_replica) => {
2168 ResolvedObjectName::ClusterReplica(ResolvedClusterReplicaName {
2169 cluster_id: cluster_replica.cluster_id(),
2170 replica_id: cluster_replica.replica_id(),
2171 })
2172 }
2173 Err(e) => {
2174 self.status = Err(e.into());
2175 ResolvedObjectName::ClusterReplica(ResolvedClusterReplicaName {
2176 cluster_id: ClusterId::system(0).expect("0 is a valid ID"),
2179 replica_id: ReplicaId::System(0),
2180 })
2181 }
2182 }
2183 }
2184 UnresolvedObjectName::Database(name) => {
2185 ResolvedObjectName::Database(self.fold_database_name(name))
2186 }
2187 UnresolvedObjectName::Schema(name) => {
2188 ResolvedObjectName::Schema(self.fold_schema_name(name))
2189 }
2190 UnresolvedObjectName::Role(name) => ResolvedObjectName::Role(self.fold_role_name(name)),
2191 UnresolvedObjectName::Item(name) => {
2192 ResolvedObjectName::Item(self.fold_item_name(RawItemName::Name(name)))
2193 }
2194 UnresolvedObjectName::NetworkPolicy(name) => ResolvedObjectName::NetworkPolicy(
2195 self.fold_network_policy_name(RawNetworkPolicyName::Unresolved(name)),
2196 ),
2197 }
2198 }
2199
2200 fn fold_function(
2201 &mut self,
2202 node: mz_sql_parser::ast::Function<Raw>,
2203 ) -> mz_sql_parser::ast::Function<Aug> {
2204 mz_ore::stack::maybe_grow(|| {
2207 mz_sql_parser::ast::Function {
2208 name: self.resolve_item_name(
2209 node.name,
2210 ItemResolutionConfig {
2213 functions: true,
2214 types: false,
2215 relations: false,
2216 },
2217 ),
2218 args: self.fold_function_args(node.args),
2219 filter: node.filter.map(|expr| Box::new(self.fold_expr(*expr))),
2220 over: node.over.map(|over| self.fold_window_spec(over)),
2221 distinct: node.distinct,
2222 }
2223 })
2224 }
2225
2226 fn fold_table_factor(
2227 &mut self,
2228 node: mz_sql_parser::ast::TableFactor<Raw>,
2229 ) -> mz_sql_parser::ast::TableFactor<Aug> {
2230 use mz_sql_parser::ast::TableFactor::*;
2231 match node {
2232 Table { name, alias } => Table {
2233 name: self.fold_item_name(name),
2234 alias: alias.map(|alias| self.fold_table_alias(alias)),
2235 },
2236 Function {
2237 function,
2238 alias,
2239 with_ordinality,
2240 } => {
2241 match &function.name {
2242 RawItemName::Name(name) => {
2243 if *name == UnresolvedItemName::unqualified(ident!("values"))
2244 && self.status.is_ok()
2245 {
2246 self.status = Err(PlanError::FromValueRequiresParen);
2247 }
2248 }
2249 _ => {}
2250 }
2251
2252 Function {
2253 function: self.fold_function(function),
2254 alias: alias.map(|alias| self.fold_table_alias(alias)),
2255 with_ordinality,
2256 }
2257 }
2258 RowsFrom {
2259 functions,
2260 alias,
2261 with_ordinality,
2262 } => RowsFrom {
2263 functions: functions
2264 .into_iter()
2265 .map(|f| self.fold_function(f))
2266 .collect(),
2267 alias: alias.map(|alias| self.fold_table_alias(alias)),
2268 with_ordinality,
2269 },
2270 Derived {
2271 lateral,
2272 subquery,
2273 alias,
2274 } => Derived {
2275 lateral,
2276 subquery: Box::new(self.fold_query(*subquery)),
2277 alias: alias.map(|alias| self.fold_table_alias(alias)),
2278 },
2279 NestedJoin { join, alias } => NestedJoin {
2280 join: Box::new(self.fold_table_with_joins(*join)),
2281 alias: alias.map(|alias| self.fold_table_alias(alias)),
2282 },
2283 }
2284 }
2285
2286 fn fold_grant_target_specification(
2287 &mut self,
2288 node: GrantTargetSpecification<Raw>,
2289 ) -> GrantTargetSpecification<Aug> {
2290 match node {
2291 GrantTargetSpecification::Object {
2292 object_type: ObjectType::Type,
2293 object_spec_inner: GrantTargetSpecificationInner::Objects { names },
2294 } => GrantTargetSpecification::Object {
2295 object_type: ObjectType::Type,
2296 object_spec_inner: GrantTargetSpecificationInner::Objects {
2297 names: names
2298 .into_iter()
2299 .map(|name| match name {
2300 UnresolvedObjectName::Item(name) => {
2301 ResolvedObjectName::Item(self.resolve_item_name_name(
2302 name,
2303 ItemResolutionConfig {
2306 functions: false,
2307 types: true,
2308 relations: false,
2309 },
2310 ))
2311 }
2312 _ => self.fold_object_name(name),
2313 })
2314 .collect(),
2315 },
2316 },
2317 _ => mz_sql_parser::ast::fold::fold_grant_target_specification(self, node),
2318 }
2319 }
2320
2321 fn fold_doc_on_identifier(&mut self, node: DocOnIdentifier<Raw>) -> DocOnIdentifier<Aug> {
2322 match node {
2323 DocOnIdentifier::Column(name) => DocOnIdentifier::Column(self.fold_column_name(name)),
2324 DocOnIdentifier::Type(name) => DocOnIdentifier::Type(self.resolve_item_name(
2325 name,
2326 ItemResolutionConfig {
2332 functions: false,
2333 types: true,
2334 relations: true,
2335 },
2336 )),
2337 }
2338 }
2339
2340 fn fold_expr(&mut self, node: Expr<Raw>) -> Expr<Aug> {
2341 mz_ore::stack::maybe_grow(|| mz_sql_parser::ast::fold::fold_expr(self, node))
2343 }
2344}
2345
2346#[mz_ore::instrument(target = "compiler", level = "trace", name = "ast_resolve_names")]
2348pub fn resolve<N>(
2349 catalog: &dyn SessionCatalog,
2350 node: N,
2351) -> Result<(N::Folded, ResolvedIds), PlanError>
2352where
2353 N: FoldNode<Raw, Aug>,
2354{
2355 let mut resolver = NameResolver::new(catalog);
2356 let result = node.fold(&mut resolver);
2357 resolver.status?;
2358 Ok((result, ResolvedIds::new(resolver.ids)))
2359}
2360
2361#[derive(Debug, Clone, Serialize, PartialEq, Eq)]
2366pub struct ResolvedIds {
2367 #[serde(serialize_with = "mz_ore::serde::map_key_to_string")]
2368 entries: BTreeMap<CatalogItemId, BTreeSet<GlobalId>>,
2369}
2370
2371impl ResolvedIds {
2372 fn new(entries: BTreeMap<CatalogItemId, BTreeSet<GlobalId>>) -> Self {
2373 ResolvedIds { entries }
2374 }
2375
2376 pub fn empty() -> Self {
2378 ResolvedIds {
2379 entries: BTreeMap::new(),
2380 }
2381 }
2382
2383 pub fn is_empty(&self) -> bool {
2385 self.entries.is_empty()
2386 }
2387
2388 pub fn collections(&self) -> impl Iterator<Item = &GlobalId> {
2390 self.entries.values().flat_map(|gids| gids.into_iter())
2391 }
2392
2393 pub fn items(&self) -> impl Iterator<Item = &CatalogItemId> {
2395 self.entries.keys()
2396 }
2397
2398 pub fn contains_item(&self, item: &CatalogItemId) -> bool {
2400 self.entries.contains_key(item)
2401 }
2402
2403 pub fn add_item(&mut self, item: CatalogItemId) {
2404 self.entries.insert(item, BTreeSet::new());
2405 }
2406
2407 pub fn remove_item(&mut self, item: &CatalogItemId) {
2408 self.entries.remove(item);
2409 }
2410
2411 pub fn retain_items<F>(&self, predicate: F) -> Self
2414 where
2415 F: Fn(&CatalogItemId) -> bool,
2416 {
2417 let mut new_ids = self.clone();
2418 new_ids
2419 .entries
2420 .retain(|item_id, _global_ids| predicate(item_id));
2421 new_ids
2422 }
2423}
2424
2425impl FromIterator<(CatalogItemId, GlobalId)> for ResolvedIds {
2426 fn from_iter<T: IntoIterator<Item = (CatalogItemId, GlobalId)>>(iter: T) -> Self {
2427 let mut ids = ResolvedIds::empty();
2428 ids.extend(iter);
2429 ids
2430 }
2431}
2432
2433impl Extend<(CatalogItemId, GlobalId)> for ResolvedIds {
2434 fn extend<T: IntoIterator<Item = (CatalogItemId, GlobalId)>>(&mut self, iter: T) {
2435 for (item_id, global_id) in iter {
2436 self.entries.entry(item_id).or_default().insert(global_id);
2437 }
2438 }
2439}
2440
2441#[derive(Debug, Clone, Serialize, PartialEq, Eq)]
2443pub struct DependencyIds(pub BTreeSet<CatalogItemId>);
2444
2445impl FromIterator<CatalogItemId> for DependencyIds {
2446 fn from_iter<T: IntoIterator<Item = CatalogItemId>>(iter: T) -> Self {
2447 DependencyIds(iter.into_iter().collect())
2448 }
2449}
2450
2451#[derive(Debug)]
2452pub struct DependencyVisitor<'a> {
2453 catalog: &'a dyn SessionCatalog,
2454 ids: BTreeMap<CatalogItemId, BTreeSet<GlobalId>>,
2455}
2456
2457impl<'a> DependencyVisitor<'a> {
2458 pub fn new(catalog: &'a dyn SessionCatalog) -> Self {
2459 DependencyVisitor {
2460 catalog,
2461 ids: Default::default(),
2462 }
2463 }
2464}
2465
2466impl<'a, 'ast> Visit<'ast, Aug> for DependencyVisitor<'a> {
2467 fn visit_item_name(&mut self, item_name: &'ast <Aug as AstInfo>::ItemName) {
2468 if let ResolvedItemName::Item { id, version, .. } = item_name {
2469 let global_ids = self.ids.entry(*id).or_default();
2470 if let Some(item) = self.catalog.try_get_item(id) {
2471 global_ids.insert(item.at_version(*version).global_id());
2472 }
2473 }
2474 }
2475
2476 fn visit_data_type(&mut self, data_type: &'ast <Aug as AstInfo>::DataType) {
2477 match data_type {
2478 ResolvedDataType::AnonymousList(data_type) => self.visit_data_type(data_type),
2479 ResolvedDataType::AnonymousMap {
2480 key_type,
2481 value_type,
2482 } => {
2483 self.visit_data_type(key_type);
2484 self.visit_data_type(value_type);
2485 }
2486 ResolvedDataType::Named { id, .. } => {
2487 self.ids.entry(*id).or_default();
2488 }
2489 ResolvedDataType::Error => {}
2490 }
2491 }
2492}
2493
2494pub fn visit_dependencies<'ast, N>(catalog: &dyn SessionCatalog, node: &'ast N) -> ResolvedIds
2495where
2496 N: VisitNode<'ast, Aug> + 'ast,
2497{
2498 let mut visitor = DependencyVisitor::new(catalog);
2499 node.visit(&mut visitor);
2500 ResolvedIds::new(visitor.ids)
2501}
2502
2503#[derive(Debug)]
2504pub struct ItemDependencyModifier<'a> {
2505 pub modified: bool,
2506 pub id_map: &'a BTreeMap<CatalogItemId, CatalogItemId>,
2507}
2508
2509impl<'ast, 'a> VisitMut<'ast, Raw> for ItemDependencyModifier<'a> {
2510 fn visit_item_name_mut(&mut self, item_name: &mut RawItemName) {
2511 if let RawItemName::Id(id, _, _) = item_name {
2512 let parsed_id = id.parse::<CatalogItemId>().unwrap();
2513 if let Some(new_id) = self.id_map.get(&parsed_id) {
2514 *id = new_id.to_string();
2515 self.modified = true;
2516 }
2517 }
2518 }
2519}
2520
2521pub fn modify_dependency_item_ids<'ast, N>(
2526 node: &'ast mut N,
2527 id_map: &BTreeMap<CatalogItemId, CatalogItemId>,
2528) -> bool
2529where
2530 N: VisitMutNode<'ast, Raw>,
2531{
2532 let mut modifier = ItemDependencyModifier {
2533 id_map,
2534 modified: false,
2535 };
2536 node.visit_mut(&mut modifier);
2537
2538 modifier.modified
2539}
2540
2541#[derive(Debug)]
2544pub struct NameSimplifier<'a> {
2545 pub catalog: &'a dyn SessionCatalog,
2546}
2547
2548impl<'ast, 'a> VisitMut<'ast, Aug> for NameSimplifier<'a> {
2549 fn visit_cluster_name_mut(&mut self, node: &mut ResolvedClusterName) {
2550 node.print_name = Some(self.catalog.get_cluster(node.id).name().into());
2551 }
2552
2553 fn visit_item_name_mut(&mut self, name: &mut ResolvedItemName) {
2554 if let ResolvedItemName::Item {
2555 id,
2556 full_name,
2557 print_id,
2558 ..
2559 } = name
2560 {
2561 let item = self.catalog.get_item(id);
2562 let catalog_full_name = self.catalog.resolve_full_name(item.name());
2563 if catalog_full_name == *full_name {
2564 *print_id = false;
2565 }
2566 }
2567 }
2568
2569 fn visit_data_type_mut(&mut self, name: &mut ResolvedDataType) {
2570 if let ResolvedDataType::Named {
2571 id,
2572 full_name,
2573 print_id,
2574 ..
2575 } = name
2576 {
2577 let item = self.catalog.get_item(id);
2578 let catalog_full_name = self.catalog.resolve_full_name(item.name());
2579 if catalog_full_name == *full_name {
2580 *print_id = false;
2581 }
2582 }
2583 }
2584}
2585
2586pub fn dependencies<'ast, N>(node: &'ast N) -> Result<BTreeSet<CatalogItemId>, anyhow::Error>
2591where
2592 N: VisitNode<'ast, Raw>,
2593{
2594 let mut visitor = IdDependencVisitor::default();
2595 node.visit(&mut visitor);
2596 match visitor.error {
2597 Some(error) => Err(error),
2598 None => Ok(visitor.ids),
2599 }
2600}
2601
2602#[derive(Debug, Default)]
2603struct IdDependencVisitor {
2604 ids: BTreeSet<CatalogItemId>,
2605 error: Option<anyhow::Error>,
2606}
2607
2608impl<'ast> Visit<'ast, Raw> for IdDependencVisitor {
2609 fn visit_item_name(&mut self, node: &'ast <Raw as AstInfo>::ItemName) {
2610 if self.error.is_some() {
2612 return;
2613 }
2614
2615 match node {
2616 RawItemName::Name(_) => (),
2618 RawItemName::Id(id, _name, _version) => match id.parse::<CatalogItemId>() {
2619 Ok(id) => {
2620 self.ids.insert(id);
2621 }
2622 Err(e) => {
2623 self.error = Some(e);
2624 }
2625 },
2626 }
2627 }
2628}