mz_sql/plan/
plan_utils.rs1use std::fmt;
13
14use mz_repr::RelationDesc;
15
16use crate::ast::Ident;
17use crate::catalog::SessionCatalog;
18use crate::normalize;
19use crate::plan::PlanError;
20use crate::plan::query::SelectOptionExtracted;
21
22pub fn maybe_rename_columns(
28 context: impl fmt::Display,
29 desc: &mut RelationDesc,
30 column_names: &[Ident],
31) -> Result<(), PlanError> {
32 if column_names.len() > desc.typ().column_types.len() {
33 return Err(column_count_mismatch(&context, desc, column_names));
34 }
35
36 for (i, name) in column_names.iter().enumerate() {
37 *desc.get_name_mut(i) = normalize::column_name(name.clone());
38 }
39
40 Ok(())
41}
42
43pub fn maybe_rename_columns_exact(
53 catalog: &dyn SessionCatalog,
54 context: impl fmt::Display,
55 desc: &mut RelationDesc,
56 column_names: &[Ident],
57) -> Result<(), PlanError> {
58 if !column_names.is_empty()
59 && column_names.len() < desc.typ().column_types.len()
60 && !catalog
61 .system_vars()
62 .unsafe_enable_incomplete_view_column_lists()
63 {
64 return Err(column_count_mismatch(&context, desc, column_names));
65 }
66 maybe_rename_columns(context, desc, column_names)
67}
68
69fn column_count_mismatch(
70 context: &dyn fmt::Display,
71 desc: &RelationDesc,
72 column_names: &[Ident],
73) -> PlanError {
74 sql_err!(
75 "{0} definition names {1} column{2}, but {0} has {3} column{4}",
76 context,
77 column_names.len(),
78 if column_names.len() == 1 { "" } else { "s" },
79 desc.typ().column_types.len(),
80 if desc.typ().column_types.len() == 1 {
81 ""
82 } else {
83 "s"
84 },
85 )
86}
87
88#[derive(Debug, Clone, Copy)]
92pub enum JoinSide {
93 Left,
95 Right,
97}
98
99impl fmt::Display for JoinSide {
100 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
101 match self {
102 JoinSide::Left => f.write_str("left"),
103 JoinSide::Right => f.write_str("right"),
104 }
105 }
106}
107
108#[derive(Debug, Default, Clone, Copy)]
114pub struct GroupSizeHints {
115 pub aggregate_input_group_size: Option<u64>,
116 pub distinct_on_input_group_size: Option<u64>,
117 pub limit_input_group_size: Option<u64>,
118}
119
120impl TryFrom<SelectOptionExtracted> for GroupSizeHints {
121 type Error = PlanError;
122
123 fn try_from(select_option_extracted: SelectOptionExtracted) -> Result<Self, Self::Error> {
130 let SelectOptionExtracted {
131 expected_group_size,
132 aggregate_input_group_size,
133 distinct_on_input_group_size,
134 limit_input_group_size,
135 ..
136 } = select_option_extracted;
137 if expected_group_size.is_some()
138 && (aggregate_input_group_size.is_some()
139 || distinct_on_input_group_size.is_some()
140 || limit_input_group_size.is_some())
141 {
142 Err(PlanError::InvalidGroupSizeHints)
143 } else {
144 let aggregate_input_group_size = aggregate_input_group_size.or(expected_group_size);
145 let distinct_on_input_group_size = distinct_on_input_group_size.or(expected_group_size);
146 let limit_input_group_size = limit_input_group_size.or(expected_group_size);
147 Ok(GroupSizeHints {
148 aggregate_input_group_size,
149 distinct_on_input_group_size,
150 limit_input_group_size,
151 })
152 }
153 }
154}