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
JavaScript
"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)