Skip to content

Commit 58f2e5d

Browse files
Enhance TRIM function support for PostgreSQL and add tests for two-argument TRIM syntax
1 parent 83baf5e commit 58f2e5d

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
@@ -8099,10 +8099,9 @@ fn parse_trim() {
80998099
parse_sql_statements("SELECT TRIM(FOO 'xyz' FROM 'xyzfooxyz')").unwrap_err()
81008100
);
81018101

8102-
//keep Snowflake/BigQuery TRIM syntax failing
8103-
let all_expected_snowflake = TestedDialects::new(vec![
8102+
// keep dialects without comma-style TRIM syntax failing
8103+
let all_expected_error = TestedDialects::new(vec![
81048104
//Box::new(GenericDialect {}),
8105-
Box::new(PostgreSqlDialect {}),
81068105
Box::new(MsSqlDialect {}),
81078106
Box::new(AnsiDialect {}),
81088107
//Box::new(SnowflakeDialect {}),
@@ -8115,7 +8114,7 @@ fn parse_trim() {
81158114

81168115
assert_eq!(
81178116
ParserError::ParserError("Expected: ), found: 'a'".to_owned()),
8118-
all_expected_snowflake
8117+
all_expected_error
81198118
.parse_sql_statements("SELECT TRIM('xyz', 'a')")
81208119
.unwrap_err()
81218120
);

tests/sqlparser_postgres.rs

Lines changed: 41 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8641,3 +8641,44 @@ fn parse_pg_analyze() {
86418641
_ => panic!("Expected Analyze, got: {stmt:?}"),
86428642
}
86438643
}
8644+
8645+
#[test]
8646+
fn parse_postgres_two_argument_trim() {
8647+
let sql = "SELECT TRIM(' xyz ', ' ')";
8648+
let select = pg().verified_only_select(sql);
8649+
assert_eq!(
8650+
&Expr::Trim {
8651+
expr: Box::new(Expr::Value(
8652+
Value::SingleQuotedString(" xyz ".to_owned()).with_empty_span()
8653+
)),
8654+
trim_where: None,
8655+
trim_what: None,
8656+
trim_characters: Some(vec![Expr::Value(
8657+
Value::SingleQuotedString(" ".to_owned()).with_empty_span()
8658+
)]),
8659+
},
8660+
expr_from_projection(only(&select.projection))
8661+
);
8662+
8663+
let sql = "SELECT TRIM('xyz', 'a')";
8664+
let select = pg().verified_only_select(sql);
8665+
assert_eq!(
8666+
&Expr::Trim {
8667+
expr: Box::new(Expr::Value(
8668+
Value::SingleQuotedString("xyz".to_owned()).with_empty_span()
8669+
)),
8670+
trim_where: None,
8671+
trim_what: None,
8672+
trim_characters: Some(vec![Expr::Value(
8673+
Value::SingleQuotedString("a".to_owned()).with_empty_span()
8674+
)]),
8675+
},
8676+
expr_from_projection(only(&select.projection))
8677+
);
8678+
8679+
let error_sql = "SELECT TRIM('xyz' 'a')";
8680+
assert_eq!(
8681+
ParserError::ParserError("Expected: ), found: 'a'".to_owned()),
8682+
pg().parse_sql_statements(error_sql).unwrap_err()
8683+
);
8684+
}

0 commit comments

Comments
 (0)