UNPKG

@wmfs/pg-model

Version:

Takes a relational database structure and returns model objects for noSQL-like abilities.

108 lines (97 loc) 3.11 kB
const expressionTypeFormatters = { equals: function (columnName, value, values) { values.push(value) return columnName + ' = $' + values.length }, notEquals: function (columnName, value, values) { values.push(value) return columnName + ' != $' + values.length }, moreThan: function (columnName, value, values) { values.push(value) return columnName + ' > $' + values.length }, lessThan: function (columnName, value, values) { values.push(value) return columnName + ' < $' + values.length }, moreThanEquals: function (columnName, value, values) { values.push(value) return columnName + ' >= $' + values.length }, lessThanEquals: function (columnName, value, values) { values.push(value) return columnName + ' <= $' + values.length }, like: function (columnName, value, values) { values.push(`%${value}%`) return columnName + '::text LIKE $' + values.length }, isNull: function (columnName, value) { return value === true ? columnName + ' is null' : columnName + ' is not null' } } module.exports = function refineSql (sql, propertyIdToColumn, options) { const values = [] if (options) { // WHERE // ----- if (Object.prototype.hasOwnProperty.call(options, 'where') && Object.keys(options.where).length) { sql += buildWhereClause(options.where, propertyIdToColumn, values) } // ORDER BY // -------- if (Object.prototype.hasOwnProperty.call(options, 'orderBy') && options.orderBy.length) { const parts = [] sql += ' ORDER BY ' options.orderBy.forEach( function (propertyId) { let direction if (propertyId[0] === '-') { direction = 'DESC' propertyId = propertyId.substring(1) } else { direction = 'ASC' } parts.push(propertyIdToColumn[propertyId] + ' ' + direction) } ) sql += parts.join(', ') if (options.nullsLast) { sql += ' NULLS LAST' } } // LIMIT // ----- if (Object.prototype.hasOwnProperty.call(options, 'limit')) { sql += ' LIMIT ' + options.limit } // OFFSET // ------ if (Object.prototype.hasOwnProperty.call(options, 'offset')) { sql += ' OFFSET ' + options.offset } } return { sql: sql, values: values } } // refineSql function buildWhereClause (where, propertyIdToColumn, values) { const parts = [] for (const [propertyId, expression] of Object.entries(where)) { const columnName = propertyIdToColumn[propertyId] const expressionType = Object.keys(expression)[0] const formatter = expressionTypeFormatters[expressionType] const param = Object.values(expression)[0] if (!Array.isArray(param)) { parts.push(formatter(columnName, param, values)) } else { const subclauseParts = param .map(p => formatter(columnName, p, values)) const subclause = `(${subclauseParts.join(' OR ')})` parts.push(subclause) } } // for ... return ` WHERE ${parts.join(' AND ')}` } // buildWhereClause