• Home
  • Features
  • Pricing
  • Docs
  • Announcements
  • Sign In

terminusdb / terminusdb-client-js / 20209064664

14 Dec 2025 02:00PM UTC coverage: 58.679% (-0.2%) from 58.84%
20209064664

Pull #354

github

web-flow
Merge 62f59cd56 into 760854714
Pull Request #354: TerminusDB Issue/2284 set operators

2458 of 4726 branches covered (52.01%)

Branch coverage included in aggregate %.

15 of 48 new or added lines in 3 files covered. (31.25%)

4 existing lines in 1 file now uncovered.

4215 of 6646 relevant lines covered (63.42%)

42.87 hits per line

Source File
Press 'n' to go to next uncovered line, 'b' for previous

79.53
/lib/query/woqlQuery.js
1
/* eslint-disable class-methods-use-this */
2
/* eslint-disable no-redeclare */
3
/* eslint-disable block-scoped-var */
4
/* eslint-disable no-var */
5
/* eslint-disable vars-on-top */
6
/* eslint-disable no-param-reassign */
7
/* eslint-disable no-unused-vars */
8
/* eslint-disable camelcase */
9
/* eslint-disable no-plusplus */
10
/* eslint-disable prefer-destructuring */
11
/* eslint-disable guard-for-in */
12
/* eslint-disable no-restricted-syntax */
13

14
/// /@ts-check
15
// WOQLQuery
16
/**
17
 * defines the internal functions of the woql query object - the
18
 * language API is defined in WOQLQuery
19
 * @module WOQLQuery
20
 * @constructor
21
 * @param {object} [query] json-ld query for initialisation
22
 * @returns {WOQLQuery}
23
 */
24

25
const WOQLCore = require('./woqlCore');
1✔
26
const { Var, Vars, Doc } = require('./woqlDoc');
1✔
27
// eslint-disable-next-line no-unused-vars
28
const typedef = require('../typedef');
1✔
29

30
// I HAVE TO REVIEW THE Inheritance and the prototype chain
31
class WOQLQuery extends WOQLCore {
2✔
32
  /**
33
   * defines the internal functions of the woql query object - the
34
   * language API is defined in WOQLQuery
35
   * @module WOQLQuery
36
   * @constructor
37
   * @param {object} [query] json-ld query for initialisation
38
   * @returns {WOQLQuery}
39
   */
40

41
  /**
42
 * Update a pattern matching rule for the triple (Subject, Predicate, oldObjValue) with the
43
 * new one (Subject, Predicate, newObjValue)
44
 * @param {string|Var} subject - The IRI of a triple’s subject or a variable
45
 * @param {string|Var} predicate - The IRI of a property or a variable
46
 * @param {string|Var} newObjValue - The value to update or a literal
47
 * @param {string|Var} oldObjValue - The old value of the object
48
 * @returns {WOQLQuery} A WOQLQuery which contains the a Update Triple Statement
49
 */
50
  update_triple(subject, predicate, newObjValue, oldObjValue) { return this; }
×
51

52
  /**
53
 * Generates a query that by default matches all triples in a graph identified by "graph"
54
 * or in all the current terminusDB's graph
55
 * @param {string | boolean} [graph] - false or the resource identifier of a graph possible
56
 * value are schema/{main - myschema - *} | instance/{main - myschema - *}  |
57
 * inference/{main - myschema - *}
58
 * @param {string|Var} [subject] - The IRI of a triple’s subject or a variable,
59
 * default value "v:Subject"
60
 * @param {string|Var} [predicate] - The IRI of a property or a variable,
61
 *  default value "v:Predicate"
62
 * @param {string|Var} [object] - The IRI of a node or a variable, or a literal,
63
 * default value "v:Object"
64
 * @returns {WOQLQuery} A WOQLQuery which contains the pattern matching expression
65
 */
66
  star(graph, subject, predicate, object) { return this; }
×
67

68
  /**
69
  * Update a pattern matching rule for the quad [S, P, O, G] (Subject, Predicate, Object, Graph)
70
  * @param {string|Var} subject - The IRI of a triple’s subject or a variable
71
  * @param {string|Var} predicate - The IRI of a property or a variable
72
  * @param {string|Var} newObject - The value to update or a literal
73
  * @param {typedef.GraphRef} graphRef - A valid graph resource identifier string
74
  * @returns {WOQLQuery} A WOQLQuery which contains the a Update Quad Statement
75
  */
76
  update_quad(subject, predicate, newObject, graphRef) { return this; }
×
77

78
  /**
79
   * @param {string|Var} id - IRI string or variable containing
80
   * @param {string|Var} type  -  IRI string or variable containing the IRI of the
81
   * @param {typedef.GraphRef} [refGraph] - Optional Graph resource identifier
82
   * @returns {WOQLQuery} A WOQLQuery which contains the insert expression
83
   */
84
  insert(id, type, refGraph) { return this; }
×
85

86
  /**
87
  * Sets the graph resource ID that will be used for subsequent chained function calls
88
  * @param {typedef.GraphRef} [graphRef] Resource String identifying the graph which will
89
  * be used for subsequent chained schema calls
90
  * @returns {WOQLQuery} A WOQLQuery which contains the partial Graph pattern matching expression
91
  */
UNCOV
92
  graph(graphRef) { return this; }
×
93

94
  /**
95
   * Specifies the identity of a node that can then be used in subsequent builder functions.
96
   * Note that node() requires subsequent chained functions to complete the triples / quads
97
   * that it produces - by itself it only generates the subject.
98
   * @param {string|Var} nodeid -  The IRI of a node or a variable containing an IRI which will
99
   * be the subject of the builder functions
100
   * @param {typedef.FuntionType} [chainType] - Optional type of builder function to build
101
   * (default is triple)
102
   * @returns {WOQLQuery} - A WOQLQuery which contains the partial Node pattern matching expression
103
   */
104
  node(nodeid, chainType) { return this; }
×
105

106
  /**
107
   * Deletes all triples in the passed graph (defaults to instance/main)
108
   * @param {typedef.GraphRef} [graphRef] - Resource String identifying the graph from
109
   * which all triples will be removed
110
   * @returns {WOQLQuery} - A WOQLQuery which contains the deletion expression
111
   * @example
112
   * nuke("schema/main")
113
   * //will delete everything from the schema/main graph
114
   */
115
  nuke(graphRef) { return this; }
×
116

117
  /**
118
   * @param {string|Var} [Subj] - The IRI of a triple’s subject or a variable
119
   * @param {string|Var} [Pred] - The IRI of a property or a variable
120
   * @param {string|Var} [Obj] - The IRI of a node or a variable, or a literal
121
   * @param {typedef.GraphRef} [Graph] - the resource identifier of a graph possible
122
   * @returns {WOQLQuery} - A WOQLQuery which contains the pattern matching expression
123
   */
124
  all(Subj, Pred, Obj, Graph) { return this; }
×
125

126
  /**
127
   * @param {boolean} tf
128
   * @returns {object}
129
   */
UNCOV
130
  boolean(tf) { return {}; }
×
131

132
  /**
133
   * @param {string} s
134
   * @returns {object}
135
   */
UNCOV
136
  string(s) { return {}; }
×
137

138
  /**
139
 * @param {any} s
140
 * @param {string} t
141
 * @returns {object}
142

143
 */
144
  literal(s, t) { return {}; }
×
145

146
  /**
147
   * @param {string} s
148
   * @returns {object}
149
   */
UNCOV
150
  iri(s) { return {}; }
×
151

152
  // eslint-disable-next-line no-underscore-dangle
153
  _set_context(ctxt) { return this; }
×
154

155
  /**
156
   * @param {WOQLQuery} Subq
157
   * @returns {WOQLQuery}
158
   */
159
  addSubQuery(Subq) {
160
    super.addSubQuery(Subq);
199✔
161
    return this;
199✔
162
  }
163

164
  /**
165
   * @param {string} msg
166
   * @returns {WOQLQuery}
167
   */
168
  parameterError(msg) {
169
    super.parameterError(msg);
3✔
170
    return this;
3✔
171
  }
172

173
  /**
174
   * @returns {WOQLQuery}
175
   */
176
  updated() {
177
    super.updated();
39✔
178
    return this;
39✔
179
  }
1✔
180

181
  // eslint-disable-next-line no-useless-constructor
182
  constructor(query) {
740✔
183
    super(query);
184
  }
1✔
185
}
186

187
/**
188
 * Read a node identified by an IRI as a JSON-LD document
189
 * @param {string} IRI -  The document id  or a variable to read
190
 * @param {string} output - Variable which will be bound to the document.
191
 * @return {WOQLQuery} WOQLQuery
192
 */
193
WOQLQuery.prototype.read_document = function (IRI, output) {
1✔
194
  if (this.cursor['@type']) this.wrapCursorWithAnd();
4!
195
  this.cursor['@type'] = 'ReadDocument';
4✔
196
  this.cursor.identifier = this.cleanNodeValue(IRI);
4✔
197
  this.cursor.document = this.expandValueVariable(output);
4✔
198
  return this;
4✔
199
};
200

201
/**
202
 * Insert a document in the graph.
203
 * @param {object} docjson -  The document to insert. Must either have an '@id' or
204
 * have a class specified key.
205
 * @param {string} [IRI] - An optional identifier specifying the document location.
206
 * @return {WOQLQuery} WOQLQuery
207
 */
208

209
WOQLQuery.prototype.insert_document = function (docjson, IRI) {
1✔
210
  if (this.cursor['@type']) this.wrapCursorWithAnd();
4!
211
  this.cursor['@type'] = 'InsertDocument';
4✔
212
  if (typeof IRI !== 'undefined') this.cursor.identifier = this.cleanNodeValue(IRI);
4✔
213

214
  this.cursor.document = this.cleanObject(docjson);
4✔
215

216
  return this.updated();
4✔
217
};
218

219
/**
220
 * Update a document identified by an IRI
221
 * @param {object} docjson -  The document to update. Must either have an '@id' or
222
 * have a class specified key.
223
 * @param {string} [IRI] - An optional identifier specifying the document location.
224
 * @return {WOQLQuery} WOQLQuery
225
 */
226

227
WOQLQuery.prototype.update_document = function (docjson, IRI) {
1✔
228
  if (this.cursor['@type']) this.wrapCursorWithAnd();
6!
229
  this.cursor['@type'] = 'UpdateDocument';
6✔
230
  if (typeof IRI !== 'undefined') this.cursor.identifier = this.cleanNodeValue(IRI);
6✔
231

232
  this.cursor.document = this.cleanObject(docjson);
6✔
233

234
  return this.updated();
6✔
235
};
236

237
/**
238
 * Delete a document from the graph.
239
 * @param {string} IRI -  The document id  or a variable
240
 * @return {WOQLQuery} WOQLQuery
241
 */
242

243
WOQLQuery.prototype.delete_document = function (IRI) {
1✔
244
  if (this.cursor['@type']) this.wrapCursorWithAnd();
3!
245
  this.cursor['@type'] = 'DeleteDocument';
3✔
246
  this.cursor.identifier = this.cleanNodeValue(IRI);
3✔
247
  return this.updated();
3✔
248
};
249

250
/**
251
 * Contains definitions of the WOQL functions which map directly to JSON-LD types
252
 * All other calls and queries can be composed from these
253
 */
254

255
// moved from woqlCore
256
WOQLQuery.prototype.wrapCursorWithAnd = function () {
1✔
257
  if (this.cursor && this.cursor['@type'] === 'And') {
154✔
258
    const newby = this.cursor.and.length;
2✔
259
    this.and({});
2✔
260
    this.cursor = this.cursor.and[newby];
2✔
261
  } else {
262
    const nj = new WOQLQuery().json(this.cursor);
152✔
263
    for (const k in this.cursor) delete this.cursor[k];
628✔
264
    // create an empty json for the new query
265
    this.and(nj, {});
152✔
266
    this.cursor = this.cursor.and[1];
152✔
267
  }
268
};
269

270
/**
271
 * Query running against any specific commit Id
272
 * @param {string}  refPath  - path to specific reference Id or commit Id
273
 * @param {WOQLQuery} [subquery] - subquery for the specific commit point
274
 * @returns {WOQLQuery}
275
 */
276

277
WOQLQuery.prototype.using = function (refPath, subquery) {
1✔
278
  if (this.cursor['@type']) this.wrapCursorWithAnd();
49!
279
  this.cursor['@type'] = 'Using';
49✔
280
  if (!refPath || typeof refPath !== 'string') {
49✔
281
    return this.parameterError('The first parameter to using must be a Collection ID (string)');
1✔
282
  }
283
  this.cursor.collection = refPath;
48✔
284
  return this.addSubQuery(subquery);
48✔
285
};
286

287
/**
288
 * Adds a text comment to a query - can also be used to wrap any part of a query to turn it off
289
 * @param {string} comment - text comment
290
 * @param {WOQLQuery} [subquery]  - query that is "commented out"
291
 * @returns {WOQLQuery}
292
 */
293

294
WOQLQuery.prototype.comment = function (comment, subquery) {
1✔
295
  // if (comment && comment === 'args')
296
  // return ['comment', 'query']
297
  if (this.cursor['@type']) this.wrapCursorWithAnd();
2!
298
  this.cursor['@type'] = 'Comment';
2✔
299
  this.cursor.comment = this.jlt(comment);
2✔
300
  return this.addSubQuery(subquery);
2✔
301
};
302

303
/**
304
 * Filters the query so that only the variables included in [V1...Vn] are returned in the bindings
305
 * @param {...string|...Var} varNames - only these variables are returned
306
 * @returns {WOQLQuery}
307
 */
308

309
WOQLQuery.prototype.select = function (...varNames) {
154✔
310
  if (this.cursor['@type']) this.wrapCursorWithAnd();
41!
311
  this.cursor['@type'] = 'Select';
41✔
312
  if (!varNames || varNames.length <= 0) {
41!
313
    return this.parameterError('Select must be given a list of variable names');
×
314
  }
315
  const last = varNames[varNames.length - 1];
41✔
316
  /**
317
  *@type {any}
318
  */
319
  let embedquery = false;
41✔
320
  if (typeof last === 'object' && !(last instanceof Var) && last.json) {
41✔
321
    embedquery = varNames.pop();
3✔
322
  } // else var embedquery = false
323
  this.cursor.variables = this.rawVarList(varNames);
41✔
324
  return this.addSubQuery(embedquery);
41✔
325
};
326

327
/**
328
 * Filter the query to return only results that are distinct in the given variables
329
 * @param {...string|...Var} varNames - these variables are guaranteed to be unique as a tuple
330
 * @returns {WOQLQuery}
331
 */
332

333
WOQLQuery.prototype.distinct = function (...varNames) {
4✔
334
  // if (list && list[0] === 'args')
335
  // return ['variable_list', 'query']
336
  if (this.cursor['@type']) this.wrapCursorWithAnd();
2!
337
  this.cursor['@type'] = 'Distinct';
2✔
338
  if (!varNames || varNames.length <= 0) {
2!
339
    return this.parameterError('Distinct must be given a list of variable names');
×
340
  }
341
  const last = varNames[varNames.length - 1];
2✔
342
  /**
343
     * @type {any}
344
     */
345
  let embedquery = false;
2✔
346
  if (typeof last === 'object' && !(last instanceof Var) && last.json) {
2✔
347
    embedquery = varNames.pop();
1✔
348
  } // else var embedquery = false
349
  this.cursor.variables = this.rawVarList(varNames);
2✔
350
  return this.addSubQuery(embedquery);
2✔
351
};
352

353
/**
354
* Logical conjunction of the contained queries - all queries must match or the entire clause fails
355
* @param {...WOQLQuery} subqueries - A list of one or more woql queries to execute as a conjunction
356
* @returns {WOQLQuery} - A WOQLQuery object containing the conjunction of queries
357
*/
358

359
WOQLQuery.prototype.and = function (...subqueries) {
497✔
360
  if (this.cursor['@type'] && this.cursor['@type'] !== 'And') {
213✔
361
    const nj = new WOQLQuery().json(this.cursor);
3✔
362
    for (const k in this.cursor) delete this.cursor[k];
11✔
363
    subqueries.unshift(nj);
3✔
364
  }
365
  this.cursor['@type'] = 'And';
213✔
366
  if (typeof this.cursor.and === 'undefined') this.cursor.and = [];
213✔
367
  for (let i = 0; i < subqueries.length; i++) {
213✔
368
    const onevar = this.jobj(subqueries[i]);
500✔
369
    if (
500✔
370
      onevar['@type'] === 'And'
548✔
371
      && onevar.and
372
    ) {
373
      for (let j = 0; j < onevar.and.length; j++) {
48✔
374
        const qjson = onevar.and[j];
150✔
375
        if (qjson) {
150!
376
          const subvar = this.jobj(qjson);
150✔
377
          this.cursor.and.push(subvar);
150✔
378
        }
379
      }
380
    } else {
381
      this.cursor.and.push(onevar);
452✔
382
    }
383
  }
384
  return this;
213✔
385
};
386

387
/**
388
 * Creates a logical OR of the arguments
389
 * @param {...WOQLQuery} subqueries - A list of one or more woql queries
390
 * to execute as alternatives
391
 * @returns {WOQLQuery} - A WOQLQuery object containing the logical Or of the subqueries
392
 */
393

394
WOQLQuery.prototype.or = function (...subqueries) {
1✔
395
  if (this.cursor['@type']) this.wrapCursorWithAnd();
2!
396
  this.cursor['@type'] = 'Or';
2✔
397
  if (typeof this.cursor.or === 'undefined') this.cursor.or = [];
2!
398
  for (let i = 0; i < subqueries.length; i++) {
2✔
399
    const onevar = this.jobj(subqueries[i]);
3!
400
    this.cursor.or.push(onevar);
3✔
401
  }
402
  return this;
2✔
403
};
404
/**
405
 * Specifies the database URL that will be the default database for the enclosed query
406
 * @param {typedef.GraphRef} graphRef- A valid graph resource identifier string
407
 * @param {WOQLQuery} [query] - The query
408
 * @returns {WOQLQuery} A WOQLQuery object containing the from expression
409
 */
410

411
/**
412
 * Specifies the database URL that will be the default database for the enclosed query
413
 * @param {typedef.GraphRef} graphRef- A valid graph resource identifier string
414
 * @param {WOQLQuery} [query] - The query
415
 * @returns {WOQLQuery} A WOQLQuery object containing the from expression
416
 */
417

418
WOQLQuery.prototype.from = function (graphRef, query) {
1✔
419
  if (this.cursor['@type']) this.wrapCursorWithAnd();
2!
420
  this.cursor['@type'] = 'From';
2✔
421
  if (!graphRef || typeof graphRef !== 'string') {
2!
422
    return this.parameterError(
×
423
      'The first parameter to from must be a Graph Filter Expression (string)',
424
    );
425
  }
426
  this.cursor.graph = this.jlt(graphRef);
2✔
427
  return this.addSubQuery(query);
2✔
428
};
429

430
/**
431
 * Specifies the graph resource to write the contained query into
432
 * @param {typedef.GraphRef} graphRef- A valid graph resource identifier string
433
 * @param {WOQLQuery} [subquery] - The query which will be written into the graph
434
 * @returns {WOQLQuery} A WOQLQuery which will be written into the graph in question
435
 */
436

437
WOQLQuery.prototype.into = function (graphRef, subquery) {
1✔
438
  // if (graph_descriptor && graph_descriptor === 'args')
439
  // return ['graph', 'query']
440
  if (this.cursor['@type']) this.wrapCursorWithAnd();
2!
441
  this.cursor['@type'] = 'Into';
2✔
442
  if (!graphRef || typeof graphRef !== 'string') {
2!
443
    return this.parameterError(
×
444
      'The first parameter to from must be a Graph Filter Expression (string)',
445
    );
446
  }
447
  this.cursor.graph = this.jlt(graphRef);
2✔
448
  return this.addSubQuery(subquery);
2✔
449
};
450

451
/**
452
 * Creates a triple pattern matching rule for the triple [S, P, O] (Subject, Predicate, Object)
453
 * @param {string|Var} subject - The IRI of a triple’s subject or a variable
454
 * @param {string|Var} predicate - The IRI of a property or a variable
455
 * @param {string|Var} object - The IRI of a node or a variable, or a literal
456
 * @returns {WOQLQuery}
457
 */
458

459
WOQLQuery.prototype.triple = function (subject, predicate, object) {
1✔
460
  // if (a && a === 'args')
461
  // return ['subject', 'predicate', 'object']
462
  if (this.cursor['@type']) this.wrapCursorWithAnd();
385✔
463
  this.cursor['@type'] = 'Triple';
385✔
464
  this.cursor.subject = this.cleanSubject(subject);
385✔
465
  this.cursor.predicate = this.cleanPredicate(predicate);
385✔
466
  this.cursor.object = this.cleanObject(object);
385✔
467
  return this;
385✔
468
};
469

470
/**
471
 * Creates a triple pattern matching rule for the triple [S, P, O] (Subject, Predicate,
472
 * Object) added in the current layer
473
 * @param {string|Var} subject - The IRI of a triple’s subject or a variable
474
 * @param {string|Var} predicate - The IRI of a property or a variable
475
 * @param {string|Var} object - The IRI of a node or a variable, or a literal
476
 * @returns {WOQLQuery}
477
 */
478

479
WOQLQuery.prototype.added_triple = function (subject, predicate, object) {
1✔
480
  // if (a && a === 'args')
481
  // return ['subject', 'predicate', 'object']
482
  if (this.cursor['@type']) this.wrapCursorWithAnd();
2!
483
  this.cursor['@type'] = 'AddedTriple';
2✔
484
  this.cursor.subject = this.cleanSubject(subject);
2✔
485
  this.cursor.predicate = this.cleanPredicate(predicate);
2✔
486
  this.cursor.object = this.cleanObject(object);
2✔
487
  return this;
2✔
488
};
489

490
/**
491
 * Creates a triple pattern matching rule for the triple [S, P, O] (Subject, Predicate,
492
 * Object) added in the current commit
493
 * @param {string|Var} subject - The IRI of a triple’s subject or a variable
494
 * @param {string|Var} predicate - The IRI of a property or a variable
495
 * @param {string|Var} object - The IRI of a node or a variable, or a literal
496
 * @returns {WOQLQuery}
497
 */
498

499
WOQLQuery.prototype.removed_triple = function (subject, predicate, object) {
1✔
500
  if (this.cursor['@type']) this.wrapCursorWithAnd();
2!
501
  this.cursor['@type'] = 'DeletedTriple';
2✔
502
  this.cursor.subject = this.cleanSubject(subject);
2✔
503
  this.cursor.predicate = this.cleanPredicate(predicate);
2✔
504
  this.cursor.object = this.cleanObject(object);
2✔
505
  return this;
2✔
506
};
507

508
/**
509
 * Creates a pattern matching rule for triple [Subject, Predicate, Object]
510
 * @param {string|Var} subject - The IRI of a triple’s subject or a variable
511
 * @param {string|Var} predicate - The IRI of a property or a variable
512
 * @param {string|Var} object - The IRI of a node or a variable, or a literal
513
 * @returns {WOQLQuery} A WOQLQuery which contains the a quad or a triple Statement
514
 */
515

516
WOQLQuery.prototype.link = function (subject, predicate, object) {
1✔
517
  if (this.cursor['@type']) this.wrapCursorWithAnd();
2!
518
  this.cursor['@type'] = 'Triple';
2✔
519
  this.cursor.subject = this.cleanSubject(subject);
2✔
520
  this.cursor.predicate = this.cleanPredicate(predicate);
2✔
521
  this.cursor.object = this.cleanSubject(object);
2✔
522
  return this;
2✔
523
};
524

525
/**
526
 * Creates a pattern matching rule for triple [Subject, Predicate, Object]
527
 * add extra information about the type of the value object
528
 * @param {string|Var} subject - The IRI of a triple’s subject or a variable
529
 * @param {string|Var} predicate - The IRI of a property or a variable
530
 * @param {string | number | boolean | Var} objValue - an specific value
531
 * @returns {WOQLQuery} A WOQLQuery which contains the a quad or a triple Statement
532
 */
533

534
WOQLQuery.prototype.value = function (subject, predicate, objValue) {
1✔
535
  if (this.cursor['@type']) this.wrapCursorWithAnd();
2!
536
  this.cursor['@type'] = 'Triple';
2✔
537
  this.cursor.subject = this.cleanSubject(subject);
2✔
538
  this.cursor.predicate = this.cleanPredicate(predicate);
2✔
539
  this.cursor.object = this.cleanDataValue(objValue, 'xsd:string');
2✔
540
  return this;
2✔
541
};
542

543
/**
544
 * Creates a pattern matching rule for the quad [S, P, O, G] (Subject, Predicate, Object, Graph)
545
 * @param {string|Var} subject - The IRI of a triple’s subject or a variable
546
 * @param {string|Var} predicate - The IRI of a property or a variable
547
 * @param {string|Var} object - The IRI of a node or a variable, or a literal
548
 * @param {typedef.GraphRef} graphRef - A valid graph resource identifier string
549
 * @returns {WOQLQuery}
550
 */
551

552
WOQLQuery.prototype.quad = function (subject, predicate, object, graphRef) {
1✔
553
  if (this.cursor['@type']) this.wrapCursorWithAnd();
8!
554
  const args = this.triple(subject, predicate, object);
8✔
555
  // if (a && a === 'args')
556
  // return args.concat(['graph'])
557
  if (!graphRef) return this.parameterError('Quad takes four parameters, the last should be a graph filter');
8!
558
  this.cursor['@type'] = 'Triple';
8✔
559
  this.cursor.graph = this.cleanGraph(graphRef);
8✔
560
  return this;
8✔
561
};
562

563
/**
564
 * Creates a pattern matching rule for the quad [S, P, O, G] (Subject, Predicate,
565
 * Object, Graph) removed from the current commit
566
 * @param {string|Var} subject - The IRI of a triple’s subject or a variable
567
 * @param {string|Var} predicate - The IRI of a property or a variable
568
 * @param {string|Var} object - The IRI of a node or a variable, or a literal
569
 * @param {typedef.GraphRef} graphRef- A valid graph resource identifier string
570
 * @returns {WOQLQuery}
571
 */
572

573
WOQLQuery.prototype.added_quad = function (subject, predicate, object, graphRef) {
1✔
574
  if (this.cursor['@type']) this.wrapCursorWithAnd();
2!
575
  const args = this.triple(subject, predicate, object);
2✔
576
  // if (a && a === 'args')
577
  // return args.concat(['graph'])
578
  if (!graphRef) return this.parameterError('Quad takes four parameters, the last should be a graph filter');
2!
579
  this.cursor['@type'] = 'AddedQuad';
2✔
580
  this.cursor.graph = this.cleanGraph(graphRef);
2✔
581
  return this;
2✔
582
};
583

584
/**
585
 * Creates a pattern matching rule for the quad [S, P, O, G] (Subject, Predicate,
586
 * Object, Graph) removed from the current commit
587
 * @param {string|Var} subject - The IRI of a triple’s subject or a variable
588
 * @param {string|Var} predicate - The IRI of a property or a variable
589
 * @param {string|Var} object - The IRI of a node or a variable, or a literal
590
 * @param {typedef.GraphRef} graphRef- A valid graph resource identifier string
591
 * @returns {WOQLQuery}
592
 */
593

594
WOQLQuery.prototype.removed_quad = function (subject, predicate, object, graphRef) {
1✔
595
  if (this.cursor['@type']) this.wrapCursorWithAnd();
2!
596
  const args = this.triple(subject, predicate, object);
2✔
597
  // if (a && a === 'args')
598
  // return args.concat(['graph'])
599
  if (!graphRef) return this.parameterError('Quad takes four parameters, the last should be a graph filter');
2!
600
  this.cursor['@type'] = 'DeletedQuad';
2✔
601
  this.cursor.graph = this.cleanGraph(graphRef);
2✔
602
  return this;
2✔
603
};
604

605
/**
606
 * Returns true if ClassA subsumes ClassB, according to the current DB schema
607
 * @param {string} classA - ClassA
608
 * @param {string} classB - ClassB
609
 * @returns {boolean} WOQLQuery
610
 */
611
WOQLQuery.prototype.sub = function (classA, classB) {
1✔
612
  if (!classA || !classB) return this.parameterError('Subsumption takes two parameters, both URIs');
6✔
613
  if (this.cursor['@type']) this.wrapCursorWithAnd();
5!
614
  this.cursor['@type'] = 'Subsumption';
5✔
615
  this.cursor.parent = this.cleanNodeValue(classA);
5✔
616
  this.cursor.child = this.cleanNodeValue(classB);
5✔
617
  return this;
5✔
618
};
619

620
WOQLQuery.prototype.subsumption = WOQLQuery.prototype.sub;
1✔
621

622
/**
623
 * Matches if a is equal to b
624
 * @param {string|number|boolean|array|Var} varName - literal, variable, array, or id
625
 * @param {string|number|boolean|array|Var} varValue - literal, variable, array, or id
626
 * @returns {WOQLQuery}
627
 */
628
WOQLQuery.prototype.eq = function (varName, varValue) {
1✔
629
  // if (a && a === 'args') return ['left', 'right']
630
  if (typeof varName === 'undefined' || typeof varValue === 'undefined') return this.parameterError('Equals takes two parameters');
7✔
631
  if (this.cursor['@type']) this.wrapCursorWithAnd();
6!
632
  this.cursor['@type'] = 'Equals';
6✔
633
  this.cursor.left = this.cleanObject(varName);
6✔
634
  this.cursor.right = this.cleanObject(varValue);
6✔
635
  return this;
6✔
636
};
637

638
WOQLQuery.prototype.equals = WOQLQuery.prototype.eq;
1✔
639

640
/**
641
 * Substring
642
 * @param {string|Var} string - String or variable
643
 * @param {number|Var} before - integer or variable (characters from start to begin)
644
 * @param {number|Var} [length] - integer or variable (length of substring)
645
 * @param {number|Var} [after] - integer or variable (number of characters after substring)
646
 * @param {string|Var} [subString] - String or variable
647
 * @returns {WOQLQuery}
648
 */
649
WOQLQuery.prototype.substr = function (string, before, length, after, subString) {
1✔
650
  // if (String && String === 'args')
651
  // return ['string', 'before', 'length', 'after', 'substring']
652
  if (!subString) {
4!
653
    subString = after;
×
654
    after = 0;
×
655
  }
656
  if (!subString) {
4!
657
    subString = length;
×
658
    length = subString.length + before;
×
659
  }
660
  if (!string || !subString || typeof subString !== 'string') {
4!
661
    return this.parameterError(
×
662
      'Substr - the first and last parameters must be strings representing the full and substring variables / literals',
663
    );
664
  }
665
  if (this.cursor['@type']) this.wrapCursorWithAnd();
4!
666
  this.cursor['@type'] = 'Substring';
4✔
667
  this.cursor.string = this.cleanDataValue(string, 'xsd:string');
4✔
668
  this.cursor.before = this.cleanDataValue(before, 'xsd:nonNegativeInteger');
4✔
669
  this.cursor.length = this.cleanDataValue(length, 'xsd:nonNegativeInteger');
4✔
670
  this.cursor.after = this.cleanDataValue(after, 'xsd:nonNegativeInteger');
4✔
671
  this.cursor.substring = this.cleanDataValue(subString, 'xsd:string');
4✔
672
  return this;
4✔
673
};
674

675
WOQLQuery.prototype.substring = WOQLQuery.prototype.substr;
1✔
676

677
/**
678
 * Use the document inteface to import documents
679
 * @deprecated
680
 * Retrieves the exernal resource defined by QueryResource and copies values
681
 * from it into variables defined in AsVars
682
 * @param {Vars | array<Var>} asvars - an array of AsVar variable mappings (see as for format below)
683
 * @param {WOQLQuery} queryResource - an external resource (remote, file, post) to query
684
 * @returns {WOQLQuery} A WOQLQuery which contains the get expression
685
 */
686
WOQLQuery.prototype.get = function (asvars, queryResource) {
1✔
687
  this.cursor['@type'] = 'Get';
3✔
688
  this.cursor.columns = asvars.json ? asvars.json() : new WOQLQuery().as(...asvars).json();
3✔
689
  if (queryResource) {
3✔
690
    this.cursor.resource = this.jobj(queryResource);
2✔
691
  } else {
692
    this.cursor.resource = {};
1✔
693
  }
694
  this.cursor = this.cursor.resource;
3✔
695
  return this;
3✔
696
};
697

698
/**
699
 * Use the document inteface to import documents
700
 * @deprecated
701
 * @put Outputs the results of a query to a file
702
 * @param {Vars | array<Var>} varsToExp - an array of AsVar variable
703
 * mappings (see as for format below)
704
 * @param {WOQLQuery} query - The query which will be executed to produce the results
705
 * @param {string} fileResource - an file resource local to the server
706
 * @returns {WOQLQuery} A WOQLQuery which contains the put expression
707
 */
708
WOQLQuery.prototype.put = function (varsToExp, query, fileResource) {
1✔
709
  if (this.cursor['@type']) this.wrapCursorWithAnd();
1!
710
  this.cursor['@type'] = 'Put';
1✔
711
  if (Array.isArray(varsToExp) && typeof varsToExp[0] !== 'object') {
1!
712
    const nasvars = [];
×
713
    for (let i = 0; i < varsToExp.length; i++) {
×
714
      const iasv = this.asv(i, varsToExp[i]);
×
715
      nasvars.push(iasv);
×
716
      this.cursor.columns = nasvars;
×
717
    }
718
  } else {
719
    this.cursor.columns = varsToExp.json
1!
720
      ? varsToExp.json()
721
      : new WOQLQuery().as(...varsToExp).json();
722
  }
723
  this.cursor.query = this.jobj(query);
1✔
724
  if (fileResource) {
1!
725
    this.cursor.resource = this.jobj(fileResource);
1✔
726
  } else {
727
    this.cursor.resource = {};
×
728
  }
729
  this.cursor = this.cursor.resource;
1✔
730
  return this;
1✔
731
};
732

733
/**
734
 * @param {...(array|string|Var)} varList variable number of arguments
735
 * @returns WOQLQuery
736
 */
737
WOQLQuery.prototype.as = function (...varList) {
15✔
738
  // if (varList && varList[0] == 'args')
739
  // return [['indexed_as_var', 'named_as_var']]
740
  if (!Array.isArray(this.query)) this.query = [];
5!
741
  if (Array.isArray(varList[0])) {
5!
742
    if (!varList[1]) {
×
743
      // indexed as vars
744
      for (var i = 0; i < varList[0].length; i++) {
×
745
        const iasv = this.asv(i, varList[0][i]);
×
746
        this.query.push(iasv);
×
747
      }
748
    } else {
749
      for (var i = 0; i < varList.length; i++) {
×
750
        const onemap = varList[i];
×
751
        if (Array.isArray(onemap) && onemap.length >= 2) {
×
752
          const type = onemap && onemap.length > 2 ? onemap[2] : false;
×
753
          const oasv = this.asv(onemap[0], onemap[1], type);
×
754
          this.query.push(oasv);
×
755
        }
756
      }
757
    }
758
  } else if (typeof varList[0] === 'number' || typeof varList[0] === 'string') {
5!
759
    if (varList[2] && typeof varList[2] === 'string') {
5✔
760
      var oasv = this.asv(varList[0], varList[1], varList[2]);
1✔
761
    } else if (varList[1] && varList[1] instanceof Var) {
4!
762
      var oasv = this.asv(varList[0], varList[1]);
×
763
    } else if (varList[1] && typeof varList[1] === 'string') {
4!
764
      if (varList[1].substring(0, 4) === 'xsd:' || varList[1].substring(0, 4) === 'xdd:') {
4!
765
        var oasv = this.asv(this.query.length, varList[0], varList[1]);
×
766
      } else {
767
        var oasv = this.asv(varList[0], varList[1]);
4✔
768
      }
769
    } else {
770
      var oasv = this.asv(this.query.length, varList[0]);
×
771
    }
772
    this.query.push(oasv);
5✔
773
  } else if (typeof varList[0] === 'object') {
×
774
    // check if it is an class object with an json method
775
    this.query.push(varList[0].json ? varList[0].json() : varList[0]);
×
776
  }
777
  return this;
5✔
778
};
779

780
/**
781
 * Identifies a remote resource by URL and specifies the format of the resource through the options
782
 * @param {object} remoteObj - The URL at which the remote resource can be accessed
783
 * @param {typedef.DataFormatObj} [formatObj] - The format of the resource data {}
784
 * @returns {WOQLQuery} A WOQLQuery which contains the remote resource identifier
785
 */
786

787
WOQLQuery.prototype.remote = function (remoteObj, formatObj) {
1✔
788
  if (this.cursor['@type']) this.wrapCursorWithAnd();
3!
789
  this.cursor['@type'] = 'QueryResource';
3✔
790
  this.cursor.source = { '@type': 'Source', url: remoteObj };
3✔
791
  this.cursor.format = 'csv'; // hard coded for now
3✔
792
  if (typeof opts !== 'undefined') this.cursor.options = formatObj;
3!
793
  return this;
3✔
794
};
795

796
/**
797
 * Identifies a resource as a local path on the client, to be sent to the server through a
798
 * HTTP POST request, with the format defined through the options
799
 * @param {string} url - The Path on the server at which the file resource can be accessed
800
 * @param {typedef.DataFormatObj} [formatObj] - imput options, optional
801
 * @param {string} [source] - It defines the source of the file, it can be 'url','post'
802
 * @returns {WOQLQuery} A WOQLQuery which contains the Post resource identifier
803
 */
804

805
WOQLQuery.prototype.post = function (url, formatObj, source = 'post') {
1!
806
  // if (fpath && fpath == 'args') return ['file', 'format']
807
  if (this.cursor['@type']) this.wrapCursorWithAnd();
1!
808
  this.cursor['@type'] = 'QueryResource';
1✔
809
  this.cursor.source = { '@type': 'Source', [source]: url };
1✔
810
  this.cursor.format = 'csv'; // hard coded for now
1✔
811
  this.cursor.options = formatObj;
1✔
812
  if (typeof formatObj !== 'undefined') this.cursor.options = formatObj;
1!
813
  return this;
1✔
814
};
815

816
/**
817
 * Deletes a single triple from the default graph of the database
818
 * @param {string|Var} subject - The IRI of a triple’s subject or a variable
819
 * @param {string|Var} predicate - The IRI of a property or a variable
820
 * @param {string|Var} object - The IRI of a node or a variable, or a literal
821
 * @returns {WOQLQuery} - A WOQLQuery which contains the Triple Deletion statement
822
 */
823

824
WOQLQuery.prototype.delete_triple = function (subject, predicate, object) {
1✔
825
  if (this.cursor['@type']) this.wrapCursorWithAnd();
6✔
826
  const args = this.triple(subject, predicate, object);
6✔
827
  this.cursor['@type'] = 'DeleteTriple';
6✔
828
  return this.updated();
6✔
829
};
830

831
/**
832
 * Adds triples according to the the pattern [subject,predicate,object]
833
 * @param {string|Var} subject - The IRI of a triple’s subject or a variable
834
 * @param {string|Var} predicate - The IRI of a property or a variable
835
 * @param {string|Var} object - The IRI of a node or a variable, or a literal
836
 * @returns {WOQLQuery}
837
 */
838

839
WOQLQuery.prototype.add_triple = function (subject, predicate, object) {
1✔
840
  if (this.cursor['@type']) this.wrapCursorWithAnd();
9!
841
  const args = this.triple(subject, predicate, object);
9✔
842
  this.cursor['@type'] = 'AddTriple';
9✔
843
  return this.updated();
9✔
844
};
845

846
/**
847
 * Deletes a single triple from the graph [Subject, Predicate, Object, Graph]
848
 * @param {string|Var} subject - The IRI of a triple’s subject or a variable
849
 * @param {string|Var} predicate - The IRI of a property or a variable
850
 * @param {string|Var} object - The IRI of a node or a variable, or a literal
851
 * @param {typedef.GraphRef} graphRef - A valid graph resource identifier string
852
 * @returns {WOQLQuery} - A WOQLQuery which contains the Delete Quad Statement
853
 */
854
WOQLQuery.prototype.delete_quad = function (subject, predicate, object, graphRef) {
1✔
855
  if (this.cursor['@type']) this.wrapCursorWithAnd();
6✔
856
  const args = this.triple(subject, predicate, object);
6✔
857
  // if (a && a == 'args') return args.concat(['graph'])
858
  if (!graphRef) {
6!
859
    return this.parameterError(
×
860
      'Delete Quad takes four parameters, the last should be a graph id',
861
    );
862
  }
863
  this.cursor['@type'] = 'DeleteTriple';
6✔
864
  this.cursor.graph = this.cleanGraph(graphRef);
6✔
865
  return this.updated();
6✔
866
};
867

868
/**
869
 * Adds quads according to the pattern [S,P,O,G]
870
 * @param {string|Var} subject - The IRI of a triple’s subject or a variable
871
 * @param {string|Var} predicate - The IRI of a property or a variable
872
 * @param {string|Var} object - The IRI of a node or a variable, or a literal
873
 * @param {typedef.GraphRef} graphRef - A valid graph resource identifier string
874
 * @returns {WOQLQuery}
875
 */
876

877
WOQLQuery.prototype.add_quad = function (subject, predicate, object, graphRef) {
1✔
878
  if (this.cursor['@type']) this.wrapCursorWithAnd();
5!
879
  const args = this.triple(subject, predicate, object);
5✔
880
  if (!graphRef) return this.parameterError('Add Quad takes four parameters, the last should be a graph id');
5!
881
  this.cursor['@type'] = 'AddTriple';
5✔
882
  this.cursor.graph = this.cleanGraph(graphRef);
5✔
883
  return this.updated();
5✔
884
};
885

886
/**
887
 * Remove whitespace from both sides of a string:
888
 * @param {string|Var} inputStr - A string or variable containing
889
 * the untrimmed version of the string
890
 * @param {string|Var} resultVarName - A string or variable
891
 * containing the trimmed version of the string
892
 * @returns {WOQLQuery} A WOQLQuery which contains the Trim pattern matching expression
893
 */
894

895
WOQLQuery.prototype.trim = function (inputStr, resultVarName) {
1✔
896
  if (this.cursor['@type']) this.wrapCursorWithAnd();
2!
897
  this.cursor['@type'] = 'Trim';
2✔
898
  this.cursor.untrimmed = this.cleanDataValue(inputStr);
2✔
899
  this.cursor.trimmed = this.cleanDataValue(resultVarName);
2✔
900
  return this;
2✔
901
};
902

903
/**
904
 * Evaluates the passed arithmetic expression and generates or matches the result value
905
 * @param {object| WOQLQuery | string} arithExp - query or JSON-LD representing the query
906
 * @param {string|Var} resultVarName - output variable
907
 * @returns {WOQLQuery}
908
 */
909

910
WOQLQuery.prototype.eval = function (arithExp, resultVarName) {
1✔
911
  if (this.cursor['@type']) this.wrapCursorWithAnd();
10!
912
  this.cursor['@type'] = 'Eval';
10✔
913
  this.cursor.expression = arithExp.json ? arithExp.json() : arithExp;
10✔
914
  this.cursor.result = this.cleanArithmeticValue(resultVarName);
10✔
915
  return this;
10✔
916
};
917

918
/**
919
 * Evaluates the passed arithmetic expression and generates or matches the result value.
920
 * Alias for eval() to support both naming conventions in fluent/chained style.
921
 * @param {object|WOQLQuery|string} arithExp - A WOQL query containing a valid arithmetic expression
922
 * @param {string|number|Var} resultVarName - Either a variable to store the result, or a numeric
923
 * literal to test against the evaluated expression
924
 * @returns {WOQLQuery}
925
 */
926

927
WOQLQuery.prototype.evaluate = function (arithExp, resultVarName) {
1✔
928
  return this.eval(arithExp, resultVarName);
2✔
929
};
930

931
/**
932
 * Adds the numbers together
933
 * @param {...(string|number|Var)} args - a variable or numeric containing the values to add
934
 * @returns {WOQLQuery} A WOQLQuery which contains the addition expression
935
 */
936

937
WOQLQuery.prototype.plus = function (...args) {
10✔
938
  // if (args && args[0] == 'args') return ['first', 'second']
939
  if (this.cursor['@type']) this.wrapCursorWithAnd();
5!
940
  this.cursor['@type'] = 'Plus';
5✔
941
  this.cursor.left = this.arop(args.shift());
5✔
942
  if (args.length > 1) {
5!
943
    this.cursor.right = this.jobj(new WOQLQuery().plus(...args.map(this.arop)));
×
944
  } else {
945
    this.cursor.right = this.arop(args[0]);
5✔
946
  }
947
  return this;
5✔
948
};
949

950
/**
951
 *
952
 * Subtracts Numbers N1..Nn
953
 * @param {...(string|number|Var)} args - variable or numeric containing the value that will be
954
 * subtracted from
955
 * @returns {WOQLQuery} A WOQLQuery which contains the subtraction expression
956
 */
957
WOQLQuery.prototype.minus = function (...args) {
4✔
958
  // if (args && args[0] === 'args') return ['first', 'right']
959
  if (this.cursor['@type']) this.wrapCursorWithAnd();
2!
960
  this.cursor['@type'] = 'Minus';
2✔
961
  this.cursor.left = this.arop(args.shift());
2✔
962
  if (args.length > 1) {
2!
963
    this.cursor.right = this.jobj(new WOQLQuery().minus(...args.map(this.arop)));
×
964
  } else {
965
    this.cursor.right = this.arop(args[0]);
2✔
966
  }
967
  return this;
2✔
968
};
969

970
/**
971
 *
972
 * Multiplies numbers N1...Nn together
973
 * @param {...(string|number|Var)} args - a variable or numeric containing the value
974
 * @returns {WOQLQuery} A WOQLQuery which contains the multiplication expression
975
 */
976
WOQLQuery.prototype.times = function (...args) {
14✔
977
  // if (args && args[0] === 'args') return ['first', 'right']
978
  if (this.cursor['@type']) this.wrapCursorWithAnd();
7!
979
  this.cursor['@type'] = 'Times';
7✔
980
  this.cursor.left = this.arop(args.shift());
7✔
981
  if (args.length > 1) {
7!
982
    this.cursor.right = this.jobj(new WOQLQuery().times(...args.map(this.arop)));
×
983
  } else {
984
    this.cursor.right = this.arop(args[0]);
7✔
985
  }
986
  return this;
7✔
987
};
988

989
/**
990
 * Divides numbers N1...Nn by each other left, to right precedence
991
 * @param {...(string|number|Var )} args - numbers to tbe divided
992
 * @returns {WOQLQuery} A WOQLQuery which contains the division expression
993
 */
994
WOQLQuery.prototype.divide = function (...args) {
4✔
995
  // if (args && args[0] === 'args') return ['left', 'right']
996
  if (this.cursor['@type']) this.wrapCursorWithAnd();
2!
997
  this.cursor['@type'] = 'Divide';
2✔
998
  this.cursor.left = this.arop(args.shift());
2✔
999
  if (args.length > 1) {
2!
1000
    this.cursor.right = this.jobj(new WOQLQuery().divide(...args.map(this.arop)));
×
1001
  } else {
1002
    this.cursor.right = this.arop(args[0]);
2✔
1003
  }
1004
  return this;
2✔
1005
};
1006

1007
/**
1008
 * Division - integer division - args are divided left to right
1009
 * @param {...(string|number|Var)} args - numbers for division
1010
 * @returns {WOQLQuery} A WOQLQuery which contains the division expression
1011
 */
1012

1013
WOQLQuery.prototype.div = function (...args) {
6✔
1014
  // if (args && args[0] === 'args') return ['left', 'right']
1015
  if (this.cursor['@type']) this.wrapCursorWithAnd();
3!
1016
  this.cursor['@type'] = 'Div';
3✔
1017
  this.cursor.left = this.arop(args.shift());
3✔
1018
  if (args.length > 1) {
3!
1019
    this.cursor.right = this.jobj(new WOQLQuery().div(...args.map(this.arop)));
×
1020
  } else {
1021
    this.cursor.right = this.arop(args[0]);
3✔
1022
  }
1023
  return this;
3✔
1024
};
1025

1026
/**
1027
 * Exponent - raises varNum01 to the power of varNum02
1028
 * @param {string|number|Var} varNum -  a variable or numeric containing the number to be
1029
 * raised to the power of the second number
1030
 * @param {number} expNum -  a variable or numeric containing the exponent
1031
 * @returns {WOQLQuery} A WOQLQuery which contains the exponent expression
1032
 */
1033
WOQLQuery.prototype.exp = function (varNum, expNum) {
1✔
1034
  // if (a && a === 'args') return ['left', 'right']
1035
  if (this.cursor['@type']) this.wrapCursorWithAnd();
3!
1036
  this.cursor['@type'] = 'Exp';
3✔
1037
  this.cursor.left = this.arop(varNum);
3✔
1038
  this.cursor.right = this.arop(expNum);
3✔
1039
  return this;
3✔
1040
};
1041

1042
/**
1043
 * Generates the nearest lower integer to the passed number
1044
 * @param {string|number|Var} varNum - Variable or numeric containing the number to be floored
1045
 * @returns {WOQLQuery} A WOQLQuery which contains the floor expression
1046
 */
1047
WOQLQuery.prototype.floor = function (varNum) {
1✔
1048
  // if (a && a === 'args') return ['argument']
1049
  if (this.cursor['@type']) this.wrapCursorWithAnd();
2!
1050
  this.cursor['@type'] = 'Floor';
2✔
1051
  this.cursor.argument = this.arop(varNum);
2✔
1052
  return this;
2✔
1053
};
1054

1055
/**
1056
 * Tests whether a given instance IRI has type Class, according to the current state of the DB
1057
 * @param {string|Var} instanceIRI - A string IRI or a variable that identify the class instance
1058
 * @param {string|Var} classId - A Class IRI or a variable
1059
 * @returns {WOQLQuery} A WOQLQuery object containing the type test
1060
 */
1061
WOQLQuery.prototype.isa = function (instanceIRI, classId) {
1✔
1062
  // if (a && a === 'args') return ['element', 'of_type']
1063
  if (this.cursor['@type']) this.wrapCursorWithAnd();
4!
1064
  this.cursor['@type'] = 'IsA';
4✔
1065
  this.cursor.element = this.cleanNodeValue(instanceIRI);
4✔
1066
  this.cursor.type = this.cleanNodeValue(classId);
4✔
1067
  return this;
4✔
1068
};
1069

1070
/**
1071
 * Generates a string Leverstein distance measure between stringA and stringB
1072
 * @param {string|Var} stringA - string literal or variable representing a string to be compared
1073
 * @param {string|Var } stringB - string literal or variable
1074
 * representing the other string to be compared
1075
 * @param {number|string|Var} distance - variable representing the distance between the variables
1076
 * @returns {WOQLQuery} A WOQLQuery which contains the Like pattern matching expression
1077
 */
1078
WOQLQuery.prototype.like = function (stringA, stringB, distance) {
1✔
1079
  // if (a && a === 'args')
1080
  // return ['left', 'right', 'like_similarity']
1081
  if (this.cursor['@type']) this.wrapCursorWithAnd();
3!
1082
  this.cursor['@type'] = 'Like';
3✔
1083
  this.cursor.left = this.cleanDataValue(stringA, 'xsd:string');
3✔
1084
  this.cursor.right = this.cleanDataValue(stringB, 'xsd:string');
3✔
1085
  if (distance) {
3✔
1086
    this.cursor.similarity = this.cleanDataValue(distance, 'xsd:decimal');
2✔
1087
  }
1088
  return this;
3✔
1089
};
1090

1091
/**
1092
 * Compares the value of v1 against v2 and returns true if v1 is less than v2
1093
 * @param {string|number|Var} varNum01 - a variable or numeric containing
1094
 * the number to be compared
1095
 * @param {string|number|Var} varNum02 - a variable or numeric containing the second comporator
1096
 * @returns {WOQLQuery} A WOQLQuery which contains the comparison expression
1097
 */
1098
WOQLQuery.prototype.less = function (varNum01, varNum02) {
1✔
1099
  if (this.cursor['@type']) this.wrapCursorWithAnd();
4!
1100
  this.cursor['@type'] = 'Less';
4✔
1101
  this.cursor.left = this.cleanDataValue(varNum01);
4✔
1102
  this.cursor.right = this.cleanDataValue(varNum02);
4✔
1103
  return this;
4✔
1104
};
1105

1106
/**
1107
 * Compares the value of v1 against v2 and returns true if v1 is greater than v2
1108
 * @param {string|number|Var} varNum01 - a variable or numeric containing the number to be compared
1109
 * @param {string|number|Var} varNum02 - a variable or numeric containing the second comporator
1110
 * @returns {WOQLQuery} A WOQLQuery which contains the comparison expression
1111
 */
1112
WOQLQuery.prototype.greater = function (varNum01, varNum02) {
1✔
1113
  if (this.cursor['@type']) this.wrapCursorWithAnd();
2!
1114
  this.cursor['@type'] = 'Greater';
2✔
1115
  this.cursor.left = this.cleanDataValue(varNum01);
2✔
1116
  this.cursor.right = this.cleanDataValue(varNum02);
2✔
1117
  return this;
2✔
1118
};
1119

1120
/**
1121
 * Specifies that the Subquery is optional - if it does not match the query will not fail
1122
 * @param {WOQLQuery} [subquery] - A subquery which will be optionally matched
1123
 * @returns {WOQLQuery} A WOQLQuery object containing the optional sub Query
1124
 */
1125
WOQLQuery.prototype.opt = function (subquery) {
1✔
1126
  if (this.cursor['@type']) this.wrapCursorWithAnd();
42✔
1127
  this.cursor['@type'] = 'Optional';
42✔
1128
  this.addSubQuery(subquery);
42✔
1129
  return this;
42✔
1130
};
1131

1132
WOQLQuery.prototype.optional = WOQLQuery.prototype.opt;
1✔
1133

1134
/**
1135
 * Generate a new IRI from the prefix and a hash of the variables which will be unique for any
1136
 * given combination of variables
1137
 * @param {string} prefix - A prefix for the IRI - typically formed of the doc prefix and the
1138
 * classtype of the entity (“doc:Person”)
1139
 * @param {array|string|Var} inputVarList - An array of variables and / or strings from which the
1140
 * unique hash will be generated
1141
 * @param {string|Var} resultVarName - Variable in which the unique ID is stored
1142
 * @returns {WOQLQuery} A WOQLQuery object containing the unique ID generating function
1143
 */
1144
WOQLQuery.prototype.unique = function (prefix, inputVarList, resultVarName) {
1✔
1145
  if (this.cursor['@type']) this.wrapCursorWithAnd();
2!
1146
  this.cursor['@type'] = 'HashKey';
2✔
1147
  this.cursor.base = this.cleanDataValue(prefix, 'xsd:string');
2✔
1148
  this.cursor.key_list = this.cleanDataValue(inputVarList);
2✔
1149
  this.cursor.uri = this.cleanNodeValue(resultVarName);
2✔
1150
  return this;
2✔
1151
};
1152

1153
/**
1154
 * Generates the node's ID combined the variable list with a specific prefix (URL base).
1155
 * If the input variables's values are the same, the output value will be the same.
1156
 * @param {string} prefix
1157
 * @param {string |array}  inputVarList the variable input list for generate the id
1158
 * @param {string} outputVar  the output variable name
1159
 */
1160

1161
WOQLQuery.prototype.idgen = function (prefix, inputVarList, outputVar) {
1✔
1162
  if (this.cursor['@type']) this.wrapCursorWithAnd();
3!
1163
  this.cursor['@type'] = 'LexicalKey';
3✔
1164
  this.cursor.base = this.cleanDataValue(prefix, 'xsd:string');
3✔
1165
  // this.cursor['base'] = this.cleanObject(this.string(prefix))
1166
  this.cursor.key_list = this.dataValueList(inputVarList);
3✔
1167
  this.cursor.uri = this.cleanNodeValue(outputVar);
3✔
1168
  return this;
3✔
1169
};
1170

1171
WOQLQuery.prototype.idgenerator = WOQLQuery.prototype.idgen;
1✔
1172

1173
/**
1174
 * Generates a random ID with a specified prefix
1175
 * Uses cryptographically secure random base64 encoding to generate unique identifiers
1176
 * @param {string} prefix - prefix for the generated ID
1177
 * @param {string} outputVar - variable that stores the generated ID
1178
 * @returns {WOQLQuery} A WOQLQuery which contains the random ID generation pattern
1179
 * @example
1180
 * idgen_random("Person/", "v:person_id")
1181
 */
1182
WOQLQuery.prototype.idgen_random = function (prefix, outputVar) {
1✔
1183
  if (this.cursor['@type']) this.wrapCursorWithAnd();
1!
1184
  this.cursor['@type'] = 'RandomKey';
1✔
1185
  this.cursor.base = this.cleanDataValue(prefix, 'xsd:string');
1✔
1186
  this.cursor.uri = this.cleanNodeValue(outputVar);
1✔
1187
  return this;
1✔
1188
};
1189

1190
/**
1191
 * Backward-compatible alias for idgen_random
1192
 * @deprecated Use idgen_random instead
1193
 */
1194
WOQLQuery.prototype.random_idgen = WOQLQuery.prototype.idgen_random;
1✔
1195

1196
/**
1197
 * Changes a string to upper-case
1198
 * @param {string|Var} inputVarName - string or variable representing the uncapitalized string
1199
 * @param {string|Var} resultVarName -  variable that stores the capitalized string output
1200
 * @returns {WOQLQuery} A WOQLQuery which contains the Upper case pattern matching expression
1201
 */
1202
WOQLQuery.prototype.upper = function (inputVarName, resultVarName) {
1✔
1203
  if (this.cursor['@type']) this.wrapCursorWithAnd();
1!
1204
  this.cursor['@type'] = 'Upper';
1✔
1205
  this.cursor.mixed = this.cleanDataValue(inputVarName);
1✔
1206
  this.cursor.upper = this.cleanDataValue(resultVarName);
1✔
1207
  return this;
1✔
1208
};
1209

1210
/**
1211
 * Changes a string to lower-case
1212
 * @param {string|Var} inputVarName -  string or variable representing the non-lowercased string
1213
 * @param {string|Var} resultVarName - variable that stores the lowercased string output
1214
 * @returns {WOQLQuery} A WOQLQuery which contains the Lower case pattern matching expression
1215
 */
1216

1217
WOQLQuery.prototype.lower = function (inputVarName, resultVarName) {
1✔
1218
  if (this.cursor['@type']) this.wrapCursorWithAnd();
1!
1219
  this.cursor['@type'] = 'Lower';
1✔
1220
  this.cursor.mixed = this.cleanDataValue(inputVarName);
1✔
1221
  this.cursor.lower = this.cleanDataValue(resultVarName);
1✔
1222
  return this;
1✔
1223
};
1224

1225
/**
1226
 * Pads out the string input to be exactly len long by appending the pad character pad to
1227
 * form output
1228
 * @param {string|Var} inputVarName - The input string or variable in unpadded state
1229
 * @param {string|Var} pad - The characters to use to pad the string or a variable representing them
1230
 * @param {number | string | Var} len - The variable or integer value representing the length of
1231
 * the output string
1232
 * @param {string|Var} resultVarName - stores output
1233
 * @returns {WOQLQuery} A WOQLQuery which contains the Pad pattern matching expression
1234
 */
1235

1236
WOQLQuery.prototype.pad = function (inputVarName, pad, len, resultVarName) {
1✔
1237
  if (this.cursor['@type']) this.wrapCursorWithAnd();
1!
1238
  this.cursor['@type'] = 'Pad';
1✔
1239
  this.cursor.string = this.cleanDataValue(inputVarName);
1✔
1240
  this.cursor.char = this.cleanDataValue(pad);
1✔
1241
  this.cursor.times = this.cleanDataValue(len, 'xsd:integer');
1✔
1242
  this.cursor.result = this.cleanDataValue(resultVarName);
1✔
1243
  return this;
1✔
1244
};
1245

1246
/**
1247
 * Splits a string (Input) into a list strings (Output) by removing separator
1248
 * @param {string|Var} inputVarName - A string or variable representing the unsplit string
1249
 * @param {string|Var} separator - A string or variable containing a sequence of charatcters
1250
 * to use as a separator
1251
 * @param {string|Var} resultVarName - variable that stores output list
1252
 * @returns {WOQLQuery} A WOQLQuery which contains the Split pattern matching expression
1253
 */
1254

1255
WOQLQuery.prototype.split = function (inputVarName, separator, resultVarName) {
1✔
1256
  if (this.cursor['@type']) this.wrapCursorWithAnd();
2!
1257
  this.cursor['@type'] = 'Split';
2✔
1258
  this.cursor.string = this.cleanDataValue(inputVarName);
2✔
1259
  this.cursor.pattern = this.cleanDataValue(separator);
2✔
1260
  this.cursor.list = this.cleanDataValue(resultVarName);
2✔
1261
  return this;
2✔
1262
};
1263

1264
/**
1265
 * Matches if List includes Element
1266
 * @param {string|object|Var} element - Either a variable, IRI or any simple datatype
1267
 * @param {string|array|Var} list - List ([string, literal] or string*) Either a variable
1268
 * representing a list or a list of variables or literals
1269
 * @returns {WOQLQuery} A WOQLQuery which contains the List inclusion pattern matching expression
1270
 */
1271
WOQLQuery.prototype.member = function (element, list) {
1✔
1272
  if (this.cursor['@type']) this.wrapCursorWithAnd();
2!
1273
  this.cursor['@type'] = 'Member';
2✔
1274
  this.cursor.member = this.cleanObject(element);
2✔
1275
  this.cursor.list = this.valueList(list);
2✔
1276
  return this;
2✔
1277
};
1278

1279
/**
1280
 * Computes the set difference between two lists (elements in listA but not in listB)
1281
 * @param {string|Var|array} listA - First list or variable
1282
 * @param {string|Var|array} listB - Second list or variable
1283
 * @param {string|Var} result - Variable to store the result
1284
 * @returns {WOQLQuery} A WOQLQuery which contains the SetDifference expression
1285
 */
1286
WOQLQuery.prototype.set_difference = function (listA, listB, result) {
1✔
NEW
1287
  if (this.cursor['@type']) this.wrapCursorWithAnd();
×
NEW
1288
  this.cursor['@type'] = 'SetDifference';
×
NEW
1289
  this.cursor.list_a = this.valueList(listA);
×
NEW
1290
  this.cursor.list_b = this.valueList(listB);
×
NEW
1291
  this.cursor.result = this.valueList(result);
×
NEW
1292
  return this;
×
1293
};
1294

1295
/**
1296
 * Computes the set intersection of two lists (elements in both listA and listB)
1297
 * @param {string|Var|array} listA - First list or variable
1298
 * @param {string|Var|array} listB - Second list or variable
1299
 * @param {string|Var} result - Variable to store the result
1300
 * @returns {WOQLQuery} A WOQLQuery which contains the SetIntersection expression
1301
 */
1302
WOQLQuery.prototype.set_intersection = function (listA, listB, result) {
1✔
NEW
1303
  if (this.cursor['@type']) this.wrapCursorWithAnd();
×
NEW
1304
  this.cursor['@type'] = 'SetIntersection';
×
NEW
1305
  this.cursor.list_a = this.valueList(listA);
×
NEW
1306
  this.cursor.list_b = this.valueList(listB);
×
NEW
1307
  this.cursor.result = this.valueList(result);
×
NEW
1308
  return this;
×
1309
};
1310

1311
/**
1312
 * Computes the set union of two lists (all unique elements from both lists)
1313
 * @param {string|Var|array} listA - First list or variable
1314
 * @param {string|Var|array} listB - Second list or variable
1315
 * @param {string|Var} result - Variable to store the result
1316
 * @returns {WOQLQuery} A WOQLQuery which contains the SetUnion expression
1317
 */
1318
WOQLQuery.prototype.set_union = function (listA, listB, result) {
1✔
NEW
1319
  if (this.cursor['@type']) this.wrapCursorWithAnd();
×
NEW
1320
  this.cursor['@type'] = 'SetUnion';
×
NEW
1321
  this.cursor.list_a = this.valueList(listA);
×
NEW
1322
  this.cursor.list_b = this.valueList(listB);
×
NEW
1323
  this.cursor.result = this.valueList(result);
×
NEW
1324
  return this;
×
1325
};
1326

1327
/**
1328
 * Checks if an element is a member of a set (efficient O(log n) lookup)
1329
 * @param {string|Var|any} element - Element to check
1330
 * @param {string|Var|array} set - Set (list) to check membership in
1331
 * @returns {WOQLQuery} A WOQLQuery which contains the SetMember expression
1332
 */
1333
WOQLQuery.prototype.set_member = function (element, set) {
1✔
NEW
1334
  if (this.cursor['@type']) this.wrapCursorWithAnd();
×
NEW
1335
  this.cursor['@type'] = 'SetMember';
×
NEW
1336
  this.cursor.element = this.cleanObject(element);
×
NEW
1337
  this.cursor.set = this.valueList(set);
×
NEW
1338
  return this;
×
1339
};
1340

1341
/**
1342
 * Converts a list to a set (removes duplicates and sorts)
1343
 * @param {string|Var|array} list - Input list or variable
1344
 * @param {string|Var} set - Variable to store the resulting set
1345
 * @returns {WOQLQuery} A WOQLQuery which contains the ListToSet expression
1346
 */
1347
WOQLQuery.prototype.list_to_set = function (list, set) {
1✔
NEW
1348
  if (this.cursor['@type']) this.wrapCursorWithAnd();
×
NEW
1349
  this.cursor['@type'] = 'ListToSet';
×
NEW
1350
  this.cursor.list = this.valueList(list);
×
NEW
1351
  this.cursor.set = this.valueList(set);
×
NEW
1352
  return this;
×
1353
};
1354

1355
/**
1356
 * takes a variable number of string arguments and concatenates them into a single string
1357
 * @param {array|string|Var} varList -  a variable representing a list or a list of variables or
1358
 * strings - variables can be embedded in the string if they do not contain spaces
1359
 * @param {string|Var}  resultVarName - A variable or string containing the output string
1360
 * @returns {WOQLQuery} A WOQLQuery which contains the Concatenation pattern matching expression
1361
 */
1362

1363
WOQLQuery.prototype.concat = function (varList, resultVarName) {
1✔
1364
  if (typeof varList === 'string') {
2✔
1365
    const slist = varList.split(/(v:)/);
1✔
1366
    const nlist = [];
1✔
1367
    if (slist[0]) nlist.push(slist[0]);
1!
1368
    for (let i = 1; i < slist.length; i += 2) {
1✔
1369
      if (slist[i]) {
2!
1370
        if (slist[i] === 'v:') {
2!
1371
          const slist2 = slist[i + 1].split(/([^\w_])/);
2✔
1372
          const x = slist2.shift();
2✔
1373
          nlist.push(`v:${x}`);
2✔
1374
          const rest = slist2.join('');
2✔
1375
          if (rest) nlist.push(rest);
2✔
1376
        }
1377
      }
1378
    }
1379
    varList = nlist;
1✔
1380
  }
1381
  if (Array.isArray(varList)) {
2!
1382
    if (this.cursor['@type']) this.wrapCursorWithAnd();
2!
1383
    this.cursor['@type'] = 'Concatenate';
2✔
1384
    this.cursor.list = this.cleanDataValue(varList, true);
2✔
1385
    this.cursor.result = this.cleanDataValue(resultVarName);
2✔
1386
  }
1387
  return this;
2✔
1388
};
1389

1390
WOQLQuery.prototype.concatenate = WOQLQuery.prototype.concat;
1✔
1391

1392
/**
1393
 * Joins a list variable together (Input) into a string variable (Output) by glueing the strings
1394
 * together with Glue
1395
 * @param {string|array|Var} varList - a variable representing a list or a list of strings
1396
 * and / or variables
1397
 * @param {string|Var} glue - A variable (v:glue) or (glue) string representing the characters
1398
 * to put in between the joined strings in input
1399
 * @param {string|Var} resultVarName - A variable or string containing the output string
1400
 * @returns {WOQLQuery} A WOQLQuery which contains the Join pattern matching expression
1401
 */
1402
WOQLQuery.prototype.join = function (varList, glue, resultVarName) {
1✔
1403
  if (this.cursor['@type']) this.wrapCursorWithAnd();
2!
1404
  this.cursor['@type'] = 'Join';
2✔
1405
  this.cursor.list = this.cleanDataValue(varList);
2✔
1406
  this.cursor.separator = this.cleanDataValue(glue);
2✔
1407
  this.cursor.result = this.cleanDataValue(resultVarName);
2✔
1408
  return this;
2✔
1409
};
1410

1411
/**
1412
 * computes the sum of the List of values passed. In contrast to other arithmetic functions,
1413
 * sum self-evaluates - it does not have to be passed to evaluate()
1414
 * @param {WOQLQuery} subquery -  a subquery or ([string or numeric]) - a list variable, or a
1415
 * list of variables or numeric literals
1416
 * @param {string|Var} total - the variable name with the sum result of the values in List
1417
 * @returns {WOQLQuery} - A WOQLQuery which contains the Sum expression
1418
 */
1419
WOQLQuery.prototype.sum = function (subquery, total) {
1✔
1420
  if (this.cursor['@type']) this.wrapCursorWithAnd();
1!
1421
  this.cursor['@type'] = 'Sum';
1✔
1422
  this.cursor.list = this.cleanDataValue(subquery);
1✔
1423
  this.cursor.result = this.cleanObject(total);
1✔
1424
  return this;
1✔
1425
};
1426

1427
/**
1428
 *
1429
 * Specifies an offset position in the results to start listing results from
1430
 * @param {number|string|Var} start - A variable that refers to an interger or an integer literal
1431
 * @param {WOQLQuery} [subquery] - WOQL Query object, you can pass a subquery as an argument
1432
 * or a chained query
1433
 * @returns {WOQLQuery} A WOQLQuery whose results will be returned starting from
1434
 * the specified offset
1435
 */
1436

1437
WOQLQuery.prototype.start = function (start, subquery) {
1✔
1438
  // if (start && start === 'args') return ['start', 'query']
1439
  if (this.cursor['@type']) this.wrapCursorWithAnd();
4!
1440
  this.cursor['@type'] = 'Start';
4✔
1441
  this.cursor.start = start;
4✔
1442
  return this.addSubQuery(subquery);
4✔
1443
};
1444

1445
/**
1446
 * Specifies a maximum number of results that will be returned from the subquery
1447
 * @param {number|string} limit - A variable that refers to an non-negative integer or a
1448
 * non-negative integer
1449
 * @param {WOQLQuery} [subquery] - A subquery whose results will be limited
1450
 * @returns {WOQLQuery} A WOQLQuery whose results will be returned starting from
1451
 * the specified offset
1452
 */
1453

1454
WOQLQuery.prototype.limit = function (limit, subquery) {
1✔
1455
  if (this.cursor['@type']) this.wrapCursorWithAnd();
22!
1456
  this.cursor['@type'] = 'Limit';
22✔
1457
  this.cursor.limit = limit;
22✔
1458
  return this.addSubQuery(subquery);
22✔
1459
};
1460

1461
/**
1462
 * Matches the regular expression defined in Patern against the Test string, to produce
1463
 * the matched patterns in Matches
1464
 * @param {string} pattern - string or variable using normal PCRE regular expression syntax with
1465
 * the exception that special characters have to be escaped twice (to enable transport in JSONLD)
1466
 * @param {string|Var} inputVarName - string or variable containing the string to be tested for
1467
 * patterns with the regex
1468
 * @param {string|array|object|Var} resultVarList - variable representing the list of matches
1469
 * or a list of strings or variables
1470
 * @returns {WOQLQuery} A WOQLQuery which contains the Regular Expression pattern
1471
 * matching expression
1472
 */
1473

1474
WOQLQuery.prototype.re = function (pattern, inputVarName, resultVarList) {
1✔
1475
  if (this.cursor['@type']) this.wrapCursorWithAnd();
3!
1476
  this.cursor['@type'] = 'Regexp';
3✔
1477
  this.cursor.pattern = this.cleanDataValue(pattern);
3✔
1478
  this.cursor.string = this.cleanDataValue(inputVarName);
3✔
1479
  this.cursor.result = this.cleanDataValue(resultVarList);
3✔
1480
  return this;
3✔
1481
};
1482

1483
WOQLQuery.prototype.regexp = WOQLQuery.prototype.re;
1✔
1484

1485
/**
1486
 * Calculates the length of the list in va and stores it in vb
1487
 * @param {string|array} inputVarList - Either a variable representing a list or a list of
1488
 * variables or literals
1489
 * @param {string|Var} resultVarName -  A variable in which the length of the list is stored or
1490
 * the length of the list as a non-negative integer
1491
 * @returns {WOQLQuery} A WOQLQuery which contains the Length pattern matching expression
1492
 */
1493
WOQLQuery.prototype.length = function (inputVarList, resultVarName) {
1✔
1494
  if (this.cursor['@type']) this.wrapCursorWithAnd();
2!
1495
  this.cursor['@type'] = 'Length';
2✔
1496
  this.cursor.list = this.cleanDataValue(inputVarList);
2✔
1497
  if (typeof resultVarName === 'number') {
2!
1498
    this.cursor.length = this.cleanObject(resultVarName, 'xsd:nonNegativeInteger');
×
1499
  } else if (typeof resultVarName === 'string') {
2!
1500
    this.cursor.length = this.varj(resultVarName);
2✔
1501
  }
1502
  return this;
2✔
1503
};
1504

1505
/**
1506
 * Extracts a contiguous subsequence from a list, following JavaScript's slice() semantics
1507
 * @param {string|array|Var} inputList - Either a variable representing a list or a list of
1508
 * variables or literals
1509
 * @param {string|Var} resultVarName - A variable in which the sliced list is stored
1510
 * @param {number|string|Var} start - The start index (0-based, supports negative indices)
1511
 * @param {number|string|Var} [end] - The end index (exclusive, optional - defaults to list length)
1512
 * @returns {WOQLQuery} A WOQLQuery which contains the Slice pattern matching expression
1513
 * @example
1514
 * let [result] = vars("result")
1515
 * slice(["a", "b", "c", "d"], result, 1, 3)  // result = ["b", "c"]
1516
 * slice(["a", "b", "c", "d"], result, -2)    // result = ["c", "d"]
1517
 */
1518
WOQLQuery.prototype.slice = function (inputList, resultVarName, start, end) {
1✔
1519
  if (this.cursor['@type']) this.wrapCursorWithAnd();
10✔
1520
  this.cursor['@type'] = 'Slice';
10✔
1521
  this.cursor.list = this.cleanDataValue(inputList);
10✔
1522
  this.cursor.result = this.cleanDataValue(resultVarName);
10✔
1523
  if (typeof start === 'number') {
10✔
1524
    this.cursor.start = this.cleanObject(start, 'xsd:integer');
9✔
1525
  } else {
1526
    this.cursor.start = this.cleanDataValue(start);
1✔
1527
  }
1528
  // end is optional - only set if provided
1529
  if (end !== undefined) {
10✔
1530
    if (typeof end === 'number') {
9✔
1531
      this.cursor.end = this.cleanObject(end, 'xsd:integer');
8✔
1532
    } else {
1533
      this.cursor.end = this.cleanDataValue(end);
1✔
1534
    }
1535
  }
1536
  return this;
10✔
1537
};
1538

1539
/**
1540
 *
1541
 * Logical negation of the contained subquery - if the subquery matches, the query
1542
 * will fail to match
1543
 * @param {string | WOQLQuery} [subquery] -  A subquery which will be negated
1544
 * @returns {WOQLQuery} A WOQLQuery object containing the negated sub Query
1545
 */
1546
WOQLQuery.prototype.not = function (subquery) {
1✔
1547
  if (this.cursor['@type']) this.wrapCursorWithAnd();
20✔
1548
  this.cursor['@type'] = 'Not';
20✔
1549
  return this.addSubQuery(subquery);
20✔
1550
};
1551

1552
/**
1553
 * Results in one solution of the subqueries
1554
 * @param {string| WOQLQuery } [subquery] - WOQL Query objects
1555
 * @returns {WOQLQuery} A WOQLQuery object containing the once sub Query
1556
 */
1557
WOQLQuery.prototype.once = function (subquery) {
1✔
1558
  // if (query && query === 'args') return ['query']
1559
  if (this.cursor['@type']) this.wrapCursorWithAnd();
1!
1560
  this.cursor['@type'] = 'Once';
1✔
1561
  return this.addSubQuery(subquery);
1✔
1562
};
1563

1564
/**
1565
 * Runs the query without backtracking on side-effects
1566
 * @param {string| WOQLQuery } [subquery] - WOQL Query objects
1567
 * @returns {WOQLQuery} A WOQLQuery object containing the immediately sub Query
1568
 */
1569
WOQLQuery.prototype.immediately = function (query) {
1✔
1570
  if (this.cursor['@type']) this.wrapCursorWithAnd();
1!
1571
  this.cursor['@type'] = 'Immediately';
1✔
1572
  return this.addSubQuery(query);
1✔
1573
};
1574

1575
/**
1576
 * Creates a count of the results of the query
1577
 * @param {string|number|Var} countVarName - variable or integer count
1578
 * @param {WOQLQuery} [subquery]
1579
 * @returns {WOQLQuery} A WOQLQuery object containing the count sub Query
1580
 */
1581
WOQLQuery.prototype.count = function (countVarName, subquery) {
1✔
1582
  if (this.cursor['@type']) this.wrapCursorWithAnd();
1!
1583
  this.cursor['@type'] = 'Count';
1✔
1584
  this.cursor.count = this.cleanObject(countVarName);
1✔
1585
  return this.addSubQuery(subquery);
1✔
1586
};
1587

1588
/**
1589
 * Casts the value of Input to a new value of type Type and stores the result in CastVar
1590
 * @param {string|number|object|Var} varName - Either a single variable or a
1591
 * literal of any basic type
1592
 * @param {string|Var} varType - Either a variable or a basic datatype (xsd / xdd)
1593
 * @param {string|Var} resultVarName - save the return variable
1594
 * @returns {WOQLQuery} A WOQLQuery which contains the casting expression
1595
 */
1596

1597
WOQLQuery.prototype.typecast = function (varName, varType, resultVarName) {
1✔
1598
  if (this.cursor['@type']) this.wrapCursorWithAnd();
4!
1599
  this.cursor['@type'] = 'Typecast';
4✔
1600
  this.cursor.value = this.cleanObject(varName);
4✔
1601
  this.cursor.type = this.cleanNodeValue(varType);
4✔
1602
  this.cursor.result = this.cleanObject(resultVarName);
4✔
1603
  return this;
4✔
1604
};
1605

1606
WOQLQuery.prototype.cast = WOQLQuery.prototype.typecast;
1✔
1607

1608
/**
1609
 * Orders the results of the contained subquery by a precedence list of variables
1610
 * @param  {...string|...Var|...array} orderedVarlist - A sequence of variables,
1611
 * by which to order the results,
1612
 * each optionally followed by either “asc” or “desc” to represent order as a list, by default
1613
 * it will sort the variable in ascending order
1614
 * @returns  {WOQLQuery} A WOQLQuery which contains the ordering expression
1615
 */
1616
WOQLQuery.prototype.order_by = function (...orderedVarlist) {
14✔
1617
  // if (orderedVarlist && orderedVarlist[0] === 'args')
1618
  // return ['variable_ordering', 'query']
1619
  if (this.cursor['@type']) this.wrapCursorWithAnd();
7!
1620
  this.cursor['@type'] = 'OrderBy';
7✔
1621
  this.cursor.ordering = [];
7✔
1622

1623
  if (!orderedVarlist || orderedVarlist.length === 0) {
7!
1624
    return this.parameterError(
×
1625
      'Order by must be passed at least one variables to order the query',
1626
    );
1627
  }
1628
  const embedquery = typeof orderedVarlist[orderedVarlist.length - 1] === 'object'
7✔
1629
    && orderedVarlist[orderedVarlist.length - 1].json
1630
    ? orderedVarlist.pop()
1631
    : false;
1632

1633
  for (let i = 0; i < orderedVarlist.length; i++) {
7✔
1634
    let obj;
12✔
1635
    if ((typeof orderedVarlist[i] === 'string' || orderedVarlist[i] instanceof Var) && orderedVarlist[i] !== '') {
12✔
1636
      obj = {
9✔
1637
        '@type': 'OrderTemplate',
1638
        variable: this.rawVar(orderedVarlist[i]),
1639
        order: 'asc',
1640
      };
1641
    } else if (orderedVarlist[i].length === 2 && orderedVarlist[i][1] === 'asc') {
3✔
1642
      obj = {
1✔
1643
        '@type': 'OrderTemplate',
1644
        variable: this.rawVar(orderedVarlist[i][0]),
1645
        order: 'asc',
1646
      };
1647
    } else if (orderedVarlist[i].length === 2 && orderedVarlist[i][1] === 'desc') {
2!
1648
      obj = {
2✔
1649
        '@type': 'OrderTemplate',
1650
        variable: this.rawVar(orderedVarlist[i][0]),
1651
        order: 'desc',
1652
      };
1653
    }
1654

1655
    if (obj) this.cursor.ordering.push(obj);
12!
1656
  }
1657
  return this.addSubQuery(embedquery);
7✔
1658
};
1659

1660
/**
1661
 *
1662
 * Groups the results of the contained subquery on the basis of identical values for Groupvars,
1663
 * extracts the patterns defined in PatternVars and stores the results in GroupedVar
1664
 * @param {array|string|Var} gvarlist - Either a single variable or an array of variables
1665
 * @param {array|string|Var} groupedvar - Either a single variable or an array of variables
1666
 * @param {string|Var} output - output variable name
1667
 * @param {WOQLQuery} [groupquery] - The query whose results will be grouped
1668
 * @returns {WOQLQuery} A WOQLQuery which contains the grouping expression
1669
 */
1670

1671
WOQLQuery.prototype.group_by = function (gvarlist, groupedvar, output, groupquery) {
1✔
1672
  // if (gvarlist && gvarlist === 'args')
1673
  // return ['group_by', 'group_template', 'grouped', 'query']
1674
  if (this.cursor['@type']) this.wrapCursorWithAnd();
4!
1675
  this.cursor['@type'] = 'GroupBy';
4✔
1676
  this.cursor.group_by = [];
4✔
1677

1678
  if (typeof gvarlist === 'string' || gvarlist instanceof Var) gvarlist = [gvarlist];
4✔
1679
  this.cursor.group_by = this.rawVarList(gvarlist);
4✔
1680
  if (typeof groupedvar === 'string' || groupedvar instanceof Var) groupedvar = [groupedvar];
4✔
1681
  this.cursor.template = this.rawVarList(groupedvar);
4✔
1682
  this.cursor.grouped = this.varj(output);
4✔
1683
  return this.addSubQuery(groupquery);
4✔
1684
};
1685

1686
/**
1687
 * A function that always matches, always returns true
1688
 * @returns {WOQLQuery} A WOQLQuery object containing the true value that will match any pattern
1689
 */
1690
WOQLQuery.prototype.true = function () {
1✔
1691
  this.cursor['@type'] = 'True';
1✔
1692
  return this;
1✔
1693
};
1694

1695
/**
1696
 * Performs a path regular expression match on the graph
1697
 * @param {string|Var} subject -  An IRI or variable that refers to an IRI representing the subject,
1698
 * i.e. the starting point of the path
1699
 * @param {string} pattern -(string) - A path regular expression describing a pattern through
1700
 * multiple edges of the graph (see: https://terminusdb.com/docs/path-query-reference-guide)
1701
 * @param {string|Var} object - An IRI or variable that refers to an IRI representing the object,
1702
 * i.e. ending point of the path
1703
 * @param {string|Var} [resultVarName] - A variable in which the actual paths
1704
 * traversed will be stored
1705
 * @returns {WOQLQuery} - A WOQLQuery which contains the path regular expression matching expression
1706
 */
1707

1708
WOQLQuery.prototype.path = function (subject, pattern, object, resultVarName) {
1✔
1709
  if (this.cursor['@type']) this.wrapCursorWithAnd();
40✔
1710
  this.cursor['@type'] = 'Path';
40✔
1711
  this.cursor.subject = this.cleanSubject(subject);
40✔
1712
  if (typeof pattern === 'string') pattern = this.compilePathPattern(pattern);
40!
1713
  this.cursor.pattern = pattern;
40✔
1714
  this.cursor.object = this.cleanObject(object);
40✔
1715
  if (typeof resultVarName !== 'undefined') {
40✔
1716
    this.cursor.path = this.varj(resultVarName);
38✔
1717
  }
1718
  return this;
40✔
1719
};
1720

1721
/**
1722
 * Extract the value of a key in a bound document.
1723
 * @param {string|Var} document - Document which is being accessed.
1724
 * @param {string|Var} field - The field from which the document which is being accessed.
1725
 * @param {string|Var} value - The value for the document and field.
1726
 * @returns {WOQLQuery} A WOQLQuery which contains the a dot Statement
1727
 */
1728

1729
WOQLQuery.prototype.dot = function (document, field, value) {
1✔
1730
  if (this.cursor['@type']) this.wrapCursorWithAnd();
1!
1731
  this.cursor['@type'] = 'Dot';
1✔
1732
  this.cursor.document = this.expandValueVariable(document);
1✔
1733
  this.cursor.field = this.cleanDataValue(field, 'xsd:string');
1✔
1734
  this.cursor.value = this.expandValueVariable(value);
1✔
1735
  return this;
1✔
1736
};
1737

1738
/**
1739
 * Calculates the size in bytes of the contents of the resource identified in ResourceID
1740
 * @param {string|Var} resourceId - A valid resource identifier string (can refer to any graph /
1741
 * branch / commit / db)
1742
 * @param {string|Var} resultVarName - The variable name
1743
 */
1744

1745
WOQLQuery.prototype.size = function (resourceId, resultVarName) {
1✔
1746
  if (this.cursor['@type']) this.wrapCursorWithAnd();
1!
1747
  this.cursor['@type'] = 'Size';
1✔
1748
  this.cursor.resource = this.cleanGraph(resourceId);
1✔
1749
  this.cursor.size = this.varj(resultVarName);
1✔
1750
  return this;
1✔
1751
};
1752

1753
/**
1754
 *
1755
 * Calculates the number of triples of the contents of the resource identified in ResourceID
1756
 * @param {string|Var} resourceId - A valid resource identifier string (can refer to any graph /
1757
 * branch / commit / db)
1758
 * @param {string|number|Var} tripleCount - An integer literal with the size in bytes or a
1759
 * variable containing that integer
1760
 * @returns {WOQLQuery} A WOQLQuery which contains the size expression
1761
 */
1762
WOQLQuery.prototype.triple_count = function (resourceId, TripleCount) {
1✔
1763
  if (this.cursor['@type']) this.wrapCursorWithAnd();
1!
1764
  this.cursor['@type'] = 'TripleCount';
1✔
1765
  this.cursor.resource = this.cleanGraph(resourceId);
1✔
1766
  this.cursor.count = this.varj(TripleCount);
1✔
1767
  return this;
1✔
1768
};
1769

1770
/**
1771
 * Returns true if 'elementId' is of type 'elementType', according to the current DB schema
1772
 * @param {string|Var} elementId - the id of a schema graph element
1773
 * @param {string|Var} elementType - the element type
1774
 * @returns {WOQLQuery} A WOQLQuery object containing the type_of pattern matching rule
1775
 */
1776

1777
WOQLQuery.prototype.type_of = function (elementId, elementType) {
1✔
1778
  if (!elementId || !elementType) return this.parameterError('type_of takes two parameters, both values');
4!
1779
  if (this.cursor['@type']) this.wrapCursorWithAnd();
4!
1780
  this.cursor['@type'] = 'TypeOf';
4✔
1781
  this.cursor.value = this.cleanObject(elementId);
4✔
1782
  this.cursor.type = this.cleanSubject(elementType);
4✔
1783
  return this;
4✔
1784
};
1785

1786
module.exports = WOQLQuery;
1✔
STATUS · Troubleshooting · Open an Issue · Sales · Support · CAREERS · ENTERPRISE · START FREE · SCHEDULE DEMO
ANNOUNCEMENTS · TWITTER · TOS & SLA · Supported CI Services · What's a CI service? · Automated Testing

© 2026 Coveralls, Inc