Mysql sort, where and limit

This commit is contained in:
Anatoliy Chakkaev 2012-01-20 00:16:30 +04:00
parent 7427289c59
commit 14c34a8058
4 changed files with 67 additions and 31 deletions

View File

@ -4,3 +4,5 @@ node_js:
- 0.6
- 0.7
before_install: git submodule init && git submodule --quiet update
before_script:
- "mysql -e 'create database myapp_test;'"

View File

@ -71,7 +71,7 @@ MySQL.prototype.toFields = function (model, data) {
var props = this._models[model].properties;
Object.keys(data).forEach(function (key) {
if (props[key]) {
fields.push('`' + key.replace(/\./g, '`.`') + '` = ' + this.toDatabase(props[key], data[key]));
fields.push('`' + key.replace(/\./g, '`.`') + '` = ' + this.toDatabase(props[key], data[key]));
}
}.bind(this));
return fields.join(',');
@ -93,7 +93,7 @@ MySQL.prototype.toDatabase = function (prop, val) {
val.getMinutes(),
val.getSeconds()
].join('-');
return this.client.escape(val);
return '"' + val + '"';
}
if (prop.type.name == "Boolean") return val ? 1 : 0;
return this.client.escape(val.toString());
@ -139,39 +139,61 @@ MySQL.prototype.destroy = function destroy(model, id, callback) {
});
};
// TODO: hook up where, order, limit and offset conditions
MySQL.prototype.all = function all(model, filter, callback) {
this.query('SELECT * FROM ' + model, function (err, data) {
var sql = 'SELECT * FROM ' + model;
var self = this;
var props = this._models[model].properties;
if (filter) {
if (filter.where) {
sql += ' ' + buildWhere(filter.where);
}
if (filter.order) {
sql += ' ' + buildOrderBy(filter.order);
}
if (filter.limit) {
sql += ' ' + buildLimit(filter.limit, filter.offset || 0);
}
}
this.query(sql, function (err, data) {
console.log(sql, err, data);
if (err) {
return callback(err, []);
}
callback(err, filter ? data.filter(applyFilter(filter)) : data);
callback(null, data);
}.bind(this));
};
function applyFilter(filter) {
if (typeof filter.where === 'function') {
return filter;
}
var keys = Object.keys(filter.where);
return function (obj) {
var pass = true;
keys.forEach(function (key) {
if (!test(filter.where[key], obj[key])) {
pass = false;
return sql;
function buildWhere(conds) {
var cs = [];
Object.keys(conds).forEach(function (key) {
var keyEscaped = '`' + key.replace(/\./g, '`.`') + '`'
if (conds[key] === null) {
cs.push(keyEscaped + ' IS NULL');
} else {
cs.push(keyEscaped + ' = ' + self.toDatabase(props[key], conds[key]));
}
});
return pass;
return 'WHERE ' + cs.join(' AND ');
}
function test(example, value) {
if (typeof value === 'string' && example && example.constructor.name === 'RegExp') {
return value.match(example);
}
// not strict equality
return example == value;
function buildOrderBy(order) {
if (typeof order === 'string') order = [order];
return 'ORDER BY ' + order.join(', ');
}
}
function buildLimit(limit, offset) {
return 'LIMIT ' + (offset ? (offset + ', ' + limit) : limit);
}
};
MySQL.prototype.destroyAll = function destroyAll(model, callback) {
this.query('DELETE FROM ' + model, function (err) {

View File

@ -8,7 +8,7 @@
},
"main": "index.js",
"scripts": {
"test": "ONLY=memory ./support/nodeunit/bin/nodeunit test/*_test.* & ONLY=redis nodeunit test/common_test.js"
"test": "ONLY=memory ./support/nodeunit/bin/nodeunit test/*_test.* & ONLY=redis nodeunit test/common_test.js & only=mysql nodeunit test/common_test.js"
},
"engines": [
"node >= 0.4.0"

View File

@ -12,7 +12,7 @@ var schemas = {
username: 'root'
},
mysql: {
database: 'sequ-test',
database: 'myapp_test',
username: 'root'
},
postgres: {
@ -34,7 +34,7 @@ Object.keys(schemas).forEach(function (schemaName) {
if (process.env.ONLY && process.env.ONLY !== schemaName) return;
context(schemaName, function () {
var schema = new Schema(schemaName, schemas[schemaName]);
// schema.log = console.log;
schema.log = console.log;
testOrm(schema);
if (specificTest[schemaName]) specificTest[schemaName](schema);
});
@ -327,6 +327,7 @@ function testOrm(schema) {
});
// matching regexp
if (Post.schema.name === 'mysql') done(); else
Post.all({where: {title: /hello/i}}, function (err, res) {
var pass = true;
res.forEach(function (r) {
@ -425,7 +426,13 @@ function testOrm(schema) {
it('should handle ORDER clause', function (test) {
var titles = [ 'Title A', 'Title Z', 'Title M', 'Title B', 'Title C' ];
var dates = [ 5, 9, 0, 17, 9 ];
var dates = Post.schema.name === 'redis' ? [ 5, 9, 0, 17, 9 ] : [
new Date(1000 * 5 ),
new Date(1000 * 9),
new Date(1000 * 0),
new Date(1000 * 17),
new Date(1000 * 9)
];
titles.forEach(function (t, i) {
Post.create({title: t, date: dates[i]}, done);
});
@ -434,8 +441,8 @@ function testOrm(schema) {
function done(err, obj) {
if (++i === titles.length) {
doStringTest();
doFilterAndSortTest();
doNumberTest();
doFilterAndSortTest();
}
}
@ -444,6 +451,8 @@ function testOrm(schema) {
function doStringTest() {
tests += 1;
Post.all({order: 'title'}, function (err, posts) {
if (err) console.log(err);
test.equal(posts.length, 5);
titles.sort().forEach(function (t, i) {
test.equal(posts[i].title, t);
});
@ -454,8 +463,10 @@ function testOrm(schema) {
function doNumberTest() {
tests += 1;
Post.all({order: 'date'}, function (err, posts) {
if (err) console.log(err);
test.equal(posts.length, 5);
dates.sort(numerically).forEach(function (d, i) {
test.equal(posts[i].date, d);
test.equal(posts[i].date.toString(), d.toString());
});
finished();
});
@ -463,7 +474,8 @@ function testOrm(schema) {
function doFilterAndSortTest() {
tests += 1;
Post.all({where: {date: 9}, order: 'title', limit: 3}, function (err, posts) {
Post.all({where: {title: new Date(1000 * 9)}, order: 'title', limit: 3}, function (err, posts) {
if (err) console.log(err);
test.equal(posts.length, 2, 'Exactly 2 posts returned by query');
[ 'Title C', 'Title Z' ].forEach(function (t, i) {
if (posts[i]) {