diff --git a/lib/mysql.js b/lib/mysql.js index 135e448..28f0069 100644 --- a/lib/mysql.js +++ b/lib/mysql.js @@ -323,6 +323,9 @@ MySQL.prototype.toDatabase = function (prop, val, forCreate) { if (!prop) { return this.client.escape(val); } + if (prop.type === String) { + return this.client.escape(String(val)); + } if (prop.type === Number) { if (isNaN(val)) { val = null; @@ -345,16 +348,25 @@ MySQL.prototype.toDatabase = function (prop, val, forCreate) { return val ? 'Point(' + val.lat + ',' + val.lng + ')' : 'NULL'; } if (prop.type === Object) { - return this.client.escape(val); + return this._serializeObject(val); } if (typeof prop.type === 'function') { - if (prop.type.modelName) { - // For embedded models - return this.client.escape(JSON.stringify(val)); - } - return this.client.escape(prop.type(val)); + return this._serializeObject(val); } - return this.client.escape(val.toString()); + return this._serializeObject(val); +}; + +MySQL.prototype._serializeObject = function(obj) { + var val; + if (obj && typeof obj.toJSON === 'function') { + obj = obj.toJSON(); + } + if (typeof obj !== 'string') { + val = JSON.stringify(obj); + } else { + val = obj; + } + return this.client.escape(val); }; /*! @@ -381,6 +393,12 @@ MySQL.prototype.fromDatabase = function (model, data) { } if (props[p]) { switch (props[p].type.name) { + case 'Number': + val = Number(val); + break; + case 'String': + val = String(val); + break; case 'Date': val = new Date(val.toString().replace(/GMT.*$/, 'GMT')); break; @@ -394,6 +412,17 @@ MySQL.prototype.fromDatabase = function (model, data) { lng: val.y }; break; + case 'List': + case 'Array': + case 'Object': + case 'JSON': + break; + default: + if (!Array.isArray(props[p].type) && !props[p].type.modelName) { + // Do not convert array and model types + val = props[p].type(val); + } + break; } } json[p] = val; diff --git a/test/mysql.test.js b/test/mysql.test.js index c4c5a96..2f533e1 100644 --- a/test/mysql.test.js +++ b/test/mysql.test.js @@ -2,6 +2,19 @@ var should = require('./init.js'); var Post, PostWithStringId, PostWithUniqueTitle, db; +// Mock up mongodb ObjectID +function ObjectID(id) { + if (!(this instanceof ObjectID)) { + return new ObjectID(id); + } + this.id1 = id.substring(0, 2); + this.id2 = id.substring(2); +} + +ObjectID.prototype.toJSON = function() { + return this.id1 + this.id2; +}; + describe('mysql', function () { before(function (done) { @@ -12,7 +25,8 @@ describe('mysql', function () { content: { type: String }, comments: [String], history: Object, - stars: Number + stars: Number, + userId: ObjectID }); PostWithStringId = db.define('PostWithStringId', { @@ -44,11 +58,11 @@ describe('mysql', function () { it('should allow array or object', function (done) { Post.create({title: 'a', content: 'AAA', comments: ['1', '2'], - history: {a: 1, b: 'b'}}, function (err, post) { + history: {a: 1, b: 'b'}}, function(err, post) { should.not.exist(err); - Post.findById(post.id, function (err, p) { + Post.findById(post.id, function(err, p) { p.id.should.be.equal(post.id); p.content.should.be.equal(post.content); @@ -59,7 +73,24 @@ describe('mysql', function () { done(); }); }); + }); + it('should allow ObjectID', function(done) { + var uid = new ObjectID('123'); + Post.create({title: 'a', content: 'AAA', userId: uid}, + function(err, post) { + + should.not.exist(err); + + Post.findById(post.id, function(err, p) { + p.id.should.be.equal(post.id); + + p.content.should.be.equal(post.content); + p.title.should.be.equal('a'); + p.userId.should.eql(uid); + done(); + }); + }); }); it('updateOrCreate should update the instance', function (done) {