UNPKG

mesa

Version:

simple elegant sql for nodejs

264 lines (257 loc) 10.7 kB
// 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); }); }); }); } };