n1-sql
Version:
95 lines (84 loc) • 2.34 kB
JavaScript
;
var Immutable = require('immutable');
var parseColumn = require('./util').parseColumn;
var toSqlColumn = require('./util').toSqlColumn;
module.exports.callJoinBuilder = function (f, state) {
var sql;
if (typeof f === "function") {
var jc = createInitialCtxt(state);
var jb = f(joinBuilder(jc));
if (!jb) {
throw '"join" needs to return a join function';
}
sql = jb._toSql();
} else if (typeof f === 'string') {
sql = f;
} else {
throw 'Unknown join definition "' + f + '".';
}
return state.updateIn(['join'], function (l) {
return l.push(sql);
});
};
function createInitialCtxt(state) {
return Immutable.Map({
cols: Immutable.List(),
joinOps: Immutable.List(),
state: state
});
}
function joinBuilder(ctxt) {
//"orgA.t" dp1 JOIN "orgB.t" dp2 ON dp1.id = dp2.id
function toSql() {
var cols = ctxt.get('cols').toJS();
if (cols.length < 2) {
throw 'Join needs at least two columns, but found only ' + cols.length + '.';
}
var joinOps = ctxt.get('joinOps').toJS();
if (cols.length !== joinOps.length + 1) {
throw 'Unexpected number of join tables and associated join operations';
}
var ra = [toSqlTable(cols[0])];
var i;
for (i = 1; i < cols.length; i++) {
ra.push('JOIN');
ra.push(toSqlTable(cols[i]));
ra.push('ON');
ra.push(toSqlJoinOp(joinOps[i - 1], cols[i - 1], cols[i]));
}
return ra.join(' ');
}
function toSqlTable(t) {
var s = t.table;
if (t.tableAlias) {
s += ' ' + t.tableAlias;
}
return s;
}
function toSqlJoinOp(joinOp, left, right) {
return [toSqlColumn(left), ' ', joinOp, ' ', toSqlColumn(right)].join('');
}
function joinOp(op) {
return function () {
var c = ctxt.updateIn(['joinOps'], function (l) {
return l.push(op);
});
return joinBuilder(c);
};
}
return {
column: function column(colId) {
var c = ctxt.updateIn(['cols'], function (l) {
var ch = parseColumn(colId, ctxt.get('state'));
var js = ctxt.get('joinOps').size;
if (js !== l.size) {
throw 'Column needs to be first or follow a join operator';
}
return l.push(ch);
});
return joinBuilder(c);
},
eq: joinOp('='),
_toSql: toSql
};
}