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.
255 lines (254 loc) • 10.9 kB
JavaScript
"use strict";
var _a;
Object.defineProperty(exports, "__esModule", { value: true });
exports.getInnerObjetRuleToApply = exports.createColumnsFromInnerObject = exports.createColumnsFrom = exports.ColumnImpl = void 0;
const ITableOrView_1 = require("../utils/ITableOrView");
const values_1 = require("../expressions/values");
const ValueSourceImpl_1 = require("./ValueSourceImpl");
const TypeAdapter_1 = require("../TypeAdapter");
const ProxyTypeAdapter_1 = require("./ProxyTypeAdapter");
const symbols_1 = require("../utils/symbols");
class ColumnImpl extends ValueSourceImpl_1.ValueSourceImpl {
constructor(table, name, valueType, valueTypeName, typeAdapter) {
super(valueType, valueTypeName, 'required', typeAdapter);
this[_a] = true;
this.__hasDefault = false;
this.__isPrimaryKey = false;
this.__isAutogeneratedPrimaryKey = false;
this.__isComputed = false;
this.__name = name;
this.__tableOrView = table;
}
__toSql(sqlBuilder, params) {
return sqlBuilder._appendColumnName(this.__asColumn(), params);
}
__toSqlForCondition(sqlBuilder, params) {
return sqlBuilder._appendColumnNameForCondition(this.__asColumn(), params);
}
__asColumn() {
return this;
}
__asOptionalColumn() {
this.__optionalType = 'optional';
return this;
}
__asColumnWithDefaultValue() {
this.__hasDefault = true;
return this;
}
__asOptionalColumnWithDefaultValue() {
this.__optionalType = 'optional';
this.__hasDefault = true;
return this;
}
__asAutogeneratedPrimaryKey() {
this.__hasDefault = true;
this.__isPrimaryKey = true;
this.__isAutogeneratedPrimaryKey = true;
return this;
}
__asAutogeneratedPrimaryKeyBySequence(sequenceName) {
this.__hasDefault = true;
this.__isPrimaryKey = true;
this.__isAutogeneratedPrimaryKey = true;
this.__sequenceName = sequenceName;
return this;
}
__asPrimaryKey() {
this.__isPrimaryKey = true;
return this;
}
__asComputedColumn() {
this.__isComputed = true;
return this;
}
__asOptionalComputedColumn() {
this.__isComputed = true;
this.__optionalType = 'optional';
return this;
}
__registerTableOrView(sqlBuilder, requiredTablesOrViews) {
(0, ITableOrView_1.__getTableOrViewPrivate)(this.__tableOrView).__registerTableOrView(sqlBuilder, requiredTablesOrViews);
}
__registerRequiredColumn(_sqlBuilder, requiredColumns, onlyForTablesOrViews) {
if (onlyForTablesOrViews.has(this.__tableOrView)) {
requiredColumns.add(this);
}
}
__getOldValues(sqlBuilder) {
return (0, ITableOrView_1.__getTableOrViewPrivate)(this.__tableOrView).__getOldValues(sqlBuilder);
}
__getValuesForInsert(sqlBuilder) {
return (0, ITableOrView_1.__getTableOrViewPrivate)(this.__tableOrView).__getValuesForInsert(sqlBuilder);
}
__isAllowed(sqlBuilder) {
return (0, ITableOrView_1.__getTableOrViewPrivate)(this.__tableOrView).__isAllowed(sqlBuilder);
}
}
exports.ColumnImpl = ColumnImpl;
_a = symbols_1.isColumnObject;
function createColumnsFrom(sqlBuilder, columns, target, table) {
for (const property in columns) {
const column = columns[property];
if ((0, values_1.isValueSource)(column)) {
const columnPrivate = (0, values_1.__getValueSourcePrivate)(column);
let valueType = columnPrivate.__valueType;
let valueTypeName = columnPrivate.__valueTypeName;
let typeAdapter = columnPrivate.__typeAdapter;
if (typeAdapter instanceof TypeAdapter_1.CustomBooleanTypeAdapter) {
// Avoid treat the column as a custom boolean
typeAdapter = new ProxyTypeAdapter_1.ProxyTypeAdapter(typeAdapter);
}
const withColumn = new ColumnImpl(table, property, valueType, valueTypeName, typeAdapter);
withColumn.__optionalType = columnPrivate.__optionalType;
if (columnPrivate.__aggregatedArrayColumns) {
withColumn.__aggregatedArrayColumns = columnPrivate.__aggregatedArrayColumns;
withColumn.__aggregatedArrayMode = columnPrivate.__aggregatedArrayMode;
}
if (columnPrivate.__uuidString) {
withColumn.__uuidString = columnPrivate.__uuidString;
}
target[property] = withColumn;
}
else {
const newTarget = {};
createColumnsFromInnerObject(sqlBuilder, column, target, table, property + '.');
target[property] = newTarget;
}
}
}
exports.createColumnsFrom = createColumnsFrom;
function createColumnsFromInnerObject(sqlBuilder, columns, target, table, prefix) {
const rule = getInnerObjetRuleToApply(sqlBuilder, columns);
for (const property in columns) {
const column = columns[property];
if ((0, values_1.isValueSource)(column)) {
const columnPrivate = (0, values_1.__getValueSourcePrivate)(column);
let valueType = columnPrivate.__valueType;
let valueTypeName = columnPrivate.__valueTypeName;
let typeAdapter = columnPrivate.__typeAdapter;
if (typeAdapter instanceof TypeAdapter_1.CustomBooleanTypeAdapter) {
// Avoid treat the column as a custom boolean
typeAdapter = new ProxyTypeAdapter_1.ProxyTypeAdapter(typeAdapter);
}
const withColumn = new ColumnImpl(table, prefix + property, valueType, valueTypeName, typeAdapter);
let optionalType = columnPrivate.__optionalType;
switch (rule) {
case 1: // Rule 1, there is requiredInOptionalObject
if (optionalType === 'originallyRequired') {
optionalType = 'optional';
}
break;
case 2: // Rule 2: all from the same left join ignoring inner objects
if (optionalType === 'originallyRequired') {
optionalType = 'requiredInOptionalObject';
}
break;
case 3: // Rule 3: there is a required property
if (optionalType !== 'required') {
optionalType = 'optional';
}
break;
case 4: // Rule 4: the general rule
if (optionalType !== 'required') {
optionalType = 'optional';
}
break;
}
withColumn.__optionalType = optionalType;
if (columnPrivate.__aggregatedArrayColumns) {
withColumn.__aggregatedArrayColumns = columnPrivate.__aggregatedArrayColumns;
withColumn.__aggregatedArrayMode = columnPrivate.__aggregatedArrayMode;
}
if (columnPrivate.__uuidString) {
withColumn.__uuidString = columnPrivate.__uuidString;
}
target[property] = withColumn;
}
else {
const newTarget = {};
createColumnsFromInnerObject(sqlBuilder, column, target, table, prefix + property + '.');
target[property] = newTarget;
}
}
}
exports.createColumnsFromInnerObject = createColumnsFromInnerObject;
function getInnerObjetRuleToApply(sqlBuilder, columns) {
let containsRequired = false;
let contaisOriginallyRequired = false;
let innerObjectsAreRequired = true;
for (const property in columns) {
const column = columns[property];
if ((0, values_1.isValueSource)(column)) {
const columnPrivate = (0, values_1.__getValueSourcePrivate)(column);
const optionalType = columnPrivate.__optionalType;
switch (optionalType) {
case 'requiredInOptionalObject':
return 1; // Rule 1, there is requiredInOptionalObject
case 'required':
containsRequired = true;
break;
case 'originallyRequired':
contaisOriginallyRequired = true;
break;
default: //do nothing
}
}
else {
if (getInnerObjetRuleToApply(sqlBuilder, column) === 3) {
// This is the only case where the inner object is required
innerObjectsAreRequired = true;
}
}
}
if (contaisOriginallyRequired) {
let firstRequiredTables = new Set();
let alwaysSameRequiredTablesSize = undefined;
for (const property in columns) {
const column = columns[property];
if (!(0, values_1.isValueSource)(column)) {
// ignore inner objects
continue;
}
const columnPrivate = (0, values_1.__getValueSourcePrivate)(column);
if (alwaysSameRequiredTablesSize === undefined) {
columnPrivate.__registerTableOrView(sqlBuilder, firstRequiredTables);
alwaysSameRequiredTablesSize = true;
}
else if (alwaysSameRequiredTablesSize) {
let valueSourceRequiredTables = new Set();
columnPrivate.__registerTableOrView(sqlBuilder, valueSourceRequiredTables);
const initialSize = firstRequiredTables.size;
if (initialSize !== valueSourceRequiredTables.size) {
alwaysSameRequiredTablesSize = false;
}
else {
valueSourceRequiredTables.forEach(table => {
firstRequiredTables.add(table);
});
if (initialSize !== firstRequiredTables.size) {
alwaysSameRequiredTablesSize = false;
}
}
}
}
// Evaluate rule 2: all from the same left join ignoring inner objects
let onlyOuterJoin = true;
firstRequiredTables.forEach(table => {
if (!(0, ITableOrView_1.__getTableOrViewPrivate)(table).__forUseInLeftJoin) {
onlyOuterJoin = false;
}
});
if (firstRequiredTables.size <= 0) {
onlyOuterJoin = false;
}
if (alwaysSameRequiredTablesSize && onlyOuterJoin) {
return 2; // Rule 2: all from the same left join ignoring inner objects
}
}
if (containsRequired || innerObjectsAreRequired) {
return 3; // Rule 3: there is a required property
}
return 4; // Rule 4: the general rule
}
exports.getInnerObjetRuleToApply = getInnerObjetRuleToApply;