diff --git a/sqlglot/dialects/mysql.py b/sqlglot/dialects/mysql.py index 6c070cbed1..b584c351e9 100644 --- a/sqlglot/dialects/mysql.py +++ b/sqlglot/dialects/mysql.py @@ -373,11 +373,6 @@ class Parser(parser.Parser): FUNCTION_PARSERS = { **parser.Parser.FUNCTION_PARSERS, - "CHAR": lambda self: self.expression( - exp.Chr, - expressions=self._parse_csv(self._parse_assignment), - charset=self._match(TokenType.USING) and self._parse_var(), - ), "GROUP_CONCAT": lambda self: self._parse_group_concat(), # https://dev.mysql.com/doc/refman/5.7/en/miscellaneous-functions.html#function_values "VALUES": lambda self: self.expression( @@ -1303,7 +1298,7 @@ def _oldstyle_limit_sql(self, expression: exp.Show) -> str: return "" def chr_sql(self, expression: exp.Chr) -> str: - this = self.expressions(sqls=[expression.this] + expression.expressions) + this = self.expressions(expression) charset = expression.args.get("charset") using = f" USING {self.sql(charset)}" if charset else "" return f"CHAR({this}{using})" diff --git a/sqlglot/generator.py b/sqlglot/generator.py index b5b6cd3cd7..2323f1406a 100644 --- a/sqlglot/generator.py +++ b/sqlglot/generator.py @@ -5472,3 +5472,9 @@ def weekstart_sql(self, expression: exp.WeekStart) -> str: return "WEEK" return self.func("WEEK", expression.this) + + def chr_sql(self, expression: exp.Chr) -> str: + this = self.expressions(expression) + charset = expression.args.get("charset") + using = f" USING {self.sql(charset)}" if charset else "" + return f"{expression.sql_name()}({this}{using})" diff --git a/sqlglot/parser.py b/sqlglot/parser.py index 9ea0504170..bf3ce07c9c 100644 --- a/sqlglot/parser.py +++ b/sqlglot/parser.py @@ -212,8 +212,6 @@ class Parser(metaclass=_Parser): "ARRAY_AGG": lambda args, dialect: exp.ArrayAgg( this=seq_get(args, 0), nulls_excluded=dialect.ARRAY_AGG_INCLUDES_NULLS is None or None ), - "CHAR": lambda args: exp.Chr(expressions=args), - "CHR": lambda args: exp.Chr(expressions=args), "COUNT": lambda args: exp.Count(this=seq_get(args, 0), expressions=args[1:], big_int=True), "CONCAT": lambda args, dialect: exp.Concat( expressions=args, @@ -1281,6 +1279,8 @@ def _parse_partitioned_by_bucket_or_truncate(self) -> t.Optional[exp.Expression] "CAST": lambda self: self._parse_cast(self.STRICT_CAST), "CEIL": lambda self: self._parse_ceil_floor(exp.Ceil), "CONVERT": lambda self: self._parse_convert(self.STRICT_CAST), + "CHAR": lambda self: self._parse_char(), + "CHR": lambda self: self._parse_char(), "DECODE": lambda self: self._parse_decode(), "EXTRACT": lambda self: self._parse_extract(), "FLOOR": lambda self: self._parse_ceil_floor(exp.Floor), @@ -6765,6 +6765,13 @@ def _parse_gap_fill(self) -> exp.GapFill: gap_fill = exp.GapFill.from_arg_list(args) return self.validate_expression(gap_fill, args) + def _parse_char(self) -> exp.Chr: + return self.expression( + exp.Chr, + expressions=self._parse_csv(self._parse_assignment), + charset=self._match(TokenType.USING) and self._parse_var(), + ) + def _parse_cast(self, strict: bool, safe: t.Optional[bool] = None) -> exp.Expression: this = self._parse_disjunction() diff --git a/tests/dialects/test_oracle.py b/tests/dialects/test_oracle.py index e832332abb..038ca8e566 100644 --- a/tests/dialects/test_oracle.py +++ b/tests/dialects/test_oracle.py @@ -806,3 +806,7 @@ def test_pseudocolumns(self): qualified.sql(dialect="oracle"), 'WITH "T" AS (SELECT 1 AS "COL") SELECT "T"."COL" AS "COL", ROWID AS "ROWID" FROM "T" "T" WHERE ROWNUM = 1', ) + + def test_chr(self): + self.validate_identity("SELECT CHR(187 USING NCHAR_CS)") + self.validate_identity("SELECT CHR(187)")