不要怂,就是干,撸起袖子干!

Commit 49f01691 by Jan Aagaard Meier

Make the ordering / quoting API consitent

1 parent 4dbb571f
...@@ -228,11 +228,12 @@ module.exports = (function() { ...@@ -228,11 +228,12 @@ module.exports = (function() {
} }
if (options.group) { if (options.group) {
options.group = Array.isArray(options.group) ? options.group.map(function(t) { return this.quoteIdentifiers(t)}.bind(this)).join(', ') : this.quoteIdentifiers(options.group) options.group = Array.isArray(options.group) ? options.group.map(function (t) { return this.quote(t) }.bind(this)).join(', ') : options.group
query += " GROUP BY " + options.group query += " GROUP BY " + options.group
} }
if (options.order) { if (options.order) {
options.order = Array.isArray(options.order) ? options.order.map(function (t) { return this.quote(t) }.bind(this)).join(', ') : options.order
query += " ORDER BY " + options.order query += " ORDER BY " + options.order
} }
......
...@@ -300,14 +300,12 @@ module.exports = (function() { ...@@ -300,14 +300,12 @@ module.exports = (function() {
} }
if(options.group) { if(options.group) {
options.group = Array.isArray(options.group) ? options.group.map(function(t) { return this.quoteIdentifiers(t) }.bind(this)).join(', ') : this.quoteIdentifiers(options.group) options.group = Array.isArray(options.group) ? options.group.map(function (t) { return this.quote(t) }.bind(this)).join(', ') : options.group
query += " GROUP BY <%= group %>" query += " GROUP BY <%= group %>"
} }
if(options.order) { if(options.order) {
options.order = options.order.replace(/([^ ]+)(.*)/, function(m, g1, g2) { options.order = Array.isArray(options.order) ? options.order.map(function (t) { return this.quote(t) }.bind(this)).join(', ') : options.order
return this.quoteIdentifiers(g1) + g2
}.bind(this))
query += " ORDER BY <%= order %>" query += " ORDER BY <%= order %>"
} }
......
var Utils = require("../utils")
module.exports = (function() { module.exports = (function() {
var QueryGenerator = { var QueryGenerator = {
addSchema: function(opts) { addSchema: function(opts) {
...@@ -268,7 +270,44 @@ module.exports = (function() { ...@@ -268,7 +270,44 @@ module.exports = (function() {
Globally disable foreign key constraints Globally disable foreign key constraints
*/ */
disableForeignKeyConstraintsQuery: function() { disableForeignKeyConstraintsQuery: function() {
throwMethodUndefined('disableForeignKeyConstraintsQuery') throwMethodUndefined('disableForeignKeyConstraintsQuery')
},
/*
Quote an object based on its type. This is a more general version of quoteIdentifier
Strings: should proxy to quoteIdentifiers
Arrays: First argument should be qouted, second argument should be append without quoting
Objects:
If fn is set, the string should start with the value of fn, starting paren,
the values of cols (which is assumed to be an array), quoted and joined with ', ', unless they are themselves functions
If direction is set, should be prepended
Currently this function is only used for ordering / grouping columns, but it could
potentially also be used for other places where we want to be able to call SQL functions (e.g. as default values)
*/
quote: function(obj, force) {
if (Utils._.isString(obj)) {
return this.quoteIdentifiers(obj, force)
} else if (Array.isArray(obj)) {
return this.quote(obj[0], force) + ' ' + obj[1]
} else { // assumes object
var s = ''
if (obj.raw) {
s = obj.raw
} else if (obj.fn) {
s += obj.fn + '('
s += obj.cols.map(function (elem) {
return this.quote(elem, force)
}.bind(this)).join(', ') + ')'
}
if (obj.direction) {
s += ' ' + obj.direction
}
return s
}
}, },
/* /*
......
...@@ -211,11 +211,12 @@ module.exports = (function() { ...@@ -211,11 +211,12 @@ module.exports = (function() {
} }
if (options.group) { if (options.group) {
options.group = Array.isArray(options.group) ? options.group.map(function(t) { return this.quoteIdentifiers(t)}.bind(this)).join(', ') : qa(options.group) options.group = Array.isArray(options.group) ? options.group.map(function (t) { return this.quote(t) }.bind(this)).join(', ') : options.group
query += " GROUP BY " + options.group query += " GROUP BY " + options.group
} }
if (options.order) { if (options.order) {
options.order = Array.isArray(options.order) ? options.order.map(function (t) { return this.quote(t) }.bind(this)).join(', ') : options.order
query += " ORDER BY " + options.order query += " ORDER BY " + options.order
} }
......
...@@ -163,20 +163,48 @@ if (dialect.match(/^mysql/)) { ...@@ -163,20 +163,48 @@ if (dialect.match(/^mysql/)) {
expectation: "SELECT * FROM `myTable` ORDER BY id DESC;", expectation: "SELECT * FROM `myTable` ORDER BY id DESC;",
context: QueryGenerator context: QueryGenerator
}, { }, {
arguments: ['myTable', {order: ["id"]}],
expectation: "SELECT * FROM `myTable` ORDER BY `id`;",
context: QueryGenerator
}, {
arguments: ['myTable', {order: ["myTable.id"]}],
expectation: "SELECT * FROM `myTable` ORDER BY `myTable`.`id`;",
context: QueryGenerator
}, {
arguments: ['myTable', {order: [["id", 'DESC']]}],
expectation: "SELECT * FROM `myTable` ORDER BY `id` DESC;",
context: QueryGenerator
}, {
arguments: ['myTable', {order: [{raw: 'f1(f2(id))', direction: 'DESC'}]}],
expectation: "SELECT * FROM `myTable` ORDER BY f1(f2(id)) DESC;",
context: QueryGenerator
}, { // Function-ception!
arguments: ['myTable', {order: [{fn: 'f1', cols: [ { fn: 'f2', cols: ['id']}], direction: 'DESC'}]}],
expectation: "SELECT * FROM `myTable` ORDER BY f1(f2(`id`)) DESC;",
context: QueryGenerator
}, {
arguments: ['myTable', {order: [[{ fn: 'max', cols: ['id']}, 'DESC'], { fn: 'min', cols: ['first', 'second'], direction: 'ASC'}]}],
expectation: "SELECT * FROM `myTable` ORDER BY max(`id`) DESC, min(`first`, `second`) ASC;",
context: QueryGenerator
}, {
arguments: ['myTable', {group: "name"}], arguments: ['myTable', {group: "name"}],
expectation: "SELECT * FROM `myTable` GROUP BY `name`;", expectation: "SELECT * FROM `myTable` GROUP BY name;",
context: QueryGenerator context: QueryGenerator
}, { }, {
arguments: ['myTable', {group: ["name"]}], arguments: ['myTable', {group: ["name"]}],
expectation: "SELECT * FROM `myTable` GROUP BY `name`;", expectation: "SELECT * FROM `myTable` GROUP BY `name`;",
context: QueryGenerator context: QueryGenerator
}, { }, {
arguments: ['myTable', {group: [{ fn: 'max', cols: ['id']}]}],
expectation: "SELECT * FROM `myTable` GROUP BY max(`id`);",
context: QueryGenerator
}, {
arguments: ['myTable', {group: ["name", "title"]}], arguments: ['myTable', {group: ["name", "title"]}],
expectation: "SELECT * FROM `myTable` GROUP BY `name`, `title`;", expectation: "SELECT * FROM `myTable` GROUP BY `name`, `title`;",
context: QueryGenerator context: QueryGenerator
}, { }, {
arguments: ['myTable', {group: "name", order: "id DESC"}], arguments: ['myTable', {group: "name", order: "id DESC"}],
expectation: "SELECT * FROM `myTable` GROUP BY `name` ORDER BY id DESC;", expectation: "SELECT * FROM `myTable` GROUP BY name ORDER BY id DESC;",
context: QueryGenerator context: QueryGenerator
}, { }, {
arguments: ['myTable', {limit: 10}], arguments: ['myTable', {limit: 10}],
......
...@@ -246,14 +246,41 @@ if (dialect.match(/^postgres/)) { ...@@ -246,14 +246,41 @@ if (dialect.match(/^postgres/)) {
expectation: "SELECT * FROM \"myTable\" WHERE foo='bar';" expectation: "SELECT * FROM \"myTable\" WHERE foo='bar';"
}, { }, {
arguments: ['myTable', {order: "id DESC"}], arguments: ['myTable', {order: "id DESC"}],
expectation: "SELECT * FROM \"myTable\" ORDER BY \"id\" DESC;" expectation: "SELECT * FROM \"myTable\" ORDER BY id DESC;"
}, {
arguments: ['myTable', {order: ["id"]}],
expectation: 'SELECT * FROM "myTable" ORDER BY "id";',
context: QueryGenerator
}, {
arguments: ['myTable', {order: ["myTable.id"]}],
expectation: 'SELECT * FROM "myTable" ORDER BY "myTable"."id";',
context: QueryGenerator
}, {
arguments: ['myTable', {order: [["id", 'DESC']]}],
expectation: 'SELECT * FROM "myTable" ORDER BY "id" DESC;',
context: QueryGenerator
}, {
arguments: ['myTable', {order: [{raw: 'f1(f2(id))', direction: 'DESC'}]}],
expectation: 'SELECT * FROM "myTable" ORDER BY f1(f2(id)) DESC;',
context: QueryGenerator
}, { // Function-ception!
arguments: ['myTable', {order: [{fn: 'f1', cols: [ { fn: 'f2', cols: ['id']}], direction: 'DESC'}]}],
expectation: 'SELECT * FROM "myTable" ORDER BY f1(f2("id")) DESC;',
context: QueryGenerator
}, {
arguments: ['myTable', {order: [[{ fn: 'max', cols: ['id']}, 'DESC'], { fn: 'min', cols: ['first', 'second'], direction: 'ASC'}]}],
expectation: 'SELECT * FROM "myTable" ORDER BY max("id") DESC, min("first", "second") ASC;',
context: QueryGenerator
}, { }, {
arguments: ['myTable', {group: "name"}], arguments: ['myTable', {group: "name"}],
expectation: "SELECT * FROM \"myTable\" GROUP BY \"name\";" expectation: "SELECT * FROM \"myTable\" GROUP BY name;"
}, { }, {
arguments: ['myTable', {group: ["name"]}], arguments: ['myTable', {group: ["name"]}],
expectation: "SELECT * FROM \"myTable\" GROUP BY \"name\";" expectation: "SELECT * FROM \"myTable\" GROUP BY \"name\";"
}, { }, {
arguments: ['myTable', {group: [{ fn: 'max', cols: ['id']}]}],
expectation: "SELECT * FROM \"myTable\" GROUP BY max(\"id\");"
},{
arguments: ['myTable', {group: ["name","title"]}], arguments: ['myTable', {group: ["name","title"]}],
expectation: "SELECT * FROM \"myTable\" GROUP BY \"name\", \"title\";" expectation: "SELECT * FROM \"myTable\" GROUP BY \"name\", \"title\";"
}, { }, {
......
...@@ -104,6 +104,123 @@ if (dialect === 'sqlite') { ...@@ -104,6 +104,123 @@ if (dialect === 'sqlite') {
} }
], ],
selectQuery: [
{
arguments: ['myTable'],
expectation: "SELECT * FROM `myTable`;",
context: QueryGenerator
}, {
arguments: ['myTable', {attributes: ['id', 'name']}],
expectation: "SELECT `id`, `name` FROM `myTable`;",
context: QueryGenerator
}, {
arguments: ['myTable', {where: {id: 2}}],
expectation: "SELECT * FROM `myTable` WHERE `myTable`.`id`=2;",
context: QueryGenerator
}, {
arguments: ['myTable', {where: {name: 'foo'}}],
expectation: "SELECT * FROM `myTable` WHERE `myTable`.`name`='foo';",
context: QueryGenerator
}, {
arguments: ['myTable', {where: {name: "foo';DROP TABLE myTable;"}}],
expectation: "SELECT * FROM `myTable` WHERE `myTable`.`name`='foo\'\';DROP TABLE myTable;';",
context: QueryGenerator
}, {
arguments: ['myTable', {where: 2}],
expectation: "SELECT * FROM `myTable` WHERE `myTable`.`id`=2;",
context: QueryGenerator
}, {
arguments: ['foo', { attributes: [['count(*)', 'count']] }],
expectation: 'SELECT count(*) as `count` FROM `foo`;',
context: QueryGenerator
}, {
arguments: ['myTable', {where: "foo='bar'"}],
expectation: "SELECT * FROM `myTable` WHERE foo='bar';",
context: QueryGenerator
}, {
arguments: ['myTable', {order: "id DESC"}],
expectation: "SELECT * FROM `myTable` ORDER BY id DESC;",
context: QueryGenerator
}, {
arguments: ['myTable', {order: ["id"]}],
expectation: "SELECT * FROM `myTable` ORDER BY `id`;",
context: QueryGenerator
}, {
arguments: ['myTable', {order: ["myTable.id"]}],
expectation: "SELECT * FROM `myTable` ORDER BY `myTable`.`id`;",
context: QueryGenerator
}, {
arguments: ['myTable', {order: [["id", 'DESC']]}],
expectation: "SELECT * FROM `myTable` ORDER BY `id` DESC;",
context: QueryGenerator
}, {
arguments: ['myTable', {order: [{raw: 'f1(f2(id))', direction: 'DESC'}]}],
expectation: "SELECT * FROM `myTable` ORDER BY f1(f2(id)) DESC;",
context: QueryGenerator
}, { // Function-ception!
arguments: ['myTable', {order: [{fn: 'f1', cols: [ { fn: 'f2', cols: ['id']}], direction: 'DESC'}]}],
expectation: "SELECT * FROM `myTable` ORDER BY f1(f2(`id`)) DESC;",
context: QueryGenerator
}, {
arguments: ['myTable', {order: [[{ fn: 'max', cols: ['id']}, 'DESC'], { fn: 'min', cols: ['first', 'second'], direction: 'ASC'}]}],
expectation: "SELECT * FROM `myTable` ORDER BY max(`id`) DESC, min(`first`, `second`) ASC;",
context: QueryGenerator
}, {
arguments: ['myTable', {group: "name"}],
expectation: "SELECT * FROM `myTable` GROUP BY name;",
context: QueryGenerator
}, {
arguments: ['myTable', {group: ["name"]}],
expectation: "SELECT * FROM `myTable` GROUP BY `name`;",
context: QueryGenerator
}, {
arguments: ['myTable', {group: [{ fn: 'max', cols: ['id']}]}],
expectation: "SELECT * FROM `myTable` GROUP BY max(`id`);",
context: QueryGenerator
}, {
arguments: ['myTable', {group: ["name", "title"]}],
expectation: "SELECT * FROM `myTable` GROUP BY `name`, `title`;",
context: QueryGenerator
}, {
arguments: ['myTable', {group: "name", order: "id DESC"}],
expectation: "SELECT * FROM `myTable` GROUP BY name ORDER BY id DESC;",
context: QueryGenerator
}, {
arguments: ['myTable', {limit: 10}],
expectation: "SELECT * FROM `myTable` LIMIT 10;",
context: QueryGenerator
}, {
arguments: ['myTable', {limit: 10, offset: 2}],
expectation: "SELECT * FROM `myTable` LIMIT 2, 10;",
context: QueryGenerator
}, {
title: 'uses default limit if only offset is specified',
arguments: ['myTable', {offset: 2}],
expectation: "SELECT * FROM `myTable` LIMIT 2, 10000000000000;",
context: QueryGenerator
}, {
title: 'multiple where arguments',
arguments: ['myTable', {where: {boat: 'canoe', weather: 'cold'}}],
expectation: "SELECT * FROM `myTable` WHERE `myTable`.`boat`='canoe' AND `myTable`.`weather`='cold';",
context: QueryGenerator
}, {
title: 'no where arguments (object)',
arguments: ['myTable', {where: {}}],
expectation: "SELECT * FROM `myTable` WHERE 1=1;",
context: QueryGenerator
}, {
title: 'no where arguments (string)',
arguments: ['myTable', {where: ''}],
expectation: "SELECT * FROM `myTable` WHERE 1=1;",
context: QueryGenerator
}, {
title: 'no where arguments (null)',
arguments: ['myTable', {where: null}],
expectation: "SELECT * FROM `myTable` WHERE 1=1;",
context: QueryGenerator
}
],
insertQuery: [ insertQuery: [
{ {
arguments: ['myTable', { name: 'foo' }], arguments: ['myTable', { name: 'foo' }],
......
Markdown is supported
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!