Skip to content

Commit

Permalink
Add to MySQL adapter transaction support
Browse files Browse the repository at this point in the history
  • Loading branch information
biggora committed Mar 3, 2014
1 parent aebdc95 commit 29a4fc0
Show file tree
Hide file tree
Showing 4 changed files with 123 additions and 21 deletions.
5 changes: 2 additions & 3 deletions lib/abstract-class.js
Original file line number Diff line number Diff line change
Expand Up @@ -106,7 +106,7 @@ AbstractClass.prototype._initProperties = function(data, applySetters) {
});

ctor.forEachProperty(function(attr) {
var type = properties[attr].type;
var type = properties[attr].type;
if (BASE_TYPES.indexOf(type.name) === -1) {
if (typeof self.__data[attr] !== 'object' && self.__data[attr]) {
try {
Expand Down Expand Up @@ -1073,7 +1073,7 @@ AbstractClass.hasMany = function hasMany(anotherClass, params) {
// which is actually just anotherClass.all({where: {thisModelNameId: this.id}}, cb);
defineScope(this.prototype, anotherClass, methodName, function() {
var x = {}, id;
if(typeof this.id === 'object') {
if (typeof this.id === 'object') {
id = this.id.toString();
} else {
id = this.id;
Expand Down Expand Up @@ -1386,7 +1386,6 @@ AbstractClass.ensureIndex = function ensureIndex(fields, params, callback) {
}
};


function buildQuery(opts, model) {

for (var okey in model.q.conditions) {
Expand Down
77 changes: 60 additions & 17 deletions lib/adapters/mysql.js
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ exports.initialize = function initializeSchema(schema, callback) {
if (!mysql) {
return;
}

var s = schema.settings;
var conSettings = {
host: s.host || 'localhost',
Expand All @@ -18,7 +18,7 @@ exports.initialize = function initializeSchema(schema, callback) {
password: s.password,
debug: s.debug
};

if (s.pool) {
var pool = mysql.createPool(conSettings);
schema.client = pool;
Expand All @@ -32,7 +32,7 @@ exports.initialize = function initializeSchema(schema, callback) {
schema.client = mysql.createConnection(conSettings);
}

schema.adapter = new MySQL(schema.client);
schema.adapter = new MySQL(schema.client, conSettings);
schema.adapter.schema = schema;
schema.client.query('USE `' + s.database + '`', function(err) {
if (err && err.message.match(/^unknown database/i)) {
Expand All @@ -53,22 +53,27 @@ exports.initialize = function initializeSchema(schema, callback) {
/**
* MySQL adapter
* @param {Object} client
* @param {Object} conSettings
*/
function MySQL(client) {
function MySQL(client, conSettings) {
this._models = {};
this.log = console.log;
this.client = client;
this.settings = conSettings;
}

require('util').inherits(MySQL, BaseSQL);

MySQL.prototype.query = function(sql, callback) {
var client = this.client;
var time = Date.now();
var log = this.log || console.log;
if (typeof callback !== 'function') {
throw new Error('callback should be a function');
}
this.client.query(sql, function(err, data) {
client.query(sql, function(err, data) {
if (log) {
// log(new Date().toISOString(), '###', sql, err);
}
if (err && err.message.match(/^unknown database/i)) {
var dbName = err.message.match(/^unknown database '(.*?)'/i)[1];
client.query('CREATE DATABASE ' + dbName, function(error) {
Expand All @@ -78,15 +83,54 @@ MySQL.prototype.query = function(sql, callback) {
callback(err);
}
});
return;
}
if (log) {
log(sql, time);
} else {
return callback(err, data);
}
callback(err, data);
});
};

/**
* Start transaction callback(err, id)
* @param {Object} params
* @param {Function} callback
*/
MySQL.prototype.begin = function(params, callback) {
var self = this;
if ('function' === typeof params) {
callback = params;
params = null;
}
self.query('USE `' + self.schema.settings.database + '`', function() {
self.query('START TRANSACTION', callback);
});
};

/**
* Commit transaction callback(err, id)
* @param {Object} params
* @param {Function} callback
*/
MySQL.prototype.commit = function(params, callback) {
if ('function' === typeof params) {
callback = params;
params = null;
}
this.query('COMMIT', callback);
};

/**
* Rollback transaction callback(err, id)
* @param {Object} params
* @param {Function} callback
*/
MySQL.prototype.rollback = function(params, callback) {
if ('function' === typeof params) {
callback = params;
params = null;
}
this.query('ROLLBACK', callback);
};

/**
* Create multi column index callback(err, id)
* @param {Object} model
Expand All @@ -107,8 +151,7 @@ MySQL.prototype.ensureIndex = function(model, fields, params, callback) {
}
// sql = 'USE `' + self.schema.settings.database + '`; ';
sql += 'ALTER TABLE `' + model + '` ADD ' + kind + ' INDEX `' + keyName + '` (' + afld.join(', ') + ');';

self.command(sql, callback);
self.query(sql, callback);
};

/**
Expand All @@ -120,7 +163,7 @@ MySQL.prototype.ensureIndex = function(model, fields, params, callback) {
MySQL.prototype.create = function(model, data, callback) {
var fields = this.toFields(model, data);
var sql = 'INSERT INTO ' + this.tableEscaped(model);

if (fields) {
sql += ' SET ' + fields;
} else {
Expand Down Expand Up @@ -173,7 +216,7 @@ MySQL.prototype.toFields = function(model, data) {
if (props[key]) {
fields.push('`' + key.replace(/\./g, '`.`') + '` = ' + this.toDatabase(props[key], data[key]));
}
}.bind(this));
}.bind(this));
return fields.join(',');
};

Expand Down Expand Up @@ -379,7 +422,7 @@ MySQL.prototype.alterTable = function(model, actualFields, actualIndexes, done,
return;
}
var found;
actualFields.forEach(function(f) {
actualFields.forEach(function(f) {
if (f.Field === propName) {
found = f;
}
Expand All @@ -391,7 +434,7 @@ MySQL.prototype.alterTable = function(model, actualFields, actualIndexes, done,
sql.push('ADD COLUMN `' + propName + '` ' + self.propertySettingsSQL(model, propName));
}
});

// drop columns
actualFields.forEach(function(f) {
var notFound = !~propNames.indexOf(f.Field);
Expand Down
60 changes: 60 additions & 0 deletions lib/schema.js
Original file line number Diff line number Diff line change
Expand Up @@ -428,6 +428,66 @@ Schema.prototype.defineForeignKey = function defineForeignKey(className, key) {
this.models[className].registerProperty(key);
};

/**
* Start transaction
*
* @param {Object} params
* @param {Function} callback
*/
Schema.prototype.begin = function begin(params, callback) {
if (typeof callback === 'undefined') {
callback = function(err) {
return err;
};
}

if (typeof this.adapter.begin === 'undefined') {
callback(new Error('TRANSACTION::begin method not defined for this adapter'));
} else {
this.adapter.begin(params, callback);
}
};

/**
* Commit transaction
*
* @param {Object} params
* @param {Function} callback
*/
Schema.prototype.commit = function commit(params, callback) {
if (typeof callback === 'undefined') {
callback = function(err) {
return err;
};
}

if (typeof this.adapter.commit === 'undefined') {
callback(new Error('TRANSACTION::commit method not defined for this adapter'));
} else {
this.adapter.commit(params, callback);
}
};

/**
* Rollback transaction
*
* @param {Object} params
* @param {Function} callback
*/
Schema.prototype.rollback = function rollback(params, callback) {
if (typeof callback === 'undefined') {
callback = function(err) {
return err;
};
}

if (typeof this.adapter.rollback === 'undefined') {
callback(new Error('TRANSACTION::rollback method not defined for this adapter'));
} else {
this.adapter.rollback(params, callback);
}
};

/**
* Close database connection
*/
Expand Down
2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
{
"name": "caminte",
"description": "ORM for every database: redis, mysql, neo4j, mongodb, rethinkdb, postgres, sqlite, tingodb",
"version": "0.0.13",
"version": "0.0.14",
"author": "Aleksej Gordejev <aleksej@gordejev.lv> (http://www.gordejev.lv)",
"homepage": "http://camintejs.com/",
"contributors": [
Expand Down

0 comments on commit 29a4fc0

Please sign in to comment.