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

Support planning Map literal #11780

Merged
merged 6 commits into from
Aug 3, 2024
Merged

Conversation

goldmedal
Copy link
Contributor

Which issue does this PR close?

Closes #11434

Rationale for this change

What changes are included in this PR?

Are these changes tested?

yes

Are there any user-facing changes?

Provide map literal syntax.

@github-actions github-actions bot added sql SQL Planner sqllogictest SQL Logic Tests (.slt) labels Aug 2, 2024
Comment on lines 338 to 342
# TODO: support parsing an empty map
# query ?
# SELECT MAP {};
# ----
# {}
Copy link
Contributor Author

Choose a reason for hiding this comment

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

I missed supporting this in sqlparser-rs. I'll have PR for it.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

I have created a PR for it sqlparser-rs/sqlparser-rs#1361

PlannerResult::Original(expr) => exprs = expr,
}
}
not_impl_err!("Unsupported map literal: {exprs:?}")
Copy link
Contributor

Choose a reason for hiding this comment

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

Suggested change
not_impl_err!("Unsupported map literal: {exprs:?}")
not_impl_err!("Unsupported MAP literal: {exprs:?}")

# {}

query error DataFusion error: Execution error: map key cannot be null
SELECT MAP {'a': 1, null: 2}
Copy link
Contributor

Choose a reason for hiding this comment

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

can we add some more negative and nested cases?

Map of map, map with values null, map with different types?

Copy link
Contributor

@comphead comphead left a comment

Choose a reason for hiding this comment

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

Imho it is great improvement thanks @goldmedal . Lets add some more tests on literal just to make sure the literal is ready to go.

Comment on lines 445 to 461
# TODO: fix accessing map with non-string key
# query ?
# SELECT MAP { 1: 'a', 2: 'b', 3: 'c' }[1];
# ----
# a

# TODO: fix accessing map with non-string key
# query ?
# SELECT MAP { MAP {1:'a', 2:'b'}:1, MAP {1:'c', 2:'d'}:2 }[MAP {1:'a', 2:'b'}];
# ----
# 1

# TODO: fix accessing map with non-string key
# query ?
# SELECT MAKE_MAP(1, null, 2, 33, 3, null)[2];
# ----
# 33
Copy link
Contributor Author

Choose a reason for hiding this comment

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

I found some issues about accessing a map with a non-string key but I think we can fix it in another PR.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Filed #11785 for them.

Copy link
Contributor

Choose a reason for hiding this comment

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

Yeah, thats the entire idea of adding tests to find potential issues.
please add the issue tracker link to the commented out tests

Comment on lines 726 to 739
let mut exprs = vec![];
entries.into_iter().try_for_each(|entry| {
exprs.push(self.sql_expr_to_logical_expr(
*entry.key,
schema,
planner_context,
)?);
exprs.push(self.sql_expr_to_logical_expr(
*entry.value,
schema,
planner_context,
)?);
Ok::<_, DataFusionError>(())
})?;
Copy link
Contributor

Choose a reason for hiding this comment

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

Can we do something like this ?

        let mut exprs =  entries.into_iter().flat_map(|entry| {
            let k = self.sql_expr_to_logical_expr(
                *entry.key,
                schema,
                planner_context,
            )?;
            let v = self.sql_expr_to_logical_expr(
                *entry.value,
                schema,
                planner_context,
            )?;
            vec![k,v]
        }).collect<>();;

Haven't tried it out just a pseudo code

Copy link
Contributor Author

Choose a reason for hiding this comment

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

I think it's wrong. What plan_make_map accepts is [k1, v1, k2, v2, ... ]. The parameters will be arranged to 2 vectors for map_udf.
If we change it to [[k1, k2, ...], [v1, v2, ...], it will become an array-to-array map, MAP {[k1, k2, ...]: [v1, v2, ...]}.

Copy link
Contributor

Choose a reason for hiding this comment

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

Like i mentioned that was just pseudo code (i should have called it a rough idea). I was try to suggest something like this

let arr = (1..10).step_by(2).into_iter().flat_map(|e| vec![e,e+1]).collect::<Vec<_>>();
[1, 2, 3, 4, 5, 6, 7, 8, 9, 10]

If we can do something like this the expressions iter can be rearrage to [k1, v1, k2, v2, ... ]

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Got it. I tried to simplify them in e8a3477. It looks better. Thanks.

PlannerResult::Original(expr) => exprs = expr,
}
}
not_impl_err!("Unsupported MAP literal: {exprs:?}")
Copy link
Contributor

Choose a reason for hiding this comment

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

Can we change it to MAP not supported by ExprPlanner: {exprs:?} to maintains consistency with other errors in the file.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

I also align the error message for Dictionary in ea38d6b.

Copy link
Contributor

@alamb alamb left a comment

Choose a reason for hiding this comment

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

This is a beautiful PR @goldmedal

Thank you @comphead and @dharanad for the review (the PR looks great now)

@alamb alamb merged commit 81668f3 into apache:main Aug 3, 2024
24 checks passed
@goldmedal goldmedal deleted the feature/11434-map-literal branch August 3, 2024 11:07
@goldmedal
Copy link
Contributor Author

Thanks @comphead @dharanad @alamb !

This pull request was closed.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
sql SQL Planner sqllogictest SQL Logic Tests (.slt)
Projects
None yet
Development

Successfully merging this pull request may close these issues.

Implement the rewrite from the Map literal to Map function
4 participants