sails-arangojs
Version:
A sails-arangojs adapter for Sails / Waterline
302 lines (269 loc) • 7.63 kB
JavaScript
const filterStatement = () => {
const SqlString = dbmodules.SqlString();
function specialValue(val, key) {
if (`${val}`.includes('(record.')) {
return val;
}
if (`${val}`.slice(0, 1) === '$') {
return `${val}`.replace('$', '');
}
if (_.isObject(val)) {
return JSON.stringify(val);
}
if (_.isString(val)) {
return `${SqlString.escape(`${val}`.trim())}`;
}
if (Number(val)) {
return val;
}
return val;
}
const getInStatement = (arr) => {
let str = '';
if (Array.isArray(arr) && arr.length > 0) {
if (arr.length === 1) {
const v = arr[0];
str = `== ${specialValue(v)}`;
} else {
const elements = arr.map((v) => (typeof v === 'string' ? `'${v}'` : v));
str = `IN [${elements}]`;
}
} else {
throw new Error('the IN statement expects an array of values.');
}
return str;
};
const getHasStatement = (val) => {
let str = '';
if (_.isString(val) || _.isNumber(val)) {
str = `${specialValue(val)}`;
} else {
throw new Error('the HAS statement expects a number or string.');
}
return str;
};
function getNotHasStatement(val) {
let str = '';
if (_.isString(val) || _.isNumber(val)) {
str = `${specialValue(val)}`;
} else {
throw new Error('the NOT HAS statement expects a number or string.');
}
return str;
}
const getNotInStatement = (arr) => {
let str = '';
if (Array.isArray(arr) && arr.length > 0) {
if (arr.length === 1) {
const v = arr[0];
str = `!= ${specialValue(v)}`;
} else {
const elements = arr.map((v) => (typeof v === 'string' ? `'${v}'` : v));
str = `NOT IN [${elements}]`;
}
} else {
throw new Error('the IN statement expects an array of values.');
}
return str;
};
const getBetweenStatement = (arr) => {
const btwn = [];
if (Array.isArray(arr) && arr.length === 2) {
btwn.push(arr[0]);
btwn.push(arr[1]);
} else {
throw new Error(
'An array of two values is expected in the BETWEEN criteria'
);
}
return `BETWEEN ${btwn.join(' AND ')}`;
};
const getComparison = (obj) => {
if (_.isEmpty(obj)) {
return '';
}
let str = null;
_.each(obj, (value, key) => {
switch (`${key}`.toLowerCase()) {
case '$gt':
str = `> ${value}`;
return;
case '$gte':
str = `>= ${value}`;
return;
case '$lt':
str = `< ${value}`;
return;
case '$lte':
str = `<= ${value}`;
return;
case '$ne':
str = `!= ${specialValue(value)}`;
return;
case '>':
str = `> ${specialValue(value)}`;
return;
case '>=':
str = `>= ${specialValue(value)}`;
return;
case '<':
str = `< ${value}`;
return;
case '<=':
str = `<= ${value}`;
return;
case '<>':
str = `!= ${specialValue(value)}`;
return;
case '!=':
str = `!= ${specialValue(value)}`;
return;
case 'like':
str = `LIKE ${`${specialValue(value)}`.toLowerCase()}`;
return;
case '$like':
str = `LIKE ${`${specialValue(value)}`.toLowerCase()}`;
return;
case 'notlike':
str = `NOT LIKE ${`${specialValue(value)}`.toLowerCase()}`;
return;
case '$notlike':
str = `NOT LIKE ${`${specialValue(value)}`.toLowerCase()}`;
return;
case '$in':
str = getInStatement(value);
return;
case 'in':
str = getInStatement(value);
return;
case '$has':
str = getHasStatement(value);
case '$nothas':
str = getNotHasStatement(value);
return;
case '$nin':
str = getNotInStatement(value);
return;
case 'nin':
str = getNotInStatement(value);
return;
case '$between':
str = getBetweenStatement(value);
return;
default:
str = null;
}
});
return str;
};
const getAndStatement = (obj) => {
const criteria = [];
const str = null;
if (_.isEmpty(obj)) {
return '';
}
_.each(obj, (value, key) => {
const keystr = `${key}`.replace(/ /g, '');
if (key.toLowerCase() === '$or' || key.toLowerCase() === 'or') {
// eslint-disable-next-line no-use-before-define
criteria.push(`(${getOrStatement(value)})`);
return;
}
if (key.toLowerCase() === 'and' || key.toLowerCase() === '$and') {
// eslint-disable-next-line no-use-before-define
criteria.push(`(${getAndArrayStatement(value)})`);
return;
}
if (key.toLowerCase() === '$between' || key.toLowerCase() === 'between') {
criteria.push(`BETWEEN ${getAndStatement(value)}`);
return;
}
// if (_.isArray(value)) {
// let inarr = '';
// if (value.length === 1) {
// const v = value[0];
// inarr = `== ${specialValue(v)}`;
// }
// inarr = `IN [${value.map((v) => specialValue(v))}]`;
// criteria.push(inarr);
// return;
// }
if (_.isObject(value)) {
if (_.has(value, '$has') || _.has(value, 'has')) {
criteria.push(`${getComparison(value)} IN record.${key} `);
return;
}
if (
_.has(value, '$like') ||
_.has(value, 'like') ||
_.has(value, '$notlike') ||
_.has(value, 'notlike')
) {
criteria.push(`LOWER(record.${key}) ${getComparison(value)}`);
return;
}
if (`${keystr}`.includes('(record.') || `${keystr}`.includes('$')) {
criteria.push(
`${`${keystr}`.replace('$', '')} ${getComparison(value)}`
);
} else {
criteria.push(`record.${key} ${getComparison(value)}`);
}
return;
}
if (`${keystr}`.includes('(record.') || `${keystr}`.includes('$')) {
criteria.push(
`${`${keystr}`.replace('$', '')} == ${specialValue(value, key)}`
);
} else {
criteria.push(`record.${key} == ${specialValue(value, key)}`);
}
});
if (str) {
return str;
}
return criteria.join(' AND ');
};
const getOrStatement = (arr) => {
const orst = [];
if (Array.isArray(arr) && arr.length > 1) {
_.each(arr, (obj) => {
orst.push(getAndStatement(obj));
});
} else {
throw new Error(
'We expect an array of more than one objects on the OR criteria'
);
}
return orst.join(' OR ');
};
const getAndArrayStatement = (arr) => {
const andst = [];
if (Array.isArray(arr)) {
_.each(arr, (obj) => {
andst.push(getAndStatement(obj));
});
} else {
throw new Error('We expect an array in the AND criteria');
}
return andst.join(' AND ');
};
const getLetStatements = (obj) => {
let str = '';
for (const key in obj) {
let val = obj[key];
// if(_.isObject(obj) || _.isArray(obj)){
// }
if (`${val}`.slice(0, 1) === '$') {
val = `${val}`.replace('$', '$');
}
str = `${str}LET ${key} = ${specialValue(val)}\n`;
}
return str;
};
return {
getAndStatement,
getLetStatements,
};
};
module.exports = String(filterStatement);