Repository: DerekStride/tree-sitter-sql (language: python)

Issue:
`group_concat` as generic `invocation`
In 8c0ca863 `group_concat` was introduced. However, this function exists in other dialects was well with a different internal structure (aka the parameters of the list)

e.g.
```sql
select
    group_concat(col1, ',')
from tab
```

This statement is not parsed correctly. I think `group_concat` should a generic node of type `invocation`

Alternatively, implement the complete internal expression syntax. It looks quite similar between MariaDB, MySQL and Impala. In that example above, the optional separator is missing.
fix: `group_concat` on impala
`group_concat` is slightly different on impala. Instead of the keyword `separator` the sep char is written after a comma.


I am not happy with the fact that we have invocation and this second line of _aggregate_functions. Imo they should be also invocations but might be difficult to add every variant of `invocations`

Closes #158 


Discussion / hints:

Ping @DerekStride @dmfay What do you think regarding `group_concat`?
It has exactly the same purpose as `string_agg`. I also raised this question in the linked issue. I don't think it should be a separate thing.

`group_concat`in MySQL and MariaDB seem to have their own style and are not just simple invocations (parameter list is different) That's why is was implemented separately.
what about adding an aggregate path in `invocation`? this conflicts with `term` atm but I think we could make it work

```js
    invocation: $ => seq(
      field('name', $.identifier),
      choice(
        paren_list(
          seq(
            optional($.keyword_distinct),
            field(
              'parameter',
              $._select_expression,
            ),
            optional($.order_by)
          )),
        seq(
          '(',
          optional($.keyword_distinct),
          field('parameter', choice($._expression, $.all_fields)),
          optional($.order_by),
          optional(seq(
            choice($.keyword_separator, ','),
            alias($._literal_string, $.literal)
          )),
          ')',
        ),
      ),
    ),
```
That looks good. I just had a similar idea. 

Fix patch:
diff --git a/grammar.js b/grammar.js
index 21e4588d..da39aada 100644
--- a/grammar.js
+++ b/grammar.js
@@ -97,7 +97,6 @@ module.exports = grammar({
     keyword_distinct: _ => make_keyword("distinct"),
     keyword_constraint: _ => make_keyword("constraint"),
     keyword_cast: _ => make_keyword("cast"),
-    keyword_group_concat: _ => make_keyword("group_concat"),
     keyword_separator: _ => make_keyword("separator"),
     keyword_max: _ => make_keyword("max"),
     keyword_min: _ => make_keyword("min"),
@@ -1933,36 +1932,34 @@ module.exports = grammar({
       ')',
     ),
 
-    _aggregate_function: $ => choice(
-      $.group_concat,
-    ),
-
-    group_concat: $ => seq(
-      field('name', $.keyword_group_concat),
-      '(',
-      $._aggregate_expression,
-      optional(seq($.keyword_separator, alias($._literal_string, $.literal))),
-      ')',
-    ),
-
-    _aggregate_expression: $ => seq(
-      optional($.keyword_distinct),
-      field('parameter', choice($._expression, $.all_fields)),
-      optional($.order_by),
-    ),
-
     invocation: $ => prec(1,
       seq(
         $.object_reference,
-        paren_list(
+        choice(
+          // default invocation
+          paren_list(
+            seq(
+              optional($.keyword_distinct),
+              field(
+                'parameter',
+                $.term,
+              ),
+              optional($.order_by)
+            )
+          ),
+          // _aggregate_function, e.g. group_concat
           seq(
+            '(',
             optional($.keyword_distinct),
-            field(
-              'parameter',
-              $.term,
-            ),
-            optional($.order_by)
-          )
+            field('parameter', $.term),
+            optional($.order_by),
+            optional(seq(
+              choice($.keyword_separator, ','),
+              alias($._literal_string, $.literal)
+            )),
+            optional($.limit),
+            ')',
+          ),
         ),
       ),
     ),
@@ -2319,7 +2316,6 @@ module.exports = grammar({
         $.subquery,
         $.cast,
         alias($.implicit_cast, $.cast),
-        $._aggregate_function,
         $.exists,
         $.invocation,
         $.binary_expression,
diff --git a/queries/highlights.scm b/queries/highlights.scm
index 60251f0b..6b324ff3 100644
--- a/queries/highlights.scm
+++ b/queries/highlights.scm
@@ -11,7 +11,6 @@
   (keyword_brin)
   (keyword_float)
   (keyword_array)
-  (keyword_group_concat)
 ] @function.call
 
 (object_reference


Test patch:
diff --git a/test/corpus/functions.txt b/test/corpus/functions.txt
index 07eacda8..faf4ada6 100644
--- a/test/corpus/functions.txt
+++ b/test/corpus/functions.txt
@@ -208,10 +208,12 @@ GROUP BY some_field;
       (keyword_select)
       (select_expression
         (term
-          value: (group_concat
-            name: (keyword_group_concat)
-            parameter: (field
+          value: (invocation
+            (object_reference
               name: (identifier))
+            parameter: (term
+              value: (field
+                name: (identifier)))
             (keyword_separator)
             (literal)))))
     (from
@@ -241,11 +243,13 @@ GROUP BY some_field;
       (keyword_select)
       (select_expression
         (term
-          value: (group_concat
-            name: (keyword_group_concat)
-            (keyword_distinct)
-            parameter: (field
+          value: (invocation
+            (object_reference
               name: (identifier))
+            (keyword_distinct)
+            parameter: (term
+              value: (field
+                name: (identifier)))
             (order_by
               (keyword_order)
               (keyword_by)
@@ -267,6 +271,41 @@ GROUP BY some_field;
         (field
           name: (identifier))))))
 
+================================================================================
+GROUP CONCAT Impala
+================================================================================
+
+SELECT GROUP_CONCAT(uid, ",")
+FROM some_table
+GROUP BY some_field;
+
+--------------------------------------------------------------------------------
+
+(program
+  (statement
+    (select
+      (keyword_select)
+      (select_expression
+        (term
+          value: (invocation
+            (object_reference
+              name: (identifier))
+            parameter: (term
+              value: (field
+                name: (identifier)))
+            parameter: (term
+              value: (literal))))))
+    (from
+      (keyword_from)
+      (relation
+        (object_reference
+          name: (identifier)))
+      (group_by
+        (keyword_group)
+        (keyword_by)
+        (field
+          name: (identifier))))))
+
 ================================================================================
 Unary ANY, ALL, SOME
 ================================================================================
@@ -284,7 +323,8 @@ WHERE id = ANY (
     (select
       (keyword_select)
       (select_expression
-        (term value: (all_fields))))
+        (term
+          value: (all_fields))))
     (from
       (keyword_from)
       (relation
@@ -322,7 +362,8 @@ WHERE id IN (
     (select
       (keyword_select)
       (select_expression
-        (term value: (all_fields))))
+        (term
+          value: (all_fields))))
     (from
       (keyword_from)
       (relation
@@ -371,7 +412,8 @@ WHERE (
     (select
       (keyword_select)
       (select_expression
-        (term value: (all_fields))))
+        (term
+          value: (all_fields))))
     (from
       (keyword_from)
       (relation
diff --git a/test/corpus/group_by.txt b/test/corpus/group_by.txt
index 77503eaf..034bab3a 100644
--- a/test/corpus/group_by.txt
+++ b/test/corpus/group_by.txt
@@ -166,5 +166,6 @@ HAVING COUNT(*) = 2;
           left: (invocation
             (object_reference
               name: (identifier))
-            parameter: (term value: (all_fields)))
+            parameter: (term
+              value: (all_fields)))
           right: (literal))))))
diff --git a/test/corpus/select.txt b/test/corpus/select.txt
index aca5b2c7..f997024c 100644
--- a/test/corpus/select.txt
+++ b/test/corpus/select.txt
@@ -57,7 +57,8 @@ SELECT * FROM my_table;
     (select
       (keyword_select)
       (select_expression
-        (term value: (all_fields))))
+        (term
+          value: (all_fields))))
     (from
       (keyword_from)
       (relation
@@ -77,7 +78,8 @@ SELECT * FROM ONLY my_table;
     (select
       (keyword_select)
       (select_expression
-        (term value: (all_fields))))
+        (term
+          value: (all_fields))))
     (from
       (keyword_from)
       (keyword_only)
@@ -648,7 +650,8 @@ SELECT * FROM my_schema.my_table;
     (select
       (keyword_select)
       (select_expression
-        (term value: (all_fields))))
+        (term
+          value: (all_fields))))
     (from
       (keyword_from)
       (relation
@@ -778,8 +781,8 @@ FROM my_table;
               name: (identifier))
             (keyword_distinct)
             parameter: (term
-                  value: (field
-                    name: (identifier)))))))
+              value: (field
+                name: (identifier)))))))
     (from
       (keyword_from)
       (relation
@@ -803,7 +806,8 @@ FROM my_table;
           value: (invocation
             (object_reference
               name: (identifier))
-            parameter: (term value: (all_fields))))))
+            parameter: (term
+              value: (all_fields))))))
     (from
       (keyword_from)
       (relation
@@ -910,7 +914,8 @@ JOIN my_other_table ON TRUE;
     (select
       (keyword_select)
       (select_expression
-        (term value: (all_fields))))
+        (term
+          value: (all_fields))))
     (from
       (keyword_from)
       (relation
@@ -1086,7 +1091,8 @@ JOIN (VALUES (1, 2), (3, 4)) AS v (col1, col2) ON TRUE;
     (select
       (keyword_select)
       (select_expression
-        (term value: (all_fields))))
+        (term
+          value: (all_fields))))
     (from
       (keyword_from)
       (relation
@@ -1314,8 +1320,8 @@ JOIN LATERAL unnest(a.arr) AS arr ON TRUE;
             name: (identifier))
           parameter: (term
             value: (field
-            (object_reference
-              name: (identifier))
+              (object_reference
+                name: (identifier))
               name: (identifier))))
         (keyword_as)
         alias: (identifier)
@@ -1457,12 +1463,12 @@ ON c.id = d.c_id;
           (keyword_on)
           predicate: (binary_expression
             left: (field
-            (object_reference
-              name: (identifier))
+              (object_reference
+                name: (identifier))
               name: (identifier))
             right: (field
-            (object_reference
-              name: (identifier))
+              (object_reference
+                name: (identifier))
               name: (identifier))))
         (keyword_on)
         predicate: (binary_expression
@@ -1508,8 +1514,8 @@ ORDER BY m.title, id ASC;
         predicate: (binary_expression
           left: (binary_expression
             left: (field
-            (object_reference
-              name: (identifier))
+              (object_reference
+                name: (identifier))
               name: (identifier))
             right: (literal))
           operator: (keyword_and)
@@ -2079,7 +2085,8 @@ FROM
     (select
       (keyword_select)
       (select_expression
-        (term value: (all_fields))))
+        (term
+          value: (all_fields))))
     (from
       (keyword_from)
       (relation
@@ -2114,7 +2121,8 @@ WHERE id = ?;
     (select
       (keyword_select)
       (select_expression
-        (term value: (all_fields))))
+        (term
+          value: (all_fields))))
     (from
       (keyword_from)
       (relation
@@ -2142,7 +2150,8 @@ WHERE id = $12;
     (select
       (keyword_select)
       (select_expression
-        (term value: (all_fields))))
+        (term
+          value: (all_fields))))
     (from
       (keyword_from)
       (relation
@@ -2180,7 +2189,8 @@ FROM
           (select
             (keyword_select)
             (select_expression
-              (term value: (all_fields))))
+              (term
+                value: (all_fields))))
           (from
             (keyword_from)
             (relation
@@ -2205,7 +2215,8 @@ FROM
     (select
       (keyword_select)
       (select_expression
-        (term value: (all_fields))))
+        (term
+          value: (all_fields))))
     (from
       (keyword_from)
       (relation
@@ -2253,7 +2264,8 @@ FROM test_data;
         (select
           (keyword_select)
           (select_expression
-            (term value: (all_fields))))
+            (term
+              value: (all_fields))))
         (from
           (keyword_from)
           (relation
@@ -2301,7 +2313,8 @@ FROM some_table s
     (select
       (keyword_select)
       (select_expression
-        (term value: (all_fields))))
+        (term
+          value: (all_fields))))
     (from
       (keyword_from)
       (relation
diff --git a/test/corpus/window_functions.txt b/test/corpus/window_functions.txt
index 2efd8d7a..0971dec2 100644
--- a/test/corpus/window_functions.txt
+++ b/test/corpus/window_functions.txt
@@ -739,7 +739,8 @@ FROM tab1
             (invocation
               (object_reference
                 name: (identifier))
-              parameter: (term value: (all_fields)))
+              parameter: (term
+                value: (all_fields)))
             (keyword_over)
             (window_specification
               (partition_by