UNPKG

ts-sql-query

Version:

Type-safe SQL query builder like QueryDSL or JOOQ in Java or Linq in .Net for TypeScript with MariaDB, MySql, Oracle, PostgreSql, Sqlite and SqlServer support.

913 lines 66.4 kB
"use strict"; Object.defineProperty(exports, "__esModule", { value: true }); exports.SqlServerSqlBuilder = void 0; const SqlBuilder_1 = require("./SqlBuilder"); const TypeAdapter_1 = require("../TypeAdapter"); const values_1 = require("../expressions/values"); const AbstractSqlBuilder_1 = require("./AbstractSqlBuilder"); const Column_1 = require("../utils/Column"); const values_2 = require("../expressions/values"); const ITableOrView_1 = require("../utils/ITableOrView"); class SqlServerSqlBuilder extends AbstractSqlBuilder_1.AbstractSqlBuilder { constructor() { super(); this.sqlServer = true; this._trueValue = 'convert(bit, 1)'; this._falseValue = 'convert(bit, 0)'; this._trueValueForCondition = '(1=1)'; this._falseValueForCondition = '(0=1)'; this._nullValueForCondition = '(0=null)'; this._updateOldValueInFrom = false; this._useForJsonInAggreagteArrayWhenPossible = true; this._operationsThatNeedParenthesis._getMonth = true; this._operationsThatNeedParenthesis._getDay = true; } _appendRawColumnName(column, params) { const columnPrivate = (0, Column_1.__getColumnPrivate)(column); const tableOrView = columnPrivate.__tableOrView; if ((0, ITableOrView_1.__getTableOrViewPrivate)(tableOrView).__oldValues) { return 'deleted.' + this._escape(columnPrivate.__name, true); } return super._appendRawColumnName(column, params); } _forceAsIdentifier(identifier) { return '[' + identifier + ']'; } _isReservedKeyword(word) { return word.toUpperCase() in reservedWords; } _nextSequenceValue(_params, sequenceName) { return 'next value for ' + this._escape(sequenceName, false); } _currentSequenceValue(_params, sequenceName) { return "(select current_value from sys.sequences where name = '" + sequenceName + "')"; } _appendSql(value, params) { if ((0, values_1.isValueSource)(value) && !(0, Column_1.isColumn)(value)) { const valueSourcePrivate = (0, values_2.__getValueSourcePrivate)(value); if (valueSourcePrivate.__isBooleanForCondition) { if (valueSourcePrivate.__optionalType === 'required') { return 'cast(case when ' + this._appendConditionSql(value, params) + ' then 1 else 0 end as bit)'; } else { return 'cast(case when ' + this._appendConditionSql(value, params) + ' then 1 when not ' + this._appendConditionSqlParenthesis(value, params) + ' then 0 else null end as bit)'; } } } return super._appendSql(value, params); } _appendConditionSql(value, params) { if ((0, values_1.isValueSource)(value) && !(0, Column_1.isColumn)(value) && (0, SqlBuilder_1.hasToSql)(value)) { const valueSourcePrivate = (0, values_2.__getValueSourcePrivate)(value); if ((0, values_1.__isBooleanValueSource)(valueSourcePrivate) && !valueSourcePrivate.__isBooleanForCondition) { const sql = value.__toSqlForCondition(this, params); if (!sql || sql === this._trueValueForCondition || sql === this._falseValueForCondition) { return sql; } else { return '(' + sql + ' = 1)'; } } } return super._appendConditionSql(value, params); } _isUuid(value) { if ((0, values_1.isValueSource)(value)) { const valuePrivate = (0, values_2.__getValueSourcePrivate)(value); if ((0, values_1.__isUuidValueSource)(valuePrivate) || valuePrivate.__uuidString) { return true; } } return false; } _appendSqlMaybeUuid(value, params) { if (this._isUuid(value)) { return 'convert(nvarchar, ' + this._appendSql(value, params) + ')'; } else { return this._appendSql(value, params); } } _appendConditionParam(value, params, columnType, columnTypeName, typeAdapter, forceTypeCast) { if ((0, values_1.__isBooleanValueType)(columnType)) { if ((0, Column_1.isColumn)(value)) { const columnPrivate = (0, Column_1.__getColumnPrivate)(value); const typeAdapter = columnPrivate.__typeAdapter; if (typeAdapter instanceof TypeAdapter_1.CustomBooleanTypeAdapter) { return '(' + this._appendRawColumnName(value, params) + ' = ' + this._appendLiteralValue(typeAdapter.trueValue, params) + ')'; } } return '(' + this._appendParam(value, params, columnType, columnTypeName, typeAdapter, forceTypeCast) + ' = 1)'; } return this._appendParam(value, params, columnType, columnTypeName, typeAdapter, forceTypeCast); } _appendParam(value, params, columnType, columnTypeName, typeAdapter, forceTypeCast) { // keep the data type to use in the query runner Object.defineProperty(params, '@' + params.length, { value: columnType in nativeTypedValueType ? columnType : columnTypeName, writable: true, enumerable: false, configurable: true }); return super._appendParam(value, params, columnType, columnTypeName, typeAdapter, forceTypeCast); } _appendColumnName(column, params) { const columnPrivate = (0, Column_1.__getColumnPrivate)(column); const typeAdapter = columnPrivate.__typeAdapter; if ((0, values_1.__isBooleanValueSource)(columnPrivate)) { if (typeAdapter instanceof TypeAdapter_1.CustomBooleanTypeAdapter) { if (columnPrivate.__optionalType === 'required') { return 'cast(case when ' + this._appendRawColumnName(column, params) + ' = ' + this._appendLiteralValue(typeAdapter.trueValue, params) + ' then 1 else 0 end as bit)'; } else { return 'cast(case ' + this._appendRawColumnName(column, params) + ' when ' + this._appendLiteralValue(typeAdapter.trueValue, params) + ' then 1 when ' + this._appendLiteralValue(typeAdapter.falseValue, params) + ' then 0 else null end as bit)'; } } } return this._appendRawColumnName(column, params); } _appendColumnNameForCondition(column, params) { const columnPrivate = (0, Column_1.__getColumnPrivate)(column); const typeAdapter = columnPrivate.__typeAdapter; if ((0, values_1.__isBooleanValueSource)(columnPrivate)) { if (typeAdapter instanceof TypeAdapter_1.CustomBooleanTypeAdapter) { return '(' + this._appendRawColumnName(column, params) + ' = ' + this._appendLiteralValue(typeAdapter.trueValue, params) + ')'; } else { return '(' + this._appendRawColumnName(column, params) + ' = 1)'; } } return this._appendRawColumnName(column, params); } _inlineSelectAsValueForCondition(query, params) { if (query.__oneColumn) { const columns = query.__columns; for (const prop in columns) { const column = columns[prop]; if ((0, values_1.isValueSource)(column) && (0, values_1.__isBooleanValueSource)((0, values_2.__getValueSourcePrivate)(column))) { return '((' + this._buildInlineSelect(query, params) + ') = 1)'; } else { return this._buildInlineSelect(query, params); } } } return this._buildInlineSelect(query, params); } _appendWithKeyword(_recursive) { // Sql Server doesn't uses the recursive keyword return 'with'; } _buildWithValues(withValues, params) { let result = withValues.__name; result += ' as (select * from (values '; const values = withValues.__values; let valuesSql = ''; for (let i = 0, length = values.length; i < length; i++) { if (valuesSql) { valuesSql += ', '; } const value = values[i]; let valueSql = ''; for (var columnName in withValues) { const column = (0, Column_1.__getColumnOfObject)(withValues.__getTableOrView(), columnName); if (!column) { continue; } if (valueSql) { valueSql += ', '; } valueSql += this._appendValueForColumn(column, value[columnName], params); } valuesSql += '(' + valueSql + ')'; } result += valuesSql; result += ') as '; result += withValues.__name; let columns = ''; for (var columnName in withValues) { const column = (0, Column_1.__getColumnOfObject)(withValues.__getTableOrView(), columnName); if (!column) { continue; } if (columns) { columns += ', '; } const columnPrivate = (0, Column_1.__getColumnPrivate)(column); columns += this._appendColumnAlias(columnPrivate.__name, params); } result += '(' + columns + ')'; result += ')'; return result; } _buildSelectWithColumnsInfoForCompound(query, params, columnsForInsert, isOutermostQuery) { const result = this._buildSelectWithColumnsInfo(query, params, columnsForInsert, isOutermostQuery); if (query.__limit !== undefined || query.__offset !== undefined || query.__orderBy || query.__customization?.beforeOrderByItems || query.__customization?.afterOrderByItems) { return 'select * from (' + result + ') _t_' + this._generateUnique() + '_'; } return result; } _buildSelectOrderBy(query, params) { // How to index it: http://www.sqlines.com/oracle/function_based_indexes const orderBy = query.__orderBy; if (!orderBy) { let orderByColumns = ''; const customization = query.__customization; if (customization && customization.beforeOrderByItems) { orderByColumns += this._appendRawFragment(customization.beforeOrderByItems, params); } if (customization && customization.afterOrderByItems) { if (orderByColumns) { orderByColumns += ', '; } orderByColumns += this._appendRawFragment(customization.afterOrderByItems, params); } if (orderByColumns) { return ' order by ' + orderByColumns; } const limit = query.__limit; const offset = query.__offset; if ((offset !== null && offset !== undefined) || (limit !== null && limit !== undefined)) { // Add fake order by to allow a limit and offset without order by const columns = {}; (0, SqlBuilder_1.flattenQueryColumns)(query.__columns, columns, ''); let index = 0; for (const property in columns) { index++; const column = columns[property]; if ((0, Column_1.isColumn)(column)) { if ((0, Column_1.__getColumnPrivate)(column).__isPrimaryKey) { return ' order by ' + index; } } } return ' order by 1'; } else { return ''; } } let orderByColumns = ''; const customization = query.__customization; if (customization && customization.beforeOrderByItems) { orderByColumns += this._appendRawFragment(customization.beforeOrderByItems, params); } for (const entry of orderBy) { if (orderByColumns) { orderByColumns += ', '; } const order = entry.order; if (!order) { orderByColumns += this._appendOrderByColumnAlias(entry, query, params); } else switch (order) { case 'asc': case 'asc nulls first': orderByColumns += this._appendOrderByColumnAlias(entry, query, params) + ' asc'; break; case 'desc': case 'desc nulls last': orderByColumns += this._appendOrderByColumnAlias(entry, query, params) + ' desc'; break; case 'asc nulls last': orderByColumns += 'iif(' + this._appendOrderByColumnAlias(entry, query, params) + ' is null, 1, 0), ' + this._appendOrderByColumnAlias(entry, query, params) + ' asc'; break; case 'desc nulls first': orderByColumns += 'iif(' + this._appendOrderByColumnAlias(entry, query, params) + ' is not null, 1, 0), ' + this._appendOrderByColumnAlias(entry, query, params) + ' desc'; break; case 'insensitive': orderByColumns += this._appendOrderByColumnAliasInsensitive(entry, query, params); break; case 'asc insensitive': case 'asc nulls first insensitive': orderByColumns += this._appendOrderByColumnAliasInsensitive(entry, query, params) + ' asc'; break; case 'desc insensitive': case 'desc nulls last insensitive': orderByColumns += this._appendOrderByColumnAliasInsensitive(entry, query, params) + ' desc'; break; case 'asc nulls last insensitive': orderByColumns += 'iif(' + this._appendOrderByColumnAlias(entry, query, params) + ' is null, 1, 0), ' + this._appendOrderByColumnAliasInsensitive(entry, query, params) + ' asc'; break; case 'desc nulls first insensitive': orderByColumns += 'iif(' + this._appendOrderByColumnAlias(entry, query, params) + ' is not null, 1, 0), ' + this._appendOrderByColumnAliasInsensitive(entry, query, params) + ' desc'; break; default: throw new Error('Invalid order by: ' + order); } } if (customization && customization.afterOrderByItems) { if (orderByColumns) { orderByColumns += ', '; } orderByColumns += this._appendRawFragment(customization.afterOrderByItems, params); } if (!orderByColumns) { return ''; } return ' order by ' + orderByColumns; } _buildSelectLimitOffset(query, params) { let result = ''; const limit = query.__limit; const offset = query.__offset; if (offset !== null && offset !== undefined) { result += ' offset ' + this._appendValue(offset, params, 'int', 'int', undefined) + ' rows'; } if (limit !== null && limit !== undefined) { if (!result) { result += ' offset 0 rows'; } result += ' fetch next ' + this._appendValue(limit, params, 'int', 'int', undefined) + ' rows only'; } if (!result && (query.__orderBy || query.__customization?.beforeOrderByItems || query.__customization?.afterOrderByItems) && !this._isCurrentRootQuery(query, params)) { // subqueries with order by requires always an offset, this add a noop offset result += ' offset 0 rows'; } return result; } _buildInsertOutput(query, params) { const idColumn = query.__idColumn; if (idColumn) { this._setContainsInsertReturningClause(params, true); return ' output inserted.' + this._appendSql(idColumn, params); } const result = this._buildQueryOutput(query.__columns, query.__table, 'inserted', params); this._setContainsInsertReturningClause(params, !!result); return result; } _buildInsertReturning(_query, _params) { return ''; } _buildUpdateOutput(query, params) { return this._buildQueryOutput(query.__columns, query.__table, 'inserted', params); } _buildUpdateReturning(_query, _params) { return ''; } _buidDeleteUsing(query, params) { const result = this._buildFromJoins(query.__using, query.__joins, undefined, params); if (result) { return ' from ' + result; } return ''; } _buildDeleteOutput(query, params) { return this._buildQueryOutput(query.__columns, query.__table, 'deleted', params); } _buildQueryOutput(queryColumns, table, alias, params) { if (!queryColumns) { return ''; } const columns = {}; (0, SqlBuilder_1.flattenQueryColumns)(queryColumns, columns, ''); const oldForceAliasFor = this._getForceAliasFor(params); const oldForceAliasAs = this._getForceAliasAs(params); this._setForceAliasFor(params, table); this._setForceAliasAs(params, alias); let requireComma = false; let result = ''; for (const property in columns) { if (requireComma) { result += ', '; } result += this._appendSql(columns[property], params); if (property) { result += ' as ' + this._appendColumnAlias(property, params); } requireComma = true; } this._setForceAliasFor(params, oldForceAliasFor); this._setForceAliasAs(params, oldForceAliasAs); if (!result) { return ''; } return ' output ' + result; } _buildDeleteReturning(_query, _params) { return ''; } _isNullValue(value) { if (value === null || value === undefined) { return true; } if (!(0, values_1.isValueSource)(value)) { return false; } const valueSourcePrivate = (0, values_2.__getValueSourcePrivate)(value); if (valueSourcePrivate.isConstValue()) { const valueSourceValue = valueSourcePrivate.getConstValue(); if (valueSourceValue === null || valueSourceValue === undefined) { return true; } } return false; } _isOptionalValue(value) { if (value === null || value === undefined) { return true; } if (!(0, values_1.isValueSource)(value)) { return false; } const valueSourcePrivate = (0, values_2.__getValueSourcePrivate)(value); if (valueSourcePrivate.isConstValue()) { const valueSourceValue = valueSourcePrivate.getConstValue(); if (valueSourceValue === null || valueSourceValue === undefined) { return true; } } return valueSourcePrivate.__optionalType !== 'required'; } _isNull(params, valueSource) { if ((0, Column_1.isColumn)(valueSource)) { return this._appendRawColumnName(valueSource, params) + ' is null'; } else if ((0, values_1.isValueSource)(valueSource)) { const valueSourcePrivate = (0, values_2.__getValueSourcePrivate)(valueSource); if (valueSourcePrivate.__isBooleanForCondition) { if (valueSourcePrivate.__optionalType === 'required') { return this._falseValueForCondition; } else { // This is a boolean value (0 or 1 from a column) that need to be use in a boolean expression return '(case when ' + this._appendConditionSql(valueSource, params) + ' then 0 when not ' + this._appendConditionSqlParenthesis(valueSource, params) + ' then 0 else 1 end = 1)'; } } } return this._appendSqlParenthesis(valueSource, params) + ' is null'; } _generalIsNull(params, value, columnType, columnTypeName, typeAdapter) { if ((0, SqlBuilder_1.hasToSql)(value)) { return this._isNull(params, value); } return this._appendValueParenthesis(value, params, columnType, columnTypeName, typeAdapter) + ' is null'; } _isNotNull(params, valueSource) { if ((0, Column_1.isColumn)(valueSource)) { this._appendRawColumnName(valueSource, params) + ' is not null'; } if ((0, values_1.isValueSource)(valueSource)) { const valueSourcePrivate = (0, values_2.__getValueSourcePrivate)(valueSource); if (valueSourcePrivate.__isBooleanForCondition) { if (valueSourcePrivate.__optionalType === 'required') { return this._trueValueForCondition; } else { // This is a boolean value (0 or 1 from a column) that need to be use in a boolean expression return '(case when ' + this._appendConditionSql(valueSource, params) + ' then 1 when not ' + this._appendConditionSqlParenthesis(valueSource, params) + ' then 1 else 0 end = 1)'; } } } return this._appendSqlParenthesis(valueSource, params) + ' is not null'; } _generalIsNotNull(params, value, columnType, columnTypeName, typeAdapter) { if ((0, SqlBuilder_1.hasToSql)(value)) { return this._isNotNull(params, value); } return this._appendValueParenthesis(value, params, columnType, columnTypeName, typeAdapter) + ' is not null'; } _is(params, valueSource, value, columnType, columnTypeName, typeAdapter) { const valueIsNull = this._isNullValue(value); const valueSourceIsNull = this._isNullValue(valueSource); const valueIsOptional = this._isOptionalValue(value); const valueSourceIsOptional = this._isOptionalValue(valueSource); if (valueIsNull) { return this._isNull(params, valueSource); } if (valueSourceIsNull) { // We know value is null or undefined, then, whe need to ensure the value source is null as well return this._generalIsNull(params, value, columnType, columnTypeName, typeAdapter); } if (valueSourceIsOptional && valueIsOptional) { return 'case when (' + this._equals(params, valueSource, value, columnType, columnTypeName, typeAdapter) + ') or (' + this._isNull(params, valueSource) + ' and ' + this._generalIsNull(params, value, columnType, columnTypeName, typeAdapter) + ') then 1 else 0 end = 1'; } else if (valueSourceIsOptional || valueIsOptional) { return 'case when ' + this._equals(params, valueSource, value, columnType, columnTypeName, typeAdapter) + ' then 1 else 0 end = 1'; } else { return this._equals(params, valueSource, value, columnType, columnTypeName, typeAdapter); } // Alternative implementation that avoid evaluate multiple times the arguments // return 'exists(select ' + this._appendSqlParenthesis(valueSource, params) + ' intersect select ' + this._appendValueParenthesis(value, params, columnTypeName, typeAdapter) + ')' } _isNot(params, valueSource, value, columnType, columnTypeName, typeAdapter) { const valueIsNull = this._isNullValue(value); const valueSourceIsNull = this._isNullValue(valueSource); const valueIsOptional = this._isOptionalValue(value); const valueSourceIsOptional = this._isOptionalValue(valueSource); if (valueIsNull) { return this._isNotNull(params, valueSource); } if (valueSourceIsNull) { // We know value is null or undefined, then, whe need to ensure the value source is null as well return this._generalIsNotNull(params, value, columnType, columnTypeName, typeAdapter); } if (valueSourceIsOptional && valueIsOptional) { return 'not (case when (' + this._equals(params, valueSource, value, columnType, columnTypeName, typeAdapter) + ') or (' + this._isNull(params, valueSource) + ' and ' + this._generalIsNull(params, value, columnType, columnTypeName, typeAdapter) + ') then 1 else 0 end = 1)'; } else if (valueSourceIsOptional || valueIsOptional) { return 'not (case when ' + this._equals(params, valueSource, value, columnType, columnTypeName, typeAdapter) + ' then 1 else 0 end = 1)'; } else { return this._notEquals(params, valueSource, value, columnType, columnTypeName, typeAdapter); } // Alternative implementation that avoid evaluate multiple times the arguments // return 'not exists(select ' + this._appendSqlParenthesis(valueSource, params) + ' intersect select ' + this._appendValueParenthesis(value, params, columnTypeName, typeAdapter) + ')' } _valueWhenNull(params, valueSource, value, columnType, columnTypeName, typeAdapter) { let result = 'isnull('; if ((0, values_1.isValueSource)(valueSource) && (0, values_2.__getValueSourcePrivate)(valueSource).__uuidString) { result += 'convert(nvarchar, ' + this._appendSql(valueSource, params) + ')'; } else { result += this._appendSql(valueSource, params); } result += ', '; if ((0, values_1.isValueSource)(value) && (0, values_2.__getValueSourcePrivate)(value).__uuidString) { result += 'convert(nvarchar, ' + this._appendValue(value, params, columnType, columnTypeName, typeAdapter) + ')'; } else { result += this._appendValue(value, params, columnType, columnTypeName, typeAdapter); } result += ')'; return result; } _escapeLikeWildcard(params, value, columnType, columnTypeName, typeAdapter) { if (typeof value === 'string') { value = value.replace(/\[/g, '[[]'); value = value.replace(/%/g, '[%]'); value = value.replace(/_/g, '[]'); return this._appendValue(value, params, columnType, columnTypeName, typeAdapter); } else { return "replace(replace(replace(" + this._appendValue(value, params, columnType, columnTypeName, typeAdapter) + ", '[', '[[]'), '%', '[%]'), '_', '[]')"; } } _startsWith(params, valueSource, value, columnType, columnTypeName, typeAdapter) { return this._appendSqlParenthesis(valueSource, params) + ' like (' + this._escapeLikeWildcard(params, value, columnType, columnTypeName, typeAdapter) + " + '%')"; } _notStartsWith(params, valueSource, value, columnType, columnTypeName, typeAdapter) { return this._appendSqlParenthesis(valueSource, params) + ' not like (' + this._escapeLikeWildcard(params, value, columnType, columnTypeName, typeAdapter) + " + '%')"; } _endsWith(params, valueSource, value, columnType, columnTypeName, typeAdapter) { return this._appendSqlParenthesis(valueSource, params) + " like ('%' + " + this._escapeLikeWildcard(params, value, columnType, columnTypeName, typeAdapter) + ')'; } _notEndsWith(params, valueSource, value, columnType, columnTypeName, typeAdapter) { return this._appendSqlParenthesis(valueSource, params) + " not like ('%' + " + this._escapeLikeWildcard(params, value, columnType, columnTypeName, typeAdapter) + ')'; } _startsWithInsensitive(params, valueSource, value, columnType, columnTypeName, typeAdapter) { if (this._isUuid(valueSource)) { return this._appendSqlParenthesis(valueSource, params) + ' like (' + this._escapeLikeWildcard(params, value, columnType, columnTypeName, typeAdapter) + " + '%')"; } const collation = this._connectionConfiguration.insesitiveCollation; if (collation) { return this._appendSqlParenthesis(valueSource, params) + ' like (' + this._escapeLikeWildcard(params, value, columnType, columnTypeName, typeAdapter) + " + '%') collate " + collation; } else if (collation === '') { return this._appendSqlParenthesis(valueSource, params) + ' like (' + this._escapeLikeWildcard(params, value, columnType, columnTypeName, typeAdapter) + " + '%')"; } else { return 'lower(' + this._appendSql(valueSource, params) + ') like lower(' + this._escapeLikeWildcard(params, value, columnType, columnTypeName, typeAdapter) + " + '%')"; } } _notStartsWithInsensitive(params, valueSource, value, columnType, columnTypeName, typeAdapter) { if (this._isUuid(valueSource)) { return this._appendSqlParenthesis(valueSource, params) + ' not like (' + this._escapeLikeWildcard(params, value, columnType, columnTypeName, typeAdapter) + " + '%')"; } const collation = this._connectionConfiguration.insesitiveCollation; if (collation) { return this._appendSqlParenthesis(valueSource, params) + ' not like (' + this._escapeLikeWildcard(params, value, columnType, columnTypeName, typeAdapter) + " + '%') collate " + collation; } else if (collation === '') { return this._appendSqlParenthesis(valueSource, params) + ' not like (' + this._escapeLikeWildcard(params, value, columnType, columnTypeName, typeAdapter) + " + '%')"; } else { return 'lower(' + this._appendSql(valueSource, params) + ') not like lower(' + this._escapeLikeWildcard(params, value, columnType, columnTypeName, typeAdapter) + " + '%')"; } } _endsWithInsensitive(params, valueSource, value, columnType, columnTypeName, typeAdapter) { if (this._isUuid(valueSource)) { return this._appendSqlParenthesis(valueSource, params) + " like ('%' + " + this._escapeLikeWildcard(params, value, columnType, columnTypeName, typeAdapter) + ')'; } const collation = this._connectionConfiguration.insesitiveCollation; if (collation) { return this._appendSqlParenthesis(valueSource, params) + " like ('%' + " + this._escapeLikeWildcard(params, value, columnType, columnTypeName, typeAdapter) + ') collate ' + collation; } else if (collation === '') { return this._appendSqlParenthesis(valueSource, params) + " like ('%' + " + this._escapeLikeWildcard(params, value, columnType, columnTypeName, typeAdapter) + ')'; } else { return 'lower(' + this._appendSql(valueSource, params) + ") like lower('%' + " + this._escapeLikeWildcard(params, value, columnType, columnTypeName, typeAdapter) + ')'; } } _notEndsWithInsensitive(params, valueSource, value, columnType, columnTypeName, typeAdapter) { if (this._isUuid(valueSource)) { return this._appendSqlParenthesis(valueSource, params) + " not like ('%' + " + this._escapeLikeWildcard(params, value, columnType, columnTypeName, typeAdapter) + ')'; } const collation = this._connectionConfiguration.insesitiveCollation; if (collation) { return this._appendSqlParenthesis(valueSource, params) + " not like ('%' + " + this._escapeLikeWildcard(params, value, columnType, columnTypeName, typeAdapter) + ') collate ' + collation; } else if (collation === '') { return this._appendSqlParenthesis(valueSource, params) + " not like ('%' + " + this._escapeLikeWildcard(params, value, columnType, columnTypeName, typeAdapter) + ')'; } else { return 'lower(' + this._appendSql(valueSource, params) + ") not like lower('%' + " + this._escapeLikeWildcard(params, value, columnType, columnTypeName, typeAdapter) + ')'; } } _contains(params, valueSource, value, columnType, columnTypeName, typeAdapter) { return this._appendSqlParenthesis(valueSource, params) + " like ('%' + " + this._escapeLikeWildcard(params, value, columnType, columnTypeName, typeAdapter) + " + '%')"; } _notContains(params, valueSource, value, columnType, columnTypeName, typeAdapter) { return this._appendSqlParenthesis(valueSource, params) + " not like ('%' + " + this._escapeLikeWildcard(params, value, columnType, columnTypeName, typeAdapter) + " + '%')"; } _containsInsensitive(params, valueSource, value, columnType, columnTypeName, typeAdapter) { if (this._isUuid(valueSource)) { return this._appendSqlParenthesis(valueSource, params) + " like ('%' + " + this._escapeLikeWildcard(params, value, columnType, columnTypeName, typeAdapter) + " + '%')"; } const collation = this._connectionConfiguration.insesitiveCollation; if (collation) { return this._appendSqlParenthesis(valueSource, params) + " like ('%' + " + this._escapeLikeWildcard(params, value, columnType, columnTypeName, typeAdapter) + " + '%') collate " + collation; } else if (collation === '') { return this._appendSqlParenthesis(valueSource, params) + " like ('%' + " + this._escapeLikeWildcard(params, value, columnType, columnTypeName, typeAdapter) + " + '%')"; } else { return 'lower(' + this._appendSql(valueSource, params) + ") like lower('%' + " + this._escapeLikeWildcard(params, value, columnType, columnTypeName, typeAdapter) + " + '%')"; } } _notContainsInsensitive(params, valueSource, value, columnType, columnTypeName, typeAdapter) { if (this._isUuid(valueSource)) { return this._appendSqlParenthesis(valueSource, params) + " not like ('%' + " + this._escapeLikeWildcard(params, value, columnType, columnTypeName, typeAdapter) + " + '%')"; } const collation = this._connectionConfiguration.insesitiveCollation; if (collation) { return this._appendSqlParenthesis(valueSource, params) + " not like ('%' + " + this._escapeLikeWildcard(params, value, columnType, columnTypeName, typeAdapter) + " + '%') collate " + collation; } else if (collation === '') { return this._appendSqlParenthesis(valueSource, params) + " not like ('%' + " + this._escapeLikeWildcard(params, value, columnType, columnTypeName, typeAdapter) + " + '%')"; } else { return 'lower(' + this._appendSql(valueSource, params) + ") not like lower('%' + " + this._escapeLikeWildcard(params, value, columnType, columnTypeName, typeAdapter) + " + '%')"; } } _trim(params, valueSource) { return 'trim(' + this._appendSqlMaybeUuid(valueSource, params) + ')'; } _trimLeft(params, valueSource) { return 'ltrim(' + this._appendSqlMaybeUuid(valueSource, params) + ')'; } _trimRight(params, valueSource) { return 'rtrim(' + this._appendSqlMaybeUuid(valueSource, params) + ')'; } _currentDate() { return 'getdate()'; } _currentTime() { return 'convert(time, current_timestamp)'; } _random() { return 'rand()'; } _divide(params, valueSource, value, columnType, columnTypeName, typeAdapter) { return 'cast(' + this._appendSql(valueSource, params) + ' as float) / cast(' + this._appendValue(value, params, this._getMathArgumentType(columnType, columnTypeName, value), this._getMathArgumentTypeName(columnType, columnTypeName, value), typeAdapter) + ' as float)'; } _asDouble(params, valueSource) { return 'cast(' + this._appendSql(valueSource, params) + 'as float)'; } _concat(params, valueSource, value, columnType, columnTypeName, typeAdapter) { let result = ''; if (this._isUuid(valueSource)) { result += 'convert(nvarchar, ' + this._appendSql(valueSource, params) + ')'; } else { result += this._appendSqlParenthesisExcluding(valueSource, params, '_concat'); } result += ' + '; if (this._isUuid(value)) { result += 'convert(nvarchar, ' + this._appendValue(value, params, columnType, columnTypeName, typeAdapter) + ')'; } else { result += this._appendValueParenthesisExcluding(value, params, columnType, columnTypeName, typeAdapter, '_concat'); } return result; } _length(params, valueSource) { return 'len(' + valueSource.__toSql(this, params) + ')'; } _ln(params, valueSource) { return 'log(' + valueSource.__toSql(this, params) + ')'; } _log10(params, valueSource) { return 'log10(' + valueSource.__toSql(this, params) + ')'; } _cbrt(params, valueSource) { return 'power(' + valueSource.__toSql(this, params) + ', 3)'; } _atan2(params, valueSource, value, columnType, columnTypeName, typeAdapter) { return 'atn2(' + valueSource.__toSql(this, params) + ', ' + this._appendValue(value, params, this._getMathArgumentType(columnType, columnTypeName, value), this._getMathArgumentTypeName(columnType, columnTypeName, value), typeAdapter) + ')'; } _minimumBetweenTwoValues(params, valueSource, value, columnType, columnTypeName, typeAdapter) { const argumentType = this._getMathArgumentType(columnType, columnTypeName, value); const argumentTypeName = this._getMathArgumentTypeName(columnType, columnTypeName, value); return 'iif(' + this._appendSql(valueSource, params) + ' < ' + this._appendValue(value, params, argumentType, argumentTypeName, typeAdapter) + ', ' + this._appendSql(valueSource, params) + ', ' + this._appendValue(value, params, argumentType, argumentTypeName, typeAdapter) + ')'; // Alternative implementation that avoid evaluate multiple times the arguments // if (isColumn(valueSource) || !isValueSource(valueSource) || valueSource.isConstValue()) { // if (isColumn(value) || !isValueSource(value) || value.isConstValue()) { // // Both values are repeteables, then, we can use the sql that compare both values repeting them // return 'iif(' + this._appendSql(valueSource, params) + ' < ' + this._appendValue(value, params, argumentType, argumentTypeName, typeAdapter) + ', ' + this._appendSql(valueSource, params) + ', ' + this._appendValue(value, params, argumentType, argumentTypeName, typeAdapter) + ')' // } // } // return '(select min(__minValue__) from (values (' + this._appendSql(valueSource, params) + '), (' + this._appendSql(valueSource, params) + ')) as __minValueTable__(__minValue__))' } _maximumBetweenTwoValues(params, valueSource, value, columnType, columnTypeName, typeAdapter) { const argumentType = this._getMathArgumentType(columnType, columnTypeName, value); const argumentTypeName = this._getMathArgumentTypeName(columnType, columnTypeName, value); return 'iif(' + this._appendSql(valueSource, params) + ' > ' + this._appendValue(value, params, argumentType, argumentTypeName, typeAdapter) + ', ' + this._appendSql(valueSource, params) + ', ' + this._appendValue(value, params, argumentType, argumentTypeName, typeAdapter) + ')'; // Alternative implementation that avoid evaluate multiple times the arguments // if (isColumn(valueSource) || !isValueSource(valueSource) || valueSource.getConstValue()) { // if (isColumn(value) || !isValueSource(value) || value.isConstValue()) { // // Both values are repeteables, then, we can use the sql that compare both values repeting them // return 'iif(' + this._appendSql(valueSource, params) + ' > ' + this._appendValue(value, params, argumentType, argumentTypeName, typeAdapter) + ', ' + this._appendSql(valueSource, params) + ', ' + this._appendValue(value, params, argumentType, argumentTypeName, typeAdapter) + ')' // } // } // return '(select max(__maxValue__) from (values (' + this._appendSql(valueSource, params) + '), (' + this._appendSql(valueSource, params) + ')) as __maxValueTable__(__maxValue__))' } _getDate(params, valueSource) { return 'datepart(day, ' + this._appendSql(valueSource, params) + ')'; } _getTime(params, valueSource) { return "datediff_big(millisecond, '1970-01-01 00:00:00', " + this._appendSql(valueSource, params) + ")"; } _getFullYear(params, valueSource) { return 'datepart(year, ' + this._appendSql(valueSource, params) + ')'; } _getMonth(params, valueSource) { return 'datepart(month, ' + this._appendSql(valueSource, params) + ') - 1'; } _getDay(params, valueSource) { return 'datepart(weekday, ' + this._appendSql(valueSource, params) + ') - 1'; } _getHours(params, valueSource) { return 'datepart(hour, ' + this._appendSql(valueSource, params) + ')'; } _getMinutes(params, valueSource) { return 'datepart(minute, ' + this._appendSql(valueSource, params) + ')'; } _getSeconds(params, valueSource) { return 'datepart(second, ' + this._appendSql(valueSource, params) + ')'; } _getMilliseconds(params, valueSource) { return 'datepart(millisecond, ' + this._appendSql(valueSource, params) + ')'; } _buildCallProcedure(params, functionName, functionParams) { let result = 'exec ' + this._escape(functionName, false); for (let i = 0, length = functionParams.length; i < length; i++) { result += ' ' + this._appendSql(functionParams[i], params); } return result; } _stringConcat(params, separator, value) { if (separator === undefined || separator === null) { return 'string_agg(' + this._appendSqlMaybeUuid(value, params) + ", ',')"; } else if (separator === '') { return 'string_agg(' + this._appendSqlMaybeUuid(value, params) + ", '')"; } else { return 'string_agg(' + this._appendSqlMaybeUuid(value, params) + ', ' + this._appendValue(separator, params, 'string', 'string', undefined) + ')'; } } _stringConcatDistinct(params, separator, value) { if (separator === undefined || separator === null) { return 'string_agg(distinct ' + this._appendSqlMaybeUuid(value, params) + ", ',')"; } else if (separator === '') { return 'string_agg(distinct ' + this._appendSqlMaybeUuid(value, params) + ", '')"; } else { return 'string_agg(distinct ' + this._appendSqlMaybeUuid(value, params) + ', ' + this._appendValue(separator, params, 'string', 'string', undefined) + ')'; } } _in(params, valueSource, value, columnType, columnTypeName, typeAdapter) { if (Array.isArray(value) && value.length <= 0) { return this._falseValueForCondition; } return super._in(params, valueSource, value, columnType, columnTypeName, typeAdapter); } _notIn(params, valueSource, value, columnType, columnTypeName, typeAdapter) { if (Array.isArray(value) && value.length <= 0) { return this._trueValueForCondition; } return super._notIn(params, valueSource, value, columnType, columnTypeName, typeAdapter); } _substrToEnd(params, valueSource, value, _columnType, _columnTypeName, typeAdapter) { if (typeof value === 'number') { return 'substring(' + this._appendSqlMaybeUuid(valueSource, params) + ', ' + this._appendValue(value + 1, params, 'int', 'int', typeAdapter) + ', len(' + this._appendSql(valueSource, params) + ') - ' + this._appendValue(value, params, 'int', 'int', typeAdapter) + ')'; } else { return 'substring(' + this._appendSqlMaybeUuid(valueSource, params) + ', ' + this._appendValueParenthesis(value, params, 'int', 'int', typeAdapter) + ' + 1, len(' + this._appendSql(valueSource, params) + ') - ' + this._appendValue(value, params, 'int', 'int', typeAdapter) + ')'; } } _substringToEnd(params, valueSource, value, _columnType, _columnTypeName, typeAdapter) { if (typeof value === 'number') { return 'substring(' + this._appendSqlMaybeUuid(valueSource, params) + ', ' + this._appendValue(value + 1, params, 'int', 'int', typeAdapter) + ', len(' + this._appendSql(valueSource, params) + ') - ' + this._appendValue(value, params, 'int', 'int', typeAdapter) + ')'; } else { return 'substring(' + this._appendSqlMaybeUuid(valueSource, params) + ', ' + this._appendValueParenthesis(value, params, 'int', 'int', typeAdapter) + ' + 1, len(' + this._appendSql(valueSource, params) + ') - ' + this._appendValue(value, params, 'int', 'int', typeAdapter) + ')'; } } _substr(params, valueSource, value, value2, _columnType, _columnTypeName, typeAdapter) { if (typeof value === 'number') { return 'substring(' + this._appendSqlMaybeUuid(valueSource, params) + ', ' + this._appendValue(value + 1, params, 'int', 'int', typeAdapter) + ', ' + this._appendValue(value2, params, 'int', 'int', typeAdapter) + ')'; } else { return 'substring(' + this._appendSqlMaybeUuid(valueSource, params) + ', ' + this._appendValueParenthesis(value, params, 'int', 'int', typeAdapter) + ' + 1, ' + this._appendValue(value2, params, 'int', 'int', typeAdapter) + ')'; } } _substring(params, valueSource, value, value2, _columnType, _columnTypeName, typeAdapter) { if (typeof value === 'number' && typeof value2 === 'number') { const count = value2 - value; return 'substring(' + this._appendSqlMaybeUuid(valueSource, params) + ', ' + this._appendValue(value + 1, params, 'int', 'int', typeAdapter) + ', ' + this._appendValue(count, params, 'int', 'int', typeAdapter) + ')'; } if (typeof value === 'number') { return 'substring(' + this._appendSqlMaybeUuid(valueSource, params) + ', ' + this._appendValue(value + 1, params, 'int', 'int', typeAdapter) + ', ' + this._appendValue(value2, params, 'int', 'int', typeAdapter) + ' - ' + this._appendValue(value, params, 'int', 'int', typeAdapter) + ')'; } else { return 'substring(' + this._appendSqlMaybeUuid(valueSource, params) + ', ' + this._appendValueParenthesis(value, params, 'int', 'int', typeAdapter) + ' + 1, ' + this._appendValue(value2, params, 'int', 'int', typeAdapter) + ' - ' + this._appendValue(value, params, 'int', 'int', typeAdapter) + ')'; } } _buildSelectAsAggregatedArray(query, _params) { if (this._useForJsonInAggreagteArrayWhenPossible && query.__asInlineAggregatedArrayValue && !query.__oneColumn && query.__type === 'plain') { return ' for json path'; } return ''; } _needAgggregateArrayColumnsTransformation(query, _params) { if (!query.__asInlineAggregatedArrayValue) { return false; } if (!this._useForJsonInAggreagteArrayWhenPossible) { return true; } if (query.__oneColumn) { return true; } return false; } _needAgggregateArrayWrapper(query, params) { if (this._useForJsonInAggreagteArrayWhenPossible && query.__asInlineAggregatedArrayValue && !query.__oneColumn && query.__type === 'plain') { return false; } return super._needAgggregateArrayWrapper(query, params); } _appendAggragateArrayWrapperBegin(query, params, aggregateId) { if (this._useForJsonInAggreagteArrayWhenPossible && query.__type === 'compound' && !query.__oneColumn) { const columns = query.__columns; let requireComma = false; let result = ''; for (const property in columns) { if (requireComma) { result += ', '; } result += 'a_' + aggregateId + '_.' + this._escape(property, true); if (property) { result += ' as ' + this._appendColumnAlias(property, params); } requireComma = true; } return 'select ' + result + ' from ('; } return super._appendAggragateArrayWrapperBegin(query, params, aggregateId); } _appendAggragateArrayWrapperEnd(query, params, aggregateId) { if (this._useForJsonInAggreagteArrayWhenPossible && query.__type === 'compound' && !query.__oneColumn) { let result = ')'; if (this._supportTableAliasWithAs) { result += ' as '; } else { result += ' '; } result += 'a_' + aggregateId + '_ for json path'; return result; } return super._appendAggragateArrayWrapperEnd(query, params, aggregateId); } _appendAggragateArrayColumns(aggregatedArrayColumns, aggregatedArrayDistinct, params, _query) { const distict = aggregatedArrayDistinct ? 'distinct ' : ''; if ((0, values_1.isValueSource)(aggregatedArrayColumns)) { return "concat('[', string_agg(" + distict + this._appendJsonValueForAggregate(aggregatedArrayColumns, params) + ", ','), ']')"; } else { const columns = {}; (0, SqlBuilder_1.flattenQueryColumns)(aggregatedArrayColumns, columns, ''); let result = ''; for (let prop in columns) { if (result) { result += `, ', "` + prop + `": ', ` + this._appendJsonValueForAggregate(columns[prop], params); } else { result += `'