Permalink
Browse files

Mysql sort, where and limit

  • Loading branch information...
1 parent 7427289 commit 14c34a805829c94f30137b88841da2f1006549df @1602 committed Jan 19, 2012
Showing with 67 additions and 31 deletions.
  1. +2 −0 .travis.yml
  2. +46 −24 lib/adapters/mysql.js
  3. +1 −1 package.json
  4. +18 −6 test/common_test.js
View
@@ -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
@@ -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
@@ -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
@@ -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,16 +463,19 @@ 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();
});
}
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]) {

0 comments on commit 14c34a8

Please sign in to comment.