import { EntityMetadata, FindOperator, ObjectLiteral, SelectQueryBuilder } from 'typeorm'; import { EntityColumnNotFound } from 'typeorm/error/EntityColumnNotFound'; export class FindUtils { static applyDataRangeWhereToQueryBuilder( qb: SelectQueryBuilder, where: ObjectLiteral | ObjectLiteral[] ): SelectQueryBuilder { const condition = this.computeWhereParameter(qb, where); let type: 'and' | 'simple' = qb.expressionMap.wheres.length > 0 ? 'and' : 'simple'; if (condition) qb.expressionMap.wheres.push({ type, condition: '(' + condition + ')' }); return qb; } static computeWhereParameter( qb: SelectQueryBuilder, where: ObjectLiteral | ObjectLiteral[] ): string { const wheres: ObjectLiteral[] = Array.isArray(where) ? where : [where]; let andConditions: string[]; let parameterIndex = Object.keys(qb.expressionMap.nativeParameters).length; if (qb.expressionMap.mainAlias!.hasMetadata) { andConditions = wheres.map((where, whereIndex) => { const propertyPaths = EntityMetadata.createPropertyPath( qb.expressionMap.mainAlias!.metadata, where ); return propertyPaths .map((propertyPath, propertyIndex) => { const columns = qb.expressionMap.mainAlias!.metadata.findColumnsWithPropertyPath( propertyPath ); if (!columns.length) { throw new EntityColumnNotFound(propertyPath); } return columns .map((column, columnIndex) => { const aliasPath = qb.expressionMap.aliasNamePrefixingEnabled ? `${qb.alias}.${propertyPath}` : column.propertyPath; let parameterValue = column.getEntityValue(where, true); const parameterName = 'where_' + whereIndex + '_' + propertyIndex + '_' + columnIndex; const parameterBaseCount = Object.keys( qb.expressionMap.nativeParameters ).filter((x) => x.startsWith(parameterName)).length; if (parameterValue === null) { return `${aliasPath} IS NULL`; } else if (parameterValue instanceof FindOperator) { let parameters: any[] = []; if (parameterValue.useParameter) { const realParameterValues: any[] = parameterValue.multipleParameters ? parameterValue.value : [parameterValue.value]; realParameterValues.forEach( (realParameterValue, realParameterValueIndex) => { qb.expressionMap.nativeParameters[ parameterName + (parameterBaseCount + realParameterValueIndex) ] = realParameterValue; parameterIndex++; parameters.push( qb.connection.driver.createParameter( parameterName + (parameterBaseCount + realParameterValueIndex), parameterIndex - 1 ) ); } ); } return parameterValue.toSql(qb.connection, aliasPath, parameters); } else { qb.expressionMap.nativeParameters[parameterName] = parameterValue; parameterIndex++; const parameter = qb.connection.driver.createParameter( parameterName, parameterIndex - 1 ); return `${aliasPath} = ${parameter}`; } }) .filter((expression) => !!expression) .join(' AND '); }) .filter((expression) => !!expression) .join(' AND '); }); if (andConditions.length > 1) return andConditions.map((where) => '(' + where + ')').join(' OR '); return andConditions.join(''); } return ''; } }