Skip to content

Commit 27822e2

Browse files
authored
Handle empty projection in Postgres SELECT statements (#1613)
1 parent 0647a4a commit 27822e2

File tree

6 files changed

+39
-2
lines changed

6 files changed

+39
-2
lines changed

src/ast/query.rs

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -350,7 +350,9 @@ impl fmt::Display for Select {
350350
}
351351
}
352352

353-
write!(f, " {}", display_comma_separated(&self.projection))?;
353+
if !self.projection.is_empty() {
354+
write!(f, " {}", display_comma_separated(&self.projection))?;
355+
}
354356

355357
if let Some(ref into) = self.into {
356358
write!(f, " {into}")?;

src/dialect/generic.rs

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -127,4 +127,8 @@ impl Dialect for GenericDialect {
127127
fn supports_struct_literal(&self) -> bool {
128128
true
129129
}
130+
131+
fn supports_empty_projections(&self) -> bool {
132+
true
133+
}
130134
}

src/dialect/mod.rs

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -410,6 +410,16 @@ pub trait Dialect: Debug + Any {
410410
false
411411
}
412412

413+
/// Return true if the dialect supports empty projections in SELECT statements
414+
///
415+
/// Example
416+
/// ```sql
417+
/// SELECT from table_name
418+
/// ```
419+
fn supports_empty_projections(&self) -> bool {
420+
false
421+
}
422+
413423
/// Dialect-specific infix parser override
414424
///
415425
/// This method is called to parse the next infix expression.

src/dialect/postgresql.rs

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -231,6 +231,16 @@ impl Dialect for PostgreSqlDialect {
231231
fn supports_named_fn_args_with_expr_name(&self) -> bool {
232232
true
233233
}
234+
235+
/// Return true if the dialect supports empty projections in SELECT statements
236+
///
237+
/// Example
238+
/// ```sql
239+
/// SELECT from table_name
240+
/// ```
241+
fn supports_empty_projections(&self) -> bool {
242+
true
243+
}
234244
}
235245

236246
pub fn parse_create(parser: &mut Parser) -> Option<Result<Statement, ParserError>> {

src/parser/mod.rs

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -9692,7 +9692,12 @@ impl<'a> Parser<'a> {
96929692
top = Some(self.parse_top()?);
96939693
}
96949694

9695-
let projection = self.parse_projection()?;
9695+
let projection =
9696+
if self.dialect.supports_empty_projections() && self.peek_keyword(Keyword::FROM) {
9697+
vec![]
9698+
} else {
9699+
self.parse_projection()?
9700+
};
96969701

96979702
let into = if self.parse_keyword(Keyword::INTO) {
96989703
let temporary = self

tests/sqlparser_common.rs

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12576,3 +12576,9 @@ fn overflow() {
1257612576
let statement = statements.pop().unwrap();
1257712577
assert_eq!(statement.to_string(), sql);
1257812578
}
12579+
12580+
#[test]
12581+
fn parse_select_without_projection() {
12582+
let dialects = all_dialects_where(|d| d.supports_empty_projections());
12583+
dialects.verified_stmt("SELECT FROM users");
12584+
}

0 commit comments

Comments
 (0)