UNPKG

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