Try to unparse a table scan with pushdown operations into a new subquery plan. If the table scan is without any pushdown operations, return None.
(
&self,
plan: &LogicalPlan,
alias: Option<TableReference>,
already_projected: bool,
)
| 1661 | /// Try to unparse a table scan with pushdown operations into a new subquery plan. |
| 1662 | /// If the table scan is without any pushdown operations, return None. |
| 1663 | fn unparse_table_scan_pushdown( |
| 1664 | &self, |
| 1665 | plan: &LogicalPlan, |
| 1666 | alias: Option<TableReference>, |
| 1667 | already_projected: bool, |
| 1668 | ) -> Result<Option<LogicalPlan>> { |
| 1669 | match plan { |
| 1670 | LogicalPlan::TableScan(table_scan) => { |
| 1671 | if !Self::is_scan_with_pushdown(table_scan) { |
| 1672 | return Ok(None); |
| 1673 | } |
| 1674 | let table_schema = table_scan.source.schema(); |
| 1675 | let mut filter_alias_rewriter = |
| 1676 | alias.as_ref().map(|alias_name| TableAliasRewriter { |
| 1677 | table_schema: &table_schema, |
| 1678 | alias_name: alias_name.clone(), |
| 1679 | }); |
| 1680 | |
| 1681 | let mut builder = LogicalPlanBuilder::scan( |
| 1682 | table_scan.table_name.clone(), |
| 1683 | Arc::clone(&table_scan.source), |
| 1684 | None, |
| 1685 | )?; |
| 1686 | // We will rebase the column references to the new alias if it exists. |
| 1687 | // If the projection or filters are empty, we will append alias to the table scan. |
| 1688 | // |
| 1689 | // Example: |
| 1690 | // select t1.c1 from t1 where t1.c1 > 1 -> select a.c1 from t1 as a where a.c1 > 1 |
| 1691 | if let Some(ref alias) = alias |
| 1692 | && (table_scan.projection.is_some() || !table_scan.filters.is_empty()) |
| 1693 | { |
| 1694 | builder = builder.alias(alias.clone())?; |
| 1695 | } |
| 1696 | |
| 1697 | // Avoid creating a duplicate Projection node, which would result in an additional subquery if a projection already exists. |
| 1698 | // For example, if the `optimize_projection` rule is applied, there will be a Projection node, and duplicate projection |
| 1699 | // information included in the TableScan node. |
| 1700 | if !already_projected && let Some(project_vec) = &table_scan.projection { |
| 1701 | if project_vec.is_empty() { |
| 1702 | builder = builder.project(self.empty_projection_fallback())?; |
| 1703 | } else { |
| 1704 | let project_columns = project_vec |
| 1705 | .iter() |
| 1706 | .cloned() |
| 1707 | .map(|i| { |
| 1708 | let schema = table_scan.source.schema(); |
| 1709 | let field = schema.field(i); |
| 1710 | if alias.is_some() { |
| 1711 | Column::new(alias.clone(), field.name().clone()) |
| 1712 | } else { |
| 1713 | Column::new( |
| 1714 | Some(table_scan.table_name.clone()), |
| 1715 | field.name().clone(), |
| 1716 | ) |
| 1717 | } |
| 1718 | }) |
| 1719 | .collect::<Vec<_>>(); |
| 1720 | builder = builder.project(project_columns)?; |
no test coverage detected