Skip to content
This repository
Browse code

Refactored query builders to use 'building blocks'.

Added AMD compatiblity.

Todo: Refactor and update tests.
  • Loading branch information...
commit 77be0461b339c1edd341c637eab1c6be2740a25c 1 parent baa7855
Ramesh Nair authored
648 docs/squel.html
379 additions, 269 deletions not shown
1,111 squel.js
@@ -27,11 +27,13 @@ OTHER DEALINGS IN THE SOFTWARE.
27 27
28 28
29 29 (function() {
30   - var Cloneable, DefaultQueryBuilderOptions, Delete, Expression, Insert, JoinWhereOrderLimit, QueryBuilder, Select, Update, WhereOrderLimit, _export, _extend,
  30 + var DistinctBlock, cls, squel, _extend,
31 31 __slice = [].slice,
32 32 __hasProp = {}.hasOwnProperty,
33   - __bind = function(fn, me){ return function(){ return fn.apply(me, arguments); }; },
34   - __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; };
  33 + __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; },
  34 + __bind = function(fn, me){ return function(){ return fn.apply(me, arguments); }; };
  35 +
  36 + cls = {};
35 37
36 38 _extend = function() {
37 39 var dst, k, sources, src, v, _i, _len;
@@ -51,7 +53,14 @@ OTHER DEALINGS IN THE SOFTWARE.
51 53 return dst;
52 54 };
53 55
54   - Cloneable = (function() {
  56 + cls.DefaultQueryBuilderOptions = {
  57 + autoQuoteTableNames: false,
  58 + autoQuoteFieldNames: false,
  59 + nameQuoteCharacter: '`',
  60 + usingValuePlaceholders: false
  61 + };
  62 +
  63 + cls.Cloneable = (function() {
55 64
56 65 function Cloneable() {}
57 66
@@ -65,7 +74,104 @@ OTHER DEALINGS IN THE SOFTWARE.
65 74
66 75 })();
67 76
68   - Expression = (function() {
  77 + cls.BaseBuilder = (function(_super) {
  78 +
  79 + __extends(BaseBuilder, _super);
  80 +
  81 + function BaseBuilder(options) {
  82 + this.options = _extend({}, cls.DefaultQueryBuilderOptions, options);
  83 + }
  84 +
  85 + BaseBuilder.prototype._getObjectClassName = function(obj) {
  86 + var arr;
  87 + if (obj && obj.constructor && obj.constructor.toString) {
  88 + arr = obj.constructor.toString().match(/function\s*(\w+)/);
  89 + if (arr && arr.length === 2) {
  90 + return arr[1];
  91 + }
  92 + }
  93 + return void 0;
  94 + };
  95 +
  96 + BaseBuilder.prototype._sanitizeCondition = function(condition) {
  97 + var c, t;
  98 + t = typeof condition;
  99 + c = this._getObjectClassName(condition);
  100 + if ('cls.Expression' !== c && "string" !== t) {
  101 + throw new Error("condition must be a string or cls.Expression instance");
  102 + }
  103 + if ('cls.Expression' === t || 'cls.Expression' === c) {
  104 + condition = condition.toString();
  105 + }
  106 + return condition;
  107 + };
  108 +
  109 + BaseBuilder.prototype._sanitizeName = function(value, type) {
  110 + if ("string" !== typeof value) {
  111 + throw new Error("" + type + " must be a string");
  112 + }
  113 + return value;
  114 + };
  115 +
  116 + BaseBuilder.prototype._sanitizeField = function(item) {
  117 + var sanitized;
  118 + sanitized = this._sanitizeName(item, "field name");
  119 + if (this.options.autoQuoteFieldNames) {
  120 + return "" + this.options.nameQuoteCharacter + sanitized + this.options.nameQuoteCharacter;
  121 + } else {
  122 + return sanitized;
  123 + }
  124 + };
  125 +
  126 + BaseBuilder.prototype._sanitizeTable = function(item) {
  127 + var sanitized;
  128 + sanitized = this._sanitizeName(item, "table name");
  129 + if (this.options.autoQuoteTableNames) {
  130 + return "" + this.options.nameQuoteCharacter + sanitized + this.options.nameQuoteCharacter;
  131 + } else {
  132 + return sanitized;
  133 + }
  134 + };
  135 +
  136 + BaseBuilder.prototype._sanitizeAlias = function(item) {
  137 + return this._sanitizeName(item, "alias");
  138 + };
  139 +
  140 + BaseBuilder.prototype._sanitizeLimitOffset = function(value) {
  141 + value = parseInt(value);
  142 + if (0 > value || isNaN(value)) {
  143 + throw new Error("limit/offset must be >=0");
  144 + }
  145 + return value;
  146 + };
  147 +
  148 + BaseBuilder.prototype._sanitizeValue = function(item) {
  149 + var t;
  150 + t = typeof item;
  151 + if (null !== item && "string" !== t && "number" !== t && "boolean" !== t) {
  152 + throw new Error("field value must be a string, number, boolean or null");
  153 + }
  154 + return item;
  155 + };
  156 +
  157 + BaseBuilder.prototype._formatValue = function(value) {
  158 + if (null === value) {
  159 + value = "NULL";
  160 + } else if ("boolean" === typeof value) {
  161 + value = value ? "TRUE" : "FALSE";
  162 + } else if ("number" !== typeof value) {
  163 + if (false === this.options.usingValuePlaceholders) {
  164 + value = "'" + value + "'";
  165 + }
  166 + }
  167 + return value;
  168 + };
  169 +
  170 + return BaseBuilder;
  171 +
  172 + })(cls.Cloneable);
  173 +
  174 + cls.Expression = (function() {
69 175 var _toString;
70 176
71 177 Expression.prototype.tree = null;
@@ -177,330 +283,183 @@ OTHER DEALINGS IN THE SOFTWARE.
177 283
178 284 })();
179 285
180   - DefaultQueryBuilderOptions = {
181   - autoQuoteTableNames: false,
182   - autoQuoteFieldNames: false,
183   - nameQuoteCharacter: '`',
184   - usingValuePlaceholders: false
185   - };
186   -
187   - QueryBuilder = (function(_super) {
  286 + cls.BuildingBlock = (function(_super) {
188 287
189   - __extends(QueryBuilder, _super);
  288 + __extends(BuildingBlock, _super);
190 289
191   - function QueryBuilder(options) {
192   - this.options = _extend({}, DefaultQueryBuilderOptions, options);
  290 + function BuildingBlock() {
  291 + return BuildingBlock.__super__.constructor.apply(this, arguments);
193 292 }
194 293
195   - QueryBuilder.prototype._getObjectClassName = function(obj) {
196   - var arr;
197   - if (obj && obj.constructor && obj.constructor.toString) {
198   - arr = obj.constructor.toString().match(/function\s*(\w+)/);
199   - if (arr && arr.length === 2) {
200   - return arr[1];
  294 + BuildingBlock.prototype.exposedMethods = function() {
  295 + var attr, ret, value;
  296 + ret = {};
  297 + for (attr in this) {
  298 + if (!__hasProp.call(this, attr)) continue;
  299 + value = this[attr];
  300 + if (typeof value === "Function") {
  301 + if (attr.charAt(0) !== '_' && attr !== 'buildStr') {
  302 + ret[attr] = value;
  303 + }
201 304 }
202 305 }
203   - return void 0;
204   - };
205   -
206   - QueryBuilder.prototype._sanitizeCondition = function(condition) {
207   - var c, t;
208   - t = typeof condition;
209   - c = this._getObjectClassName(condition);
210   - if ('Expression' !== c && "string" !== t) {
211   - throw new Error("condition must be a string or Expression instance");
212   - }
213   - if ('Expression' === t || 'Expression' === c) {
214   - condition = condition.toString();
215   - }
216   - return condition;
  306 + return ret;
217 307 };
218 308
219   - QueryBuilder.prototype._sanitizeName = function(value, type) {
220   - if ("string" !== typeof value) {
221   - throw new Error("" + type + " must be a string");
222   - }
223   - return value;
  309 + BuildingBlock.prototype.buildStr = function(queryBuilder) {
  310 + return '';
224 311 };
225 312
226   - QueryBuilder.prototype._sanitizeField = function(item) {
227   - var sanitized;
228   - sanitized = this._sanitizeName(item, "field name");
229   - if (this.options.autoQuoteFieldNames) {
230   - return "" + this.options.nameQuoteCharacter + sanitized + this.options.nameQuoteCharacter;
231   - } else {
232   - return sanitized;
233   - }
234   - };
  313 + return BuildingBlock;
235 314
236   - QueryBuilder.prototype._sanitizeTable = function(item) {
237   - var sanitized;
238   - sanitized = this._sanitizeName(item, "table name");
239   - if (this.options.autoQuoteTableNames) {
240   - return "" + this.options.nameQuoteCharacter + sanitized + this.options.nameQuoteCharacter;
241   - } else {
242   - return sanitized;
243   - }
244   - };
  315 + })(cls.BaseBuilder);
245 316
246   - QueryBuilder.prototype._sanitizeAlias = function(item) {
247   - return this._sanitizeName(item, "alias");
248   - };
  317 + cls.StringBlock = (function(_super) {
249 318
250   - QueryBuilder.prototype._sanitizeLimitOffset = function(value) {
251   - value = parseInt(value);
252   - if (0 > value || isNaN(value)) {
253   - throw new Error("limit/offset must be >=0");
254   - }
255   - return value;
256   - };
  319 + __extends(StringBlock, _super);
257 320
258   - QueryBuilder.prototype._sanitizeValue = function(item) {
259   - var t;
260   - t = typeof item;
261   - if (null !== item && "string" !== t && "number" !== t && "boolean" !== t) {
262   - throw new Error("field value must be a string, number, boolean or null");
263   - }
264   - return item;
265   - };
  321 + function StringBlock(options, str) {
  322 + StringBlock.__super__.constructor.call(this, options);
  323 + this.str = str;
  324 + }
266 325
267   - QueryBuilder.prototype._formatValue = function(value) {
268   - if (null === value) {
269   - value = "NULL";
270   - } else if ("boolean" === typeof value) {
271   - value = value ? "TRUE" : "FALSE";
272   - } else if ("number" !== typeof value) {
273   - if (false === this.options.usingValuePlaceholders) {
274   - value = "'" + value + "'";
275   - }
276   - }
277   - return value;
  326 + StringBlock.prototype.buildStr = function(queryBuilder) {
  327 + return this.str;
278 328 };
279 329
280   - return QueryBuilder;
281   -
282   - })(Cloneable);
283   -
284   - WhereOrderLimit = (function(_super) {
285   -
286   - __extends(WhereOrderLimit, _super);
  330 + return StringBlock;
287 331
288   - function WhereOrderLimit(options) {
289   - this._limitString = __bind(this._limitString, this);
  332 + })(cls.BuildingBlock);
290 333
291   - this._orderString = __bind(this._orderString, this);
  334 + cls.FromTableBlock = (function(_super) {
292 335
293   - this._whereString = __bind(this._whereString, this);
  336 + __extends(FromTableBlock, _super);
294 337
295   - this.limit = __bind(this.limit, this);
296   -
297   - this.order = __bind(this.order, this);
298   -
299   - this.where = __bind(this.where, this);
300   - WhereOrderLimit.__super__.constructor.call(this, options);
301   - this.wheres = [];
302   - this.orders = [];
303   - this.limits = null;
  338 + function FromTableBlock(options) {
  339 + FromTableBlock.__super__.constructor.call(this, options);
  340 + this.froms = [];
304 341 }
305 342
306   - WhereOrderLimit.prototype.where = function(condition) {
307   - condition = this._sanitizeCondition(condition);
308   - if ("" !== condition) {
309   - this.wheres.push(condition);
  343 + FromTableBlock.prototype.from = function(table, alias) {
  344 + if (alias == null) {
  345 + alias = null;
310 346 }
311   - return this;
312   - };
313   -
314   - WhereOrderLimit.prototype.order = function(field, asc) {
315   - if (asc == null) {
316   - asc = true;
  347 + table = this._sanitizeTable(table);
  348 + if (alias) {
  349 + alias = this._sanitizeAlias(alias);
317 350 }
318   - field = this._sanitizeField(field);
319   - this.orders.push({
320   - field: field,
321   - dir: asc ? "ASC" : "DESC"
  351 + return this.froms.push({
  352 + name: table,
  353 + alias: alias
322 354 });
323   - return this;
324   - };
325   -
326   - WhereOrderLimit.prototype.limit = function(max) {
327   - max = this._sanitizeLimitOffset(max);
328   - this.limits = max;
329   - return this;
330 355 };
331 356
332   - WhereOrderLimit.prototype._whereString = function() {
333   - if (0 < this.wheres.length) {
334   - return " WHERE (" + this.wheres.join(") AND (") + ")";
335   - } else {
336   - return "";
  357 + FromTableBlock.prototype.buildStr = function(queryBuilder) {
  358 + var table, tables, _i, _len, _ref;
  359 + if (0 >= this.froms.length) {
  360 + throw new Error("from() needs to be called");
337 361 }
338   - };
339   -
340   - WhereOrderLimit.prototype._orderString = function() {
341   - var o, orders, _i, _len, _ref;
342   - if (0 < this.orders.length) {
343   - orders = "";
344   - _ref = this.orders;
345   - for (_i = 0, _len = _ref.length; _i < _len; _i++) {
346   - o = _ref[_i];
347   - if ("" !== orders) {
348   - orders += ", ";
349   - }
350   - orders += "" + o.field + " " + o.dir;
  362 + tables = "";
  363 + _ref = this.froms;
  364 + for (_i = 0, _len = _ref.length; _i < _len; _i++) {
  365 + table = _ref[_i];
  366 + if ("" !== tables) {
  367 + tables += ", ";
  368 + }
  369 + tables += table.name;
  370 + if (table.alias) {
  371 + tables += " `" + table.alias + "`";
351 372 }
352   - return " ORDER BY " + orders;
353   - } else {
354   - return "";
355   - }
356   - };
357   -
358   - WhereOrderLimit.prototype._limitString = function() {
359   - if (this.limits) {
360   - return " LIMIT " + this.limits;
361   - } else {
362   - return "";
363 373 }
  374 + return "FROM " + tables;
364 375 };
365 376
366   - return WhereOrderLimit;
367   -
368   - })(QueryBuilder);
  377 + return FromTableBlock;
369 378
370   - JoinWhereOrderLimit = (function(_super) {
  379 + })(cls.BuildingBlock);
371 380
372   - __extends(JoinWhereOrderLimit, _super);
  381 + cls.UpdateTableBlock = (function(_super) {
373 382
374   - function JoinWhereOrderLimit(options) {
375   - this._joinString = __bind(this._joinString, this);
  383 + __extends(UpdateTableBlock, _super);
376 384
377   - this.outer_join = __bind(this.outer_join, this);
378   -
379   - this.right_join = __bind(this.right_join, this);
380   -
381   - this.left_join = __bind(this.left_join, this);
382   -
383   - this.join = __bind(this.join, this);
384   - JoinWhereOrderLimit.__super__.constructor.call(this, options);
385   - this.joins = [];
  385 + function UpdateTableBlock(options) {
  386 + UpdateTableBlock.__super__.constructor.call(this, options);
  387 + this.tables = [];
386 388 }
387 389
388   - JoinWhereOrderLimit.prototype.join = function(table, alias, condition, type) {
389   - if (type == null) {
390   - type = 'INNER';
  390 + UpdateTableBlock.prototype.table = function(table, alias) {
  391 + if (alias == null) {
  392 + alias = null;
391 393 }
392 394 table = this._sanitizeTable(table);
393 395 if (alias) {
394 396 alias = this._sanitizeAlias(alias);
395 397 }
396   - if (condition) {
397   - condition = this._sanitizeCondition(condition);
398   - }
399   - this.joins.push({
400   - type: type,
401   - table: table,
402   - alias: alias,
403   - condition: condition
  398 + return this.tables.push({
  399 + name: table,
  400 + alias: alias
404 401 });
405   - return this;
406 402 };
407 403
408   - JoinWhereOrderLimit.prototype.left_join = function(table, alias, condition) {
409   - if (alias == null) {
410   - alias = null;
411   - }
412   - if (condition == null) {
413   - condition = null;
  404 + UpdateTableBlock.prototype.buildStr = function(queryBuilder) {
  405 + var table, tables, _i, _len, _ref;
  406 + if (0 >= this.tables.length) {
  407 + throw new Error("table() needs to be called");
414 408 }
415   - return this.join(table, alias, condition, 'LEFT');
416   - };
417   -
418   - JoinWhereOrderLimit.prototype.right_join = function(table, alias, condition) {
419   - if (alias == null) {
420   - alias = null;
421   - }
422   - if (condition == null) {
423   - condition = null;
424   - }
425   - return this.join(table, alias, condition, 'RIGHT');
426   - };
427   -
428   - JoinWhereOrderLimit.prototype.outer_join = function(table, alias, condition) {
429   - if (alias == null) {
430   - alias = null;
431   - }
432   - if (condition == null) {
433   - condition = null;
434   - }
435   - return this.join(table, alias, condition, 'OUTER');
436   - };
437   -
438   - JoinWhereOrderLimit.prototype._joinString = function() {
439   - var j, joins, _i, _len, _ref;
440   - joins = "";
441   - _ref = this.joins || [];
  409 + tables = "";
  410 + _ref = this.tables;
442 411 for (_i = 0, _len = _ref.length; _i < _len; _i++) {
443   - j = _ref[_i];
444   - joins += " " + j.type + " JOIN " + j.table;
445   - if (j.alias) {
446   - joins += " `" + j.alias + "`";
  412 + table = _ref[_i];
  413 + if ("" !== tables) {
  414 + tables += ", ";
447 415 }
448   - if (j.condition) {
449   - joins += " ON (" + j.condition + ")";
  416 + tables += table.name;
  417 + if (table.alias) {
  418 + tables += " AS `" + table.alias + "`";
450 419 }
451 420 }
452   - return joins;
  421 + return tables;
453 422 };
454 423
455   - return JoinWhereOrderLimit;
  424 + return UpdateTableBlock;
456 425
457   - })(WhereOrderLimit);
  426 + })(cls.BuildingBlock);
458 427
459   - Select = (function(_super) {
  428 + cls.IntoTableBlock = (function(_super) {
460 429
461   - __extends(Select, _super);
  430 + __extends(IntoTableBlock, _super);
462 431
463   - function Select(options) {
464   - this.toString = __bind(this.toString, this);
  432 + function IntoTableBlock(options) {
  433 + IntoTableBlock.__super__.constructor.call(this, options);
  434 + this.table = null;
  435 + }
465 436
466   - this.offset = __bind(this.offset, this);
  437 + IntoTableBlock.prototype.table = function(table) {
  438 + return table = this._sanitizeTable(table);
  439 + };
467 440
468   - this.group = __bind(this.group, this);
  441 + IntoTableBlock.prototype.buildStr = function(queryBuilder) {
  442 + if (!this.table) {
  443 + throw new Error("into() needs to be called");
  444 + }
  445 + return this.table;
  446 + };
469 447
470   - this.field = __bind(this.field, this);
  448 + return IntoTableBlock;
471 449
472   - this.from = __bind(this.from, this);
  450 + })(cls.BuildingBlock);
473 451
474   - this.distinct = __bind(this.distinct, this);
475   - Select.__super__.constructor.call(this, options);
476   - this.froms = [];
477   - this.fields = [];
478   - this.groups = [];
479   - this.offsets = null;
480   - this.useDistinct = false;
481   - }
  452 + cls.GetFieldBlock = (function(_super) {
482 453
483   - Select.prototype.distinct = function() {
484   - this.useDistinct = true;
485   - return this;
486   - };
  454 + __extends(GetFieldBlock, _super);
487 455
488   - Select.prototype.from = function(table, alias) {
489   - if (alias == null) {
490   - alias = null;
491   - }
492   - table = this._sanitizeTable(table);
493   - if (alias) {
494   - alias = this._sanitizeAlias(alias);
495   - }
496   - this.froms.push({
497   - name: table,
498   - alias: alias
499   - });
500   - return this;
501   - };
  456 + function GetFieldBlock(options) {
  457 + this.field = __bind(this.field, this);
  458 + GetFieldBlock.__super__.constructor.call(this, options);
  459 + this.fields = [];
  460 + }
502 461
503   - Select.prototype.field = function(field, alias) {
  462 + GetFieldBlock.prototype.field = function(field, alias) {
504 463 if (alias == null) {
505 464 alias = null;
506 465 }
@@ -508,34 +467,14 @@ OTHER DEALINGS IN THE SOFTWARE.
508 467 if (alias) {
509 468 alias = this._sanitizeAlias(alias);
510 469 }
511   - this.fields.push({
  470 + return this.fields.push({
512 471 name: field,
513 472 alias: alias
514 473 });
515   - return this;
516   - };
517   -
518   - Select.prototype.group = function(field) {
519   - field = this._sanitizeField(field);
520   - this.groups.push(field);
521   - return this;
522   - };
523   -
524   - Select.prototype.offset = function(start) {
525   - start = this._sanitizeLimitOffset(start);
526   - this.offsets = start;
527   - return this;
528 474 };
529 475
530   - Select.prototype.toString = function() {
531   - var f, field, fields, groups, ret, table, tables, _i, _j, _k, _len, _len1, _len2, _ref, _ref1, _ref2;
532   - if (0 >= this.froms.length) {
533   - throw new Error("from() needs to be called");
534   - }
535   - ret = "SELECT ";
536   - if (this.useDistinct) {
537   - ret += "DISTINCT ";
538   - }
  476 + GetFieldBlock.prototype.buildStr = function(queryBuilder) {
  477 + var field, fields, _i, _len, _ref;
539 478 fields = "";
540 479 _ref = this.fields;
541 480 for (_i = 0, _len = _ref.length; _i < _len; _i++) {
@@ -548,88 +487,36 @@ OTHER DEALINGS IN THE SOFTWARE.
548 487 fields += " AS \"" + field.alias + "\"";
549 488 }
550 489 }
551   - ret += "" === fields ? "*" : fields;
552   - tables = "";
553   - _ref1 = this.froms;
554   - for (_j = 0, _len1 = _ref1.length; _j < _len1; _j++) {
555   - table = _ref1[_j];
556   - if ("" !== tables) {
557   - tables += ", ";
558   - }
559   - tables += table.name;
560   - if (table.alias) {
561   - tables += " `" + table.alias + "`";
562   - }
563   - }
564   - ret += " FROM " + tables;
565   - ret += this._joinString();
566   - ret += this._whereString();
567   - if (0 < this.groups.length) {
568   - groups = "";
569   - _ref2 = this.groups;
570   - for (_k = 0, _len2 = _ref2.length; _k < _len2; _k++) {
571   - f = _ref2[_k];
572   - if ("" !== groups) {
573   - groups += ", ";
574   - }
575   - groups += f;
576   - }
577   - ret += " GROUP BY " + groups;
578   - }
579   - ret += this._orderString();
580   - ret += this._limitString();
581   - if (this.offsets) {
582   - ret += " OFFSET " + this.offsets;
  490 + if ("" === fields) {
  491 + return "*";
  492 + } else {
  493 + return fields;
583 494 }
584   - return ret;
585 495 };
586 496
587   - return Select;
588   -
589   - })(JoinWhereOrderLimit);
  497 + return GetFieldBlock;
590 498
591   - Update = (function(_super) {
  499 + })(cls.BuildingBlock);
592 500
593   - __extends(Update, _super);
  501 + cls.SetFieldBlock = (function(_super) {
594 502
595   - function Update(options) {
596   - this.toString = __bind(this.toString, this);
  503 + __extends(SetFieldBlock, _super);
597 504
  505 + function SetFieldBlock(options) {
598 506 this.set = __bind(this.set, this);
599   -
600   - this.table = __bind(this.table, this);
601   - Update.__super__.constructor.call(this, options);
602   - this.tables = [];
  507 + SetFieldBlock.__super__.constructor.call(this, options);
603 508 this.fields = {};
604 509 }
605 510
606   - Update.prototype.table = function(table, alias) {
607   - if (alias == null) {
608   - alias = null;
609   - }
610   - table = this._sanitizeTable(table);
611   - if (alias) {
612   - alias = this._sanitizeAlias(alias);
613   - }
614   - this.tables.push({
615   - name: table,
616   - alias: alias
617   - });
618   - return this;
619   - };
620   -
621   - Update.prototype.set = function(field, value) {
  511 + SetFieldBlock.prototype.set = function(field, value) {
622 512 field = this._sanitizeField(field);
623 513 value = this._sanitizeValue(value);
624 514 this.fields[field] = value;
625 515 return this;
626 516 };
627 517
628   - Update.prototype.toString = function() {
629   - var field, fieldNames, fields, ret, table, tables, _i, _j, _len, _len1, _ref;
630   - if (0 >= this.tables.length) {
631   - throw new Error("table() needs to be called");
632   - }
  518 + SetFieldBlock.prototype.buildStr = function(queryBuilder) {
  519 + var field, fieldNames, fields, _i, _len;
633 520 fieldNames = (function() {
634 521 var _ref, _results;
635 522 _ref = this.fields;
@@ -643,117 +530,40 @@ OTHER DEALINGS IN THE SOFTWARE.
643 530 if (0 >= fieldNames.length) {
644 531 throw new Error("set() needs to be called");
645 532 }
646   - ret = "UPDATE ";
647   - tables = "";
648   - _ref = this.tables;
649   - for (_i = 0, _len = _ref.length; _i < _len; _i++) {
650   - table = _ref[_i];
651   - if ("" !== tables) {
652   - tables += ", ";
653   - }
654   - tables += table.name;
655   - if (table.alias) {
656   - tables += " AS `" + table.alias + "`";
657   - }
658   - }
659   - ret += tables;
660 533 fields = "";
661   - for (_j = 0, _len1 = fieldNames.length; _j < _len1; _j++) {
662   - field = fieldNames[_j];
  534 + for (_i = 0, _len = fieldNames.length; _i < _len; _i++) {
  535 + field = fieldNames[_i];
663 536 if ("" !== fields) {
664 537 fields += ", ";
665 538 }
666 539 fields += "" + field + " = " + (this._formatValue(this.fields[field]));
667 540 }
668   - ret += " SET " + fields;
669   - ret += this._whereString();
670   - ret += this._orderString();
671   - ret += this._limitString();
672   - return ret;
  541 + return "SET " + fields;
673 542 };
674 543
675   - return Update;
676   -
677   - })(WhereOrderLimit);
  544 + return SetFieldBlock;
678 545
679   - Delete = (function(_super) {
  546 + })(cls.BuildingBlock);
680 547
681   - __extends(Delete, _super);
  548 + cls.InsertIntoFieldBlock = (function(_super) {
682 549
683   - function Delete() {
684   - this.toString = __bind(this.toString, this);
685   -
686   - this.from = __bind(this.from, this);
687   - return Delete.__super__.constructor.apply(this, arguments);
688   - }
689   -
690   - Delete.prototype.table = null;
691   -
692   - Delete.prototype.from = function(table, alias) {
693   - table = this._sanitizeTable(table);
694   - if (alias) {
695   - alias = this._sanitizeAlias(alias);
696   - }
697   - this.table = {
698   - name: table,
699   - alias: alias
700   - };
701   - return this;
702   - };
703   -
704   - Delete.prototype.toString = function() {
705   - var ret;
706   - if (!this.table) {
707   - throw new Error("from() needs to be called");
708   - }
709   - ret = "DELETE FROM " + this.table.name;
710   - if (this.table.alias) {
711   - ret += " `" + this.table.alias + "`";
712   - }
713   - ret += this._joinString();
714   - ret += this._whereString();
715   - ret += this._orderString();
716   - ret += this._limitString();
717   - return ret;
718   - };
719   -
720   - return Delete;
721   -
722   - })(JoinWhereOrderLimit);
723   -
724   - Insert = (function(_super) {
725   -
726   - __extends(Insert, _super);
727   -
728   - function Insert(options) {
729   - this.toString = __bind(this.toString, this);
  550 + __extends(InsertIntoFieldBlock, _super);
730 551
  552 + function InsertIntoFieldBlock(options) {
731 553 this.set = __bind(this.set, this);
732   -
733   - this.into = __bind(this.into, this);
734   - Insert.__super__.constructor.call(this, options);
735   - this.table = null;
  554 + InsertIntoFieldBlock.__super__.constructor.call(this, options);
736 555 this.fields = {};
737 556 }
738 557
739   - Insert.prototype.into = function(table) {
740   - table = this._sanitizeTable(table);
741   - this.table = table;
742   - return this;
743   - };
744   -
745   - Insert.prototype.set = function(field, value) {
  558 + InsertIntoFieldBlock.prototype.set = function(field, value) {
746 559 field = this._sanitizeField(field);
747 560 value = this._sanitizeValue(value);
748 561 this.fields[field] = value;
749 562 return this;
750 563 };
751 564
752   - Insert.prototype.toString = function() {
  565 + InsertIntoFieldBlock.prototype.buildStr = function(queryBuilder) {
753 566 var field, fieldNames, fields, name, values, _i, _len;
754   - if (!this.table) {
755   - throw new Error("into() needs to be called");
756   - }
757 567 fieldNames = (function() {
758 568 var _ref, _results;
759 569 _ref = this.fields;
@@ -780,49 +590,422 @@ OTHER DEALINGS IN THE SOFTWARE.
780 590 }
781 591 values += this._formatValue(this.fields[field]);
782 592 }
783   - return "INSERT INTO " + this.table + " (" + fields + ") VALUES (" + values + ")";
  593 + return "(" + fields + ") VALUES (" + values + ")";
  594 + };
  595 +
  596 + return InsertIntoFieldBlock;
  597 +
  598 + })(cls.BuildingBlock);
  599 +
  600 + DistinctBlock = (function(_super) {
  601 +
  602 + __extends(DistinctBlock, _super);
  603 +
  604 + function DistinctBlock(options) {
  605 + DistinctBlock.__super__.constructor.call(this, options);
  606 + this.use_distinct = false;
  607 + }
  608 +
  609 + DistinctBlock.prototype.distinct = function() {
  610 + return this.useDistinct = true;
  611 + };
  612 +
  613 + DistinctBlock.prototype.buildStr = function(queryBuilder) {
  614 + if (this.useDistinct) {
  615 + return "DISTINCT";
  616 + } else {
  617 + return "";
  618 + }
784 619 };
785 620
  621 + return DistinctBlock;
  622 +
  623 + })(cls.BuildingBlock);
  624 +
  625 + cls.GroupByBlock = (function(_super) {
  626 +
  627 + __extends(GroupByBlock, _super);
  628 +
  629 + function GroupByBlock(options) {
  630 + this.group = __bind(this.group, this);
  631 + GroupByBlock.__super__.constructor.call(this, options);
  632 + this.groups = [];
  633 + }
  634 +
  635 + GroupByBlock.prototype.group = function(field) {
  636 + field = this._sanitizeField(field);
  637 + return this.groups.push(field);
  638 + };
  639 +
  640 + GroupByBlock.prototype.buildStr = function(queryBuilder) {
  641 + var f, groups, _i, _len, _ref;
  642 + groups = "";
  643 + if (0 < this.groups.length) {
  644 + _ref = this.groups;
  645 + for (_i = 0, _len = _ref.length; _i < _len; _i++) {
  646 + f = _ref[_i];
  647 + if ("" !== groups) {
  648 + groups += ", ";
  649 + }
  650 + groups += f;
  651 + }
  652 + groups = "GROUP BY " + groups;
  653 + }
  654 + return groups;
  655 + };
  656 +
  657 + return GroupByBlock;
  658 +
  659 + })(cls.BuildingBlock);
  660 +
  661 + cls.OffsetBlock = (function(_super) {
  662 +
  663 + __extends(OffsetBlock, _super);
  664 +
  665 + function OffsetBlock(options) {
  666 + this.offset = __bind(this.offset, this);
  667 + OffsetBlock.__super__.constructor.call(this, options);
  668 + this.offsets = null;
  669 + }
  670 +
  671 + OffsetBlock.prototype.offset = function(start) {
  672 + start = this._sanitizeLimitOffset(start);
  673 + return this.offsets = start;
  674 + };
  675 +
  676 + OffsetBlock.prototype.buildStr = function(queryBuilder) {
  677 + if (this.offsets("OFFSET " + this.offsets)) {
  678 +
  679 + } else {
  680 + return "";
  681 + }
  682 + };
  683 +
  684 + return OffsetBlock;
  685 +
  686 + })(cls.BuildingBlock);
  687 +
  688 + cls.WhereBlock = (function(_super) {
  689 +
  690 + __extends(WhereBlock, _super);
  691 +
  692 + function WhereBlock(options) {
  693 + this.where = __bind(this.where, this);
  694 + WhereBlock.__super__.constructor.call(this, options);
  695 + this.wheres = [];
  696 + }
  697 +
  698 + WhereBlock.prototype.where = function(condition) {
  699 + condition = this._sanitizeCondition(condition);
  700 + if ("" !== condition) {
  701 + return this.wheres.push(condition);
  702 + }
  703 + };
  704 +
  705 + WhereBlock.prototype.buildStr = function(queryBuilder) {
  706 + if (this.offsets("OFFSET " + this.offsets)) {
  707 +
  708 + } else {
  709 + return "";
  710 + }
  711 + };
  712 +
  713 + return WhereBlock;
  714 +
  715 + })(cls.BuildingBlock);
  716 +
  717 + cls.OrderByBlock = (function(_super) {
  718 +
  719 + __extends(OrderByBlock, _super);
  720 +
  721 + function OrderByBlock(options) {
  722 + this.order = __bind(this.order, this);
  723 + OrderByBlock.__super__.constructor.call(this, options);
  724 + this.orders = [];
  725 + }
  726 +
  727 + OrderByBlock.prototype.order = function(field, asc) {
  728 + if (asc == null) {
  729 + asc = true;
  730 + }
  731 + field = this._sanitizeField(field);
  732 + return this.orders.push({
  733 + field: field,
  734 + dir: asc ? "ASC" : "DESC"
  735 + });
  736 + };
  737 +
  738 + OrderByBlock.prototype.buildStr = function(queryBuilder) {
  739 + var o, orders, _i, _len, _ref;
  740 + if (0 < this.orders.length) {
  741 + orders = "";
  742 + _ref = this.orders;
  743 + for (_i = 0, _len = _ref.length; _i < _len; _i++) {
  744 + o = _ref[_i];
  745 + if ("" !== orders) {
  746 + orders += ", ";
  747 + }
  748 + orders += "" + o.field + " " + o.dir;
  749 + }
  750 + return "ORDER BY " + orders;
  751 + } else {
  752 + return "";
  753 + }
  754 + };
  755 +
  756 + return OrderByBlock;
  757 +
  758 + })(cls.BuildingBlock);
  759 +
  760 + cls.LimitBlock = (function(_super) {
  761 +
  762 + __extends(LimitBlock, _super);
  763 +
  764 + function LimitBlock(options) {
  765 + this.limit = __bind(this.limit, this);
  766 + LimitBlock.__super__.constructor.call(this, options);
  767 + this.limits = null;
  768 + }
  769 +
  770 + LimitBlock.prototype.limit = function(max) {
  771 + max = this._sanitizeLimitOffset(max);
  772 + return this.limits = max;
  773 + };
  774 +
  775 + LimitBlock.prototype.buildStr = function(queryBuilder) {
  776 + if (this.limits("LIMIT " + this.limits)) {
  777 +
  778 + } else {
  779 + return "";
  780 + }
  781 + };
  782 +
  783 + return LimitBlock;
  784 +
  785 + })(cls.BuildingBlock);
  786 +
  787 + cls.JoinBlock = (function(_super) {
  788 +
  789 + __extends(JoinBlock, _super);
  790 +
  791 + function JoinBlock(options) {
  792 + this.outer_join = __bind(this.outer_join, this);
  793 +
  794 + this.right_join = __bind(this.right_join, this);
  795 +
  796 + this.left_join = __bind(this.left_join, this);
  797 +
  798 + this.join = __bind(this.join, this);
  799 + JoinBlock.__super__.constructor.call(this, options);
  800 + this.joins = [];
  801 + }
  802 +
  803 + JoinBlock.prototype.join = function(table, alias, condition, type) {
  804 + if (type == null) {
  805 + type = 'INNER';
  806 + }
  807 + table = this._sanitizeTable(table);
  808 + if (alias) {
  809 + alias = this._sanitizeAlias(alias);
  810 + }
  811 + if (condition) {
  812 + condition = this._sanitizeCondition(condition);
  813 + }
  814 + this.joins.push({
  815 + type: type,
  816 + table: table,
  817 + alias: alias,
  818 + condition: condition
  819 + });
  820 + return this;
  821 + };
  822 +
  823 + JoinBlock.prototype.left_join = function(table, alias, condition) {
  824 + if (alias == null) {
  825 + alias = null;
  826 + }
  827 + if (condition == null) {
  828 + condition = null;
  829 + }
  830 + return this.join(table, alias, condition, 'LEFT');
  831 + };
  832 +
  833 + JoinBlock.prototype.right_join = function(table, alias, condition) {
  834 + if (alias == null) {
  835 + alias = null;
  836 + }
  837 + if (condition == null) {
  838 + condition = null;
  839 + }
  840 + return this.join(table, alias, condition, 'RIGHT');
  841 + };
  842 +
  843 + JoinBlock.prototype.outer_join = function(table, alias, condition) {
  844 + if (alias == null) {
  845 + alias = null;
  846 + }
  847 + if (condition == null) {
  848 + condition = null;
  849 + }
  850 + return this.join(table, alias, condition, 'OUTER');
  851 + };
  852 +
  853 + JoinBlock.prototype.buildStr = function(queryBuilder) {
  854 + var j, joins, _i, _len, _ref;
  855 + joins = "";
  856 + _ref = this.joins || [];
  857 + for (_i = 0, _len = _ref.length; _i < _len; _i++) {
  858 + j = _ref[_i];
  859 + joins += " " + j.type + " JOIN " + j.table;
  860 + if (j.alias) {
  861 + joins += " `" + j.alias + "`";
  862 + }
  863 + if (j.condition) {
  864 + joins += " ON (" + j.condition + ")";
  865 + }
  866 + }
  867 + return joins;
  868 + };
  869 +
  870 + return JoinBlock;
  871 +
  872 + })(cls.BuildingBlock);
  873 +
  874 + cls.QueryBuilder = (function(_super) {
  875 +
  876 + __extends(QueryBuilder, _super);
  877 +
  878 + function QueryBuilder(blocks) {
  879 + var block, methodBody, methodName, _fn, _i, _len, _ref, _ref1,
  880 + _this = this;
  881 + this.block = blocks;
  882 + _ref = this.blocks;
  883 + for (_i = 0, _len = _ref.length; _i < _len; _i++) {
  884 + block = _ref[_i];
  885 + _ref1 = block.exposedMethods();
  886 + _fn = function(name, body) {
  887 + return _this[name] = function() {
  888 + body.apply(_this, arguments);
  889 + return _this;
  890 + };
  891 + };
  892 + for (methodName in _ref1) {
  893 + if (!__hasProp.call(_ref1, methodName)) continue;
  894 + methodBody = _ref1[methodName];
  895 + if (this[methodName] != null) {
  896 + throw new Error(_getObjectClassName(this) + ("already has a builder method called " + methodName));
  897 + }
  898 + _fn(methodName, methodBody);
  899 + }
  900 + }
  901 + ({
  902 + toString: function() {
  903 + return ((function() {
  904 + var _j, _len1, _ref2, _results;
  905 + _ref2 = this.blocks;
  906 + _results = [];
  907 + for (_j = 0, _len1 = _ref2.length; _j < _len1; _j++) {
  908 + block = _ref2[_j];
  909 + _results.push(block.buildStr(this));
  910 + }
  911 + return _results;
  912 + }).call(_this)).join(" ");
  913 + }
  914 + });
  915 + }
  916 +
  917 + return QueryBuilder;
  918 +
  919 + })(cls.BaseBuilder);
  920 +
  921 + cls.Select = (function(_super) {
  922 +
  923 + __extends(Select, _super);
  924 +
  925 + function Select(options) {
  926 + var blocks;
  927 + blocks = [new cls.StringBlock(options, 'SELECT'), new cls.GetFieldBlock(options), new cls.FromTableBlock(options), new cls.JoinBlock(options), new cls.WhereBlock(options), new cls.GroupByBlock(options), new cls.OrderByBlock(options), new cls.LimitBlock(options), new cls.OffsetBlock(options)];
  928 + Select.__super__.constructor.call(this, blocks);
  929 + }
  930 +
  931 + return Select;
  932 +
  933 + })(cls.QueryBuilder);
  934 +
  935 + cls.Update = (function(_super) {
  936 +
  937 + __extends(Update, _super);
  938 +
  939 + function Update(options) {
  940 + var blocks;
  941 + blocks = [new cls.StringBlock(options, 'UPDATE'), new cls.UpdateTableBlock(options), new cls.SetFieldBlock(options), new cls.WhereBlock(options), new cls.OrderByBlock(options), new cls.LimitBlock(options)];
  942 + Update.__super__.constructor.call(this, blocks);
  943 + }
  944 +
  945 + return Update;
  946 +
  947 + })(cls.QueryBuilder);
  948 +
  949 + cls.Delete = (function(_super) {
  950 +
  951 + __extends(Delete, _super);
  952 +
  953 + function Delete(options) {
  954 + var blocks;
  955 + blocks = [new cls.StringBlock(options, 'DELETE'), new cls.FromTableBlock(options), new cls.JoinBlock(options), new cls.WhereBlock(options), new cls.OrderByBlock(options), new cls.LimitBlock(options)];
  956 + Delete.__super__.constructor.call(this, blocks);
  957 + }
  958 +
  959 + return Delete;
  960 +
  961 + })(cls.QueryBuilder);
  962 +
  963 + cls.Insert = (function(_super) {
  964 +
  965 + __extends(Insert, _super);
  966 +
  967 + function Insert(options) {
  968 + var blocks;
  969 + blocks = [new cls.StringBlock(options, 'INSERT'), new cls.IntoTableBlock(options), new cls.InsertIntoFieldBlock(options)];
  970 + Insert.__super__.constructor.call(this, blocks);
  971 + }
  972 +
786 973 return Insert;
787 974
788   - })(QueryBuilder);
  975 + })(cls.BaseBuilder);
789 976
790   - _export = {
  977 + squel = {
791 978 expr: function() {
792   - return new Expression;
  979 + return new cls.Expression;
793 980 },
794 981 select: function(options) {
795   - return new Select(options);
  982 + return new cls.Select(options);
796 983 },
797 984 update: function(options) {
798   - return new Update(options);
  985 + return new cls.Update(options);
799 986 },
800 987 insert: function(options) {
801   - return new Insert(options);
  988 + return new cls.Insert(options);
802 989 },
803 990 "delete": function(options) {
804   - return new Delete(options);
805   - },
806   - DefaultQueryBuilderOptions: DefaultQueryBuilderOptions,
807   - Cloneable: Cloneable,
808   - Expression: Expression,
809   - QueryBuilder: QueryBuilder,
810   - WhereOrderLimit: WhereOrderLimit,