Skip to content

Commit d42d024

Browse files
author
Bergwinkl Thomas
committed
add DISTINCT ON support for Postgres
1 parent b644cef commit d42d024

4 files changed

Lines changed: 76 additions & 1 deletion

File tree

lib/dialect/postgres.js

Lines changed: 17 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -109,6 +109,7 @@ Postgres.prototype.visit = function(node) {
109109
case 'DROP' : return this.visitDrop(node);
110110
case 'TRUNCATE' : return this.visitTruncate(node);
111111
case 'DISTINCT' : return this.visitDistinct(node);
112+
case 'DISTINCT ON' : return this.visitDistinctOn(node);
112113
case 'ALIAS' : return this.visitAlias(node);
113114
case 'ALTER' : return this.visitAlter(node);
114115
case 'CAST' : return this.visitCast(node);
@@ -180,9 +181,20 @@ Postgres.prototype.quote = function(word, quoteCharacter) {
180181

181182
Postgres.prototype.visitSelect = function(select) {
182183
var result = ['SELECT']
184+
183185
if (select.isDistinct) result.push('DISTINCT');
184-
result.push(select.nodes.map(this.visit.bind(this)).join(', '));
186+
187+
var distinctOnNode = select.nodes.filter(function (node) {return node.type === 'DISTINCT ON';}).shift();
188+
var nonDistinctOnNodes = select.nodes.filter(function (node) {return node.type !== 'DISTINCT ON';});
189+
190+
if (distinctOnNode) {
191+
result.push(this.visit(distinctOnNode));
192+
}
193+
194+
result.push(nonDistinctOnNodes.map(this.visit.bind(this)).join(', '));
195+
185196
this._selectOrDeleteEndIndex = this.output.length + result.length;
197+
186198
return result;
187199
};
188200

@@ -295,6 +307,10 @@ Postgres.prototype.visitDistinct = function(truncate) {
295307
return [];
296308
};
297309

310+
Postgres.prototype.visitDistinctOn = function(distinctOn) {
311+
return ['DISTINCT ON('+distinctOn.nodes.map(this.visit.bind(this)).join(', ')+')'];
312+
};
313+
298314
Postgres.prototype.visitAlias = function(alias) {
299315
var result = [this.visit(alias.value) + ' AS ' + this.quote(alias.alias)];
300316
return result;

lib/node/distinctOn.js

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

lib/node/query.js

Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,7 @@ var Create = require('./create');
2222
var Drop = require('./drop');
2323
var Truncate = require('./truncate');
2424
var Distinct = require('./distinct');
25+
var DistinctOn = require('./distinctOn');
2526
var Alter = require('./alter');
2627
var AddColumn = require('./addColumn');
2728
var DropColumn = require('./dropColumn');
@@ -317,6 +318,33 @@ var Query = Node.define({
317318
return this.add(new Distinct());
318319
},
319320

321+
distinctOn: function() {
322+
var distinctOn;
323+
if (this._distinctOn) {
324+
distinctOn = this._distinctOn;
325+
} else {
326+
var select = this.nodes.filter(function (node) {return node.type === 'SELECT';}).shift();
327+
328+
distinctOn = this._distinctOn = new DistinctOn();
329+
select.add(distinctOn);
330+
}
331+
332+
//allow things like .distinctOn(a.star(), [ a.id, a.name ])
333+
//this will flatten them into a single array
334+
var args = sliced(arguments).reduce(function(cur, next) {
335+
if (util.isArray(next)) {
336+
return cur.concat(next);
337+
}
338+
339+
cur.push(next);
340+
return cur;
341+
}, []);
342+
343+
distinctOn.addAll(args);
344+
345+
return this;
346+
},
347+
320348
alter: function() {
321349
return this.add(new Alter());
322350
},

test/dialects/distinct-on-tests.js

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,24 @@
1+
'use strict';
2+
3+
var Harness = require('./support');
4+
var user = Harness.defineUserTable();
5+
var Sql = require('../../lib').setDialect('postgres');
6+
7+
Harness.test({
8+
query: user.select().distinctOn(user.id),
9+
pg: {
10+
text : 'SELECT DISTINCT ON("user"."id") "user".* FROM "user"',
11+
string: 'SELECT DISTINCT ON("user"."id") "user".* FROM "user"'
12+
},
13+
params: []
14+
});
15+
16+
Harness.test({
17+
query: user.select(user.id,user.name).distinctOn(user.id),
18+
pg: {
19+
text : 'SELECT DISTINCT ON("user"."id") "user"."id", "user"."name" FROM "user"',
20+
string: 'SELECT DISTINCT ON("user"."id") "user"."id", "user"."name" FROM "user"'
21+
},
22+
params: []
23+
});
24+

0 commit comments

Comments
 (0)