index.js
[ hits: 201, misses: 15, sloc: 216, coverage: 93.06% ] [+]
- (function() {
- var Query, Select, copy, dialects, fluid, normalize, passthrough_resolver, sys, unknown;
- var __bind = function(fn, me){ return function(){ return fn.apply(me, arguments); }; }, __hasProp = Object.prototype.hasOwnProperty, __extends = function(child, parent) {
- for (var key in parent) { if (__hasProp.call(parent, key)) child[key] = parent[key]; }
- function ctor() { this.constructor = child; }
- ctor.prototype = parent.prototype;
- child.prototype = new ctor;
- child.__super__ = parent.prototype;
- return child;
- }, __slice = Array.prototype.slice;
- fluid = require('./fluid');
- sys = require('sys');
- unknown = function(type, val) {
- throw new Error("Unknown " + type + ": " + val);
- };
- copy = function(thing) {
- var c, k, obj, v;
- if (thing.constructor === Array) {
- c = [];
- c.push.apply(c, thing);
- return c;
- } else if ('object' === typeof thing) {
- obj = {};
- for (k in thing) {
- v = thing[k];
- obj[k] = copy(v);
- }
- return obj;
- } else {
- return thing;
- }
- };
- dialects = exports.dialects = {
- "default": 'mysql',
- mysql: require('./mysql')
- };
- passthrough_resolver = {
- table: function(n) {
- return n;
- },
- field: function(n) {
- return n;
- }
- };
- exports.Query = Query = (function() {
- function Query(opts) {
- this.dialect = opts.dialect || dialects["default"];
- this.resolve = opts.resolver || passthrough_resolver;
- if ('string' === typeof this.dialect) {
- this.dialect = dialects[this.dialect];
- }
- this.s = {
- includedAliases: {},
- fields: {},
- tableStack: [],
- where: [],
- order: [],
- groupings: [],
- parameters: [],
- raw_where: []
- };
- }
- Query.prototype.clone = function() {
- var child, firstTable;
- firstTable = this.s.tableStack[0][0];
- child = new this.constructor(firstTable);
- child.dialect = this.dialect;
- child.resolve = this.resolve;
- child.s = copy(this.s);
- return child;
- };
- Query.prototype.aliasPair = function(table) {
- var a, t;
- if ('object' === typeof table && Object.keys(table).length === 1) {
- return ((function() {
- var _results;
- _results = [];
- for (a in table) {
- t = table[a];
- _results.push([t, a]);
- }
- return _results;
- })())[0];
- } else {
- return [table, table];
- }
- };
- Query.prototype.pushTable = function(table, alias, type, clause) {
- var _base, _ref;
- if (table === "t1t1") {
- throw new Error("here");
- }
- if (type !== 'NOP') {
- this.s.includedAliases[alias] = table;
- if ((_ref = (_base = this.s.fields)[alias]) == null) {
- _base[alias] = [];
- }
- }
- return this.s.tableStack.push([table, alias, type, clause]);
- };
- Query.prototype.lastTable = function() {
- return this.s.tableStack[this.s.tableStack.length - 1][1];
- };
- Query.prototype.includesAlias = function(a) {
- return this.s.includedAliases[a];
- };
- Query.prototype.pushParams = function(clauses) {
- var clause, _i, _len, _ref, _results;
- _results = [];
- for (_i = 0, _len = clauses.length; _i < _len; _i++) {
- clause = clauses[_i];
- _results.push(clause.op === 'multi' ? (sys.puts("pushParam recursing" + clause.clauses), this.pushParams(clause.clauses)) : clause.op === 'IN' ? (_ref = this.s.parameters).push.apply(_ref, clause.value) : this.s.parameters.push(clause.value));
- }
- return _results;
- };
- Query.prototype.visit = fluid(function(fn) {
- if (fn != null) {
- return fn.call(this, this);
- }
- });
- Query.prototype.toSql = function() {
- return this.dialect["render" + this.s.queryType](this.s);
- };
- Query.prototype.toString = function() {
- return "[Query \"" + (this.toSql().substring(0, 20)) + "\"]";
- };
- Query.prototype.execute = function(conn, cb) {
- if (conn['acquire'] != null) {
- return conn.acquire(__bind(function(c) {
- return this.execute(c, cb);
- }, this));
- } else {
- return conn.query(this.toSql(), this.s.parameters, cb);
- }
- };
- return Query;
- })();
- exports.Select = Select = (function() {
- __extends(Select, Query);
- function Select(table, opts) {
- var alias, _ref;
- if (opts == null) {
- opts = {};
- }
- Select.__super__.constructor.call(this, opts);
- this.s.queryType = 'Select';
- _ref = this.aliasPair(table), table = _ref[0], alias = _ref[1];
- this.pushTable(table, alias);
- }
- Select.prototype.from = fluid(function(alias) {
- var table;
- if (table = this.includesAlias(alias)) {
- return this.pushTable(table, alias, 'NOP');
- } else {
- return unknown('table', table);
- }
- });
- Select.prototype.fields = fluid(function() {
- var alias, f, fields, _i, _len, _results;
- fields = 1 <= arguments.length ? __slice.call(arguments, 0) : [];
- alias = this.lastTable();
- _results = [];
- for (_i = 0, _len = fields.length; _i < _len; _i++) {
- f = fields[_i];
- _results.push(this.s.fields[alias].push(f));
- }
- return _results;
- });
- Select.prototype.field = Select.fields;
- Select.prototype.join = fluid(function(tbl, opts) {
- var alias, clause, table, type, _ref;
- if (opts == null) {
- opts = {};
- }
- _ref = this.aliasPair(tbl), table = _ref[0], alias = _ref[1];
- if (this.includesAlias(alias)) {
- throw new Error("Table alias is not unique: " + alias);
- }
- type = this.dialect.joinType(opts.type);
- clause = opts.on;
- if (clause != null) {
- if (clause.constructor !== Array) {
- clause = [clause];
- }
- clause = normalize.clauses(clause, alias, this.dialect.joinOp);
- if (clause.length > 1) {
- clause = {
- op: 'multi',
- glue: ' AND ',
- clauses: clause
- };
- } else {
- clause = clause[0];
- }
- }
- return this.pushTable(table, alias, type, clause);
- });
- Select.prototype.where = fluid(function(tbl, clause) {
- var normalized, _ref;
- if (!(clause != null)) {
- clause = tbl;
- tbl = this.lastTable();
- }
- if (this.includesAlias(tbl) == null) {
- unknown('table', tbl);
- }
- normalized = normalize.clauses([clause], tbl, this.dialect.whereOp);
- (_ref = this.s.where).push.apply(_ref, normalized);
- return this.pushParams(normalized);
- });
- Select.prototype.or = fluid(function() {
- var args, clauses;
- args = 1 <= arguments.length ? __slice.call(arguments, 0) : [];
- clauses = normalize.clauses(args, this.lastTable(), this.dialect.whereOp);
- this.s.where.push({
- op: 'multi',
- glue: ' OR ',
- clauses: clauses
- });
- return this.pushParams(clauses);
- });
- Select.prototype.orderBy = fluid(function() {
- var args, orderings, _ref;
- args = 1 <= arguments.length ? __slice.call(arguments, 0) : [];
- orderings = normalize.orderings(args, this.lastTable(), this.dialect.order);
- return (_ref = this.s.order).push.apply(_ref, orderings);
- });
- Select.prototype.groupBy = function() {
- var field, fields, groupings, _ref;
- fields = 1 <= arguments.length ? __slice.call(arguments, 0) : [];
- groupings = (function() {
- var _i, _len, _results;
- _results = [];
- for (_i = 0, _len = fields.length; _i < _len; _i++) {
- field = fields[_i];
- _results.push(normalize.fieldAndTable({
- table: this.lastTable(),
- field: field
- }));
- }
- return _results;
- }).call(this);
- return (_ref = this.s.groupings).push.apply(_ref, groupings);
- };
- Select.prototype.limit = fluid(function(l) {
- return this.s.limit = l;
- });
- return Select;
- })();
- exports.normalize = normalize = {
- clauses: function(clauses, table, normalizeOp) {
- var clause, constraint, fld, normalized, op, val, _i, _len;
- normalized = [];
- for (_i = 0, _len = clauses.length; _i < _len; _i++) {
- clause = clauses[_i];
- for (fld in clause) {
- constraint = clause[fld];
- if ('object' === typeof constraint) {
- for (op in constraint) {
- val = constraint[op];
- op = normalizeOp(op);
- normalized.push(normalize.fieldAndTable({
- field: fld,
- op: op,
- value: val,
- table: table
- }));
- }
- } else {
- normalized.push(normalize.fieldAndTable({
- field: fld,
- op: '=',
- value: constraint,
- table: table
- }));
- }
- }
- }
- return normalized;
- },
- orderings: function(orderings, table) {
- var add, direction, field, normalized, ordering, _i, _len, _ref;
- normalized = [];
- add = function(field, direction) {
- direction = (function() {
- switch ((direction || '').toLowerCase()) {
- case 'asc':
- case 'ascending':
- return 'ASC';
- case 'desc':
- case 'descending':
- return 'DESC';
- case '':
- return '';
- default:
- throw new Error("Unsupported ordering direction " + direction);
- }
- })();
- return normalized.push(normalize.fieldAndTable({
- field: field,
- table: table,
- direction: direction
- }));
- };
- for (_i = 0, _len = orderings.length; _i < _len; _i++) {
- ordering = orderings[_i];
- if ('string' === typeof ordering) {
- _ref = ordering.split(/\ +/), field = _ref[0], direction = _ref[1];
- add(field, direction);
- } else {
- for (field in ordering) {
- direction = ordering[field];
- add(field, direction);
- }
- }
- }
- return normalized;
- },
- fieldAndTable: function(normalized) {
- var field, table, _ref;
- _ref = normalized.field.split('.'), table = _ref[0], field = _ref[1];
- if (field != null) {
- normalized.table = table;
- normalized.field = field;
- }
- return normalized;
- }
- };
- exports.from = function(tbl, fields, opts) {
- var select;
- if (tbl.constructor === Select) {
- throw new Error("Inner queries not supported yet");
- }
- if (!(opts != null) && (fields != null) && fields.constructor !== Array) {
- opts = fields;
- fields = null;
- }
- select = new Select(tbl, opts);
- if (fields != null) {
- select.fields.apply(select, fields);
- }
- return select;
- };
- }).call(this);
fluid.js
[ hits: 4, misses: 0, sloc: 4, coverage: 100.00% ] [+]
- module.exports = function (fn) {
- return function() {
- fn.apply(this, arguments)
- return this
- }
- }
mysql.js
[ hits: 95, misses: 11, sloc: 106, coverage: 89.62% ] [+]
- (function() {
- var AND, BOUND_PARAM, DEFAULT_JOIN, JOIN_TYPES, LITERAL, OR, QUOTED, fieldList, group, joins, limit, order, renderBoundParam, renderClause, sys, where;
- var __indexOf = Array.prototype.indexOf || function(item) {
- for (var i = 0, l = this.length; i < l; i++) {
- if (this[i] === item) return i;
- }
- return -1;
- };
- sys = require('sys');
- AND = ' AND ';
- OR = ' OR ';
- JOIN_TYPES = ['INNER', 'CROSS', 'FULL OUTER', 'LEFT', 'LEFT INNER', 'LEFT OUTER', 'RIGHT', 'RIGHT INNER', 'RIGHT OUTER'];
- QUOTED = 'quoted';
- LITERAL = 'literal';
- BOUND_PARAM = '?';
- DEFAULT_JOIN = "INNER";
- exports.renderSelect = function(qs) {
- var ret;
- ret = "SELECT " + (fieldList(qs)) + " FROM ";
- ret += joins(qs);
- ret += where(qs);
- ret += group(qs);
- ret += order(qs);
- return ret += limit(qs);
- };
- fieldList = function(qs) {
- var fields, tbl, tbl_fields, _ref;
- fields = [];
- _ref = qs.fields;
- for (tbl in _ref) {
- tbl_fields = _ref[tbl];
- if (tbl_fields.length) {
- tbl_fields.forEach(function(f) {
- return fields.push("" + tbl + "." + f);
- });
- } else {
- fields.push("" + tbl + ".*");
- }
- }
- return fields.join(', ');
- };
- joins = exports.joins = function(qs) {
- var alias, clause, i, ret, table, tables, type;
- i = 0;
- tables = (function() {
- var _i, _len, _ref, _ref2, _results;
- _ref = qs.tableStack;
- _results = [];
- for (_i = 0, _len = _ref.length; _i < _len; _i++) {
- _ref2 = _ref[_i], table = _ref2[0], alias = _ref2[1], type = _ref2[2], clause = _ref2[3];
- if (type === 'NOP') {
- continue;
- }
- ret = i++ ? "" + (type.toUpperCase()) + " JOIN " + table : table;
- if (table !== alias) {
- ret += " AS " + alias;
- }
- if (clause != null) {
- ret += " ON " + (renderClause(clause, function(v) {
- return v;
- }));
- }
- _results.push(ret);
- }
- return _results;
- })();
- return tables.join(' ');
- };
- where = exports.where = function(qs) {
- if (qs.where.length) {
- return " WHERE " + (renderClause(qs.where));
- } else {
- return "";
- }
- };
- group = exports.group = function(qs) {
- if (qs.groupings.length) {
- return " GROUP BY " + (qs.groupings.map(function(g) {
- return g.table + '.' + g.field;
- }).join(', '));
- } else {
- return "";
- }
- };
- order = exports.order = function(qs) {
- if (qs.order.length) {
- return ' ORDER BY ' + qs.order.map(function(o) {
- return o.table + '.' + o.field + (o.direction ? ' ' + o.direction : '');
- }).join(', ');
- } else {
- return "";
- }
- };
- limit = function(qs) {
- if (qs.limit != null) {
- return " LIMIT " + qs.limit;
- } else {
- return "";
- }
- };
- renderBoundParam = function(v) {
- if (v && v.constructor === Array) {
- return "(" + (v.map(function() {
- return BOUND_PARAM;
- }).join(', ')) + ")";
- } else {
- return BOUND_PARAM;
- }
- };
- exports.renderClause = renderClause = function(input, renderValue) {
- var render;
- if (renderValue == null) {
- renderValue = renderBoundParam;
- }
- render = function(clause) {
- if ((clause != null) && clause.constructor === Array) {
- return "" + (clause.map(render).join(' AND '));
- } else if (typeof clause === 'object') {
- if (clause.op === 'multi') {
- return "(" + (clause.clauses.map(render).join(clause.glue)) + ")";
- } else {
- return "" + clause.table + "." + clause.field + " " + clause.op + " " + (renderValue(clause.value));
- }
- } else {
- throw new Error("Unexpected clause type, this is probably a bug");
- }
- };
- return render(input);
- };
- exports.joinOp = exports.whereOp = function(op) {
- switch (op.toLowerCase()) {
- case 'ne':
- case '!=':
- case '<>':
- return '!=';
- case 'eq':
- case '=':
- return '=';
- case 'lt':
- case '<':
- return '<';
- case 'gt':
- case '>':
- return '>';
- case 'lte':
- case '<=':
- return '<=';
- case 'gte':
- case '>=':
- return '>=';
- case 'in':
- return 'IN';
- default:
- throw new Error("Unsupported comparison operator: " + op);
- }
- };
- exports.joinType = function(type) {
- if (type == null) {
- return DEFAULT_JOIN;
- }
- type = type.toUpperCase();
- if (__indexOf.call(JOIN_TYPES, type) >= 0) {
- return type;
- }
- throw new Error("Unsupported join type: " + type);
- };
- }).call(this);