Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
15 changes: 15 additions & 0 deletions prqlc/prqlc/src/sql/gen_projection.rs
Original file line number Diff line number Diff line change
Expand Up @@ -120,6 +120,19 @@ pub(super) fn translate_wildcards(ctx: &AnchorContext, cols: Vec<CId>) -> (Vec<C
(output, excluded)
}

fn deduplicate_select_items(items: &mut Vec<SelectItem>) {
// Dropping all duplicated identifiers
let mut seen = HashSet::new();
items.retain(|select_item| match select_item {
SelectItem::UnnamedExpr(sql_ast::Expr::CompoundIdentifier(idents)) => {
// If any of the identifiers hadn't been seen yet, retain the expr
idents.iter().any(|ident| seen.insert(ident.clone()))
}
SelectItem::ExprWithAlias { alias, .. } => seen.insert(alias.clone()),
_ => true,
});
}

pub(super) fn translate_select_items(
cols: Vec<CId>,
mut excluded: Excluded,
Expand Down Expand Up @@ -164,6 +177,8 @@ pub(super) fn translate_select_items(
})
.try_collect()?;

deduplicate_select_items(&mut res);

if res.is_empty() && !ctx.dialect.supports_zero_columns() {
// In some cases, no columns will appear in the projection
// for SQL to parse correctly, we inject a `NULL`.
Expand Down
73 changes: 63 additions & 10 deletions prqlc/prqlc/tests/integration/sql.rs
Original file line number Diff line number Diff line change
Expand Up @@ -918,6 +918,62 @@ fn test_sort_in_nested_join() {
);
}

#[test]
fn test_sort_in_nested_join_with_extra_derive_and_select() {
// #5302
assert_snapshot!(compile(r#"
from albums
join side:left (
from artists
derive {
my_new_col = f"artist: {name}"
}
group {my_new_col} (aggregate { first_name = first this.`name`})
sort {this.my_new_col, first_name}
derive {new_name = first_name, other_new_name = first_name}
select {this.my_new_col, this.new_name, this.other_new_name}
) (this.id == that.my_new_col)
"#).unwrap(),
@r#"
WITH table_1 AS (
SELECT
CONCAT('artist: ', name) AS my_new_col,
FIRST_VALUE(name) AS _expr_0
FROM
artists
GROUP BY
CONCAT('artist: ', name)
),
table_2 AS (
SELECT
my_new_col,
_expr_0 AS new_name,
_expr_0 AS other_new_name,
_expr_0
FROM
table_1
),
table_0 AS (
SELECT
my_new_col,
new_name,
other_new_name,
FIRST_VALUE(name) AS _expr_0
FROM
table_2
)
SELECT
albums.*,
table_0.my_new_col,
table_0.new_name,
table_0.other_new_name
FROM
albums
LEFT OUTER JOIN table_0 ON albums.id = table_0.my_new_col
"#
);
}

#[test]
fn test_sort_in_nested_append() {
assert_snapshot!(compile(r#"
Expand Down Expand Up @@ -3885,7 +3941,6 @@ fn test_name_shadowing() {
"###).unwrap(),
@r"
SELECT
a AS _expr_0,
a AS _expr_0,
a + 1 AS a
FROM
Expand All @@ -3903,7 +3958,6 @@ fn test_name_shadowing() {
"###).unwrap(),
@r"
SELECT
a AS _expr_0,
a AS _expr_0,
a + 1,
a + 1 + 2 AS a
Expand Down Expand Up @@ -5098,7 +5152,6 @@ fn test_lineage() {
' 3' AS a
)
SELECT
a,
a
FROM
table_0
Expand Down Expand Up @@ -5513,22 +5566,22 @@ fn unstable_ordering() {
assert_snapshot!(compile(r###"
# All lines are mandatory
from foo
take 10000
take 10000
# We need 8+ aliases to trigger the issue
derive { a1 = 1, a2 = 1, a3 = 1, a4 = 1, a5 = 1, a6 = 1, a7 = 1, a8 = 1 }
# The `select !` itself is required, but its content is not
select !{ a1, a2, a3, a4, a5, a6, a7, a8 }
select !{ a1, a2, a3, a4, a5, a6, a7, a8 }

# We may remove `u` from both these statements, but the `select !` must remain
select { b, c, u }
select !{ u }
select !{ u }

# Aggregate verb seems to not matter
group { b } ( aggregate { c = count c } )
derive { d = c }
select !{ c }
group { b } ( aggregate { c = count c } )
derive { d = c }
select !{ c }

group { d } ( aggregate { b = sum b } )
group { d } ( aggregate { b = sum b } )
sort { d }"###).unwrap(), @r"
WITH table_1 AS (
SELECT
Expand Down