const ObjectionToKnexConvertingOperation = require('../ObjectionToKnexConvertingOperation'); const { isKnexQueryBuilder } = require('../../../utils/knexUtils'); class WhereInCompositeSqliteOperation extends ObjectionToKnexConvertingOperation { constructor(name, opt) { super(name, opt); this.prefix = this.opt.prefix || null; } onBuildKnex(knexBuilder) { this.build(knexBuilder, this.args[0], this.args[1]); } build(knexBuilder, columns, values) { let isCompositeKey = Array.isArray(columns) && columns.length > 1; if (isCompositeKey) { this.buildComposite(knexBuilder, columns, values); } else { this.buildNonComposite(knexBuilder, columns, values); } } buildComposite(knexBuilder, columns, values) { const whereMethod = this.prefix === 'not' ? 'whereNot' : 'where'; if (!Array.isArray(values)) { // If the `values` is not an array of values but a function or a subquery // we have no way to implement this method. throw new Error(`sqlite doesn't support multi-column where in clauses`); } // Sqlite doesn't support the `where in` syntax for multiple columns but // we can emulate it using grouped `or` clauses. knexBuilder[whereMethod](builder => { values.forEach(val => { builder.orWhere(builder => { columns.forEach((col, idx) => { builder.andWhere(col, val[idx]); }); }); }); }); } buildNonComposite(knexBuilder, columns, values) { let col = typeof columns === 'string' ? columns : columns[0]; if (Array.isArray(values)) { values = pickNonNull(values, []); } else if (!isKnexQueryBuilder(values)) { values = [values]; } // For non-composite keys we can use the normal whereIn. if (this.prefix === 'not') { knexBuilder.whereNotIn(col, values); } else { knexBuilder.whereIn(col, values); } } } 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 = WhereInCompositeSqliteOperation;