Skip to content

Commit

Permalink
fix: string_agg function in pg
Browse files Browse the repository at this point in the history
  • Loading branch information
taozhi8833998 committed May 7, 2024
1 parent a6f931d commit 7d065a2
Show file tree
Hide file tree
Showing 7 changed files with 69 additions and 47 deletions.
18 changes: 9 additions & 9 deletions pegjs/noql.pegjs
Original file line number Diff line number Diff line change
Expand Up @@ -4286,16 +4286,16 @@ aggr_fun_count
}

concat_separator
= kw:'SEPARATOR'i? __ s:literal_string {
// => { keyword: string | null; value: literal_string; }
= kw:COMMA __ s:literal_string {
// => { symbol: ','; delimiter: literal_string; }
return {
keyword: kw,
value: s
symbol: ke,
delimiter: s
}
}

distinct_args
= d:KW_DISTINCT? __ LPAREN __ c:expr __ RPAREN __ tail:(__ (KW_AND / KW_OR) __ expr)* __ or:order_by_clause? __ s:concat_separator? {
= d:KW_DISTINCT? __ LPAREN __ c:expr __ RPAREN __ tail:(__ (KW_AND / KW_OR) __ expr)* __ s:concat_separator? __ or:order_by_clause? {
/* => { distinct: 'DISTINCT'; expr: expr; orderby?: order_by_clause; separator?: concat_separator; } */
const len = tail.length
let result = c
Expand All @@ -4310,7 +4310,7 @@ distinct_args
separator: s
};
}
/ d:KW_DISTINCT? __ c:or_and_expr __ or:order_by_clause? __ s:concat_separator? {
/ d:KW_DISTINCT? __ c:or_and_expr __ s:concat_separator? __ or:order_by_clause? {
/* => { distinct: 'DISTINCT'; expr: expr; orderby?: order_by_clause; separator?: concat_separator; } */
return { distinct: d, expr: c, orderby: or, separator: s };
}
Expand All @@ -4320,13 +4320,12 @@ count_arg
/ distinct_args

aggr_array_agg
= pre:(ident __ DOT)? __ name:KW_ARRAY_AGG __ LPAREN __ arg:distinct_args __ o:order_by_clause? __ RPAREN {
// => { type: 'aggr_func'; args:count_arg; name: 'ARRAY_AGG'; orderby?: order_by_clause }
= pre:(ident __ DOT)? __ name:(KW_ARRAY_AGG / KW_STRING_AGG) __ LPAREN __ arg:distinct_args __ RPAREN {
// => { type: 'aggr_func'; args:count_arg; name: 'ARRAY_AGG' | 'STRING_AGG'; }
return {
type: 'aggr_func',
name: pre ? `${pre[0]}.${name}` : name,
args: arg,
orderby: o,
};
}

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

KW_ARRAY = "ARRAY"i !ident_start { return 'ARRAY'; }
KW_ARRAY_AGG = "ARRAY_AGG"i !ident_start { return 'ARRAY_AGG'; }
KW_STRING_AGG = "STRING_AGG"i !ident_start { return 'STRING_AGG'; }
KW_COUNT = "COUNT"i !ident_start { return 'COUNT'; }
KW_GROUP_CONCAT = "GROUP_CONCAT"i !ident_start { return 'GROUP_CONCAT'; }
KW_MAX = "MAX"i !ident_start { return 'MAX'; }
Expand Down
18 changes: 9 additions & 9 deletions pegjs/postgresql.pegjs
Original file line number Diff line number Diff line change
Expand Up @@ -4496,16 +4496,16 @@ aggr_fun_count
}

concat_separator
= kw:'SEPARATOR'i? __ s:literal_string {
// => { keyword: string | null; value: literal_string; }
= kw:COMMA __ s:literal_string {
// => { symbol: ','; delimiter: literal_string; }
return {
keyword: kw,
value: s
symbol: kw,
delimiter: s
}
}

distinct_args
= d:KW_DISTINCT? __ LPAREN __ c:expr __ RPAREN __ tail:(__ (KW_AND / KW_OR) __ expr)* __ or:order_by_clause? __ s:concat_separator? {
= d:KW_DISTINCT? __ LPAREN __ c:expr __ RPAREN __ tail:(__ (KW_AND / KW_OR) __ expr)* __ s:concat_separator? __ or:order_by_clause? {
/* => { distinct: 'DISTINCT'; expr: expr; orderby?: order_by_clause; separator?: concat_separator; } */
const len = tail.length
let result = c
Expand All @@ -4520,7 +4520,7 @@ distinct_args
separator: s
};
}
/ d:KW_DISTINCT? __ c:or_and_expr __ or:order_by_clause? __ s:concat_separator? {
/ d:KW_DISTINCT? __ c:or_and_expr __ s:concat_separator? __ or:order_by_clause? {
/* => { distinct: 'DISTINCT'; expr: expr; orderby?: order_by_clause; separator?: concat_separator; } */
return { distinct: d, expr: c, orderby: or, separator: s };
}
Expand All @@ -4530,13 +4530,12 @@ count_arg
/ distinct_args

aggr_array_agg
= pre:(ident __ DOT)? __ name:KW_ARRAY_AGG __ LPAREN __ arg:distinct_args __ o:order_by_clause? __ RPAREN {
// => { type: 'aggr_func'; args:count_arg; name: 'ARRAY_AGG'; orderby?: order_by_clause }
= pre:(ident __ DOT)? __ name:(KW_ARRAY_AGG / KW_STRING_AGG) __ LPAREN __ arg:distinct_args __ RPAREN {
// => { type: 'aggr_func'; args:count_arg; name: 'ARRAY_AGG' | 'STRING_AGG'; }
return {
type: 'aggr_func',
name: pre ? `${pre[0]}.${name}` : name,
args: arg,
orderby: o,
};
}

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

KW_ARRAY = "ARRAY"i !ident_start { return 'ARRAY'; }
KW_ARRAY_AGG = "ARRAY_AGG"i !ident_start { return 'ARRAY_AGG'; }
KW_STRING_AGG = "STRING_AGG"i !ident_start { return 'STRING_AGG'; }
KW_COUNT = "COUNT"i !ident_start { return 'COUNT'; }
KW_GROUP_CONCAT = "GROUP_CONCAT"i !ident_start { return 'GROUP_CONCAT'; }
KW_MAX = "MAX"i !ident_start { return 'MAX'; }
Expand Down
18 changes: 9 additions & 9 deletions pegjs/redshift.pegjs
Original file line number Diff line number Diff line change
Expand Up @@ -4350,16 +4350,16 @@ aggr_fun_count
}

concat_separator
= kw:'SEPARATOR'i? __ s:literal_string {
// => { keyword: string | null; value: literal_string; }
= kw:COMMA __ s:literal_string {
// => { symbol: ','; delimiter: literal_string; }
return {
keyword: kw,
value: s
symbol: ke,
delimiter: s
}
}

distinct_args
= d:KW_DISTINCT? __ LPAREN __ c:expr __ RPAREN __ tail:(__ (KW_AND / KW_OR) __ expr)* __ or:order_by_clause? __ s:concat_separator? {
= d:KW_DISTINCT? __ LPAREN __ c:expr __ RPAREN __ tail:(__ (KW_AND / KW_OR) __ expr)* __ s:concat_separator? __ or:order_by_clause? {
/* => { distinct: 'DISTINCT'; expr: expr; orderby?: order_by_clause; separator?: concat_separator; } */
const len = tail.length
let result = c
Expand All @@ -4374,7 +4374,7 @@ distinct_args
separator: s
};
}
/ d:KW_DISTINCT? __ c:or_and_expr __ or:order_by_clause? __ s:concat_separator? {
/ d:KW_DISTINCT? __ c:or_and_expr __ s:concat_separator? __ or:order_by_clause? {
/* => { distinct: 'DISTINCT'; expr: expr; orderby?: order_by_clause; separator?: concat_separator; } */
return { distinct: d, expr: c, orderby: or, separator: s };
}
Expand All @@ -4384,13 +4384,12 @@ count_arg
/ distinct_args

aggr_array_agg
= pre:(ident __ DOT)? __ name:KW_ARRAY_AGG __ LPAREN __ arg:distinct_args __ o:order_by_clause? __ RPAREN {
// => { type: 'aggr_func'; args:count_arg; name: 'ARRAY_AGG'; orderby?: order_by_clause }
= pre:(ident __ DOT)? __ name:(KW_ARRAY_AGG / KW_STRING_AGG) __ LPAREN __ arg:distinct_args __ RPAREN {
// => { type: 'aggr_func'; args:count_arg; name: 'ARRAY_AGG' | 'STRING_AGG'; }
return {
type: 'aggr_func',
name: pre ? `${pre[0]}.${name}` : name,
args: arg,
orderby: o,
};
}

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

KW_ARRAY = "ARRAY"i !ident_start { return 'ARRAY'; }
KW_ARRAY_AGG = "ARRAY_AGG"i !ident_start { return 'ARRAY_AGG'; }
KW_STRING_AGG = "STRING_AGG"i !ident_start { return 'STRING_AGG'; }
KW_COUNT = "COUNT"i !ident_start { return 'COUNT'; }
KW_GROUP_CONCAT = "GROUP_CONCAT"i !ident_start { return 'GROUP_CONCAT'; }
KW_MAX = "MAX"i !ident_start { return 'MAX'; }
Expand Down
18 changes: 9 additions & 9 deletions pegjs/snowflake.pegjs
Original file line number Diff line number Diff line change
Expand Up @@ -3687,16 +3687,16 @@ aggr_fun_count
}

concat_separator
= kw:'SEPARATOR'i? __ s:literal_string {
// => { keyword: string | null; value: literal_string; }
= kw:COMMA __ s:literal_string {
// => { symbol: ','; delimiter: literal_string; }
return {
keyword: kw,
value: s
symbol: ke,
delimiter: s
}
}

distinct_args
= d:KW_DISTINCT? __ LPAREN __ c:expr __ RPAREN __ tail:(__ (KW_AND / KW_OR) __ expr)* __ or:order_by_clause? __ s:concat_separator? {
= d:KW_DISTINCT? __ LPAREN __ c:expr __ RPAREN __ tail:(__ (KW_AND / KW_OR) __ expr)* __ s:concat_separator? __ or:order_by_clause? {
/* => { distinct: 'DISTINCT'; expr: expr; orderby?: order_by_clause; separator?: concat_separator; } */
const len = tail.length
let result = c
Expand All @@ -3711,7 +3711,7 @@ distinct_args
separator: s
};
}
/ d:KW_DISTINCT? __ c:or_and_expr __ or:order_by_clause? __ s:concat_separator? {
/ d:KW_DISTINCT? __ c:or_and_expr __ s:concat_separator? __ or:order_by_clause? {
/* => { distinct: 'DISTINCT'; expr: expr; orderby?: order_by_clause; separator?: concat_separator; } */
return { distinct: d, expr: c, orderby: or, separator: s };
}
Expand All @@ -3721,13 +3721,12 @@ count_arg
/ distinct_args

aggr_array_agg
= pre:(ident __ DOT)? __ name:KW_ARRAY_AGG __ LPAREN __ arg:distinct_args __ o:order_by_clause? __ RPAREN {
// => { type: 'aggr_func'; args:count_arg; name: 'ARRAY_AGG'; orderby?: order_by_clause }
= pre:(ident __ DOT)? __ name:(KW_ARRAY_AGG / KW_STRING_AGG) __ LPAREN __ arg:distinct_args __ RPAREN {
// => { type: 'aggr_func'; args:count_arg; name: 'ARRAY_AGG' | 'STRING_AGG'; }
return {
type: 'aggr_func',
name: pre ? `${pre[0]}.${name}` : name,
args: arg,
orderby: o,
};
}

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

KW_ARRAY = "ARRAY"i !ident_start { return 'ARRAY'; }
KW_ARRAY_AGG = "ARRAY_AGG"i !ident_start { return 'ARRAY_AGG'; }
KW_STRING_AGG = "STRING_AGG"i !ident_start { return 'STRING_AGG'; }
KW_COUNT = "COUNT"i !ident_start { return 'COUNT'; }
KW_GROUP_CONCAT = "GROUP_CONCAT"i !ident_start { return 'GROUP_CONCAT'; }
KW_MAX = "MAX"i !ident_start { return 'MAX'; }
Expand Down
18 changes: 9 additions & 9 deletions pegjs/trino.pegjs
Original file line number Diff line number Diff line change
Expand Up @@ -3755,16 +3755,16 @@ aggr_fun_count
}

concat_separator
= kw:'SEPARATOR'i? __ s:literal_string {
// => { keyword: string | null; value: literal_string; }
= kw:COMMA __ s:literal_string {
// => { symbol: ','; delimiter: literal_string; }
return {
keyword: kw,
value: s
symbol: ke,
delimiter: s
}
}

distinct_args
= d:KW_DISTINCT? __ LPAREN __ c:expr __ RPAREN __ tail:(__ (KW_AND / KW_OR) __ expr)* __ or:order_by_clause? __ s:concat_separator? {
= d:KW_DISTINCT? __ LPAREN __ c:expr __ RPAREN __ tail:(__ (KW_AND / KW_OR) __ expr)* __ s:concat_separator? __ or:order_by_clause? {
/* => { distinct: 'DISTINCT'; expr: expr; orderby?: order_by_clause; separator?: concat_separator; } */
const len = tail.length
let result = c
Expand All @@ -3779,7 +3779,7 @@ distinct_args
separator: s
};
}
/ d:KW_DISTINCT? __ c:or_and_expr __ or:order_by_clause? __ s:concat_separator? {
/ d:KW_DISTINCT? __ c:or_and_expr __ s:concat_separator? __ or:order_by_clause? {
/* => { distinct: 'DISTINCT'; expr: expr; orderby?: order_by_clause; separator?: concat_separator; } */
return { distinct: d, expr: c, orderby: or, separator: s };
}
Expand All @@ -3789,13 +3789,12 @@ count_arg
/ distinct_args

aggr_array_agg
= pre:(ident __ DOT)? __ name:KW_ARRAY_AGG __ LPAREN __ arg:distinct_args __ o:order_by_clause? __ RPAREN {
// => { type: 'aggr_func'; args:count_arg; name: 'ARRAY_AGG'; orderby?: order_by_clause }
= pre:(ident __ DOT)? __ name:(KW_ARRAY_AGG / KW_STRING_AGG) __ LPAREN __ arg:distinct_args __ RPAREN {
// => { type: 'aggr_func'; args:count_arg; name: 'ARRAY_AGG' | 'STRING_AGG'; }
return {
type: 'aggr_func',
name: pre ? `${pre[0]}.${name}` : name,
args: arg,
orderby: o,
};
}

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

KW_ARRAY = "ARRAY"i !ident_start { return 'ARRAY'; }
KW_ARRAY_AGG = "ARRAY_AGG"i !ident_start { return 'ARRAY_AGG'; }
KW_STRING_AGG = "STRING_AGG"i !ident_start { return 'STRING_AGG'; }
KW_COUNT = "COUNT"i !ident_start { return 'COUNT'; }
KW_GROUP_CONCAT = "GROUP_CONCAT"i !ident_start { return 'GROUP_CONCAT'; }
KW_MAX = "MAX"i !ident_start { return 'MAX'; }
Expand Down
5 changes: 3 additions & 2 deletions src/aggregation.js
Original file line number Diff line number Diff line change
Expand Up @@ -10,8 +10,9 @@ function aggrToSQL(expr) {
const overStr = overToSQL(over)
const separator = ' '
if (args.distinct) str = ['DISTINCT', str].join(separator)
if (args.orderby) str = `${str} ${orderOrPartitionByToSQL(args.orderby, 'order by')}`
if (args.separator) str = [str, toUpper(args.separator.keyword), literalToSQL(args.separator.value)].filter(hasVal).join(' ')
if (args.separator && args.separator.delimiter) str = [str, literalToSQL(args.separator.delimiter)].join(`${args.separator.symbol} `)
if (args.orderby) str = [str, orderOrPartitionByToSQL(args.orderby, 'order by')].join(' ')
if (args.separator && args.separator.value) str = [str, toUpper(args.separator.keyword), literalToSQL(args.separator.value)].filter(hasVal).join(' ')
const withinGroup = within_group_orderby ? `WITHIN GROUP (${orderOrPartitionByToSQL(within_group_orderby, 'order by')})` : ''
const filterStr = filter ? `FILTER (WHERE ${exprToSQL(filter.where)})` : ''
return [`${fnName}(${str})`, withinGroup, overStr, filterStr].filter(hasVal).join(' ')
Expand Down
21 changes: 21 additions & 0 deletions test/postgres.spec.js
Original file line number Diff line number Diff line change
Expand Up @@ -1472,6 +1472,27 @@ describe('Postgres', () => {
`CREATE TABLE "electronics" PARTITION OF "products" FOR VALUES IN ('Electronics')`
]
},
{
title: 'distinct in args',
sql: [
`SELECT
f.title,
STRING_AGG (
a.first_name || ' ' || a.last_name,
','
ORDER BY
a.first_name,
a.last_name
) actors
FROM
film f
INNER JOIN film_actor fa USING (film_id)
INNER JOIN actor a USING (actor_id)
GROUP BY
f.title;`,
`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`
]
},
]
function neatlyNestTestedSQL(sqlList){
sqlList.forEach(sqlInfo => {
Expand Down

0 comments on commit 7d065a2

Please sign in to comment.