Skip to content

Commit e978c61

Browse files
Enhance TRIM function support for PostgreSQL and add tests for two-argument TRIM syntax
1 parent d9b53a0 commit e978c61

File tree

4 files changed

+53
-7
lines changed

4 files changed

+53
-7
lines changed

src/ast/mod.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1131,7 +1131,7 @@ pub enum Expr {
11311131
/// ```sql
11321132
/// TRIM([BOTH | LEADING | TRAILING] [<expr> FROM] <expr>)
11331133
/// TRIM(<expr>)
1134-
/// TRIM(<expr>, [, characters]) -- only Snowflake or Bigquery
1134+
/// TRIM(<expr>, [, characters]) -- PostgreSQL, DuckDB, Snowflake, BigQuery, Generic
11351135
/// ```
11361136
Trim {
11371137
/// The expression to trim from.

src/parser/mod.rs

Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2940,7 +2940,7 @@ impl<'a> Parser<'a> {
29402940
/// ```sql
29412941
/// TRIM ([WHERE] ['text' FROM] 'text')
29422942
/// TRIM ('text')
2943-
/// TRIM(<expr>, [, characters]) -- only Snowflake or BigQuery
2943+
/// TRIM(<expr>, [, characters]) -- PostgreSQL, DuckDB, Snowflake, BigQuery, Generic
29442944
/// ```
29452945
pub fn parse_trim_expr(&mut self) -> Result<Expr, ParserError> {
29462946
self.expect_token(&Token::LParen)?;
@@ -2962,7 +2962,13 @@ impl<'a> Parser<'a> {
29622962
trim_characters: None,
29632963
})
29642964
} else if self.consume_token(&Token::Comma)
2965-
&& dialect_of!(self is DuckDbDialect | SnowflakeDialect | BigQueryDialect | GenericDialect)
2965+
&& dialect_of!(
2966+
self is DuckDbDialect
2967+
| SnowflakeDialect
2968+
| BigQueryDialect
2969+
| PostgreSqlDialect
2970+
| GenericDialect
2971+
)
29662972
{
29672973
let characters = self.parse_comma_separated(Parser::parse_expr)?;
29682974
self.expect_token(&Token::RParen)?;

tests/sqlparser_common.rs

Lines changed: 3 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -8079,10 +8079,9 @@ fn parse_trim() {
80798079
parse_sql_statements("SELECT TRIM(FOO 'xyz' FROM 'xyzfooxyz')").unwrap_err()
80808080
);
80818081

8082-
//keep Snowflake/BigQuery TRIM syntax failing
8083-
let all_expected_snowflake = TestedDialects::new(vec![
8082+
// keep dialects without comma-style TRIM syntax failing
8083+
let all_expected_error = TestedDialects::new(vec![
80848084
//Box::new(GenericDialect {}),
8085-
Box::new(PostgreSqlDialect {}),
80868085
Box::new(MsSqlDialect {}),
80878086
Box::new(AnsiDialect {}),
80888087
//Box::new(SnowflakeDialect {}),
@@ -8095,7 +8094,7 @@ fn parse_trim() {
80958094

80968095
assert_eq!(
80978096
ParserError::ParserError("Expected: ), found: 'a'".to_owned()),
8098-
all_expected_snowflake
8097+
all_expected_error
80998098
.parse_sql_statements("SELECT TRIM('xyz', 'a')")
81008099
.unwrap_err()
81018100
);

tests/sqlparser_postgres.rs

Lines changed: 41 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8596,3 +8596,44 @@ fn parse_pg_analyze() {
85968596
_ => panic!("Expected Analyze, got: {stmt:?}"),
85978597
}
85988598
}
8599+
8600+
#[test]
8601+
fn parse_postgres_two_argument_trim() {
8602+
let sql = "SELECT TRIM(' xyz ', ' ')";
8603+
let select = pg().verified_only_select(sql);
8604+
assert_eq!(
8605+
&Expr::Trim {
8606+
expr: Box::new(Expr::Value(
8607+
Value::SingleQuotedString(" xyz ".to_owned()).with_empty_span()
8608+
)),
8609+
trim_where: None,
8610+
trim_what: None,
8611+
trim_characters: Some(vec![Expr::Value(
8612+
Value::SingleQuotedString(" ".to_owned()).with_empty_span()
8613+
)]),
8614+
},
8615+
expr_from_projection(only(&select.projection))
8616+
);
8617+
8618+
let sql = "SELECT TRIM('xyz', 'a')";
8619+
let select = pg().verified_only_select(sql);
8620+
assert_eq!(
8621+
&Expr::Trim {
8622+
expr: Box::new(Expr::Value(
8623+
Value::SingleQuotedString("xyz".to_owned()).with_empty_span()
8624+
)),
8625+
trim_where: None,
8626+
trim_what: None,
8627+
trim_characters: Some(vec![Expr::Value(
8628+
Value::SingleQuotedString("a".to_owned()).with_empty_span()
8629+
)]),
8630+
},
8631+
expr_from_projection(only(&select.projection))
8632+
);
8633+
8634+
let error_sql = "SELECT TRIM('xyz' 'a')";
8635+
assert_eq!(
8636+
ParserError::ParserError("Expected: ), found: 'a'".to_owned()),
8637+
pg().parse_sql_statements(error_sql).unwrap_err()
8638+
);
8639+
}

0 commit comments

Comments
 (0)