(
column_names: &[ColumnName],
left_qcx: &QueryContext,
left: HirRelationExpr,
left_scope: Scope,
right_qcx: &QueryContext,
right: HirRelationExpr,
right_scope: Scope,
| 3856 | // See page 440 of ANSI SQL 2016 spec for details on scoping of using/natural joins |
| 3857 | #[allow(clippy::too_many_arguments)] |
| 3858 | fn plan_using_constraint( |
| 3859 | column_names: &[ColumnName], |
| 3860 | left_qcx: &QueryContext, |
| 3861 | left: HirRelationExpr, |
| 3862 | left_scope: Scope, |
| 3863 | right_qcx: &QueryContext, |
| 3864 | right: HirRelationExpr, |
| 3865 | right_scope: Scope, |
| 3866 | kind: JoinKind, |
| 3867 | alias: Option<&Ident>, |
| 3868 | ) -> Result<(HirRelationExpr, Scope), PlanError> { |
| 3869 | let mut both_scope = left_scope.clone().product(right_scope.clone())?; |
| 3870 | |
| 3871 | // Cargo culting PG here; no discernable reason this must fail, but PG does |
| 3872 | // so we do, as well. |
| 3873 | let mut unique_column_names = BTreeSet::new(); |
| 3874 | for c in column_names { |
| 3875 | if !unique_column_names.insert(c) { |
| 3876 | return Err(PlanError::Unsupported { |
| 3877 | feature: format!( |
| 3878 | "column name {} appears more than once in USING clause", |
| 3879 | c.quoted() |
| 3880 | ), |
| 3881 | discussion_no: None, |
| 3882 | }); |
| 3883 | } |
| 3884 | } |
| 3885 | |
| 3886 | let alias_item_name = alias.map(|alias| PartialItemName { |
| 3887 | database: None, |
| 3888 | schema: None, |
| 3889 | item: alias.clone().to_string(), |
| 3890 | }); |
| 3891 | |
| 3892 | if let Some(alias_item_name) = &alias_item_name { |
| 3893 | for partial_item_name in both_scope.table_names() { |
| 3894 | if partial_item_name.matches(alias_item_name) { |
| 3895 | sql_bail!( |
| 3896 | "table name \"{}\" specified more than once", |
| 3897 | alias_item_name |
| 3898 | ) |
| 3899 | } |
| 3900 | } |
| 3901 | } |
| 3902 | |
| 3903 | let ecx = &ExprContext { |
| 3904 | qcx: right_qcx, |
| 3905 | name: "USING clause", |
| 3906 | scope: &both_scope, |
| 3907 | relation_type: &SqlRelationType::new( |
| 3908 | left_qcx |
| 3909 | .relation_type(&left) |
| 3910 | .column_types |
| 3911 | .into_iter() |
| 3912 | .chain(right_qcx.relation_type(&right).column_types) |
| 3913 | .collect(), |
| 3914 | ), |
| 3915 | allow_aggregates: false, |
no test coverage detected