TODO(database-issues#8620): Remove once subsources are removed Validates the requested subsources do not have name conflicts with each other and that the same upstream table is not referenced multiple times.
(
requested_source_exports: &[RequestedSourceExport<T>],
)
| 142 | /// Validates the requested subsources do not have name conflicts with each other |
| 143 | /// and that the same upstream table is not referenced multiple times. |
| 144 | fn validate_source_export_names<T>( |
| 145 | requested_source_exports: &[RequestedSourceExport<T>], |
| 146 | ) -> Result<(), PlanError> { |
| 147 | // This condition would get caught during the catalog transaction, but produces a |
| 148 | // vague, non-contextual error. Instead, error here so we can suggest to the user |
| 149 | // how to fix the problem. |
| 150 | if let Some(name) = requested_source_exports |
| 151 | .iter() |
| 152 | .map(|subsource| &subsource.name) |
| 153 | .duplicates() |
| 154 | .next() |
| 155 | .cloned() |
| 156 | { |
| 157 | let mut upstream_references: Vec<_> = requested_source_exports |
| 158 | .into_iter() |
| 159 | .filter_map(|subsource| { |
| 160 | if &subsource.name == &name { |
| 161 | Some(subsource.external_reference.clone()) |
| 162 | } else { |
| 163 | None |
| 164 | } |
| 165 | }) |
| 166 | .collect(); |
| 167 | |
| 168 | upstream_references.sort(); |
| 169 | |
| 170 | Err(PlanError::SubsourceNameConflict { |
| 171 | name, |
| 172 | upstream_references, |
| 173 | })?; |
| 174 | } |
| 175 | |
| 176 | // We disallow subsource statements from referencing the same upstream table, but we allow |
| 177 | // `CREATE TABLE .. FROM SOURCE` statements to do so. Since `CREATE TABLE .. FROM SOURCE` |
| 178 | // purification will only provide 1 `requested_source_export`, we can leave this here without |
| 179 | // needing to differentiate between the two types of statements. |
| 180 | // TODO(roshan): Remove this when auto-generated subsources are deprecated. |
| 181 | if let Some(name) = requested_source_exports |
| 182 | .iter() |
| 183 | .map(|export| &export.external_reference) |
| 184 | .duplicates() |
| 185 | .next() |
| 186 | .cloned() |
| 187 | { |
| 188 | let mut target_names: Vec<_> = requested_source_exports |
| 189 | .into_iter() |
| 190 | .filter_map(|export| { |
| 191 | if &export.external_reference == &name { |
| 192 | Some(export.name.clone()) |
| 193 | } else { |
| 194 | None |
| 195 | } |
| 196 | }) |
| 197 | .collect(); |
| 198 | |
| 199 | target_names.sort(); |
| 200 | |
| 201 | Err(PlanError::SubsourceDuplicateReference { name, target_names })?; |
no test coverage detected