blob: a866946d216af374410a4a121f5e92b0a06f4d49 [file] [log] [blame]
Ian Maxon032a1782015-06-30 17:10:51 -07001/*
2 * Copyright 2009-2013 by The Regents of the University of California
3 * Licensed under the Apache License, Version 2.0 (the "License");
4 * you may not use this file except in compliance with the License.
5 * you may obtain a copy of the License from
6 *
7 * http://www.apache.org/licenses/LICENSE-2.0
8 *
9 * Unless required by applicable law or agreed to in writing, software
10 * distributed under the License is distributed on an "AS IS" BASIS,
11 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 * See the License for the specific language governing permissions and
13 * limitations under the License.
14 */
15
genia.likes.science@gmail.com67605862013-10-04 05:43:57 -070016function AsterixDBConnection(configuration) {
17 this._properties = {};
18 this._properties["dataverse"] = "";
19 this._properties["mode"] = "synchronous";
20
21 // This is a demo setup related fix. Enabled by proxy to Asterix REST API.
22 this._properties["endpoint_root"] = "/";
Zachary Heilbron1c0bd7f2014-03-06 12:54:09 -080023
genia.likes.science@gmail.com67605862013-10-04 05:43:57 -070024 var configuration = arguments || {};
Zachary Heilbron1c0bd7f2014-03-06 12:54:09 -080025
genia.likes.science@gmail.com67605862013-10-04 05:43:57 -070026 for (var key in configuration) {
27 this._properties[key] = configuration[key];
28 }
Zachary Heilbron1c0bd7f2014-03-06 12:54:09 -080029
genia.likes.science@gmail.com67605862013-10-04 05:43:57 -070030 return this;
31}
32
33
34AsterixDBConnection.prototype.dataverse = function(dataverseName) {
35 this._properties["dataverse"] = dataverseName;
Zachary Heilbron1c0bd7f2014-03-06 12:54:09 -080036
genia.likes.science@gmail.com67605862013-10-04 05:43:57 -070037 return this;
38};
39
40
41AsterixDBConnection.prototype.query = function(statements, successFn, mode) {
genia.likes.science@gmail.com67605862013-10-04 05:43:57 -070042 if ( typeof statements === 'string') {
43 statements = [ statements ];
44 }
Zachary Heilbron1c0bd7f2014-03-06 12:54:09 -080045
genia.likes.science@gmail.com67605862013-10-04 05:43:57 -070046 var m = typeof mode ? mode : "synchronous";
Zachary Heilbron1c0bd7f2014-03-06 12:54:09 -080047
genia.likes.science@gmail.com67605862013-10-04 05:43:57 -070048 var query = "use dataverse " + this._properties["dataverse"] + ";\n" + statements.join("\n");
Zachary Heilbron1c0bd7f2014-03-06 12:54:09 -080049
genia.likes.science@gmail.com67605862013-10-04 05:43:57 -070050 this._api(
51 {
52 "query" : query,
53 "mode" : m
54 },
Zachary Heilbron1c0bd7f2014-03-06 12:54:09 -080055 successFn,
genia.likes.science@gmail.com67605862013-10-04 05:43:57 -070056 "query"
57 );
58
59 return this;
60};
61
62
63AsterixDBConnection.prototype.query_status = function(data, successFn) {
64
65 this._api(
66 data,
67 successFn,
68 "query/status"
69 );
70
71 return this;
72};
73
74
75AsterixDBConnection.prototype.query_result = function(data, successFn) {
76 this._api(
77 data,
78 successFn,
79 "query/result"
Zachary Heilbron1c0bd7f2014-03-06 12:54:09 -080080 );
genia.likes.science@gmail.com67605862013-10-04 05:43:57 -070081
82 return this;
83};
84
85
86AsterixDBConnection.prototype.ddl = function(statements, successFn) {
87 if ( typeof statements === 'string') {
88 statements = [ statements ];
89 }
Zachary Heilbron1c0bd7f2014-03-06 12:54:09 -080090
genia.likes.science@gmail.com67605862013-10-04 05:43:57 -070091 this._api(
92 {
93 "ddl" : "use dataverse " + this._properties["dataverse"] + ";\n" + statements.join("\n")
94 },
95 successFn,
96 "ddl"
97 );
98}
99
100
101AsterixDBConnection.prototype.update = function(statements, successFn) {
102 if ( typeof statements === 'string') {
103 statements = [ statements ];
104 }
Zachary Heilbron1c0bd7f2014-03-06 12:54:09 -0800105
genia.likes.science@gmail.com67605862013-10-04 05:43:57 -0700106 this._api(
107 {
108 "statements" : "use dataverse " + this._properties["dataverse"] + ";\n" + statements.join("\n")
109 },
110 successFn,
111 "update"
112 );
113}
114
115
116AsterixDBConnection.prototype._api = function(json, onSuccess, endpoint) {
117 var success_fn = onSuccess;
Zachary Heilbron1c0bd7f2014-03-06 12:54:09 -0800118 var endpoint_url = this._properties["endpoint_root"] + endpoint;
genia.likes.science@gmail.com67605862013-10-04 05:43:57 -0700119
120 $.ajax({
121 type: 'GET',
122 url: endpoint_url,
123 data : json,
124 dataType: "json",
125 success: function(data) {
126 success_fn(data);
127 },
128 error: function(xhr, status, error) {
129 }
130 });
Zachary Heilbron1c0bd7f2014-03-06 12:54:09 -0800131
genia.likes.science@gmail.com67605862013-10-04 05:43:57 -0700132 return this;
133};
134
135
136// Asterix Expressions - Base
137function AExpression () {
138
139 this._properties = {};
140 this._success = function() {};
141
142 if (arguments.length == 1) {
Zachary Heilbron1c0bd7f2014-03-06 12:54:09 -0800143 this._properties["value"] = arguments[0];
genia.likes.science@gmail.com67605862013-10-04 05:43:57 -0700144 }
145
146 return this;
147}
148
149
150AExpression.prototype.bind = function(options) {
151 var options = options || {};
152
153 if (options.hasOwnProperty("success")) {
154 this._success = options["success"];
155 }
156
157 if (options.hasOwnProperty("return")) {
158 this._properties["return"] = " return " + options["return"].val();
159 }
160};
161
162
163AExpression.prototype.run = function(successFn) {
164 return this;
165};
166
167
Zachary Heilbron1c0bd7f2014-03-06 12:54:09 -0800168AExpression.prototype.val = function() {
genia.likes.science@gmail.com67605862013-10-04 05:43:57 -0700169
170 var value = "";
171
172 // If there is a dataverse defined, provide it.
173 if (this._properties.hasOwnProperty("dataverse")) {
174 value += "use dataverse " + this._properties["dataverse"] + ";\n";
175 };
176
177 if (this._properties.hasOwnProperty("value")) {
178 value += this._properties["value"].toString();
179 }
180
181 return value;
182};
183
184
185// @param expressionValue [String]
186AExpression.prototype.set = function(expressionValue) {
Zachary Heilbron1c0bd7f2014-03-06 12:54:09 -0800187 this._properties["value"] = expressionValue;
genia.likes.science@gmail.com67605862013-10-04 05:43:57 -0700188 return this;
189};
190
191
192// AQL Statements
193// SingleStatement ::= DataverseDeclaration
194// | FunctionDeclaration
195// | CreateStatement
196// | DropStatement
197// | LoadStatement
198// | SetStatement
199// | InsertStatement
200// | DeleteStatement
201// | Query
202function InsertStatement(quantifiedName, query) {
203 AExpression.call(this);
Zachary Heilbron1c0bd7f2014-03-06 12:54:09 -0800204
genia.likes.science@gmail.com67605862013-10-04 05:43:57 -0700205 var innerQuery = "";
206 if (query instanceof AExpression) {
207 innerQuery = query.val();
208 } else if (typeof query == "object" && Object.getPrototypeOf( query ) === Object.prototype ) {
Zachary Heilbron1c0bd7f2014-03-06 12:54:09 -0800209
genia.likes.science@gmail.com67605862013-10-04 05:43:57 -0700210 var insertStatements = [];
211 for (querykey in query) {
212 if (query[querykey] instanceof AExpression) {
213 insertStatements.push('"' + querykey + '" : ' + query[querykey].val());
214 } else if (typeof query[querykey] == "string") {
215 insertStatements.push('"' + querykey + '" : ' + query[querykey]);
216 } else {
217 insertStatements.push('"' + querykey + '" : ' + query[querykey].toString());
218 }
219 }
Zachary Heilbron1c0bd7f2014-03-06 12:54:09 -0800220
genia.likes.science@gmail.com67605862013-10-04 05:43:57 -0700221 innerQuery = "{" + insertStatements.join(', ') + "}";
222 }
Zachary Heilbron1c0bd7f2014-03-06 12:54:09 -0800223
genia.likes.science@gmail.com67605862013-10-04 05:43:57 -0700224 var statement = "insert into dataset " + quantifiedName + "(" + innerQuery + ");";
Zachary Heilbron1c0bd7f2014-03-06 12:54:09 -0800225
genia.likes.science@gmail.com67605862013-10-04 05:43:57 -0700226 AExpression.prototype.set.call(this, statement);
227
228 return this;
229}
230
231InsertStatement.prototype = Object.create(AExpression.prototype);
232InsertStatement.prototype.constructor = InsertStatement;
233
234
235// Delete Statement
236// DeleteStatement ::= "delete" Variable "from" "dataset" QualifiedName ( "where" Expression )?
237function DeleteStatement (variable, quantifiedName, whereExpression) {
238 AExpression.call(this);
Zachary Heilbron1c0bd7f2014-03-06 12:54:09 -0800239
genia.likes.science@gmail.com67605862013-10-04 05:43:57 -0700240 var statement = "delete " + variable + " from dataset " + quantifiedName;
Zachary Heilbron1c0bd7f2014-03-06 12:54:09 -0800241
genia.likes.science@gmail.com67605862013-10-04 05:43:57 -0700242 if (whereExpression instanceof AExpression) {
243 statement += " where " + whereExpression.val();
244 }
Zachary Heilbron1c0bd7f2014-03-06 12:54:09 -0800245
genia.likes.science@gmail.com67605862013-10-04 05:43:57 -0700246 AExpression.prototype.set.call(this, statement);
Zachary Heilbron1c0bd7f2014-03-06 12:54:09 -0800247
genia.likes.science@gmail.com67605862013-10-04 05:43:57 -0700248 return this;
249}
250
251DeleteStatement.prototype = Object.create(AExpression.prototype);
252DeleteStatement.prototype.constructor = DeleteStatement;
253
254// SetStatement
255//
256// Grammar
257// "set" Identifier StringLiteral
258function SetStatement (identifier, stringLiteral) {
259 AExpression.call(this);
260
261 var statement = "set " + identifier + ' "' + stringLiteral + '";';
262
263 AExpression.prototype.set.call(this, statement);
264
265 return this;
266}
267
268SetStatement.prototype = Object.create(AExpression.prototype);
269SetStatement.prototype.constructor = SetStatement;
270
271
272// Other Expressions
273
274// FunctionExpression
275// Parent: AsterixExpression
Zachary Heilbron1c0bd7f2014-03-06 12:54:09 -0800276//
277// @param options [Various],
genia.likes.science@gmail.com67605862013-10-04 05:43:57 -0700278// @key function [String], a function to be applid to the expression
279// @key expression [AsterixExpression or AQLClause] an AsterixExpression/Clause to which the fn will be applied
280function FunctionExpression() {
Zachary Heilbron1c0bd7f2014-03-06 12:54:09 -0800281
genia.likes.science@gmail.com67605862013-10-04 05:43:57 -0700282 // Initialize superclass
283 AExpression.call(this);
Zachary Heilbron1c0bd7f2014-03-06 12:54:09 -0800284
genia.likes.science@gmail.com67605862013-10-04 05:43:57 -0700285 this._properties["function"] = "";
286 this._properties["expressions"] = [];
287
288 // Check for fn/expression input
289 if (arguments.length >= 2 && typeof arguments[0] == "string") {
Zachary Heilbron1c0bd7f2014-03-06 12:54:09 -0800290
genia.likes.science@gmail.com67605862013-10-04 05:43:57 -0700291 this._properties["function"] = arguments[0];
292
293 for (i = 1; i < arguments.length; i++) {
294 if (arguments[i] instanceof AExpression || arguments[i] instanceof AQLClause) {
295 this._properties["expressions"].push(arguments[i]);
296 } else {
297 this._properties["expressions"].push(new AExpression(arguments[i]));
298 }
299 }
Zachary Heilbron1c0bd7f2014-03-06 12:54:09 -0800300 }
genia.likes.science@gmail.com67605862013-10-04 05:43:57 -0700301
302 // Return FunctionCallExpression object
303 return this;
304}
305
306
307FunctionExpression.prototype = Object.create(AExpression.prototype);
308FunctionExpression.prototype.constructor = FunctionExpression;
Zachary Heilbron1c0bd7f2014-03-06 12:54:09 -0800309
genia.likes.science@gmail.com67605862013-10-04 05:43:57 -0700310
311FunctionExpression.prototype.val = function () {
312 var fn_args = [];
313 for (var i = 0; i < this._properties["expressions"].length; i++) {
314 fn_args.push(this._properties["expressions"][i].val());
315 }
316
317 return this._properties["function"] + "(" + fn_args.join(", ") + ")";
318};
319
320
321// FLWOGRExpression
322//
323// FLWOGRExpression ::= ( ForClause | LetClause ) ( Clause )* "return" Expression
324function FLWOGRExpression (options) {
325 // Initialize superclass
326 AExpression.call(this);
327
328 this._properties["clauses"] = [];
329 this._properties["minSize"] = 0;
330
331 // Bind options and return
332 this.bind(options);
333 return this;
334}
335
336
337FLWOGRExpression.prototype = Object.create(AExpression.prototype);
338FLWOGRExpression.prototype.constructor = FLWOGRExpression;
339
340
341FLWOGRExpression.prototype.bind = function(options) {
342 AExpression.prototype.bind.call(this, options);
343
344 var options = options || {};
345
346 if (options instanceof SetStatement) {
347 this._properties["clauses"].push(options);
348 this._properties["minSize"] += 1;
349 }
350
351 if (this._properties["clauses"].length <= this._properties["minSize"]) {
352 // Needs to start with for or let clause
353 if (options instanceof ForClause || options instanceof LetClause) {
354 this._properties["clauses"].push(options);
355 }
356 } else {
357 if (options instanceof AQLClause) {
358 this._properties["clauses"].push(options);
359 }
360 }
361
362 return this;
363};
364
365
366FLWOGRExpression.prototype.val = function() {
367 var value = AExpression.prototype.val.call(this);
368
369 var clauseValues = [];
370 for (var c in this._properties["clauses"]) {
371 clauseValues.push(this._properties["clauses"][c].val());
372 }
373
374 return value + clauseValues.join("\n");// + ";";
375};
376
377// Pretty Expression Shorthand
378
379FLWOGRExpression.prototype.ReturnClause = function(expression) {
380 return this.bind(new ReturnClause(expression));
381};
382
383FLWOGRExpression.prototype.ForClause = function() {
384 return this.bind(new ForClause(Array.prototype.slice.call(arguments)));
385};
386
387FLWOGRExpression.prototype.LetClause = function() {
388 return this.bind(new LetClause(Array.prototype.slice.call(arguments)));
389};
390
391FLWOGRExpression.prototype.WhereClause = function() {
392 return this.bind(new WhereClause(Array.prototype.slice.call(arguments)));
393};
394
395FLWOGRExpression.prototype.and = function() {
396 var args = Array.prototype.slice.call(arguments);
397 args.push(true);
398 return this.bind(new WhereClause().and(args));
399};
400
401FLWOGRExpression.prototype.or = function() {
402 var args = Array.prototype.slice.call(arguments);
403 args.push(true);
404 return this.bind(new WhereClause().or(args));
405};
406
407FLWOGRExpression.prototype.OrderbyClause = function() {
408 return this.bind(new OrderbyClause(Array.prototype.slice.call(arguments)));
409};
410
411
412FLWOGRExpression.prototype.GroupClause = function() {
413 return this.bind(new GroupClause(Array.prototype.slice.call(arguments)));
414};
415
416FLWOGRExpression.prototype.LimitClause = function() {
417 return this.bind(new LimitClause(Array.prototype.slice.call(arguments)));
418};
419
420FLWOGRExpression.prototype.DistinctClause = function() {
421 return this.bind(new DistinctClause(Array.prototype.slice.call(arguments)));
422};
423
424FLWOGRExpression.prototype.AQLClause = function() {
425 return this.bind(new AQLClause(Array.prototype.slice.call(arguments)));
426};
427
428
429// AQLClause
430//
431// Base Clause ::= ForClause | LetClause | WhereClause | OrderbyClause | GroupClause | LimitClause | DistinctClause
432function AQLClause() {
433 this._properties = {};
434 this._properties["clause"] = "";
435 this._properties["stack"] = [];
436 if (typeof arguments[0] == 'string') {
437 this._properties["clause"] = arguments[0];
438 }
439 return this;
440}
441
442AQLClause.prototype.val = function() {
443 var value = this._properties["clause"];
Zachary Heilbron1c0bd7f2014-03-06 12:54:09 -0800444
genia.likes.science@gmail.com67605862013-10-04 05:43:57 -0700445 return value;
446};
447
448AQLClause.prototype.bind = function(options) {
449
450 if (options instanceof AQLClause) {
451 this._properties["clause"] += " " + options.val();
452 }
453
454 return this;
455};
456
457AQLClause.prototype.set = function(value) {
458 this._properties["clause"] = value;
459 return this;
460};
461
462
463// ForClause
464//
465// Grammar:
466// "for" Variable ( "at" Variable )? "in" ( Expression )
467//
Zachary Heilbron1c0bd7f2014-03-06 12:54:09 -0800468// @param for_variable [String], REQUIRED, first variable in clause
genia.likes.science@gmail.com67605862013-10-04 05:43:57 -0700469// @param at_variable [String], NOT REQUIRED, first variable in clause
470// @param expression [AsterixExpression], REQUIRED, expression to evaluate
471function ForClause(for_variable, at_variable, expression) {
472 AQLClause.call(this);
Zachary Heilbron1c0bd7f2014-03-06 12:54:09 -0800473
genia.likes.science@gmail.com67605862013-10-04 05:43:57 -0700474 var parameters = [];
475 if (arguments[0] instanceof Array) {
476 parameters = arguments[0];
477 } else {
478 parameters = arguments;
479 }
Zachary Heilbron1c0bd7f2014-03-06 12:54:09 -0800480
genia.likes.science@gmail.com67605862013-10-04 05:43:57 -0700481 this._properties["clause"] = "for " + parameters[0];
Zachary Heilbron1c0bd7f2014-03-06 12:54:09 -0800482
genia.likes.science@gmail.com67605862013-10-04 05:43:57 -0700483 if (parameters.length == 3) {
484 this._properties["clause"] += " at " + parameters[1];
485 this._properties["clause"] += " in " + parameters[2].val();
486 } else if (parameters.length == 2) {
487 this._properties["clause"] += " in " + parameters[1].val();
488 }
Zachary Heilbron1c0bd7f2014-03-06 12:54:09 -0800489
genia.likes.science@gmail.com67605862013-10-04 05:43:57 -0700490 return this;
491}
492
493ForClause.prototype = Object.create(AQLClause.prototype);
494ForClause.prototype.constructor = ForClause;
495
496
497// LetClause
498//
499// Grammar:
500// LetClause ::= "let" Variable ":=" Expression
501//
502// @param let_variable [String]
503// @param expression [AExpression]
504//
505// TODO Vigorous error checking
506function LetClause(let_variable, expression) {
507 AQLClause.call(this);
Zachary Heilbron1c0bd7f2014-03-06 12:54:09 -0800508
genia.likes.science@gmail.com67605862013-10-04 05:43:57 -0700509 var parameters = [];
510 if (arguments[0] instanceof Array) {
511 parameters = arguments[0];
512 } else {
513 parameters = arguments;
514 }
Zachary Heilbron1c0bd7f2014-03-06 12:54:09 -0800515
genia.likes.science@gmail.com67605862013-10-04 05:43:57 -0700516 this._properties["clause"] = "let " + parameters[0] + " := ";
517 this._properties["clause"] += parameters[1].val();
Zachary Heilbron1c0bd7f2014-03-06 12:54:09 -0800518
519 return this;
genia.likes.science@gmail.com67605862013-10-04 05:43:57 -0700520}
521
522LetClause.prototype = Object.create(AQLClause.prototype);
523LetClause.prototype.constructor = LetClause;
524
525
526// ReturnClause
527//
528// Grammar:
529// return [AQLExpression]
530function ReturnClause(expression) {
531 AQLClause.call(this);
532
533 this._properties["clause"] = "return ";
Zachary Heilbron1c0bd7f2014-03-06 12:54:09 -0800534
genia.likes.science@gmail.com67605862013-10-04 05:43:57 -0700535 if (expression instanceof AExpression || expression instanceof AQLClause) {
536 this._properties["clause"] += expression.val();
Zachary Heilbron1c0bd7f2014-03-06 12:54:09 -0800537
genia.likes.science@gmail.com67605862013-10-04 05:43:57 -0700538 } else if ( typeof expression == "object" && Object.getPrototypeOf( expression ) === Object.prototype ) {
Zachary Heilbron1c0bd7f2014-03-06 12:54:09 -0800539
genia.likes.science@gmail.com67605862013-10-04 05:43:57 -0700540 this._properties["clause"] += "\n{\n";
541 var returnStatements = [];
542 for (returnValue in expression) {
Zachary Heilbron1c0bd7f2014-03-06 12:54:09 -0800543
544 if (expression[returnValue] instanceof AExpression) {
545 returnStatements.push('"' + returnValue + '" ' + " : " + expression[returnValue].val());
546 } else if (typeof expression[returnValue] == "string") {
547 returnStatements.push('"' + returnValue + '" ' + " : " + expression[returnValue]);
genia.likes.science@gmail.com67605862013-10-04 05:43:57 -0700548 }
549 }
550 this._properties["clause"] += returnStatements.join(",\n");
Zachary Heilbron1c0bd7f2014-03-06 12:54:09 -0800551 this._properties["clause"] += "\n}";
552
genia.likes.science@gmail.com67605862013-10-04 05:43:57 -0700553 } else {
554 this._properties["clause"] += new AQLClause().set(expression).val();
555 }
556
557 return this;
558}
559
560
561ReturnClause.prototype = Object.create(AQLClause.prototype);
562ReturnClause.prototype.constructor = ReturnClause;
563
564
565// WhereClause
566//
Zachary Heilbron1c0bd7f2014-03-06 12:54:09 -0800567// Grammar:
genia.likes.science@gmail.com67605862013-10-04 05:43:57 -0700568// ::= "where" Expression
Zachary Heilbron1c0bd7f2014-03-06 12:54:09 -0800569//
genia.likes.science@gmail.com67605862013-10-04 05:43:57 -0700570// @param expression [BooleanExpression], pushes this expression onto the stack
571function WhereClause(expression) {
572 AQLClause.call(this);
Zachary Heilbron1c0bd7f2014-03-06 12:54:09 -0800573
genia.likes.science@gmail.com67605862013-10-04 05:43:57 -0700574 this._properties["stack"] = [];
575
576 if (expression instanceof Array) {
577 this.bind(expression[0]);
578 } else {
579 this.bind(expression);
580 }
Zachary Heilbron1c0bd7f2014-03-06 12:54:09 -0800581
genia.likes.science@gmail.com67605862013-10-04 05:43:57 -0700582 return this;
583}
584
585
586WhereClause.prototype = Object.create(AQLClause.prototype);
587WhereClause.prototype.constructor = WhereClause;
588
589
590WhereClause.prototype.bind = function(expression) {
591 if (expression instanceof AExpression) {
592 this._properties["stack"].push(expression);
593 }
594 return this;
595};
596
597
598WhereClause.prototype.val = function() {
Zachary Heilbron1c0bd7f2014-03-06 12:54:09 -0800599 var value = "";
600
genia.likes.science@gmail.com67605862013-10-04 05:43:57 -0700601 if (this._properties["stack"].length == 0) {
602 return value;
603 }
604
605 var count = this._properties["stack"].length - 1;
606 while (count >= 0) {
607 value += this._properties["stack"][count].val() + " ";
608 count -= 1;
609 }
Zachary Heilbron1c0bd7f2014-03-06 12:54:09 -0800610
genia.likes.science@gmail.com67605862013-10-04 05:43:57 -0700611 return "where " + value;
612};
613
614
615WhereClause.prototype.and = function() {
Zachary Heilbron1c0bd7f2014-03-06 12:54:09 -0800616
genia.likes.science@gmail.com67605862013-10-04 05:43:57 -0700617 var parameters = [];
618 if (arguments[0] instanceof Array) {
619 parameters = arguments[0];
620 } else {
621 parameters = arguments;
622 }
Zachary Heilbron1c0bd7f2014-03-06 12:54:09 -0800623
624 var andClauses = [];
genia.likes.science@gmail.com67605862013-10-04 05:43:57 -0700625 for (var expression in parameters) {
Zachary Heilbron1c0bd7f2014-03-06 12:54:09 -0800626
genia.likes.science@gmail.com67605862013-10-04 05:43:57 -0700627 if (parameters[expression] instanceof AExpression) {
628 andClauses.push(parameters[expression].val());
629 }
630 }
Zachary Heilbron1c0bd7f2014-03-06 12:54:09 -0800631
genia.likes.science@gmail.com67605862013-10-04 05:43:57 -0700632 if (andClauses.length > 0) {
633 this._properties["stack"].push(new AExpression().set(andClauses.join(" and ")));
634 }
Zachary Heilbron1c0bd7f2014-03-06 12:54:09 -0800635
genia.likes.science@gmail.com67605862013-10-04 05:43:57 -0700636 return this;
637};
638
639
640WhereClause.prototype.or = function() {
641
642 var parameters = [];
643 if (arguments[0] instanceof Array) {
644 parameters = arguments[0];
645 } else {
646 parameters = arguments;
647 }
648
Zachary Heilbron1c0bd7f2014-03-06 12:54:09 -0800649 var orClauses = [];
genia.likes.science@gmail.com67605862013-10-04 05:43:57 -0700650 for (var expression in parameters) {
Zachary Heilbron1c0bd7f2014-03-06 12:54:09 -0800651
genia.likes.science@gmail.com67605862013-10-04 05:43:57 -0700652 if (parameters[expression] instanceof AExpression) {
653 orClauses.push(parameters[expression].val());
654 }
655 }
Zachary Heilbron1c0bd7f2014-03-06 12:54:09 -0800656
genia.likes.science@gmail.com67605862013-10-04 05:43:57 -0700657 if (andClauses.length > 0) {
658 this._properties["stack"].push(new AExpression().set(orClauses.join(" and ")));
659 }
Zachary Heilbron1c0bd7f2014-03-06 12:54:09 -0800660
genia.likes.science@gmail.com67605862013-10-04 05:43:57 -0700661 return this;
662};
663
664// LimitClause
665// Grammar:
666// LimitClause ::= "limit" Expression ( "offset" Expression )?
Zachary Heilbron1c0bd7f2014-03-06 12:54:09 -0800667//
genia.likes.science@gmail.com67605862013-10-04 05:43:57 -0700668// @param limitExpression [REQUIRED, AQLExpression]
669// @param offsetExpression [OPTIONAL, AQLExpression]
670function LimitClause(limitExpression, offsetExpression) {
671
672 AQLClause.call(this);
Zachary Heilbron1c0bd7f2014-03-06 12:54:09 -0800673
genia.likes.science@gmail.com67605862013-10-04 05:43:57 -0700674 var parameters = [];
675 if (arguments[0] instanceof Array) {
676 parameters = arguments[0];
677 } else {
678 parameters = arguments;
679 }
Zachary Heilbron1c0bd7f2014-03-06 12:54:09 -0800680
genia.likes.science@gmail.com67605862013-10-04 05:43:57 -0700681 // limitExpression required
682 this._properties["clause"] = "limit " + parameters[0].val();
683
684 // Optional: Offset
685 if (parameters.length == 2) {
686 this._properties["clause"] += " offset " + parameters[1].val();
687 }
688
689 return this;
690}
691
692LimitClause.prototype = Object.create(AQLClause.prototype);
693LimitClause.prototype.constructor = LimitClause;
694
695
696// OrderbyClause
697//
698// Grammar:
699// OrderbyClause ::= "order" "by" Expression ( ( "asc" ) | ( "desc" ) )? ( "," Expression ( ( "asc" ) | ( "desc" ) )? )*
700//
Zachary Heilbron1c0bd7f2014-03-06 12:54:09 -0800701// @params AQLExpressions and asc/desc strings, in any quantity. At least one required.
genia.likes.science@gmail.com67605862013-10-04 05:43:57 -0700702function OrderbyClause() {
Zachary Heilbron1c0bd7f2014-03-06 12:54:09 -0800703
genia.likes.science@gmail.com67605862013-10-04 05:43:57 -0700704 AQLClause.call(this);
705
706 // At least one argument expression is required, and first should be expression
707 if (arguments.length == 0) {
708 this._properties["clause"] = null;
Zachary Heilbron1c0bd7f2014-03-06 12:54:09 -0800709 return this;
genia.likes.science@gmail.com67605862013-10-04 05:43:57 -0700710 }
Zachary Heilbron1c0bd7f2014-03-06 12:54:09 -0800711
genia.likes.science@gmail.com67605862013-10-04 05:43:57 -0700712 var parameters = [];
713 if (arguments[0] instanceof Array) {
714 parameters = arguments[0];
715 } else {
716 parameters = arguments;
717 }
718
719 var expc = 0;
Zachary Heilbron1c0bd7f2014-03-06 12:54:09 -0800720 var expressions = [];
genia.likes.science@gmail.com67605862013-10-04 05:43:57 -0700721
722 while (expc < parameters.length) {
Zachary Heilbron1c0bd7f2014-03-06 12:54:09 -0800723
genia.likes.science@gmail.com67605862013-10-04 05:43:57 -0700724 var expression = "";
725
726 if (parameters[expc] instanceof AExpression) {
727 expression += parameters[expc].val();
728 }
729
730 var next = expc + 1;
731 if (next < parameters.length && (parameters[next] == "asc" || parameters[next] == "desc")) {
732 expc++;
733 expression += " " + parameters[expc];
734 }
Zachary Heilbron1c0bd7f2014-03-06 12:54:09 -0800735
genia.likes.science@gmail.com67605862013-10-04 05:43:57 -0700736 expressions.push(expression);
Zachary Heilbron1c0bd7f2014-03-06 12:54:09 -0800737
genia.likes.science@gmail.com67605862013-10-04 05:43:57 -0700738 expc++;
739 }
740
741 this._properties["clause"] = "order by " + expressions.join(", ");
742 return this;
743}
744
745OrderbyClause.prototype = Object.create(AQLClause.prototype);
746OrderbyClause.prototype.constructor = OrderbyClause;
747
748
749// GroupClause
750//
751// Grammar:
752// GroupClause ::= "group" "by" ( Variable ":=" )? Expression ( "," ( Variable ":=" )? Expression )* ( "decor" Variable ":=" Expression ( "," "decor" Variable ":=" Expression )* )? "with" VariableRef ( "," VariableRef )*
753function GroupClause() {
754 AQLClause.call(this);
755
756 if (arguments.length == 0) {
757 this._properties["clause"] = null;
Zachary Heilbron1c0bd7f2014-03-06 12:54:09 -0800758 return this;
759 }
760
genia.likes.science@gmail.com67605862013-10-04 05:43:57 -0700761 var parameters = [];
762 if (arguments[0] instanceof Array) {
763 parameters = arguments[0];
764 } else {
765 parameters = arguments;
766 }
767
768 var expc = 0;
769 var expressions = [];
770 var variableRefs = [];
771 var isDecor = false;
Zachary Heilbron1c0bd7f2014-03-06 12:54:09 -0800772
genia.likes.science@gmail.com67605862013-10-04 05:43:57 -0700773 while (expc < parameters.length) {
774
775 if (parameters[expc] instanceof AExpression) {
776
777 isDecor = false;
778 expressions.push(parameters[expc].val());
779
Zachary Heilbron1c0bd7f2014-03-06 12:54:09 -0800780 } else if (typeof parameters[expc] == "string") {
781
genia.likes.science@gmail.com67605862013-10-04 05:43:57 -0700782 // Special keywords, decor & with
783 if (parameters[expc] == "decor") {
784 isDecor = true;
785 } else if (parameters[expc] == "with") {
786 isDecor = false;
787 expc++;
788 while (expc < parameters.length) {
789 variableRefs.push(parameters[expc]);
790 expc++;
791 }
Zachary Heilbron1c0bd7f2014-03-06 12:54:09 -0800792
genia.likes.science@gmail.com67605862013-10-04 05:43:57 -0700793 // Variables and variable refs
794 } else {
Zachary Heilbron1c0bd7f2014-03-06 12:54:09 -0800795
genia.likes.science@gmail.com67605862013-10-04 05:43:57 -0700796 var nextc = expc + 1;
797 var expression = "";
Zachary Heilbron1c0bd7f2014-03-06 12:54:09 -0800798
genia.likes.science@gmail.com67605862013-10-04 05:43:57 -0700799 if (isDecor) {
Zachary Heilbron1c0bd7f2014-03-06 12:54:09 -0800800 expression += "decor ";
genia.likes.science@gmail.com67605862013-10-04 05:43:57 -0700801 isDecor = false;
802 }
803
804 expression += parameters[expc] + " := " + parameters[nextc].val();
805 expressions.push(expression);
806 expc++;
807 }
808 }
809
810 expc++;
811 }
812
813 this._properties["clause"] = "group by " + expressions.join(", ") + " with " + variableRefs.join(", ");
814 return this;
815}
816
817GroupClause.prototype = Object.create(AQLClause.prototype);
818GroupClause.prototype.constructor = GroupClause;
819
820
821// Quantified Expression
Zachary Heilbron1c0bd7f2014-03-06 12:54:09 -0800822//
genia.likes.science@gmail.com67605862013-10-04 05:43:57 -0700823// Grammar
824// QuantifiedExpression ::= ( ( "some" ) | ( "every" ) ) Variable "in" Expression ( "," Variable "in" Expression )* "satisfies" Expression
Zachary Heilbron1c0bd7f2014-03-06 12:54:09 -0800825//
genia.likes.science@gmail.com67605862013-10-04 05:43:57 -0700826// @param String some/every
827// @param [AExpression]
828// @param [Aexpression] satisfiesExpression
829function QuantifiedExpression (keyword, expressions, satisfiesExpression) {
830 AExpression.call(this);
831
832 var expression = keyword + " ";
833 var varsInExpressions = [];
834
835 for (var varInExpression in expressions) {
Zachary Heilbron1c0bd7f2014-03-06 12:54:09 -0800836 varsInExpressions.push(varInExpression + " in " + expressions[varInExpression].val());
837 }
genia.likes.science@gmail.com67605862013-10-04 05:43:57 -0700838 expression += varsInExpressions.join(", ") + " satisfies " + satisfiesExpression.val();
Zachary Heilbron1c0bd7f2014-03-06 12:54:09 -0800839
genia.likes.science@gmail.com67605862013-10-04 05:43:57 -0700840 AExpression.prototype.set.call(this, expression);
841
842 return this;
843}
844
845QuantifiedExpression.prototype = Object.create(AExpression.prototype);
846QuantifiedExpression.prototype.constructor = QuantifiedExpression;
847
848QuantifiedExpression.prototype.val = function() {
849 var value = AExpression.prototype.val.call(this);
Zachary Heilbron1c0bd7f2014-03-06 12:54:09 -0800850 return "(" + value + ")";
genia.likes.science@gmail.com67605862013-10-04 05:43:57 -0700851};