Repository: tobymao/sqlglot
Issue category: Bug Report

Issue:
“Default” is a keyword, but it was converted into a string value after translation.
```
Python 3.13.0 | packaged by Anaconda, Inc. | (main, Oct  7 2024, 16:25:56) [Clang 14.0.6 ] on darwin
Type "help", "copyright", "credits" or "license" for more information.
>>> import sqlglot
>>> sqlglot.transpile("insert into t(i) values (default)", read="mysql", write="duckdb")[0]
'INSERT INTO t (i) VALUES ("default")'
```


“Default” is a keyword, but it was converted into a string value after translation.


Hints:

Patch:
diff --git a/sqlglot/dialects/dialect.py b/sqlglot/dialects/dialect.py
index 5b12f56c0c..eca2bf592a 100644
--- a/sqlglot/dialects/dialect.py
+++ b/sqlglot/dialects/dialect.py
@@ -411,6 +411,9 @@ class Dialect(metaclass=_Dialect):
     is cast to x's type to match it instead.
     """
 
+    SUPPORTS_VALUES_DEFAULT = True
+    """Whether the DEFAULT keyword is supported in the VALUES clause."""
+
     REGEXP_EXTRACT_DEFAULT_GROUP = 0
     """The default value for the capturing group."""
 
diff --git a/sqlglot/dialects/presto.py b/sqlglot/dialects/presto.py
index ec702a097c..056d974c27 100644
--- a/sqlglot/dialects/presto.py
+++ b/sqlglot/dialects/presto.py
@@ -198,6 +198,7 @@ class Presto(Dialect):
     TYPED_DIVISION = True
     TABLESAMPLE_SIZE_IS_PERCENT = True
     LOG_BASE_FIRST: t.Optional[bool] = None
+    SUPPORTS_VALUES_DEFAULT = False
 
     TIME_MAPPING = MySQL.TIME_MAPPING
 
diff --git a/sqlglot/parser.py b/sqlglot/parser.py
index 2a477d9b90..12419e8c21 100644
--- a/sqlglot/parser.py
+++ b/sqlglot/parser.py
@@ -2946,8 +2946,13 @@ def _parse_partition(self) -> t.Optional[exp.Partition]:
         )
 
     def _parse_value(self) -> t.Optional[exp.Tuple]:
+        def _parse_value_expression() -> t.Optional[exp.Expression]:
+            if self.dialect.SUPPORTS_VALUES_DEFAULT and self._match(TokenType.DEFAULT):
+                return exp.var(self._prev.text.upper())
+            return self._parse_expression()
+
         if self._match(TokenType.L_PAREN):
-            expressions = self._parse_csv(self._parse_expression)
+            expressions = self._parse_csv(_parse_value_expression)
             self._match_r_paren()
             return self.expression(exp.Tuple, expressions=expressions)
 


Test patch:
diff --git a/tests/dialects/test_mysql.py b/tests/dialects/test_mysql.py
index fd6b36f1be..9e5b74e0bb 100644
--- a/tests/dialects/test_mysql.py
+++ b/tests/dialects/test_mysql.py
@@ -118,6 +118,13 @@ def test_ddl(self):
             "CREATE TABLE `foo` (a VARCHAR(10), INDEX idx_a (a DESC))",
         )
 
+        self.validate_all(
+            "insert into t(i) values (default)",
+            write={
+                "duckdb": "INSERT INTO t (i) VALUES (DEFAULT)",
+                "mysql": "INSERT INTO t (i) VALUES (DEFAULT)",
+            },
+        )
         self.validate_all(
             "CREATE TABLE t (id INT UNSIGNED)",
             write={