diff --git a/sqlglot/dialects/mysql.py b/sqlglot/dialects/mysql.py index bae0e50358..e4de9348b9 100644 --- a/sqlglot/dialects/mysql.py +++ b/sqlglot/dialects/mysql.py @@ -193,6 +193,12 @@ class Parser(parser.Parser): TokenType.VALUES, } + CONJUNCTION = { + **parser.Parser.CONJUNCTION, + TokenType.DAMP: exp.And, + TokenType.XOR: exp.Xor, + } + TABLE_ALIAS_TOKENS = ( parser.Parser.TABLE_ALIAS_TOKENS - parser.Parser.TABLE_INDEX_HINT_TOKENS ) diff --git a/sqlglot/expressions.py b/sqlglot/expressions.py index 242e66ce65..28562c0c95 100644 --- a/sqlglot/expressions.py +++ b/sqlglot/expressions.py @@ -3517,6 +3517,10 @@ class Or(Connector): pass +class Xor(Connector): + pass + + class BitwiseAnd(Binary): pass diff --git a/sqlglot/generator.py b/sqlglot/generator.py index 4ac988f371..358858ac51 100644 --- a/sqlglot/generator.py +++ b/sqlglot/generator.py @@ -2016,6 +2016,9 @@ def add_sql(self, expression: exp.Add) -> str: def and_sql(self, expression: exp.And) -> str: return self.connector_sql(expression, "AND") + def xor_sql(self, expression: exp.And) -> str: + return self.connector_sql(expression, "XOR") + def connector_sql(self, expression: exp.Connector, op: str) -> str: if not self.pretty: return self.binary(expression, op) diff --git a/sqlglot/tokens.py b/sqlglot/tokens.py index 999bde231f..ed145949a8 100644 --- a/sqlglot/tokens.py +++ b/sqlglot/tokens.py @@ -52,6 +52,7 @@ class TokenType(AutoName): PARAMETER = auto() SESSION_PARAMETER = auto() DAMP = auto() + XOR = auto() BLOCK_START = auto() BLOCK_END = auto() @@ -590,6 +591,7 @@ class Tokenizer(metaclass=_Tokenizer): "OFFSET": TokenType.OFFSET, "ON": TokenType.ON, "OR": TokenType.OR, + "XOR": TokenType.XOR, "ORDER BY": TokenType.ORDER_BY, "ORDINALITY": TokenType.ORDINALITY, "OUTER": TokenType.OUTER, diff --git a/tests/dialects/test_mysql.py b/tests/dialects/test_mysql.py index 3539ad0a9e..70ffcd92c2 100644 --- a/tests/dialects/test_mysql.py +++ b/tests/dialects/test_mysql.py @@ -69,6 +69,8 @@ def test_ddl(self): ) def test_identity(self): + self.validate_identity("SELECT 1 XOR 0") + self.validate_identity("SELECT 1 && 0", "SELECT 1 AND 0") self.validate_identity("SELECT /*+ BKA(t1) NO_BKA(t2) */ * FROM t1 INNER JOIN t2") self.validate_identity("SELECT /*+ MERGE(dt) */ * FROM (SELECT * FROM t1) AS dt") self.validate_identity("SELECT /*+ INDEX(t, i) */ c1 FROM t WHERE c2 = 'value'")