Skip to content

Commit

Permalink
Mysql sort, where and limit
Browse files Browse the repository at this point in the history
  • Loading branch information
1602 committed Jan 19, 2012
1 parent 7427289 commit 14c34a8
Show file tree
Hide file tree
Showing 4 changed files with 67 additions and 31 deletions.
2 changes: 2 additions & 0 deletions .travis.yml
Expand Up @@ -4,3 +4,5 @@ node_js:
- 0.6 - 0.6
- 0.7 - 0.7
before_install: git submodule init && git submodule --quiet update before_install: git submodule init && git submodule --quiet update
before_script:
- "mysql -e 'create database myapp_test;'"
70 changes: 46 additions & 24 deletions lib/adapters/mysql.js
Expand Up @@ -71,7 +71,7 @@ MySQL.prototype.toFields = function (model, data) {
var props = this._models[model].properties; var props = this._models[model].properties;
Object.keys(data).forEach(function (key) { Object.keys(data).forEach(function (key) {
if (props[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)); }.bind(this));
return fields.join(','); return fields.join(',');
Expand All @@ -93,7 +93,7 @@ MySQL.prototype.toDatabase = function (prop, val) {
val.getMinutes(), val.getMinutes(),
val.getSeconds() val.getSeconds()
].join('-'); ].join('-');
return this.client.escape(val); return '"' + val + '"';
} }
if (prop.type.name == "Boolean") return val ? 1 : 0; if (prop.type.name == "Boolean") return val ? 1 : 0;
return this.client.escape(val.toString()); return this.client.escape(val.toString());
Expand Down Expand Up @@ -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) { 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) { if (err) {
return callback(err, []); return callback(err, []);
} }
callback(err, filter ? data.filter(applyFilter(filter)) : data); callback(null, data);
}.bind(this)); }.bind(this));
};


function applyFilter(filter) { return sql;
if (typeof filter.where === 'function') {
return filter; function buildWhere(conds) {
} var cs = [];
var keys = Object.keys(filter.where); Object.keys(conds).forEach(function (key) {
return function (obj) { var keyEscaped = '`' + key.replace(/\./g, '`.`') + '`'
var pass = true; if (conds[key] === null) {
keys.forEach(function (key) { cs.push(keyEscaped + ' IS NULL');
if (!test(filter.where[key], obj[key])) { } else {
pass = false; cs.push(keyEscaped + ' = ' + self.toDatabase(props[key], conds[key]));
} }
}); });
return pass; return 'WHERE ' + cs.join(' AND ');
} }


function test(example, value) { function buildOrderBy(order) {
if (typeof value === 'string' && example && example.constructor.name === 'RegExp') { if (typeof order === 'string') order = [order];
return value.match(example); return 'ORDER BY ' + order.join(', ');
}
// not strict equality
return example == value;
} }
}
function buildLimit(limit, offset) {
return 'LIMIT ' + (offset ? (offset + ', ' + limit) : limit);
}

};


MySQL.prototype.destroyAll = function destroyAll(model, callback) { MySQL.prototype.destroyAll = function destroyAll(model, callback) {
this.query('DELETE FROM ' + model, function (err) { this.query('DELETE FROM ' + model, function (err) {
Expand Down
2 changes: 1 addition & 1 deletion package.json
Expand Up @@ -8,7 +8,7 @@
}, },
"main": "index.js", "main": "index.js",
"scripts": { "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": [ "engines": [
"node >= 0.4.0" "node >= 0.4.0"
Expand Down
24 changes: 18 additions & 6 deletions test/common_test.js
Expand Up @@ -12,7 +12,7 @@ var schemas = {
username: 'root' username: 'root'
}, },
mysql: { mysql: {
database: 'sequ-test', database: 'myapp_test',
username: 'root' username: 'root'
}, },
postgres: { postgres: {
Expand All @@ -34,7 +34,7 @@ Object.keys(schemas).forEach(function (schemaName) {
if (process.env.ONLY && process.env.ONLY !== schemaName) return; if (process.env.ONLY && process.env.ONLY !== schemaName) return;
context(schemaName, function () { context(schemaName, function () {
var schema = new Schema(schemaName, schemas[schemaName]); var schema = new Schema(schemaName, schemas[schemaName]);
// schema.log = console.log; schema.log = console.log;
testOrm(schema); testOrm(schema);
if (specificTest[schemaName]) specificTest[schemaName](schema); if (specificTest[schemaName]) specificTest[schemaName](schema);
}); });
Expand Down Expand Up @@ -327,6 +327,7 @@ function testOrm(schema) {
}); });


// matching regexp // matching regexp
if (Post.schema.name === 'mysql') done(); else
Post.all({where: {title: /hello/i}}, function (err, res) { Post.all({where: {title: /hello/i}}, function (err, res) {
var pass = true; var pass = true;
res.forEach(function (r) { res.forEach(function (r) {
Expand Down Expand Up @@ -425,7 +426,13 @@ function testOrm(schema) {


it('should handle ORDER clause', function (test) { it('should handle ORDER clause', function (test) {
var titles = [ 'Title A', 'Title Z', 'Title M', 'Title B', 'Title C' ]; 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) { titles.forEach(function (t, i) {
Post.create({title: t, date: dates[i]}, done); Post.create({title: t, date: dates[i]}, done);
}); });
Expand All @@ -434,8 +441,8 @@ function testOrm(schema) {
function done(err, obj) { function done(err, obj) {
if (++i === titles.length) { if (++i === titles.length) {
doStringTest(); doStringTest();
doFilterAndSortTest();
doNumberTest(); doNumberTest();
doFilterAndSortTest();
} }
} }


Expand All @@ -444,6 +451,8 @@ function testOrm(schema) {
function doStringTest() { function doStringTest() {
tests += 1; tests += 1;
Post.all({order: 'title'}, function (err, posts) { Post.all({order: 'title'}, function (err, posts) {
if (err) console.log(err);
test.equal(posts.length, 5);
titles.sort().forEach(function (t, i) { titles.sort().forEach(function (t, i) {
test.equal(posts[i].title, t); test.equal(posts[i].title, t);
}); });
Expand All @@ -454,16 +463,19 @@ function testOrm(schema) {
function doNumberTest() { function doNumberTest() {
tests += 1; tests += 1;
Post.all({order: 'date'}, function (err, posts) { Post.all({order: 'date'}, function (err, posts) {
if (err) console.log(err);
test.equal(posts.length, 5);
dates.sort(numerically).forEach(function (d, i) { dates.sort(numerically).forEach(function (d, i) {
test.equal(posts[i].date, d); test.equal(posts[i].date.toString(), d.toString());
}); });
finished(); finished();
}); });
} }


function doFilterAndSortTest() { function doFilterAndSortTest() {
tests += 1; 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'); test.equal(posts.length, 2, 'Exactly 2 posts returned by query');
[ 'Title C', 'Title Z' ].forEach(function (t, i) { [ 'Title C', 'Title Z' ].forEach(function (t, i) {
if (posts[i]) { if (posts[i]) {
Expand Down

0 comments on commit 14c34a8

Please sign in to comment.