Repository: tobymao/sqlglot

Issue:
TABLESAMPLE BERNOULLI doesn't translate from TrinoSQL to SparkSQL
`TABLESAMPLE BERNOULLI (50)` in TrinoSQL isn't translated cleanly to SparkSQL, as SparkSQL doesn't support `TABLESAMPLE BERNOULLI (50)`.  `TABLESAMPLE (50)` would be a fine translation -- it will use a random sampling, but the result will be similar. 


Discussion:
> TABLESAMPLE (50) would be a fine translation -- it will use a random sampling, but the result will be similar.

Don't think this form is supported in Spark either, see: https://spark.apache.org/docs/latest/sql-ref-syntax-qry-select-sampling.html

Example:

```sql
➜  sqlglot git:(main) spark-sql -e "WITH foo(x) AS (SELECT 1) SELECT * FROM foo TABLESAMPLE (50)"
Error in query:
50 is not a valid byte length literal, expected syntax: DIGIT+ ('B' | 'K' | 'M' | 'G')(line 1, pos 57)

== SQL ==
WITH foo(x) AS (SELECT 1) SELECT * FROM foo TABLESAMPLE (50)
---------------------------------------------------------^^^
```
Happy to tackle this, can take a look a bit later if someone doesn't beat me to it.

Resolving patch:
diff --git a/sqlglot/dialects/hive.py b/sqlglot/dialects/hive.py
--- a/sqlglot/dialects/hive.py
+++ b/sqlglot/dialects/hive.py
@@ -177,6 +177,7 @@ class Tokenizer(tokens.Tokenizer):
         IDENTIFIERS = ["`"]
         STRING_ESCAPES = ["\\"]
         ENCODE = "utf-8"
+        IDENTIFIER_CAN_START_WITH_DIGIT = True
 
         KEYWORDS = {
             **tokens.Tokenizer.KEYWORDS,
@@ -199,9 +200,8 @@ class Tokenizer(tokens.Tokenizer):
             "BD": "DECIMAL",
         }
 
-        IDENTIFIER_CAN_START_WITH_DIGIT = True
-
     class Parser(parser.Parser):
+        LOG_DEFAULTS_TO_LN = True
         STRICT_CAST = False
 
         FUNCTIONS = {
@@ -255,9 +255,11 @@ class Parser(parser.Parser):
             ),
         }
 
-        LOG_DEFAULTS_TO_LN = True
-
     class Generator(generator.Generator):
+        LIMIT_FETCH = "LIMIT"
+        TABLESAMPLE_WITH_METHOD = False
+        TABLESAMPLE_SIZE_IS_PERCENT = True
+
         TYPE_MAPPING = {
             **generator.Generator.TYPE_MAPPING,  # type: ignore
             exp.DataType.Type.TEXT: "STRING",
@@ -340,8 +342,6 @@ class Generator(generator.Generator):
             exp.TableFormatProperty: exp.Properties.Location.POST_SCHEMA,
         }
 
-        LIMIT_FETCH = "LIMIT"
-
         def arrayagg_sql(self, expression: exp.ArrayAgg) -> str:
             return self.func(
                 "COLLECT_LIST",
@@ -362,4 +362,5 @@ def datatype_sql(self, expression: exp.DataType) -> str:
                 expression = exp.DataType.build("text")
             elif expression.this in exp.DataType.TEMPORAL_TYPES:
                 expression = exp.DataType.build(expression.this)
+
             return super().datatype_sql(expression)
diff --git a/sqlglot/generator.py b/sqlglot/generator.py
--- a/sqlglot/generator.py
+++ b/sqlglot/generator.py
@@ -113,6 +113,12 @@ class Generator:
     # Whether or not the INTERVAL expression works only with values like '1 day'
     SINGLE_STRING_INTERVAL = False
 
+    # Whether or not the TABLESAMPLE clause supports a method name, like BERNOULLI
+    TABLESAMPLE_WITH_METHOD = True
+
+    # Whether or not to treat the number in TABLESAMPLE (50) as a percentage
+    TABLESAMPLE_SIZE_IS_PERCENT = False
+
     # Whether or not limit and fetch are supported (possible values: "ALL", "LIMIT", "FETCH")
     LIMIT_FETCH = "ALL"
 
@@ -1069,7 +1075,7 @@ def tablesample_sql(self, expression: exp.TableSample, seed_prefix: str = "SEED"
             this = self.sql(expression, "this")
             alias = ""
         method = self.sql(expression, "method")
-        method = f"{method.upper()} " if method else ""
+        method = f"{method.upper()} " if method and self.TABLESAMPLE_WITH_METHOD else ""
         numerator = self.sql(expression, "bucket_numerator")
         denominator = self.sql(expression, "bucket_denominator")
         field = self.sql(expression, "bucket_field")
@@ -1080,6 +1086,8 @@ def tablesample_sql(self, expression: exp.TableSample, seed_prefix: str = "SEED"
         rows = self.sql(expression, "rows")
         rows = f"{rows} ROWS" if rows else ""
         size = self.sql(expression, "size")
+        if size and self.TABLESAMPLE_SIZE_IS_PERCENT:
+            size = f"{size} PERCENT"
         seed = self.sql(expression, "seed")
         seed = f" {seed_prefix} ({seed})" if seed else ""
         kind = expression.args.get("kind", "TABLESAMPLE")


Test patch:
diff --git a/tests/dialects/test_hive.py b/tests/dialects/test_hive.py
--- a/tests/dialects/test_hive.py
+++ b/tests/dialects/test_hive.py
@@ -507,11 +507,10 @@ def test_hive(self):
             },
         )
         self.validate_all(
-            "SELECT * FROM x TABLESAMPLE(10) y",
+            "SELECT * FROM x TABLESAMPLE(10 PERCENT) y",
             write={
-                "presto": "SELECT * FROM x AS y TABLESAMPLE (10)",
-                "hive": "SELECT * FROM x TABLESAMPLE (10) AS y",
-                "spark": "SELECT * FROM x TABLESAMPLE (10) AS y",
+                "hive": "SELECT * FROM x TABLESAMPLE (10 PERCENT) AS y",
+                "spark": "SELECT * FROM x TABLESAMPLE (10 PERCENT) AS y",
             },
         )
         self.validate_all(
@@ -653,25 +652,13 @@ def test_hive(self):
             },
         )
         self.validate_all(
-            "SELECT * FROM x TABLESAMPLE (1) AS foo",
+            "SELECT * FROM x TABLESAMPLE (1 PERCENT) AS foo",
             read={
-                "presto": "SELECT * FROM x AS foo TABLESAMPLE (1)",
+                "presto": "SELECT * FROM x AS foo TABLESAMPLE BERNOULLI (1)",
             },
             write={
-                "presto": "SELECT * FROM x AS foo TABLESAMPLE (1)",
-                "hive": "SELECT * FROM x TABLESAMPLE (1) AS foo",
-                "spark": "SELECT * FROM x TABLESAMPLE (1) AS foo",
-            },
-        )
-        self.validate_all(
-            "SELECT * FROM x TABLESAMPLE (1) AS foo",
-            read={
-                "presto": "SELECT * FROM x AS foo TABLESAMPLE (1)",
-            },
-            write={
-                "presto": "SELECT * FROM x AS foo TABLESAMPLE (1)",
-                "hive": "SELECT * FROM x TABLESAMPLE (1) AS foo",
-                "spark": "SELECT * FROM x TABLESAMPLE (1) AS foo",
+                "hive": "SELECT * FROM x TABLESAMPLE (1 PERCENT) AS foo",
+                "spark": "SELECT * FROM x TABLESAMPLE (1 PERCENT) AS foo",
             },
         )
         self.validate_all(