drizzle-orm 0.10.27 → 0.10.28
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/.eslintrc +28 -0
- package/.tslintignore +1 -0
- package/CHANGELOG.md +202 -0
- package/package.json +1 -6
- package/pnpm-lock.yaml +1842 -0
- package/src/builders/aggregators/abstractAggregator.ts +41 -0
- package/src/builders/aggregators/deleteAggregator.ts +44 -0
- package/src/builders/aggregators/insertAggregator.ts +120 -0
- package/src/builders/aggregators/selectAggregator.ts +163 -0
- package/src/builders/aggregators/updateAggregator.ts +56 -0
- package/src/builders/highLvlBuilders/abstractRequestBuilder.ts +51 -0
- package/src/builders/highLvlBuilders/deleteRequestBuilder.ts +59 -0
- package/src/builders/highLvlBuilders/insertRequestBuilder.ts +75 -0
- package/src/builders/highLvlBuilders/order.ts +4 -0
- package/src/builders/highLvlBuilders/selectRequestBuilder.ts +229 -0
- package/src/builders/highLvlBuilders/updateRequestBuilder.ts +80 -0
- package/src/builders/index.ts +21 -0
- package/src/builders/joinBuilders/builders/abstractJoinBuilder.ts +98 -0
- package/src/builders/joinBuilders/builders/selectWithFiveJoins.ts +110 -0
- package/src/builders/joinBuilders/builders/selectWithFourJoins.ts +254 -0
- package/src/builders/joinBuilders/builders/selectWithJoin.ts +189 -0
- package/src/builders/joinBuilders/builders/selectWithThreeJoins.ts +231 -0
- package/src/builders/joinBuilders/builders/selectWithTwoJoins.ts +210 -0
- package/src/builders/joinBuilders/join.ts +40 -0
- package/src/builders/joinBuilders/joinWith.ts +21 -0
- package/src/builders/joinBuilders/responses/selectResponseFiveJoins.ts +82 -0
- package/src/builders/joinBuilders/responses/selectResponseFourJoins.ts +73 -0
- package/src/builders/joinBuilders/responses/selectResponseThreeJoins.ts +64 -0
- package/src/builders/joinBuilders/responses/selectResponseTwoJoins.ts +57 -0
- package/src/builders/joinBuilders/responses/selectResponseWithJoin.ts +49 -0
- package/src/builders/joinBuilders/static.ts +9 -0
- package/src/builders/lowLvlBuilders/alter.ts +0 -0
- package/src/builders/lowLvlBuilders/create.ts +115 -0
- package/src/builders/lowLvlBuilders/delets/delete.ts +13 -0
- package/src/builders/lowLvlBuilders/delets/deleteFilter.ts +17 -0
- package/src/builders/lowLvlBuilders/delets/deleteFrom.ts +15 -0
- package/src/builders/lowLvlBuilders/inserts/insert.ts +11 -0
- package/src/builders/lowLvlBuilders/inserts/insertInto.ts +16 -0
- package/src/builders/lowLvlBuilders/inserts/onConflictInsert.ts +19 -0
- package/src/builders/lowLvlBuilders/inserts/valuesInsert.ts +27 -0
- package/src/builders/lowLvlBuilders/selects/select.ts +14 -0
- package/src/builders/lowLvlBuilders/selects/selectFrom.ts +50 -0
- package/src/builders/lowLvlBuilders/selects/selectJoined.ts +44 -0
- package/src/builders/lowLvlBuilders/selects/whereSelect.ts +36 -0
- package/src/builders/lowLvlBuilders/updates/update.ts +13 -0
- package/src/builders/lowLvlBuilders/updates/updateIn.ts +17 -0
- package/src/builders/lowLvlBuilders/updates/whereSelect.ts +17 -0
- package/src/builders/lowLvlBuilders/updates/whereSet.ts +21 -0
- package/src/builders/requestBuilders/updates/combine.ts +34 -0
- package/src/builders/requestBuilders/updates/increment.ts +24 -0
- package/src/builders/requestBuilders/updates/setObjects.ts +27 -0
- package/src/builders/requestBuilders/updates/static.ts +15 -0
- package/src/builders/requestBuilders/updates/updates.ts +8 -0
- package/src/builders/requestBuilders/where/and.ts +35 -0
- package/src/builders/requestBuilders/where/const.ts +23 -0
- package/src/builders/requestBuilders/where/constArray.ts +37 -0
- package/src/builders/requestBuilders/where/eqWhere.ts +20 -0
- package/src/builders/requestBuilders/where/greater.ts +20 -0
- package/src/builders/requestBuilders/where/greaterEq.ts +20 -0
- package/src/builders/requestBuilders/where/in.ts +20 -0
- package/src/builders/requestBuilders/where/isNotNull.ts +17 -0
- package/src/builders/requestBuilders/where/isNull.ts +17 -0
- package/src/builders/requestBuilders/where/less.ts +20 -0
- package/src/builders/requestBuilders/where/lessEq.ts +20 -0
- package/src/builders/requestBuilders/where/like.ts +20 -0
- package/src/builders/requestBuilders/where/notEqWhere.ts +20 -0
- package/src/builders/requestBuilders/where/or.ts +35 -0
- package/src/builders/requestBuilders/where/rawWhere.ts +10 -0
- package/src/builders/requestBuilders/where/static.ts +60 -0
- package/src/builders/requestBuilders/where/var.ts +19 -0
- package/src/builders/requestBuilders/where/where.ts +5 -0
- package/src/builders/transaction/transaction.ts +21 -0
- package/src/columns/column.ts +195 -0
- package/src/columns/index.ts +10 -0
- package/src/columns/types/columnType.ts +8 -0
- package/src/columns/types/pgBigDecimal.ts +29 -0
- package/src/columns/types/pgBigInt.ts +36 -0
- package/src/columns/types/pgBigSerial.ts +36 -0
- package/src/columns/types/pgBoolean.ts +18 -0
- package/src/columns/types/pgEnum.ts +17 -0
- package/src/columns/types/pgInteger.ts +21 -0
- package/src/columns/types/pgJsonb.ts +21 -0
- package/src/columns/types/pgSerial.ts +18 -0
- package/src/columns/types/pgSmallInt.ts +18 -0
- package/src/columns/types/pgText.ts +18 -0
- package/src/columns/types/pgTime.ts +18 -0
- package/src/columns/types/pgTimestamp.ts +18 -0
- package/src/columns/types/pgTimestamptz.ts +18 -0
- package/src/columns/types/pgVarChar.ts +24 -0
- package/src/db/db.ts +43 -0
- package/src/db/dbConnector.ts +30 -0
- package/src/db/dbStringConnector.ts +29 -0
- package/src/db/group_by.ts +75 -0
- package/src/db/index.ts +4 -0
- package/src/db/session.ts +16 -0
- package/src/docs/cases/simple_delete.ts +35 -0
- package/src/docs/cases/simple_insert.ts +65 -0
- package/src/docs/cases/simple_join.ts +140 -0
- package/src/docs/cases/simple_select.ts +72 -0
- package/src/docs/cases/simple_update.ts +40 -0
- package/src/docs/tables/citiesTable.ts +22 -0
- package/src/docs/tables/userGroupsTable.ts +12 -0
- package/src/docs/tables/usersTable.ts +33 -0
- package/src/docs/tables/usersToUserGroups.ts +14 -0
- package/src/docs/types/rolesType.ts +4 -0
- package/src/errors/baseError.ts +47 -0
- package/src/errors/builderError.ts +31 -0
- package/src/errors/dbErrors.ts +24 -0
- package/src/index.ts +20 -0
- package/src/indexes/tableIndex.ts +25 -0
- package/src/logger/abstractLogger.ts +4 -0
- package/src/logger/consoleLogger.ts +11 -0
- package/src/mappers/index.ts +0 -0
- package/src/mappers/responseMapper.ts +46 -0
- package/src/migrator/index.ts +0 -0
- package/src/migrator/migrator.ts +97 -0
- package/src/serializer/serializer.ts +336 -0
- package/src/tables/abstractTable.ts +188 -0
- package/src/tables/index.ts +4 -0
- package/src/tables/inferTypes.ts +67 -0
- package/src/tables/migrationsTable.ts +11 -0
- package/src/types/type.ts +15 -0
- package/src/utils/ecranate.ts +4 -0
- package/tsconfig.json +13 -0
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
/* eslint-disable max-len */
|
|
2
|
+
import { AbstractColumn, Column } from '../../columns/column';
|
|
3
|
+
import ColumnType from '../../columns/types/columnType';
|
|
4
|
+
import { AbstractTable } from '../../tables';
|
|
5
|
+
import { ecranate } from '../../utils/ecranate';
|
|
6
|
+
|
|
7
|
+
// eslint-disable-next-line max-len
|
|
8
|
+
export default class Aggregator {
|
|
9
|
+
protected _fields: Array<string> = [];
|
|
10
|
+
protected _table: AbstractTable<any>;
|
|
11
|
+
|
|
12
|
+
public constructor(table: AbstractTable<any>, partial?: {[name: string]: AbstractColumn<ColumnType<any>, boolean, boolean, AbstractTable<any>>}) {
|
|
13
|
+
this._table = table;
|
|
14
|
+
if (!partial) {
|
|
15
|
+
this._fields = this.generateSelectArray(this._table.tableName(),
|
|
16
|
+
Object.values(this._table.mapServiceToDb()));
|
|
17
|
+
} else {
|
|
18
|
+
this._fields = this.generateSelectArray(this._table.tableName(),
|
|
19
|
+
Object.values(partial));
|
|
20
|
+
}
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
protected generateSelectArray = (table: string, columns: AbstractColumn<ColumnType>[], id?: number) => {
|
|
24
|
+
const selectFields: string[] = [];
|
|
25
|
+
|
|
26
|
+
columns.forEach((field: any) => {
|
|
27
|
+
if (field instanceof Column) {
|
|
28
|
+
selectFields.push(' ');
|
|
29
|
+
selectFields.push(table);
|
|
30
|
+
selectFields.push('.');
|
|
31
|
+
selectFields.push(ecranate(field.getColumnName()));
|
|
32
|
+
selectFields.push(' AS ');
|
|
33
|
+
selectFields.push(ecranate(`${field.getAlias()}${id ? `_${id}` : ''}`));
|
|
34
|
+
selectFields.push(',');
|
|
35
|
+
}
|
|
36
|
+
});
|
|
37
|
+
|
|
38
|
+
selectFields.pop();
|
|
39
|
+
return selectFields;
|
|
40
|
+
};
|
|
41
|
+
}
|
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
import { AbstractTable } from '../../tables';
|
|
2
|
+
import Expr from '../requestBuilders/where/where';
|
|
3
|
+
import Aggregator from './abstractAggregator';
|
|
4
|
+
|
|
5
|
+
export default class DeleteAggregator extends Aggregator {
|
|
6
|
+
private _from: Array<string> = [];
|
|
7
|
+
private _filters: Array<string> = [];
|
|
8
|
+
private _values: Array<any> = [];
|
|
9
|
+
private _delete: Array<string> = ['DELETE'];
|
|
10
|
+
|
|
11
|
+
public constructor(table: AbstractTable<any>) {
|
|
12
|
+
super(table);
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
public filters = (filters: Expr): DeleteAggregator => {
|
|
16
|
+
if (filters) {
|
|
17
|
+
const filterQuery = filters.toQuery();
|
|
18
|
+
this._filters.push('WHERE ');
|
|
19
|
+
this._filters.push(filterQuery.query);
|
|
20
|
+
this._values = filterQuery.values;
|
|
21
|
+
}
|
|
22
|
+
return this;
|
|
23
|
+
};
|
|
24
|
+
|
|
25
|
+
public appendFrom = (tableName: string): DeleteAggregator => {
|
|
26
|
+
this._from.push(' FROM ');
|
|
27
|
+
this._from.push(tableName);
|
|
28
|
+
return this;
|
|
29
|
+
};
|
|
30
|
+
|
|
31
|
+
public buildQuery = (): { query: string, values: Array<any> } => {
|
|
32
|
+
// this._delete.push(this._fields.join(''));
|
|
33
|
+
this._delete.push('\n');
|
|
34
|
+
this._delete.push(this._from.join(''));
|
|
35
|
+
this._delete.push('\n');
|
|
36
|
+
this._delete.push(this._filters.join(''));
|
|
37
|
+
this._delete.push('\n');
|
|
38
|
+
this._delete.push('RETURNING');
|
|
39
|
+
this._delete.push('\n');
|
|
40
|
+
this._delete.push(this._fields.join(''));
|
|
41
|
+
|
|
42
|
+
return { query: this._delete.join(''), values: this._values };
|
|
43
|
+
};
|
|
44
|
+
}
|
|
@@ -0,0 +1,120 @@
|
|
|
1
|
+
/* eslint-disable @typescript-eslint/no-loop-func */
|
|
2
|
+
import { IndexedColumn } from '../../columns/column';
|
|
3
|
+
import { AbstractTable } from '../../tables';
|
|
4
|
+
import { ExtractModel, Indexing } from '../../tables/inferTypes';
|
|
5
|
+
import { UpdateExpr } from '../requestBuilders/updates/updates';
|
|
6
|
+
import Aggregator from './abstractAggregator';
|
|
7
|
+
|
|
8
|
+
export default class InsertAggregator extends Aggregator {
|
|
9
|
+
private _onConflict: Array<string> = [];
|
|
10
|
+
private _columns: Array<string> = [];
|
|
11
|
+
private _query: Array<string> = [];
|
|
12
|
+
private _values: Array<any> = [];
|
|
13
|
+
private _from: Array<string> = [];
|
|
14
|
+
private _insert: Array<string> = ['INSERT INTO'];
|
|
15
|
+
|
|
16
|
+
public constructor(table: AbstractTable<any>) {
|
|
17
|
+
super(table);
|
|
18
|
+
this._from.push(' ');
|
|
19
|
+
this._from.push(table.tableName());
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
public appendColumns = () => {
|
|
23
|
+
const mapper = this._table.mapServiceToDb();
|
|
24
|
+
const columns = Object.values(mapper);
|
|
25
|
+
|
|
26
|
+
for (let i = 0; i < columns.length; i += 1) {
|
|
27
|
+
const column = columns[i];
|
|
28
|
+
|
|
29
|
+
this._columns.push('"');
|
|
30
|
+
this._columns.push(column.getColumnName());
|
|
31
|
+
this._columns.push('"');
|
|
32
|
+
|
|
33
|
+
if (i < columns.length - 1) {
|
|
34
|
+
this._columns.push(', ');
|
|
35
|
+
}
|
|
36
|
+
}
|
|
37
|
+
};
|
|
38
|
+
|
|
39
|
+
public appendValues = (values: {[name: string]: any}[]) => {
|
|
40
|
+
// @TODO Check if values not empty
|
|
41
|
+
const mapper = this._table.mapServiceToDb();
|
|
42
|
+
|
|
43
|
+
let position: number = 0;
|
|
44
|
+
for (let i = 0; i < values.length; i += 1) {
|
|
45
|
+
const value = values[i];
|
|
46
|
+
|
|
47
|
+
this._query.push('(');
|
|
48
|
+
const entries = Object.entries(mapper);
|
|
49
|
+
|
|
50
|
+
entries.forEach(([key], index) => {
|
|
51
|
+
const valueToInsert = value[key as keyof ExtractModel<any>];
|
|
52
|
+
const isKeyExistsInValue = key.toString() in value;
|
|
53
|
+
|
|
54
|
+
const column = mapper[key as keyof ExtractModel<any>];
|
|
55
|
+
|
|
56
|
+
if (isKeyExistsInValue) {
|
|
57
|
+
if (valueToInsert !== undefined && valueToInsert !== null) {
|
|
58
|
+
position += 1;
|
|
59
|
+
this._query.push(`$${position}`);
|
|
60
|
+
this._values.push(column.getColumnType().insertStrategy(valueToInsert));
|
|
61
|
+
} else {
|
|
62
|
+
this._query.push('null');
|
|
63
|
+
}
|
|
64
|
+
} else {
|
|
65
|
+
this._query.push('DEFAULT');
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
if (index < entries.length - 1) {
|
|
69
|
+
this._query.push(', ');
|
|
70
|
+
}
|
|
71
|
+
});
|
|
72
|
+
|
|
73
|
+
if (i < values.length - 1) {
|
|
74
|
+
this._query.push('),\n');
|
|
75
|
+
} else {
|
|
76
|
+
this._query.push(')\n');
|
|
77
|
+
}
|
|
78
|
+
}
|
|
79
|
+
};
|
|
80
|
+
|
|
81
|
+
public appendOnConflict = (column: Indexing,
|
|
82
|
+
updates?: UpdateExpr) => {
|
|
83
|
+
if (column) {
|
|
84
|
+
const indexName = column instanceof IndexedColumn
|
|
85
|
+
? column.getColumnName() : column.getColumns().map((it) => it.getColumnName()).join(',');
|
|
86
|
+
this._onConflict.push(`ON CONFLICT (${indexName})\n`);
|
|
87
|
+
if (updates) {
|
|
88
|
+
const currentPointerPosition = this._values.length > 0
|
|
89
|
+
? this._values.length + 1 : undefined;
|
|
90
|
+
|
|
91
|
+
const updatesQuery = updates.toQuery(currentPointerPosition);
|
|
92
|
+
|
|
93
|
+
this._onConflict.push('DO UPDATE\n');
|
|
94
|
+
this._onConflict.push(`SET ${updatesQuery.query}`);
|
|
95
|
+
|
|
96
|
+
this._values.push(...updatesQuery.values);
|
|
97
|
+
} else {
|
|
98
|
+
this._onConflict.push('DO NOTHING\n');
|
|
99
|
+
}
|
|
100
|
+
}
|
|
101
|
+
return this;
|
|
102
|
+
};
|
|
103
|
+
|
|
104
|
+
public buildQuery = (): { query: string, values: Array<any> } => {
|
|
105
|
+
this._insert.push(this._from.join(''));
|
|
106
|
+
this._insert.push(' (');
|
|
107
|
+
this._insert.push(this._columns.join(''));
|
|
108
|
+
this._insert.push(') ');
|
|
109
|
+
this._insert.push('VALUES\n');
|
|
110
|
+
this._insert.push(this._query.join(''));
|
|
111
|
+
this._insert.push('\n');
|
|
112
|
+
this._insert.push(this._onConflict.join(''));
|
|
113
|
+
this._insert.push('\n');
|
|
114
|
+
this._insert.push('RETURNING');
|
|
115
|
+
this._insert.push('\n');
|
|
116
|
+
this._insert.push(this._fields.join(''));
|
|
117
|
+
|
|
118
|
+
return { query: this._insert.join(''), values: this._values };
|
|
119
|
+
};
|
|
120
|
+
}
|
|
@@ -0,0 +1,163 @@
|
|
|
1
|
+
/* eslint-disable max-len */
|
|
2
|
+
import { AbstractColumn } from '../../columns/column';
|
|
3
|
+
import ColumnType from '../../columns/types/columnType';
|
|
4
|
+
import { AbstractTable } from '../../tables';
|
|
5
|
+
import { ecranate } from '../../utils/ecranate';
|
|
6
|
+
import Order from '../highLvlBuilders/order';
|
|
7
|
+
import Join from '../joinBuilders/join';
|
|
8
|
+
import Expr from '../requestBuilders/where/where';
|
|
9
|
+
import Aggregator from './abstractAggregator';
|
|
10
|
+
|
|
11
|
+
export default class SelectAggregator extends Aggregator {
|
|
12
|
+
private _from: Array<string> = [];
|
|
13
|
+
private _filters: Array<string> = [];
|
|
14
|
+
private _select: Array<string> = ['SELECT'];
|
|
15
|
+
private _join: Array<string> = [];
|
|
16
|
+
private _limit: Array<string> = [];
|
|
17
|
+
private _offset: Array<string> = [];
|
|
18
|
+
private _distinct: Array<string> = [];
|
|
19
|
+
// private _groupBy: Array<string> = [];
|
|
20
|
+
private _orderBy: Array<string> = [];
|
|
21
|
+
private _values: Array<any> = [];
|
|
22
|
+
|
|
23
|
+
private _joinCache: {[tableName: string]: string} = {};
|
|
24
|
+
|
|
25
|
+
// public constructor(table: AbstractTable<any>);
|
|
26
|
+
// public constructor(table: AbstractTable<any>, partial: {[name: string]: AbstractColumn<ColumnType<any>, boolean, boolean, AbstractTable<any>>})
|
|
27
|
+
public constructor(table: AbstractTable<any>, partial?: {[name: string]: AbstractColumn<ColumnType<any>, boolean, boolean, AbstractTable<any>>}) {
|
|
28
|
+
super(table, partial);
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
public filters = (filters: Expr): SelectAggregator => {
|
|
32
|
+
if (filters) {
|
|
33
|
+
const queryBuilder = filters.toQuery(1, this._joinCache);
|
|
34
|
+
this._filters.push('WHERE ');
|
|
35
|
+
this._filters.push(queryBuilder.query);
|
|
36
|
+
this._values = queryBuilder.values;
|
|
37
|
+
}
|
|
38
|
+
return this;
|
|
39
|
+
};
|
|
40
|
+
|
|
41
|
+
public limit = (limit?: number): SelectAggregator => {
|
|
42
|
+
if (limit) {
|
|
43
|
+
this._limit.push('LIMIT ');
|
|
44
|
+
this._limit.push(limit.toString());
|
|
45
|
+
}
|
|
46
|
+
return this;
|
|
47
|
+
};
|
|
48
|
+
|
|
49
|
+
public offset = (offset?: number): SelectAggregator => {
|
|
50
|
+
if (offset) {
|
|
51
|
+
this._offset.push('OFFSET ');
|
|
52
|
+
this._offset.push(offset.toString());
|
|
53
|
+
}
|
|
54
|
+
return this;
|
|
55
|
+
};
|
|
56
|
+
|
|
57
|
+
public orderBy = (column?: AbstractColumn<ColumnType, boolean, boolean>,
|
|
58
|
+
order?: Order): SelectAggregator => {
|
|
59
|
+
if (column !== null && column !== undefined) {
|
|
60
|
+
this._orderBy.push('ORDER BY ');
|
|
61
|
+
const columnParent = this._joinCache[column.getParent().tableName()] ? this._joinCache[column.getParent().tableName()] : column.getParent().tableName();
|
|
62
|
+
this._orderBy.push(`${columnParent}.${ecranate(column.getColumnName())} `);
|
|
63
|
+
this._orderBy.push(Order[order!]);
|
|
64
|
+
}
|
|
65
|
+
return this;
|
|
66
|
+
};
|
|
67
|
+
|
|
68
|
+
public distinct = (column?: AbstractColumn<ColumnType, boolean, boolean>): SelectAggregator => {
|
|
69
|
+
if (column) {
|
|
70
|
+
this._distinct.push(` DISTINCT ON(${column.getParent().tableName()}.${ecranate(column.getColumnName())}) `);
|
|
71
|
+
}
|
|
72
|
+
return this;
|
|
73
|
+
};
|
|
74
|
+
|
|
75
|
+
public appendFrom = (tableName: string): SelectAggregator => {
|
|
76
|
+
this._from.push('FROM ');
|
|
77
|
+
this._from.push(tableName);
|
|
78
|
+
// this._from.push(`${tableName} AS ${tableName}_0`);
|
|
79
|
+
this._joinCache[tableName] = tableName;
|
|
80
|
+
return this;
|
|
81
|
+
};
|
|
82
|
+
|
|
83
|
+
// Add select generator for second table also
|
|
84
|
+
public join = (joins: Array<{
|
|
85
|
+
join: Join<any>, partial?: {[name: string]: AbstractColumn<ColumnType<any>, boolean, boolean, any>},
|
|
86
|
+
id?: number
|
|
87
|
+
}>): SelectAggregator => {
|
|
88
|
+
// const cache: {[tableName: string]: string} = {};
|
|
89
|
+
joins.forEach((joinObject: {
|
|
90
|
+
join: Join<any>, partial?: {[name: string]: AbstractColumn<ColumnType<any>, boolean, boolean, any>},
|
|
91
|
+
id?: number
|
|
92
|
+
}) => {
|
|
93
|
+
if (joinObject) {
|
|
94
|
+
const tableFrom = joinObject.join.fromColumn.getParentName();
|
|
95
|
+
const tableTo = joinObject.join.toColumn.getParentName();
|
|
96
|
+
const { type } = joinObject.join;
|
|
97
|
+
|
|
98
|
+
let fromAlias = '';
|
|
99
|
+
if (this._joinCache[tableFrom]) {
|
|
100
|
+
fromAlias = this._joinCache[tableFrom];
|
|
101
|
+
} else {
|
|
102
|
+
fromAlias = `${tableFrom}${joinObject.id ? `_${joinObject.id}` : ''}`;
|
|
103
|
+
this._joinCache[tableFrom] = fromAlias;
|
|
104
|
+
}
|
|
105
|
+
|
|
106
|
+
let selectString;
|
|
107
|
+
if (joinObject.partial) {
|
|
108
|
+
selectString = this.generateSelectArray(`${tableTo}${joinObject.id ? `_${joinObject.id}` : ''}`, Object.values(joinObject.partial), joinObject.id).join('');
|
|
109
|
+
} else {
|
|
110
|
+
selectString = this.generateSelectArray(`${tableTo}${joinObject.id ? `_${joinObject.id}` : ''}`, Object.values(joinObject.join.mappedServiceToDb), joinObject.id).join('');
|
|
111
|
+
}
|
|
112
|
+
this._fields.push(', ');
|
|
113
|
+
this._fields.push(selectString);
|
|
114
|
+
this._join.push('\n');
|
|
115
|
+
this._join.push(type);
|
|
116
|
+
this._join.push(' ');
|
|
117
|
+
this._join.push(tableTo);
|
|
118
|
+
this._join.push(' ');
|
|
119
|
+
this._join.push(`AS ${tableTo}${joinObject.id ? `_${joinObject.id}` : ''}`);
|
|
120
|
+
this._joinCache[tableTo] = `${tableTo}${joinObject.id ? `_${joinObject.id}` : ''}`;
|
|
121
|
+
this._join.push('\n');
|
|
122
|
+
this._join.push('ON ');
|
|
123
|
+
this._join.push(fromAlias);
|
|
124
|
+
// if (this._joinCache[tableFrom]) {
|
|
125
|
+
// this._join.push(this._joinCache[tableFrom]);
|
|
126
|
+
// } else {
|
|
127
|
+
// this._join.push(tableFrom);
|
|
128
|
+
// this._joinCache[tableFrom] = `${tableFrom}${joinObject.id ? `_${joinObject.id}` : ''}`;
|
|
129
|
+
// }
|
|
130
|
+
this._join.push('.');
|
|
131
|
+
this._join.push(joinObject.join.fromColumn.getColumnName());
|
|
132
|
+
this._join.push(' = ');
|
|
133
|
+
this._join.push(`${tableTo}${joinObject.id ? `_${joinObject.id}` : ''}`);
|
|
134
|
+
// this._join.push(toAlias);
|
|
135
|
+
this._join.push('.');
|
|
136
|
+
this._join.push(joinObject.join.toColumn.getColumnName());
|
|
137
|
+
}
|
|
138
|
+
});
|
|
139
|
+
|
|
140
|
+
return this;
|
|
141
|
+
};
|
|
142
|
+
|
|
143
|
+
public buildQuery = (): { query: string, values: Array<any> } => {
|
|
144
|
+
this._select.push(this._distinct.join(''));
|
|
145
|
+
this._select.push(this._fields.join(''));
|
|
146
|
+
this._select.push('\n');
|
|
147
|
+
this._select.push(this._from.join(''));
|
|
148
|
+
this._select.push('\n');
|
|
149
|
+
this._select.push(this._join.join(''));
|
|
150
|
+
if (this._join.length > 0) {
|
|
151
|
+
this._select.push('\n');
|
|
152
|
+
}
|
|
153
|
+
this._select.push(this._filters.join(''));
|
|
154
|
+
this._select.push('\n');
|
|
155
|
+
this._select.push(this._orderBy.join(''));
|
|
156
|
+
this._select.push('\n');
|
|
157
|
+
this._select.push(this._limit.join(''));
|
|
158
|
+
this._select.push('\n');
|
|
159
|
+
this._select.push(this._offset.join(''));
|
|
160
|
+
|
|
161
|
+
return { query: this._select.join(''), values: this._values };
|
|
162
|
+
};
|
|
163
|
+
}
|
|
@@ -0,0 +1,56 @@
|
|
|
1
|
+
import { AbstractTable } from '../../tables';
|
|
2
|
+
import { UpdateExpr } from '../requestBuilders/updates/updates';
|
|
3
|
+
import Expr from '../requestBuilders/where/where';
|
|
4
|
+
import Aggregator from './abstractAggregator';
|
|
5
|
+
|
|
6
|
+
export default class UpdateAggregator extends Aggregator {
|
|
7
|
+
private _updates: Array<string> = [];
|
|
8
|
+
private _filters: Array<string> = [];
|
|
9
|
+
private _from: Array<string> = [];
|
|
10
|
+
private _values: Array<any> = [];
|
|
11
|
+
private _update: Array<string> = ['UPDATE'];
|
|
12
|
+
|
|
13
|
+
public constructor(table: AbstractTable<any>) {
|
|
14
|
+
super(table);
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
public where = (filters: Expr): UpdateAggregator => {
|
|
18
|
+
if (filters) {
|
|
19
|
+
const currentPointerPosition = this._values.length > 0 ? this._values.length + 1 : undefined;
|
|
20
|
+
const filterQuery = filters.toQuery(currentPointerPosition);
|
|
21
|
+
|
|
22
|
+
this._filters.push('WHERE ');
|
|
23
|
+
this._filters.push(filterQuery.query);
|
|
24
|
+
|
|
25
|
+
this._values.push(...filterQuery.values);
|
|
26
|
+
}
|
|
27
|
+
return this;
|
|
28
|
+
};
|
|
29
|
+
|
|
30
|
+
public appendFrom = (tableName: string): UpdateAggregator => {
|
|
31
|
+
this._from.push(' ');
|
|
32
|
+
this._from.push(tableName);
|
|
33
|
+
return this;
|
|
34
|
+
};
|
|
35
|
+
|
|
36
|
+
public set = (updates: UpdateExpr): UpdateAggregator => {
|
|
37
|
+
const setQuery = updates.toQuery();
|
|
38
|
+
this._updates.push(`\nSET ${setQuery.query}`);
|
|
39
|
+
this._values.push(...setQuery.values);
|
|
40
|
+
return this;
|
|
41
|
+
};
|
|
42
|
+
|
|
43
|
+
public buildQuery = (): { query: string, values: Array<any> } => {
|
|
44
|
+
this._update.push(this._from.join(''));
|
|
45
|
+
this._update.push('\n');
|
|
46
|
+
this._update.push(this._updates.join(''));
|
|
47
|
+
this._update.push('\n');
|
|
48
|
+
this._update.push(this._filters.join(''));
|
|
49
|
+
this._update.push('\n');
|
|
50
|
+
this._update.push('RETURNING');
|
|
51
|
+
this._update.push('\n');
|
|
52
|
+
this._update.push(this._fields.join(''));
|
|
53
|
+
|
|
54
|
+
return { query: this._update.join(''), values: this._values };
|
|
55
|
+
};
|
|
56
|
+
}
|
|
@@ -0,0 +1,51 @@
|
|
|
1
|
+
import { AbstractColumn } from '../../columns/column';
|
|
2
|
+
import ColumnType from '../../columns/types/columnType';
|
|
3
|
+
import { ISession } from '../../db/session';
|
|
4
|
+
import BaseLogger from '../../logger/abstractLogger';
|
|
5
|
+
import { AbstractTable } from '../../tables';
|
|
6
|
+
import { ExtractModel } from '../../tables/inferTypes';
|
|
7
|
+
|
|
8
|
+
export default abstract class TableRequestBuilder<TTable extends AbstractTable<TTable>,
|
|
9
|
+
TPartial extends {[name: string]: AbstractColumn<ColumnType<any>, boolean, boolean, TTable>} = {}> {
|
|
10
|
+
protected _table: TTable;
|
|
11
|
+
protected _session: ISession;
|
|
12
|
+
protected _mappedServiceToDb: { [name in keyof ExtractModel<TTable>]
|
|
13
|
+
: AbstractColumn<ColumnType>; };
|
|
14
|
+
|
|
15
|
+
protected _columns: AbstractColumn<ColumnType>[];
|
|
16
|
+
protected _logger?: BaseLogger;
|
|
17
|
+
|
|
18
|
+
public constructor(table: AbstractTable<TTable>,
|
|
19
|
+
session: ISession,
|
|
20
|
+
mappedServiceToDb: { [name in keyof ExtractModel<TTable>]: AbstractColumn<ColumnType>; },
|
|
21
|
+
logger?: BaseLogger) {
|
|
22
|
+
this._mappedServiceToDb = mappedServiceToDb;
|
|
23
|
+
this._table = table as unknown as TTable;
|
|
24
|
+
this._session = session;
|
|
25
|
+
this._columns = Object.values(mappedServiceToDb);
|
|
26
|
+
this._logger = logger;
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
public all = async () => {
|
|
30
|
+
const res = await this._execute();
|
|
31
|
+
return res;
|
|
32
|
+
};
|
|
33
|
+
|
|
34
|
+
/**
|
|
35
|
+
* Current function will return an element only if response is of length 1
|
|
36
|
+
* If there are more or less than 1 element, will throw an Error
|
|
37
|
+
*/
|
|
38
|
+
public findOne = async () => {
|
|
39
|
+
const executionRes = await this._execute();
|
|
40
|
+
if (executionRes.length > 1) {
|
|
41
|
+
throw new Error('Request contains more than 1 element');
|
|
42
|
+
} else if (executionRes.length < 1) {
|
|
43
|
+
throw new Error('Request contains less than 1 element ');
|
|
44
|
+
} else {
|
|
45
|
+
return executionRes[0];
|
|
46
|
+
}
|
|
47
|
+
};
|
|
48
|
+
|
|
49
|
+
// eslint-disable-next-line max-len
|
|
50
|
+
protected abstract _execute(): Promise<Array<[keyof TPartial] extends [never] ? ExtractModel<TTable>: ExtractModel<TPartial>>>;
|
|
51
|
+
}
|
|
@@ -0,0 +1,59 @@
|
|
|
1
|
+
/* eslint-disable max-len */
|
|
2
|
+
import { AbstractColumn } from '../../columns/column';
|
|
3
|
+
import ColumnType from '../../columns/types/columnType';
|
|
4
|
+
import { ISession } from '../../db/session';
|
|
5
|
+
import BuilderError, { BuilderType } from '../../errors/builderError';
|
|
6
|
+
import BaseLogger from '../../logger/abstractLogger';
|
|
7
|
+
import QueryResponseMapper from '../../mappers/responseMapper';
|
|
8
|
+
import { AbstractTable } from '../../tables';
|
|
9
|
+
import { ExtractModel } from '../../tables/inferTypes';
|
|
10
|
+
import Delete from '../lowLvlBuilders/delets/delete';
|
|
11
|
+
import Expr from '../requestBuilders/where/where';
|
|
12
|
+
import TableRequestBuilder from './abstractRequestBuilder';
|
|
13
|
+
|
|
14
|
+
export default class DeleteTRB<TTable extends AbstractTable<TTable>, TPartial extends {[name: string]: AbstractColumn<ColumnType<any>, boolean, boolean, TTable>} = {}>
|
|
15
|
+
extends TableRequestBuilder<TTable, TPartial> {
|
|
16
|
+
private _filter: Expr;
|
|
17
|
+
|
|
18
|
+
public constructor(
|
|
19
|
+
table: AbstractTable<TTable>,
|
|
20
|
+
session: ISession,
|
|
21
|
+
mappedServiceToDb: { [name in keyof ExtractModel<TTable>]: AbstractColumn<ColumnType>; },
|
|
22
|
+
logger?: BaseLogger,
|
|
23
|
+
) {
|
|
24
|
+
super(table, session, mappedServiceToDb, logger);
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
public where = (expr: Expr): DeleteTRB<TTable> => {
|
|
28
|
+
this._filter = expr;
|
|
29
|
+
return this;
|
|
30
|
+
};
|
|
31
|
+
|
|
32
|
+
public execute = async () => {
|
|
33
|
+
await this._execute();
|
|
34
|
+
};
|
|
35
|
+
|
|
36
|
+
protected _execute = async (): Promise<Array<[keyof TPartial] extends [never] ? ExtractModel<TTable>: ExtractModel<TPartial>>> => {
|
|
37
|
+
const queryBuilder = Delete
|
|
38
|
+
.from(this._table)
|
|
39
|
+
.filteredBy(this._filter);
|
|
40
|
+
|
|
41
|
+
let query = '';
|
|
42
|
+
let values = [];
|
|
43
|
+
try {
|
|
44
|
+
const builderResult = queryBuilder.build();
|
|
45
|
+
query = builderResult.query;
|
|
46
|
+
values = builderResult.values;
|
|
47
|
+
} catch (e: any) {
|
|
48
|
+
throw new BuilderError(BuilderType.DELETE, this._table.tableName(),
|
|
49
|
+
this._columns, e, this._filter);
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
if (this._logger) {
|
|
53
|
+
this._logger.info(`Deleting from ${this._table.tableName()} using query:\n ${query}`);
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
const result = await this._session.execute(query, values);
|
|
57
|
+
return QueryResponseMapper.map(this._mappedServiceToDb, result) as Array<[keyof TPartial] extends [never] ? ExtractModel<TTable>: ExtractModel<TPartial>>;
|
|
58
|
+
};
|
|
59
|
+
}
|
|
@@ -0,0 +1,75 @@
|
|
|
1
|
+
/* eslint-disable max-len */
|
|
2
|
+
import { combine, set } from '..';
|
|
3
|
+
import { AbstractColumn } from '../../columns/column';
|
|
4
|
+
import ColumnType from '../../columns/types/columnType';
|
|
5
|
+
import { ISession } from '../../db/session';
|
|
6
|
+
import BuilderError, { BuilderType } from '../../errors/builderError';
|
|
7
|
+
import BaseLogger from '../../logger/abstractLogger';
|
|
8
|
+
import QueryResponseMapper from '../../mappers/responseMapper';
|
|
9
|
+
import { AbstractTable } from '../../tables';
|
|
10
|
+
import { ExtractModel, Indexing } from '../../tables/inferTypes';
|
|
11
|
+
import Insert from '../lowLvlBuilders/inserts/insert';
|
|
12
|
+
import { UpdateExpr } from '../requestBuilders/updates/updates';
|
|
13
|
+
import TableRequestBuilder from './abstractRequestBuilder';
|
|
14
|
+
|
|
15
|
+
export default class InsertTRB<TTable extends AbstractTable<TTable>, TPartial extends {[name: string]: AbstractColumn<ColumnType<any>, boolean, boolean, TTable>} = {}>
|
|
16
|
+
extends TableRequestBuilder<TTable, TPartial> {
|
|
17
|
+
private _values: ExtractModel<TTable>[];
|
|
18
|
+
private _onConflict: UpdateExpr;
|
|
19
|
+
private _onConflictField: Indexing;
|
|
20
|
+
|
|
21
|
+
public constructor(
|
|
22
|
+
values: ExtractModel<TTable>[],
|
|
23
|
+
session: ISession,
|
|
24
|
+
mappedServiceToDb: { [name in keyof ExtractModel<TTable>]: AbstractColumn<ColumnType>; },
|
|
25
|
+
table: AbstractTable<TTable>,
|
|
26
|
+
logger?: BaseLogger,
|
|
27
|
+
) {
|
|
28
|
+
super(table, session, mappedServiceToDb, logger);
|
|
29
|
+
this._values = values;
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
public execute = async () => {
|
|
33
|
+
await this._execute();
|
|
34
|
+
};
|
|
35
|
+
|
|
36
|
+
public onConflict = (
|
|
37
|
+
callback: (table: TTable) => Indexing,
|
|
38
|
+
update: Partial<ExtractModel<TTable>>,
|
|
39
|
+
): InsertTRB<TTable> => {
|
|
40
|
+
this._onConflictField = callback(this._table);
|
|
41
|
+
const updates: Array<UpdateExpr> = [];
|
|
42
|
+
Object.entries(update).forEach(([key, value]) => {
|
|
43
|
+
const column = this._mappedServiceToDb[key as keyof ExtractModel<TTable>];
|
|
44
|
+
updates.push(set(column, value as any));
|
|
45
|
+
});
|
|
46
|
+
this._onConflict = combine(updates);
|
|
47
|
+
return this;
|
|
48
|
+
};
|
|
49
|
+
|
|
50
|
+
protected _execute = async (): Promise<Array<[keyof TPartial] extends [never] ? ExtractModel<TTable>: ExtractModel<TPartial>>> => {
|
|
51
|
+
if (!this._values) throw Error('Values should be provided firestly\nExample: table.values().execute()');
|
|
52
|
+
|
|
53
|
+
const queryBuilder = Insert
|
|
54
|
+
.into(this._table)
|
|
55
|
+
.values(this._values)
|
|
56
|
+
.onConflict(this._onConflict, this._onConflictField);
|
|
57
|
+
|
|
58
|
+
let query = '';
|
|
59
|
+
let values = [];
|
|
60
|
+
try {
|
|
61
|
+
const builderResult = queryBuilder.build();
|
|
62
|
+
query = builderResult.query;
|
|
63
|
+
values = builderResult.values;
|
|
64
|
+
} catch (e: any) {
|
|
65
|
+
throw new BuilderError(BuilderType.INSERT, this._table.tableName(), this._columns, e);
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
if (this._logger) {
|
|
69
|
+
this._logger.info(`Inserting to ${this._table.tableName()} using query:\n ${query}\n${values}`);
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
const result = await this._session.execute(query, values);
|
|
73
|
+
return QueryResponseMapper.map(this._mappedServiceToDb, result) as Array<[keyof TPartial] extends [never] ? ExtractModel<TTable>: ExtractModel<TPartial>>;
|
|
74
|
+
};
|
|
75
|
+
}
|