UNPKG

40.3 kBJavaScriptView Raw
1// Generated by CoffeeScript 1.4.0
2/*
3These are the classes that represent nodes in the AST for a SQL statement.
4Application code should very rarely have to deal with these classes directly;
5Instead, the APIs exposed by the various query manager classes are intended to
6cover the majority of use-cases.
7
8However, in the spirit of "making hard things possible", all of AST nodes are
9exported from this module so you can constructed and assemble them manually if
10you need to.
11*/
12
13var AbstractAlias, And, Binary, CONST_NODES, Column, ColumnSet, ComparableMixin, Delete, Distinct, Field, FixedNodeSet, GroupBy, Having, Identifier, Insert, IntegerNode, JOIN_TYPES, Join, JoinType, Limit, Node, NodeSet, Offset, Or, OrderBy, Ordering, Parameter, ParenthesizedNodeSet, Prefixed, Relation, RelationSet, Returning, Select, SelectColumnSet, SqlFunction, Statement, TextNode, Tuple, Update, ValueNode, Where, binaryOp, copy, exists, getAlias, k, name, notExists, sqlFunction, text, toColumn, toField, toParam, toProjection, toRelation, tuple, v, _i, _j, _len, _len1, _ref, _ref1, _ref2,
14 __hasProp = {}.hasOwnProperty,
15 __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; },
16 __slice = [].slice;
17
18Node = (function() {
19
20 function Node() {}
21
22 /* (Empty) base Node class
23 */
24
25
26 Node.prototype.render = function(dialect) {
27 var message;
28 message = "" + this.constructor + " has no render method. Parents: " + dialect.path;
29 throw new Error(message);
30 };
31
32 return Node;
33
34})();
35
36ValueNode = (function(_super) {
37
38 __extends(ValueNode, _super);
39
40 /* A ValueNode is a literal string that should be printed unescaped.
41 */
42
43
44 function ValueNode(value) {
45 this.value = value;
46 if (this.value != null) {
47 if (!this.valid()) {
48 throw new Error("Invalid " + this.constructor.name + ": " + this.value);
49 }
50 }
51 }
52
53 ValueNode.prototype.copy = function() {
54 return new this.constructor(this.value);
55 };
56
57 ValueNode.prototype.valid = function() {
58 return true;
59 };
60
61 ValueNode.prototype.render = function() {
62 return this.value;
63 };
64
65 return ValueNode;
66
67})(Node);
68
69IntegerNode = (function(_super) {
70
71 __extends(IntegerNode, _super);
72
73 function IntegerNode() {
74 return IntegerNode.__super__.constructor.apply(this, arguments);
75 }
76
77 /* A :class:`nodes::ValueNode` that validates it's input is an integer.
78 */
79
80
81 IntegerNode.prototype.valid = function() {
82 return !isNaN(this.value = parseInt(this.value));
83 };
84
85 return IntegerNode;
86
87})(ValueNode);
88
89Identifier = (function(_super) {
90
91 __extends(Identifier, _super);
92
93 function Identifier() {
94 return Identifier.__super__.constructor.apply(this, arguments);
95 }
96
97 /*
98 An identifier is a column or relation name that may need to be quoted.
99 */
100
101
102 Identifier.prototype.render = function(dialect) {
103 return dialect.quote(this.value);
104 };
105
106 return Identifier;
107
108})(ValueNode);
109
110CONST_NODES = {};
111
112_ref = ['DEFAULT', 'NULL', 'IS_NULL', 'IS_NOT_NULL'];
113for (_i = 0, _len = _ref.length; _i < _len; _i++) {
114 name = _ref[_i];
115 CONST_NODES[name] = new ValueNode(name.replace('_', ' '));
116}
117
118JoinType = (function(_super) {
119
120 __extends(JoinType, _super);
121
122 function JoinType() {
123 return JoinType.__super__.constructor.apply(this, arguments);
124 }
125
126 return JoinType;
127
128})(ValueNode);
129
130JOIN_TYPES = {};
131
132_ref1 = ['LEFT', 'RIGHT', 'INNER', 'LEFT_OUTER', 'RIGHT_OUTER', 'FULL_OUTER', 'NATURAL', 'CROSS'];
133for (_j = 0, _len1 = _ref1.length; _j < _len1; _j++) {
134 name = _ref1[_j];
135 JOIN_TYPES[name] = new JoinType(name.replace('_', ' '));
136}
137
138NodeSet = (function(_super) {
139
140 __extends(NodeSet, _super);
141
142 /* A set of nodes joined together by ``@glue``
143 */
144
145
146 function NodeSet(nodes, glue) {
147 var node, _k, _len2, _ref2;
148 if (glue == null) {
149 glue = ' ';
150 }
151 /*
152 :param @nodes: A list of child nodes.
153 :param glue: A string that will be used to join the nodes when rendering
154 */
155
156 this.nodes = [];
157 if (nodes) {
158 for (_k = 0, _len2 = nodes.length; _k < _len2; _k++) {
159 node = nodes[_k];
160 this.addNode(node);
161 }
162 }
163 if ((_ref2 = this.glue) == null) {
164 this.glue = glue;
165 }
166 }
167
168 NodeSet.prototype.copy = function() {
169 /*
170 Make a deep copy of this node and it's children
171 */
172
173 var c;
174 c = new this.constructor(this.nodes.map(copy), this.glue);
175 return c;
176 };
177
178 NodeSet.prototype.addNode = function(node) {
179 /* Add a new Node to the end of this set
180 */
181 return this.nodes.push(node);
182 };
183
184 NodeSet.prototype.params = function(parents) {
185 var node, params, _k, _len2, _ref2;
186 if (parents == null) {
187 parents = [];
188 }
189 /*
190 Recurse over child nodes, collecting parameter values.
191 */
192
193 params = [];
194 parents = parents.concat([this]);
195 _ref2 = this.nodes;
196 for (_k = 0, _len2 = _ref2.length; _k < _len2; _k++) {
197 node = _ref2[_k];
198 if (node.params != null) {
199 params = params.concat(node.params(parents));
200 }
201 }
202 return params;
203 };
204
205 NodeSet.prototype.render = function(dialect) {
206 return this.nodes.map(function(n) {
207 return dialect.render(n);
208 }).filter(function(n) {
209 return n;
210 }).join(this.glue);
211 };
212
213 return NodeSet;
214
215})(Node);
216
217FixedNodeSet = (function(_super) {
218
219 __extends(FixedNodeSet, _super);
220
221 function FixedNodeSet() {
222 FixedNodeSet.__super__.constructor.apply(this, arguments);
223 this.addNode = null;
224 }
225
226 return FixedNodeSet;
227
228})(NodeSet);
229
230Statement = (function(_super) {
231
232 __extends(Statement, _super);
233
234 Statement.prefix = '';
235
236 Statement.structure = function(structure) {
237 var _this = this;
238 this._nodeOrder = [];
239 return structure.forEach(function(_arg) {
240 var k, type;
241 k = _arg[0], type = _arg[1];
242 _this._nodeOrder.push(k);
243 _this.prototype.__defineGetter__(k, function() {
244 var _base;
245 return (_base = this._private)[k] || (_base[k] = new type);
246 });
247 return _this.prototype.__defineSetter__(k, function(v) {
248 return this._private[k] = v;
249 });
250 });
251 };
252
253 function Statement(opts) {
254 this._private = {};
255 if (opts) {
256 this.initialize(opts);
257 }
258 }
259
260 Statement.prototype.initialize = function(opts) {
261 return this.initialize = null;
262 };
263
264 Statement.prototype.copy = function() {
265 var c, k, node, _ref2;
266 c = new this.constructor;
267 _ref2 = this._private;
268 for (k in _ref2) {
269 node = _ref2[k];
270 c[k] = copy(node);
271 }
272 c.initialize = null;
273 return c;
274 };
275
276 Statement.prototype.render = function(dialect) {
277 var k, node, parts;
278 parts = (function() {
279 var _k, _len2, _ref2, _results;
280 _ref2 = this.constructor._nodeOrder;
281 _results = [];
282 for (_k = 0, _len2 = _ref2.length; _k < _len2; _k++) {
283 k = _ref2[_k];
284 if (node = this._private[k]) {
285 _results.push(dialect.render(node));
286 }
287 }
288 return _results;
289 }).call(this);
290 if (parts.length) {
291 return this.constructor.prefix + parts.join(' ');
292 } else {
293 return "";
294 }
295 };
296
297 Statement.prototype.params = function(parents) {
298 var k, node, nodes, order, params, _k, _len2, _ref2;
299 if (parents == null) {
300 parents = [];
301 }
302 /*
303 Collect parameters from child nodes.
304 */
305
306 params = [];
307 parents = parents.concat([this]);
308 nodes = this._private;
309 order = this.constructor._nodeOrder;
310 _ref2 = (function() {
311 var _l, _len2, _results;
312 _results = [];
313 for (_l = 0, _len2 = order.length; _l < _len2; _l++) {
314 k = order[_l];
315 _results.push(nodes[k]);
316 }
317 return _results;
318 })();
319 for (_k = 0, _len2 = _ref2.length; _k < _len2; _k++) {
320 node = _ref2[_k];
321 if (node != null ? node.params : void 0) {
322 params = params.concat(node.params(parents));
323 }
324 }
325 return params;
326 };
327
328 return Statement;
329
330})(Node);
331
332ParenthesizedNodeSet = (function(_super) {
333
334 __extends(ParenthesizedNodeSet, _super);
335
336 function ParenthesizedNodeSet() {
337 return ParenthesizedNodeSet.__super__.constructor.apply(this, arguments);
338 }
339
340 /* A NodeSet wrapped in parenthesis.
341 */
342
343
344 ParenthesizedNodeSet.prototype.render = function() {
345 return "(" + ParenthesizedNodeSet.__super__.render.apply(this, arguments) + ")";
346 };
347
348 return ParenthesizedNodeSet;
349
350})(NodeSet);
351
352AbstractAlias = (function(_super) {
353
354 __extends(AbstractAlias, _super);
355
356 function AbstractAlias(obj, alias) {
357 this.obj = obj;
358 this.alias = alias;
359 }
360
361 AbstractAlias.prototype.copy = function() {
362 return new this.constructor(copy(this.obj), this.alias);
363 };
364
365 AbstractAlias.prototype.ref = function() {
366 return this.alias;
367 };
368
369 AbstractAlias.prototype.render = function(dialect) {
370 return dialect.maybeParens(dialect.render(this.obj)) + " AS " + dialect.quote(this.alias);
371 };
372
373 AbstractAlias.prototype.params = function(parents) {
374 var _base;
375 if (parents == null) {
376 parents = [];
377 }
378 parents = parents.concat([this]);
379 return (typeof (_base = this.obj).params === "function" ? _base.params() : void 0) || [];
380 };
381
382 return AbstractAlias;
383
384})(Node);
385
386TextNode = (function(_super) {
387 var Alias, paramRegexp;
388
389 __extends(TextNode, _super);
390
391 function TextNode(text, bindVals) {
392 this.text = text;
393 this.bindVals = bindVals != null ? bindVals : [];
394 }
395
396 paramRegexp = /\$([\w]+)\b/g;
397
398 TextNode.prototype.render = function(dialect) {
399 var _this = this;
400 return this.text.replace(paramRegexp, function(_, name) {
401 if (name in _this.bindVals) {
402 return dialect.render(new Parameter(_this.bindVals[name]));
403 } else {
404 throw new Error("Parameter " + name + " not present in " + _this.bindVals);
405 }
406 });
407 };
408
409 TextNode.prototype.params = function() {
410 return this.bindVals;
411 };
412
413 TextNode.prototype.as = function(alias) {
414 return new Alias(this, alias);
415 };
416
417 TextNode.Alias = Alias = (function(_super1) {
418
419 __extends(Alias, _super1);
420
421 function Alias() {
422 return Alias.__super__.constructor.apply(this, arguments);
423 }
424
425 return Alias;
426
427 })(AbstractAlias);
428
429 return TextNode;
430
431})(Node);
432
433SqlFunction = (function(_super) {
434 var Alias;
435
436 __extends(SqlFunction, _super);
437
438 /* Includes :class:`nodes::ComparableMixin`
439 */
440
441
442 function SqlFunction(name, arglist) {
443 this.name = name;
444 this.arglist = arglist;
445 }
446
447 SqlFunction.prototype.ref = function() {
448 return this.name;
449 };
450
451 SqlFunction.prototype.copy = function() {
452 return new this.constructor(this.name, copy(this.arglist));
453 };
454
455 SqlFunction.prototype.render = function(dialect) {
456 return "" + this.name + (dialect.render(this.arglist));
457 };
458
459 SqlFunction.prototype.as = function(alias) {
460 return new Alias(this, alias);
461 };
462
463 SqlFunction.prototype.params = function(parents) {
464 return this.arglist.params();
465 };
466
467 SqlFunction.Alias = Alias = (function(_super1) {
468 var shouldRenderFull;
469
470 __extends(Alias, _super1);
471
472 function Alias() {
473 return Alias.__super__.constructor.apply(this, arguments);
474 }
475
476 shouldRenderFull = function(parents) {
477 if (parents.some(function(it) {
478 return it instanceof Column;
479 })) {
480 return false;
481 }
482 return parents.some(function(node) {
483 return node instanceof ColumnSet || node instanceof RelationSet;
484 });
485 };
486
487 Alias.prototype.render = function(dialect, parents) {
488 if (shouldRenderFull(parents)) {
489 return dialect.render(this.obj) + " AS " + dialect.quote(this.alias);
490 } else {
491 return dialect.quote(this.alias);
492 }
493 };
494
495 Alias.prototype.params = function(parents) {
496 if (parents == null) {
497 parents = [];
498 }
499 if (parents.length === 0 || shouldRenderFull(parents)) {
500 return Alias.__super__.params.apply(this, arguments);
501 } else {
502 return [];
503 }
504 };
505
506 return Alias;
507
508 })(AbstractAlias);
509
510 return SqlFunction;
511
512})(Node);
513
514Parameter = (function(_super) {
515
516 __extends(Parameter, _super);
517
518 function Parameter() {
519 return Parameter.__super__.constructor.apply(this, arguments);
520 }
521
522 /*
523 Like a ValueNode, but will render as a bound parameter place-holder
524 (e.g. ``$1``) and it's value will be collected by
525 :meth:`nodes::NodeSet.params`
526 */
527
528
529 Parameter.prototype.render = function(dialect) {
530 return "?";
531 };
532
533 Parameter.prototype.params = function() {
534 return [this.value];
535 };
536
537 return Parameter;
538
539})(ValueNode);
540
541Relation = (function(_super) {
542 var Alias;
543
544 __extends(Relation, _super);
545
546 function Relation() {
547 return Relation.__super__.constructor.apply(this, arguments);
548 }
549
550 /*
551 A relation node represents a table name or alias in a statement.
552 */
553
554
555 Relation.prototype.ref = function() {
556 /*
557 Return the table name. Aliased tables return the alias name.
558 */
559 return this.value;
560 };
561
562 Relation.prototype.project = function(field) {
563 /* Return a new :class:`nodes::Column` of `field` from this table.
564 */
565 return new Column(this, toField(field));
566 };
567
568 Relation.prototype.as = function(alias) {
569 return new Alias(this, alias);
570 };
571
572 Relation.Alias = Alias = (function(_super1) {
573
574 __extends(Alias, _super1);
575
576 function Alias() {
577 return Alias.__super__.constructor.apply(this, arguments);
578 }
579
580 /* An aliased :class:`nodes::Relation`
581 */
582
583
584 Alias.prototype.project = function(field) {
585 return Relation.prototype.project.call(this, field);
586 };
587
588 Alias.prototype.render = function(dialect, parents) {
589 if (parents.some(function(n) {
590 return n instanceof Column;
591 })) {
592 return dialect.quote(this.alias);
593 } else {
594 return Alias.__super__.render.apply(this, arguments);
595 }
596 };
597
598 return Alias;
599
600 })(AbstractAlias);
601
602 return Relation;
603
604})(Identifier);
605
606Field = (function(_super) {
607
608 __extends(Field, _super);
609
610 /* A column name
611 */
612
613
614 function Field() {
615 return Field.__super__.constructor.apply(this, arguments);
616 }
617
618 return Field;
619
620})(Identifier);
621
622Column = (function(_super) {
623 var Alias;
624
625 __extends(Column, _super);
626
627 /*
628 Includes :class:`nodes::ComparableMixin`
629 */
630
631
632 function Column(source, field) {
633 this.source = source;
634 this.field = field;
635 Column.__super__.constructor.call(this, [this.source, this.field], '.');
636 }
637
638 Column.prototype.rel = function() {
639 return this.source;
640 };
641
642 Column.prototype.copy = function() {
643 return new this.constructor(copy(this.source), copy(this.field));
644 };
645
646 Column.prototype.as = function(alias) {
647 return new Alias(this, alias);
648 };
649
650 Column.Alias = Alias = (function(_super1) {
651
652 __extends(Alias, _super1);
653
654 function Alias() {
655 return Alias.__super__.constructor.apply(this, arguments);
656 }
657
658 /* An aliased :class:`nodes::Column`
659 */
660
661
662 Alias.prototype.rel = function() {
663 return this.obj.rel();
664 };
665
666 Alias.prototype.render = function(dialect, parents) {
667 if (parents.some(function(n) {
668 return n instanceof ColumnSet;
669 })) {
670 return Alias.__super__.render.apply(this, arguments);
671 } else {
672 return dialect.quote(this.alias);
673 }
674 };
675
676 return Alias;
677
678 })(AbstractAlias);
679
680 return Column;
681
682})(FixedNodeSet);
683
684Limit = (function(_super) {
685
686 __extends(Limit, _super);
687
688 function Limit() {
689 return Limit.__super__.constructor.apply(this, arguments);
690 }
691
692 Limit.prototype.render = function() {
693 if (this.value) {
694 return "LIMIT " + this.value;
695 } else {
696 return "";
697 }
698 };
699
700 return Limit;
701
702})(IntegerNode);
703
704Offset = (function(_super) {
705
706 __extends(Offset, _super);
707
708 function Offset() {
709 return Offset.__super__.constructor.apply(this, arguments);
710 }
711
712 Offset.prototype.render = function() {
713 if (this.value) {
714 return "OFFSET " + this.value;
715 } else {
716 return "";
717 }
718 };
719
720 return Offset;
721
722})(IntegerNode);
723
724Binary = (function(_super) {
725
726 __extends(Binary, _super);
727
728 function Binary(left, op, right) {
729 this.left = left;
730 this.op = op;
731 this.right = right;
732 Binary.__super__.constructor.call(this, [this.left, this.op, this.right], ' ');
733 }
734
735 Binary.prototype.copy = function() {
736 return new this.constructor(copy(this.left), this.op, copy(this.right));
737 };
738
739 Binary.prototype.and = function() {
740 var args;
741 args = 1 <= arguments.length ? __slice.call(arguments, 0) : [];
742 return new And([this].concat(__slice.call(args)));
743 };
744
745 Binary.prototype.or = function() {
746 return new Or([this].concat(__slice.call(args)));
747 };
748
749 Binary.prototype.render = function(dialect) {
750 return [dialect.render(this.left), dialect.operator(this.op), dialect.render(this.right)].join(' ');
751 };
752
753 return Binary;
754
755})(FixedNodeSet);
756
757Tuple = (function(_super) {
758
759 __extends(Tuple, _super);
760
761 function Tuple() {
762 return Tuple.__super__.constructor.apply(this, arguments);
763 }
764
765 Tuple.prototype.glue = ', ';
766
767 return Tuple;
768
769})(ParenthesizedNodeSet);
770
771ColumnSet = (function(_super) {
772
773 __extends(ColumnSet, _super);
774
775 function ColumnSet() {
776 return ColumnSet.__super__.constructor.apply(this, arguments);
777 }
778
779 /* The list of projected columns in a query
780 */
781
782
783 ColumnSet.prototype.glue = ', ';
784
785 return ColumnSet;
786
787})(NodeSet);
788
789Returning = (function(_super) {
790
791 __extends(Returning, _super);
792
793 function Returning() {
794 return Returning.__super__.constructor.apply(this, arguments);
795 }
796
797 Returning.extend = function(klazz) {
798 return klazz.prototype.addReturning = function(cols) {
799 var col, _k, _len2;
800 for (_k = 0, _len2 = cols.length; _k < _len2; _k++) {
801 col = cols[_k];
802 this.returning.addNode(toField(col));
803 }
804 return null;
805 };
806 };
807
808 Returning.prototype.render = function() {
809 var string;
810 if (string = Returning.__super__.render.apply(this, arguments)) {
811 return "RETURNING " + string;
812 } else {
813 return "";
814 }
815 };
816
817 return Returning;
818
819})(ColumnSet);
820
821Distinct = (function(_super) {
822
823 __extends(Distinct, _super);
824
825 function Distinct(enable) {
826 this.enable = enable != null ? enable : false;
827 Distinct.__super__.constructor.apply(this, arguments);
828 }
829
830 Distinct.prototype.copy = function() {
831 return new this.constructor(this.enable, copy(this.nodes));
832 };
833
834 Distinct.prototype.render = function(dialect) {
835 if (!this.enable) {
836 return '';
837 } else if (this.nodes.length) {
838 return "DISTINCT(" + Distinct.__super__.render.apply(this, arguments) + ")";
839 } else {
840 return 'DISTINCT';
841 }
842 };
843
844 return Distinct;
845
846})(ColumnSet);
847
848SelectColumnSet = (function(_super) {
849
850 __extends(SelectColumnSet, _super);
851
852 function SelectColumnSet() {
853 return SelectColumnSet.__super__.constructor.apply(this, arguments);
854 }
855
856 SelectColumnSet.prototype.prune = function(predicate) {
857 /*
858 Recurse over child nodes, removing all Column nodes that match the
859 predicate.
860 */
861 return this.nodes = this.nodes.filter(function(n) {
862 return !predicate(n);
863 });
864 };
865
866 SelectColumnSet.prototype.render = function(dialect) {
867 if (!this.nodes.length) {
868 return '*';
869 } else {
870 return SelectColumnSet.__super__.render.apply(this, arguments);
871 }
872 };
873
874 return SelectColumnSet;
875
876})(ColumnSet);
877
878RelationSet = (function(_super) {
879
880 __extends(RelationSet, _super);
881
882 function RelationSet() {
883 return RelationSet.__super__.constructor.apply(this, arguments);
884 }
885
886 /*
887 Manages a set of relations and exposes methods to find them by alias.
888 */
889
890
891 RelationSet.prototype.addNode = function(node) {
892 if (!this.first) {
893 this.relsByName = {};
894 this.nodes.push(node);
895 return this.first = this.active = this.relsByName[node.ref()] = node;
896 } else {
897 RelationSet.__super__.addNode.apply(this, arguments);
898 return this.active = this.relsByName[node.ref()] = node.relation;
899 }
900 };
901
902 RelationSet.prototype.copy = function() {
903 var c, _ref2, _ref3;
904 c = RelationSet.__super__.copy.apply(this, arguments);
905 if (((_ref2 = this.active) != null ? typeof _ref2.ref === "function" ? _ref2.ref() : void 0 : void 0) !== ((_ref3 = c.active) != null ? typeof _ref3.ref === "function" ? _ref3.ref() : void 0 : void 0)) {
906 c["switch"](this.active.ref());
907 }
908 return c;
909 };
910
911 RelationSet.prototype.get = function(name, strict) {
912 var found;
913 if (strict == null) {
914 strict = true;
915 }
916 if ('string' !== typeof name) {
917 name = name.ref();
918 }
919 found = this.relsByName[name];
920 if (strict && !found) {
921 throw new Error("No such relation " + name + " in " + (Object.keys(this.relsByName)));
922 }
923 return found;
924 };
925
926 RelationSet.prototype["switch"] = function(name) {
927 return this.active = this.get(name);
928 };
929
930 RelationSet.prototype.render = function(dialect) {
931 var string;
932 if (string = RelationSet.__super__.render.apply(this, arguments)) {
933 return "FROM " + string;
934 } else {
935 return "";
936 }
937 };
938
939 return RelationSet;
940
941})(NodeSet);
942
943Join = (function(_super) {
944 var JOIN, ON;
945
946 __extends(Join, _super);
947
948 JOIN = new ValueNode('JOIN');
949
950 ON = new ValueNode('ON');
951
952 function Join(type, relation) {
953 var nodes;
954 this.type = type;
955 this.relation = relation;
956 nodes = [this.type, JOIN, this.relation];
957 Join.__super__.constructor.call(this, nodes);
958 }
959
960 Join.prototype.on = function(clause) {
961 if (this.nodes.length < 4) {
962 this.nodes.push(ON);
963 }
964 return this.nodes.push(clause);
965 };
966
967 Join.prototype.ref = function() {
968 return this.relation.ref();
969 };
970
971 Join.prototype.copy = function() {
972 var c, clause, _k, _len2, _ref2;
973 c = new this.constructor(copy(this.type), copy(this.relation));
974 _ref2 = this.nodes.slice(4);
975 for (_k = 0, _len2 = _ref2.length; _k < _len2; _k++) {
976 clause = _ref2[_k];
977 c.on(clause);
978 }
979 return c;
980 };
981
982 return Join;
983
984})(FixedNodeSet);
985
986Where = (function(_super) {
987
988 __extends(Where, _super);
989
990 function Where() {
991 return Where.__super__.constructor.apply(this, arguments);
992 }
993
994 Where.prototype.glue = ' AND ';
995
996 Where.prototype.render = function(dialect) {
997 var string;
998 if (string = Where.__super__.render.apply(this, arguments)) {
999 return "WHERE " + string;
1000 } else {
1001 return "";
1002 }
1003 };
1004
1005 return Where;
1006
1007})(NodeSet);
1008
1009Or = (function(_super) {
1010
1011 __extends(Or, _super);
1012
1013 function Or() {
1014 return Or.__super__.constructor.apply(this, arguments);
1015 }
1016
1017 Or.prototype.glue = ' OR ';
1018
1019 Or.prototype.and = function() {
1020 var args;
1021 args = 1 <= arguments.length ? __slice.call(arguments, 0) : [];
1022 return new And([this].concat(__slice.call(args)));
1023 };
1024
1025 Or.prototype.or = function() {
1026 var arg, args, ret, _k, _len2;
1027 args = 1 <= arguments.length ? __slice.call(arguments, 0) : [];
1028 ret = this.copy();
1029 for (_k = 0, _len2 = args.length; _k < _len2; _k++) {
1030 arg = args[_k];
1031 ret.addNode(arg);
1032 }
1033 return ret;
1034 };
1035
1036 return Or;
1037
1038})(ParenthesizedNodeSet);
1039
1040And = (function(_super) {
1041
1042 __extends(And, _super);
1043
1044 function And() {
1045 return And.__super__.constructor.apply(this, arguments);
1046 }
1047
1048 And.prototype.glue = ' AND ';
1049
1050 And.prototype.and = function() {
1051 var arg, args, ret, _k, _len2;
1052 args = 1 <= arguments.length ? __slice.call(arguments, 0) : [];
1053 ret = this.copy();
1054 for (_k = 0, _len2 = args.length; _k < _len2; _k++) {
1055 arg = args[_k];
1056 ret.addNode(arg);
1057 }
1058 return ret;
1059 };
1060
1061 And.prototype.or = function() {
1062 var args;
1063 args = 1 <= arguments.length ? __slice.call(arguments, 0) : [];
1064 return new Or([this].concat(__slice.call(args)));
1065 };
1066
1067 return And;
1068
1069})(ParenthesizedNodeSet);
1070
1071GroupBy = (function(_super) {
1072
1073 __extends(GroupBy, _super);
1074
1075 function GroupBy() {
1076 return GroupBy.__super__.constructor.apply(this, arguments);
1077 }
1078
1079 GroupBy.prototype.glue = ', ';
1080
1081 GroupBy.prototype.render = function(dialect) {
1082 var string;
1083 if (string = GroupBy.__super__.render.apply(this, arguments)) {
1084 return "GROUP BY " + string;
1085 } else {
1086 return "";
1087 }
1088 };
1089
1090 return GroupBy;
1091
1092})(NodeSet);
1093
1094Having = (function(_super) {
1095
1096 __extends(Having, _super);
1097
1098 function Having() {
1099 return Having.__super__.constructor.apply(this, arguments);
1100 }
1101
1102 Having.prototype.glue = ' AND ';
1103
1104 Having.prototype.render = function(dialect) {
1105 var string;
1106 if (string = Having.__super__.render.apply(this, arguments)) {
1107 return "HAVING " + string;
1108 } else {
1109 return "";
1110 }
1111 };
1112
1113 return Having;
1114
1115})(NodeSet);
1116
1117OrderBy = (function(_super) {
1118
1119 __extends(OrderBy, _super);
1120
1121 function OrderBy(orderings) {
1122 OrderBy.__super__.constructor.call(this, orderings, ', ');
1123 }
1124
1125 OrderBy.prototype.render = function(dialect) {
1126 var string;
1127 if (string = OrderBy.__super__.render.apply(this, arguments)) {
1128 return "ORDER BY " + string;
1129 } else {
1130 return "";
1131 }
1132 };
1133
1134 return OrderBy;
1135
1136})(NodeSet);
1137
1138Ordering = (function(_super) {
1139
1140 __extends(Ordering, _super);
1141
1142 function Ordering(projection, direction) {
1143 if (typeof direction === 'string') {
1144 direction = new ValueNode(direction);
1145 }
1146 Ordering.__super__.constructor.call(this, [projection, direction]);
1147 }
1148
1149 return Ordering;
1150
1151})(FixedNodeSet);
1152
1153Select = (function(_super) {
1154
1155 __extends(Select, _super);
1156
1157 /*
1158 The root node of a SELECT query
1159 */
1160
1161
1162 function Select() {
1163 return Select.__super__.constructor.apply(this, arguments);
1164 }
1165
1166 Select.prefix = 'SELECT ';
1167
1168 Select.structure([['distinct', Distinct], ['projections', SelectColumnSet], ['relations', RelationSet], ['where', Where], ['groupBy', GroupBy], ['having', Having], ['orderBy', OrderBy], ['limit', Limit], ['offset', Offset]]);
1169
1170 Select.prototype.initialize = function(opts) {
1171 this.projections;
1172 if (opts.table) {
1173 return this.relations.addNode(toRelation(opts.table));
1174 }
1175 };
1176
1177 return Select;
1178
1179})(Statement);
1180
1181Update = (function(_super) {
1182 var UpdateSet;
1183
1184 __extends(Update, _super);
1185
1186 /*
1187 The root node of an UPDATE query
1188 */
1189
1190
1191 function Update() {
1192 return Update.__super__.constructor.apply(this, arguments);
1193 }
1194
1195 UpdateSet = (function(_super1) {
1196
1197 __extends(UpdateSet, _super1);
1198
1199 function UpdateSet(nodes) {
1200 UpdateSet.__super__.constructor.call(this, nodes, ', ');
1201 }
1202
1203 UpdateSet.prototype.render = function(dialect) {
1204 var string;
1205 if (string = UpdateSet.__super__.render.apply(this, arguments)) {
1206 return "SET " + string;
1207 } else {
1208 return "";
1209 }
1210 };
1211
1212 return UpdateSet;
1213
1214 })(NodeSet);
1215
1216 Update.prefix = 'UPDATE ';
1217
1218 Update.structure([['relation', Relation], ['updates', UpdateSet], ['orderBy', OrderBy], ['limit', Limit], ['fromList', RelationSet], ['where', Where], ['returning', Returning]]);
1219
1220 Returning.extend(Update);
1221
1222 Update.prototype.initialize = function(opts) {
1223 return this.relation = toRelation(opts.table);
1224 };
1225
1226 return Update;
1227
1228})(Statement);
1229
1230Insert = (function(_super) {
1231 var ColumnList, InsertData, valOrDefault;
1232
1233 __extends(Insert, _super);
1234
1235 /*
1236 The root node of an INSERT query
1237 */
1238
1239
1240 function Insert() {
1241 return Insert.__super__.constructor.apply(this, arguments);
1242 }
1243
1244 InsertData = (function(_super1) {
1245
1246 __extends(InsertData, _super1);
1247
1248 function InsertData() {
1249 return InsertData.__super__.constructor.apply(this, arguments);
1250 }
1251
1252 InsertData.prototype.glue = ', ';
1253
1254 InsertData.prototype.render = function(dialect) {
1255 var string;
1256 if (string = InsertData.__super__.render.apply(this, arguments)) {
1257 return "VALUES " + string;
1258 } else {
1259 return "";
1260 }
1261 };
1262
1263 return InsertData;
1264
1265 })(NodeSet);
1266
1267 Insert.ColumnList = ColumnList = (function(_super1) {
1268
1269 __extends(ColumnList, _super1);
1270
1271 function ColumnList() {
1272 return ColumnList.__super__.constructor.apply(this, arguments);
1273 }
1274
1275 return ColumnList;
1276
1277 })(Tuple);
1278
1279 Insert.prefix = 'INSERT INTO ';
1280
1281 Insert.structure([['relation', Relation], ['columns', ColumnList], ['data', InsertData], ['returning', Returning]]);
1282
1283 Returning.extend(Insert);
1284
1285 Insert.prototype.initialize = function(opts) {
1286 var _ref2;
1287 if (!((_ref2 = opts.fields) != null ? _ref2.length : void 0)) {
1288 throw new Error("Column list is required when constructing an INSERT");
1289 }
1290 this.columns = new ColumnList(opts.fields.map(toField));
1291 return this.relation = toRelation(opts.table);
1292 };
1293
1294 Insert.prototype.addRow = function(row) {
1295 if (this.data instanceof Select) {
1296 throw new Error("Cannot add rows when inserting from a SELECT");
1297 }
1298 if (Array.isArray(row)) {
1299 return this.addRowArray(row);
1300 } else {
1301 return this.addRowObject(row);
1302 }
1303 };
1304
1305 Insert.prototype.addRowArray = function(row) {
1306 var count, message, params, v;
1307 if (!(count = this.columns.nodes.length)) {
1308 throw new Error("Must set column list before inserting arrays");
1309 }
1310 if (row.length !== count) {
1311 message = "Wrong number of values in array, expected " + this.columns.nodes;
1312 throw new Error(message);
1313 }
1314 params = (function() {
1315 var _k, _len2, _results;
1316 _results = [];
1317 for (_k = 0, _len2 = row.length; _k < _len2; _k++) {
1318 v = row[_k];
1319 if (v instanceof Node) {
1320 _results.push(v);
1321 } else {
1322 _results.push(new Parameter(v));
1323 }
1324 }
1325 return _results;
1326 })();
1327 return this.data.addNode(new Tuple(params));
1328 };
1329
1330 Insert.prototype.addRowObject = function(row) {
1331 /*
1332 Add a row from an object. This will set the column list of the query if it
1333 isn't set yet. If it `is` set, then only keys matching the existing column
1334 list will be inserted.
1335 */
1336 return this.addRowArray(this.columns.nodes.map(valOrDefault.bind(row)));
1337 };
1338
1339 valOrDefault = function(field) {
1340 var key;
1341 key = field.value;
1342 if (this.hasOwnProperty(key)) {
1343 return this[key];
1344 } else {
1345 return CONST_NODES.DEFAULT;
1346 }
1347 };
1348
1349 Insert.prototype.from = function(query) {
1350 if (!(query instanceof Select)) {
1351 throw new Error("Can only insert from a SELECT");
1352 }
1353 return this.data = query;
1354 };
1355
1356 return Insert;
1357
1358})(Statement);
1359
1360Delete = (function(_super) {
1361
1362 __extends(Delete, _super);
1363
1364 /*
1365 The root node of a DELETE query
1366 */
1367
1368
1369 function Delete() {
1370 return Delete.__super__.constructor.apply(this, arguments);
1371 }
1372
1373 Delete.prefix = 'DELETE ';
1374
1375 Delete.structure([['relations', RelationSet], ['where', Where], ['orderBy', OrderBy], ['limit', Limit], ['returning', Returning]]);
1376
1377 Returning.extend(Delete);
1378
1379 Delete.prototype.initialize = function(opts) {
1380 return this.relations.addNode(toRelation(opts.table));
1381 };
1382
1383 return Delete;
1384
1385})(Statement);
1386
1387ComparableMixin = (function() {
1388
1389 function ComparableMixin() {}
1390
1391 /*
1392 A mixin that adds comparison methods to a class. Each of these comparison
1393 methods will yield a new AST node comparing the invocant to the argument.
1394 */
1395
1396
1397 ComparableMixin.prototype.eq = function(other) {
1398 /* ``this = other``
1399 */
1400 return new Binary(this, '=', toParam(other));
1401 };
1402
1403 ComparableMixin.prototype.ne = function(other) {
1404 /* ``this <> other``
1405 */
1406 return new Binary(this, '<>', toParam(other));
1407 };
1408
1409 ComparableMixin.prototype.gt = function(other) {
1410 /* ``this > other``
1411 */
1412 return new Binary(this, '>', toParam(other));
1413 };
1414
1415 ComparableMixin.prototype.lt = function(other) {
1416 /* ``this < other``
1417 */
1418 return new Binary(this, '<', toParam(other));
1419 };
1420
1421 ComparableMixin.prototype.lte = function(other) {
1422 /* ``this <= other``
1423 */
1424 return new Binary(this, '<=', toParam(other));
1425 };
1426
1427 ComparableMixin.prototype.gte = function(other) {
1428 /* ``this >= other``
1429 */
1430 return new Binary(this, '>=', toParam(other));
1431 };
1432
1433 ComparableMixin.prototype.compare = function(op, other) {
1434 /* ``this op other`` **DANGER** `op` is **NOT** escaped!
1435 */
1436 return new Binary(this, op, toParam(other));
1437 };
1438
1439 return ComparableMixin;
1440
1441})();
1442
1443_ref2 = ComparableMixin.prototype;
1444for (k in _ref2) {
1445 v = _ref2[k];
1446 TextNode.prototype[k] = v;
1447 SqlFunction.prototype[k] = v;
1448 SqlFunction.Alias.prototype[k] = v;
1449 Column.prototype[k] = v;
1450 Column.Alias.prototype[k] = v;
1451 Tuple.prototype[k] = v;
1452}
1453
1454toParam = function(it) {
1455 /*
1456 Return a Node that can be used as a parameter.
1457
1458 * :class:`queries/select::SelectQuery` instances will be treated as
1459 un-named sub queries,
1460 * Node instances will be returned unchanged.
1461 * Arrays will be turned into a :class:`nodes::Tuple` instance.
1462
1463 All other types will be wrapped in a :class:`nodes::Parameter` instance.
1464 */
1465
1466 var SelectQuery;
1467 SelectQuery = require('./queries/select');
1468 if ((it != null ? it.constructor : void 0) === SelectQuery) {
1469 return new Tuple([it.q]);
1470 } else if (it instanceof Node) {
1471 return it;
1472 } else if (Array.isArray(it)) {
1473 return new Tuple(it.map(toParam));
1474 } else {
1475 return new Parameter(it);
1476 }
1477};
1478
1479toRelation = function(it) {
1480 /*
1481 Transform ``it`` into a :class:`nodes::Relation` instance.
1482
1483 This accepts `strings, `Relation`` and ``Alias`` instances, and objects with
1484 a single key-value pair, which will be turned into an ``Alias`` instance.
1485
1486 Examples::
1487
1488 toRelation('table1') == new Relation('table1')
1489 toRelation(t1: 'table1') == new Alias(new Relation('table1'), 't1')
1490
1491 **Throws Errors** if the input is not valid.
1492 */
1493
1494 var alias;
1495 switch (it.constructor) {
1496 case Relation:
1497 case Relation.Alias:
1498 case SqlFunction:
1499 case SqlFunction.Alias:
1500 return it;
1501 case String:
1502 return new Relation(it);
1503 case Object:
1504 if (alias = getAlias(it)) {
1505 return toRelation(it[alias]).as(alias);
1506 } else {
1507 throw new Error("Can't make relation out of " + it);
1508 }
1509 break;
1510 default:
1511 throw new Error("Can't make relation out of " + it);
1512 }
1513};
1514
1515toField = function(it) {
1516 if (typeof it === 'string') {
1517 return new Field(it);
1518 } else if (it instanceof Field) {
1519 return it;
1520 } else {
1521 throw new Error("Can't make a field out of " + it);
1522 }
1523};
1524
1525toColumn = function(relation, field) {
1526 /*
1527 Create a new :class:`nodes::Column` instance.
1528
1529 The first argument is optional and specifies a table (or alias) name.
1530 Alternatively, you can specify the relation name and field with a single
1531 dot-separated string::
1532
1533 toColumn('departments.name') == toColumn('departments', 'name')
1534
1535 Either argument can be an pre-constructed node object (of the correct type).
1536 */
1537
1538 var parts;
1539 if (field != null) {
1540 return new Column(toRelation(relation), toField(field));
1541 } else if (typeof relation === 'string') {
1542 parts = relation.split('.');
1543 if (parts.length === 2) {
1544 return new Column(toRelation(parts[0]), toField(parts[1]));
1545 }
1546 }
1547 throw new Error("Can't make projection from object: " + relation);
1548};
1549
1550toProjection = toColumn;
1551
1552sqlFunction = function(name, args) {
1553 /*
1554 Create a new SQL function call node. For example::
1555
1556 count = sqlFunction('count', [new ValueNode('*')])
1557 */
1558 return new SqlFunction(name, new Tuple(args.map(toParam)));
1559};
1560
1561getAlias = function(o) {
1562 /*
1563 Check if ``o`` is an object literal representing an alias, and return the
1564 alias name if it is.
1565 */
1566
1567 var keys;
1568 if ('object' === typeof o) {
1569 keys = Object.keys(o);
1570 if (keys.length === 1) {
1571 return keys[0];
1572 }
1573 }
1574 return null;
1575};
1576
1577text = function(rawSQL, bindVals) {
1578 /*
1579 Construct a node with a raw SQL string and (optionally) parameters. Useful for
1580 when you want to construct a query that is difficult or impossible with the
1581 normal APIs. [#]_
1582
1583 To use bound parameters in the SQL string, use ``$`` prefixed names, and
1584 pass a ``bindVals`` argument with corresponding property names. For example,
1585 :meth:`~queries/sud::SUDQuery.where` doesn't (currently) support the SQL
1586 ``BETWEEN`` operator, but if you needed it, you could use ``text``::
1587
1588 function peopleInWeightRange (min, max, callback) {
1589 return select('people')
1590 .where(text("weight BETWEEN $min AND $max", {min: min, max: max}))
1591 .execute(callback)
1592 }
1593
1594 Because javascript doesn't distinguish between array indexing and property
1595 access, it can be more clear to use numbered parameters for such short
1596 snippets::
1597
1598 function peopleInWeightRange (min, max, callback) {
1599 return select('people')
1600 .where(text("weight BETWEEN $0 AND $1", [min, max]))
1601 .execute(callback)
1602 }
1603
1604 If you find yourself using this function often, please consider opening an
1605 issue on `Github <https://github.com/BetSmartMedia/gesundheit>`_ with details
1606 on your use case so gesundheit can support it more elegantly.
1607 */
1608 return new TextNode(rawSQL, bindVals);
1609};
1610
1611binaryOp = function(left, op, right) {
1612 /*
1613 Create a new :class:`nodes::Binary` node::
1614
1615 binaryOp('hstore_column', '->', toParam(y))
1616 # hstore_column -> ?
1617
1618 This is for special cases, normally you want to use the methods from
1619 :class:`nodes::ComparableMixin`.
1620 */
1621 return new Binary(left, op, right);
1622};
1623
1624Prefixed = (function(_super) {
1625
1626 __extends(Prefixed, _super);
1627
1628 function Prefixed(prefix, node) {
1629 this.prefix = prefix;
1630 this.node = node;
1631 }
1632
1633 Prefixed.prototype.render = function() {
1634 return this.prefix + this.node.render.apply(this.node, arguments);
1635 };
1636
1637 Prefixed.prototype.params = function() {
1638 var _base;
1639 return (typeof (_base = this.node).params === "function" ? _base.params() : void 0) || [];
1640 };
1641
1642 return Prefixed;
1643
1644})(ValueNode);
1645
1646exists = function(subquery) {
1647 /* Create an ``EXISTS (<subquery>)`` node for `where`
1648 */
1649 return new Prefixed('EXISTS ', new Tuple([subquery.q || subquery]));
1650};
1651
1652notExists = function(subquery) {
1653 /* Create a ``NOT EXISTS (<subquery>)`` node for `where`
1654 */
1655 return new Prefixed('NOT EXISTS ', new Tuple([subquery.q || subquery]));
1656};
1657
1658tuple = function(input) {
1659 /*
1660 Create a new Tuple from an array of nodes. Any item in the array that is
1661 **not** an `instanceof Node` will be turned into a parameter with
1662 :func:`nodes::toParam`.
1663 */
1664 return new Tuple(input.map(toParam));
1665};
1666
1667module.exports = {
1668 CONST_NODES: CONST_NODES,
1669 JOIN_TYPES: JOIN_TYPES,
1670 binaryOp: binaryOp,
1671 exists: exists,
1672 getAlias: getAlias,
1673 notExists: notExists,
1674 sqlFunction: sqlFunction,
1675 text: text,
1676 toField: toField,
1677 toParam: toParam,
1678 toColumn: toColumn,
1679 toProjection: toProjection,
1680 toRelation: toRelation,
1681 tuple: tuple,
1682 Node: Node,
1683 ValueNode: ValueNode,
1684 IntegerNode: IntegerNode,
1685 Identifier: Identifier,
1686 JoinType: JoinType,
1687 NodeSet: NodeSet,
1688 FixedNodeSet: FixedNodeSet,
1689 Statement: Statement,
1690 ParenthesizedNodeSet: ParenthesizedNodeSet,
1691 TextNode: TextNode,
1692 SqlFunction: SqlFunction,
1693 Parameter: Parameter,
1694 Relation: Relation,
1695 Field: Field,
1696 Column: Column,
1697 Limit: Limit,
1698 Offset: Offset,
1699 Binary: Binary,
1700 Tuple: Tuple,
1701 ColumnSet: ColumnSet,
1702 Returning: Returning,
1703 Distinct: Distinct,
1704 SelectColumnSet: SelectColumnSet,
1705 RelationSet: RelationSet,
1706 Join: Join,
1707 Where: Where,
1708 Or: Or,
1709 And: And,
1710 GroupBy: GroupBy,
1711 OrderBy: OrderBy,
1712 Ordering: Ordering,
1713 Select: Select,
1714 Update: Update,
1715 Insert: Insert,
1716 Delete: Delete,
1717 ComparableMixin: ComparableMixin
1718};
1719
1720copy = function(it) {
1721 var c, _results;
1722 if (!it) {
1723 return it;
1724 }
1725 switch (it.constructor) {
1726 case String:
1727 case Number:
1728 case Boolean:
1729 return it;
1730 case Array:
1731 return it.map(copy);
1732 case Object:
1733 c = {};
1734 _results = [];
1735 for (k in it) {
1736 v = it[k];
1737 _results.push(c[k] = copy(v));
1738 }
1739 return _results;
1740 break;
1741 default:
1742 if (it.copy != null) {
1743 return it.copy();
1744 } else {
1745 throw new Error("Don't know how to copy " + it);
1746 }
1747 }
1748};