Repository: tobymao/sqlglot

Issue:
Mysql syntax not fully supported/accurate
@VaggelisD @georgesittas 
```
import sqlglot

print(sqlglot.transpile("SELECT COUNT(DISTINCT(pl.identifier)) AS total_players, array_agg(pl.player_title) AS player_titles FROM playlogs pl WHERE pl.start >= (CURRENT_DATE - interval '1 week') GROUP BY pl.identifier, pl.player_title",  write="mysql")[0])
```

returns:
    
`SELECT COUNT(DISTINCT (pl.identifier)) AS total_players, ARRAY_AGG(pl.player_title) AS player_titles FROM playlogs AS pl WHERE pl.start >= (CURRENT_DATE - INTERVAL '1' WEEK) GROUP BY pl.identifier, pl.player_title`

expected:

`SELECT COUNT(DISTINCT pl.identifier) AS total_players, GROUP_CONCAT(pl.player_title) AS player_titles FROM playlogs pl WHERE pl.start >= DATE_SUB(CURRENT_DATE(), INTERVAL 1 WEEK) GROUP BY pl.identifier, pl.player_title`

Here is a list of replacements I have managed to log and correct, I know you have some of them but maybe check what you don't have from this list

```
def convert_sql_to_mysql(sql_query):
    sql_query = sql_query.lower()
    sql_query = sql_query.replace("extract(dow FROM", "weekday(")
    sql_query = sql_query.replace("interval '", "interval ")
    sql_query = sql_query.replace(" second'", " second")
    sql_query = sql_query.replace(" seconds'", " second")
    sql_query = sql_query.replace(" minute'", " minute")
    sql_query = sql_query.replace(" minutes'", " minute")
    sql_query = sql_query.replace(" hour'", " hour")
    sql_query = sql_query.replace(" hours'", " hour")
    sql_query = sql_query.replace(" day'", " day")
    sql_query = sql_query.replace(" days'", " day")
    sql_query = sql_query.replace(" week'", " week")
    sql_query = sql_query.replace(" weeks'", " week")
    sql_query = sql_query.replace(" month'", " month")
    sql_query = sql_query.replace(" months'", " month")
    sql_query = sql_query.replace(" year'", " year")
    sql_query = sql_query.replace(" years'", " year") 
    sql_query = sql_query.replace("::date", "")
    sql_query = sql_query.replace("nulls last", "")
    sql_query = sql_query.replace("ilike", "like")
    sql_query = sql_query.replace("::float", "")
    sql_query = sql_query.replace("to_char", "date_format")
    sql_query = sql_query.replace("hh24:mi:ss", "%H:%i:%s")
    sql_query = sql_query.replace("hh24:mi", "%H:%i")
    sql_query = sql_query.replace("yyyy-mm-dd", "%Y-%m-%d")
    sql_query = sql_query.replace("to_timestamp", "timestamp")
    sql_query = sql_query.replace("date_trunc('day',", "date(")
    sql_query = sql_query.replace("date_trunc('month', current_date)", "date_format(CURDATE(), '%Y-%m-01')")
    sql_query = sql_query.replace("date_trunc('week',", "week(")
    sql_query = sql_query.replace("date_part('year',", "year(")
    sql_query = sql_query.replace("date_part('month',", "month(")
    sql_query = sql_query.replace("date_part('week',", "week(")
    sql_query = sql_query.replace("::timestamp", "")
    sql_query = sql_query.replace("extract(dow from", "DAYNAME(")
    sql_query = sql_query.replace("date_trunc('month',", "MONTHNAME(")
    sql_query = sql_query.replace("to_date(", "str_to_date(")
    sql_query = sql_query.replace("timestamp(", "str_to_date(")
    sql_query = sql_query.replace("yyyy-mm", "%Y-%m")
    sql_query = sql_query.replace("yyyy", "%Y")
    sql_query = sql_query.replace("avg(extract(epoch from (", "avg(").replace("))))","))")
    sql_query = sql_query.replace("avg(extract(epoch from (", "avg(").replace(")))",")")
    sql_query = sql_query.replace("array_agg(", "group_concat(")

    return mysql_query = sql_query
```



Discussion:
@FaizelK this is unrelated to the `EXTRACT(epoch FROM ...)` [issue](https://github.com/tobymao/sqlglot/issues/3366#issuecomment-2082329344) you mentioned in the other thread, and the above example doesn't really indicate what's wrong with the generated SQL, or what the read dialect is. We'd appreciate it if you put more effort into future issues so that we can easily troubleshoot and fix them.

The interval subtraction and the `DATE_SUB` expression in the expected SQL have the same behavior:

```
mysql> SELECT CURRENT_DATE - INTERVAL '1' WEEK;
+----------------------------------+
| CURRENT_DATE - INTERVAL '1' WEEK |
+----------------------------------+
| 2024-04-22                       |
+----------------------------------+
1 row in set (0.00 sec)

mysql> SELECT DATE_SUB(CURRENT_DATE(), INTERVAL 1 WEEK);
+-------------------------------------------+
| DATE_SUB(CURRENT_DATE(), INTERVAL 1 WEEK) |
+-------------------------------------------+
| 2024-04-22                                |
+-------------------------------------------+
1 row in set (0.00 sec)
```

In any case, converting the former to the latter is out of scope for the reason outlined in https://github.com/tobymao/sqlglot/issues/3365#issuecomment-2081400718.

We're assuming the scope of this issue to be the just the `EXTRACT(EPOCH FROM value)` conversion that we discussed in the other thread.
@georgesittas 
Heres is the expected of the mentioned

```
import sqlglot

print(sqlglot.transpile("SELECT mt.mode_was, AVG(EXTRACT(epoch FROM (CAST(mt.cross_time AS DATETIME) - CAST(mt.second_cross_time AS DATETIME)))) AS average_time FROM main_table AS mt GROUP BY mt.mode_was ORDER BY CASE WHEN average_time IS NULL THEN 1 ELSE 0 END DESC, average_time DESC LIMIT 1",  write="mysql")[0])
```

returns

`SELECT mt.mode_was, AVG(EXTRACT(epoch FROM (CAST(mt.cross_time AS DATETIME) - CAST(mt.second_cross_time AS DATETIME)))) AS average_time FROM main_table AS mt GROUP BY mt.mode_was ORDER BY CASE WHEN average_time IS NULL THEN 1 ELSE 0 END DESC, average_time DESC LIMIT 1`

expected

`SELECT mt.mode_was, AVG(UNIX_TIMESTAMP(CAST(mt.cross_time AS DATETIME)) - UNIX_TIMESTAMP(CAST(mt.second_cross_time AS DATETIME))) AS average_time FROM main_table AS mt GROUP BY mt.mode_was ORDER BY IF(average_time IS NULL, 1, 0), average_time DESC LIMIT 1;`



Resolving patch:
diff --git a/sqlglot/dialects/mysql.py b/sqlglot/dialects/mysql.py
--- a/sqlglot/dialects/mysql.py
+++ b/sqlglot/dialects/mysql.py
@@ -782,6 +782,13 @@ class Generator(generator.Generator):
             exp.DataType.Type.TIMESTAMPLTZ,
         }
 
+        def extract_sql(self, expression: exp.Extract) -> str:
+            unit = expression.name
+            if unit and unit.lower() == "epoch":
+                return self.func("UNIX_TIMESTAMP", expression.expression)
+
+            return super().extract_sql(expression)
+
         def datatype_sql(self, expression: exp.DataType) -> str:
             # https://dev.mysql.com/doc/refman/8.0/en/numeric-type-syntax.html
             result = super().datatype_sql(expression)


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
@@ -598,6 +598,13 @@ def test_mysql_time(self):
         )
 
     def test_mysql(self):
+        self.validate_all(
+            "SELECT UNIX_TIMESTAMP(CAST('2024-04-29 12:00:00' AS DATETIME))",
+            read={
+                "mysql": "SELECT UNIX_TIMESTAMP(CAST('2024-04-29 12:00:00' AS DATETIME))",
+                "postgres": "SELECT EXTRACT(epoch FROM TIMESTAMP '2024-04-29 12:00:00')",
+            },
+        )
         self.validate_all(
             "SELECT JSON_EXTRACT('[10, 20, [30, 40]]', '$[1]')",
             read={