Repository: tobymao/sqlglot

Issue:
subquery in limit or offset is compiled to syntactically invalid sql
**Fully reproducible code snippet**

I might be using sqlglot incorrectly, but I am trying to create the sqlglot-builder-equivalent version of this DuckDB query:

```sql
SELECT *
FROM t LIMIT (SELECT 5)
```

I looked at the parse tree:

```
In [8]: import sqlglot as sg

In [9]: sg.__version__
Out[9]: '18.5.2.dev11'

In [10]: sg.parse_one("select * from t limit (select 5)")
Out[10]:
(SELECT expressions:
  (STAR ), limit:
  (LIMIT expression:
    (SUBQUERY this:
      (SELECT expressions:
        (LITERAL this: 5, is_string: False)))), from:
  (FROM this:
    (TABLE this:
      (IDENTIFIER this: t, quoted: False))))
```

and then tried:

```
In [43]: sg.select("*").from_("t").limit(sg.select("5").subquery()).sql("duckdb")
Out[43]: 'SELECT * FROM t(SELECT 5) LIMIT'
```

For now what I am doing is:

```
In [44]: sg.select("*").from_("t").limit(sg.select("5").subquery().sql('duckdb')).sql("duckdb")
Out[44]: 'SELECT * FROM t LIMIT (SELECT 5)'
```

which generates the desired output.

**Official Documentation**

N/A



Discussion:
I think there is a bug in `Select.limit`: we're constructing the wrong AST by setting `Limit.this` instead of `Limit.expression`.

```python
>>> import sqlglot
>>> sqlglot.parse_one("select * from t limit (select 5)")
(SELECT expressions:
  (STAR ), limit:
  (LIMIT expression:
    (SUBQUERY this:
      (SELECT expressions:
        (LITERAL this: 5, is_string: False)))), from:
  (FROM this:
    (TABLE this:
      (IDENTIFIER this: t, quoted: False))))
>>> sqlglot.select("*").from_("t").limit(sqlglot.select("5").subquery())
(SELECT expressions:
  (STAR ), from:
  (FROM this:
    (TABLE this:
      (IDENTIFIER this: t, quoted: False))), limit:
  (LIMIT this:
    (SUBQUERY this:
      (SELECT expressions:
        (LITERAL this: 5, is_string: False)))))
```

In any case, thanks for the report @cpcloud, will take a closer look into this.

Resolving patch:
diff --git a/sqlglot/expressions.py b/sqlglot/expressions.py
--- a/sqlglot/expressions.py
+++ b/sqlglot/expressions.py
@@ -2861,6 +2861,7 @@ def limit(
             prefix="LIMIT",
             dialect=dialect,
             copy=copy,
+            into_arg="expression",
             **opts,
         )
 
@@ -5130,10 +5131,11 @@ def _apply_builder(
     prefix=None,
     into=None,
     dialect=None,
+    into_arg="this",
     **opts,
 ):
     if _is_wrong_expression(expression, into):
-        expression = into(this=expression)
+        expression = into(**{into_arg: expression})
     instance = maybe_copy(instance, copy)
     expression = maybe_parse(
         sql_or_expression=expression,


Test patch:
diff --git a/tests/dialects/test_duckdb.py b/tests/dialects/test_duckdb.py
--- a/tests/dialects/test_duckdb.py
+++ b/tests/dialects/test_duckdb.py
@@ -6,6 +6,11 @@ class TestDuckDB(Validator):
     dialect = "duckdb"
 
     def test_duckdb(self):
+        self.assertEqual(
+            parse_one("select * from t limit (select 5)").sql(dialect="duckdb"),
+            exp.select("*").from_("t").limit(exp.select("5").subquery()).sql(dialect="duckdb"),
+        )
+
         for join_type in ("SEMI", "ANTI"):
             exists = "EXISTS" if join_type == "SEMI" else "NOT EXISTS"