const ObjectionToKnexConvertingOperation = require('../ObjectionToKnexConvertingOperation'); const { isKnexQueryBuilder } = require('../../../utils/knexUtils'); class WhereInCompositeOperation extends ObjectionToKnexConvertingOperation { constructor(name, opt) { super(name, opt); this.prefix = this.opt.prefix || null; } onBuildKnex(knexBuilder, builder) { this.build(builder.knex(), knexBuilder, this.args[0], this.args[1]); } build(knex, knexBuilder, columns, values) { let isCompositeKey = Array.isArray(columns) && columns.length > 1; if (isCompositeKey) { this.buildComposite(knex, knexBuilder, columns, values); } else { this.buildNonComposite(knexBuilder, columns, values); } } buildComposite(knex, knexBuilder, columns, values) { if (Array.isArray(values)) { this.buildCompositeValue(knexBuilder, columns, values); } else { this.buildCompositeSubquery(knex, knexBuilder, columns, values); } } buildCompositeValue(knexBuilder, columns, values) { this.whereIn(knexBuilder, columns, values); } buildCompositeSubquery(knex, knexBuilder, columns, subquery) { const sql = `(${columns .map(col => { // On older versions of knex, raw doesn't work // with `??`. We use `?` for those. if (typeof col === 'object') { return '?'; } else { return '??'; } }) .join(',')})`; this.whereIn(knexBuilder, knex.raw(sql, columns), subquery); } buildNonComposite(knexBuilder, columns, values) { const col = typeof columns === 'string' ? columns : columns[0]; if (Array.isArray(values)) { values = pickNonNull(values, []); } else if (!isKnexQueryBuilder(values)) { values = [values]; } this.whereIn(knexBuilder, col, values); } whereIn(knexBuilder, col, val) { if (this.prefix === 'not') { knexBuilder.whereNotIn(col, val); } else { knexBuilder.whereIn(col, val); } } } function pickNonNull(values, output) { for (let i = 0, l = values.length; i < l; ++i) { const val = values[i]; if (Array.isArray(val)) { pickNonNull(val, output); } else if (val !== null && val !== undefined) { output.push(val); } } return output; } module.exports = WhereInCompositeOperation;