Skip to content

Commit 1354d7e

Browse files
author
Justin Reidy
committed
adding groupBy and arrayAgg
1 parent 825aea1 commit 1354d7e

6 files changed

Lines changed: 59 additions & 7 deletions

File tree

lib/column.js

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -62,6 +62,13 @@ Column.prototype.as = function(alias) {
6262
return new ColumnNode(context);
6363
}
6464

65+
Column.prototype.arrayAgg = function(alias) {
66+
var context = contextify(this);
67+
context.asArray = true;
68+
context.alias = alias || context.name + 's';
69+
return new ColumnNode(context);
70+
}
71+
6572
binaryMethod('equals', '=');
6673
binaryMethod('equal', '=');
6774
binaryMethod('notEqual', '<>');

lib/dialect/postgres.js

Lines changed: 17 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,7 @@ Postgres.prototype.visit = function(node) {
2020
case 'FROM': return this.visitFrom(node);
2121
case 'WHERE': return this.visitWhere(node);
2222
case 'ORDER BY': return this.visitOrderBy(node);
23+
case 'GROUP BY': return this.visitGroupBy(node);
2324
case 'RETURNING': return this.visitReturning(node);
2425
case 'BINARY': return this.visitBinary(node);
2526
case 'TABLE': return this.visitTable(node);
@@ -28,7 +29,7 @@ Postgres.prototype.visit = function(node) {
2829
case 'TEXT': return node.text;
2930
case 'UNARY': return this.visitUnary(node);
3031
case 'PARAMETER': return this.visitParameter(node);
31-
case 'LIMIT':
32+
case 'LIMIT':
3233
case 'OFFSET':
3334
return this.visitModifier(node);
3435
default: throw new Error("Unrecognized node type " + node.type);
@@ -106,6 +107,11 @@ Postgres.prototype.visitOrderBy = function(orderBy) {
106107
return result;
107108
}
108109

110+
Postgres.prototype.visitGroupBy = function(groupBy) {
111+
var result = ['GROUP BY', groupBy.nodes.map(this.visit.bind(this)).join(', ')];
112+
return result;
113+
}
114+
109115
Postgres.prototype.visitBinary = function(binary) {
110116
return '(' + this.visit(binary.left) + ' ' + binary.operator + ' ' + this.visit(binary.right) + ')';
111117
}
@@ -146,7 +152,11 @@ Postgres.prototype.visitTable = function(tableNode) {
146152

147153
Postgres.prototype.visitColumn = function(columnNode) {
148154
var table = columnNode.table;
155+
var inSelectClause = !this._selectOrDeleteEndIndex;
149156
var txt = "";
157+
if(inSelectClause && columnNode.asArray) {
158+
txt += 'array_agg(';
159+
}
150160
if(!this._visitedInsert && !this._visitingUpdate) {
151161
if(table.alias) {
152162
txt = table.alias;
@@ -157,11 +167,14 @@ Postgres.prototype.visitColumn = function(columnNode) {
157167
}
158168
txt += this.quote(table.getName());
159169
}
160-
txt += '.'
170+
txt += '.';
161171
}
162172
txt += this.quote(columnNode.name);
163-
var inSelectClause = !this._selectOrDeleteEndIndex;
164-
if(inSelectClause && columnNode.alias) {
173+
if(inSelectClause && columnNode.asArray) {
174+
txt += ')';
175+
txt += ' as ' + this.quote(columnNode.alias);
176+
}
177+
else if(inSelectClause && columnNode.alias) {
165178
txt += ' as ' + this.quote(columnNode.alias);
166179
}
167180
return txt;

lib/node/column.js

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@ module.exports = Node.define({
55
constructor: function(config) {
66
this.name = config.name;
77
this.alias = config.alias;
8+
this.asArray = config.asArray;
89
this.table = config.table;
910
this.value = config.getValue();
1011
}

lib/node/groupBy.js

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
var Node = require(__dirname);
2+
3+
module.exports = Node.define({
4+
type: 'GROUP BY'
5+
});

lib/node/query.js

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@ var Select = require(__dirname + '/select');
33
var From = require(__dirname + '/from');
44
var Where = require(__dirname + '/where');
55
var OrderBy = require(__dirname + '/orderBy');
6+
var GroupBy = require(__dirname + '/groupBy');
67
var Insert = require(__dirname + '/insert');
78
var Update = require(__dirname + '/update');
89
var Delete = require(__dirname + '/delete');
@@ -55,6 +56,14 @@ var Query = Node.define({
5556
});
5657
return this.add(orderBy);
5758
},
59+
group: function() {
60+
var args = Array.prototype.slice.call(arguments, 0);
61+
var groupBy = new GroupBy();
62+
var nodes = args.forEach(function(arg) {
63+
groupBy.add(arg.toNode());
64+
});
65+
return this.add(groupBy);
66+
},
5867
insert: function(o) {
5968
var self = this;
6069
var args = Array.prototype.slice.call(arguments, 0);

test/dialect-tests.js

Lines changed: 20 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -93,8 +93,8 @@ test({
9393
});
9494

9595
test({
96-
query : user.select(user.name.as('user name'), user.id.as('user id')).from(user),
97-
pg : 'SELECT "user"."name" as "user name", "user"."id" as "user id" FROM "user"'
96+
query : user.select(user.name, post.content).from(user.join(post).on(user.id.equals(post.userId))),
97+
pg : 'SELECT "user"."name", "post"."content" FROM "user" INNER JOIN "post" ON ("user"."id" = "post"."userId")'
9898
});
9999

100100
test({
@@ -142,7 +142,7 @@ test({
142142

143143
test({
144144
query : post.select(post.content).order(post.content),
145-
pg : 'SELECT "post"."content" FROM "post" ORDER BY "post"."content"',
145+
pg : 'SELECT "post"."content" FROM "post" ORDER BY "post"."content"'
146146
});
147147

148148
test({
@@ -155,6 +155,23 @@ test({
155155
pg : 'SELECT "post"."content" FROM "post" ORDER BY "post"."content", ("post"."userId" DESC)'
156156
});
157157

158+
//GROUP BY & AGGREGATES
159+
test({
160+
query : post.select(post.content).group(post.userId),
161+
pg : 'SELECT "post"."content" FROM "post" GROUP BY "post"."userId"'
162+
});
163+
164+
test({
165+
query : post.select(post.content.arrayAgg()).group(post.userId),
166+
pg : 'SELECT array_agg("post"."content") as "contents" FROM "post" GROUP BY "post"."userId"'
167+
});
168+
169+
test({
170+
query : post.select(post.content.arrayAgg('post contents')).group(post.userId),
171+
pg : 'SELECT array_agg("post"."content") as "post contents" FROM "post" GROUP BY "post"."userId"'
172+
});
173+
174+
158175

159176
test({
160177
query : post.insert(post.content.value('test'), post.userId.value(1)),

0 commit comments

Comments
 (0)