blob: ae8fae98bf357139d61f026cb9f44f19ed563f98 [file] [log] [blame]
genia.likes.science@gmail.com2c678ea2013-06-05 19:49:24 -07001// AsterixSDK
2// Core Object for REST API communication
3// Handles callbacks to client applications, communication to REST API, and
4// endpoint selection. Initializes an RPC consumer object.
5//
6// Usage:
7// var a = new AsterixSDK();
8function AsterixSDK() {
9
10 // Asterix SDK request handler initialization
11 // TODO Depending on configuration, may need multiples of these...
12 this.xhr = new easyXDM.Rpc({
13 remote: "http://localhost:19002/sdk/static/client.html"
14 }, {
15 remote: {
16 post: {}
17 }
18 });
19
20
21 // Asterix SDK => send
22 // Posts a message containing an API endpoint, json data,
23 // and a UI callback function.
24 //
25 // Usage:
26 // var a = AsterixSDK();
27 // a.send(
28 // http://localhost:19002/XYZ,
29 // json
30 // );
31 myThis = this;
32 this.send = function (endpoint, data, extras) {
33 this.extras = extras;
34 this.xhr.post(
35 endpoint,
36 data,
37 this.branch
38 );
39 };
40
41
42 // Set callback functions
43 this.callbacks = {};
44
45 this.callback = function(fn, mode) {
46 if (mode == "sync" || mode == "async") {
47 this.callbacks[mode] = fn;
48 }
49
50 return this;
51 };
52
53
54 // Set branching method on send
55 this.branch = function(response) {
56 if (response && response["error-code"]) {
57
58 alert("Error [Code" + response["error-code"][0] + "]: " + response["error-code"][1]);
59
60 } else if (response && response["results"]) {
61 var fn_callback = myThis.callbacks["sync"];
62 fn_callback(response, myThis.extras);
63
64 } else if (response["handle"]) {
65
66 var fn_callback = this.callbacks["async"];
67 fn_callback(response, extra);
68
69 } else if (response["status"]) {
70
71 var fn_callback = this.callbacks["sync"];
72 fn_callback(response, extra);
73 }
74 }
75
76
77 // Asterix SDK => requestHandler
78 // Handlers remote requests to Asterix REST API
79 // using the easyXDM RPC protocol
80 // Usually should only be called by client side, could be overridden
81 // TODO Get rid of jQuery ajax notation in favor of xmlhttprequest pure js
82 this.requestHandler = function() {
83 var rpc = new easyXDM.Rpc({}, {
84 local: {
85 post: {
86 method: function(url, data, fn, fnError){
87 $.ajax({
88 type : 'GET',
89 url : url,
90 data : data,
91 dataType : "json",
92 success : function(res) {
93 fn(res);
94 }
95 });
96 }
97 }
98 }
99 });
100 }
101}
102
103
genia.likes.science@gmail.com90d08722013-05-28 04:40:12 -0700104// Temporary AsterixExpression Placeholder
105function AExpression () {
genia.likes.science@gmail.com512454d2013-05-28 03:32:20 -0700106 this._properties = {};
107 this._success = function() {};
108
genia.likes.science@gmail.com512454d2013-05-28 03:32:20 -0700109 return this;
110}
111
genia.likes.science@gmail.com90d08722013-05-28 04:40:12 -0700112
113AExpression.prototype.bind = function(options) {
genia.likes.science@gmail.com512454d2013-05-28 03:32:20 -0700114 var options = options || {};
115
genia.likes.science@gmail.com512454d2013-05-28 03:32:20 -0700116 if (options.hasOwnProperty("dataverse")) {
117 this._properties["dataverse"] = options["dataverse"];
118 }
119
120 if (options.hasOwnProperty("success")) {
121 this._success = options["success"];
122 }
genia.likes.science@gmail.com38612632013-05-28 13:11:52 -0700123
124 if (options.hasOwnProperty("return")) {
125 this._properties["return"] = " return " + options["return"].val();
126 }
genia.likes.science@gmail.com512454d2013-05-28 03:32:20 -0700127};
128
genia.likes.science@gmail.com512454d2013-05-28 03:32:20 -0700129
genia.likes.science@gmail.com90d08722013-05-28 04:40:12 -0700130AExpression.prototype.run = function() {
genia.likes.science@gmail.com512454d2013-05-28 03:32:20 -0700131 var success_fn = this._success;
132
133 $.ajax({
134 type : 'GET',
genia.likes.science@gmail.com2c678ea2013-06-05 19:49:24 -0700135 url : "http://localhost:19002/query",
genia.likes.science@gmail.com512454d2013-05-28 03:32:20 -0700136 data : {"query" : this.val()},
137 dataType : "json",
138 success : function(data) {
139 success_fn(data);
140 }
141 });
142
143 return this;
genia.likes.science@gmail.com90d08722013-05-28 04:40:12 -0700144};
145
146
147AExpression.prototype.val = function() {
148
genia.likes.science@gmail.com2ba32242013-05-31 03:10:48 -0700149 var value = "";
150
genia.likes.science@gmail.com90d08722013-05-28 04:40:12 -0700151 // If there is a dataverse defined, provide it.
152 if (this._properties.hasOwnProperty("dataverse")) {
genia.likes.science@gmail.com2ba32242013-05-31 03:10:48 -0700153 value += "use dataverse " + this._properties["dataverse"] + ";\n";
154 };
155
156 if (this._properties.hasOwnProperty("value")) {
157 value += this._properties["value"];
genia.likes.science@gmail.com90d08722013-05-28 04:40:12 -0700158 }
genia.likes.science@gmail.com2ba32242013-05-31 03:10:48 -0700159
160 return value;
genia.likes.science@gmail.com38612632013-05-28 13:11:52 -0700161};
162
genia.likes.science@gmail.com2ba32242013-05-31 03:10:48 -0700163// @param expressionValue [String]
164AExpression.prototype.set = function(expressionValue) {
165 this._properties["value"] = expressionValue;
166 return this;
genia.likes.science@gmail.com38612632013-05-28 13:11:52 -0700167};
168
genia.likes.science@gmail.com73dcc702013-05-28 04:21:28 -0700169
genia.likes.science@gmail.com90d08722013-05-28 04:40:12 -0700170AExpression.prototype.error = function(msg) {
171 return "Asterix FunctionExpression Error: " + msg;
172};
173
174
175// FunctionExpression
176// Parent: AsterixExpression
177//
178// @param options [Various],
179// @key function [String], a function to be applid to the expression
180// @key expression [AsterixExpression or AsterixClause] an AsterixExpression/Clause to which the fn will be applied
181function FunctionExpression(options) {
182
183 // Initialize superclass
184 AExpression.call(this);
185
186 // Possible to initialize a function epxression without inputs, or with them
187 this.bind(options);
188
189 // Return object
190 return this;
191}
192
193
194FunctionExpression.prototype = Object.create(AExpression.prototype);
195FunctionExpression.prototype.constructor = FunctionExpression;
196
197
198FunctionExpression.prototype.bind = function(options) {
199
200 AExpression.prototype.bind.call(this, options);
201
202 var options = options || {};
203
204 if (options.hasOwnProperty("function")) {
205 this._properties["function"] = options["function"];
206 }
207
208 if (options.hasOwnProperty("expression")) {
209 this._properties["expression"] = options["expression"];
210 }
211
212 return this;
213};
214
215FunctionExpression.prototype.val = function () {
genia.likes.science@gmail.com2ba32242013-05-31 03:10:48 -0700216 return this._properties["function"] + "(" + this._properties["expression"].val() + ")";
genia.likes.science@gmail.com90d08722013-05-28 04:40:12 -0700217};
218
genia.likes.science@gmail.com73dcc702013-05-28 04:21:28 -0700219
genia.likes.science@gmail.com73dcc702013-05-28 04:21:28 -0700220// FLWOGR ::= ( ForClause | LetClause ) ( Clause )* "return" Expression
221// Clause ::= ForClause | LetClause | WhereClause | OrderbyClause | GroupClause | LimitClause | DistinctClause
genia.likes.science@gmail.com38612632013-05-28 13:11:52 -0700222//
genia.likes.science@gmail.com73dcc702013-05-28 04:21:28 -0700223// WhereClause ::= "where" Expression
224// OrderbyClause ::= "order" "by" Expression ( ( "asc" ) | ( "desc" ) )? ( "," Expression ( ( "asc" ) | ( "desc" ) )? )*
genia.likes.science@gmail.comb4cb6b32013-05-29 04:30:38 -0700225//
genia.likes.science@gmail.com73dcc702013-05-28 04:21:28 -0700226// GroupClause ::= "group" "by" ( Variable ":=" )? Expression ( "," ( Variable ":=" )? Expression )* ( "decor" Variable ":=" Expression ( "," "decor" Variable ":=" Expression )* )? "with" VariableRef ( "," VariableRef )*
227// LimitClause ::= "limit" Expression ( "offset" Expression )?
228// DistinctClause ::= "distinct" "by" Expression ( "," Expression )*
genia.likes.science@gmail.com73dcc702013-05-28 04:21:28 -0700229
230
genia.likes.science@gmail.com38612632013-05-28 13:11:52 -0700231// FLWOGRExpression
genia.likes.science@gmail.com90d08722013-05-28 04:40:12 -0700232//
233// FLWOGRExpression ::= ( ForClause | LetClause ) ( Clause )* "return" Expression
genia.likes.science@gmail.com38612632013-05-28 13:11:52 -0700234function FLWOGRExpression (options) {
235 // Initialize superclass
236 AExpression.call(this);
genia.likes.science@gmail.com90d08722013-05-28 04:40:12 -0700237
genia.likes.science@gmail.com38612632013-05-28 13:11:52 -0700238 this._properties["clauses"] = [];
genia.likes.science@gmail.com79e603a2013-05-31 10:03:23 -0700239 this._properties["minSize"] = 0;
genia.likes.science@gmail.com38612632013-05-28 13:11:52 -0700240
241 // Bind options and return
242 this.bind(options);
243 return this;
genia.likes.science@gmail.com90d08722013-05-28 04:40:12 -0700244}
245
246
genia.likes.science@gmail.com38612632013-05-28 13:11:52 -0700247FLWOGRExpression.prototype = Object.create(AExpression.prototype);
248FLWOGRExpression.prototype.constructor = FLWOGRExpression;
249
250
251FLWOGRExpression.prototype.bind = function(options) {
252 AExpression.prototype.bind.call(this, options);
253
254 var options = options || {};
255
genia.likes.science@gmail.com79e603a2013-05-31 10:03:23 -0700256 if (options instanceof SetStatement) {
257 this._properties["clauses"].push(options);
258 this._properties["minSize"] += 1;
259 }
260
261 if (this._properties["clauses"].length <= this._properties["minSize"]) {
genia.likes.science@gmail.com38612632013-05-28 13:11:52 -0700262 // Needs to start with for or let clause
263 if (options instanceof ForClause || options instanceof LetClause) {
264 this._properties["clauses"].push(options);
265 }
266 } else {
267 if (options instanceof AQLClause) {
268 this._properties["clauses"].push(options);
269 }
270 }
271
272 return this;
273};
274
275
276FLWOGRExpression.prototype.val = function() {
277 var value = AExpression.prototype.val.call(this);
278
genia.likes.science@gmail.com2ba32242013-05-31 03:10:48 -0700279 var clauseValues = [];
genia.likes.science@gmail.com38612632013-05-28 13:11:52 -0700280 for (var c in this._properties["clauses"]) {
genia.likes.science@gmail.com2ba32242013-05-31 03:10:48 -0700281 clauseValues.push(this._properties["clauses"][c].val());
genia.likes.science@gmail.com38612632013-05-28 13:11:52 -0700282 }
283
genia.likes.science@gmail.com79e603a2013-05-31 10:03:23 -0700284 return value + clauseValues.join("\n");// + ";";
genia.likes.science@gmail.com38612632013-05-28 13:11:52 -0700285};
286
genia.likes.science@gmail.com2ba32242013-05-31 03:10:48 -0700287
genia.likes.science@gmail.com73dcc702013-05-28 04:21:28 -0700288// AQLClause
289//
290// Base Clause ::= ForClause | LetClause | WhereClause | OrderbyClause | GroupClause | LimitClause | DistinctClause
291function AQLClause() {
292 this._properties = {};
293 this._properties["clause"] = "";
294}
295
296AQLClause.prototype.val = function() {
297 var value = this._properties["clause"];
298
299 if (this._properties.hasOwnProperty("return")) {
300 value += " return " + this._properties["return"].val();
301 }
302
303 return value;
304};
305
306AQLClause.prototype.bind = function(options) {
307 var options = options || {};
308
309 if (options.hasOwnProperty("return")) {
310 this._properties["return"] = options["return"];
311 }
312
313 return this;
314};
315
genia.likes.science@gmail.com39578302013-05-31 04:42:26 -0700316AQLClause.prototype.set = function(value) {
317 this._properties["clause"] = value;
318 return this;
319};
320
genia.likes.science@gmail.com73dcc702013-05-28 04:21:28 -0700321
322// ForClause
323//
324// Grammar:
325// "for" Variable ( "at" Variable )? "in" ( Expression )
326//
327// @param for_variable [String], REQUIRED, first variable in clause
328// @param at_variable [String], NOT REQUIRED, first variable in clause
329// @param expression [AsterixExpression], REQUIRED, expression to evaluate
330//
331// TODO Error Checking
332function ForClause(for_variable, at_variable, expression) {
333 AQLClause.call(this);
334
335 // at_variable is optional, check if defined
336 var at = typeof at_variable ? at_variable : null;
337
338 // Prepare clause
genia.likes.science@gmail.com2c678ea2013-06-05 19:49:24 -0700339 this._properties["clause"] = "for " + for_variable;
genia.likes.science@gmail.com73dcc702013-05-28 04:21:28 -0700340 if (at != null) {
genia.likes.science@gmail.com2c678ea2013-06-05 19:49:24 -0700341 this._properties["clause"] += " at " + at_variable;
genia.likes.science@gmail.com73dcc702013-05-28 04:21:28 -0700342 }
343 this._properties["clause"] += " in " + expression.val();
344 return this;
345}
346
347ForClause.prototype = Object.create(AQLClause.prototype);
348ForClause.prototype.constructor = ForClause;
genia.likes.science@gmail.com38612632013-05-28 13:11:52 -0700349
350
351// LetClause
352//
353// Grammar:
354// LetClause ::= "let" Variable ":=" Expression
355//
356// @param let_variable [String]
357// @param expression [AExpression]
358//
359// TODO Vigorous error checking
360function LetClause(let_variable, expression) {
361 AQLClause.call(this);
362
363 this._properties["clause"] = "let $" + let_variable + " := ";
364 this._properties["clause"] += expression.val();
365
366 return this;
367}
368
369LetClause.prototype = Object.create(AQLClause.prototype);
370LetClause.prototype.constructor = LetClause;
371
372
genia.likes.science@gmail.com5ca104c2013-05-29 05:39:26 -0700373// ReturnClause
374//
375// Grammar:
376// return [AQLExpression]
377function ReturnClause(expression) {
378 AQLClause.call(this);
379
380 this._properties["clause"] = "return ";
genia.likes.science@gmail.com79e603a2013-05-31 10:03:23 -0700381 if (expression instanceof AExpression || expression instanceof AQLClause) {
genia.likes.science@gmail.com5ca104c2013-05-29 05:39:26 -0700382 this._properties["clause"] += expression.val();
genia.likes.science@gmail.com2ba32242013-05-31 03:10:48 -0700383 } else if ( Object.getPrototypeOf( expression ) === Object.prototype ) {
384
385 this._properties["clause"] += "{";
386 var returnStatements = [];
387 for (returnValue in expression) {
388
389 if (expression[returnValue] instanceof AExpression) {
genia.likes.science@gmail.comfba7cc82013-05-31 04:04:08 -0700390 returnStatements.push('"' + returnValue + '" ' + " : " + expression[returnValue].val());
genia.likes.science@gmail.com2ba32242013-05-31 03:10:48 -0700391 } else if (typeof expression[returnValue] == "string") {
genia.likes.science@gmail.comfba7cc82013-05-31 04:04:08 -0700392 returnStatements.push('"' + returnValue + '" ' + " : " + expression[returnValue]);
genia.likes.science@gmail.com2ba32242013-05-31 03:10:48 -0700393 }
394 }
395 this._properties["clause"] += returnStatements.join(",\n");
396 this._properties["clause"] += "}";
397
genia.likes.science@gmail.com5ca104c2013-05-29 05:39:26 -0700398 } else {
genia.likes.science@gmail.com44ff94a2013-05-31 11:09:34 -0700399 this._properties["clause"] += new AExpression().set(expression).val();
genia.likes.science@gmail.com5ca104c2013-05-29 05:39:26 -0700400 }
401
402 return this;
403}
404
405ReturnClause.prototype = Object.create(AQLClause.prototype);
406ReturnClause.prototype.constructor = ReturnClause;
407
genia.likes.science@gmail.com2ba32242013-05-31 03:10:48 -0700408ReturnClause.prototype.val = function () {
409 return this._properties["clause"];
410};
411
412
genia.likes.science@gmail.com38612632013-05-28 13:11:52 -0700413// WhereClause
414//
415// Grammar:
416// ::= "where" Expression
417//
418// @param expression [BooleanExpression], pushes this expression onto the stack
genia.likes.science@gmail.com38612632013-05-28 13:11:52 -0700419function WhereClause(expression) {
420 AQLClause.call(this);
421
422 this._properties["stack"] = [];
423
424 this.bind(expression);
425
426 return this;
427}
428
429
430WhereClause.prototype = Object.create(AQLClause.prototype);
431WhereClause.prototype.constructor = WhereClause;
432
433
434WhereClause.prototype.bind = function(expression) {
genia.likes.science@gmail.com64ca88e2013-05-31 10:40:39 -0700435 if (expression instanceof AExpression) {
genia.likes.science@gmail.com38612632013-05-28 13:11:52 -0700436 this._properties["stack"].push(expression);
437 }
438};
439
440
441WhereClause.prototype.val = function() {
442 var value = "where ";
443
444 var count = this._properties["stack"].length - 1;
445 while (count >= 0) {
446 value += this._properties["stack"][count].val() + " ";
447 count -= 1;
448 }
449
450 return value;
genia.likes.science@gmail.com64ca88e2013-05-31 10:40:39 -0700451};
genia.likes.science@gmail.com38612632013-05-28 13:11:52 -0700452
453
genia.likes.science@gmail.com2ba32242013-05-31 03:10:48 -0700454// LimitClause
455// Grammar:
456// LimitClause ::= "limit" Expression ( "offset" Expression )?
457//
458// @param limitExpression [REQUIRED, AQLExpression]
459// @param offsetExpression [OPTIONAL, AQLExpression]
460function LimitClause(limitExpression, offsetExpression) {
461
462 AQLClause.call(this);
463
464 // limitExpression required
465 this._properties["clause"] = "limit " + limitExpression.val();
466
467 // Optional: Offset
468 var offset = typeof offsetExpression ? offsetExpression : null;
469 if (offset != null) {
470 this._properties["clause"] += " offset " + offsetExpression.val();
471 }
472
473 return this;
474}
475
476LimitClause.prototype = Object.create(AQLClause.prototype);
477LimitClause.prototype.constructor = LimitClause;
478
479
480// OrderbyClause
481//
482// Grammar:
483// OrderbyClause ::= "order" "by" Expression ( ( "asc" ) | ( "desc" ) )? ( "," Expression ( ( "asc" ) | ( "desc" ) )? )*
484//
485// @params AQLExpressions and asc/desc strings, in any quantity. At least one required.
486function OrderbyClause() {
487
488 AQLClause.call(this);
489
490 // At least one argument expression is required, and first should be expression
491 if (arguments.length == 0 || !(arguments[0] instanceof AExpression)) {
492 // TODO Not sure which error to throw for an empty OrderBy but this should fail.
493 alert("Order By Error");
494 this._properties["clause"] = null;
495 return this;
496 }
497
498 var expc = 0;
499 var expressions = [];
500
501 while (expc < arguments.length) {
502
503 var expression = "";
504
505 if (arguments[expc] instanceof AExpression) {
506 expression += arguments[expc].val();
507 }
508
509 var next = expc + 1;
510 if (next < arguments.length && (arguments[next] == "asc" || arguments[next] == "desc")) {
511 expc++;
512 expression += " " + arguments[expc];
513 }
514
515 expressions.push(expression);
516
517 expc++;
518 }
519
520 this._properties["clause"] = "order by " + expressions.join(", ");
521 return this;
522}
523
524OrderbyClause.prototype = Object.create(AQLClause.prototype);
525OrderbyClause.prototype.constructor = OrderbyClause;
526
527
genia.likes.science@gmail.com6e392912013-05-31 03:46:59 -0700528// GroupClause
529//
530// Grammar:
531// GroupClause ::= "group" "by" ( Variable ":=" )? Expression ( "," ( Variable ":=" )? Expression )* ( "decor" Variable ":=" Expression ( "," "decor" Variable ":=" Expression )* )? "with" VariableRef ( "," VariableRef )*
532function GroupClause() {
533 AQLClause.call(this);
534
535 if (arguments.length == 0) {
536 // TODO Not sure which error to throw for an empty GroupBy but this should fail.
537 alert("Group Error");
538 this._properties["clause"] = null;
539 return this;
540 }
541
542 var expc = 0;
543 var expressions = [];
544 var variableRefs = [];
545 var isDecor = false;
546
547 while (expc < arguments.length) {
548
549 if (arguments[expc] instanceof AExpression) {
550
551 isDecor = false;
552 expressions.push(arguments[expc].val());
553
554 } else if (typeof arguments[expc] == "string") {
555
556 // Special keywords, decor & with
557 if (arguments[expc] == "decor") {
558 isDecor = true;
559 } else if (arguments[expc] == "with") {
560 isDecor = false;
561 expc++;
562 while (expc < arguments.length) {
563 variableRefs.push("$" + arguments[expc]);
564 expc++;
565 }
566
567 // Variables and variable refs
568 } else {
569
570 var nextc = expc + 1;
571 var expression = "";
572
573 if (isDecor) {
574 expression += "decor ";
575 isDecor = false;
576 }
577
578 expression += "$" + arguments[expc] + " := " + arguments[nextc].val();
579 expressions.push(expression);
580 expc++;
581 }
582 }
583
584 expc++;
585 }
586
587 this._properties["clause"] = "group by " + expressions.join(", ") + " with " + variableRefs.join(", ");
588 return this;
589}
590
591GroupClause.prototype = Object.create(AQLClause.prototype);
592GroupClause.prototype.constructor = GroupClause;
593
genia.likes.science@gmail.com38612632013-05-28 13:11:52 -0700594// BooleanExpression
595//
596// TODO
597function BooleanExpression(expression) {
598 this.value = expression;
genia.likes.science@gmail.com6fd7b2e2013-05-31 00:40:28 -0700599 alert("Debugging Bool: " + arguments.length + " " + expression);
genia.likes.science@gmail.com38612632013-05-28 13:11:52 -0700600}
601
602BooleanExpression.prototype.val = function() {
603 return this.value;
604}
genia.likes.science@gmail.com79e603a2013-05-31 10:03:23 -0700605
606
607// SetStatement
608//
609// Grammar
610// "set" Identifier StringLiteral
611function SetStatement (identifier, stringLiteral) {
612 AExpression.call(this);
613
614 var statement = "set " + identifier + ' "' + stringLiteral + '";';
615
616 AExpression.prototype.set.call(this, statement);
617
618 return this;
619}
620
621SetStatement.prototype = Object.create(AExpression.prototype);
622SetStatement.prototype.constructor = SetStatement;
genia.likes.science@gmail.come34c57b2013-05-31 10:15:49 -0700623
624
625// Quantified Expression
626//
627// Grammar
628// QuantifiedExpression ::= ( ( "some" ) | ( "every" ) ) Variable "in" Expression ( "," Variable "in" Expression )* "satisfies" Expression
629//
630// @param String some/every
631// @param [AExpression]
632// @param [Aexpression] satisfiesExpression
633function QuantifiedExpression (keyword, expressions, satisfiesExpression) {
634 AExpression.call(this);
635
636 var expression = keyword + " ";
637 var varsInExpressions = [];
638
639 for (var varInExpression in expressions) {
640 varsInExpressions.push(varInExpression + " in " + expressions[varInExpression].val());
641 }
642 expression += varsInExpressions.join(", ") + " satisfies " + satisfiesExpression.val();
643
644 AExpression.prototype.set.call(this, expression);
645
646 return this;
647}
648
649QuantifiedExpression.prototype = Object.create(AExpression.prototype);
650QuantifiedExpression.prototype.constructor = QuantifiedExpression;
genia.likes.science@gmail.com64ca88e2013-05-31 10:40:39 -0700651
652QuantifiedExpression.prototype.val = function() {
653 var value = AExpression.prototype.val.call(this);
654 return "(" + value + ")";
655};
genia.likes.science@gmail.com44ff94a2013-05-31 11:09:34 -0700656
657
658// Functions that can be used to call core expressions/clauses more cleanly
659function AFLWOGR () {
660
661}
662
663function AClause () {
664
665}
666
667function ALetClause () {
668
669}
670
671function AWhereClause () {
672
673}
674
675function AOrderbyClause () {
676
677}
678
679function AGroupClause () {
680
681}
682
683function ALimitClause () {
684
685}
686
687function ADistinctClause () {
688
689}
690
691function AVariable () {
692
693}