Skip to content

Commit

Permalink
add struct.* wildcard selection support
Browse files Browse the repository at this point in the history
  • Loading branch information
alexander-beedie committed Jun 21, 2024
1 parent 3bb8050 commit 2cfdfb2
Show file tree
Hide file tree
Showing 8 changed files with 187 additions and 84 deletions.
2 changes: 1 addition & 1 deletion crates/polars-plan/src/plans/conversion/expr_expansion.rs
Original file line number Diff line number Diff line change
Expand Up @@ -634,7 +634,7 @@ fn find_flags(expr: &Expr) -> PolarsResult<ExpansionFlags> {

/// In case of single col(*) -> do nothing, no selection is the same as select all
/// In other cases replace the wildcard with an expression with all columns
pub(crate) fn rewrite_projections(
pub fn rewrite_projections(
exprs: Vec<Expr>,
schema: &Schema,
keys: &[Expr],
Expand Down
2 changes: 1 addition & 1 deletion crates/polars-plan/src/plans/conversion/mod.rs
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
mod convert_utils;
mod dsl_to_ir;
mod expr_expansion;
pub(crate) mod expr_expansion;
mod expr_to_ir;
mod ir_to_dsl;
#[cfg(any(feature = "ipc", feature = "parquet", feature = "csv"))]
Expand Down
2 changes: 1 addition & 1 deletion crates/polars-plan/src/plans/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ pub(crate) mod ir;
mod apply;
mod builder_dsl;
mod builder_ir;
pub(crate) mod conversion;
pub mod conversion;
#[cfg(feature = "debugging")]
pub(crate) mod debug;
pub mod expr_ir;
Expand Down
1 change: 1 addition & 0 deletions crates/polars-plan/src/prelude.rs
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ pub(crate) use polars_time::prelude::*;
pub use polars_utils::arena::{Arena, Node};

pub use crate::dsl::*;
pub use crate::plans::conversion::expr_expansion::rewrite_projections;
#[cfg(feature = "debugging")]
pub use crate::plans::debug::*;
pub use crate::plans::options::*;
Expand Down
56 changes: 26 additions & 30 deletions crates/polars-sql/src/context.rs
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ use polars_lazy::prelude::*;
use polars_ops::frame::JoinCoalesce;
use polars_plan::prelude::*;
use sqlparser::ast::{
Distinct, ExcludeSelectItem, Expr as SQLExpr, FunctionArg, GroupByExpr, JoinConstraint,
Distinct, ExcludeSelectItem, Expr as SQLExpr, FunctionArg, GroupByExpr, Ident, JoinConstraint,
JoinOperator, ObjectName, ObjectType, Offset, OrderByExpr, Query, Select, SelectItem, SetExpr,
SetOperator, SetQuantifier, Statement, TableAlias, TableFactor, TableWithJoins, UnaryOperator,
Value as SQLValue, Values, WildcardAdditionalOptions,
Expand Down Expand Up @@ -600,36 +600,44 @@ impl SQLContext {
lf = self.process_where(lf, &select_stmt.selection)?;

// Column projections.
let projections: Vec<_> = select_stmt
let projections: Vec<Expr> = select_stmt
.projection
.iter()
.map(|select_item| {
Ok(match select_item {
SelectItem::UnnamedExpr(expr) => parse_sql_expr(expr, self, schema.as_deref())?,
SelectItem::UnnamedExpr(expr) => {
vec![parse_sql_expr(expr, self, schema.as_deref())?]
},
SelectItem::ExprWithAlias { expr, alias } => {
let expr = parse_sql_expr(expr, self, schema.as_deref())?;
expr.alias(&alias.value)
vec![expr.alias(&alias.value)]
},
SelectItem::QualifiedWildcard(oname, wildcard_options) => self
.process_qualified_wildcard(
oname,
SelectItem::QualifiedWildcard(obj_name, wildcard_options) => {
let expanded = self.process_qualified_wildcard(
obj_name,
wildcard_options,
&mut contains_wildcard_exclude,
)?,
schema.as_deref(),
)?;
rewrite_projections(vec![expanded], &(schema.clone().unwrap()), &[])?
},
SelectItem::Wildcard(wildcard_options) => {
contains_wildcard = true;
let e = col("*");
self.process_wildcard_additional_options(
vec![self.process_wildcard_additional_options(
e,
wildcard_options,
&mut contains_wildcard_exclude,
)?
)?]
},
})
})
.collect::<PolarsResult<_>>()?;
.collect::<PolarsResult<Vec<Vec<_>>>>()?
.into_iter()
.flatten()
.collect();

// Check for "GROUP BY ..." (after projections, as there may be ordinal/position ints).
// Check for "GROUP BY ..." (after determining projections)
let mut group_by_keys: Vec<Expr> = Vec::new();
match &select_stmt.group_by {
// Standard "GROUP BY x, y, z" syntax (also recognising ordinal values)
Expand Down Expand Up @@ -1152,25 +1160,13 @@ impl SQLContext {
ObjectName(idents): &ObjectName,
options: &WildcardAdditionalOptions,
contains_wildcard_exclude: &mut bool,
schema: Option<&Schema>,
) -> PolarsResult<Expr> {
let idents = idents.as_slice();
let e = match idents {
[tbl_name] => {
let lf = self.table_map.get_mut(&tbl_name.value).ok_or_else(|| {
polars_err!(
SQLInterface: "no table named '{}' found",
tbl_name
)
})?;
let schema = lf.schema_with_arenas(&mut self.lp_arena, &mut self.expr_arena)?;
cols(schema.iter_names())
},
e => polars_bail!(
SQLSyntax: "invalid wildcard expression ({:?})",
e
),
};
self.process_wildcard_additional_options(e, options, contains_wildcard_exclude)
let mut new_idents = idents.clone();
new_idents.push(Ident::new("*"));
let identifier = SQLExpr::CompoundIdentifier(new_idents);
let expr = parse_sql_expr(&identifier, self, schema)?;
self.process_wildcard_additional_options(expr, options, contains_wildcard_exclude)
}

fn process_wildcard_additional_options(
Expand Down
17 changes: 11 additions & 6 deletions crates/polars-sql/src/sql_expr.rs
Original file line number Diff line number Diff line change
Expand Up @@ -390,23 +390,28 @@ impl SQLExprVisitor<'_> {
} else {
Schema::new()
}))
};
}?;

let mut column: PolarsResult<Expr> = if lf.is_none() {
let mut column: PolarsResult<Expr> = if lf.is_none() && schema.is_empty() {
Ok(col(&ident_root.value))
} else {
let col_name = &remaining_idents.next().unwrap().value;
if let Some((_, name, _)) = schema?.get_full(col_name) {
let resolved = &self.ctx.resolve_name(&ident_root.value, col_name);
let name = &remaining_idents.next().unwrap().value;
if lf.is_some() && name == "*" {
Ok(cols(schema.iter_names()))
} else if let Some((_, name, _)) = schema.get_full(name) {
let resolved = &self.ctx.resolve_name(&ident_root.value, name);
Ok(if name != resolved {
col(resolved).alias(name)
} else {
col(name)
})
} else if lf.is_none() {
remaining_idents = idents.iter().skip(1);
Ok(col(&ident_root.value))
} else {
polars_bail!(
SQLInterface: "no column named '{}' found in table '{}'",
col_name,
name,
ident_root
)
}
Expand Down
Loading

0 comments on commit 2cfdfb2

Please sign in to comment.