Socket
Socket
Sign inDemoInstall

jsonsql

Package Overview
Dependencies
0
Maintainers
1
Versions
11
Alerts
File Explorer

Advanced tools

Install Socket

Detect and block malicious and high-risk dependencies

Install

Comparing version 0.0.4 to 0.1.0

examples/comparative_query.js

448

index.js
var AND = '&&'
, OR = '||'
, AND_STR = 'and'
, OR_STR = 'or'
, NOT = '!'
, EQUAL = '='
, LIKE = '~'
, NOTEQUAL = NOT + EQUAL
, NOTLIKE = NOT + LIKE
, WILDCARD = '*'
, COMMA = ','
, DELIMITER = '.'
, LEFT = '('
, RIGHT = ')'
, WHERE = 'where'
, synopsis = {
pathway: [],
groups: {}
}
, AST = {}
, options = {};
, OR = '||'
, AND_STR = 'and'
, OR_STR = 'or'
, NOT = '!'
, EQUAL = '='
, LIKE = '~'
, NOTEQUAL = NOT + EQUAL
, NOTLIKE = NOT + LIKE
, GT = '>'
, GE = '>='
, LT = '<'
, LE = '<='
, WILDCARD = '*'
, COMMA = ','
, DELIMITER = '.'
, LEFT = '('
, RIGHT = ')'
, WHERE = 'where'
, synopsis = {
pathway: [],
groups: {}
}
, AST = {}
, options = {};
var print = console.log;
function getObjectType(obj) {
return Object.prototype.toString.call(obj);
}
function isDate(obj) {
return getObjectType(obj) === '[object Date]';
}
// ------------------ splitter -------------------- //
function Tokenize(query) {
var parts = __splitTrim(query, WHERE);
var pathway = parts[0];
var where = parts[1];
var parts = __splitTrim(query, WHERE);
var pathway = parts[0];
var where = parts[1];
synopsis.pathway = __splitTrim(pathway, COMMA);
for (var i = 0, len = synopsis.pathway.length; i < len; i++) {
synopsis.pathway[i] = __splitTrim(synopsis.pathway[i], DELIMITER);
if (synopsis.pathway[i][0] == WILDCARD)
synopsis.pathway[i].shift();
if(synopsis.pathway[i].length === 0)
synopsis.pathway.splice(i, 1);
}
synopsis.pathway = __splitTrim(pathway, COMMA);
for (var i = 0, len = synopsis.pathway.length; i < len; i++) {
synopsis.pathway[i] = __splitTrim(synopsis.pathway[i], DELIMITER);
if (synopsis.pathway[i][0] == WILDCARD)
synopsis.pathway[i].shift();
if (synopsis.pathway[i].length === 0)
synopsis.pathway.splice(i, 1);
}
var lastLeft = -1,
lastRight = -1,
current = 0;
while (current < where.length) {
if (where[current] === LEFT) {
lastLeft = current;
} else if (where[current] === RIGHT) {
lastRight = current;
if (lastRight > lastLeft && lastLeft !== -1) {
var k = 'gr' + '_' + new Date().getTime();
synopsis.groups[k] = where.substring(lastLeft + 1, lastRight);
where = where.replace(LEFT + synopsis.groups[k] + RIGHT, k);
current = -1;
}
}
current += 1;
var lastLeft = -1,
lastRight = -1,
current = 0;
while (current < where.length) {
if (where[current] === LEFT) {
lastLeft = current;
} else if (where[current] === RIGHT) {
lastRight = current;
if (lastRight > lastLeft && lastLeft !== -1) {
var k = 'gr' + '_' + new Date().getTime();
synopsis.groups[k] = where.substring(lastLeft + 1, lastRight);
where = where.replace(LEFT + synopsis.groups[k] + RIGHT, k);
current = -1;
}
}
LogicalGrouping(AST, where);
current += 1;
}
LogicalGrouping(AST, where);
}
function LogicalGrouping(current, where) {
var lastAnd = __findIndex(where, AND),
lastOr = __findIndex(where, OR);
var lastAnd = __findIndex(where, AND),
lastOr = __findIndex(where, OR);
if (lastAnd !== Number.MAX_VALUE || lastOr !== Number.MAX_VALUE) {
if (lastAnd < lastOr) {
current.and = current.and || [];
var parts = __splitTrim(where, AND);
current.and.push(parts[0]);
LogicalGrouping(current.and, parts[1]);
} else {
current.or = current.or || [];
var parts = __splitTrim(where, OR);
current.or.push(parts[0]);
LogicalGrouping(current.or, parts[1]);
}
if (lastAnd !== Number.MAX_VALUE || lastOr !== Number.MAX_VALUE) {
if (lastAnd < lastOr) {
current.and = current.and || [];
var parts = __splitTrim(where, AND);
current.and.push(parts[0]);
LogicalGrouping(current.and, parts[1]);
} else {
if (synopsis.groups[where]) {
where = synopsis.groups[where];
LogicalGrouping(current, where);
} else {
if (Array.isArray(current))
current.push(where);
else
current.or = [where];
ExtractExpression(AST.or ? AST.or : AST.and)
}
current.or = current.or || [];
var parts = __splitTrim(where, OR);
current.or.push(parts[0]);
LogicalGrouping(current.or, parts[1]);
}
} else {
if (synopsis.groups[where]) {
where = synopsis.groups[where];
LogicalGrouping(current, where);
} else {
if (Array.isArray(current))
current.push(where);
else
current.or = [where];
ExtractExpression(AST.or ? AST.or : AST.and)
}
}
}
function ExtractExpression(logicalGroup) {
for (var k in logicalGroup) {
if (logicalGroup.hasOwnProperty(k)) {
if (Array.isArray(logicalGroup[k])) {
ExtractExpression(logicalGroup[k]);
}
else if (typeof logicalGroup[k] === 'string') {
if (__contains(logicalGroup[k], NOTEQUAL)) {
var parts = __splitTrim(logicalGroup[k], NOTEQUAL);
logicalGroup[k] = {
ne: [
parts[0],
parts[1]
]
};
} else if (__contains(logicalGroup[k], NOTLIKE)) {
var parts = __splitTrim(logicalGroup[k], NOTLIKE);
logicalGroup[k] = {
nreq: [
parts[0],
parts[1]
]
};
} else if (__contains(logicalGroup[k], EQUAL)) {
var parts = __splitTrim(logicalGroup[k], EQUAL);
logicalGroup[k] = {
eq: [
parts[0],
parts[1]
]
};
} else if (__contains(logicalGroup[k], LIKE)) {
var parts = __splitTrim(logicalGroup[k], LIKE);
logicalGroup[k] = { // rough eq
req: [
parts[0],
parts[1]
]
};
}
}
for (var k in logicalGroup) {
if (logicalGroup.hasOwnProperty(k)) {
if (Array.isArray(logicalGroup[k])) {
ExtractExpression(logicalGroup[k]);
}
else if (typeof logicalGroup[k] === 'string') {
if (__contains(logicalGroup[k], NOTEQUAL)) {
var parts = __splitTrim(logicalGroup[k], NOTEQUAL);
logicalGroup[k] = {
ne: [
parts[0],
parts[1]
]
};
} else if (__contains(logicalGroup[k], NOTLIKE)) {
var parts = __splitTrim(logicalGroup[k], NOTLIKE);
logicalGroup[k] = {
nreq: [
parts[0],
parts[1]
]
};
} else if (__contains(logicalGroup[k], LIKE)) {
var parts = __splitTrim(logicalGroup[k], LIKE);
logicalGroup[k] = { // rough eq
req: [
parts[0],
parts[1]
]
};
} else if (__contains(logicalGroup[k], GE)) {
var parts = __splitTrim(logicalGroup[k], GE);
logicalGroup[k] = { // greater than or equal
ge: [
parts[0],
parts[1]
]
};
} else if (__contains(logicalGroup[k], GT)) {
var parts = __splitTrim(logicalGroup[k], GT);
logicalGroup[k] = { // greater than
gt: [
parts[0],
parts[1]
]
};
} else if (__contains(logicalGroup[k], LE)) {
var parts = __splitTrim(logicalGroup[k], LE);
logicalGroup[k] = { // less than or equal
le: [
parts[0],
parts[1]
]
};
} else if (__contains(logicalGroup[k], LT)) {
var parts = __splitTrim(logicalGroup[k], LT);
logicalGroup[k] = { // less than
lt: [
parts[0],
parts[1]
]
};
} else if (__contains(logicalGroup[k], EQUAL)) {
var parts = __splitTrim(logicalGroup[k], EQUAL);
logicalGroup[k] = {
eq: [
parts[0],
parts[1]
]
};
}
}
}
}
}
function __findIndex(str, token) {
var index = str.indexOf(token);
return index === -1 ? Number.MAX_VALUE : index;
var index = str.indexOf(token);
return index === -1 ? Number.MAX_VALUE : index;
}
function __splitTrim(str, token) {
return str.split(token).map(function (p) {
return p.trim();
});
return str.split(token).map(function (p) {
return p.trim();
});
}
function __contains(a, b) {
return a.indexOf(b) > -1;
return a.indexOf(b) > -1;
}
function __hierarchize(obj, dottedPath) {
var parts = __splitTrim(dottedPath, DELIMITER);
var res = obj;
for (var p in parts)
if (res.hasOwnProperty(parts[p]))
res = res[parts[p]];
else
return '';
return res.toString();
var parts = __splitTrim(dottedPath, DELIMITER);
var res = obj;
for (var p in parts) {
if (res.hasOwnProperty(parts[p]))
res = res[parts[p]];
else
return '';
}
// support comparison for Date
if(isDate(res)) res = res.valueOf()
else res.toString();
return res
}
function FilterOR(ASTNode, row) {
var res = false;
for (var k in ASTNode) {
var filterFunc = (k === AND_STR ? FilterAND : (k === OR_STR ? FilterOR : Filter));
res = res || filterFunc(ASTNode[k], row);
if (options.trace)
console.log(synopsis.step, '======((( or', ASTNode[k], res);
if (res) return res;
}
return res;
var res = false;
for (var k in ASTNode) {
var filterFunc = (k === AND_STR ? FilterAND : (k === OR_STR ? FilterOR : Filter));
res = res || filterFunc(ASTNode[k], row);
if (options.trace)
print(synopsis.step, '======((( or', ASTNode[k], res);
if (res) return res;
}
return res;
}
function FilterAND(ASTNode, row) {
var res = true;
for (var k in ASTNode) {
var filterFunc = (k === AND_STR ? FilterAND : (k === OR_STR ? FilterOR : Filter));
res = res && filterFunc(ASTNode[k], row);
if (options.trace)
console.log(synopsis.step, '======((( and', ASTNode[k], res);
if (!res) return res;
}
return res;
var res = true;
for (var k in ASTNode) {
var filterFunc = (k === AND_STR ? FilterAND : (k === OR_STR ? FilterOR : Filter));
res = res && filterFunc(ASTNode[k], row);
if (options.trace)
print(synopsis.step, '======((( and', ASTNode[k], res);
if (!res) return res;
}
return res;
}
function Filter(ASTNode, row) {
synopsis.step += 1;
if (ASTNode.or) {
var res = FilterOR(ASTNode.or, row);
if (options.trace)
console.log(synopsis.step, 'OR', ASTNode, res);
return res;
} else if (ASTNode.and) {
var res = FilterAND(ASTNode.and, row);
if (options.trace)
console.log(synopsis.step, 'AND', ASTNode, res);
return res;
} else if (typeof ASTNode === 'object') {
if (ASTNode.eq) { // =
return __hierarchize(row, ASTNode.eq[0]) === ASTNode.eq[1];
} else if (ASTNode.ne) { // !=
return __hierarchize(row, ASTNode.ne[0]) !== ASTNode.ne[1];
} else if (ASTNode.req) { // ~
return __contains(__hierarchize(row, ASTNode.req[0]), ASTNode.req[1]);
} else if (ASTNode.nreq) { // ~
return !__contains(__hierarchize(row, ASTNode.nreq[0]), ASTNode.nreq[1]);
} else {
return Filter(ASTNode, row);
}
synopsis.step += 1;
if (ASTNode.or) {
var res = FilterOR(ASTNode.or, row);
if (options.trace)
print(synopsis.step, 'OR', ASTNode, res);
return res;
} else if (ASTNode.and) {
var res = FilterAND(ASTNode.and, row);
if (options.trace)
print(synopsis.step, 'AND', ASTNode, res);
return res;
} else if (typeof ASTNode === 'object') {
if (ASTNode.eq) { // =
return __hierarchize(row, ASTNode.eq[0]) === ASTNode.eq[1];
} else if (ASTNode.ne) { // !=
return __hierarchize(row, ASTNode.ne[0]) !== ASTNode.ne[1];
} else if (ASTNode.req) { // ~
return __contains(__hierarchize(row, ASTNode.req[0]), ASTNode.req[1]);
} else if (ASTNode.nreq) { // ~
return !__contains(__hierarchize(row, ASTNode.nreq[0]), ASTNode.nreq[1]);
} else if (ASTNode.gt) { // >
return __hierarchize(row, ASTNode.gt[0]) > ASTNode.gt[1];
} else if (ASTNode.ge) { // >=
return __hierarchize(row, ASTNode.ge[0]) >= ASTNode.ge[1];
} else if (ASTNode.lt) { // <
return __hierarchize(row, ASTNode.lt[0]) < ASTNode.lt[1];
} else if (ASTNode.le) { // <=
return __hierarchize(row, ASTNode.le[0]) <= ASTNode.le[1];
} else {
return Filter(ASTNode, row);
}
}
}
function Parse(dataSource) {
var result = [];
for (var k in dataSource)
if (Filter(AST, dataSource[k]))
result.push(dataSource[k]);
return result;
var result = [];
for (var k in dataSource)
if (Filter(AST, dataSource[k]))
result.push(dataSource[k]);
return result;
}
function Fields(result) {
if (result && synopsis.pathway.length > 0) {
//console.log(synopsis.pathway);
return result.map(function (ele) {
var res = {};
for(var i = 0, len = synopsis.pathway.length; i< len; i++){
var key = synopsis.pathway[i].join(DELIMITER);
res[key] = __hierarchize(ele, key);
}
return res;
});
}
return result;
if (result && synopsis.pathway.length > 0) {
//print(synopsis.pathway);
return result.map(function (ele) {
var res = {};
for (var i = 0, len = synopsis.pathway.length; i < len; i++) {
var key = synopsis.pathway[i].join(DELIMITER);
res[key] = __hierarchize(ele, key);
}
return res;
});
}
return result;
}
function Query(dataSource, query, opts) {
synopsis = {
pathway: [],
groups: {},
step: 0
synopsis = {
pathway: [],
groups: {},
step: 0
};
AST = {};
opts = opts || {
trace: false
};
AST = {};
opts = opts || {
trace: false
};
options = opts;
Tokenize(query);
return Fields(Parse(dataSource));
options = opts;
Tokenize(query);
return Fields(Parse(dataSource));
}

@@ -236,0 +294,0 @@

{
"name": "jsonsql",
"version": "0.0.4",
"version": "0.1.0",
"description" : "A SQL-like query language for JSON objects.",

@@ -5,0 +5,0 @@ "main": "index.js",

# jsonSQL
[![npm version](https://badge.fury.io/js/jsonsql.svg?branche=master)](http://badge.fury.io/js/jsonsql)
A SQL-like query language for JSON objects.
## Install
`npm install jsonsql`
```
npm install jsonsql
```

@@ -20,5 +25,5 @@ ## Semantics

## Example
## Generic query
#### Data Source:
##### Data Source:
```javascript

@@ -70,3 +75,5 @@ var dataSource = {

```
#### Query by jsonSQL:
- - -
##### Query with condition:
```javascript

@@ -77,3 +84,3 @@ var Query = require('jsonSQL');

```
#### RESULT OUTPUT:
##### RESULT OUTPUT:

@@ -102,3 +109,4 @@ ```bash

#### Multi-Fields Query:
- - -
##### Multi-Fields Query:
```javascript

@@ -108,3 +116,3 @@ var res = Query(dataSource, '*.id, *.holy.addr where holy.name=CRAP');

```
#### RESULT OUTPUT:
##### RESULT OUTPUT:
```bash

@@ -114,2 +122,55 @@ ======RESULT 2

'holy.addr': '7f:e8:ee:32:cd:15' } ]
```
```
## Comparsion
##### Data Source:
```javascript
var dataSource = {
'4866102f06de4f38bc30592e001cf423': {
name: 'Tom',
age: 33,
birth: new Date(2016, 1, 1)
},
'd07872f7d2e8447bbe874bbfd3fb0296': {
name: 'Jack',
age: 18,
birth: new Date(2015, 1, 1)
},
'd935869b80f542a9bf3f6a59d4f635f1': {
name: 'Peter',
age: 26,
birth: new Date(2014, 1, 1)
},
};
```
- - -
##### Number comparison:
```javascript
var Query = require('../index');
var res = Query(dataSource, '* where age<=30');
console.log('======RESULT 1\n',res);
```
##### RESULT OUTPUT:
```bash
======RESULT 1
[ { name: 'Jack',
age: 18,
birth: Sun Feb 01 2015 00:00:00 GMT+0800 (CST) },
{ name: 'Peter',
age: 26,
birth: Sat Feb 01 2014 00:00:00 GMT+0800 (CST) } ]
```
##### Date comparison:
```javascript
var res = Query(dataSource, '* where birth>' + new Date(2015,1,1).valueOf());
console.log('======RESULT 2\n',res);
```
##### RESULT OUTPUT:
```bash
======RESULT 2
[ { name: 'Tom',
age: 33,
birth: Mon Feb 01 2016 00:00:00 GMT+0800 (CST) } ]
```
SocketSocket SOC 2 Logo

Product

  • Package Alerts
  • Integrations
  • Docs
  • Pricing
  • FAQ
  • Roadmap

Stay in touch

Get open source security insights delivered straight into your inbox.


  • Terms
  • Privacy
  • Security

Made with ⚡️ by Socket Inc