mesa
Version:
simple elegant sql for nodejs
264 lines (257 loc) • 10.7 kB
JavaScript
// Generated by CoffeeScript 1.10.0
var _, createCriterion, mohair, setManyIncludes, setOneInclude,
indexOf = [].indexOf || function(item) { for (var i = 0, l = this.length; i < l; i++) { if (i in this && this[i] === item) return i; } return -1; };
_ = require('underscore');
mohair = require('mohair');
createCriterion = function(pk, fk, records) {
var criterion;
criterion = {};
criterion[fk] = _.unique(_.pluck(records, pk));
return criterion;
};
setOneInclude = function(name, pk, fk, records, associated) {
return records.forEach(function(record) {
return record[name] = _.detect(associated, function(x) {
return record[fk] === x[pk];
});
});
};
setManyIncludes = function(name, pk, fk, records, associated) {
return records.forEach(function(record) {
return record[name] = _.filter(associated, function(x) {
return record[fk] === x[pk];
});
});
};
module.exports = {
_prepareAssociatedTable: function(table, subIncludes) {
var localTable, self;
self = this;
localTable = 'function' === typeof table ? table() : table;
if ('object' === typeof subIncludes) {
localTable = localTable.includes(subIncludes);
}
if (self.enableConnectionReuseForIncludes) {
localTable = localTable.connection(self._connection);
}
return localTable;
},
hasAssociated: function(name, associationFun) {
var associations, self;
self = this;
associations = _.extend({}, self._associations);
associations[name] = associationFun;
return self.set('_associations', associations);
},
_getIncludes: function(records, cb) {
var doneCount, fetchKeys, firstError, keysToFetch, self;
self = this;
if (self._includes == null) {
process.nextTick(function() {
return cb(null, records);
});
return;
}
keysToFetch = Object.keys(self._includes);
if (keysToFetch.length === 0) {
throw new Error('empty includes');
}
keysToFetch.forEach(function(key) {
if (!((self._associations != null) && (self._associations[key] != null))) {
throw new Error("no association: " + key);
}
});
if (self.enableParallelIncludes) {
if (typeof self.hookBeforeIncludes === "function") {
self.hookBeforeIncludes(self, keysToFetch);
}
if (keysToFetch.length === 0) {
if (typeof self.hookAfterIncludes === "function") {
self.hookAfterIncludes(self, keysToFetch);
}
cb(null, records);
return;
}
firstError = null;
doneCount = 0;
return keysToFetch.forEach(function(key) {
if (typeof self.hookBeforeInclude === "function") {
self.hookBeforeInclude(self, key);
}
return self._associations[key].call(self, self._includes[key], records, function(err) {
if (typeof self.hookAfterInclude === "function") {
self.hookAfterInclude(self, key);
}
doneCount++;
if (err != null) {
if (firstError == null) {
firstError = err;
}
}
if (doneCount === keysToFetch.length) {
if (firstError != null) {
return cb(firstError);
} else {
return cb(null, records);
}
}
});
});
} else {
fetchKeys = function(keys) {
var key, rest;
if (keys.length === 0) {
if (typeof self.hookAfterIncludes === "function") {
self.hookAfterIncludes(self, keysToFetch);
}
cb(null, records);
return;
}
key = keys[0];
rest = keys.slice(1);
if (typeof self.hookBeforeInclude === "function") {
self.hookBeforeInclude(self, key);
}
return self._associations[key].call(self, self._includes[key], records, function(err) {
if (typeof self.hookAfterInclude === "function") {
self.hookAfterInclude(self, key);
}
if (err != null) {
cb(err);
return;
}
return fetchKeys(rest);
});
};
if (typeof self.hookBeforeIncludes === "function") {
self.hookBeforeIncludes(self, keysToFetch);
}
return fetchKeys(keysToFetch);
}
},
hasOne: function(name, associatedTable, options) {
return this.hasAssociated(name, function(subIncludes, records, cb) {
var criterion, foreignKey, localAssociatedTable, primaryKey, self;
self = this;
localAssociatedTable = self._prepareAssociatedTable(associatedTable, subIncludes);
primaryKey = (options != null ? options.primaryKey : void 0) || self._primaryKey;
foreignKey = (options != null ? options.foreignKey : void 0) || (self._table + "_" + self._primaryKey);
criterion = createCriterion(primaryKey, foreignKey, records);
if (typeof self.hookBeforeHasOne === "function") {
self.hookBeforeHasOne(name, self, localAssociatedTable);
}
return localAssociatedTable.where(criterion).find(function(err, associated) {
if (typeof self.hookAfterHasOne === "function") {
self.hookAfterHasOne(name, self, localAssociatedTable, err, associated);
}
if (err != null) {
return cb(err);
}
setOneInclude(name, foreignKey, primaryKey, records, associated);
return cb(null, records);
});
});
},
hasMany: function(name, associatedTable, options) {
return this.hasAssociated(name, function(subIncludes, records, cb) {
var criterion, foreignKey, localAssociatedTable, primaryKey, self;
self = this;
localAssociatedTable = self._prepareAssociatedTable(associatedTable, subIncludes);
primaryKey = (options != null ? options.primaryKey : void 0) || self._primaryKey;
foreignKey = (options != null ? options.foreignKey : void 0) || (self._table + "_" + self._primaryKey);
criterion = createCriterion(primaryKey, foreignKey, records);
if (typeof self.hookBeforeHasMany === "function") {
self.hookBeforeHasMany(name, self, localAssociatedTable);
}
return localAssociatedTable.where(criterion).find(function(err, associated) {
if (typeof self.hookAfterHasMany === "function") {
self.hookAfterHasMany(name, self, localAssociatedTable, err, associated);
}
if (err != null) {
return cb(err);
}
setManyIncludes(name, foreignKey, primaryKey, records, associated);
return cb(null, records);
});
});
},
belongsTo: function(name, associatedTable, options) {
return this.hasAssociated(name, function(subIncludes, records, cb) {
var criterion, foreignKey, localAssociatedTable, primaryKey, self;
self = this;
localAssociatedTable = self._prepareAssociatedTable(associatedTable, subIncludes);
primaryKey = (options != null ? options.primaryKey : void 0) || self._primaryKey;
foreignKey = (options != null ? options.foreignKey : void 0) || (localAssociatedTable._table + "_" + localAssociatedTable._primaryKey);
criterion = createCriterion(foreignKey, primaryKey, records);
if (typeof self.hookBeforeBelongsTo === "function") {
self.hookBeforeBelongsTo(name, self, localAssociatedTable);
}
return localAssociatedTable.where(criterion).find(function(err, associated) {
if (typeof self.hookAfterBelongsTo === "function") {
self.hookAfterBelongsTo(name, self, localAssociatedTable, err, associated);
}
if (err != null) {
return cb(err);
}
setOneInclude(name, primaryKey, foreignKey, records, associated);
return cb(null, records);
});
});
},
hasManyThrough: function(name, associatedTable, joinTable, options) {
return this.hasAssociated(name, function(subIncludes, records, cb) {
var foreignKey, intersectionCriterion, localAssociatedTable, localJoinTable, otherForeignKey, otherPrimaryKey, primaryKey, self;
self = this;
localAssociatedTable = self._prepareAssociatedTable(associatedTable, subIncludes);
primaryKey = (options != null ? options.primaryKey : void 0) || self._primaryKey;
foreignKey = (options != null ? options.foreignKey : void 0) || (self._table + "_" + self._primaryKey);
otherPrimaryKey = (options != null ? options.otherPrimaryKey : void 0) || localAssociatedTable._primaryKey;
otherForeignKey = (options != null ? options.otherForeignKey : void 0) || (localAssociatedTable._table + "_" + localAssociatedTable._primaryKey);
intersectionCriterion = createCriterion(primaryKey, foreignKey, records);
localJoinTable = self._prepareAssociatedTable(joinTable);
localJoinTable = localJoinTable.where(intersectionCriterion);
if (typeof self.hookBeforeHasManyThroughJoinTable === "function") {
self.hookBeforeHasManyThroughJoinTable(name, self, localAssociatedTable, localJoinTable);
}
return localJoinTable.find(function(err, intersection) {
var criterion;
if (typeof self.hookAfterHasManyThroughJoinTable === "function") {
self.hookAfterHasManyThroughJoinTable(name, self, localAssociatedTable, localJoinTable, err, results);
}
if (err != null) {
return cb(err);
}
records.forEach(function(record) {
return record[name] = [];
});
if (intersection.length === 0) {
return cb(null, records);
}
criterion = createCriterion(otherForeignKey, otherPrimaryKey, intersection);
if (typeof self.hookBeforeHasManyThrough === "function") {
self.hookBeforeHasManyThrough(name, self, localAssociatedTable, localJoinTable);
}
return localAssociatedTable.where(criterion).find(function(err, associated) {
if (typeof self.hookAfterHasManyThrough === "function") {
self.hookAfterHasManyThrough(name, self, localAssociatedTable, localJoinTable, err, associated);
}
if (err != null) {
return cb(err);
}
records.forEach(function(record) {
var otherPrimaryKeys, relevantIntersection;
relevantIntersection = _.filter(intersection, function(x) {
return x[foreignKey] === record[primaryKey];
});
otherPrimaryKeys = _.pluck(relevantIntersection, otherForeignKey);
return record[name] = associated.filter(function(x) {
var ref;
return ref = x[otherPrimaryKey], indexOf.call(otherPrimaryKeys, ref) >= 0;
});
});
return cb(null, records);
});
});
});
}
};