From e17a0953609ea7b075a830030d1cbfb646464b86 Mon Sep 17 00:00:00 2001
From: tobymao <toby.mao@gmail.com>
Date: Fri, 5 May 2023 10:04:39 -0700
Subject: [PATCH] Fix: postgres exponent precedence closes #1555

---
 sqlglot/__init__.py             |  2 +-
 sqlglot/dialects/postgres.py    | 11 +++++++++--
 tests/dialects/test_postgres.py |  8 ++++++++
 3 files changed, 18 insertions(+), 3 deletions(-)

diff --git a/sqlglot/__init__.py b/sqlglot/__init__.py
index 6f73061f93..8a68767a57 100644
--- a/sqlglot/__init__.py
+++ b/sqlglot/__init__.py
@@ -181,7 +181,7 @@ def transpile(
     Returns:
         The list of transpiled SQL statements.
     """
-    write = write or read if identity else write
+    write = (read if write is None else write) if identity else write
     return [
         Dialect.get_or_raise(write)().generate(expression, **opts)
         for expression in parse(sql, read, error_level=error_level)
diff --git a/sqlglot/dialects/postgres.py b/sqlglot/dialects/postgres.py
index 4ff6d0183c..2132778606 100644
--- a/sqlglot/dialects/postgres.py
+++ b/sqlglot/dialects/postgres.py
@@ -1,5 +1,7 @@
 from __future__ import annotations
 
+import typing as t
+
 from sqlglot import exp, generator, parser, tokens, transforms
 from sqlglot.dialects.dialect import (
     Dialect,
@@ -273,8 +275,7 @@ class Parser(parser.Parser):
             TokenType.HASH: exp.BitwiseXor,
         }
 
-        FACTOR = {
-            **parser.Parser.FACTOR,
+        EXPONENT = {
             TokenType.CARET: exp.Pow,
         }
 
@@ -285,6 +286,12 @@ class Parser(parser.Parser):
             TokenType.LT_AT: binary_range_parser(exp.ArrayContained),
         }
 
+        def _parse_factor(self) -> t.Optional[exp.Expression]:
+            return self._parse_tokens(self._parse_exponent, self.FACTOR)
+
+        def _parse_exponent(self) -> t.Optional[exp.Expression]:
+            return self._parse_tokens(self._parse_unary, self.EXPONENT)
+
         def _parse_date_part(self) -> exp.Expression:
             part = self._parse_type()
             self._match(TokenType.COMMA)
diff --git a/tests/dialects/test_postgres.py b/tests/dialects/test_postgres.py
index 952bb7ff14..b53638f297 100644
--- a/tests/dialects/test_postgres.py
+++ b/tests/dialects/test_postgres.py
@@ -491,6 +491,14 @@ def test_postgres(self):
             },
         )
 
+        self.validate_all(
+            "x / y ^ z",
+            write={
+                "": "x / POWER(y, z)",
+                "postgres": "x / y ^ z",
+            },
+        )
+
         self.assertIsInstance(parse_one("id::UUID", read="postgres"), exp.TryCast)
 
     def test_bool_or(self):