nuno-faria commented on code in PR #19221:
URL: https://github.com/apache/datafusion/pull/19221#discussion_r2628395045
##########
datafusion/sql/src/unparser/ast.rs:
##########
@@ -140,7 +140,15 @@ impl Default for QueryBuilder {
pub struct SelectBuilder {
distinct: Option<ast::Distinct>,
top: Option<ast::Top>,
- projection: Vec<ast::SelectItem>,
+ /// Projection items for the SELECT clause.
+ ///
+ /// This field uses `Option` to distinguish between three distinct states:
+ /// - `None`: No projection has been set (not yet initialized)
+ /// - `Some(vec![])`: Empty projection explicitly set (generates `SELECT
FROM ...` or `SELECT 1 FROM ...`)
+ /// - `Some(vec![...])`: Non-empty projection with specific
columns/expressions
+ ///
+ /// Use `projection()` to set this field and `already_projected()` to
check if it has been set.
+ projection: Option<Vec<ast::SelectItem>>,
Review Comment:
For anyone else reviewing this: projection needs to be an `Option` to be
able to distinguish between explicitly empty (`SELECT FROM`) and select all
(`SELECT * FROM`).
##########
datafusion/sql/src/unparser/plan.rs:
##########
@@ -98,6 +98,16 @@ pub fn plan_to_sql(plan: &LogicalPlan) ->
Result<ast::Statement> {
}
impl Unparser<'_> {
+ /// Generates appropriate projection expression for empty projection lists.
+ /// Returns an empty vec for dialects supporting empty select lists,
+ /// or a dummy literal `1` for other dialects.
+ fn empty_projection_fallback(&self) -> Vec<Expr> {
+ if self.dialect.supports_empty_select_list() {
+ Vec::new()
+ } else {
+ vec![Expr::Literal(ScalarValue::Int64(Some(1)), None)]
+ }
+ }
Review Comment:
nit: Perhaps it's better to move this method to the end of Unparser, so
`plan_to_sql` remains at the top.
##########
datafusion/sql/src/unparser/dialect.rs:
##########
@@ -218,6 +218,46 @@ pub trait Dialect: Send + Sync {
fn timestamp_with_tz_to_string(&self, dt: DateTime<Tz>, _unit: TimeUnit)
-> String {
dt.to_string()
}
+
+ /// Whether the dialect supports an empty select list such as `SELECT FROM
table`.
+ ///
+ /// An empty select list returns rows without any column data, which is
useful for:
+ /// - Counting rows: `SELECT FROM users WHERE active = true` (combined
with `COUNT(*)`)
+ /// - Testing row existence without retrieving column data
+ /// - Performance optimization when only row counts or existence checks
are needed
+ ///
+ /// # Supported Databases
+ ///
+ /// - **PostgreSQL**: Fully supported. Returns rows with zero columns.
+ /// - **DataFusion**: Supported natively.
Review Comment:
nit: Since there isn't a DataFusion dialect (and the `DefaultDialect`
returns false) it might be better to remove it from the documentation to avoid
any confusion.
--
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.
To unsubscribe, e-mail: [email protected]
For queries about this service, please contact Infrastructure at:
[email protected]
---------------------------------------------------------------------
To unsubscribe, e-mail: [email protected]
For additional commands, e-mail: [email protected]