Repository: tobymao/sqlglot

Issue:
Oracle with ties not supported
When I try to parse a oracle sql like this:
```python
from sqlglot import parse_one, Dialects
query = 'select * from produto order by id desc fetch first 10 rows with ties'
parsed_query = parse_one(query, read=Dialects.ORACLE)
```
It outputs me:
```python
sqlglot.errors.ParseError: Invalid expression / Unexpected token. Line 1, Col: 60.
select * from produto order by id desc fetch first 10 rows with ties
```

How can I add support for this syntax?


Discussion:

Resolving patch:
diff --git a/sqlglot/expressions.py b/sqlglot/expressions.py
--- a/sqlglot/expressions.py
+++ b/sqlglot/expressions.py
@@ -1331,7 +1331,12 @@ class Partition(Expression):
 
 
 class Fetch(Expression):
-    arg_types = {"direction": False, "count": False}
+    arg_types = {
+        "direction": False,
+        "count": False,
+        "percent": False,
+        "with_ties": False,
+    }
 
 
 class Group(Expression):
diff --git a/sqlglot/generator.py b/sqlglot/generator.py
--- a/sqlglot/generator.py
+++ b/sqlglot/generator.py
@@ -784,7 +784,10 @@ def fetch_sql(self, expression: exp.Fetch) -> str:
         direction = f" {direction.upper()}" if direction else ""
         count = expression.args.get("count")
         count = f" {count}" if count else ""
-        return f"{self.seg('FETCH')}{direction}{count} ROWS ONLY"
+        if expression.args.get("percent"):
+            count = f"{count} PERCENT"
+        with_ties_or_only = "WITH TIES" if expression.args.get("with_ties") else "ONLY"
+        return f"{self.seg('FETCH')}{direction}{count} ROWS {with_ties_or_only}"
 
     def filter_sql(self, expression: exp.Filter) -> str:
         this = self.sql(expression, "this")
diff --git a/sqlglot/parser.py b/sqlglot/parser.py
--- a/sqlglot/parser.py
+++ b/sqlglot/parser.py
@@ -2465,10 +2465,25 @@ def _parse_limit(
         if self._match(TokenType.FETCH):
             direction = self._match_set((TokenType.FIRST, TokenType.NEXT))
             direction = self._prev.text if direction else "FIRST"
+
             count = self._parse_number()
+            percent = self._match(TokenType.PERCENT)
+
             self._match_set((TokenType.ROW, TokenType.ROWS))
-            self._match(TokenType.ONLY)
-            return self.expression(exp.Fetch, direction=direction, count=count)
+
+            only = self._match(TokenType.ONLY)
+            with_ties = self._match_text_seq("WITH", "TIES")
+
+            if only and with_ties:
+                self.raise_error("Cannot specify both ONLY and WITH TIES in FETCH clause")
+
+            return self.expression(
+                exp.Fetch,
+                direction=direction,
+                count=count,
+                percent=percent,
+                with_ties=with_ties,
+            )
 
         return this
 


Test patch:
diff --git a/tests/fixtures/identity.sql b/tests/fixtures/identity.sql
--- a/tests/fixtures/identity.sql
+++ b/tests/fixtures/identity.sql
@@ -252,6 +252,8 @@ SELECT * FROM test LIMIT 1 + 1
 SELECT * FROM test LIMIT 100 OFFSET 200
 SELECT * FROM test FETCH FIRST ROWS ONLY
 SELECT * FROM test FETCH FIRST 1 ROWS ONLY
+SELECT * FROM test ORDER BY id DESC FETCH FIRST 10 ROWS WITH TIES
+SELECT * FROM test ORDER BY id DESC FETCH FIRST 10 PERCENT ROWS WITH TIES
 SELECT * FROM test FETCH NEXT 1 ROWS ONLY
 SELECT (1 > 2) AS x FROM test
 SELECT NOT (1 > 2) FROM test