Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with HTTPS or Subversion.

Download ZIP
Browse files

refactored for jslint

  • Loading branch information...
commit ea3a390eb7352f57cfc4b254e0b5360bb54ba4cd 1 parent 1b6dc0f
@joeferner authored
View
4 jslint
@@ -0,0 +1,4 @@
+DEFAULTFILES="lib/connection.js lib/driver.js lib/model.js lib/persist.js lib/persist_utils.js lib/drivers/* lib/query.js lib/sqltree.js lib/transaction.js lib/type.js"
+FILES=${1:-$DEFAULTFILES}
+echo $FILES
+jslint --indent=2 --nomen --vars --node --continue --forin --plusplus --color $FILES
View
64 lib/class.js
@@ -0,0 +1,64 @@
+/* Simple JavaScript Inheritance
+ * By John Resig http://ejohn.org/
+ * MIT Licensed.
+ */
+// Inspired by base2 and Prototype
+var initializing = false, fnTest = /xyz/.test(function(){xyz;}) ? /\b_super\b/ : /.*/;
+
+// The base Class implementation (does nothing)
+var Class = function(){};
+
+// Create a new Class that inherits from this class
+Class.extend = function(prop) {
+ var _super = this.prototype;
+
+ // Instantiate a base class (but only create the instance,
+ // don't run the init constructor)
+ initializing = true;
+ var prototype = new this();
+ initializing = false;
+
+ // Copy the properties over onto the new prototype
+ for (var name in prop) {
+ // Check if we're overwriting an existing function
+ prototype[name] = typeof prop[name] == "function" &&
+ typeof _super[name] == "function" && fnTest.test(prop[name]) ?
+ (function(name, fn){
+ return function() {
+ var tmp = this._super;
+
+ // Add a new ._super() method that is the same method
+ // but on the super-class
+ this._super = _super[name];
+
+ // The method only need to be bound temporarily, so we
+ // remove it when we're done executing
+ var ret = fn.apply(this, arguments);
+ this._super = tmp;
+
+ return ret;
+ };
+ })(name, prop[name]) :
+ prop[name];
+ }
+
+ // The dummy class constructor
+ function Class() {
+ // All construction is actually done in the init method
+ if ( !initializing && this.init )
+ this.init.apply(this, arguments);
+ }
+
+ // Populate our constructed prototype object
+ Class.prototype = prototype;
+
+ // Enforce the constructor to be what we expect
+ Class.prototype.constructor = Class;
+
+ // And make this class extendable
+ Class.extend = arguments.callee;
+
+ return Class;
+};
+
+module.exports = Class;
View
200 lib/connection.js
@@ -1,23 +1,24 @@
+'use strict';
var util = require('util');
var persistUtils = require('./persist_utils');
var Transaction = require('./transaction');
var async = require('async');
+var Class = require('./class');
-var Connection = persistUtils.Class.extend({
- init: function(driver) {
+var Connection = Class.extend({
+ init: function (driver) {
this.driver = driver;
},
- save: function(obj, callback) {
+ save: function (obj, callback) {
var self = this;
- if(obj instanceof Array) {
- if(obj.length == 0) {
+ if (obj instanceof Array) {
+ if (obj.length === 0) {
callback(null);
- }
- else {
- this.save(obj[0], function(err) {
- if(err) { callback(err); return; }
+ } else {
+ this.save(obj[0], function (err) {
+ if (err) { callback(err); return; }
self.save(obj.slice(1), callback);
});
}
@@ -27,15 +28,14 @@ var Connection = persistUtils.Class.extend({
this._save(true, obj, callback);
},
- update: function(obj, callback) {
+ update: function (obj, callback) {
var self = this;
- if(obj instanceof Array) {
- if(obj.length == 0) {
+ if (obj instanceof Array) {
+ if (obj.length === 0) {
callback(null);
- }
- else {
- this.update(obj[0], function(err) {
- if(err) { callback(err); return; }
+ } else {
+ this.update(obj[0], function (err) {
+ if (err) { callback(err); return; }
self.update(obj.slice(1), callback);
});
}
@@ -45,36 +45,36 @@ var Connection = persistUtils.Class.extend({
this._save(false, obj, callback);
},
- _save: function(isNew, obj, callback) {
+ _save: function (isNew, obj, callback) {
var self = this;
- if(obj._getModel().onSave) {
+ if (obj._getModel().onSave) {
obj._getModel().onSave(obj);
}
obj._getModel().emit("beforeSave", obj);
- if(isNew) {
+ if (isNew) {
obj._getModel().emit("beforeCreate", obj);
} else {
obj._getModel().emit("beforeUpdate", obj);
}
var sqlAndValues;
- if(isNew) {
+ if (isNew) {
sqlAndValues = this.driver.getInsertSql(obj);
} else {
sqlAndValues = this.driver.getUpdateSql(obj);
}
- this.runSql(sqlAndValues.sql, sqlAndValues.values, function(err, data) {
- if(err) { callback(err); return; }
- if(data.lastId) {
+ this.runSql(sqlAndValues.sql, sqlAndValues.values, function (err, data) {
+ if (err) { callback(err); return; }
+ if (data.lastId) {
var idPropName = obj._getModel().getIdPropertyName();
obj[idPropName] = data.lastId;
}
- obj._getConnection = function() { return self; }; // hide from JSON.stringify
- obj._isPersisted = function() { return true; };
- self.saveAssociations(obj, function(err, obj) {
- if(isNew) {
+ obj._getConnection = function () { return self; }; // hide from JSON.stringify
+ obj._isPersisted = function () { return true; };
+ self.saveAssociations(obj, function (err, obj) {
+ if (isNew) {
obj._getModel().emit("afterCreate", obj);
obj._getModel().emit("afterSave", obj);
} else {
@@ -87,10 +87,10 @@ var Connection = persistUtils.Class.extend({
});
},
- updatePartial: function(model, id, data, callback) {
+ updatePartial: function (model, id, data, callback) {
var self = this;
- if(model.onSave) {
+ if (model.onSave) {
model.onSave(data);
}
@@ -98,11 +98,11 @@ var Connection = persistUtils.Class.extend({
this.runSql(sqlAndValues.sql, sqlAndValues.values, callback);
},
- chain: function(tasks, chainCallback) {
+ chain: function (tasks, chainCallback) {
var self = this;
- if(tasks instanceof Array) {
- async.mapSeries(tasks, function(item, callback){
- if(typeof(item) == 'function') {
+ if (tasks instanceof Array) {
+ async.mapSeries(tasks, function (item, callback) {
+ if (typeof (item) === 'function') {
item.call(item, self, callback);
} else {
callback(new Error('Invalid item for chaining.'));
@@ -110,19 +110,21 @@ var Connection = persistUtils.Class.extend({
}, chainCallback);
} else {
var items = [];
- for(var key in tasks) {
+ var key;
+ for (key in tasks) {
items.push({ key: key, task: tasks[key] });
}
- async.mapSeries(items, function(item, callback){
- item.task.call(item.task, self, function(err, value) {
- if(err) { callback(err); return; }
+ async.mapSeries(items, function (item, callback) {
+ item.task.call(item.task, self, function (err, value) {
+ if (err) { callback(err); return; }
var v = { key: item.key, value: value };
callback(null, v);
});
- }, function(err, items) {
- if(err) { chainCallback(err); return; }
+ }, function (err, items) {
+ if (err) { chainCallback(err); return; }
var results = {};
- for(var i=0; i<items.length; i++) {
+ var i;
+ for (i = 0; i < items.length; i++) {
results[items[i].key] = items[i].value;
}
chainCallback(null, results);
@@ -130,96 +132,100 @@ var Connection = persistUtils.Class.extend({
}
},
- saveAssociation: function(obj, name, association, callback) {
+ saveAssociation: function (obj, name, association, callback) {
var self = this;
- if(association.type == 'hasMany' && obj['_' + name] && association.through) {
+ if (association.type === 'hasMany' && obj['_' + name] && association.through) {
var relatedObjs = obj['_' + name];
var Query = require('./query'); // late bind query because it causes a circular reference
new Query(this, association.through)
.where(association.foreignKey + " = ?", obj.getId())
- .deleteAll(function(err, deleteCallback) {
- async.forEachSeries(relatedObjs, function(relatedObj, saveRelatedObjCallback) {
+ .deleteAll(function (err, deleteCallback) {
+ async.forEachSeries(relatedObjs, function (relatedObj, saveRelatedObjCallback) {
var sqlAndValues = self.driver.getManyToManyInsertSql(association, obj, relatedObj);
self.runSql(sqlAndValues.sql, sqlAndValues.values, saveRelatedObjCallback);
- }, callback)
+ }, callback);
});
} else {
callback(null);
}
},
- saveAssociations: function(obj, callback) {
+ saveAssociations: function (obj, callback) {
var self = this;
var associations = [];
- for(var name in obj._getModel().associations) {
+ var name;
+ for (name in obj._getModel().associations) {
associations.push({
name: name,
association: obj._getModel().associations[name]
});
}
- async.forEachSeries(associations, function(association, saveAssociationCallback) {
+ async.forEachSeries(associations, function (association, saveAssociationCallback) {
self.saveAssociation(obj, association.name, association.association, saveAssociationCallback);
- }, function(err) {
+ }, function (err) {
callback(err, obj);
});
},
- each: function(sqlTree, callback, doneCallback) {
+ each: function (sqlTree, callback, doneCallback) {
var self = this;
var sqlAndValues = this.driver.getSqlFromSqlTree(sqlTree);
- this.runSqlEach(sqlAndValues.sql, sqlAndValues.values, function(err, data) {
- if(err) { callback(err); return; }
+ this.runSqlEach(sqlAndValues.sql, sqlAndValues.values, function (err, data) {
+ if (err) { callback(err); return; }
var obj = sqlTree.toObject(data);
- obj._getConnection = function() { return self; }; // hide from JSON.stringify
+ obj._getConnection = function () { return self; }; // hide from JSON.stringify
callback(null, obj);
- }, function() {
- if(doneCallback) {
+ }, function () {
+ if (doneCallback) {
doneCallback();
}
});
},
- _resultsArrayGetById: function(model, array, id) {
- for(var i=0; i<array.length; i++) {
+ _resultsArrayGetById: function (model, array, id) {
+ var i;
+ for (i = 0; i < array.length; i++) {
var itemId = array[i].getId();
- if(itemId == id) {
+ if (itemId === id) {
return array[i];
}
}
return null;
},
- _augmentResultsArrayWithHelpers: function(model, array) {
+ _augmentResultsArrayWithHelpers: function (model, array) {
array.getById = this._resultsArrayGetById.bind(this, model, array);
},
- all: function(sqlTree, callback) {
+ all: function (sqlTree, callback) {
var self = this;
var sqlAndValues = this.driver.getSqlFromSqlTree(sqlTree);
- this.runSqlAll(sqlAndValues.sql, sqlAndValues.values, function(err, data) {
- if(err) { callback(err); return; }
+ this.runSqlAll(sqlAndValues.sql, sqlAndValues.values, function (err, data) {
+ if (err) { callback(err); return; }
var objs = sqlTree.toObjects(data);
// add connections to all the objects
- for(var i=0; i<objs.length; i++) {
- objs[i]._getConnection = function() { return self; }; // hide from JSON.stringify
+ var i;
+ var selfFunc = function () { return self; };
+ for (i = 0; i < objs.length; i++) {
+ objs[i]._getConnection = selfFunc; // hide from JSON.stringify
}
- if(typeof(sqlTree.model) == "function") {
- self._augmentResultsArrayWithHelpers(sqlTree.model(), objs)
+ if (typeof (sqlTree.model) === "function") {
+ self._augmentResultsArrayWithHelpers(sqlTree.model(), objs);
}
callback(null, objs);
});
},
- single: function(sqlTree, fieldName, callback) {
+ single: function (sqlTree, fieldName, callback) {
var self = this;
var sqlAndValues = this.driver.getSqlFromSqlTree(sqlTree);
- this.runSqlAll(sqlAndValues.sql, sqlAndValues.values, function(err, data) {
- if(err) { callback(err); return; }
+ this.runSqlAll(sqlAndValues.sql, sqlAndValues.values, function (err, data) {
+ if (err) { callback(err); return; }
callback(null, data[0][fieldName]);
});
},
@@ -228,19 +234,19 @@ var Connection = persistUtils.Class.extend({
// [sql, ...], callback
// sql, values, callback
// sql, callback
- runSql: function() {
+ runSql: function () {
var self = this;
var args = arguments;
// todo: there has to be a better way to handle this mess.
// todo: when it's an array the results to callback should be an array of results.
- if(arguments[0] instanceof Array) {
- runSqlCallback = args[arguments.length-1];
- if(typeof(runSqlCallback) != "function") runSqlCallback = function(){};
+ if (arguments[0] instanceof Array) {
+ var runSqlCallback = args[arguments.length - 1];
+ if (typeof (runSqlCallback) !== "function") { runSqlCallback = function () {}; }
- async.mapSeries(arguments[0], function(item, callback) {
- if(args.length == 2) {
+ async.mapSeries(arguments[0], function (item, callback) {
+ if (args.length === 2) {
self.runSql(item, callback);
- } else if(args.length == 3) {
+ } else if (args.length === 3) {
self.runSql(item, args[1], callback);
} else {
throw new Error("invalid number of arguments");
@@ -250,64 +256,64 @@ var Connection = persistUtils.Class.extend({
}
var stmt;
- if(arguments.length == 2) { // sql, callback
+ if (arguments.length === 2) { // sql, callback
try {
this.runSql2(arguments[0], arguments[1]);
- } catch(e) {
- e.sql = arguments[0];
- e.values = arguments[1];
- throw e;
+ } catch (ex1) {
+ ex1.sql = arguments[0];
+ ex1.values = arguments[1];
+ throw ex1;
}
- } else if(arguments.length == 3) { // sql, values, callback
+ } else if (arguments.length === 3) { // sql, values, callback
try {
this.runSql3(arguments[0], arguments[1], arguments[2]);
- } catch(e) {
- e.sql = arguments[0];
- e.values = arguments[1];
- arguments[2](e);
+ } catch (ex2) {
+ ex2.sql = arguments[0];
+ ex2.values = arguments[1];
+ arguments[2](ex2);
}
} else {
throw new Error("Invalid number of arguments");
}
},
- runSql2: function(sql, callback) {
+ runSql2: function (sql, callback) {
throw new Error("Not Implemented");
},
- runSql3: function(sql, values, callback) {
+ runSql3: function (sql, values, callback) {
throw new Error("Not Implemented");
},
- runSqlAll: function(sql, params, callback) {
+ runSqlAll: function (sql, params, callback) {
throw new Error("Not Implemented");
},
- runSqlEach: function(sql, params, callback, doneCallback) {
+ runSqlEach: function (sql, params, callback, doneCallback) {
throw new Error("Not Implemented");
},
- close: function() {
+ close: function () {
throw new Error("Not Implemented");
},
- tx: function(callback) {
+ tx: function (callback) {
var self = this;
- this.beginTransaction(function(err) {
- if(err) { callback(err); return; }
+ this.beginTransaction(function (err) {
+ if (err) { callback(err); return; }
callback(null, new Transaction(self));
});
},
- beginTransaction: function(callback) {
+ beginTransaction: function (callback) {
throw new Error("Not Implemented");
},
- commitTransaction: function(callback) {
+ commitTransaction: function (callback) {
throw new Error("Not Implemented");
},
- rollbackTransaction: function(callback) {
+ rollbackTransaction: function (callback) {
throw new Error("Not Implemented");
},
});
View
130 lib/driver.js
@@ -1,29 +1,34 @@
+'use strict';
var persistUtils = require('./persist_utils');
var persist = require('./persist');
var util = require('util');
+var Class = require('./class');
-var Driver = persistUtils.Class.extend({
- init: function() {
+var Driver = Class.extend({
+ init: function () {
},
- connect: function(opts, callback) {
+ connect: function (opts, callback) {
throw new Error("Not Implemented");
},
- getValuesSubstitutionString: function(index) {
+ getValuesSubstitutionString: function (index) {
return '?';
},
- getInsertSql: function(obj) {
+ getInsertSql: function (obj) {
var columnNamesSql = [];
var valuesSql = [];
var values = [];
var valueSubstitutionIndex = 1;
- for(var columnKey in obj._getModel().columns) {
+ var columnKey;
+ for (columnKey in obj._getModel().columns) {
var column = obj._getModel().columns[columnKey];
- if(column.primaryKey && column.autoIncrement) continue;
+ if (column.primaryKey && column.autoIncrement) {
+ continue;
+ }
columnNamesSql.push(column.dbColumnName);
valuesSql.push(this.getValuesSubstitutionString(valueSubstitutionIndex++));
values.push(obj[columnKey]);
@@ -35,13 +40,13 @@ var Driver = persistUtils.Class.extend({
return result;
},
- getManyToManyInsertSql: function(association, obj, relatedObj) {
+ getManyToManyInsertSql: function (association, obj, relatedObj) {
var valueSubstitutionIndex = 1;
var columnNamesSql = [ association.foreignKey, association.manyToManyForeignKey ];
var valuesSql = [
this.getValuesSubstitutionString(valueSubstitutionIndex++),
this.getValuesSubstitutionString(valueSubstitutionIndex++)];
- if(!relatedObj.getId) {
+ if (!relatedObj.getId) {
throw new Error('a related object "' + util.inspect(relatedObj, false, 1) + '" from a many-to-many appears to not have come from the database. You must save related objects first before calling save on the parent object.');
}
var values = [ obj.getId(), relatedObj.getId() ];
@@ -52,14 +57,17 @@ var Driver = persistUtils.Class.extend({
return result;
},
- getUpdateSql: function(obj) {
+ getUpdateSql: function (obj) {
var valueSubstitutionIndex = 1;
var columnNamesSql = [];
var values = [];
- for(var columnKey in obj._getModel().columns) {
+ var columnKey;
+ for (columnKey in obj._getModel().columns) {
var column = obj._getModel().columns[columnKey];
- if(column.primaryKey && column.autoIncrement) continue;
+ if (column.primaryKey && column.autoIncrement) {
+ continue;
+ }
columnNamesSql.push(column.dbColumnName + ' = ' + this.getValuesSubstitutionString(valueSubstitutionIndex++));
values.push(obj[columnKey]);
}
@@ -72,21 +80,24 @@ var Driver = persistUtils.Class.extend({
return { sql: sql, values: values };
},
- getUpdatePartialSql: function(model, id, data) {
+ getUpdatePartialSql: function (model, id, data) {
var valueSubstitutionIndex = 1;
var columnNamesSql = [];
var values = [];
- for(var prop in data) {
+ var prop;
+ for (prop in data) {
var column = model.columns[prop];
- if(column) {
- if(column.primaryKey && column.autoIncrement) throw new Error("Invalid column to update '" + prop + "', cannot be a primary or autoincrementing column.");
+ if (column) {
+ if (column.primaryKey && column.autoIncrement) {
+ throw new Error("Invalid column to update '" + prop + "', cannot be a primary or autoincrementing column.");
+ }
columnNamesSql.push(column.dbColumnName + ' = ' + this.getValuesSubstitutionString(valueSubstitutionIndex++));
values.push(data[prop]);
} else {
var association = model.associations[prop];
- if(association) {
- if(association.type == 'hasOne') {
+ if (association) {
+ if (association.type === 'hasOne') {
columnNamesSql.push(association.foreignKey + ' = ' + this.getValuesSubstitutionString(valueSubstitutionIndex++));
values.push(data[prop].getId());
} else {
@@ -98,7 +109,7 @@ var Driver = persistUtils.Class.extend({
}
}
- if(columnNamesSql.length == 0) {
+ if (columnNamesSql.length === 0) {
throw new Error("No columns to update.");
}
@@ -111,34 +122,34 @@ var Driver = persistUtils.Class.extend({
return results;
},
- getColumnName: function(column, aliasTables) {
+ getColumnName: function (column, aliasTables) {
var name = column.dbColumnName;
- if(aliasTables) {
+ if (aliasTables) {
name = column.tableAlias + '.' + name;
}
return name;
},
- propertyNamesToColumnNames: function(sqlTree, expr) {
- return expr.replace(/([a-zA-Z_\.]+)/g, function(m) {
+ propertyNamesToColumnNames: function (sqlTree, expr) {
+ return expr.replace(/([a-zA-Z_\.]+)/g, function (m) {
var parts = m.split('.');
var partIndex = 0;
- if(sqlTree.model && sqlTree.model.columns) {
+ if (sqlTree.model && sqlTree.model.columns) {
var model = sqlTree.model;
- for(; partIndex < parts.length - 1; partIndex++) {
+ for (partIndex; partIndex < parts.length - 1; partIndex++) {
var association = model.associations[parts[partIndex]];
model = association.model;
}
var column = sqlTree.findColumnByModelNameAndColumnName(model.modelName, parts[partIndex]);
- if(column) {
+ if (column) {
return column.tableAlias + '.' + column.dbColumnName;
}
// fall back and try to lookup by name
column = sqlTree.model.columns[m];
- if(column) {
+ if (column) {
return sqlTree.tableAlias + '.' + column.dbColumnName;
}
}
@@ -148,26 +159,27 @@ var Driver = persistUtils.Class.extend({
});
},
- getTableAliasSql: function(tableName, alias) {
+ getTableAliasSql: function (tableName, alias) {
return tableName + " AS " + alias;
},
- getSqlFromSqlTree: function(sqlTree) {
+ getSqlFromSqlTree: function (sqlTree) {
var self = this;
var sql = '';
var values = [];
var aliasTables = true;
var valueSubstitutionIndex = 1;
+ var i;
- if(sqlTree.action == 'delete') {
+ if (sqlTree.action === 'delete') {
aliasTables = false;
}
- if(sqlTree.action == 'min') {
+ if (sqlTree.action === 'min') {
sql += 'SELECT min(' + this.getColumnName(sqlTree.columns[0], aliasTables) + ') as min ';
- } else if(sqlTree.action == 'max') {
+ } else if (sqlTree.action === 'max') {
sql += 'SELECT max(' + this.getColumnName(sqlTree.columns[0], aliasTables) + ') as max ';
- } else if(sqlTree.action == 'count') {
+ } else if (sqlTree.action === 'count') {
sql += 'SELECT count(*) as count ';
} else {
sql += sqlTree.action + ' ';
@@ -175,20 +187,20 @@ var Driver = persistUtils.Class.extend({
sql = this.addColumnsSql(sql, sqlTree, aliasTables);
}
- if(aliasTables) {
+ if (aliasTables) {
sql += util.format('FROM %s ', this.getTableAliasSql(sqlTree.tableName, sqlTree.tableAlias));
} else {
sql += util.format('FROM %s ', sqlTree.tableName);
}
- if(sqlTree.joins) {
- for(var i=0; i<sqlTree.joins.length; i++) {
+ if (sqlTree.joins) {
+ for (i = 0; i < sqlTree.joins.length; i++) {
var join = sqlTree.joins[i];
var joinSql;
- switch(join.type) {
- case 'join': joinSql = "INNER JOIN"; break;
- case 'left join': joinSql = "LEFT JOIN"; break;
- default: throw new Error("unhandled join type '" + join.type + "'");
+ switch (join.type) {
+ case 'join': joinSql = "INNER JOIN"; break;
+ case 'left join': joinSql = "LEFT JOIN"; break;
+ default: throw new Error("unhandled join type '" + join.type + "'");
}
sql += util.format("%s %s ON %s.%s=%s ", joinSql, this.getTableAliasSql(join.otherTable, join.tableAlias), join.tableAlias, join.otherTableId, join.thisTableId);
}
@@ -196,34 +208,35 @@ var Driver = persistUtils.Class.extend({
// process where
var expressions = [];
- for(var i = 0; i<sqlTree.where.length; i++) {
+ var getValuesSubstitutionStringFunc = function (match) {
+ return self.getValuesSubstitutionString(valueSubstitutionIndex++);
+ };
+ for (i = 0; i < sqlTree.where.length; i++) {
var item = sqlTree.where[i];
var expr = item.expr;
- if(aliasTables) {
+ if (aliasTables) {
expr = this.propertyNamesToColumnNames(sqlTree, item.expr);
}
- expr = expr.replace(/\?/, function(match) {
- return self.getValuesSubstitutionString(valueSubstitutionIndex++);
- });
+ expr = expr.replace(/\?/, getValuesSubstitutionStringFunc);
expressions.push(expr);
values = values.concat(item.params);
}
- if(expressions.length > 0) {
+ if (expressions.length > 0) {
sql += 'WHERE ' + expressions.join(' AND ') + ' ';
}
- if(sqlTree.orderBy && sqlTree.orderBy.length > 0) {
+ if (sqlTree.orderBy && sqlTree.orderBy.length > 0) {
sql += 'ORDER BY ';
var orderBys = [];
- for(var i=0; i<sqlTree.orderBy.length; i++) {
+ for (i = 0; i < sqlTree.orderBy.length; i++) {
var orderBy = sqlTree.orderBy[i];
var orderByClause = orderBy.column.alias + ' ';
- if(orderBy.direction) {
- switch(orderBy.direction) {
- case persist.Ascending: orderByClause += 'ASC'; break;
- case persist.Descending: orderByClause += 'DESC'; break;
- default: throw new Error("Invalid order by direction " + orderBy.direction);
+ if (orderBy.direction) {
+ switch (orderBy.direction) {
+ case persist.Ascending: orderByClause += 'ASC'; break;
+ case persist.Descending: orderByClause += 'DESC'; break;
+ default: throw new Error("Invalid order by direction " + orderBy.direction);
}
}
orderBys.push(orderByClause);
@@ -239,9 +252,10 @@ var Driver = persistUtils.Class.extend({
return result;
},
- addColumnsSql: function(sql, sqlTree, aliasTables) {
+ addColumnsSql: function (sql, sqlTree, aliasTables) {
var columns = [];
- for(var i=0; i<sqlTree.columns.length; i++) {
+ var i;
+ for (i = 0; i < sqlTree.columns.length; i++) {
var column = sqlTree.columns[i];
columns.push(this.getColumnName(column, aliasTables) + ' AS ' + column.alias);
}
@@ -249,10 +263,10 @@ var Driver = persistUtils.Class.extend({
return sql;
},
- addLimitClause: function(sql, sqlTree) {
- if(sqlTree.limitCount) {
+ addLimitClause: function (sql, sqlTree) {
+ if (sqlTree.limitCount) {
sql += 'LIMIT ' + sqlTree.limitCount;
- if(sqlTree.limitOffset) {
+ if (sqlTree.limitOffset) {
sql += ' OFFSET ' + sqlTree.limitOffset;
}
sql += ' ';
View
79 lib/drivers/mysql.js
@@ -1,86 +1,71 @@
+'use strict';
var Driver = require('../driver');
var Connection = require('../connection');
-var mysql = require('mysql')
-
-var MySqlDriver = Driver.extend({
- init: function() {
- this._super();
- },
-
- connect: function(opts, callback) {
- if(opts.db) {
- var connection = new MySqlConnection(this, db, false);
- callback(null, connection);
- } else {
- var db = new mysql.createClient(opts);
- var connection = new MySqlConnection(this, db, true);
- callback(null, connection);
- }
- }
-});
+var mysql = require('mysql');
var MySqlConnection = Connection.extend({
- init: function(driver, db, createdConnection) {
+ init: function (driver, db, createdConnection) {
this._super(driver);
this.db = db;
this.createdConnection = createdConnection;
},
- close: function() {
- if(this.createdConnection) {
+ close: function () {
+ if (this.createdConnection) {
this.db.end();
}
},
- beginTransaction: function(callback) {
+ beginTransaction: function (callback) {
this.runSql(["SET autocommit=0", "START TRANSACTION"], callback);
},
- commitTransaction: function(callback) {
+ commitTransaction: function (callback) {
this.runSql("COMMIT", callback);
},
- rollbackTransaction: function(callback) {
+ rollbackTransaction: function (callback) {
this.runSql("ROLLBACK", callback);
},
- updateLastId: function(results) {
- if(results.insertId) {
+ updateLastId: function (results) {
+ if (results.insertId) {
results.lastId = results.insertId;
}
- if(results.affectedRows) {
+ if (results.affectedRows) {
results.changes = results.affectedRows;
}
},
- runSql2: function(sql, callback) {
+ runSql2: function (sql, callback) {
var self = this;
- this.db.query(sql, function(err, results) {
- if(err) { callback(err); return; }
+ this.db.query(sql, function (err, results) {
+ if (err) { callback(err); return; }
self.updateLastId(results);
callback(null, results);
});
},
- runSql3: function(sql, values, callback) {
+ runSql3: function (sql, values, callback) {
var self = this;
- this.db.query(sql, values, function(err, results) {
- if(err) { callback(err); return; }
+ this.db.query(sql, values, function (err, results) {
+ if (err) { callback(err); return; }
self.updateLastId(results);
callback(null, results);
});
},
- runSqlAll: function(sql, params, callback) {
+ runSqlAll: function (sql, params, callback) {
this.runSql(sql, params, callback);
},
- runSqlEach: function(sql, params, callback, doneCallback) {
+ runSqlEach: function (sql, params, callback, doneCallback) {
// todo: check with the mysql project to see if there is a way to do "each" as opposed to getting all the results back
- this.runSql(sql, params, function(err, rows) {
- if(err) { callback(err); return; }
- for(var i=0; i<rows.length; i++) {
+ this.runSql(sql, params, function (err, rows) {
+ if (err) { callback(err); return; }
+ var i;
+ for (i = 0; i < rows.length; i++) {
callback(null, rows[i]);
}
doneCallback();
@@ -88,4 +73,22 @@ var MySqlConnection = Connection.extend({
}
});
+var MySqlDriver = Driver.extend({
+ init: function () {
+ this._super();
+ },
+
+ connect: function (opts, callback) {
+ var conn;
+ if (opts.db) {
+ conn = new MySqlConnection(this, opts.db, false);
+ callback(null, conn);
+ } else {
+ var db = new mysql.createClient(opts);
+ conn = new MySqlConnection(this, db, true);
+ callback(null, conn);
+ }
+ }
+});
+
module.exports = MySqlDriver;
View
203 lib/drivers/oracle.js
@@ -1,3 +1,4 @@
+'use strict';
var Driver = require('../driver');
var Connection = require('../connection');
@@ -5,134 +6,70 @@ var oracle = require('oracle');
var util = require('util');
var persistUtil = require('../persist_utils');
-var OracleDriver = Driver.extend({
- init: function() {
- this._super();
- },
-
- connect: function(opts, callback) {
- var self = this;
- oracle.connect(opts, function(err, conn) {
- if(err) { callback(err); return; }
- var connection = new OracleConnection(self, conn);
- callback(null, connection);
- });
- },
-
- getValuesSubstitutionString: function(index) {
- return ':' + index;
- },
-
- getTableAliasSql: function(tableName, alias) {
- return tableName + " " + alias;
- },
-
- getInsertSql: function(obj) {
- var columnNamesSql = [];
- var valuesSql = [];
- var values = [];
- var valueSubstitutionIndex = 1;
- var autoIncrementColumnName;
-
- for(var columnKey in obj._getModel().columns) {
- var column = obj._getModel().columns[columnKey];
- if(column.primaryKey && column.autoIncrement) {
- autoIncrementColumnName = column.dbColumnName;
- } else {
- columnNamesSql.push(column.dbColumnName);
- valuesSql.push(this.getValuesSubstitutionString(valueSubstitutionIndex++));
- values.push(obj[columnKey]);
- }
- }
-
- var returningSql = '';
- if(autoIncrementColumnName) {
- returningSql = 'RETURNING ' + autoIncrementColumnName + ' INTO ' + this.getValuesSubstitutionString(valueSubstitutionIndex++);
- values.push(new oracle.OutParam());
- }
-
- var sql = util.format('INSERT INTO %s (%s) VALUES (%s) %s', obj._getModel().tableName, columnNamesSql.join(','), valuesSql.join(','), returningSql);
- var result = { sql: sql, values: values };
- //console.log(result);
- return result;
- },
-
- addLimitClause: function(sql, sqlTree) {
- if(sqlTree.limitCount || sqlTree.limitOffset) {
- if(!sqlTree.limitCount) {
- sqlTree.limitCount = 99999999;
- }
- if(!sqlTree.limitOffset) {
- sqlTree.limitOffset = 0;
- }
- sql = util.format("SELECT * FROM (SELECT rnumalias.*, ROWNUM persist_rnum FROM (%s) rnumalias WHERE ROWNUM <= %s) WHERE persist_rnum > %s", sql, sqlTree.limitOffset + sqlTree.limitCount, sqlTree.limitOffset);
- }
- return sql;
- }
-});
-
var OracleConnection = Connection.extend({
- init: function(driver, client) {
+ init: function (driver, client) {
this._super(driver);
this.client = client;
this.client.setAutoCommit(true);
},
- close: function() {
+ close: function () {
this.client.close();
},
- beginTransaction: function(callback) {
+ beginTransaction: function (callback) {
this.client.setAutoCommit(false);
callback();
},
- commitTransaction: function(callback) {
+ commitTransaction: function (callback) {
var self = this;
- this.client.commit(function(err) {
+ this.client.commit(function (err) {
self.client.setAutoCommit(true);
callback(err);
});
},
- rollbackTransaction: function(callback) {
+ rollbackTransaction: function (callback) {
var self = this;
- this.client.rollback(function(err) {
+ this.client.rollback(function (err) {
self.client.setAutoCommit(true);
callback(err);
});
},
- updateLastId: function(results) {
+ updateLastId: function (results) {
//console.log(results);
- if(results.returnParam) {
+ if (results.returnParam) {
results.lastId = results.returnParam;
}
},
- postProcessResults: function(results) {
- if(results instanceof Array) {
- for(var i=0; i<results.length; i++) {
+ postProcessResults: function (results) {
+ if (results instanceof Array) {
+ var fixKeyFunc = function (key, val) {
+ if (key.toLowerCase() === 'persist_rnum') {
+ return null;
+ }
+ if (key && typeof (key) === "string") {
+ return key.toLowerCase();
+ }
+ return key;
+ };
+ var i;
+ for (i = 0; i < results.length; i++) {
var result = results[i];
- persistUtil.alterHashKeys(result, function(key, val) {
- if(key.toLowerCase() == 'persist_rnum') {
- return null;
- }
- if(key && typeof(key) == "string") {
- return key.toLowerCase();
- }
- return key;
- });
+ persistUtil.alterHashKeys(result, fixKeyFunc);
}
}
},
- runSql2: function(sql, callback) {
+ runSql2: function (sql, callback) {
var self = this;
- this.client.execute(sql, [], function(err, results) {
- if(err) { callback(err); return; }
+ this.client.execute(sql, [], function (err, results) {
+ if (err) { callback(err); return; }
self.updateLastId(results);
- if(results.command == 'SELECT') {
+ if (results.command === 'SELECT') {
results = results.rows;
}
self.postProcessResults(results);
@@ -140,25 +77,26 @@ var OracleConnection = Connection.extend({
});
},
- runSql3: function(sql, values, callback) {
+ runSql3: function (sql, values, callback) {
var self = this;
- this.client.execute(sql, values, function(err, results) {
- if(err) { callback(err); return; }
+ this.client.execute(sql, values, function (err, results) {
+ if (err) { callback(err); return; }
self.updateLastId(results);
self.postProcessResults(results);
callback(null, results);
});
},
- runSqlAll: function(sql, params, callback) {
+ runSqlAll: function (sql, params, callback) {
this.runSql(sql, params, callback);
},
- runSqlEach: function(sql, params, callback, doneCallback) {
+ runSqlEach: function (sql, params, callback, doneCallback) {
// todo: check with the db-oracle project to see if there is a way to do "each" as opposed to getting all the results back
- this.runSql(sql, params, function(err, rows) {
- if(err) { callback(err); return; }
- for(var i=0; i<rows.length; i++) {
+ this.runSql(sql, params, function (err, rows) {
+ if (err) { callback(err); return; }
+ var i;
+ for (i = 0; i < rows.length; i++) {
callback(null, rows[i]);
}
doneCallback();
@@ -166,4 +104,71 @@ var OracleConnection = Connection.extend({
}
});
+var OracleDriver = Driver.extend({
+ init: function () {
+ this._super();
+ },
+
+ connect: function (opts, callback) {
+ var self = this;
+ oracle.connect(opts, function (err, conn) {
+ if (err) { callback(err); return; }
+ var connection = new OracleConnection(self, conn);
+ callback(null, connection);
+ });
+ },
+
+ getValuesSubstitutionString: function (index) {
+ return ':' + index;
+ },
+
+ getTableAliasSql: function (tableName, alias) {
+ return tableName + " " + alias;
+ },
+
+ getInsertSql: function (obj) {
+ var columnNamesSql = [];
+ var valuesSql = [];
+ var values = [];
+ var valueSubstitutionIndex = 1;
+ var autoIncrementColumnName;
+
+ var columnKey;
+ for (columnKey in obj._getModel().columns) {
+ var column = obj._getModel().columns[columnKey];
+ if (column.primaryKey && column.autoIncrement) {
+ autoIncrementColumnName = column.dbColumnName;
+ } else {
+ columnNamesSql.push(column.dbColumnName);
+ valuesSql.push(this.getValuesSubstitutionString(valueSubstitutionIndex++));
+ values.push(obj[columnKey]);
+ }
+ }
+
+ var returningSql = '';
+ if (autoIncrementColumnName) {
+ returningSql = 'RETURNING ' + autoIncrementColumnName + ' INTO ' + this.getValuesSubstitutionString(valueSubstitutionIndex++);
+ values.push(new oracle.OutParam());
+ }
+
+ var sql = util.format('INSERT INTO %s (%s) VALUES (%s) %s', obj._getModel().tableName, columnNamesSql.join(','), valuesSql.join(','), returningSql);
+ var result = { sql: sql, values: values };
+ //console.log(result);
+ return result;
+ },
+
+ addLimitClause: function (sql, sqlTree) {
+ if (sqlTree.limitCount || sqlTree.limitOffset) {
+ if (!sqlTree.limitCount) {
+ sqlTree.limitCount = 99999999;
+ }
+ if (!sqlTree.limitOffset) {
+ sqlTree.limitOffset = 0;
+ }
+ sql = util.format("SELECT * FROM (SELECT rnumalias.*, ROWNUM persist_rnum FROM (%s) rnumalias WHERE ROWNUM <= %s) WHERE persist_rnum > %s", sql, sqlTree.limitOffset + sqlTree.limitCount, sqlTree.limitOffset);
+ }
+ return sql;
+ }
+});
+
module.exports = OracleDriver;
View
163 lib/drivers/pg.js
@@ -1,134 +1,84 @@
+'use strict';
var Driver = require('../driver');
var Connection = require('../connection');
var pg = require('pg');
var util = require('util');
-var PostgreSqlDriver = Driver.extend({
- init: function() {
- this._super();
- },
-
- connect: function(opts, callback) {
- var self = this;
- if(opts.db) {
- var connection = new PostgreSqlConnection(self, opts.db, false);
- callback(null, connection);
- } else {
- var client = new pg.Client(opts.connectionString || opts);
- client.connect(function(err) {
- if(err) { callback(err); return; }
- var connection = new PostgreSqlConnection(self, client, true);
- callback(null, connection);
- });
- }
- },
-
- getValuesSubstitutionString: function(index) {
- return '$' + index;
- },
-
- getInsertSql: function(obj) {
- var columnNamesSql = [];
- var valuesSql = [];
- var values = [];
- var valueSubstitutionIndex = 1;
- var autoIncrementColumnName;
-
- for(var columnKey in obj._getModel().columns) {
- var column = obj._getModel().columns[columnKey];
- columnNamesSql.push(column.dbColumnName);
- if(column.primaryKey && column.autoIncrement) {
- autoIncrementColumnName = column.dbColumnName;
- valuesSql.push('DEFAULT');
- } else {
- valuesSql.push(this.getValuesSubstitutionString(valueSubstitutionIndex++));
- values.push(obj[columnKey]);
- }
- }
-
- var returningSql = '';
- if(autoIncrementColumnName) {
- returningSql = 'RETURNING ' + autoIncrementColumnName;
- }
-
- var sql = util.format('INSERT INTO %s (%s) VALUES (%s) %s;', obj._getModel().tableName, columnNamesSql.join(','), valuesSql.join(','), returningSql);
- var result = { sql: sql, values: values };
- //console.log(result);
- return result;
- }
-});
-
var PostgreSqlConnection = Connection.extend({
- init: function(driver, client, createdConnection) {
+ init: function (driver, client, createdConnection) {
this._super(driver);
this.client = client;
this.createdConnection = createdConnection;
},
- close: function() {
- if(this.createdConnection) {
+ close: function () {
+ if (this.createdConnection) {
this.client.end();
}
},
- beginTransaction: function(callback) {
+ beginTransaction: function (callback) {
this.runSql("BEGIN", callback);
},
- commitTransaction: function(callback) {
+ commitTransaction: function (callback) {
this.runSql("COMMIT", callback);
},
- rollbackTransaction: function(callback) {
+ rollbackTransaction: function (callback) {
this.runSql("ROLLBACK", callback);
},
- updateLastId: function(results) {
+ updateLastId: function (results) {
//console.log(results);
- if(results && results.command == 'INSERT' && results.rows && results.rows.length == 1) {
- for(var key in results.rows[0]) {
+ if (results && results.command === 'INSERT' && results.rows && results.rows.length === 1) {
+ var key;
+ for (key in results.rows[0]) {
results.lastId = results.rows[0][key];
- break;
+ if (results.lastId) {
+ break;
+ }
}
}
},
- runSql2: function(sql, callback) {
+ runSql2: function (sql, callback) {
//console.log(sql);
var self = this;
- this.client.query(sql, function(err, results) {
- if(err) { callback(err); return; }
+ this.client.query(sql, function (err, results) {
+ if (err) { callback(err); return; }
self.updateLastId(results);
- if(results.command == 'SELECT') {
+ if (results.command === 'SELECT') {
results = results.rows;
}
callback(null, results);
});
},
- runSql3: function(sql, values, callback) {
+ runSql3: function (sql, values, callback) {
//console.log(sql);
var self = this;
- this.client.query(sql, values, function(err, results) {
- if(err) { callback(err); return; }
+ this.client.query(sql, values, function (err, results) {
+ if (err) { callback(err); return; }
self.updateLastId(results);
- if(results.command == 'SELECT') {
+ if (results.command === 'SELECT') {
results = results.rows;
}
callback(null, results);
});
},
- runSqlAll: function(sql, params, callback) {
+ runSqlAll: function (sql, params, callback) {
this.runSql(sql, params, callback);
},
- runSqlEach: function(sql, params, callback, doneCallback) {
+ runSqlEach: function (sql, params, callback, doneCallback) {
// todo: check with the pg project to see if there is a way to do "each" as opposed to getting all the results back
- this.runSql(sql, params, function(err, rows) {
- if(err) { callback(err); return; }
- for(var i=0; i<rows.length; i++) {
+ this.runSql(sql, params, function (err, rows) {
+ if (err) { callback(err); return; }
+ var i;
+ for (i = 0; i < rows.length; i++) {
callback(null, rows[i]);
}
doneCallback();
@@ -136,4 +86,61 @@ var PostgreSqlConnection = Connection.extend({
}
});
+var PostgreSqlDriver = Driver.extend({
+ init: function () {
+ this._super();
+ },
+
+ connect: function (opts, callback) {
+ var self = this;
+ var conn;
+ if (opts.db) {
+ conn = new PostgreSqlConnection(self, opts.db, false);
+ callback(null, conn);
+ } else {
+ var client = new pg.Client(opts.connectionString || opts);
+ client.connect(function (err) {
+ if (err) { callback(err); return; }
+ conn = new PostgreSqlConnection(self, client, true);
+ callback(null, conn);
+ });
+ }
+ },
+
+ getValuesSubstitutionString: function (index) {
+ return '$' + index;
+ },
+
+ getInsertSql: function (obj) {
+ var columnNamesSql = [];
+ var valuesSql = [];
+ var values = [];
+ var valueSubstitutionIndex = 1;
+ var autoIncrementColumnName;
+
+ var columnKey;
+ for (columnKey in obj._getModel().columns) {
+ var column = obj._getModel().columns[columnKey];
+ columnNamesSql.push(column.dbColumnName);
+ if (column.primaryKey && column.autoIncrement) {
+ autoIncrementColumnName = column.dbColumnName;
+ valuesSql.push('DEFAULT');
+ } else {
+ valuesSql.push(this.getValuesSubstitutionString(valueSubstitutionIndex++));
+ values.push(obj[columnKey]);
+ }
+ }
+
+ var returningSql = '';
+ if (autoIncrementColumnName) {
+ returningSql = 'RETURNING ' + autoIncrementColumnName;
+ }
+
+ var sql = util.format('INSERT INTO %s (%s) VALUES (%s) %s;', obj._getModel().tableName, columnNamesSql.join(','), valuesSql.join(','), returningSql);
+ var result = { sql: sql, values: values };
+ //console.log(result);
+ return result;
+ }
+});
+
module.exports = PostgreSqlDriver;
View
86 lib/drivers/sqlite3.js
@@ -1,72 +1,47 @@
+'use strict';
var Driver = require('../driver');
var Connection = require('../connection');
var sqlite3 = require('sqlite3').verbose();
-var Sqlite3Driver = Driver.extend({
- init: function() {
- this._super();
- },
-
- connect: function(opts, callback) {
- if(opts.db) {
- var connection = new Sqlite3Connection(this, db, false);
- callback(null, connection);
- } else {
- var filename = opts.filename;
- if(!filename) throw new Error("Sqlite3 driver requires 'filename'");
- var trace = opts.trace;
-
- var db = new sqlite3.Database(filename);
- if(trace) {
- db.on('trace', function(sql) {
- console.log(sql);
- });
- }
- var connection = new Sqlite3Connection(this, db, true);
- callback(null, connection);
- }
- }
-});
-
var Sqlite3Connection = Connection.extend({
- init: function(driver, db, createdConnection) {
+ init: function (driver, db, createdConnection) {
this._super(driver);
this.db = db;
this.createdConnection = createdConnection;
},
- close: function() {
- if(this.createdConnection) {
+ close: function () {
+ if (this.createdConnection) {
this.db.close();
}
},
- beginTransaction: function(callback) {
+ beginTransaction: function (callback) {
this.runSql("BEGIN TRANSACTION", callback);
},
- commitTransaction: function(callback) {
+ commitTransaction: function (callback) {
this.runSql("COMMIT TRANSACTION", callback);
},
- rollbackTransaction: function(callback) {
+ rollbackTransaction: function (callback) {
this.runSql("ROLLBACK TRANSACTION", callback);
},
- runSql2: function(sql, callback) {
- this.db.run(sql, function(err) {
- if(err) { callback(err); return; }
+ runSql2: function (sql, callback) {
+ this.db.run(sql, function (err) {
+ if (err) { callback(err); return; }
callback(null, {});
});
},
- runSql3: function(sql, values, callback) {
- var stmt = this.db.prepare(sql, function(err) {
- if(err) callback(err);
+ runSql3: function (sql, values, callback) {
+ var stmt = this.db.prepare(sql, function (err) {
+ if (err) { callback(err); return; }
});
- stmt.run(values, function(err) {
- if(err) { callback(err); return; }
+ stmt.run(values, function (err) {
+ if (err) { callback(err); return; }
callback(null, {
lastId: stmt.lastID,
changes: stmt.changes
@@ -75,13 +50,40 @@ var Sqlite3Connection = Connection.extend({
stmt.finalize();
},
- runSqlAll: function(sql, params, callback) {
+ runSqlAll: function (sql, params, callback) {
this.db.all(sql, params, callback);
},
- runSqlEach: function(sql, params, callback, doneCallback) {
+ runSqlEach: function (sql, params, callback, doneCallback) {
this.db.each(sql, params, callback, doneCallback);
}
});
+var Sqlite3Driver = Driver.extend({
+ init: function () {
+ this._super();
+ },
+
+ connect: function (opts, callback) {
+ var conn;
+ if (opts.db) {
+ conn = new Sqlite3Connection(this, opts.db, false);
+ callback(null, conn);
+ } else {
+ var filename = opts.filename;
+ if (!filename) { throw new Error("Sqlite3 driver requires 'filename'"); }
+ var trace = opts.trace;
+
+ var db = new sqlite3.Database(filename);
+ if (trace) {
+ db.on('trace', function (sql) {
+ console.log(sql);
+ });
+ }
+ conn = new Sqlite3Connection(this, db, true);
+ callback(null, conn);
+ }
+ }
+});
+
module.exports = Sqlite3Driver;
View
590 lib/model.js
@@ -1,71 +1,32 @@
+'use strict';
+
var inflection = require('./inflection');
var Query = require('./query');
var util = require('util');
var persistUtil = require('./persist_utils');
var events = require("events");
-function normalizeType(typeName) {
- return typeName; // TODO: all lower case, verify string, etc.
-}
-
-function normalizeColumnDef(propertyName, columnDef) {
- if(!columnDef) {
- throw new Error(util.format('Invalid column definition for property "%s" of model "%s"', propertyName, this.modelName));
- }
- if(typeof(columnDef) == "string") {
- columnDef = {
- type: normalizeType(columnDef)
- };
- }
-
- if(!columnDef.defaultValue) {
- columnDef.defaultValue = function() { return null; };
- } else {
- if(typeof(columnDef.defaultValue) != "function") {
- var val = columnDef.defaultValue;
- columnDef.defaultValue = function() { return val; };
+function copyValuesIntoObject(values, obj) {
+ var valKey;
+ for (valKey in values) {
+ var setter = obj.__lookupSetter__(valKey);
+ if (setter) {
+ setter(values[valKey]);
+ } else {
+ obj[valKey] = values[valKey];
}
}
-
- if(!columnDef.dbColumnName) {
- columnDef.dbColumnName = inflection.underscore(propertyName);
- }
-
- return columnDef;
-}
-
-function saveInstance(connection, callback) {
- if(!connection) throw new Error("connection is null or undefined");
- if(!connection.update) throw new Error("argument 1 to save does not appear to be a connection");
-
- if(this._isPersisted()) {
- connection.update(this, callback);
- } else {
- connection.save(this, callback);
- }
-}
-
-function updateInstance(connection, props, callback) {
- copyValuesIntoObject(props, this);
- this.save(connection, callback);
}
-function deleteInstance(connection, callback) {
- var self = this;
- this._getModel().emit("beforeDelete", this);
- var query = new Query(connection, this._getModel());
- query.where("id = ?", this[this._getModel().getIdPropertyName()]);
- query.deleteAll(function() {
- self._getModel().emit("afterDelete", self);
- callback.apply(self, arguments);
- });
+function normalizeType(typeName) {
+ return typeName; // TODO: all lower case, verify string, etc.
}
function doesObjectHaveAConnection(obj) {
- if(!obj._getConnection) {
+ if (!obj._getConnection) {
return false;
}
- if(obj._getConnection && !obj._getConnection()) {
+ if (obj._getConnection && !obj._getConnection()) {
return false;
}
return true;
@@ -80,51 +41,50 @@ function addHasManyAssociationMethod(obj, associationName, association) {
// SELECT * FROM phones
// INNER JOIN person_phone ON person_phone.phone_id = phones.id
// WHERE person_phone.person_id = 5
- obj.__defineGetter__(associationName, function() {
- if(!doesObjectHaveAConnection(obj)) {
+ obj.__defineGetter__(associationName, function () {
+ if (!doesObjectHaveAConnection(obj)) {
return [];
}
var query = new Query(obj._getConnection(), association.model);
- if(association.through) {
- query = query.join(association.through, association.manyToManyForeignKey, association.model.getIdColumn().dbColumnName)
+ if (association.through) {
+ query = query.join(association.through, association.manyToManyForeignKey, association.model.getIdColumn().dbColumnName);
}
return query.where(association.foreignKey + " = ?", obj.getId());
});
- obj.__defineSetter__(associationName, function(val){
+ obj.__defineSetter__(associationName, function (val) {
obj['_' + associationName] = val;
});
}
function addHasOneAssociationMethod(obj, associationName, association) {
- var self = this;
var foreignKeyPropertyName = inflection.camelize(association.foreignKey, true);
// foreignKeyPropertyName = personId
// associationName = person
- obj.__defineGetter__(foreignKeyPropertyName, function(){
+ obj.__defineGetter__(foreignKeyPropertyName, function () {
var result = null;
- if(obj['_' + foreignKeyPropertyName]) {
+ if (obj['_' + foreignKeyPropertyName]) {
result = obj['_' + foreignKeyPropertyName];
}
- if(obj['_' + associationName] && obj['_' + associationName].getId) {
+ if (obj['_' + associationName] && obj['_' + associationName].getId) {
result = obj['_' + associationName].getId();
}
return result;
});
- obj.__defineSetter__(foreignKeyPropertyName, function(val){
+ obj.__defineSetter__(foreignKeyPropertyName, function (val) {
obj['_' + foreignKeyPropertyName] = val;
obj['_' + associationName] = null;
});
- obj.__defineGetter__(associationName, function() {
+ obj.__defineGetter__(associationName, function () {
// value was set on the object so treat it as a normal property
- if(obj['_' + associationName]) {
+ if (obj['_' + associationName]) {
return obj['_' + associationName];
}
// object didn't come from the database so we can't fetch the query.
- if(!doesObjectHaveAConnection(obj)) {
+ if (!doesObjectHaveAConnection(obj)) {
return null;
}
@@ -135,297 +95,341 @@ function addHasOneAssociationMethod(obj, associationName, association) {
var result = query.where(idColumn + " = ?", foreignKey);
return result;
});
- obj.__defineSetter__(associationName, function(val) {
+ obj.__defineSetter__(associationName, function (val) {
obj['_' + foreignKeyPropertyName] = null;
obj['_' + associationName] = val;
});
}
function addAssociationMethod(obj, associationName, association) {
- switch(association.type) {
- case "hasMany":
- addHasManyAssociationMethod(obj, associationName, association);
- break;
- case "hasOne":
- addHasOneAssociationMethod(obj, associationName, association);
- break;
- default:
- throw new Error("Invalid association type '" + association.type + "'");
+ switch (association.type) {
+ case "hasMany":
+ addHasManyAssociationMethod(obj, associationName, association);
+ break;
+ case "hasOne":
+ addHasOneAssociationMethod(obj, associationName, association);
+ break;
+ default:
+ throw new Error("Invalid association type '" + association.type + "'");
}
}
function addAssociationMethods(obj) {
- for(var associationName in obj._getModel().associations) {
+ var associationName;
+ for (associationName in obj._getModel().associations) {
var association = obj._getModel().associations[associationName];
addAssociationMethod(obj, associationName, association);
}
}
-function copyValuesIntoObject(values, obj) {
- for(var valKey in values) {
- var setter = obj.__lookupSetter__(valKey);
- if(setter) {
- setter(values[valKey]);
- } else {
- obj[valKey] = values[valKey];
- }
- }
-}
-
function createColumnPropertiesOnObject(obj) {
- for(var columnName in obj._getModel().columns) {
+ var columnName;
+ for (columnName in obj._getModel().columns) {
var column = obj._getModel().columns[columnName];
- if(!obj[columnName]) {
- if(!column.foreignKey) {
+ if (!obj[columnName]) {
+ if (!column.foreignKey) {
obj[columnName] = column.defaultValue();
}
}
}
}
-function addColumn(propertyName, columnDef) {
- var col = this.normalizeColumnDef(propertyName, columnDef);
- this.columns[propertyName] = col;
-};
-
-function getIdPropertyName() {
- for(var name in this.columns) {
- if(this.columns[name].primaryKey) {
- return name;
- }
- }
- return null;
+function ensurePrimaryKeyColumn(model) {
+ // todo: only add if they haven't defined one yet
+ model.addColumn("id", { type: "integer", primaryKey: true, autoIncrement: true });
}
-function getIdColumn() {
- for(var name in this.columns) {
- if(this.columns[name].primaryKey) {
- return this.columns[name];
- }
+function addColumns(model, columnDefs) {
+ var propertyName;
+ for (propertyName in columnDefs) {
+ model.addColumn(propertyName, columnDefs[propertyName]);
}
- return null;
+ ensurePrimaryKeyColumn(model);
}
-function getId() {
- return this[this._getModel().getIdPropertyName()];
-}
+exports.define = function (name, columnDefs) {
+ var Model = function (values) {
+ this._getModel = function () { return Model; }; // hide from JSON.stringify
-function normalizeHasManyOptions(associatedModel, opts) {
- var foreignKey = inflection.foreignKey(this.modelName);
- opts = opts || {};
- opts.type = "hasMany";
- opts.model = associatedModel;
- opts.foreignKey = opts.foreignKey || foreignKey;
- return opts;
-}
+ this.save = function (connection, callback) {
+ if (!connection) {
+ throw new Error("connection is null or undefined");
+ }
+ if (!connection.update) {
+ throw new Error("argument 1 to save does not appear to be a connection");
+ }
-function hasMany(associatedModel, opts) {
- opts = this.normalizeHasManyOptions(associatedModel, opts);
- var name = inflection.camelize(inflection.pluralize(associatedModel.modelName), true);
- if(this.associations[name]) {
- return this;
- }
- this.associations[name] = opts;
+ if (this._isPersisted()) {
+ connection.update(this, callback);
+ } else {
+ connection.save(this, callback);
+ }
+ };
+ this.save = persistUtil.bind('save', this.save, this);
- if(opts.through) {
- opts.manyToManyForeignKey = opts.manyToManyForeignKey || inflection.foreignKey(associatedModel.modelName);
- var associatedOpts = persistUtil.shallowCopy(opts);
- delete associatedOpts.manyToManyForeignKey;
- delete associatedOpts.foreignKey;
- associatedModel.hasMany(this, associatedOpts);
- } else {
- associatedModel.hasOne(this);
- }
+ this.update = function (connection, props, callback) {
+ copyValuesIntoObject(props, this);
+ this.save(connection, callback);
+ };
+ this.update = persistUtil.bind('update', this.update, this);
+
+ this.delete = function (connection, callback) {
+ var self = this;
+ this._getModel().emit("beforeDelete", this);
+ var query = new Query(connection, this._getModel());
+ query.where("id = ?", this[this._getModel().getIdPropertyName()]);
+ query.deleteAll(function () {
+ self._getModel().emit("afterDelete", self);
+ callback.apply(self, arguments);
+ });
+ };
+ this.delete = persistUtil.bind('delete', this.delete, this);
- return this;
-};
+ this.getId = function () {
+ return this[this._getModel().getIdPropertyName()];
+ };
+ this.getId = persistUtil.bind('getId', this.getId, this);
-function normalizeHasOneOptions(associatedModel, opts) {
- var foreignKey = inflection.foreignKey(associatedModel.modelName);
- opts = opts || {};
- opts.type = "hasOne";
- opts.model = associatedModel;
- opts.foreignKey = opts.foreignKey || foreignKey;
- return opts;
-}
+ this._isPersisted = function () { return false; };
+
+ addAssociationMethods(this);
+ if (values) {
+ copyValuesIntoObject(values, this);
+ }
+ createColumnPropertiesOnObject(this);
-function hasOne(associatedModel, opts) {
- opts = this.normalizeHasOneOptions(associatedModel, opts);
- var name = inflection.camelize(associatedModel.modelName, true);
- if(this.associations[name]) {
return this;
- }
- this.associations[name] = opts;
+ };
- var foreignKeyPropertyName = inflection.camelize(opts.foreignKey, true);
- this.addColumn(foreignKeyPropertyName, { type: "int", foreignKey: true });
+ Model.modelName = name;
+ Model.tableName = inflection.pluralize(name);
+ Model.associations = {};
+ Model.columns = {};
- var associatedOpts = persistUtil.shallowCopy(opts);
- delete associatedOpts.foreignKey;
- associatedModel.hasMany(this, associatedOpts);
+ Model.eventEmmiter = new events.EventEmitter();
+ var n;
+ for (n in events.EventEmitter.prototype) {
+ Model[n] = events.EventEmitter.prototype[n];
+ /*
+ Model[n] = function() {
+ Model.eventEmmiter.apply(Model.eventEmmiter, arguments);
+ }*/
+ }
- return this;
-};
+ Model.normalizeColumnDef = function (propertyName, columnDef) {
+ if (!columnDef) {
+ throw new Error(util.format('Invalid column definition for property "%s" of model "%s"', propertyName, this.modelName));
+ }
+ if (typeof (columnDef) === "string") {
+ columnDef = {
+ type: normalizeType(columnDef)
+ };
+ }
-function using(connection) {
- return new Query(connection, this);
-};
+ if (!columnDef.defaultValue) {
+ columnDef.defaultValue = function () { return null; };
+ } else {
+ if (typeof (columnDef.defaultValue) !== "function") {
+ var val = columnDef.defaultValue;
+ columnDef.defaultValue = function () { return val; };
+ }
+ }
-function ensurePrimaryKeyColumn(model) {
- // todo: only add if they haven't defined one yet
- model.addColumn("id", { type: "integer", primaryKey: true, autoIncrement: true });
-}
+ if (!columnDef.dbColumnName) {
+ columnDef.dbColumnName = inflection.underscore(propertyName);
+ }
-function addColumns(model, columnDefs) {
- for(var propertyName in columnDefs) {
- model.addColumn(propertyName, columnDefs[propertyName]);
- }
- ensurePrimaryKeyColumn(model);
-}
+ return columnDef;
+ };
-function count(connection, callback) {
- return this.using(connection).count(callback);
-}
+ Model.addColumn = function (propertyName, columnDef) {
+ var col = this.normalizeColumnDef(propertyName, columnDef);
+ this.columns[propertyName] = col;
+ };
-function orderBy() {
- var query = this.using(null);
- return query.orderBy.apply(query, arguments);
-}
+ Model.getIdColumn = function () {
+ var name;
+ for (name in this.columns) {
+ if (this.columns[name].primaryKey) {
+ return this.columns[name];
+ }
+ }
+ return null;
+ };
-function where() {
- var query = this.using(null);
- return query.where.apply(query, arguments);
-}
+ Model.getIdPropertyName = function () {
+ var name;
+ for (name in this.columns) {
+ if (this.columns[name].primaryKey) {
+ return name;
+ }
+ }
+ return null;
+ };
-function include() {
- var query = this.using(null);
- return query.include.apply(query, arguments);
-}
+ Model.normalizeHasManyOptions = function (associatedModel, opts) {
+ var foreignKey = inflection.foreignKey(this.modelName);
+ opts = opts || {};
+ opts.type = "hasMany";
+ opts.model = associatedModel;
+ opts.foreignKey = opts.foreignKey || foreignKey;
+ return opts;
+ };
-function all(connection, callback) {
- var query = this.using(connection);
- return query.all.apply(query, arguments);
-}
+ Model.hasMany = function (associatedModel, opts) {
+ opts = this.normalizeHasManyOptions(associatedModel, opts);
+ var name = inflection.camelize(inflection.pluralize(associatedModel.modelName), true);
+ if (this.associations[name]) {
+ return this;
+ }
+ this.associations[name] = opts;
+
+ if (opts.through) {
+ opts.manyToManyForeignKey = opts.manyToManyForeignKey || inflection.foreignKey(associatedModel.modelName);
+ var associatedOpts = persistUtil.shallowCopy(opts);
+ delete associatedOpts.manyToManyForeignKey;
+ delete associatedOpts.foreignKey;
+ associatedModel.hasMany(this, associatedOpts);
+ } else {
+ associatedModel.hasOne(this);
+ }
-function first(connection, callback) {
- var query = this.using(connection);
- return query.first.apply(query, arguments);
-}
+ return this;
+ };
-// connection, id, callback
-// id (chaining)
-function getById() {
- var self = this;
- if(arguments.length == 1) {
- var id = arguments[0];
- return function(connection, callback) {
- var query = self.using(connection);
- return query.getById(id, callback);
+ Model.normalizeHasOneOptions = function (associatedModel, opts) {
+ var foreignKey = inflection.foreignKey(associatedModel.modelName);
+ opts = opts || {};
+ opts.type = "hasOne";
+ opts.model = associatedModel;
+ opts.foreignKey = opts.foreignKey || foreignKey;
+ return opts;
+ };
+
+ Model.hasOne = function (associatedModel, opts) {
+ opts = this.normalizeHasOneOptions(associatedModel, opts);
+ var name = inflection.camelize(associatedModel.modelName, true);
+ if (this.associations[name]) {
+ return this;
}
- } else {
- var connection = arguments[0];
- var id = arguments[1];
- var callback = arguments[2];
- var query = self.using(connection);
- return query.getById(id, callback);
- }
-}
+ this.associations[name] = opts;
-function deleteAll(connection, callback) {
- var query = this.using(connection);
- return query.deleteAll.apply(query, arguments);
-}
+ var foreignKeyPropertyName = inflection.camelize(opts.foreignKey, true);
+ this.addColumn(foreignKeyPropertyName, { type: "int", foreignKey: true });
-function min(fieldName) {
- var query = this.using(null);
- return query.min.apply(query, arguments);
-}
+ var associatedOpts = persistUtil.shallowCopy(opts);
+ delete associatedOpts.foreignKey;
+ associatedModel.hasMany(this, associatedOpts);
-function max(fieldName) {
- var query = this.using(null);
- return query.max.apply(query, arguments);
-}
+ return this;
+ };
+
+ Model.using = function (connection) {
+ return new Query(connection, this);
+ };
+
+ // connection, id, data, callback
+ // id, data (chaining)
+ Model.update = function () {
+ var id;
+ var data;
+
+ // chaining
+ if (arguments.length === 2) {
+ id = arguments[0];
+ data = arguments[1];
+ var self = this;
+ return persistUtil.bind('update', function (conn, callback) {
+ self.update(conn, id, data, callback);
+ }, this);
+ }
-// connection, id, data, callback
-// id, data (chaining)
-function update() {
- // chaining
- if(arguments.length == 2) {
- var id = arguments[0];
- var data = arguments[1];
+ // non-chaining
+ var connection = arguments[0];
+ id = arguments[1];
+ data = arguments[2];
+ var callback = arguments[3];
+ if (!connection) { throw new Error("connection is null or undefined"); }
+ if (!connection.update) { throw new Error("argument 1 to save does not appear to be a connection"); }
+
+ connection.updatePartial(this, id, data, callback);
+ return null;
+ };
+
+ // connection, id, callback
+ // id (chaining)
+ Model.getById = function () {
var self = this;
- return persistUtil.bind('update', function(conn, callback) {
- self.update(conn, id, data, callback);
- }, this);
- }
+ var id;
+ if (arguments.length === 1) {
+ id = arguments[0];
+ return function (connection, callback) {
+ var query = self.using(connection);
+ return query.getById(id, callback);
+ };
+ } else {
+ var connection = arguments[0];
+ id = arguments[1];
+ var callback = arguments[2];
+ var query = self.using(connection);
+ return query.getById(id, callback);
+ }
+ };
- // non-chaining
- var connection = arguments[0];
- var id = arguments[1];
- var data = arguments[2];
- var callback = arguments[3];
- if(!connection) throw new Error("connection is null or undefined");
- if(!connection.update) throw new Error("argument 1 to save does not appear to be a connection");
+ Model.count = function (connection, callback) {
+ return this.using(connection).count(callback);
+ };
+ Model.count = persistUtil.bind('count', Model.count, Model);
- connection.updatePartial(this, id, data, callback);
- return null;
-}
+ Model.orderBy = function () {
+ var query = this.using(null);
+ return query.orderBy.apply(query, arguments);
+ };
+ Model.orderBy = persistUtil.bind('orderBy', Model.orderBy, Model);
-exports.define = function(name, columnDefs) {
- var Model = function(values) {
- this._getModel = function() { return Model; } // hide from JSON.stringify
- this.save = persistUtil.bind('save', saveInstance, this);
- this.update = persistUtil.bind('update', updateInstance, this);
- this.delete = persistUtil.bind('delete', deleteInstance, this);
- this.getId = persistUtil.bind('getId', getId, this);
- this._isPersisted = function() { return false; }
+ Model.where = function () {
+ var query = this.using(null);
+ return query.where.apply(query, arguments);
+ };
+ Model.where = persistUtil.bind('where', Model.where, Model);
- addAssociationMethods(this);
- if(values) {
- copyValuesIntoObject(values, this);
- }
- createColumnPropertiesOnObject(this);
+ Model.include = function () {
+ var query = this.using(null);
+ return query.include.apply(query, arguments);
+ };
+ Model.include = persistUtil.bind('include', Model.include, Model);
- return this;
+ Model.all = function (connection, callback) {
+ var query = this.using(connection);
+ return query.all.apply(query, arguments);
};
+ Model.all = persistUtil.bind('all', Model.all, Model);
- Model.modelName = name;
- Model.tableName = inflection.pluralize(name);
- Model.associations = {};
- Model.columns = {};
+ Model.first = function (connection, callback) {
+ var query = this.using(connection);
+ return query.first.apply(query, arguments);
+ };
+ Model.first = persistUtil.bind('first', Model.first, Model);
- Model.eventEmmiter = new events.EventEmitter();
- for(var n in events.EventEmitter.prototype) {
- Model[n] = events.EventEmitter.prototype[n];
- /*
- Model[n] = function() {
- Model.eventEmmiter.apply(Model.eventEmmiter, arguments);
- }*/
- }
+ Model.deleteAll = function (connection, callback) {
+ var query = this.using(connection);
+ return query.deleteAll.apply(query, arguments);
+ };
+ Model.deleteAll = persistUtil.bind('deleteAll', Model.deleteAll, Model);
- Model.normalizeColumnDef = normalizeColumnDef;
- Model.addColumn = addColumn;
- Model.getIdColumn = getIdColumn;
- Model.getIdPropertyName = getIdPropertyName;
- Model.normalizeHasManyOptions = normalizeHasManyOptions;
- Model.hasMany = hasMany;
- Model.normalizeHasOneOptions = normalizeHasOneOptions;
- Model.hasOne = hasOne;
- Model.using = using;
- Model.update = update;
- Model.getById = getById;
-
- Model.include = persistUtil.bind('include', include, Model);
- Model.count = persistUtil.bind('count', count, Model);
- Model.where = persistUtil.bind('where', where, Model);
- Model.orderBy = persistUtil.bind('orderBy', orderBy, Model);
- Model.all = persistUtil.bind('all', all, Model);
- Model.first = persistUtil.bind('first', first, Model);
- Model.deleteAll = persistUtil.bind('deleteAll', deleteAll, Model);
- Model.min = persistUtil.bind('min', min, Model);
- Model.max = persistUtil.bind('max', max, Model);
+ Model.min = function (fieldName) {
+ var query = this.using(null);
+ return query.min.apply(query, arguments);
+ };
+ Model.min = persistUtil.bind('min', Model.min, Model);
+
+ Model.max = function (fieldName) {
+ var query = this.using(null);
+ return query.max.apply(query, arguments);
+ };
+ Model.max = persistUtil.bind('max', Model.max, Model);
addColumns(Model, columnDefs);
return Model;
-}
+};
View
40 lib/persist.js
@@ -1,3 +1,4 @@
+'use strict';
var util = require('util');
var fs = require('fs');
@@ -12,15 +13,24 @@ exports.Descending = "desc";
var defaultConnectOptions = null;
-exports.define = function(name, columnDefs) {
+exports.define = function (name, columnDefs) {
return Model.define(name, columnDefs);
-}
+};
+
+var setDefaultConnectOptions = exports.setDefaultConnectOptions = function (options) {
+ defaultConnectOptions = options;
+};
+
+var getDefaultConnectOptions = exports.getDefaultConnectOptions = function () {
+ return defaultConnectOptions;
+};
// opts, callback
// callback - use database.json for connection information
-exports.connect = function() {
+exports.connect = function () {
var callback = arguments[arguments.length - 1];
- if(arguments.length == 1) {
+ var opts;
+ if (arguments.length === 1) {
opts = getDefaultConnectOptions();
} else {
opts = arguments[0];
@@ -30,30 +40,22 @@ exports.connect = function() {
var Driver = require('./drivers/' + driverName + '.js');
var driver = new Driver();
driver.connect(opts, callback);
-}
-
-setDefaultConnectOptions = exports.setDefaultConnectOptions = function(options) {
- defaultConnectOptions = options;
-}
-
-getDefaultConnectOptions = exports.getDefaultConnectOptions = function() {
- return defaultConnectOptions;
-}
+};
-loadDatabaseJson = exports.loadDatabaseJson = function(path) {
+var loadDatabaseJson = exports.loadDatabaseJson = function (path) {
var databaseJson = JSON.parse(fs.readFileSync(path).toString());
setDefaultConnectOptions(databaseJson[databaseJson['default']]);
-}
+};
-tryLoadDatabaseJson = exports.tryLoadDatabaseJson = function(path) {
+var tryLoadDatabaseJson = exports.tryLoadDatabaseJson = function (path) {
try {
var stats = fs.statSync(path);
- if(stats) {
+ if (stats) {
loadDatabaseJson(path);
}
- } catch(e) {
+ } catch (e) {
// fail silently this is only a tryLoad.
}
-}
+};
tryLoadDatabaseJson(path.join(process.cwd(), "database.json"));
View
104 lib/persist_utils.js
@@ -1,118 +1,60 @@
+'use strict';
-exports.bind = function(name, func, scope) {
+exports.bind = function (name, func, scope) {
var _function = func;
- var results = function() {
+ var results = function () {
return _function.apply(scope, arguments);
- }
+ };
results._name = name;
return results;
-}
+};