Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

sql: support USING on implicitly coercible data types #5313

Merged

Conversation

sploiselle
Copy link
Contributor

@sploiselle sploiselle commented Jan 13, 2021

Fixes MaterializeInc/database-issues#1629


This change is Reviewable

Copy link
Contributor

@justinj justinj left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM, do you have a source that the logic for coerce_homogenous_exprs is indeed what's needed here? Mostly just curious, seems right!

@@ -239,3 +239,41 @@ Unable to automatically determine a timestamp for your query; this can happen if

! SELECT * FROM names FULL OUTER JOIN mods_unmat ON 1 = 0;
Unable to automatically determine a timestamp for your query; this can happen if your query depends on non-materialized sources

# Test joins on implicitly coercible data types
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Is there a reason this needs to be tested in testdrive as opposed to the sqllogictests?

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Agreed that an SLT here would be best!

for column_name in column_names {
let (l, _) = left_scope.resolve_column(column_name)?;
let (lhs, _) = left_scope.resolve_column(column_name)?;
let (r, _) = right_scope.resolve_column(column_name)?;
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

nit: for consistency s/r/rhs/?

Copy link
Member

@benesch benesch left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Code looks good, but I think a small reordering (of stuff that existed before) could improve clarity. 1s!

@@ -239,3 +239,41 @@ Unable to automatically determine a timestamp for your query; this can happen if

! SELECT * FROM names FULL OUTER JOIN mods_unmat ON 1 = 0;
Unable to automatically determine a timestamp for your query; this can happen if your query depends on non-materialized sources

# Test joins on implicitly coercible data types
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Agreed that an SLT here would be best!

@sploiselle
Copy link
Contributor Author

@justinj really, really good q re: coerce_homogeneous_exprs––using this function lets us avoid going all the way through the function selection machinery (func::resolve_func, func::select_impl –– which is definitely an option) bc we know we can directly invoke the functions we want with homogeneously typed exprs. That we want to use these same homogeneously typed exprs twice then makes it really decisive that this is the better choice.

As for a source, the logic is that for the join to work, the two expressions must be of the same type, as evidenced by the fact that BinaryFunc::Eq and VariadicFunc::Coalesce both require homogeneously typed exprs (though I realize that this makes my argument circular ¯\(ツ)/¯), and this is kind of implicit cast is allowed bc PG does it.

Not sure if I under-, over-, or incorrect-dimensionally-shot your question, but please lmk!

@benesch
Copy link
Member

benesch commented Jan 13, 2021

Ok, what do you think about restructuring the body of the loop in plan_using_constraint so it looks like this:

        let (lhs, _) = left_scope.resolve_column(column_name)?;
        let (mut rhs, _) = right_scope.resolve_column(column_name)?;
        if lhs.level != 0 || rhs.level != 0 {
            bail!(
                "Internal error: name {} in USING resolved to outer column",
                column_name
            )
        }

        // The new column can be named using aliases from either the right or
        // left.
        let mut names = left_scope.items[lhs.column].names.clone();
        names.extend(right_scope.items[rhs.column].names.clone());

        // Adjust the RHS reference to its post-join location.
        rhs.column += left_scope.len();

        // Join keys must be resolved to same type.
        let mut exprs = coerce_homogeneous_exprs(
            &format!("NATURAL/USING join column {}", column_name),
            &ecx,
            vec![
                CoercibleScalarExpr::Coerced(ScalarExpr::Column(lhs)),
                CoercibleScalarExpr::Coerced(ScalarExpr::Column(rhs)),
            ],
            None,
        )?;
        let (expr1, expr2) = (exprs.remove(0), exprs.remove(0));

        join_exprs.push(ScalarExpr::CallBinary {
            func: BinaryFunc::Eq,
            expr1: Box::new(expr1.clone()),
            expr2: Box::new(expr2.clone()),
        });
        map_exprs.push(ScalarExpr::CallVariadic {
            func: VariadicFunc::Coalesce,
            exprs: vec![expr1, expr2],
        });
        new_items.push(ScopeItem {
            names,
            expr: None,
            nameable: true,
        });
        dropped_columns.insert(lhs.column);
        dropped_columns.insert(rhs.column);

The idea is to do the thing that requires the unadjusted RHS column, adjust the RHS column, and then do all the things that require the adjusted RHS column.

@sploiselle
Copy link
Contributor Author

@benesch Nice 🙇🙇🙇

Copy link
Member

@benesch benesch left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Looks swell to me!

@sploiselle sploiselle merged commit 2376402 into MaterializeInc:main Jan 14, 2021
@sploiselle sploiselle deleted the natural-join-implicit-casts branch January 14, 2021 01:59
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

3 participants