sql.js ➔ recurseWhere   F
last analyzed

Complexity

Conditions 17
Paths 21

Size

Total Lines 61

Duplication

Lines 0
Ratio 0 %

Importance

Changes 1
Bugs 0 Features 0
Metric Value
cc 17
c 1
b 0
f 0
nc 21
nop 3
dl 0
loc 61
rs 1.8

How to fix   Long Method    Complexity   

Long Method

Small methods make your code easier to understand, in particular if combined with a good name. Besides, if your method is small, finding a good name is usually much easier.

For example, if you find yourself adding comments to a method's body, this is usually a good sign to extract the commented part to a new method, and use the comment as a starting point when coming up with a good name for this new method.

Commonly applied refactorings include:

Complexity

Complex classes like sql.js ➔ recurseWhere often do a lot of different things. To break such a class down, we need to identify a cohesive component within that class. A common approach to find such a component is to look for fields/methods that share the same prefixes, or suffixes.

Once you have determined the fields that belong together, you can apply the Extract Class refactoring. If the component makes sense as a sub-class, Extract Subclass is also a candidate, and is often faster.

1
import {parse} from 'node-sqlparser'
2
import {Promise} from 'bluebird'
3
import path from 'path'
4
import _ from 'lodash'
5
import {coreUtils, config, Manager, cmsData} from '../../'
0 ignored issues
show
Unused Code introduced by
The variable config seems to be never used. Consider removing it.
Loading history...
6
7
/**
8
 * take a string and json to escape sql character and convert to sql like syntax
9
 *
10
 * Example: escapeAbeValuesFromStringRequest('select title from ./ where `abe_meta.template`=`{{article}}`', {article: "test"})
11
 *
12
 * Return string: select title from ___abe_dot______abe_dot______abe___ where  `abe_meta.template`=`test`
13
 * 
14
 * 
15
 * @param  {String} str      raw abe request sql string
16
 * @param  {Object} jsonPage json object of post
17
 * @return {String}          escaped string
18
 */
19
export function escapeAbeValuesFromStringRequest(str, jsonPage) {
20
  var matchFrom = /from .(.*?) /
21
  var matchVariable = /{{(.*?)}}/
22
23
  var matchFromExec = matchFrom.exec(str)
24
  if (matchFromExec != null && matchFromExec[1] != null) {
25
    var fromMatch
26
    var toReplace = matchFromExec[1]
27
    while ((fromMatch = matchVariable.exec(toReplace))) {
28
      try {
29
        var arFrom = fromMatch[1].split('.')
30
        var value = _.get(jsonPage, arFrom)
31
        if (value != null) {
32
          toReplace = toReplace.replace('{{' + fromMatch[1] + '}}', value)
33
        } else {
34
          toReplace = toReplace.replace('{{' + fromMatch[1] + '}}', '')
35
        }
36
      } catch (e) {}
0 ignored issues
show
Coding Style Comprehensibility Best Practice introduced by
Empty catch clauses should be used with caution; consider adding a comment why this is needed.
Loading history...
37
    }
38
39
    str = str.replace(matchFromExec[1], toReplace)
40
  }
41
42
  var from = /from ([\S\s]+)/.exec(str)
43
44
  var matches = from
45
  if (matches[1]) {
46
    var res = matches[1]
47
    var splitAttr = [
48
      ' where ',
49
      ' order by ',
50
      ' limit ',
51
      ' WHERE ',
52
      ' ORDER BY ',
53
      ' LIMIT '
54
    ]
55
    for (var i = 0; i < splitAttr.length; i++) {
56
      if (res.indexOf(splitAttr[i]) > -1) {
57
        res = res.substring(0, res.indexOf(splitAttr[i]))
58
      }
59
    }
60
    var escapedFrom = res.replace(/\//g, '___abe___')
61
    escapedFrom = escapedFrom.replace(/\./g, '___abe_dot___')
62
    escapedFrom = escapedFrom.replace(/-/g, '___abe_dash___')
63
    str = str.replace(res, escapedFrom)
64
  }
65
66
  str = str.replace(/``/g, "''")
67
68
  return str
69
}
70
71
/**
72
 * analyse and create an object from request sql string
73
 *
74
 * Example: handleSqlRequest('select title from ./ where `abe_meta.template`=`{{article}}`', {article: "test"})
75
 * 
76
 * @param  {String} str      Sql string request
77
 * @param  {Object} jsonPage json of post
78
 * @return {Object}          {type, columns, from, where, string, limit, orderby}
79
 */
80
export function handleSqlRequest(str, jsonPage) {
81
  var req = escapeAbeValuesFromStringRequest(str, jsonPage)
82
  var request = parse(req)
83
  var reconstructSql = ''
84
  // SQL TYPE
85
  var type = ''
86
  if (request.type != null) {
87
    type = request.type
88
  }
89
  reconstructSql += `${type} `
90
  // SQL COLUMNS
91
  var columns = []
92
  if (request.columns != null) {
93
    if (request.columns === '*') {
94
      columns.push('*')
95
    } else {
96
      Array.prototype.forEach.call(request.columns, item => {
97
        columns.push(item.expr.column)
98
      })
99
    }
100
  }
101
  reconstructSql += `${JSON.stringify(columns)} `
102
  // SQL FROM
103
  var from = []
104
  if (request.from != null) {
105
    Array.prototype.forEach.call(request.from, item => {
106
      from.push(item.table)
107
    })
108
  } else {
109
    from.push('*')
110
  }
111
  reconstructSql += `from ${JSON.stringify(from)} `
112
113
  var where = null
114
  if (request.where != null) {
115
    where = request.where
116
  }
117
118
  var limit = -1
119
  if (request.limit != null) {
120
    limit = request.limit[request.limit.length - 1].value
121
  }
122
123
  var orderby = null
124
  if (request.orderby != null && request.orderby.length > 0) {
125
    orderby = {
126
      column: request.orderby[0].expr.column,
127
      type: request.orderby[0].type
128
    }
129
    reconstructSql += `ORDER BY ${orderby.column} ${orderby.type} `
130
  }
131
132
  return {
133
    type: type,
134
    columns: columns,
135
    from: from,
136
    where: where,
137
    string: reconstructSql,
138
    limit: limit,
139
    orderby: orderby
140
  }
141
}
142
143
/**
144
 * get JSON from abe tag attribute source
145
 *
146
 * {{abe type='data' key='titles' desc='select titles' source='[{"title": "rouge", "id": 1},{"title": "vert", "id": 2},{"title": "blue", "id": 3}]' display="{{title}}"}}
147
 *
148
 * return 
149
 * [{"title": "rouge", "id": 1},{"title": "vert", "id": 2},{"title": "blue", "id": 3}]
150
 * 
151
 * @param  {String} str abe tag
152
 * @return {String}     json string
153
 */
154
export function getDataSource(str) {
155
  var reg = /source=(['|"])(.*?)\1[ |\}]/g
156
  var match = reg.exec(str)
157
  if (match != null) {
158
    return match[2]
159
  }
160
161
  return ''
162
}
163
164
/**
165
 * replaces escaped characters with the right ones
166
 * @param  {String} statement the from clause
167
 * @return {String}           the from sanitized
168
 */
169
export function sanitizeFromStatement(statement) {
170
  var from = ''
171
172
  if (statement != null) {
173
    from = statement[0].replace(/___abe_dot___/g, '.')
174
    from = from.replace(/___abe___/g, '/')
175
    from = from.replace(/___abe_dash___/g, '-')
176
  }
177
178
  return from
179
}
180
181
/**
182
 * calculate the directory to analyze from the from clause
183
 * @param  {String} statement the from clause
184
 * @param  {String} tplPath   the path from the template originator
185
 * @return {string}           the directory to analyze
186
 */
187
export function getFromDirectory(statement, tplPath = '/') {
188
  var pathFromDir = ''
189
190
  if (statement === '' || statement === '*' || statement === '/') {
191
    pathFromDir = Manager.instance.pathData
192
  } else if (statement === './') {
193
    pathFromDir = path.join(Manager.instance.pathData, tplPath)
194
  } else if (statement.indexOf('/') === 0) {
195
    pathFromDir = path.join(Manager.instance.pathData, statement)
196
  } else if (statement.indexOf('/') !== 0) {
197
    pathFromDir = path.join(Manager.instance.pathData, tplPath, statement)
198
  }
199
200
  return pathFromDir
201
}
202
203
/**
204
 * sort array of files from where clause
205
 *
206
 * @param  {Array} files
207
 * @param  {Object} orderby {orderby: {column: 'date'}} | {orderby: {column: 'random', type: 'ASC'}}
208
 * @return {Array}         sorted array
209
 */
210
export function executeOrderByClause(files, orderby) {
211
  if (orderby != null) {
212
    if (orderby.column.toLowerCase() === 'random') {
213
      files = coreUtils.sort.shuffle(files)
214
    } else if (orderby.column.toLowerCase() === 'date') {
215
      if (orderby.type.toLowerCase() === 'asc') {
216
        files.sort(cmsData.sort.byDateAsc)
217
      } else if (orderby.type.toLowerCase() === 'desc') {
218
        files.sort(cmsData.sort.byDateDesc)
219
      }
220
    } else {
221
      files.sort(
222
        coreUtils.sort.predicatBy(
223
          orderby.column.toLowerCase(),
224
          orderby.type.toLowerCase() === 'desc' ? -1 : 1
225
        )
226
      )
227
    }
228
  }
229
230
  return files
231
}
232
233
/**
234
 * Keep only published post
235
 *
236
 * keepOnlyPublishedPost([files])
237
 *
238
 * @param  {Array} files      paths
239
 * @return {Array}                files
240
 */
241
export function keepOnlyPublishedPost(files) {
242
  var publishedValue = []
243
  Array.prototype.forEach.call(files, file => {
244
    if (file.publish != null) {
245
      publishedValue.push(file.publish)
246
    }
247
  })
248
249
  return publishedValue
250
}
251
252
/**
253
 * Check array of files have path that match path statement
254
 *
255
 * executeFromClause([array], ['/'], ['/'])
256
 *
257
 * @param  {Array} statement      paths
258
 * @param  {Array} pathFromClause paths
259
 * @return {Array}                files
260
 */
261
export function executeFromClause(files, statement, pathFromClause) {
262
  var from = sanitizeFromStatement(statement)
263
264
  // if the from clause ends with a dot, we won't recurse the directory analyze
265
  if (from.slice(-1) === '.') {
266
    from = from.slice(0, -1)
267
  }
268
269
  var fromDirectory = getFromDirectory(from, pathFromClause)
270
271
  var files_array = files.filter(element => {
272
    if (element.path.indexOf(fromDirectory) > -1) {
273
      return true
274
    }
275
    return false
276
  })
277
278
  return files_array
279
}
280
281
/**
282
 * Execute sql query like to find abe json post that match the query
283
 * 
284
 * @param  {Array} pathQuery of paths
0 ignored issues
show
Documentation introduced by
The parameter pathQuery does not exist. Did you maybe forget to remove this comment?
Loading history...
285
 * @param  {String} match     request sql
286
 * @param  {Object} jsonPage  json of post
287
 * @return {Array}           found object that match
288
 */
289
export function execQuery(match, jsonPage) {
290
  var files = keepOnlyPublishedPost(Manager.instance.getList())
291
  var request = handleSqlRequest(
292
    cmsData.regex.getAttr(match, 'source'),
293
    jsonPage
294
  )
295
  var pathQuery =
296
    jsonPage && jsonPage.abe_meta != null && jsonPage.abe_meta.link != null
297
      ? path.dirname(jsonPage.abe_meta.link)
298
      : '/'
299
300
  files = executeFromClause(files, request.from, pathQuery)
301
  files = executeWhereClause(files, request.where, request.columns, jsonPage)
302
  files = executeOrderByClause(files, request.orderby)
303
  files = executeLimitClause(files, request.limit)
304
  return files
305
}
306
307
export function executeQuerySync(match, jsonPage) {
308
  return execQuery(match, jsonPage)
309
}
310
311
export function executeQuery(match, jsonPage) {
312
  var p = new Promise(resolve => {
313
    var res = execQuery(match, jsonPage)
314
    resolve(res)
315
  }).catch(function(e) {
316
    console.error(e)
317
  })
318
319
  return p
320
}
321
322
/**
323
 * check if a given string an url, string json, file url, abe sql request
324
 * 
325
 * get('http://google.com')
326
 * get('{"test":"test"}')
327
 * get('select * from ../')
328
 * get('test')
329
 * 
330
 * @param  {String} str 
331
 * @return {String} url | request | value | file | other
332
 */
333
export function getSourceType(str) {
334
  if (/^(http:\/\/|https:\/\/|:\/\/|\/(.*)\?(.*)[^ ]=)/.test(str)) {
335
    return 'url'
336
  }
337
338
  if (/select[\S\s]*?from/.test(str)) {
339
    return 'request'
340
  }
341
342
  try {
343
    JSON.parse(str)
344
    return 'value'
345
  } catch (e) {}
0 ignored issues
show
Coding Style Comprehensibility Best Practice introduced by
Empty catch clauses should be used with caution; consider adding a comment why this is needed.
Loading history...
346
347
  if (/\.json/.test(str)) {
348
    return 'file'
349
  }
350
351
  return 'other'
352
}
353
354
/**
355
 * return array of post that match sql where statement
356
 *
357
 * Example: handleSqlRequest('select title from ./ where `abe_meta.template`=`article`', {})
358
 *
359
 * @param  {Array} files    
360
 * @param  {Object} wheres   clause
361
 * @param  {Int} maxLimit 
0 ignored issues
show
Documentation introduced by
The parameter maxLimit does not exist. Did you maybe forget to remove this comment?
Loading history...
362
 * @param  {Array} columns  sql
363
 * @param  {Object} jsonPage json post
364
 * @return {Array}          of files
365
 */
366
export function executeWhereClause(files, wheres, columns, jsonPage) {
367
  if (typeof wheres === 'undefined' || wheres === null) return files
0 ignored issues
show
Coding Style Best Practice introduced by
Curly braces around statements make for more readable code and help prevent bugs when you add further statements.

Consider adding curly braces around all statements when they are executed conditionally. This is optional if there is only one statement, but leaving them out can lead to unexpected behaviour if another statement is added later.

Consider:

if (a > 0)
    b = 42;

If you or someone else later decides to put another statement in, only the first statement will be executed.

if (a > 0)
    console.log("a > 0");
    b = 42;

In this case the statement b = 42 will always be executed, while the logging statement will be executed conditionally.

if (a > 0) {
    console.log("a > 0");
    b = 42;
}

ensures that the proper code will be executed conditionally no matter how many statements are added or removed.

Loading history...
368
  var res = []
369
  var json = {}
370
  var jsonValues = {}
371
372
  for (let file of files) {
373
    if (wheres != null) {
374
      if (!recurseWhere(wheres, file, jsonPage)) {
375
        json = JSON.parse(JSON.stringify(file))
376
        jsonValues = {}
377
378
        if (columns != null && columns.length > 0 && columns[0] !== '*') {
379
          Array.prototype.forEach.call(columns, column => {
380
            if (json[column] != null) {
0 ignored issues
show
Bug introduced by
The variable json is changed as part of the for-each loop for example by JSON.parse(JSON.stringify(file)) on line 375. Only the value of the last iteration will be visible in this function if it is called after the loop.
Loading history...
381
              jsonValues[column] = json[column]
0 ignored issues
show
Bug introduced by
The variable jsonValues is changed as part of the for-each loop for example by {} on line 376. Only the value of the last iteration will be visible in this function if it is called after the loop.
Loading history...
382
            }
383
          })
384
          jsonValues['abe_meta'] = json['abe_meta']
385
        } else {
386
          jsonValues = json
387
        }
388
389
        res.push(jsonValues)
390
      }
391
    }
392
  }
393
394
  return res
395
}
396
397
/**
398
 * return array of post in the limit
399
 *
400
 * Example: executeLimitClause({}, 2)
401
 *
402
 * @param  {Array} files
403
 * @param  {Int} maxLimit 
404
 * @return {Array} of files
405
 */
406
export function executeLimitClause(files, maxLimit) {
407
  if (files.length > maxLimit && maxLimit > 0) {
408
    files.splice(maxLimit, files.length - maxLimit)
409
  }
410
411
  return files
412
}
413
414
/**
415
 * Compare where left and where right clause
416
 * 
417
 * @param  {Object} where           clause
418
 * @param  {Object} jsonDoc         json of current post
419
 * @param  {Object} jsonOriginalDoc json of post to compare
420
 * @return {Object}                 {left: value, right: value}
421
 */
422
export function getWhereValuesToCompare(where, jsonDoc, jsonOriginalDoc) {
423
  var regexIsVariable = /^{{(.*)}}$/
424
  var value = null
425
  var compare = null
426
427
  try {
428
    var variableLeft = where.left.column
429
    var whereLeftColumn = where.left.column
430
    var checkIfLeftIsAVariable = regexIsVariable.exec(variableLeft)
431
    if (checkIfLeftIsAVariable != null && checkIfLeftIsAVariable.length > 0) {
432
      variableLeft = checkIfLeftIsAVariable[1]
433
    }
434
    var arVariableLeft = variableLeft.split('.')
435
    value = _.get(jsonDoc, arVariableLeft)
436
  } catch (e) {
437
    // console.log('e', e)
438
  }
439
440
  if (where.operator === 'IN' || where.operator === 'NOT IN') {
441
    if (value == null) {
442
      // is the form of variableLeft something like elt.attribute or elt[].attribute?
443
      // so maybe is elt an array ?
444
      let arValues = variableLeft.split('.')
445
      let key = arValues[0]
446
      if (key.slice(-2) == '[]') {
447
        key = key.slice(0, -2)
448
      }
449
      let records = _.get(jsonDoc, key)
450
      whereLeftColumn = arValues[1]
451
      value = []
452
      // if yes, value is then an array of values
453
      if (records != null) {
454
        Array.prototype.forEach.call(records, record => {
455
          try {
456
            let val = record[arValues[1]]
457
            value.push(val)
458
          } catch (e) {
459
            console.log(e.stack)
0 ignored issues
show
Debugging Code introduced by
console.log looks like debug code. Are you sure you do not want to remove it?
Loading history...
460
          }
461
        })
462
      }
463
    }
464
    compare = []
465
    Array.prototype.forEach.call(where.right.value, right => {
466
      var matchRightVariable = regexIsVariable.exec(right.column)
467
      if (matchRightVariable != null && matchRightVariable.length > 0) {
468
        try {
469
          var jsonOriginalValues = _.get(jsonOriginalDoc, matchRightVariable[1])
470
          if (
471
            Object.prototype.toString.call(jsonOriginalValues) ===
472
            '[object Array]'
473
          ) {
474
            Array.prototype.forEach.call(
475
              jsonOriginalValues,
476
              jsonOriginalValue => {
477
                compare.push(_.get(jsonOriginalValue, whereLeftColumn))
0 ignored issues
show
Bug introduced by
The variable whereLeftColumn does not seem to be initialized in case var variableLeft = where.left.column on line 428 throws an error. Are you sure this can never be the case?
Loading history...
478
              }
479
            )
480
          } else {
481
            compare.push(jsonOriginalValues)
482
          }
483
        } catch (e) {}
0 ignored issues
show
Coding Style Comprehensibility Best Practice introduced by
Empty catch clauses should be used with caution; consider adding a comment why this is needed.
Loading history...
484
      } else {
485
        compare.push(right.column)
486
      }
487
    })
488
  } else {
489
    if (where.right.column != null) {
490
      compare = where.right.column
491
    } else if (where.right.value != null) {
492
      compare = where.right.value
493
    }
494
495
    var matchRightVariable = regexIsVariable.exec(compare)
496
497
    if (matchRightVariable != null && matchRightVariable.length > 0) {
498
      try {
499
        var arVariableRight = matchRightVariable[1].split('.')
500
        var shouldCompare = _.get(jsonOriginalDoc, arVariableRight)
501
        if (shouldCompare != null) {
502
          compare = shouldCompare
503
        } else {
504
          compare = null
505
        }
506
      } catch (e) {
507
        compare = null
508
      }
509
    }
510
  }
511
512
  return {
513
    left: value,
514
    right: compare
515
  }
516
}
517
518
export function isInStatementCorrect(values, isCorrect) {
519
  let hasPassedTest = false
520
  if (Object.prototype.toString.call(values.left) === '[object Array]') {
521
    Array.prototype.forEach.call(values.left, left => {
522
      Array.prototype.forEach.call(values.right, right => {
523
        if (left != null && left === right) {
524
          hasPassedTest = true
525
        }
526
      })
527
    })
528
  } else {
529
    Array.prototype.forEach.call(values.right, right => {
530
      if (values.left === right) {
531
        hasPassedTest = true
532
      }
533
    })
534
  }
535
536
  if (hasPassedTest) isCorrect = !isCorrect
0 ignored issues
show
Coding Style Best Practice introduced by
Curly braces around statements make for more readable code and help prevent bugs when you add further statements.

Consider adding curly braces around all statements when they are executed conditionally. This is optional if there is only one statement, but leaving them out can lead to unexpected behaviour if another statement is added later.

Consider:

if (a > 0)
    b = 42;

If you or someone else later decides to put another statement in, only the first statement will be executed.

if (a > 0)
    console.log("a > 0");
    b = 42;

In this case the statement b = 42 will always be executed, while the logging statement will be executed conditionally.

if (a > 0) {
    console.log("a > 0");
    b = 42;
}

ensures that the proper code will be executed conditionally no matter how many statements are added or removed.

Loading history...
537
538
  return isCorrect
539
}
540
541
/**
542
 * Check where.left value that match where operator (=, !=, >, >=, <, <=, LIKE, NOT LIKE, AND, OR, IN, NOT IN)
543
 * if operator AND or OR
544
 * Recurse on where.left and where.right sql clause
545
 *
546
 * 
547
 * @param  {Object} where           clause
548
 * @param  {Object} jsonDoc         json of current post
549
 * @param  {Object} jsonOriginalDoc json of post to compare
550
 * @return {Boolean}                 true if not matching | false if matching
551
 */
552
export function recurseWhere(where, jsonDoc, jsonOriginalDoc) {
553
  var isNotLeftCorrect = false
0 ignored issues
show
Unused Code introduced by
The assignment to variable isNotLeftCorrect seems to be never used. Consider removing it.
Loading history...
554
  var isNotRightCorrect = false
0 ignored issues
show
Unused Code introduced by
The assignment to variable isNotRightCorrect seems to be never used. Consider removing it.
Loading history...
555
  var isNotCorrect = false
556
  var values
557
558
  switch (where.operator) {
0 ignored issues
show
Coding Style introduced by
As per coding-style, switch statements should have a default case.
Loading history...
559
    case '=':
560
      values = getWhereValuesToCompare(where, jsonDoc, jsonOriginalDoc)
561
      isNotCorrect = !(values.left === values.right)
562
      break
563
    case '!=':
564
      values = getWhereValuesToCompare(where, jsonDoc, jsonOriginalDoc)
565
      isNotCorrect = !(values.left !== values.right)
566
      break
567
    case '>':
568
      values = getWhereValuesToCompare(where, jsonDoc, jsonOriginalDoc)
569
      isNotCorrect = !(values.left > values.right)
570
      break
571
    case '>=':
572
      values = getWhereValuesToCompare(where, jsonDoc, jsonOriginalDoc)
573
      isNotCorrect = !(values.left >= values.right)
574
      break
575
    case '<':
576
      values = getWhereValuesToCompare(where, jsonDoc, jsonOriginalDoc)
577
      isNotCorrect = !(values.left < values.right)
578
      break
579
    case '<=':
580
      values = getWhereValuesToCompare(where, jsonDoc, jsonOriginalDoc)
581
      isNotCorrect = !(values.left <= values.right)
582
      break
583
    case 'LIKE':
584
      values = getWhereValuesToCompare(where, jsonDoc, jsonOriginalDoc)
585
      isNotCorrect = !(values.left && values.left.indexOf(values.right) > -1)
586
      break
587
    case 'NOT LIKE':
588
      values = getWhereValuesToCompare(where, jsonDoc, jsonOriginalDoc)
589
      isNotCorrect = !(values.left && values.left.indexOf(values.right) === -1)
590
      break
591
    case 'AND':
592
      isNotLeftCorrect = recurseWhere(where.left, jsonDoc, jsonOriginalDoc)
593
      isNotRightCorrect = recurseWhere(where.right, jsonDoc, jsonOriginalDoc)
594
      isNotCorrect = isNotLeftCorrect || isNotRightCorrect ? true : false
595
      break
596
    case 'OR':
597
      isNotLeftCorrect = recurseWhere(where.left, jsonDoc, jsonOriginalDoc)
598
      isNotRightCorrect = recurseWhere(where.right, jsonDoc, jsonOriginalDoc)
599
      isNotCorrect = isNotLeftCorrect && isNotRightCorrect ? true : false
600
      break
601
    case 'IN':
602
      values = getWhereValuesToCompare(where, jsonDoc, jsonOriginalDoc)
603
      isNotCorrect = isInStatementCorrect(values, true)
604
      break
605
    case 'NOT IN':
606
      values = getWhereValuesToCompare(where, jsonDoc, jsonOriginalDoc)
607
      isNotCorrect = isInStatementCorrect(values, false)
608
      break
609
  }
610
611
  return isNotCorrect
612
}
613