blob: 1b4f754d799bb2b4c62c266bb5b70b2483276839 [file] [log] [blame]
genia.likes.science@gmail.com90d08722013-05-28 04:40:12 -07001// Temporary AsterixExpression Placeholder
2function AExpression () {
genia.likes.science@gmail.com512454d2013-05-28 03:32:20 -07003 this._properties = {};
4 this._success = function() {};
5
genia.likes.science@gmail.com512454d2013-05-28 03:32:20 -07006 return this;
7}
8
genia.likes.science@gmail.com90d08722013-05-28 04:40:12 -07009
10AExpression.prototype.bind = function(options) {
genia.likes.science@gmail.com512454d2013-05-28 03:32:20 -070011 var options = options || {};
12
genia.likes.science@gmail.com512454d2013-05-28 03:32:20 -070013 if (options.hasOwnProperty("success")) {
14 this._success = options["success"];
15 }
genia.likes.science@gmail.com38612632013-05-28 13:11:52 -070016
17 if (options.hasOwnProperty("return")) {
18 this._properties["return"] = " return " + options["return"].val();
19 }
genia.likes.science@gmail.com512454d2013-05-28 03:32:20 -070020};
21
genia.likes.science@gmail.com512454d2013-05-28 03:32:20 -070022
genia.likes.science@gmail.com18f3bf22013-06-12 07:45:02 -070023AExpression.prototype.run = function(successFn) {
24 var success_fn = successFn;
genia.likes.science@gmail.com512454d2013-05-28 03:32:20 -070025
26 $.ajax({
27 type : 'GET',
genia.likes.science@gmail.comfc5f5092013-06-12 00:49:46 -070028 url : "http://localhost:19002/query",
genia.likes.science@gmail.com18f3bf22013-06-12 07:45:02 -070029 data : {"query" : "use dataverse TinySocial;\n" + this.val()},
genia.likes.science@gmail.com512454d2013-05-28 03:32:20 -070030 dataType : "json",
31 success : function(data) {
32 success_fn(data);
33 }
34 });
35
36 return this;
genia.likes.science@gmail.com90d08722013-05-28 04:40:12 -070037};
38
39
40AExpression.prototype.val = function() {
41
genia.likes.science@gmail.com2ba32242013-05-31 03:10:48 -070042 var value = "";
43
genia.likes.science@gmail.com90d08722013-05-28 04:40:12 -070044 // If there is a dataverse defined, provide it.
45 if (this._properties.hasOwnProperty("dataverse")) {
genia.likes.science@gmail.com2ba32242013-05-31 03:10:48 -070046 value += "use dataverse " + this._properties["dataverse"] + ";\n";
47 };
48
49 if (this._properties.hasOwnProperty("value")) {
50 value += this._properties["value"];
genia.likes.science@gmail.com90d08722013-05-28 04:40:12 -070051 }
genia.likes.science@gmail.com2ba32242013-05-31 03:10:48 -070052
53 return value;
genia.likes.science@gmail.com38612632013-05-28 13:11:52 -070054};
55
genia.likes.science@gmail.com2ba32242013-05-31 03:10:48 -070056// @param expressionValue [String]
57AExpression.prototype.set = function(expressionValue) {
58 this._properties["value"] = expressionValue;
59 return this;
genia.likes.science@gmail.com38612632013-05-28 13:11:52 -070060};
61
genia.likes.science@gmail.com73dcc702013-05-28 04:21:28 -070062
genia.likes.science@gmail.com90d08722013-05-28 04:40:12 -070063AExpression.prototype.error = function(msg) {
genia.likes.science@gmail.com18f3bf22013-06-12 07:45:02 -070064 //return "Asterix FunctionExpression Error: " + msg;
genia.likes.science@gmail.com90d08722013-05-28 04:40:12 -070065};
66
67
68// FunctionExpression
69// Parent: AsterixExpression
70//
71// @param options [Various],
72// @key function [String], a function to be applid to the expression
genia.likes.science@gmail.com18f3bf22013-06-12 07:45:02 -070073// @key expression [AsterixExpression or AQLClause] an AsterixExpression/Clause to which the fn will be applied
74function FunctionExpression() {
genia.likes.science@gmail.com90d08722013-05-28 04:40:12 -070075
76 // Initialize superclass
77 AExpression.call(this);
genia.likes.science@gmail.com18f3bf22013-06-12 07:45:02 -070078
79 this._properties["function"] = "";
80 this._properties["expression"] = new AExpression().set("");
genia.likes.science@gmail.com90d08722013-05-28 04:40:12 -070081
genia.likes.science@gmail.com18f3bf22013-06-12 07:45:02 -070082 // Check for fn/expression input
83 if (arguments.length == 2 && typeof arguments[0] == "string" &&
84 (arguments[1] instanceof AExpression || arguments[1] instanceof AQLClause)) {
85
86 this._properties["function"] = arguments[0];
87 this._properties["expression"] = arguments[1];
88
89 }
genia.likes.science@gmail.com90d08722013-05-28 04:40:12 -070090
91 // Return object
92 return this;
93}
94
95
96FunctionExpression.prototype = Object.create(AExpression.prototype);
97FunctionExpression.prototype.constructor = FunctionExpression;
98
99
genia.likes.science@gmail.com18f3bf22013-06-12 07:45:02 -0700100FunctionExpression.prototype.fn = function(fnName) {
genia.likes.science@gmail.com90d08722013-05-28 04:40:12 -0700101
genia.likes.science@gmail.com18f3bf22013-06-12 07:45:02 -0700102 if (typeof fnName == "string") {
103 this._properties["function"] = fnName;
104 }
genia.likes.science@gmail.com90d08722013-05-28 04:40:12 -0700105
genia.likes.science@gmail.com90d08722013-05-28 04:40:12 -0700106 return this;
107};
108
genia.likes.science@gmail.com18f3bf22013-06-12 07:45:02 -0700109
110FunctionExpression.prototype.expression = function(expression) {
111 if (expression instanceof AExpression || expression instanceof AQLClause) {
112 this._properties["expression"] = expression;
113 }
114
115 return this;
116};
117
118
genia.likes.science@gmail.com90d08722013-05-28 04:40:12 -0700119FunctionExpression.prototype.val = function () {
genia.likes.science@gmail.com2ba32242013-05-31 03:10:48 -0700120 return this._properties["function"] + "(" + this._properties["expression"].val() + ")";
genia.likes.science@gmail.com90d08722013-05-28 04:40:12 -0700121};
122
genia.likes.science@gmail.com73dcc702013-05-28 04:21:28 -0700123
genia.likes.science@gmail.com73dcc702013-05-28 04:21:28 -0700124// FLWOGR ::= ( ForClause | LetClause ) ( Clause )* "return" Expression
125// Clause ::= ForClause | LetClause | WhereClause | OrderbyClause | GroupClause | LimitClause | DistinctClause
genia.likes.science@gmail.com38612632013-05-28 13:11:52 -0700126//
genia.likes.science@gmail.com73dcc702013-05-28 04:21:28 -0700127// WhereClause ::= "where" Expression
128// OrderbyClause ::= "order" "by" Expression ( ( "asc" ) | ( "desc" ) )? ( "," Expression ( ( "asc" ) | ( "desc" ) )? )*
genia.likes.science@gmail.comb4cb6b32013-05-29 04:30:38 -0700129//
genia.likes.science@gmail.com73dcc702013-05-28 04:21:28 -0700130// GroupClause ::= "group" "by" ( Variable ":=" )? Expression ( "," ( Variable ":=" )? Expression )* ( "decor" Variable ":=" Expression ( "," "decor" Variable ":=" Expression )* )? "with" VariableRef ( "," VariableRef )*
131// LimitClause ::= "limit" Expression ( "offset" Expression )?
132// DistinctClause ::= "distinct" "by" Expression ( "," Expression )*
genia.likes.science@gmail.com73dcc702013-05-28 04:21:28 -0700133
134
genia.likes.science@gmail.com38612632013-05-28 13:11:52 -0700135// FLWOGRExpression
genia.likes.science@gmail.com90d08722013-05-28 04:40:12 -0700136//
137// FLWOGRExpression ::= ( ForClause | LetClause ) ( Clause )* "return" Expression
genia.likes.science@gmail.com38612632013-05-28 13:11:52 -0700138function FLWOGRExpression (options) {
139 // Initialize superclass
140 AExpression.call(this);
genia.likes.science@gmail.com90d08722013-05-28 04:40:12 -0700141
genia.likes.science@gmail.com38612632013-05-28 13:11:52 -0700142 this._properties["clauses"] = [];
genia.likes.science@gmail.com79e603a2013-05-31 10:03:23 -0700143 this._properties["minSize"] = 0;
genia.likes.science@gmail.com38612632013-05-28 13:11:52 -0700144
145 // Bind options and return
146 this.bind(options);
147 return this;
genia.likes.science@gmail.com90d08722013-05-28 04:40:12 -0700148}
149
150
genia.likes.science@gmail.com38612632013-05-28 13:11:52 -0700151FLWOGRExpression.prototype = Object.create(AExpression.prototype);
152FLWOGRExpression.prototype.constructor = FLWOGRExpression;
153
154
155FLWOGRExpression.prototype.bind = function(options) {
156 AExpression.prototype.bind.call(this, options);
157
158 var options = options || {};
159
genia.likes.science@gmail.com79e603a2013-05-31 10:03:23 -0700160 if (options instanceof SetStatement) {
161 this._properties["clauses"].push(options);
162 this._properties["minSize"] += 1;
163 }
164
165 if (this._properties["clauses"].length <= this._properties["minSize"]) {
genia.likes.science@gmail.com38612632013-05-28 13:11:52 -0700166 // Needs to start with for or let clause
167 if (options instanceof ForClause || options instanceof LetClause) {
168 this._properties["clauses"].push(options);
169 }
170 } else {
171 if (options instanceof AQLClause) {
172 this._properties["clauses"].push(options);
173 }
174 }
175
176 return this;
177};
178
179
180FLWOGRExpression.prototype.val = function() {
181 var value = AExpression.prototype.val.call(this);
182
genia.likes.science@gmail.com2ba32242013-05-31 03:10:48 -0700183 var clauseValues = [];
genia.likes.science@gmail.com38612632013-05-28 13:11:52 -0700184 for (var c in this._properties["clauses"]) {
genia.likes.science@gmail.com2ba32242013-05-31 03:10:48 -0700185 clauseValues.push(this._properties["clauses"][c].val());
genia.likes.science@gmail.com38612632013-05-28 13:11:52 -0700186 }
187
genia.likes.science@gmail.com79e603a2013-05-31 10:03:23 -0700188 return value + clauseValues.join("\n");// + ";";
genia.likes.science@gmail.com38612632013-05-28 13:11:52 -0700189};
190
genia.likes.science@gmail.com2ba32242013-05-31 03:10:48 -0700191
genia.likes.science@gmail.com73dcc702013-05-28 04:21:28 -0700192// AQLClause
193//
194// Base Clause ::= ForClause | LetClause | WhereClause | OrderbyClause | GroupClause | LimitClause | DistinctClause
195function AQLClause() {
196 this._properties = {};
197 this._properties["clause"] = "";
198}
199
200AQLClause.prototype.val = function() {
201 var value = this._properties["clause"];
202
203 if (this._properties.hasOwnProperty("return")) {
204 value += " return " + this._properties["return"].val();
205 }
206
207 return value;
208};
209
210AQLClause.prototype.bind = function(options) {
genia.likes.science@gmail.com73dcc702013-05-28 04:21:28 -0700211
genia.likes.science@gmail.com18f3bf22013-06-12 07:45:02 -0700212 if (options instanceof AQLClause) {
213 this._properties["clause"] += " " + options.val();
genia.likes.science@gmail.com73dcc702013-05-28 04:21:28 -0700214 }
215
216 return this;
217};
218
genia.likes.science@gmail.com39578302013-05-31 04:42:26 -0700219AQLClause.prototype.set = function(value) {
220 this._properties["clause"] = value;
221 return this;
222};
223
genia.likes.science@gmail.com73dcc702013-05-28 04:21:28 -0700224
225// ForClause
226//
227// Grammar:
228// "for" Variable ( "at" Variable )? "in" ( Expression )
229//
230// @param for_variable [String], REQUIRED, first variable in clause
231// @param at_variable [String], NOT REQUIRED, first variable in clause
232// @param expression [AsterixExpression], REQUIRED, expression to evaluate
233//
234// TODO Error Checking
235function ForClause(for_variable, at_variable, expression) {
236 AQLClause.call(this);
237
238 // at_variable is optional, check if defined
239 var at = typeof at_variable ? at_variable : null;
240
241 // Prepare clause
242 this._properties["clause"] = "for $" + for_variable;
243 if (at != null) {
244 this._properties["clause"] += " at $" + at_variable;
245 }
246 this._properties["clause"] += " in " + expression.val();
247 return this;
248}
249
250ForClause.prototype = Object.create(AQLClause.prototype);
251ForClause.prototype.constructor = ForClause;
genia.likes.science@gmail.com38612632013-05-28 13:11:52 -0700252
253
254// LetClause
255//
256// Grammar:
257// LetClause ::= "let" Variable ":=" Expression
258//
259// @param let_variable [String]
260// @param expression [AExpression]
261//
262// TODO Vigorous error checking
263function LetClause(let_variable, expression) {
264 AQLClause.call(this);
265
266 this._properties["clause"] = "let $" + let_variable + " := ";
267 this._properties["clause"] += expression.val();
268
269 return this;
270}
271
272LetClause.prototype = Object.create(AQLClause.prototype);
273LetClause.prototype.constructor = LetClause;
274
275
genia.likes.science@gmail.com5ca104c2013-05-29 05:39:26 -0700276// ReturnClause
277//
278// Grammar:
279// return [AQLExpression]
280function ReturnClause(expression) {
281 AQLClause.call(this);
282
283 this._properties["clause"] = "return ";
genia.likes.science@gmail.com79e603a2013-05-31 10:03:23 -0700284 if (expression instanceof AExpression || expression instanceof AQLClause) {
genia.likes.science@gmail.com5ca104c2013-05-29 05:39:26 -0700285 this._properties["clause"] += expression.val();
genia.likes.science@gmail.com2ba32242013-05-31 03:10:48 -0700286 } else if ( Object.getPrototypeOf( expression ) === Object.prototype ) {
287
288 this._properties["clause"] += "{";
289 var returnStatements = [];
290 for (returnValue in expression) {
291
292 if (expression[returnValue] instanceof AExpression) {
genia.likes.science@gmail.comfba7cc82013-05-31 04:04:08 -0700293 returnStatements.push('"' + returnValue + '" ' + " : " + expression[returnValue].val());
genia.likes.science@gmail.com2ba32242013-05-31 03:10:48 -0700294 } else if (typeof expression[returnValue] == "string") {
genia.likes.science@gmail.comfba7cc82013-05-31 04:04:08 -0700295 returnStatements.push('"' + returnValue + '" ' + " : " + expression[returnValue]);
genia.likes.science@gmail.com2ba32242013-05-31 03:10:48 -0700296 }
297 }
298 this._properties["clause"] += returnStatements.join(",\n");
299 this._properties["clause"] += "}";
300
genia.likes.science@gmail.com5ca104c2013-05-29 05:39:26 -0700301 } else {
genia.likes.science@gmail.com44ff94a2013-05-31 11:09:34 -0700302 this._properties["clause"] += new AExpression().set(expression).val();
genia.likes.science@gmail.com5ca104c2013-05-29 05:39:26 -0700303 }
304
305 return this;
306}
307
308ReturnClause.prototype = Object.create(AQLClause.prototype);
309ReturnClause.prototype.constructor = ReturnClause;
310
genia.likes.science@gmail.com2ba32242013-05-31 03:10:48 -0700311ReturnClause.prototype.val = function () {
312 return this._properties["clause"];
313};
314
315
genia.likes.science@gmail.com38612632013-05-28 13:11:52 -0700316// WhereClause
317//
318// Grammar:
319// ::= "where" Expression
320//
321// @param expression [BooleanExpression], pushes this expression onto the stack
genia.likes.science@gmail.com38612632013-05-28 13:11:52 -0700322function WhereClause(expression) {
323 AQLClause.call(this);
324
325 this._properties["stack"] = [];
326
327 this.bind(expression);
328
329 return this;
330}
331
332
333WhereClause.prototype = Object.create(AQLClause.prototype);
334WhereClause.prototype.constructor = WhereClause;
335
336
337WhereClause.prototype.bind = function(expression) {
genia.likes.science@gmail.com64ca88e2013-05-31 10:40:39 -0700338 if (expression instanceof AExpression) {
genia.likes.science@gmail.com38612632013-05-28 13:11:52 -0700339 this._properties["stack"].push(expression);
340 }
341};
342
343
344WhereClause.prototype.val = function() {
345 var value = "where ";
346
347 var count = this._properties["stack"].length - 1;
348 while (count >= 0) {
349 value += this._properties["stack"][count].val() + " ";
350 count -= 1;
351 }
352
353 return value;
genia.likes.science@gmail.com64ca88e2013-05-31 10:40:39 -0700354};
genia.likes.science@gmail.com38612632013-05-28 13:11:52 -0700355
356
genia.likes.science@gmail.com2ba32242013-05-31 03:10:48 -0700357// LimitClause
358// Grammar:
359// LimitClause ::= "limit" Expression ( "offset" Expression )?
360//
361// @param limitExpression [REQUIRED, AQLExpression]
362// @param offsetExpression [OPTIONAL, AQLExpression]
363function LimitClause(limitExpression, offsetExpression) {
364
365 AQLClause.call(this);
366
367 // limitExpression required
368 this._properties["clause"] = "limit " + limitExpression.val();
369
370 // Optional: Offset
371 var offset = typeof offsetExpression ? offsetExpression : null;
372 if (offset != null) {
373 this._properties["clause"] += " offset " + offsetExpression.val();
374 }
375
376 return this;
377}
378
379LimitClause.prototype = Object.create(AQLClause.prototype);
380LimitClause.prototype.constructor = LimitClause;
381
382
383// OrderbyClause
384//
385// Grammar:
386// OrderbyClause ::= "order" "by" Expression ( ( "asc" ) | ( "desc" ) )? ( "," Expression ( ( "asc" ) | ( "desc" ) )? )*
387//
388// @params AQLExpressions and asc/desc strings, in any quantity. At least one required.
389function OrderbyClause() {
390
391 AQLClause.call(this);
392
393 // At least one argument expression is required, and first should be expression
394 if (arguments.length == 0 || !(arguments[0] instanceof AExpression)) {
genia.likes.science@gmail.com18f3bf22013-06-12 07:45:02 -0700395
genia.likes.science@gmail.com2ba32242013-05-31 03:10:48 -0700396 // TODO Not sure which error to throw for an empty OrderBy but this should fail.
397 alert("Order By Error");
398 this._properties["clause"] = null;
399 return this;
400 }
401
402 var expc = 0;
403 var expressions = [];
404
405 while (expc < arguments.length) {
406
407 var expression = "";
408
409 if (arguments[expc] instanceof AExpression) {
410 expression += arguments[expc].val();
411 }
412
413 var next = expc + 1;
414 if (next < arguments.length && (arguments[next] == "asc" || arguments[next] == "desc")) {
415 expc++;
416 expression += " " + arguments[expc];
417 }
418
419 expressions.push(expression);
420
421 expc++;
422 }
423
424 this._properties["clause"] = "order by " + expressions.join(", ");
425 return this;
426}
427
428OrderbyClause.prototype = Object.create(AQLClause.prototype);
429OrderbyClause.prototype.constructor = OrderbyClause;
430
431
genia.likes.science@gmail.com6e392912013-05-31 03:46:59 -0700432// GroupClause
433//
434// Grammar:
435// GroupClause ::= "group" "by" ( Variable ":=" )? Expression ( "," ( Variable ":=" )? Expression )* ( "decor" Variable ":=" Expression ( "," "decor" Variable ":=" Expression )* )? "with" VariableRef ( "," VariableRef )*
436function GroupClause() {
437 AQLClause.call(this);
438
439 if (arguments.length == 0) {
440 // TODO Not sure which error to throw for an empty GroupBy but this should fail.
441 alert("Group Error");
442 this._properties["clause"] = null;
443 return this;
444 }
445
446 var expc = 0;
447 var expressions = [];
448 var variableRefs = [];
449 var isDecor = false;
450
451 while (expc < arguments.length) {
452
453 if (arguments[expc] instanceof AExpression) {
454
455 isDecor = false;
456 expressions.push(arguments[expc].val());
457
458 } else if (typeof arguments[expc] == "string") {
459
460 // Special keywords, decor & with
461 if (arguments[expc] == "decor") {
462 isDecor = true;
463 } else if (arguments[expc] == "with") {
464 isDecor = false;
465 expc++;
466 while (expc < arguments.length) {
467 variableRefs.push("$" + arguments[expc]);
468 expc++;
469 }
470
471 // Variables and variable refs
472 } else {
473
474 var nextc = expc + 1;
475 var expression = "";
476
477 if (isDecor) {
478 expression += "decor ";
479 isDecor = false;
480 }
481
482 expression += "$" + arguments[expc] + " := " + arguments[nextc].val();
483 expressions.push(expression);
484 expc++;
485 }
486 }
487
488 expc++;
489 }
490
491 this._properties["clause"] = "group by " + expressions.join(", ") + " with " + variableRefs.join(", ");
492 return this;
493}
494
495GroupClause.prototype = Object.create(AQLClause.prototype);
496GroupClause.prototype.constructor = GroupClause;
497
genia.likes.science@gmail.com38612632013-05-28 13:11:52 -0700498// BooleanExpression
499//
500// TODO
501function BooleanExpression(expression) {
502 this.value = expression;
genia.likes.science@gmail.com6fd7b2e2013-05-31 00:40:28 -0700503 alert("Debugging Bool: " + arguments.length + " " + expression);
genia.likes.science@gmail.com38612632013-05-28 13:11:52 -0700504}
505
506BooleanExpression.prototype.val = function() {
507 return this.value;
508}
genia.likes.science@gmail.com79e603a2013-05-31 10:03:23 -0700509
510
511// SetStatement
512//
513// Grammar
514// "set" Identifier StringLiteral
515function SetStatement (identifier, stringLiteral) {
516 AExpression.call(this);
517
518 var statement = "set " + identifier + ' "' + stringLiteral + '";';
519
520 AExpression.prototype.set.call(this, statement);
521
522 return this;
523}
524
525SetStatement.prototype = Object.create(AExpression.prototype);
526SetStatement.prototype.constructor = SetStatement;
genia.likes.science@gmail.come34c57b2013-05-31 10:15:49 -0700527
528
529// Quantified Expression
530//
531// Grammar
532// QuantifiedExpression ::= ( ( "some" ) | ( "every" ) ) Variable "in" Expression ( "," Variable "in" Expression )* "satisfies" Expression
533//
534// @param String some/every
535// @param [AExpression]
536// @param [Aexpression] satisfiesExpression
537function QuantifiedExpression (keyword, expressions, satisfiesExpression) {
538 AExpression.call(this);
539
540 var expression = keyword + " ";
541 var varsInExpressions = [];
542
543 for (var varInExpression in expressions) {
544 varsInExpressions.push(varInExpression + " in " + expressions[varInExpression].val());
545 }
546 expression += varsInExpressions.join(", ") + " satisfies " + satisfiesExpression.val();
547
548 AExpression.prototype.set.call(this, expression);
549
550 return this;
551}
552
553QuantifiedExpression.prototype = Object.create(AExpression.prototype);
554QuantifiedExpression.prototype.constructor = QuantifiedExpression;
genia.likes.science@gmail.com64ca88e2013-05-31 10:40:39 -0700555
556QuantifiedExpression.prototype.val = function() {
557 var value = AExpression.prototype.val.call(this);
558 return "(" + value + ")";
559};
genia.likes.science@gmail.com44ff94a2013-05-31 11:09:34 -0700560
561
562// Functions that can be used to call core expressions/clauses more cleanly
563function AFLWOGR () {
564
565}
566
567function AClause () {
568
569}
570
571function ALetClause () {
572
573}
574
575function AWhereClause () {
576
577}
578
579function AOrderbyClause () {
580
581}
582
583function AGroupClause () {
584
585}
586
587function ALimitClause () {
588
589}
590
591function ADistinctClause () {
592
593}
594
595function AVariable () {
596
597}