This commit is contained in:
Anatoliy Chakkaev 2011-10-23 23:43:53 +04:00
parent 8b6c608c6c
commit f251ac9a5b
4 changed files with 99 additions and 48 deletions

View File

@ -8,14 +8,12 @@ exports.initialize = function initializeSchema(schema, callback) {
schema.client = mysql.createClient({
host: s.host || 'localhost',
port: s.port || 3306,
user: s.user,
user: s.username,
password: s.password,
database: s.database,
debug: s.debug
});
schema.client.auth(schema.settings.password, callback);
schema.adapter = new MySQL(schema.client);
};
@ -29,57 +27,107 @@ MySQL.prototype.define = function (descr) {
};
MySQL.prototype.save = function (model, data, callback) {
this.client.query()
this.client.hmset(model + ':' + data.id, data, callback);
var sql = 'UPDATE ' + model + ' SET ' + this.toFields(model, data) +
' WHERE id = ' + data.id;
this.client.query(sql, function (err) {
callback(err);
});
};
/**
* Must invoke callback(err, id)
*/
MySQL.prototype.create = function (model, data, callback) {
this.client.incr(model + ':id', function (err, id) {
data.id = id;
this.save(model, data, function (err) {
if (callback) {
callback(err, id);
}
});
var fields = this.toFields(model, data);
var sql = 'INSERT ' + model;
if (fields) {
sql += ' SET ' + fields;
} else {
sql += ' VALUES ()';
}
this.client.query(sql, function (err, info) {
callback(err, info && info.insertId);
});
};
MySQL.prototype.toFields = function (model, data) {
var fields = [];
var props = this._models[model].properties;
Object.keys(data).forEach(function (key) {
if (props[key]) {
fields.push(key + ' = ' + this.toDatabase(props[key], data[key]));
}
}.bind(this));
return fields.join(',');
};
MySQL.prototype.toDatabase = function (prop, val) {
if (prop.type.name === 'Number') return val;
if (val === null) return 'NULL';
if (prop.type.name === 'Date') {
if (!val.toUTCString) {
val = new Date(val);
}
val = [
val.getFullYear(),
val.getMonth() + 1,
val.getDate(),
val.getHours(),
val.getMinutes(),
val.getSeconds()
].join('-');
return this.client.escape(val);
}
return this.client.escape(val.toString());
};
MySQL.prototype.fromDatabase = function (model, data) {
if (!data) return null;
var props = this._models[model].properties;
Object.keys(data).forEach(function (key) {
var val = data[key];
if (props[key]) {
// if (props[key])
}
data[key] = val;
});
return data;
};
MySQL.prototype.exists = function (model, id, callback) {
this.client.exists(model + ':' + id, function (err, exists) {
if (callback) {
callback(err, exists);
}
var sql = 'SELECT 1 FROM ' + model + ' WHERE id = ' + id + ' LIMIT 1';
this.client.query(sql, function (err, data) {
if (err) return callback(err);
callback(null, data.length === 1);
});
};
MySQL.prototype.find = function find(model, id, callback) {
this.client.hgetall(model + ':' + id, function (err, data) {
if (data && data.id) {
data.id = id;
var sql = 'SELECT * FROM ' + model + ' WHERE id = ' + id + ' LIMIT 1';
this.client.query(sql, function (err, data) {
if (data && data.length === 1) {
data[0].id = id;
} else {
data = null;
data = [null];
}
callback(err, data);
});
callback(err, this.fromDatabase(model, data[0]));
}.bind(this));
};
MySQL.prototype.destroy = function destroy(model, id, callback) {
this.client.del(model + ':' + id, function (err) {
var sql = 'DELETE FROM ' + model + ' WHERE id = ' + id + ' LIMIT 1';
this.client.query(sql, function (err) {
callback(err);
});
};
MySQL.prototype.all = function all(model, filter, callback) {
this.client.keys(model + ':*', function (err, keys) {
this.client.query('SELECT * FROM ' + model, function (err, data) {
if (err) {
return callback(err, []);
}
var query = keys.map(function (key) {
return ['hgetall', key];
});
this.client.multi(query).exec(function (err, replies) {
callback(err, filter ? replies.filter(applyFilter(filter)) : replies);
});
callback(err, filter ? data.filter(applyFilter(filter)) : data);
}.bind(this));
};
@ -108,27 +156,22 @@ function applyFilter(filter) {
}
MySQL.prototype.destroyAll = function destroyAll(model, callback) {
this.client.keys(model + ':*', function (err, keys) {
this.client.query('DELETE FROM ' + model, function (err) {
if (err) {
return callback(err, []);
}
var query = keys.map(function (key) {
return ['del', key];
});
this.client.multi(query).exec(function (err, replies) {
callback(err);
});
callback(err);
}.bind(this));
};
MySQL.prototype.count = function count(model, callback) {
this.client.keys(model + ':*', function (err, keys) {
callback(err, err ? null : keys.length);
this.client.query('SELECT count(*) as cnt FROM ' + model, function (err, res) {
callback(err, err ? null : res[0].cnt);
});
};
MySQL.prototype.updateAttributes = function updateAttrs(model, id, data, cb) {
this.client.hmset(model + ':' + id, data, cb);
data.id = id;
this.save(model, data, cb);
};

View File

@ -3,6 +3,7 @@
*/
var AbstractClass = require('./abstract-class').AbstractClass;
var util = require('util');
var path = require('path');
/**
* Export public API
@ -34,9 +35,9 @@ function Schema(name, settings) {
// this is only one initialization entry point of adapter
// this module should define `adapter` member of `this` (schema)
var adapter;
try {
if (path.existsSync(__dirname + '/adapters/' + name + '.js')) {
adapter = require('./adapters/' + name);
} catch (e) {
} else {
try {
adapter = require(name);
} catch (e) {
@ -146,10 +147,10 @@ Schema.prototype.defineForeignKey = function defineForeignKey(className, key) {
if (this.adapter.defineForeignKey) {
this.adapter.defineForeignKey(className, key, function (err, keyType) {
if (err) throw err;
this.definitions[className].properties[key] = keyType;
this.definitions[className].properties[key] = {type: keyType};
}.bind(this));
} else {
this.definitions[className].properties[key] = Number;
this.definitions[className].properties[key] = {type: Number};
}
};

View File

@ -15,7 +15,8 @@
},
"dependencies": {
"redis": ">= 0.6.7",
"mongoose": ">= 2.2.3"
"mongoose": ">= 2.2.3",
"mysql": ">= 0.9.4"
},
"devDependencies": {}
}

View File

@ -11,6 +11,10 @@ var schemas = {
database: 'sequ-test',
username: 'root'
},
mysql: {
database: 'sequ-test',
username: 'root'
},
neo4j: { url: 'http://localhost:7474/' },
mongoose: { url: 'mongodb://localhost/test' },
redis: {},
@ -128,7 +132,7 @@ function testOrm(schema) {
title: title,
date: date
}, function (err, obj) {
test.ok(obj.id);
test.ok(obj.id, 'Object id should present');
test.equals(obj.title, title);
// test.equals(obj.date, date);
obj.title = title2;
@ -154,7 +158,8 @@ function testOrm(schema) {
test.equals(obj.date, date);
Post.find(obj.id, function () {
test.equal(obj.title, title);
test.equal(obj.date, date.toString());
console.log(obj.date.toString());
test.equal(obj.date.toString(), date.toString());
test.done();
});
});
@ -189,6 +194,7 @@ function testOrm(schema) {
test.ok(exists, 'Object exists');
post.destroy(function () {
Post.exists(post.id, function (err, exists) {
if (err) console.log(err);
test.ok(!exists, 'Hey! ORM told me that object exists, but it looks like it doesn\'t. Something went wrong...');
Post.find(post.id, function (err, obj) {
test.equal(obj, null, 'Param obj should be null');