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.

1,199 lines 139 kB
"use strict"; Object.defineProperty(exports, "__esModule", { value: true }); exports.AbstractSqlBuilder = void 0; const SqlBuilder_1 = require("./SqlBuilder"); const ITableOrView_1 = require("../utils/ITableOrView"); const values_1 = require("../expressions/values"); const Column_1 = require("../utils/Column"); const TypeAdapter_1 = require("../TypeAdapter"); const ValueSourceImpl_1 = require("../internal/ValueSourceImpl"); const SqlBuilder_2 = require("./SqlBuilder"); const ITableOrView_2 = require("../utils/ITableOrView"); const Column_2 = require("../utils/Column"); const SqlBuilder_3 = require("./SqlBuilder"); const values_2 = require("../expressions/values"); class AbstractSqlBuilder { constructor() { this._unique = 1; this._supportTableAliasWithAs = true; this._insertSupportWith = true; this._updateNewAlias = '_new_'; this._updateOldValueInFrom = true; this._trueValue = 'true'; this._trueValueForCondition = 'true'; this._falseValue = 'false'; this._falseValueForCondition = 'false'; this._supportOrderByWhenAggregateArray = false; this._supportLimitWhenAggregateArray = false; this._operationsThatNeedParenthesis = { _equals: true, _notEquals: true, _is: true, _isNot: true, _equalsInsensitive: true, _notEqualsInsensitive: true, _lessThan: true, _greaterThan: true, _lessOrEquals: true, _greaterOrEquals: true, _and: true, _or: true, _concat: true, _add: true, _substract: true, _multiply: true, _divide: true, _modulo: true, _fragment: true }; } _generateUnique() { return this._unique++; } _resetUnique() { this._unique = 1; } _getSafeTableOrView(params) { return params._safeTableOrView; } _setSafeTableOrView(params, tableOrView) { Object.defineProperty(params, '_safeTableOrView', { value: tableOrView, writable: true, enumerable: false, configurable: true }); } _getForceAliasAs(params) { return params._forceAliasAs; } _setForceAliasAs(params, value) { Object.defineProperty(params, '_forceAliasAs', { value: value, writable: true, enumerable: false, configurable: true }); } _getForceAliasFor(params) { return params._forceAliasFor; } _setForceAliasFor(params, value) { Object.defineProperty(params, '_forceAliasFor', { value: value, writable: true, enumerable: false, configurable: true }); } _getFakeNamesOf(params) { return params._fakeNamesOf; } _setFakeNamesOf(params, value) { Object.defineProperty(params, '_fakeNamesOf', { value: value, writable: true, enumerable: false, configurable: true }); } _generateExternalWith(params) { return !!params._generateExternalWith; } _setGenerateExternalWith(params, value) { Object.defineProperty(params, '_generateExternalWith', { value: value, writable: true, enumerable: false, configurable: true }); } _isWithGenerated(params) { return !!params._withGenerated; } _setWithGenerated(params, value) { Object.defineProperty(params, '_withGenerated', { value: value, writable: true, enumerable: false, configurable: true }); } _isWithGeneratedFinished(params) { return !!params._withGeneratedFinished; } _setWithGeneratedFinished(params, value) { Object.defineProperty(params, '_withGeneratedFinished', { value: value, writable: true, enumerable: false, configurable: true }); } _isAggregateArrayWrapped(params) { return !!params._isAggregateArrayWrapped; } _setAggregateArrayWrapped(params, value) { Object.defineProperty(params, '_isAggregateArrayWrapped', { value: value, writable: true, enumerable: false, configurable: true }); } _getResultingOperation(params) { return params._resultingOperation; } _setResultingOperation(params, value) { Object.defineProperty(params, '_resultingOperation', { value: value, writable: true, enumerable: false, configurable: true }); } // Read in the query runner _getContainsInsertReturningClause(params) { return params._containsInsertReturningClause; } _setContainsInsertReturningClause(params, value) { Object.defineProperty(params, '_containsInsertReturningClause', { value: value, writable: true, enumerable: false, configurable: true }); } _ensureRootQuery(query, params) { const rootQuery = params._rootQuery; if (!rootQuery) { Object.defineProperty(params, '_rootQuery', { value: query, writable: true, enumerable: false, configurable: true }); } } _isCurrentRootQuery(query, params) { const rootQuery = params._rootQuery; return rootQuery === query; } _resetRootQuery(query, params) { const rootQuery = params._rootQuery; if (rootQuery === query) { Object.defineProperty(params, '_rootQuery', { value: undefined, writable: true, enumerable: false, configurable: true }); } } _getRootQuery(params) { return params._containsInsertReturningClause; } _setRootQuery(params, value) { Object.defineProperty(params, '_rootQuery', { value: value, writable: true, enumerable: false, configurable: true }); } _isValue(value) { if (value === null || value === undefined) { return false; } if (!this._connectionConfiguration.allowEmptyString && value === '') { return false; } if (Array.isArray(value) && value.length <= 0) { return false; } return true; } _isReservedKeyword(_word) { return false; } _forceAsIdentifier(identifier) { return '"' + identifier + '"'; } _escape(identifier, strict) { return this._connectionConfiguration.escape(identifier, strict); } _needParenthesis(value) { const operation = (0, SqlBuilder_2.operationOf)(value); if (!operation) { return false; } if (this._operationsThatNeedParenthesis[operation]) { return true; } return false; } _needParenthesisExcluding(value, excluding) { const operation = (0, SqlBuilder_2.operationOf)(value); if (!operation) { return false; } if (operation === excluding) { return false; } if (this._operationsThatNeedParenthesis[operation]) { return true; } return false; } _appendColumnName(column, params) { const columnPrivate = (0, Column_2.__getColumnPrivate)(column); const typeAdapter = columnPrivate.__typeAdapter; if ((0, values_1.__isBooleanValueSource)(columnPrivate) && typeAdapter instanceof TypeAdapter_1.CustomBooleanTypeAdapter) { return '(' + this._appendRawColumnName(column, params) + ' = ' + this._appendLiteralValue(typeAdapter.trueValue, params) + ')'; } return this._appendRawColumnName(column, params); } _appendColumnNameForCondition(column, params) { const columnPrivate = (0, Column_2.__getColumnPrivate)(column); const typeAdapter = columnPrivate.__typeAdapter; if ((0, values_1.__isBooleanValueSource)(columnPrivate) && typeAdapter instanceof TypeAdapter_1.CustomBooleanTypeAdapter) { return this._appendRawColumnName(column, params) + ' = ' + this._appendLiteralValue(typeAdapter.trueValue, params); } return this._appendRawColumnName(column, params); } _appendRawColumnName(column, params) { const columnPrivate = (0, Column_2.__getColumnPrivate)(column); const tableOrView = columnPrivate.__tableOrView; const tablePrivate = (0, ITableOrView_2.__getTableOrViewPrivate)(tableOrView); const forceAliasFor = this._getForceAliasFor(params); const forceAliasAs = this._getForceAliasAs(params); const fakeNamesOf = this._getFakeNamesOf(params); if (tablePrivate.__valuesForInsert) { return this._appendRawColumnNameForValuesForInsert(column, params); } if (forceAliasFor === tableOrView && forceAliasAs) { return this._escape(forceAliasAs, true) + '.' + this._escape(columnPrivate.__name, true); } if (fakeNamesOf && fakeNamesOf.has(tableOrView)) { if (tablePrivate.__as) { return this._escape('_old_', true) + '.' + this._escape(tablePrivate.__as + '__' + columnPrivate.__name, true); } else { return this._escape('_old_', true) + '.' + this._escape(tablePrivate.__name + '__' + columnPrivate.__name, true); } } if (tablePrivate.__as) { return this._escape(tablePrivate.__as, true) + '.' + this._escape(columnPrivate.__name, true); } else if (this._getSafeTableOrView(params) === tableOrView) { return this._escape(columnPrivate.__name, true); } else { return this._escape(tablePrivate.__name, false) + '.' + this._escape(columnPrivate.__name, true); } } _appendRawColumnNameForValuesForInsert(column, _params) { const columnPrivate = (0, Column_2.__getColumnPrivate)(column); return 'excluded.' + this._escape(columnPrivate.__name, true); } _appendLiteralValue(value, _params) { if (typeof value === 'number') { return '' + value; } else { return "'" + value + "'"; } } _getTableOrViewVisibleName(table) { const t = (0, ITableOrView_2.__getTableOrViewPrivate)(table); let result = this._escape(t.__name, false); if (t.__as) { result += ' as ' + this._escape(t.__as, true); } if (t.__customizationName) { result += ' (customization name: ' + t.__customizationName + ')'; } return result; } _appendTableOrViewName(table, params) { const t = (0, ITableOrView_2.__getTableOrViewPrivate)(table); if (t.__template) { return this._appendRawFragment(t.__template, params); } const forceAliasFor = this._getForceAliasFor(params); const forceAliasAs = this._getForceAliasAs(params); let result = this._appendTableOrViewNameForFrom(table, params); if (forceAliasFor === table && forceAliasAs) { if (this._supportTableAliasWithAs) { result += ' as '; } else { result += ' '; } result += this._escape(forceAliasAs, true); } else if (t.__as) { if (this._supportTableAliasWithAs) { result += ' as '; } else { result += ' '; } result += this._escape(t.__as, true); } else { const alias = this._appendTableOrViewNoAliasForFrom(table, params); if (alias) { if (this._supportTableAliasWithAs) { result += ' as '; } else { result += ' '; } result += alias; } } return result; } _appendTableOrViewNameForFrom(table, _params) { const t = (0, ITableOrView_2.__getTableOrViewPrivate)(table); return this._escape(t.__name, false); } _appendTableOrViewNoAliasForFrom(_table, _params) { return ''; } _appendRawFragment(rawFragment, params) { return rawFragment.__toSql(this, params); // RawFragment has a hidden implemetation of ToSql } _appendCondition(condition, params) { if ((0, SqlBuilder_2.hasToSql)(condition)) { return condition.__toSqlForCondition(this, params); } throw new Error('Conditions must have a __toSqlForCondition method'); } _appendConditionParenthesis(condition, params) { if (this._needParenthesis(condition)) { return '(' + this._appendCondition(condition, params) + ')'; } return this._appendCondition(condition, params); } _appendConditionParenthesisExcuding(condition, params, excluding) { if (this._needParenthesisExcluding(condition, excluding)) { return '(' + this._appendCondition(condition, params) + ')'; } return this._appendCondition(condition, params); } _appendSql(value, params) { return value.__toSql(this, params); // All ValueSource or Column have a hidden implemetation of ToSql } _appendSqlParenthesis(value, params) { if (this._needParenthesis(value)) { return '(' + this._appendSql(value, params) + ')'; } return this._appendSql(value, params); } _appendSqlParenthesisExcluding(value, params, excluding) { if (this._needParenthesisExcluding(value, excluding)) { return '(' + this._appendSql(value, params) + ')'; } return this._appendSql(value, params); } _appendSpreadValue(value, params, columnType, columnTypeName, typeAdapter, forceTypeCast = false) { if ((0, SqlBuilder_2.hasToSql)(value)) { return '(' + this._appendSql(value, params) + ')'; } if (Array.isArray(value)) { if (value.length <= 0) { return '()'; } let arrayResult = '(' + this._appendValue(value[0], params, columnType, columnTypeName, typeAdapter, forceTypeCast); for (let i = 1, length = value.length; i < length; i++) { arrayResult += ', ' + this._appendValue(value[i], params, columnType, columnTypeName, typeAdapter, forceTypeCast); } return arrayResult + ')'; } const adaptedValue = this._transformParamToDB(value, columnType, columnTypeName, typeAdapter); return '(' + this._appendParam(adaptedValue, params, columnType, columnTypeName, typeAdapter, forceTypeCast) + ')'; } _appendValue(value, params, columnType, columnTypeName, typeAdapter, forceTypeCast = false) { if ((0, SqlBuilder_2.hasToSql)(value)) { return this._appendSql(value, params); } const adaptedValue = this._transformParamToDB(value, columnType, columnTypeName, typeAdapter); return this._appendParam(adaptedValue, params, columnType, columnTypeName, typeAdapter, forceTypeCast); } _appendValueParenthesis(value, params, columnType, columnTypeName, typeAdapter, forceTypeCast = false) { if (this._needParenthesis(value)) { return '(' + this._appendValue(value, params, columnType, columnTypeName, typeAdapter, forceTypeCast) + ')'; } return this._appendValue(value, params, columnType, columnTypeName, typeAdapter, forceTypeCast); } _appendValueParenthesisExcluding(value, params, columnType, columnTypeName, typeAdapter, excluding, forceTypeCast = false) { if (this._needParenthesisExcluding(value, excluding)) { return '(' + this._appendValue(value, params, columnType, columnTypeName, typeAdapter, forceTypeCast) + ')'; } return this._appendValue(value, params, columnType, columnTypeName, typeAdapter, forceTypeCast); } _appendConditionSql(value, params) { return value.__toSqlForCondition(this, params); // All ValueSource or Column have a hidden implemetation of ToSql } _appendConditionSqlParenthesisExcluding(value, params, excluding) { if (this._needParenthesisExcluding(value, excluding)) { return '(' + this._appendConditionSql(value, params) + ')'; } return this._appendConditionSql(value, params); } _appendConditionSqlParenthesis(value, params) { if (this._needParenthesis(value)) { return '(' + this._appendConditionSql(value, params) + ')'; } return this._appendConditionSql(value, params); } _appendConditionValue(value, params, columnType, columnTypeName, typeAdapter, forceTypeCast = false) { if ((0, SqlBuilder_2.hasToSql)(value)) { return this._appendConditionSql(value, params); } const adaptedValue = this._transformParamToDB(value, columnType, columnTypeName, typeAdapter); return this._appendConditionParam(adaptedValue, params, columnType, columnTypeName, typeAdapter, forceTypeCast); } _appendConditionValueParenthesis(value, params, columnType, columnTypeName, typeAdapter, forceTypeCast = false) { if (this._needParenthesis(value)) { return '(' + this._appendConditionValue(value, params, columnType, columnTypeName, typeAdapter, forceTypeCast) + ')'; } return this._appendConditionValue(value, params, columnType, columnTypeName, typeAdapter, forceTypeCast); } _appendConditionValueParenthesisExcluding(value, params, columnType, columnTypeName, typeAdapter, excluding, forceTypeCast = false) { if (this._needParenthesisExcluding(value, excluding)) { return '(' + this._appendConditionValue(value, params, columnType, columnTypeName, typeAdapter, forceTypeCast) + ')'; } return this._appendConditionValue(value, params, columnType, columnTypeName, typeAdapter, forceTypeCast); } _transformParamToDB(value, _columnType, columnTypeName, typeAdapter) { if (typeAdapter) { return typeAdapter.transformValueToDB(value, columnTypeName, this._defaultTypeAdapter); } else { return this._defaultTypeAdapter.transformValueToDB(value, columnTypeName); } } _appendParam(value, params, _columnType, columnTypeName, typeAdapter, forceTypeCast) { const placeholder = this._queryRunner.addParam(params, value); if (typeAdapter && typeAdapter.transformPlaceholder) { return typeAdapter.transformPlaceholder(placeholder, columnTypeName, forceTypeCast, value, this._defaultTypeAdapter); } else { return this._defaultTypeAdapter.transformPlaceholder(placeholder, columnTypeName, forceTypeCast, value); } } _appendConditionParam(value, params, columnType, columnTypeName, typeAdapter, forceTypeCast) { return this._appendParam(value, params, columnType, columnTypeName, typeAdapter, forceTypeCast); } _appendColumnAlias(name, _params) { return this._escape(name, true); } _appendColumnValue(value, params, _isOutermostQuery) { return this._appendSql(value, params); } _buildWith(withData, params) { let withs = withData.__withs; if (this._isWithGenerated(params)) { if (this._generateExternalWith(params)) { withs = withData.__withs.filter(value => { return (0, ITableOrView_2.__getTableOrViewPrivate)(value).__hasExternalDependencies; }); this._setGenerateExternalWith(params, false); } else { return ''; } } else { withs = withData.__withs; this._setWithGenerated(params, true); } if (withs.length <= 0) { this._setWithGeneratedFinished(params, true); return ''; } let result = ''; let recursive = false; for (let i = 0, length = withs.length; i < length; i++) { const withView = (0, SqlBuilder_3.getWithData)(withs[i]); if (withView.__type === 'values') { const values = this._buildWithValues(withView, params); if (values) { if (result) { result += ', '; } result += values; } continue; } const customization = withView.__selectData.__customization; if (result) { result += ', '; } result += withView.__name; result += this._appendWithColumns(withView, params); result += ' as '; if (customization && customization.beforeWithQuery) { result += this._appendRawFragment(customization.beforeWithQuery, params) + ' '; } result += '('; result += this._buildSelect(withView.__selectData, params); result += ')'; if (customization && customization.afterWithQuery) { result += ' ' + this._appendRawFragment(customization.afterWithQuery, params); } recursive = recursive || !!withView.__recursive; } this._setWithGeneratedFinished(params, true); return this._appendWithKeyword(recursive) + ' ' + result + ' '; } _buildWithValues(withValues, params) { let result = withValues.__name; let columns = ''; for (var columnName in withValues) { const column = (0, Column_2.__getColumnOfObject)(withValues.__getTableOrView(), columnName); if (!column) { continue; } if (columns) { columns += ', '; } const columnPrivate = (0, Column_2.__getColumnPrivate)(column); columns += this._appendColumnAlias(columnPrivate.__name, params); } result += '(' + columns + ')'; result += ' as (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_2.__getColumnOfObject)(withValues.__getTableOrView(), columnName); if (!column) { continue; } if (valueSql) { valueSql += ', '; } valueSql += this._appendValueForColumn(column, value[columnName], params); } valuesSql += '(' + valueSql + ')'; } result += valuesSql; result += ')'; return result; } _appendWithColumns(_withData, _params) { return ''; } _appendWithKeyword(recursive) { if (recursive) { return 'with recursive'; } return 'with'; } _inlineSelectAsValue(query, params) { const result = '(' + this._buildInlineSelect(query, params) + ')'; return result; } _inlineSelectAsValueForCondition(query, params) { const result = '(' + this._buildInlineSelect(query, params) + ')'; return result; } _buildInlineSelect(query, params) { const oldWithGeneratedFinished = this._isWithGeneratedFinished(params); const oldGenerateExternalWith = this._generateExternalWith(params); this._setGenerateExternalWith(params, true); this._setWithGeneratedFinished(params, false); const result = this._buildSelectWithColumnsInfo(query, params, {}, false); this._setWithGeneratedFinished(params, oldWithGeneratedFinished); this._setGenerateExternalWith(params, oldGenerateExternalWith); return result; } _buildSelect(query, params) { this._ensureRootQuery(query, params); const isOutermostQuery = this._isCurrentRootQuery(query, params); const result = this._buildSelectWithColumnsInfo(query, params, {}, isOutermostQuery); this._resetRootQuery(query, params); return result; } _appendCompoundOperator(compoundOperator, _params) { switch (compoundOperator) { case 'union': return ' union '; case 'unionAll': return ' union all '; case 'intersect': return ' intersect '; case 'intersectAll': return ' intersect all '; case 'except': return ' except '; case 'exceptAll': return ' except all '; case 'minus': return ' except '; case 'minusAll': return ' except all '; default: throw new Error('Invalid compound operator: ' + compoundOperator); } } _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 '(' + result + ')'; } return result; } _buildFromJoins(tables, joins, requiredTablesOrViews, params) { let fromJoins = ''; if (tables && tables.length > 0) { let requireComma = false; for (let i = 0, length = tables.length; i < length; i++) { if (requireComma) { fromJoins += ', '; } fromJoins += this._appendTableOrViewName(tables[i], params); requireComma = true; } } if (!joins || joins.length <= 0) { return fromJoins; } for (let i = 0, length = joins.length; i < length; i++) { const join = joins[i]; if (join.__optional) { if (!requiredTablesOrViews.has(join.__tableOrView)) { continue; } } switch (join.__joinType) { case 'join': fromJoins += ' join '; break; case 'innerJoin': fromJoins += ' inner join '; break; case 'leftJoin': fromJoins += ' left join '; break; case 'leftOuterJoin': fromJoins += ' left outer join '; break; default: throw new Error('Invalid join type: ' + join.__joinType); } fromJoins += this._appendTableOrViewName(join.__tableOrView, params); if (join.__on) { const onCondition = this._appendCondition(join.__on, params); if (onCondition) { fromJoins += ' on ' + onCondition; } } } return fromJoins; } _buildSelectWithColumnsInfo(query, params, columnsForInsert, isOutermostQuery) { const oldSafeTableOrView = this._getSafeTableOrView(params); const oldWithGenerated = this._isWithGenerated(params); const oldWithGeneratedFinished = this._isWithGeneratedFinished(params); const oldAggregateArrayWrapped = this._isAggregateArrayWrapped(params); const customization = query.__customization; const needAgggregateArrayWrapper = this._needAgggregateArrayWrapper(query, params); const aggregateId = needAgggregateArrayWrapper ? this._generateUnique() : 0; if (query.__type === 'compound') { this._setSafeTableOrView(params, undefined); let selectQuery = ''; if (needAgggregateArrayWrapper) { selectQuery += this._appendAggragateArrayWrapperBegin(query, params, aggregateId); this._setAggregateArrayWrapped(params, true); } if (customization && customization.beforeQuery) { selectQuery += this._appendRawFragment(customization.beforeQuery, params) + ' '; } selectQuery += this._buildWith(query, params); selectQuery += this._buildSelectWithColumnsInfoForCompound(query.__firstQuery, params, columnsForInsert, isOutermostQuery); selectQuery += this._appendCompoundOperator(query.__compoundOperator, params); selectQuery += this._buildSelectWithColumnsInfoForCompound(query.__secondQuery, params, columnsForInsert, isOutermostQuery); if (!query.__asInlineAggregatedArrayValue || !this._supportOrderByWhenAggregateArray || this._isAggregateArrayWrapped(params)) { selectQuery += this._buildSelectOrderBy(query, params); } if (!query.__asInlineAggregatedArrayValue || !this._supportLimitWhenAggregateArray || this._isAggregateArrayWrapped(params)) { selectQuery += this._buildSelectLimitOffset(query, params); } selectQuery += this._buildSelectAsAggregatedArray(query, params); if (customization && customization.afterQuery) { selectQuery += ' ' + this._appendRawFragment(customization.afterQuery, params); } if (needAgggregateArrayWrapper) { selectQuery += this._appendAggragateArrayWrapperEnd(query, params, aggregateId); } this._setSafeTableOrView(params, oldSafeTableOrView); this._setWithGenerated(params, oldWithGenerated); this._setWithGeneratedFinished(params, oldWithGeneratedFinished); this._setAggregateArrayWrapped(params, oldAggregateArrayWrapped); return selectQuery; } const requiredTablesOrViews = query.__requiredTablesOrViews; const oldFakeNameOf = this._getFakeNamesOf(params); if (oldFakeNameOf) { if (requiredTablesOrViews) { const newFakeNameOf = new Set(); requiredTablesOrViews.forEach(v => { if (oldFakeNameOf.has(v)) { newFakeNameOf.add(v); } }); if (newFakeNameOf.size > 0) { this._setFakeNamesOf(params, newFakeNameOf); } else { this._setFakeNamesOf(params, undefined); } } else { this._setFakeNamesOf(params, undefined); } } const tables = query.__tablesOrViews; const tablesLength = tables.length; const joins = query.__joins; let hasJoins = false; for (let i = 0, length = joins.length; i < length; i++) { const join = joins[i]; if (join.__optional) { if (!requiredTablesOrViews.has(join.__tableOrView)) { continue; } } hasJoins = true; break; } if (tablesLength === 1 && !hasJoins) { this._setSafeTableOrView(params, tables[0]); } else { this._setSafeTableOrView(params, undefined); } let selectQuery = ''; if (needAgggregateArrayWrapper) { selectQuery += this._appendAggragateArrayWrapperBegin(query, params, aggregateId); this._setAggregateArrayWrapped(params, true); } if (customization && customization.beforeQuery) { selectQuery += this._appendRawFragment(customization.beforeQuery, params) + ' '; } selectQuery += this._buildWith(query, params); selectQuery += 'select '; if (customization && customization.afterSelectKeyword) { selectQuery += this._appendRawFragment(customization.afterSelectKeyword, params) + ' '; } if (query.__distinct) { selectQuery += 'distinct '; } if (customization && customization.beforeColumns) { selectQuery += this._appendRawFragment(customization.beforeColumns, params) + ' '; } const columns = {}; (0, SqlBuilder_1.flattenQueryColumns)(query.__columns, columns, ''); if (needAgggregateArrayWrapper || !this._needAgggregateArrayColumnsTransformation(query, params)) { let requireComma = false; for (const property in columns) { if (requireComma) { selectQuery += ', '; } const columnForInsert = columnsForInsert[property]; selectQuery += this._appendSelectColumn(columns[property], params, columnForInsert, isOutermostQuery); if (property) { selectQuery += ' as ' + this._appendColumnAlias(property, params); } requireComma = true; } } else { let aggregatedArrayColumns; if (query.__oneColumn) { aggregatedArrayColumns = query.__columns['result']; if (!aggregatedArrayColumns) { throw new Error('Illegal state: result column for a select one column not found'); } } else { aggregatedArrayColumns = query.__columns; } selectQuery += this._appendAggragateArrayColumns(aggregatedArrayColumns, false, params, query); } if (tablesLength <= 0) { selectQuery += this._fromNoTable(); } else { selectQuery += ' from '; selectQuery += this._buildFromJoins(tables, joins, query.__requiredTablesOrViews, params); } const where = query.__where; if (where) { const whereCondition = this._appendCondition(where, params); if (whereCondition) { selectQuery += ' where ' + whereCondition; } } // Oracle recursive const startWith = query.__startWith; if (startWith) { const startWithCondition = this._appendCondition(startWith, params); if (startWithCondition) { selectQuery += ' start with ' + startWithCondition; } } // Oracle recursive const connectdBy = query.__connectBy; if (connectdBy) { const connectByCondition = this._appendCondition(connectdBy, params); if (connectByCondition) { if (query.__connectByNoCycle) { selectQuery += ' connect by nocycle ' + connectByCondition; } else { selectQuery += ' connect by ' + connectByCondition; } } } let requireComma = false; const groupBy = query.__groupBy; for (let i = 0, length = groupBy.length; i < length; i++) { if (requireComma) { selectQuery += ', '; } else { selectQuery += ' group by '; } selectQuery += this._appendSelectColumn(groupBy[i], params, undefined, isOutermostQuery); requireComma = true; } const having = query.__having; if (having) { const havingCondition = this._appendCondition(having, params); if (havingCondition) { selectQuery += ' having ' + havingCondition; } } if (customization && customization.customWindow) { selectQuery += ' window '; selectQuery += this._appendRawFragment(customization.customWindow, params); } if (!query.__asInlineAggregatedArrayValue || !this._supportOrderByWhenAggregateArray || this._isAggregateArrayWrapped(params)) { selectQuery += this._buildSelectOrderBy(query, params); } if (!query.__asInlineAggregatedArrayValue || !this._supportLimitWhenAggregateArray || this._isAggregateArrayWrapped(params)) { selectQuery += this._buildSelectLimitOffset(query, params); } selectQuery += this._buildSelectAsAggregatedArray(query, params); if (customization && customization.afterQuery) { selectQuery += ' ' + this._appendRawFragment(customization.afterQuery, params); } if (needAgggregateArrayWrapper) { selectQuery += this._appendAggragateArrayWrapperEnd(query, params, aggregateId); } this._setSafeTableOrView(params, oldSafeTableOrView); this._setFakeNamesOf(params, oldFakeNameOf); this._setWithGenerated(params, oldWithGenerated); this._setWithGeneratedFinished(params, oldWithGeneratedFinished); this._setAggregateArrayWrapped(params, oldAggregateArrayWrapped); return selectQuery; } _appendSelectColumn(value, params, columnForInsert, isOutermostQuery) { if (columnForInsert) { const sql = this._appendCustomBooleanRemapForColumnIfRequired(columnForInsert, value, params); if (sql) { return sql; } } return this._appendColumnValue(value, params, isOutermostQuery); } _fromNoTable() { return ''; } _buildSelectOrderBy(query, params) { 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 ''; } if (query.__orderingSiblingsOnly) { // Oracle recursive return ' order siblings by ' + orderByColumns; } else { return ' order by ' + orderByColumns; } } 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 'desc': case 'asc nulls first': case 'asc nulls last': case 'desc nulls first': case 'desc nulls last': orderByColumns += this._appendOrderByColumnAlias(entry, query, params) + ' ' + order; break; case 'insensitive': case 'asc insensitive': case 'desc insensitive': case 'asc nulls first insensitive': case 'asc nulls last insensitive': case 'desc nulls first insensitive': case 'desc nulls last insensitive': { let sqlOrder = order.substring(0, order.length - 12); if (sqlOrder) { sqlOrder = ' ' + sqlOrder; } orderByColumns += this._appendOrderByColumnAliasInsensitive(entry, query, params) + sqlOrder; 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 ''; } if (query.__orderingSiblingsOnly) { // Oracle recursive return ' order siblings by ' + orderByColumns; } else { return ' order by ' + orderByColumns; } } _appendOrderByColumnAlias(entry, query, params) { const expression = entry.expression; const columns = query.__columns; if (typeof expression === 'string') { const column = (0, SqlBuilder_1.getQueryColumn)(columns, expression); if (!column) { throw new Error('Column ' + expression + ' included in the order by not found in the select clause'); } return this._appendColumnAlias(expression, params); } else if ((0, values_1.isValueSource)(expression)) { const oldSafeTableOrView = this._getSafeTableOrView(params); this._setSafeTableOrView(params, undefined); const result = this._appendSql(expression, params); this._setSafeTableOrView(params, oldSafeTableOrView); return result; } else { const oldSafeTableOrView = this._getSafeTableOrView(params); this._setSafeTableOrView(params, undefined); const result = this._appendRawFragment(expression, params); this._setSafeTableOrView(params, oldSafeTableOrView); return result; } } _appendOrderByColumnAliasInsensitive(entry, query, params) { const collation = this._connectionConfiguration.insesitiveCollation; const stringColumn = this._isStringOrderByColumn(entry, query); if (!stringColumn) { // Ignore the insensitive term, it do nothing return this._appendOrderByColumnAlias(entry, query, params); } else if (collation) { return this._appendOrderByColumnAlias(entry, query, params) + ' collate ' + collation; } else if (collation === '') { return this._appendOrderByColumnAlias(entry, query, params); } else { return 'lower(' + this._appendOrderByColumnAlias(entry, query, params) + ')'; } } _isStringOrderByColumn(entry, query) { const expression = entry.expression; const columns = query.__columns; if (typeof expression === 'string') { const column = (0, SqlBuilder_1.getQueryColumn)(columns, expression); if (!column) { throw new Error('Column ' + expression + ' included in the order by not found in the select clause'); } return (0, values_1.__isStringValueSource)((0, values_2.__getValueSourcePrivate)(column)); } else if ((0, values_1.isValueSource)(expression)) { return (0, values_1.__isStringValueSource)((0, values_2.__getValueSourcePrivate)(expression)); } else { return false; } } _buildSelectLimitOffset(query, params) { let result = ''; const offset = query.__offset; if (offset !== null && offset !== undefined) { result += ' offset ' + this._appendValue(offset, params, 'int', 'int', undefined) + ' rows'; } const limit = query.__limit; if (limit !== null && limit !== undefined) { result += ' fetch next ' + this._appendValue(limit, params, 'int', 'int', undefined) + ' rows only'; } return result; } _buildInsertMultiple(query, params) { const multiple = query.__multiple; if (!multiple) { throw new Error('Exepected a multiple insert'); } if (multiple.length <= 0) { return ''; } this._ensureRootQuery(query, params); const oldSafeTableOrView = this._getSafeTableOrView(params); const oldFakeNameOf = this._getFakeNamesOf(params); this._setFakeNamesOf(params, undefined); const table = query.__table; const customization = query.__customization; this._setSafeTableOrView(params, table); let insertQuery = ''; if (customization && customization.beforeQuery) { insertQuery += this._appendRawFragment(customization.beforeQuery, params) + ' '; } if (this._insertSupportWith) { insertQuery += this._buildWith(query, params); } insertQuery += 'insert '; if (customization && customization.afterInsertKeyword) { insertQuery += this._appendRawFragment(customization.afterInsertKeyword, params) + ' '; } insertQuery += this._buildInsertOnConflictBeforeInto(query, params); insertQuery += 'into '; insertQuery += this._appendTableOrViewName(table, params); const shape = query.__shape; let usedColumns = {}; let translationToShape; if (shape) { // Follow shape order for (let i = 0, length = multiple.length; i < length; i++) { const sets = multiple[i]; const properties = Object.getOwnPropertyNames(sets); for (let j = 0, length = properties.length; j < length; j++) { const property = properties[j]; const columnName = shape[property]; if (typeof columnName !== 'string') { continue; } usedColumns[columnName] = true; } } // Sort according the shape const unorderedUsedColumn = usedColumns; usedColumns = {}; translationToShape = {}; const properties = Object.getOwnPropertyNames(shape); for (let i = 0, length = properties.length; i < length; i++) { const property = properties[i]; const columnName = shape[property]; const column = (0, Column_2.__getColumnOfObject)(table, columnName); if (!column) { // Additional property provided in the value object // Skipped because it is not part of the table // This allows to have more complex objects used in the query continue; } if (!(columnName in unorderedUsedColumn)) { // No value set for that property in the shape continue; } usedColumns[columnName] = true; translationToShape[columnName] = property; } } else { // No shape, follow set order for (let i = 0, length = multiple.length; i < length; i++) { const sets = multiple[i]; const properties = Object.getOwnPropertyNames(sets); for (let j = 0, length = properties.length; j < length; j++) { const columnName = properties[j]; usedColumns[columnName] = true; } } } let columns = ''; const nextSequenceValues = []; for (var columnName in table) { const column = (0, Column_2.__getColumnOfObject)(table, columnName); if (!column) { continue; } const columnPrivate = (0, Column_2.__getColumnPrivate)(column); if (!columnPrivate.__sequenceName) { continue; } if (columns) { columns += ', '; } columns += this._appendRawColumnName(column, params); nextSequenceValues.push(columnPrivate.__sequenceName); } for (let columnName in usedColumns) { const column = (0, Column_2.__getColumnOfObject)(table, columnName); if (!column) { // Additional property provided in the value object // Skipped because it is not part of the table // This allows to have more complex objects used in the query continue; } if (columns) { columns += ', '; } columns += this._appendRawColumnName(column, params); } insertQuery += ' (' + columns + ')'; insertQuery += this._buildInsertOutput(query, params); let multipleValues = ''; for (let i = 0, length = multiple.length; i < length; i++) { let values = ''; for (let j = 0, length = nextSequenceValues.length; j < length; j++) { if (values) { values += ', '; } const sequenceName = nextSequenceValues[j]; values += this._nextSequenceValue(params, sequenceName); } const sets = multiple[i]; for (let columnName in usedColumns)