blob: ed304064cbbee7b9f394a3edfab2056fd6fe1d0f [file] [log] [blame]
Ian Maxon032a1782015-06-30 17:10:51 -07001/*
Ian Maxon928bbd12015-09-14 17:12:48 -07002 * Licensed to the Apache Software Foundation (ASF) under one
3 * or more contributor license agreements. See the NOTICE file
4 * distributed with this work for additional information
5 * regarding copyright ownership. The ASF licenses this file
6 * to you under the Apache License, Version 2.0 (the
7 * "License"); you may not use this file except in compliance
8 * with the License. You may obtain a copy of the License at
Ian Maxon032a1782015-06-30 17:10:51 -07009 *
Ian Maxon928bbd12015-09-14 17:12:48 -070010 * http://www.apache.org/licenses/LICENSE-2.0
Ian Maxon032a1782015-06-30 17:10:51 -070011 *
Ian Maxon928bbd12015-09-14 17:12:48 -070012 * Unless required by applicable law or agreed to in writing,
13 * software distributed under the License is distributed on an
14 * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
15 * KIND, either express or implied. See the License for the
16 * specific language governing permissions and limitations
17 * under the License.
Ian Maxon032a1782015-06-30 17:10:51 -070018 */
19
genia.likes.science@gmail.com67605862013-10-04 05:43:57 -070020function AsterixDBConnection(configuration) {
21 this._properties = {};
22 this._properties["dataverse"] = "";
23 this._properties["mode"] = "synchronous";
24
25 // This is a demo setup related fix. Enabled by proxy to Asterix REST API.
26 this._properties["endpoint_root"] = "/";
Zachary Heilbron1c0bd7f2014-03-06 12:54:09 -080027
genia.likes.science@gmail.com67605862013-10-04 05:43:57 -070028 var configuration = arguments || {};
Zachary Heilbron1c0bd7f2014-03-06 12:54:09 -080029
genia.likes.science@gmail.com67605862013-10-04 05:43:57 -070030 for (var key in configuration) {
31 this._properties[key] = configuration[key];
32 }
Zachary Heilbron1c0bd7f2014-03-06 12:54:09 -080033
genia.likes.science@gmail.com67605862013-10-04 05:43:57 -070034 return this;
35}
36
37
38AsterixDBConnection.prototype.dataverse = function(dataverseName) {
39 this._properties["dataverse"] = dataverseName;
Zachary Heilbron1c0bd7f2014-03-06 12:54:09 -080040
genia.likes.science@gmail.com67605862013-10-04 05:43:57 -070041 return this;
42};
43
44
45AsterixDBConnection.prototype.query = function(statements, successFn, mode) {
genia.likes.science@gmail.com67605862013-10-04 05:43:57 -070046 if ( typeof statements === 'string') {
47 statements = [ statements ];
48 }
Zachary Heilbron1c0bd7f2014-03-06 12:54:09 -080049
genia.likes.science@gmail.com67605862013-10-04 05:43:57 -070050 var m = typeof mode ? mode : "synchronous";
Zachary Heilbron1c0bd7f2014-03-06 12:54:09 -080051
genia.likes.science@gmail.com67605862013-10-04 05:43:57 -070052 var query = "use dataverse " + this._properties["dataverse"] + ";\n" + statements.join("\n");
Zachary Heilbron1c0bd7f2014-03-06 12:54:09 -080053
genia.likes.science@gmail.com67605862013-10-04 05:43:57 -070054 this._api(
55 {
56 "query" : query,
57 "mode" : m
58 },
Zachary Heilbron1c0bd7f2014-03-06 12:54:09 -080059 successFn,
genia.likes.science@gmail.com67605862013-10-04 05:43:57 -070060 "query"
61 );
62
63 return this;
64};
65
66
67AsterixDBConnection.prototype.query_status = function(data, successFn) {
68
69 this._api(
70 data,
71 successFn,
72 "query/status"
73 );
74
75 return this;
76};
77
78
79AsterixDBConnection.prototype.query_result = function(data, successFn) {
80 this._api(
81 data,
82 successFn,
83 "query/result"
Zachary Heilbron1c0bd7f2014-03-06 12:54:09 -080084 );
genia.likes.science@gmail.com67605862013-10-04 05:43:57 -070085
86 return this;
87};
88
89
90AsterixDBConnection.prototype.ddl = function(statements, successFn) {
91 if ( typeof statements === 'string') {
92 statements = [ statements ];
93 }
Zachary Heilbron1c0bd7f2014-03-06 12:54:09 -080094
genia.likes.science@gmail.com67605862013-10-04 05:43:57 -070095 this._api(
96 {
97 "ddl" : "use dataverse " + this._properties["dataverse"] + ";\n" + statements.join("\n")
98 },
99 successFn,
100 "ddl"
101 );
102}
103
104
105AsterixDBConnection.prototype.update = function(statements, successFn) {
106 if ( typeof statements === 'string') {
107 statements = [ statements ];
108 }
Zachary Heilbron1c0bd7f2014-03-06 12:54:09 -0800109
genia.likes.science@gmail.com67605862013-10-04 05:43:57 -0700110 this._api(
111 {
112 "statements" : "use dataverse " + this._properties["dataverse"] + ";\n" + statements.join("\n")
113 },
114 successFn,
115 "update"
116 );
117}
118
119
120AsterixDBConnection.prototype._api = function(json, onSuccess, endpoint) {
121 var success_fn = onSuccess;
Zachary Heilbron1c0bd7f2014-03-06 12:54:09 -0800122 var endpoint_url = this._properties["endpoint_root"] + endpoint;
genia.likes.science@gmail.com67605862013-10-04 05:43:57 -0700123
124 $.ajax({
125 type: 'GET',
126 url: endpoint_url,
127 data : json,
128 dataType: "json",
129 success: function(data) {
130 success_fn(data);
131 },
132 error: function(xhr, status, error) {
133 }
134 });
Zachary Heilbron1c0bd7f2014-03-06 12:54:09 -0800135
genia.likes.science@gmail.com67605862013-10-04 05:43:57 -0700136 return this;
137};
138
139
140// Asterix Expressions - Base
141function AExpression () {
142
143 this._properties = {};
144 this._success = function() {};
145
146 if (arguments.length == 1) {
Zachary Heilbron1c0bd7f2014-03-06 12:54:09 -0800147 this._properties["value"] = arguments[0];
genia.likes.science@gmail.com67605862013-10-04 05:43:57 -0700148 }
149
150 return this;
151}
152
153
154AExpression.prototype.bind = function(options) {
155 var options = options || {};
156
157 if (options.hasOwnProperty("success")) {
158 this._success = options["success"];
159 }
160
161 if (options.hasOwnProperty("return")) {
162 this._properties["return"] = " return " + options["return"].val();
163 }
164};
165
166
167AExpression.prototype.run = function(successFn) {
168 return this;
169};
170
171
Zachary Heilbron1c0bd7f2014-03-06 12:54:09 -0800172AExpression.prototype.val = function() {
genia.likes.science@gmail.com67605862013-10-04 05:43:57 -0700173
174 var value = "";
175
176 // If there is a dataverse defined, provide it.
177 if (this._properties.hasOwnProperty("dataverse")) {
178 value += "use dataverse " + this._properties["dataverse"] + ";\n";
179 };
180
181 if (this._properties.hasOwnProperty("value")) {
182 value += this._properties["value"].toString();
183 }
184
185 return value;
186};
187
188
189// @param expressionValue [String]
190AExpression.prototype.set = function(expressionValue) {
Zachary Heilbron1c0bd7f2014-03-06 12:54:09 -0800191 this._properties["value"] = expressionValue;
genia.likes.science@gmail.com67605862013-10-04 05:43:57 -0700192 return this;
193};
194
195
196// AQL Statements
197// SingleStatement ::= DataverseDeclaration
198// | FunctionDeclaration
199// | CreateStatement
200// | DropStatement
201// | LoadStatement
202// | SetStatement
203// | InsertStatement
204// | DeleteStatement
205// | Query
206function InsertStatement(quantifiedName, query) {
207 AExpression.call(this);
Zachary Heilbron1c0bd7f2014-03-06 12:54:09 -0800208
genia.likes.science@gmail.com67605862013-10-04 05:43:57 -0700209 var innerQuery = "";
210 if (query instanceof AExpression) {
211 innerQuery = query.val();
212 } else if (typeof query == "object" && Object.getPrototypeOf( query ) === Object.prototype ) {
Zachary Heilbron1c0bd7f2014-03-06 12:54:09 -0800213
genia.likes.science@gmail.com67605862013-10-04 05:43:57 -0700214 var insertStatements = [];
215 for (querykey in query) {
216 if (query[querykey] instanceof AExpression) {
217 insertStatements.push('"' + querykey + '" : ' + query[querykey].val());
218 } else if (typeof query[querykey] == "string") {
219 insertStatements.push('"' + querykey + '" : ' + query[querykey]);
220 } else {
221 insertStatements.push('"' + querykey + '" : ' + query[querykey].toString());
222 }
223 }
Zachary Heilbron1c0bd7f2014-03-06 12:54:09 -0800224
genia.likes.science@gmail.com67605862013-10-04 05:43:57 -0700225 innerQuery = "{" + insertStatements.join(', ') + "}";
226 }
Zachary Heilbron1c0bd7f2014-03-06 12:54:09 -0800227
genia.likes.science@gmail.com67605862013-10-04 05:43:57 -0700228 var statement = "insert into dataset " + quantifiedName + "(" + innerQuery + ");";
Zachary Heilbron1c0bd7f2014-03-06 12:54:09 -0800229
genia.likes.science@gmail.com67605862013-10-04 05:43:57 -0700230 AExpression.prototype.set.call(this, statement);
231
232 return this;
233}
234
235InsertStatement.prototype = Object.create(AExpression.prototype);
236InsertStatement.prototype.constructor = InsertStatement;
237
238
239// Delete Statement
240// DeleteStatement ::= "delete" Variable "from" "dataset" QualifiedName ( "where" Expression )?
241function DeleteStatement (variable, quantifiedName, whereExpression) {
242 AExpression.call(this);
Zachary Heilbron1c0bd7f2014-03-06 12:54:09 -0800243
genia.likes.science@gmail.com67605862013-10-04 05:43:57 -0700244 var statement = "delete " + variable + " from dataset " + quantifiedName;
Zachary Heilbron1c0bd7f2014-03-06 12:54:09 -0800245
genia.likes.science@gmail.com67605862013-10-04 05:43:57 -0700246 if (whereExpression instanceof AExpression) {
247 statement += " where " + whereExpression.val();
248 }
Zachary Heilbron1c0bd7f2014-03-06 12:54:09 -0800249
genia.likes.science@gmail.com67605862013-10-04 05:43:57 -0700250 AExpression.prototype.set.call(this, statement);
Zachary Heilbron1c0bd7f2014-03-06 12:54:09 -0800251
genia.likes.science@gmail.com67605862013-10-04 05:43:57 -0700252 return this;
253}
254
255DeleteStatement.prototype = Object.create(AExpression.prototype);
256DeleteStatement.prototype.constructor = DeleteStatement;
257
258// SetStatement
259//
260// Grammar
261// "set" Identifier StringLiteral
262function SetStatement (identifier, stringLiteral) {
263 AExpression.call(this);
264
265 var statement = "set " + identifier + ' "' + stringLiteral + '";';
266
267 AExpression.prototype.set.call(this, statement);
268
269 return this;
270}
271
272SetStatement.prototype = Object.create(AExpression.prototype);
273SetStatement.prototype.constructor = SetStatement;
274
275
276// Other Expressions
277
278// FunctionExpression
279// Parent: AsterixExpression
Zachary Heilbron1c0bd7f2014-03-06 12:54:09 -0800280//
281// @param options [Various],
genia.likes.science@gmail.com67605862013-10-04 05:43:57 -0700282// @key function [String], a function to be applid to the expression
283// @key expression [AsterixExpression or AQLClause] an AsterixExpression/Clause to which the fn will be applied
284function FunctionExpression() {
Zachary Heilbron1c0bd7f2014-03-06 12:54:09 -0800285
genia.likes.science@gmail.com67605862013-10-04 05:43:57 -0700286 // Initialize superclass
287 AExpression.call(this);
Zachary Heilbron1c0bd7f2014-03-06 12:54:09 -0800288
genia.likes.science@gmail.com67605862013-10-04 05:43:57 -0700289 this._properties["function"] = "";
290 this._properties["expressions"] = [];
291
292 // Check for fn/expression input
293 if (arguments.length >= 2 && typeof arguments[0] == "string") {
Zachary Heilbron1c0bd7f2014-03-06 12:54:09 -0800294
genia.likes.science@gmail.com67605862013-10-04 05:43:57 -0700295 this._properties["function"] = arguments[0];
296
297 for (i = 1; i < arguments.length; i++) {
298 if (arguments[i] instanceof AExpression || arguments[i] instanceof AQLClause) {
299 this._properties["expressions"].push(arguments[i]);
300 } else {
301 this._properties["expressions"].push(new AExpression(arguments[i]));
302 }
303 }
Zachary Heilbron1c0bd7f2014-03-06 12:54:09 -0800304 }
genia.likes.science@gmail.com67605862013-10-04 05:43:57 -0700305
306 // Return FunctionCallExpression object
307 return this;
308}
309
310
311FunctionExpression.prototype = Object.create(AExpression.prototype);
312FunctionExpression.prototype.constructor = FunctionExpression;
Zachary Heilbron1c0bd7f2014-03-06 12:54:09 -0800313
genia.likes.science@gmail.com67605862013-10-04 05:43:57 -0700314
315FunctionExpression.prototype.val = function () {
316 var fn_args = [];
317 for (var i = 0; i < this._properties["expressions"].length; i++) {
318 fn_args.push(this._properties["expressions"][i].val());
319 }
320
321 return this._properties["function"] + "(" + fn_args.join(", ") + ")";
322};
323
324
325// FLWOGRExpression
326//
327// FLWOGRExpression ::= ( ForClause | LetClause ) ( Clause )* "return" Expression
328function FLWOGRExpression (options) {
329 // Initialize superclass
330 AExpression.call(this);
331
332 this._properties["clauses"] = [];
333 this._properties["minSize"] = 0;
334
335 // Bind options and return
336 this.bind(options);
337 return this;
338}
339
340
341FLWOGRExpression.prototype = Object.create(AExpression.prototype);
342FLWOGRExpression.prototype.constructor = FLWOGRExpression;
343
344
345FLWOGRExpression.prototype.bind = function(options) {
346 AExpression.prototype.bind.call(this, options);
347
348 var options = options || {};
349
350 if (options instanceof SetStatement) {
351 this._properties["clauses"].push(options);
352 this._properties["minSize"] += 1;
353 }
354
355 if (this._properties["clauses"].length <= this._properties["minSize"]) {
356 // Needs to start with for or let clause
357 if (options instanceof ForClause || options instanceof LetClause) {
358 this._properties["clauses"].push(options);
359 }
360 } else {
361 if (options instanceof AQLClause) {
362 this._properties["clauses"].push(options);
363 }
364 }
365
366 return this;
367};
368
369
370FLWOGRExpression.prototype.val = function() {
371 var value = AExpression.prototype.val.call(this);
372
373 var clauseValues = [];
374 for (var c in this._properties["clauses"]) {
375 clauseValues.push(this._properties["clauses"][c].val());
376 }
377
378 return value + clauseValues.join("\n");// + ";";
379};
380
381// Pretty Expression Shorthand
382
383FLWOGRExpression.prototype.ReturnClause = function(expression) {
384 return this.bind(new ReturnClause(expression));
385};
386
387FLWOGRExpression.prototype.ForClause = function() {
388 return this.bind(new ForClause(Array.prototype.slice.call(arguments)));
389};
390
391FLWOGRExpression.prototype.LetClause = function() {
392 return this.bind(new LetClause(Array.prototype.slice.call(arguments)));
393};
394
395FLWOGRExpression.prototype.WhereClause = function() {
396 return this.bind(new WhereClause(Array.prototype.slice.call(arguments)));
397};
398
399FLWOGRExpression.prototype.and = function() {
400 var args = Array.prototype.slice.call(arguments);
401 args.push(true);
402 return this.bind(new WhereClause().and(args));
403};
404
405FLWOGRExpression.prototype.or = function() {
406 var args = Array.prototype.slice.call(arguments);
407 args.push(true);
408 return this.bind(new WhereClause().or(args));
409};
410
411FLWOGRExpression.prototype.OrderbyClause = function() {
412 return this.bind(new OrderbyClause(Array.prototype.slice.call(arguments)));
413};
414
415
416FLWOGRExpression.prototype.GroupClause = function() {
417 return this.bind(new GroupClause(Array.prototype.slice.call(arguments)));
418};
419
420FLWOGRExpression.prototype.LimitClause = function() {
421 return this.bind(new LimitClause(Array.prototype.slice.call(arguments)));
422};
423
424FLWOGRExpression.prototype.DistinctClause = function() {
425 return this.bind(new DistinctClause(Array.prototype.slice.call(arguments)));
426};
427
428FLWOGRExpression.prototype.AQLClause = function() {
429 return this.bind(new AQLClause(Array.prototype.slice.call(arguments)));
430};
431
432
433// AQLClause
434//
435// Base Clause ::= ForClause | LetClause | WhereClause | OrderbyClause | GroupClause | LimitClause | DistinctClause
436function AQLClause() {
437 this._properties = {};
438 this._properties["clause"] = "";
439 this._properties["stack"] = [];
440 if (typeof arguments[0] == 'string') {
441 this._properties["clause"] = arguments[0];
442 }
443 return this;
444}
445
446AQLClause.prototype.val = function() {
447 var value = this._properties["clause"];
Zachary Heilbron1c0bd7f2014-03-06 12:54:09 -0800448
genia.likes.science@gmail.com67605862013-10-04 05:43:57 -0700449 return value;
450};
451
452AQLClause.prototype.bind = function(options) {
453
454 if (options instanceof AQLClause) {
455 this._properties["clause"] += " " + options.val();
456 }
457
458 return this;
459};
460
461AQLClause.prototype.set = function(value) {
462 this._properties["clause"] = value;
463 return this;
464};
465
466
467// ForClause
468//
469// Grammar:
470// "for" Variable ( "at" Variable )? "in" ( Expression )
471//
Zachary Heilbron1c0bd7f2014-03-06 12:54:09 -0800472// @param for_variable [String], REQUIRED, first variable in clause
genia.likes.science@gmail.com67605862013-10-04 05:43:57 -0700473// @param at_variable [String], NOT REQUIRED, first variable in clause
474// @param expression [AsterixExpression], REQUIRED, expression to evaluate
475function ForClause(for_variable, at_variable, expression) {
476 AQLClause.call(this);
Zachary Heilbron1c0bd7f2014-03-06 12:54:09 -0800477
genia.likes.science@gmail.com67605862013-10-04 05:43:57 -0700478 var parameters = [];
479 if (arguments[0] instanceof Array) {
480 parameters = arguments[0];
481 } else {
482 parameters = arguments;
483 }
Zachary Heilbron1c0bd7f2014-03-06 12:54:09 -0800484
genia.likes.science@gmail.com67605862013-10-04 05:43:57 -0700485 this._properties["clause"] = "for " + parameters[0];
Zachary Heilbron1c0bd7f2014-03-06 12:54:09 -0800486
genia.likes.science@gmail.com67605862013-10-04 05:43:57 -0700487 if (parameters.length == 3) {
488 this._properties["clause"] += " at " + parameters[1];
489 this._properties["clause"] += " in " + parameters[2].val();
490 } else if (parameters.length == 2) {
491 this._properties["clause"] += " in " + parameters[1].val();
492 }
Zachary Heilbron1c0bd7f2014-03-06 12:54:09 -0800493
genia.likes.science@gmail.com67605862013-10-04 05:43:57 -0700494 return this;
495}
496
497ForClause.prototype = Object.create(AQLClause.prototype);
498ForClause.prototype.constructor = ForClause;
499
500
501// LetClause
502//
503// Grammar:
504// LetClause ::= "let" Variable ":=" Expression
505//
506// @param let_variable [String]
507// @param expression [AExpression]
508//
509// TODO Vigorous error checking
510function LetClause(let_variable, expression) {
511 AQLClause.call(this);
Zachary Heilbron1c0bd7f2014-03-06 12:54:09 -0800512
genia.likes.science@gmail.com67605862013-10-04 05:43:57 -0700513 var parameters = [];
514 if (arguments[0] instanceof Array) {
515 parameters = arguments[0];
516 } else {
517 parameters = arguments;
518 }
Zachary Heilbron1c0bd7f2014-03-06 12:54:09 -0800519
genia.likes.science@gmail.com67605862013-10-04 05:43:57 -0700520 this._properties["clause"] = "let " + parameters[0] + " := ";
521 this._properties["clause"] += parameters[1].val();
Zachary Heilbron1c0bd7f2014-03-06 12:54:09 -0800522
523 return this;
genia.likes.science@gmail.com67605862013-10-04 05:43:57 -0700524}
525
526LetClause.prototype = Object.create(AQLClause.prototype);
527LetClause.prototype.constructor = LetClause;
528
529
530// ReturnClause
531//
532// Grammar:
533// return [AQLExpression]
534function ReturnClause(expression) {
535 AQLClause.call(this);
536
537 this._properties["clause"] = "return ";
Zachary Heilbron1c0bd7f2014-03-06 12:54:09 -0800538
genia.likes.science@gmail.com67605862013-10-04 05:43:57 -0700539 if (expression instanceof AExpression || expression instanceof AQLClause) {
540 this._properties["clause"] += expression.val();
Zachary Heilbron1c0bd7f2014-03-06 12:54:09 -0800541
genia.likes.science@gmail.com67605862013-10-04 05:43:57 -0700542 } else if ( typeof expression == "object" && Object.getPrototypeOf( expression ) === Object.prototype ) {
Zachary Heilbron1c0bd7f2014-03-06 12:54:09 -0800543
genia.likes.science@gmail.com67605862013-10-04 05:43:57 -0700544 this._properties["clause"] += "\n{\n";
545 var returnStatements = [];
546 for (returnValue in expression) {
Zachary Heilbron1c0bd7f2014-03-06 12:54:09 -0800547
548 if (expression[returnValue] instanceof AExpression) {
549 returnStatements.push('"' + returnValue + '" ' + " : " + expression[returnValue].val());
550 } else if (typeof expression[returnValue] == "string") {
551 returnStatements.push('"' + returnValue + '" ' + " : " + expression[returnValue]);
genia.likes.science@gmail.com67605862013-10-04 05:43:57 -0700552 }
553 }
554 this._properties["clause"] += returnStatements.join(",\n");
Zachary Heilbron1c0bd7f2014-03-06 12:54:09 -0800555 this._properties["clause"] += "\n}";
556
genia.likes.science@gmail.com67605862013-10-04 05:43:57 -0700557 } else {
558 this._properties["clause"] += new AQLClause().set(expression).val();
559 }
560
561 return this;
562}
563
564
565ReturnClause.prototype = Object.create(AQLClause.prototype);
566ReturnClause.prototype.constructor = ReturnClause;
567
568
569// WhereClause
570//
Zachary Heilbron1c0bd7f2014-03-06 12:54:09 -0800571// Grammar:
genia.likes.science@gmail.com67605862013-10-04 05:43:57 -0700572// ::= "where" Expression
Zachary Heilbron1c0bd7f2014-03-06 12:54:09 -0800573//
genia.likes.science@gmail.com67605862013-10-04 05:43:57 -0700574// @param expression [BooleanExpression], pushes this expression onto the stack
575function WhereClause(expression) {
576 AQLClause.call(this);
Zachary Heilbron1c0bd7f2014-03-06 12:54:09 -0800577
genia.likes.science@gmail.com67605862013-10-04 05:43:57 -0700578 this._properties["stack"] = [];
579
580 if (expression instanceof Array) {
581 this.bind(expression[0]);
582 } else {
583 this.bind(expression);
584 }
Zachary Heilbron1c0bd7f2014-03-06 12:54:09 -0800585
genia.likes.science@gmail.com67605862013-10-04 05:43:57 -0700586 return this;
587}
588
589
590WhereClause.prototype = Object.create(AQLClause.prototype);
591WhereClause.prototype.constructor = WhereClause;
592
593
594WhereClause.prototype.bind = function(expression) {
595 if (expression instanceof AExpression) {
596 this._properties["stack"].push(expression);
597 }
598 return this;
599};
600
601
602WhereClause.prototype.val = function() {
Zachary Heilbron1c0bd7f2014-03-06 12:54:09 -0800603 var value = "";
604
genia.likes.science@gmail.com67605862013-10-04 05:43:57 -0700605 if (this._properties["stack"].length == 0) {
606 return value;
607 }
608
609 var count = this._properties["stack"].length - 1;
610 while (count >= 0) {
611 value += this._properties["stack"][count].val() + " ";
612 count -= 1;
613 }
Zachary Heilbron1c0bd7f2014-03-06 12:54:09 -0800614
genia.likes.science@gmail.com67605862013-10-04 05:43:57 -0700615 return "where " + value;
616};
617
618
619WhereClause.prototype.and = function() {
Zachary Heilbron1c0bd7f2014-03-06 12:54:09 -0800620
genia.likes.science@gmail.com67605862013-10-04 05:43:57 -0700621 var parameters = [];
622 if (arguments[0] instanceof Array) {
623 parameters = arguments[0];
624 } else {
625 parameters = arguments;
626 }
Zachary Heilbron1c0bd7f2014-03-06 12:54:09 -0800627
628 var andClauses = [];
genia.likes.science@gmail.com67605862013-10-04 05:43:57 -0700629 for (var expression in parameters) {
Zachary Heilbron1c0bd7f2014-03-06 12:54:09 -0800630
genia.likes.science@gmail.com67605862013-10-04 05:43:57 -0700631 if (parameters[expression] instanceof AExpression) {
632 andClauses.push(parameters[expression].val());
633 }
634 }
Zachary Heilbron1c0bd7f2014-03-06 12:54:09 -0800635
genia.likes.science@gmail.com67605862013-10-04 05:43:57 -0700636 if (andClauses.length > 0) {
637 this._properties["stack"].push(new AExpression().set(andClauses.join(" and ")));
638 }
Zachary Heilbron1c0bd7f2014-03-06 12:54:09 -0800639
genia.likes.science@gmail.com67605862013-10-04 05:43:57 -0700640 return this;
641};
642
643
644WhereClause.prototype.or = function() {
645
646 var parameters = [];
647 if (arguments[0] instanceof Array) {
648 parameters = arguments[0];
649 } else {
650 parameters = arguments;
651 }
652
Zachary Heilbron1c0bd7f2014-03-06 12:54:09 -0800653 var orClauses = [];
genia.likes.science@gmail.com67605862013-10-04 05:43:57 -0700654 for (var expression in parameters) {
Zachary Heilbron1c0bd7f2014-03-06 12:54:09 -0800655
genia.likes.science@gmail.com67605862013-10-04 05:43:57 -0700656 if (parameters[expression] instanceof AExpression) {
657 orClauses.push(parameters[expression].val());
658 }
659 }
Zachary Heilbron1c0bd7f2014-03-06 12:54:09 -0800660
genia.likes.science@gmail.com67605862013-10-04 05:43:57 -0700661 if (andClauses.length > 0) {
662 this._properties["stack"].push(new AExpression().set(orClauses.join(" and ")));
663 }
Zachary Heilbron1c0bd7f2014-03-06 12:54:09 -0800664
genia.likes.science@gmail.com67605862013-10-04 05:43:57 -0700665 return this;
666};
667
668// LimitClause
669// Grammar:
670// LimitClause ::= "limit" Expression ( "offset" Expression )?
Zachary Heilbron1c0bd7f2014-03-06 12:54:09 -0800671//
genia.likes.science@gmail.com67605862013-10-04 05:43:57 -0700672// @param limitExpression [REQUIRED, AQLExpression]
673// @param offsetExpression [OPTIONAL, AQLExpression]
674function LimitClause(limitExpression, offsetExpression) {
675
676 AQLClause.call(this);
Zachary Heilbron1c0bd7f2014-03-06 12:54:09 -0800677
genia.likes.science@gmail.com67605862013-10-04 05:43:57 -0700678 var parameters = [];
679 if (arguments[0] instanceof Array) {
680 parameters = arguments[0];
681 } else {
682 parameters = arguments;
683 }
Zachary Heilbron1c0bd7f2014-03-06 12:54:09 -0800684
genia.likes.science@gmail.com67605862013-10-04 05:43:57 -0700685 // limitExpression required
686 this._properties["clause"] = "limit " + parameters[0].val();
687
688 // Optional: Offset
689 if (parameters.length == 2) {
690 this._properties["clause"] += " offset " + parameters[1].val();
691 }
692
693 return this;
694}
695
696LimitClause.prototype = Object.create(AQLClause.prototype);
697LimitClause.prototype.constructor = LimitClause;
698
699
700// OrderbyClause
701//
702// Grammar:
703// OrderbyClause ::= "order" "by" Expression ( ( "asc" ) | ( "desc" ) )? ( "," Expression ( ( "asc" ) | ( "desc" ) )? )*
704//
Zachary Heilbron1c0bd7f2014-03-06 12:54:09 -0800705// @params AQLExpressions and asc/desc strings, in any quantity. At least one required.
genia.likes.science@gmail.com67605862013-10-04 05:43:57 -0700706function OrderbyClause() {
Zachary Heilbron1c0bd7f2014-03-06 12:54:09 -0800707
genia.likes.science@gmail.com67605862013-10-04 05:43:57 -0700708 AQLClause.call(this);
709
710 // At least one argument expression is required, and first should be expression
711 if (arguments.length == 0) {
712 this._properties["clause"] = null;
Zachary Heilbron1c0bd7f2014-03-06 12:54:09 -0800713 return this;
genia.likes.science@gmail.com67605862013-10-04 05:43:57 -0700714 }
Zachary Heilbron1c0bd7f2014-03-06 12:54:09 -0800715
genia.likes.science@gmail.com67605862013-10-04 05:43:57 -0700716 var parameters = [];
717 if (arguments[0] instanceof Array) {
718 parameters = arguments[0];
719 } else {
720 parameters = arguments;
721 }
722
723 var expc = 0;
Zachary Heilbron1c0bd7f2014-03-06 12:54:09 -0800724 var expressions = [];
genia.likes.science@gmail.com67605862013-10-04 05:43:57 -0700725
726 while (expc < parameters.length) {
Zachary Heilbron1c0bd7f2014-03-06 12:54:09 -0800727
genia.likes.science@gmail.com67605862013-10-04 05:43:57 -0700728 var expression = "";
729
730 if (parameters[expc] instanceof AExpression) {
731 expression += parameters[expc].val();
732 }
733
734 var next = expc + 1;
735 if (next < parameters.length && (parameters[next] == "asc" || parameters[next] == "desc")) {
736 expc++;
737 expression += " " + parameters[expc];
738 }
Zachary Heilbron1c0bd7f2014-03-06 12:54:09 -0800739
genia.likes.science@gmail.com67605862013-10-04 05:43:57 -0700740 expressions.push(expression);
Zachary Heilbron1c0bd7f2014-03-06 12:54:09 -0800741
genia.likes.science@gmail.com67605862013-10-04 05:43:57 -0700742 expc++;
743 }
744
745 this._properties["clause"] = "order by " + expressions.join(", ");
746 return this;
747}
748
749OrderbyClause.prototype = Object.create(AQLClause.prototype);
750OrderbyClause.prototype.constructor = OrderbyClause;
751
752
753// GroupClause
754//
755// Grammar:
756// GroupClause ::= "group" "by" ( Variable ":=" )? Expression ( "," ( Variable ":=" )? Expression )* ( "decor" Variable ":=" Expression ( "," "decor" Variable ":=" Expression )* )? "with" VariableRef ( "," VariableRef )*
757function GroupClause() {
758 AQLClause.call(this);
759
760 if (arguments.length == 0) {
761 this._properties["clause"] = null;
Zachary Heilbron1c0bd7f2014-03-06 12:54:09 -0800762 return this;
763 }
764
genia.likes.science@gmail.com67605862013-10-04 05:43:57 -0700765 var parameters = [];
766 if (arguments[0] instanceof Array) {
767 parameters = arguments[0];
768 } else {
769 parameters = arguments;
770 }
771
772 var expc = 0;
773 var expressions = [];
774 var variableRefs = [];
775 var isDecor = false;
Zachary Heilbron1c0bd7f2014-03-06 12:54:09 -0800776
genia.likes.science@gmail.com67605862013-10-04 05:43:57 -0700777 while (expc < parameters.length) {
778
779 if (parameters[expc] instanceof AExpression) {
780
781 isDecor = false;
782 expressions.push(parameters[expc].val());
783
Zachary Heilbron1c0bd7f2014-03-06 12:54:09 -0800784 } else if (typeof parameters[expc] == "string") {
785
genia.likes.science@gmail.com67605862013-10-04 05:43:57 -0700786 // Special keywords, decor & with
787 if (parameters[expc] == "decor") {
788 isDecor = true;
789 } else if (parameters[expc] == "with") {
790 isDecor = false;
791 expc++;
792 while (expc < parameters.length) {
793 variableRefs.push(parameters[expc]);
794 expc++;
795 }
Zachary Heilbron1c0bd7f2014-03-06 12:54:09 -0800796
genia.likes.science@gmail.com67605862013-10-04 05:43:57 -0700797 // Variables and variable refs
798 } else {
Zachary Heilbron1c0bd7f2014-03-06 12:54:09 -0800799
genia.likes.science@gmail.com67605862013-10-04 05:43:57 -0700800 var nextc = expc + 1;
801 var expression = "";
Zachary Heilbron1c0bd7f2014-03-06 12:54:09 -0800802
genia.likes.science@gmail.com67605862013-10-04 05:43:57 -0700803 if (isDecor) {
Zachary Heilbron1c0bd7f2014-03-06 12:54:09 -0800804 expression += "decor ";
genia.likes.science@gmail.com67605862013-10-04 05:43:57 -0700805 isDecor = false;
806 }
807
808 expression += parameters[expc] + " := " + parameters[nextc].val();
809 expressions.push(expression);
810 expc++;
811 }
812 }
813
814 expc++;
815 }
816
817 this._properties["clause"] = "group by " + expressions.join(", ") + " with " + variableRefs.join(", ");
818 return this;
819}
820
821GroupClause.prototype = Object.create(AQLClause.prototype);
822GroupClause.prototype.constructor = GroupClause;
823
824
825// Quantified Expression
Zachary Heilbron1c0bd7f2014-03-06 12:54:09 -0800826//
genia.likes.science@gmail.com67605862013-10-04 05:43:57 -0700827// Grammar
828// QuantifiedExpression ::= ( ( "some" ) | ( "every" ) ) Variable "in" Expression ( "," Variable "in" Expression )* "satisfies" Expression
Zachary Heilbron1c0bd7f2014-03-06 12:54:09 -0800829//
genia.likes.science@gmail.com67605862013-10-04 05:43:57 -0700830// @param String some/every
831// @param [AExpression]
832// @param [Aexpression] satisfiesExpression
833function QuantifiedExpression (keyword, expressions, satisfiesExpression) {
834 AExpression.call(this);
835
836 var expression = keyword + " ";
837 var varsInExpressions = [];
838
839 for (var varInExpression in expressions) {
Zachary Heilbron1c0bd7f2014-03-06 12:54:09 -0800840 varsInExpressions.push(varInExpression + " in " + expressions[varInExpression].val());
841 }
genia.likes.science@gmail.com67605862013-10-04 05:43:57 -0700842 expression += varsInExpressions.join(", ") + " satisfies " + satisfiesExpression.val();
Zachary Heilbron1c0bd7f2014-03-06 12:54:09 -0800843
genia.likes.science@gmail.com67605862013-10-04 05:43:57 -0700844 AExpression.prototype.set.call(this, expression);
845
846 return this;
847}
848
849QuantifiedExpression.prototype = Object.create(AExpression.prototype);
850QuantifiedExpression.prototype.constructor = QuantifiedExpression;
851
852QuantifiedExpression.prototype.val = function() {
853 var value = AExpression.prototype.val.call(this);
Zachary Heilbron1c0bd7f2014-03-06 12:54:09 -0800854 return "(" + value + ")";
genia.likes.science@gmail.com67605862013-10-04 05:43:57 -0700855};