Skip to content

Commit bd26cf1

Browse files
Merge pull request #1895 from taozhi8833998/fix-string-agg-func-pg
fix: string_agg function in pg
2 parents 9970976 + 7d065a2 commit bd26cf1

File tree

7 files changed

+69
-47
lines changed

7 files changed

+69
-47
lines changed

pegjs/noql.pegjs

Lines changed: 9 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -4286,16 +4286,16 @@ aggr_fun_count
42864286
}
42874287

42884288
concat_separator
4289-
= kw:'SEPARATOR'i? __ s:literal_string {
4290-
// => { keyword: string | null; value: literal_string; }
4289+
= kw:COMMA __ s:literal_string {
4290+
// => { symbol: ','; delimiter: literal_string; }
42914291
return {
4292-
keyword: kw,
4293-
value: s
4292+
symbol: ke,
4293+
delimiter: s
42944294
}
42954295
}
42964296

42974297
distinct_args
4298-
= d:KW_DISTINCT? __ LPAREN __ c:expr __ RPAREN __ tail:(__ (KW_AND / KW_OR) __ expr)* __ or:order_by_clause? __ s:concat_separator? {
4298+
= d:KW_DISTINCT? __ LPAREN __ c:expr __ RPAREN __ tail:(__ (KW_AND / KW_OR) __ expr)* __ s:concat_separator? __ or:order_by_clause? {
42994299
/* => { distinct: 'DISTINCT'; expr: expr; orderby?: order_by_clause; separator?: concat_separator; } */
43004300
const len = tail.length
43014301
let result = c
@@ -4310,7 +4310,7 @@ distinct_args
43104310
separator: s
43114311
};
43124312
}
4313-
/ d:KW_DISTINCT? __ c:or_and_expr __ or:order_by_clause? __ s:concat_separator? {
4313+
/ d:KW_DISTINCT? __ c:or_and_expr __ s:concat_separator? __ or:order_by_clause? {
43144314
/* => { distinct: 'DISTINCT'; expr: expr; orderby?: order_by_clause; separator?: concat_separator; } */
43154315
return { distinct: d, expr: c, orderby: or, separator: s };
43164316
}
@@ -4320,13 +4320,12 @@ count_arg
43204320
/ distinct_args
43214321

43224322
aggr_array_agg
4323-
= pre:(ident __ DOT)? __ name:KW_ARRAY_AGG __ LPAREN __ arg:distinct_args __ o:order_by_clause? __ RPAREN {
4324-
// => { type: 'aggr_func'; args:count_arg; name: 'ARRAY_AGG'; orderby?: order_by_clause }
4323+
= pre:(ident __ DOT)? __ name:(KW_ARRAY_AGG / KW_STRING_AGG) __ LPAREN __ arg:distinct_args __ RPAREN {
4324+
// => { type: 'aggr_func'; args:count_arg; name: 'ARRAY_AGG' | 'STRING_AGG'; }
43254325
return {
43264326
type: 'aggr_func',
43274327
name: pre ? `${pre[0]}.${name}` : name,
43284328
args: arg,
4329-
orderby: o,
43304329
};
43314330
}
43324331

@@ -4837,6 +4836,7 @@ KW_OR = "OR"i !ident_start { return 'OR'; }
48374836

48384837
KW_ARRAY = "ARRAY"i !ident_start { return 'ARRAY'; }
48394838
KW_ARRAY_AGG = "ARRAY_AGG"i !ident_start { return 'ARRAY_AGG'; }
4839+
KW_STRING_AGG = "STRING_AGG"i !ident_start { return 'STRING_AGG'; }
48404840
KW_COUNT = "COUNT"i !ident_start { return 'COUNT'; }
48414841
KW_GROUP_CONCAT = "GROUP_CONCAT"i !ident_start { return 'GROUP_CONCAT'; }
48424842
KW_MAX = "MAX"i !ident_start { return 'MAX'; }

pegjs/postgresql.pegjs

Lines changed: 9 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -4496,16 +4496,16 @@ aggr_fun_count
44964496
}
44974497

44984498
concat_separator
4499-
= kw:'SEPARATOR'i? __ s:literal_string {
4500-
// => { keyword: string | null; value: literal_string; }
4499+
= kw:COMMA __ s:literal_string {
4500+
// => { symbol: ','; delimiter: literal_string; }
45014501
return {
4502-
keyword: kw,
4503-
value: s
4502+
symbol: kw,
4503+
delimiter: s
45044504
}
45054505
}
45064506

45074507
distinct_args
4508-
= d:KW_DISTINCT? __ LPAREN __ c:expr __ RPAREN __ tail:(__ (KW_AND / KW_OR) __ expr)* __ or:order_by_clause? __ s:concat_separator? {
4508+
= d:KW_DISTINCT? __ LPAREN __ c:expr __ RPAREN __ tail:(__ (KW_AND / KW_OR) __ expr)* __ s:concat_separator? __ or:order_by_clause? {
45094509
/* => { distinct: 'DISTINCT'; expr: expr; orderby?: order_by_clause; separator?: concat_separator; } */
45104510
const len = tail.length
45114511
let result = c
@@ -4520,7 +4520,7 @@ distinct_args
45204520
separator: s
45214521
};
45224522
}
4523-
/ d:KW_DISTINCT? __ c:or_and_expr __ or:order_by_clause? __ s:concat_separator? {
4523+
/ d:KW_DISTINCT? __ c:or_and_expr __ s:concat_separator? __ or:order_by_clause? {
45244524
/* => { distinct: 'DISTINCT'; expr: expr; orderby?: order_by_clause; separator?: concat_separator; } */
45254525
return { distinct: d, expr: c, orderby: or, separator: s };
45264526
}
@@ -4530,13 +4530,12 @@ count_arg
45304530
/ distinct_args
45314531

45324532
aggr_array_agg
4533-
= pre:(ident __ DOT)? __ name:KW_ARRAY_AGG __ LPAREN __ arg:distinct_args __ o:order_by_clause? __ RPAREN {
4534-
// => { type: 'aggr_func'; args:count_arg; name: 'ARRAY_AGG'; orderby?: order_by_clause }
4533+
= pre:(ident __ DOT)? __ name:(KW_ARRAY_AGG / KW_STRING_AGG) __ LPAREN __ arg:distinct_args __ RPAREN {
4534+
// => { type: 'aggr_func'; args:count_arg; name: 'ARRAY_AGG' | 'STRING_AGG'; }
45354535
return {
45364536
type: 'aggr_func',
45374537
name: pre ? `${pre[0]}.${name}` : name,
45384538
args: arg,
4539-
orderby: o,
45404539
};
45414540
}
45424541

@@ -5048,6 +5047,7 @@ KW_OR = "OR"i !ident_start { return 'OR'; }
50485047

50495048
KW_ARRAY = "ARRAY"i !ident_start { return 'ARRAY'; }
50505049
KW_ARRAY_AGG = "ARRAY_AGG"i !ident_start { return 'ARRAY_AGG'; }
5050+
KW_STRING_AGG = "STRING_AGG"i !ident_start { return 'STRING_AGG'; }
50515051
KW_COUNT = "COUNT"i !ident_start { return 'COUNT'; }
50525052
KW_GROUP_CONCAT = "GROUP_CONCAT"i !ident_start { return 'GROUP_CONCAT'; }
50535053
KW_MAX = "MAX"i !ident_start { return 'MAX'; }

pegjs/redshift.pegjs

Lines changed: 9 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -4350,16 +4350,16 @@ aggr_fun_count
43504350
}
43514351

43524352
concat_separator
4353-
= kw:'SEPARATOR'i? __ s:literal_string {
4354-
// => { keyword: string | null; value: literal_string; }
4353+
= kw:COMMA __ s:literal_string {
4354+
// => { symbol: ','; delimiter: literal_string; }
43554355
return {
4356-
keyword: kw,
4357-
value: s
4356+
symbol: ke,
4357+
delimiter: s
43584358
}
43594359
}
43604360

43614361
distinct_args
4362-
= d:KW_DISTINCT? __ LPAREN __ c:expr __ RPAREN __ tail:(__ (KW_AND / KW_OR) __ expr)* __ or:order_by_clause? __ s:concat_separator? {
4362+
= d:KW_DISTINCT? __ LPAREN __ c:expr __ RPAREN __ tail:(__ (KW_AND / KW_OR) __ expr)* __ s:concat_separator? __ or:order_by_clause? {
43634363
/* => { distinct: 'DISTINCT'; expr: expr; orderby?: order_by_clause; separator?: concat_separator; } */
43644364
const len = tail.length
43654365
let result = c
@@ -4374,7 +4374,7 @@ distinct_args
43744374
separator: s
43754375
};
43764376
}
4377-
/ d:KW_DISTINCT? __ c:or_and_expr __ or:order_by_clause? __ s:concat_separator? {
4377+
/ d:KW_DISTINCT? __ c:or_and_expr __ s:concat_separator? __ or:order_by_clause? {
43784378
/* => { distinct: 'DISTINCT'; expr: expr; orderby?: order_by_clause; separator?: concat_separator; } */
43794379
return { distinct: d, expr: c, orderby: or, separator: s };
43804380
}
@@ -4384,13 +4384,12 @@ count_arg
43844384
/ distinct_args
43854385

43864386
aggr_array_agg
4387-
= pre:(ident __ DOT)? __ name:KW_ARRAY_AGG __ LPAREN __ arg:distinct_args __ o:order_by_clause? __ RPAREN {
4388-
// => { type: 'aggr_func'; args:count_arg; name: 'ARRAY_AGG'; orderby?: order_by_clause }
4387+
= pre:(ident __ DOT)? __ name:(KW_ARRAY_AGG / KW_STRING_AGG) __ LPAREN __ arg:distinct_args __ RPAREN {
4388+
// => { type: 'aggr_func'; args:count_arg; name: 'ARRAY_AGG' | 'STRING_AGG'; }
43894389
return {
43904390
type: 'aggr_func',
43914391
name: pre ? `${pre[0]}.${name}` : name,
43924392
args: arg,
4393-
orderby: o,
43944393
};
43954394
}
43964395

@@ -4905,6 +4904,7 @@ KW_OR = "OR"i !ident_start { return 'OR'; }
49054904

49064905
KW_ARRAY = "ARRAY"i !ident_start { return 'ARRAY'; }
49074906
KW_ARRAY_AGG = "ARRAY_AGG"i !ident_start { return 'ARRAY_AGG'; }
4907+
KW_STRING_AGG = "STRING_AGG"i !ident_start { return 'STRING_AGG'; }
49084908
KW_COUNT = "COUNT"i !ident_start { return 'COUNT'; }
49094909
KW_GROUP_CONCAT = "GROUP_CONCAT"i !ident_start { return 'GROUP_CONCAT'; }
49104910
KW_MAX = "MAX"i !ident_start { return 'MAX'; }

pegjs/snowflake.pegjs

Lines changed: 9 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -3687,16 +3687,16 @@ aggr_fun_count
36873687
}
36883688

36893689
concat_separator
3690-
= kw:'SEPARATOR'i? __ s:literal_string {
3691-
// => { keyword: string | null; value: literal_string; }
3690+
= kw:COMMA __ s:literal_string {
3691+
// => { symbol: ','; delimiter: literal_string; }
36923692
return {
3693-
keyword: kw,
3694-
value: s
3693+
symbol: ke,
3694+
delimiter: s
36953695
}
36963696
}
36973697

36983698
distinct_args
3699-
= d:KW_DISTINCT? __ LPAREN __ c:expr __ RPAREN __ tail:(__ (KW_AND / KW_OR) __ expr)* __ or:order_by_clause? __ s:concat_separator? {
3699+
= d:KW_DISTINCT? __ LPAREN __ c:expr __ RPAREN __ tail:(__ (KW_AND / KW_OR) __ expr)* __ s:concat_separator? __ or:order_by_clause? {
37003700
/* => { distinct: 'DISTINCT'; expr: expr; orderby?: order_by_clause; separator?: concat_separator; } */
37013701
const len = tail.length
37023702
let result = c
@@ -3711,7 +3711,7 @@ distinct_args
37113711
separator: s
37123712
};
37133713
}
3714-
/ d:KW_DISTINCT? __ c:or_and_expr __ or:order_by_clause? __ s:concat_separator? {
3714+
/ d:KW_DISTINCT? __ c:or_and_expr __ s:concat_separator? __ or:order_by_clause? {
37153715
/* => { distinct: 'DISTINCT'; expr: expr; orderby?: order_by_clause; separator?: concat_separator; } */
37163716
return { distinct: d, expr: c, orderby: or, separator: s };
37173717
}
@@ -3721,13 +3721,12 @@ count_arg
37213721
/ distinct_args
37223722

37233723
aggr_array_agg
3724-
= pre:(ident __ DOT)? __ name:KW_ARRAY_AGG __ LPAREN __ arg:distinct_args __ o:order_by_clause? __ RPAREN {
3725-
// => { type: 'aggr_func'; args:count_arg; name: 'ARRAY_AGG'; orderby?: order_by_clause }
3724+
= pre:(ident __ DOT)? __ name:(KW_ARRAY_AGG / KW_STRING_AGG) __ LPAREN __ arg:distinct_args __ RPAREN {
3725+
// => { type: 'aggr_func'; args:count_arg; name: 'ARRAY_AGG' | 'STRING_AGG'; }
37263726
return {
37273727
type: 'aggr_func',
37283728
name: pre ? `${pre[0]}.${name}` : name,
37293729
args: arg,
3730-
orderby: o,
37313730
};
37323731
}
37333732

@@ -4314,6 +4313,7 @@ KW_OR = "OR"i !ident_start { return 'OR'; }
43144313

43154314
KW_ARRAY = "ARRAY"i !ident_start { return 'ARRAY'; }
43164315
KW_ARRAY_AGG = "ARRAY_AGG"i !ident_start { return 'ARRAY_AGG'; }
4316+
KW_STRING_AGG = "STRING_AGG"i !ident_start { return 'STRING_AGG'; }
43174317
KW_COUNT = "COUNT"i !ident_start { return 'COUNT'; }
43184318
KW_GROUP_CONCAT = "GROUP_CONCAT"i !ident_start { return 'GROUP_CONCAT'; }
43194319
KW_MAX = "MAX"i !ident_start { return 'MAX'; }

pegjs/trino.pegjs

Lines changed: 9 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -3755,16 +3755,16 @@ aggr_fun_count
37553755
}
37563756

37573757
concat_separator
3758-
= kw:'SEPARATOR'i? __ s:literal_string {
3759-
// => { keyword: string | null; value: literal_string; }
3758+
= kw:COMMA __ s:literal_string {
3759+
// => { symbol: ','; delimiter: literal_string; }
37603760
return {
3761-
keyword: kw,
3762-
value: s
3761+
symbol: ke,
3762+
delimiter: s
37633763
}
37643764
}
37653765

37663766
distinct_args
3767-
= d:KW_DISTINCT? __ LPAREN __ c:expr __ RPAREN __ tail:(__ (KW_AND / KW_OR) __ expr)* __ or:order_by_clause? __ s:concat_separator? {
3767+
= d:KW_DISTINCT? __ LPAREN __ c:expr __ RPAREN __ tail:(__ (KW_AND / KW_OR) __ expr)* __ s:concat_separator? __ or:order_by_clause? {
37683768
/* => { distinct: 'DISTINCT'; expr: expr; orderby?: order_by_clause; separator?: concat_separator; } */
37693769
const len = tail.length
37703770
let result = c
@@ -3779,7 +3779,7 @@ distinct_args
37793779
separator: s
37803780
};
37813781
}
3782-
/ d:KW_DISTINCT? __ c:or_and_expr __ or:order_by_clause? __ s:concat_separator? {
3782+
/ d:KW_DISTINCT? __ c:or_and_expr __ s:concat_separator? __ or:order_by_clause? {
37833783
/* => { distinct: 'DISTINCT'; expr: expr; orderby?: order_by_clause; separator?: concat_separator; } */
37843784
return { distinct: d, expr: c, orderby: or, separator: s };
37853785
}
@@ -3789,13 +3789,12 @@ count_arg
37893789
/ distinct_args
37903790

37913791
aggr_array_agg
3792-
= pre:(ident __ DOT)? __ name:KW_ARRAY_AGG __ LPAREN __ arg:distinct_args __ o:order_by_clause? __ RPAREN {
3793-
// => { type: 'aggr_func'; args:count_arg; name: 'ARRAY_AGG'; orderby?: order_by_clause }
3792+
= pre:(ident __ DOT)? __ name:(KW_ARRAY_AGG / KW_STRING_AGG) __ LPAREN __ arg:distinct_args __ RPAREN {
3793+
// => { type: 'aggr_func'; args:count_arg; name: 'ARRAY_AGG' | 'STRING_AGG'; }
37943794
return {
37953795
type: 'aggr_func',
37963796
name: pre ? `${pre[0]}.${name}` : name,
37973797
args: arg,
3798-
orderby: o,
37993798
};
38003799
}
38013800

@@ -4356,6 +4355,7 @@ KW_OR = "OR"i !ident_start { return 'OR'; }
43564355

43574356
KW_ARRAY = "ARRAY"i !ident_start { return 'ARRAY'; }
43584357
KW_ARRAY_AGG = "ARRAY_AGG"i !ident_start { return 'ARRAY_AGG'; }
4358+
KW_STRING_AGG = "STRING_AGG"i !ident_start { return 'STRING_AGG'; }
43594359
KW_COUNT = "COUNT"i !ident_start { return 'COUNT'; }
43604360
KW_GROUP_CONCAT = "GROUP_CONCAT"i !ident_start { return 'GROUP_CONCAT'; }
43614361
KW_MAX = "MAX"i !ident_start { return 'MAX'; }

src/aggregation.js

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -10,8 +10,9 @@ function aggrToSQL(expr) {
1010
const overStr = overToSQL(over)
1111
const separator = ' '
1212
if (args.distinct) str = ['DISTINCT', str].join(separator)
13-
if (args.orderby) str = `${str} ${orderOrPartitionByToSQL(args.orderby, 'order by')}`
14-
if (args.separator) str = [str, toUpper(args.separator.keyword), literalToSQL(args.separator.value)].filter(hasVal).join(' ')
13+
if (args.separator && args.separator.delimiter) str = [str, literalToSQL(args.separator.delimiter)].join(`${args.separator.symbol} `)
14+
if (args.orderby) str = [str, orderOrPartitionByToSQL(args.orderby, 'order by')].join(' ')
15+
if (args.separator && args.separator.value) str = [str, toUpper(args.separator.keyword), literalToSQL(args.separator.value)].filter(hasVal).join(' ')
1516
const withinGroup = within_group_orderby ? `WITHIN GROUP (${orderOrPartitionByToSQL(within_group_orderby, 'order by')})` : ''
1617
const filterStr = filter ? `FILTER (WHERE ${exprToSQL(filter.where)})` : ''
1718
return [`${fnName}(${str})`, withinGroup, overStr, filterStr].filter(hasVal).join(' ')

test/postgres.spec.js

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1472,6 +1472,27 @@ describe('Postgres', () => {
14721472
`CREATE TABLE "electronics" PARTITION OF "products" FOR VALUES IN ('Electronics')`
14731473
]
14741474
},
1475+
{
1476+
title: 'distinct in args',
1477+
sql: [
1478+
`SELECT
1479+
f.title,
1480+
STRING_AGG (
1481+
a.first_name || ' ' || a.last_name,
1482+
','
1483+
ORDER BY
1484+
a.first_name,
1485+
a.last_name
1486+
) actors
1487+
FROM
1488+
film f
1489+
INNER JOIN film_actor fa USING (film_id)
1490+
INNER JOIN actor a USING (actor_id)
1491+
GROUP BY
1492+
f.title;`,
1493+
`SELECT "f".title, STRING_AGG("a".first_name || ' ' || "a".last_name, ',' ORDER BY "a".first_name ASC, "a".last_name ASC) AS "actors" FROM "film" AS "f" INNER JOIN "film_actor" AS "fa" USING ("film_id") INNER JOIN "actor" AS "a" USING ("actor_id") GROUP BY "f".title`
1494+
]
1495+
},
14751496
]
14761497
function neatlyNestTestedSQL(sqlList){
14771498
sqlList.forEach(sqlInfo => {

0 commit comments

Comments
 (0)