Repository: tobymao/sqlglot

Issue:
DuckDB `^` operator is parsed incorrectly as XOR when it should be POW
When testing SQLGlot with DuckDB, there is a parsing error when using the `^` operator in SQL statements. SQLGlot incorrectly translates this to the `XOR` function, whereas in DuckDB, the `^` operator is used for exponentiation (power).

#### Original Query:

```sql
SELECT ?::DOUBLE ^ ?::DOUBLE LIMIT 1
```

#### SQLGlot Translation:

```sql
SELECT XOR(CAST(? AS DOUBLE), CAST(? AS DOUBLE)) LIMIT 1
```

#### Expected Behavior:
The translation should retain the `^` operator, as it computes the power of `x` to `y` in DuckDB:

```sql
SELECT ?::DOUBLE ^ ?::DOUBLE LIMIT 1
```

#### DuckDB Reference:
By inspecting the DuckDB function definitions, the `^` operator is defined as the exponentiation function:
```sql
SELECT * FROM duckdb_functions() WHERE function_name = '^';
```

Discussion:

Solution patch:
diff --git a/sqlglot/dialects/duckdb.py b/sqlglot/dialects/duckdb.py
index 467152fb1e..8eb766b3c3 100644
--- a/sqlglot/dialects/duckdb.py
+++ b/sqlglot/dialects/duckdb.py
@@ -289,6 +289,7 @@ class Tokenizer(tokens.Tokenizer):
         KEYWORDS = {
             **tokens.Tokenizer.KEYWORDS,
             "//": TokenType.DIV,
+            "**": TokenType.DSTAR,
             "ATTACH": TokenType.COMMAND,
             "BINARY": TokenType.VARBINARY,
             "BITSTRING": TokenType.BIT,
@@ -325,6 +326,13 @@ class Parser(parser.Parser):
             **parser.Parser.BITWISE,
             TokenType.TILDA: exp.RegexpLike,
         }
+        BITWISE.pop(TokenType.CARET)
+
+        EXPONENT = {
+            **parser.Parser.EXPONENT,
+            TokenType.CARET: exp.Pow,
+            TokenType.DSTAR: exp.Pow,
+        }
 
         FUNCTIONS_WITH_ALIASED_ARGS = {*parser.Parser.FUNCTIONS_WITH_ALIASED_ARGS, "STRUCT_PACK"}
 


Test patch:
diff --git a/tests/dialects/test_duckdb.py b/tests/dialects/test_duckdb.py
index fe919b0a90..5925789ed5 100644
--- a/tests/dialects/test_duckdb.py
+++ b/tests/dialects/test_duckdb.py
@@ -864,6 +864,8 @@ def test_duckdb(self):
                 "redshift": UnsupportedError,
             },
         )
+        self.validate_identity("a ^ b", "POWER(a, b)")
+        self.validate_identity("a ** b", "POWER(a, b)")
 
     def test_array_index(self):
         with self.assertLogs(helper_logger) as cm: