217 lines
7.8 KiB
JavaScript
217 lines
7.8 KiB
JavaScript
const knex = require('knex');
|
|
|
|
knex.QueryBuilder.extend('whereGroup', function(condition, rules) {
|
|
condition = condition.toLowerCase();
|
|
|
|
for (let rule of rules) {
|
|
if (!rule.condition) {
|
|
let where = condition == 'or' ? 'orWhere' : 'where';
|
|
let column = rule.data ? rule.data.column : rule.column;
|
|
|
|
if (rule.data && rule.data.table) {
|
|
if (rule.data.schema) {
|
|
column = rule.data.schema + '.' + rule.data.table + '.' + column;
|
|
} else {
|
|
column = rule.data.table + '.' + column;
|
|
}
|
|
} else if (rule.table) {
|
|
if (rule.schema) {
|
|
column = rule.schema + '.' + rule.table + '.' + column;
|
|
} else {
|
|
column = rule.table + '.' + column;
|
|
}
|
|
}
|
|
|
|
if (typeof rule.value == 'undefined') {
|
|
rule.value = null;
|
|
}
|
|
|
|
if (rule.operator == 'between') {
|
|
this[where + 'Between'](column, rule.value);
|
|
} else if (rule.operator == 'not_between') {
|
|
this[where + 'NotBetween'](column, rule.value);
|
|
} else if (rule.operator == 'is_null') {
|
|
this[where + 'Null'](column);
|
|
} else if (rule.operator == 'is_not_null') {
|
|
this[where + 'NotNull'](column);
|
|
} else if (rule.operator == 'in') {
|
|
this[where + 'In'](column, rule.value);
|
|
} else if (rule.operator == 'not_in') {
|
|
this[where + 'NotIn'](column, rule.value);
|
|
} else if (rule.operator == 'begins_with') {
|
|
// simple escaping for likes, knex doesn't do this (\ is default in most databases)
|
|
// perhaps improve by using raw query like
|
|
// this[where](knex.raw("?? like ? escape '\'"), [column, escapedValue]);
|
|
let escapedValue = rule.value.replace(/[\\%_^]/g, '\\$&');
|
|
this[where](column, 'like', escapedValue + '%');
|
|
} else if (rule.operator == 'not_begins_with') {
|
|
let escapedValue = rule.value.replace(/[\\%_^]/g, '\\$&');
|
|
this[where + 'Not'](column, 'like', escapedValue + '%');
|
|
} else if (rule.operator == 'ends_with') {
|
|
let escapedValue = rule.value.replace(/[\\%_^]/g, '\\$&');
|
|
this[where](column, 'like', '%' + escapedValue);
|
|
} else if (rule.operator == 'not_ends_with') {
|
|
let escapedValue = rule.value.replace(/[\\%_^]/g, '\\$&');
|
|
this[where + 'Not'](column, 'like', '%' + escapedValue);
|
|
} else if (rule.operator == 'contains') {
|
|
let escapedValue = rule.value.replace(/[\\%_^]/g, '\\$&');
|
|
this[where](column, 'like', '%' + escapedValue + '%');
|
|
} else if (rule.operator == 'not_contains') {
|
|
let escapedValue = rule.value.replace(/[\\%_^]/g, '\\$&');
|
|
this[where + 'Not'](column, 'like', '%' + escapedValue + '%');
|
|
} else {
|
|
this[where](column, rule.operation, rule.value);
|
|
}
|
|
} else {
|
|
this[condition + 'Where'](function() {
|
|
this.whereGroup(rule.condition, rule.rules);
|
|
});
|
|
}
|
|
}
|
|
|
|
return this;
|
|
});
|
|
|
|
knex.QueryBuilder.extend('fromJSON', function(ast, meta) {
|
|
if (ast.type == 'count') {
|
|
return this.count('* as Total').from(function() {
|
|
this.fromJSON(Object.assign({}, ast, {
|
|
type: 'select',
|
|
offset: null,
|
|
limit: null,
|
|
orders: null
|
|
})).as('t1');
|
|
}).first();
|
|
} else if (ast.type == 'insert' || ast.type == 'update') {
|
|
let values = {};
|
|
|
|
for (let val of ast.values) {
|
|
if (val.type == 'json') {
|
|
// json support
|
|
values[val.column] = JSON.stringify(val.value);
|
|
} else {
|
|
values[val.column] = val.value;
|
|
}
|
|
}
|
|
|
|
this[ast.type](values);
|
|
} else {
|
|
this[ast.type]();
|
|
}
|
|
|
|
if (ast.returning && !(this.client?.config?.client?.includes('mysql'))) {
|
|
// Adding the option includeTriggerModifications allows you
|
|
// to run statements on tables that contain triggers. Only affects MSSQL.
|
|
this.returning(ast.returning, { includeTriggerModifications: true });
|
|
}
|
|
|
|
if (ast.table) {
|
|
let table = ast.table.name || ast.table;
|
|
|
|
if (ast.table.schema) {
|
|
table = ast.table.schema + '.' + table;
|
|
}
|
|
|
|
if (ast.table.alias) {
|
|
table += ' as ' + ast.table.alias;
|
|
}
|
|
|
|
this.from(table);
|
|
}
|
|
|
|
if ((ast.type == 'select' || ast.type == 'first') && ast.joins && ast.joins.length) {
|
|
for (let join of ast.joins) {
|
|
let table = join.table;
|
|
|
|
if (join.schema) {
|
|
table = join.schema + '.' + table;
|
|
}
|
|
|
|
if (join.alias) {
|
|
table += ' as ' + join.alias;
|
|
}
|
|
|
|
this[(join.type || 'inner').toLowerCase() + 'Join'](table, function() {
|
|
for (let clause of join.clauses.rules) {
|
|
this.on(
|
|
(clause.schema ? clause.schema + '.' : '') + clause.table + '.' + clause.column,
|
|
clause.operation,
|
|
(clause.value.schema ? clause.value.schema + '.' : '') + clause.value.table + '.' + clause.value.column
|
|
);
|
|
}
|
|
});
|
|
}
|
|
}
|
|
|
|
if ((ast.type == 'select' || ast.type == 'first') && ast.columns) {
|
|
for (let col of ast.columns) {
|
|
let column = col.column || col;
|
|
|
|
if (ast.joins && ast.joins.length && col.table) {
|
|
column = col.table + '.' + column;
|
|
|
|
if (col.schema) {
|
|
column = col.schema + '.' + column;
|
|
}
|
|
}
|
|
|
|
if (col.alias) {
|
|
column += ' as ' + col.alias;
|
|
}
|
|
|
|
this[col.aggregate ? col.aggregate.toLowerCase() : 'column'](column);
|
|
}
|
|
}
|
|
|
|
if ((ast.type == 'select' || ast.type == 'first') && ast.groupBy && ast.groupBy.length) {
|
|
for (let col of ast.groupBy) {
|
|
if (ast.joins && ast.joins.length && col.table) {
|
|
if (col.schema) {
|
|
this.groupBy(col.schema + '.' + col.table + '.' + col.column);
|
|
} else {
|
|
this.groupBy(col.table + '.' + col.column);
|
|
}
|
|
} else {
|
|
this.groupBy(col.column || col);
|
|
}
|
|
}
|
|
}
|
|
|
|
if (ast.wheres && ast.wheres.condition) {
|
|
this.whereGroup(ast.wheres.condition, ast.wheres.rules);
|
|
}
|
|
|
|
if ((ast.type == 'select' || ast.type == 'first') && ast.orders && ast.orders.length) {
|
|
for (let order of ast.orders) {
|
|
if (ast.joins && ast.joins.length && order.table) {
|
|
if (order.schema) {
|
|
this.orderBy(order.schema + '.' + order.table + '.' + order.column, order.direction);
|
|
} else {
|
|
this.orderBy(order.table + '.' + order.column, order.direction);
|
|
}
|
|
} else {
|
|
this.orderBy(order.column, order.direction);
|
|
}
|
|
}
|
|
}
|
|
|
|
if (ast.distinct) {
|
|
this.distinct();
|
|
}
|
|
|
|
if (ast.type == 'select' && ast.limit) {
|
|
this.limit(ast.limit);
|
|
}
|
|
|
|
if (ast.type == 'select' && ast.offset) {
|
|
this.offset(ast.offset);
|
|
}
|
|
|
|
if (meta) {
|
|
this.queryContext(meta);
|
|
}
|
|
|
|
return this;
|
|
});
|
|
|
|
module.exports = knex; |