Repository: tobymao/sqlglot

Issue:
function from_unixtime trans error
source code:
from sqlglot import transpile
print(transpile("select from_unixtime(1711366265)", read="mysql", write="postgres"))
print(transpile("select from_unixtime(1711366265)", read="mysql", write="redshift"))

// output 
['SELECT FROM_UNIXTIME(1711366265)']
['SELECT FROM_UNIXTIME(1711366265)']

but postgres and redshift has no function from_unixtime,  will post error


Discussion:

Resolving patch:
diff --git a/sqlglot/dialects/mysql.py b/sqlglot/dialects/mysql.py
--- a/sqlglot/dialects/mysql.py
+++ b/sqlglot/dialects/mysql.py
@@ -291,6 +291,7 @@ class Parser(parser.Parser):
             "DAYOFWEEK": lambda args: exp.DayOfWeek(this=exp.TsOrDsToDate(this=seq_get(args, 0))),
             "DAYOFYEAR": lambda args: exp.DayOfYear(this=exp.TsOrDsToDate(this=seq_get(args, 0))),
             "INSTR": lambda args: exp.StrPosition(substr=seq_get(args, 1), this=seq_get(args, 0)),
+            "FROM_UNIXTIME": build_formatted_time(exp.UnixToTime, "mysql"),
             "ISNULL": isnull_to_is_null,
             "LOCATE": locate_to_strposition,
             "MAKETIME": exp.TimeFromParts.from_arg_list,
@@ -720,6 +721,7 @@ class Generator(generator.Generator):
             exp.TsOrDsAdd: _date_add_sql("ADD"),
             exp.TsOrDsDiff: lambda self, e: self.func("DATEDIFF", e.this, e.expression),
             exp.TsOrDsToDate: _ts_or_ds_to_date_sql,
+            exp.UnixToTime: lambda self, e: self.func("FROM_UNIXTIME", e.this, self.format_time(e)),
             exp.Week: _remove_ts_or_ds_to_date(),
             exp.WeekOfYear: _remove_ts_or_ds_to_date(rename_func("WEEKOFYEAR")),
             exp.Year: _remove_ts_or_ds_to_date(),
diff --git a/sqlglot/dialects/redshift.py b/sqlglot/dialects/redshift.py
--- a/sqlglot/dialects/redshift.py
+++ b/sqlglot/dialects/redshift.py
@@ -176,6 +176,8 @@ class Generator(Postgres.Generator):
             exp.TableSample: no_tablesample_sql,
             exp.TsOrDsAdd: date_delta_sql("DATEADD"),
             exp.TsOrDsDiff: date_delta_sql("DATEDIFF"),
+            exp.UnixToTime: lambda self,
+            e: f"(TIMESTAMP 'epoch' + {self.sql(e.this)} * INTERVAL '1 SECOND')",
         }
 
         # Postgres maps exp.Pivot to no_pivot_sql, but Redshift support pivots
diff --git a/sqlglot/expressions.py b/sqlglot/expressions.py
--- a/sqlglot/expressions.py
+++ b/sqlglot/expressions.py
@@ -5707,7 +5707,14 @@ class UnixToStr(Func):
 # https://prestodb.io/docs/current/functions/datetime.html
 # presto has weird zone/hours/minutes
 class UnixToTime(Func):
-    arg_types = {"this": True, "scale": False, "zone": False, "hours": False, "minutes": False}
+    arg_types = {
+        "this": True,
+        "scale": False,
+        "zone": False,
+        "hours": False,
+        "minutes": False,
+        "format": False,
+    }
 
     SECONDS = Literal.number(0)
     DECIS = Literal.number(1)


Test patch:
diff --git a/tests/dialects/test_mysql.py b/tests/dialects/test_mysql.py
--- a/tests/dialects/test_mysql.py
+++ b/tests/dialects/test_mysql.py
@@ -513,9 +513,8 @@ def test_date_format(self):
         )
 
     def test_mysql_time(self):
-        self.validate_identity("FROM_UNIXTIME(a, b)")
-        self.validate_identity("FROM_UNIXTIME(a, b, c)")
         self.validate_identity("TIME_STR_TO_UNIX(x)", "UNIX_TIMESTAMP(x)")
+        self.validate_identity("SELECT FROM_UNIXTIME(1711366265, '%Y %D %M')")
         self.validate_all(
             "SELECT TO_DAYS(x)",
             write={
@@ -581,6 +580,17 @@ def test_mysql_time(self):
         self.validate_all(
             "STR_TO_DATE(x, '%Y-%m-%dT%T')", write={"presto": "DATE_PARSE(x, '%Y-%m-%dT%T')"}
         )
+        self.validate_all(
+            "SELECT FROM_UNIXTIME(col)",
+            read={
+                "postgres": "SELECT TO_TIMESTAMP(col)",
+            },
+            write={
+                "mysql": "SELECT FROM_UNIXTIME(col)",
+                "postgres": "SELECT TO_TIMESTAMP(col)",
+                "redshift": "SELECT (TIMESTAMP 'epoch' + col * INTERVAL '1 SECOND')",
+            },
+        )
 
     def test_mysql(self):
         self.validate_all(