pg-mvc-service 2.0.129 → 2.1.1

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.
Files changed (97) hide show
  1. package/dist/PoolManager.d.ts +7 -0
  2. package/dist/PoolManager.d.ts.map +1 -0
  3. package/dist/Service.d.ts +82 -0
  4. package/dist/Service.d.ts.map +1 -0
  5. package/dist/Service.js +40 -23
  6. package/dist/Utils/DateTimeUtil.d.ts +58 -0
  7. package/dist/Utils/DateTimeUtil.d.ts.map +1 -0
  8. package/dist/Utils/NumberUtil.d.ts +10 -0
  9. package/dist/Utils/NumberUtil.d.ts.map +1 -0
  10. package/dist/Utils/StringUtil.d.ts +16 -0
  11. package/dist/Utils/StringUtil.d.ts.map +1 -0
  12. package/dist/clients/AwsS3Client.d.ts +35 -0
  13. package/dist/clients/AwsS3Client.d.ts.map +1 -0
  14. package/dist/clients/Base64Client.d.ts +31 -0
  15. package/dist/clients/Base64Client.d.ts.map +1 -0
  16. package/dist/clients/EncryptClient.d.ts +18 -0
  17. package/dist/clients/EncryptClient.d.ts.map +1 -0
  18. package/dist/clients/StringClient.d.ts +6 -0
  19. package/dist/clients/StringClient.d.ts.map +1 -0
  20. package/dist/cron/BaseCron.d.ts +35 -0
  21. package/dist/cron/BaseCron.d.ts.map +1 -0
  22. package/dist/cron/CronExecuter.d.ts +2 -0
  23. package/dist/cron/CronExecuter.d.ts.map +1 -0
  24. package/dist/cron/CronType.d.ts +6 -0
  25. package/dist/cron/CronType.d.ts.map +1 -0
  26. package/dist/documents/Swagger.d.ts +10 -0
  27. package/dist/documents/Swagger.d.ts.map +1 -0
  28. package/dist/exceptions/Exception.d.ts +31 -0
  29. package/dist/exceptions/Exception.d.ts.map +1 -0
  30. package/{src/index.ts → dist/index.d.ts} +2 -6
  31. package/dist/index.d.ts.map +1 -0
  32. package/dist/models/ExpressionClient.d.ts +12 -0
  33. package/dist/models/ExpressionClient.d.ts.map +1 -0
  34. package/dist/models/MigrateDatabase.d.ts +19 -0
  35. package/dist/models/MigrateDatabase.d.ts.map +1 -0
  36. package/dist/models/MigrateRollback.d.ts +18 -0
  37. package/dist/models/MigrateRollback.d.ts.map +1 -0
  38. package/dist/models/MigrateTable.d.ts +13 -0
  39. package/dist/models/MigrateTable.d.ts.map +1 -0
  40. package/dist/models/SqlUtils/SelectExpression.d.ts +31 -0
  41. package/dist/models/SqlUtils/SelectExpression.d.ts.map +1 -0
  42. package/dist/models/SqlUtils/UpdateExpression.d.ts +8 -0
  43. package/dist/models/SqlUtils/UpdateExpression.d.ts.map +1 -0
  44. package/dist/models/SqlUtils/ValidateValueUtil.d.ts +19 -0
  45. package/dist/models/SqlUtils/ValidateValueUtil.d.ts.map +1 -0
  46. package/dist/models/SqlUtils/WhereExpression.d.ts +30 -0
  47. package/dist/models/SqlUtils/WhereExpression.d.ts.map +1 -0
  48. package/dist/models/TableDoc.d.ts +3 -0
  49. package/dist/models/TableDoc.d.ts.map +1 -0
  50. package/dist/models/TableModel.d.ts +196 -0
  51. package/dist/models/TableModel.d.ts.map +1 -0
  52. package/dist/models/Type.d.ts +64 -0
  53. package/dist/models/Type.d.ts.map +1 -0
  54. package/dist/models/Utils/MessageUtil.d.ts +7 -0
  55. package/dist/models/Utils/MessageUtil.d.ts.map +1 -0
  56. package/dist/models/ValidateClient.d.ts +27 -0
  57. package/dist/models/ValidateClient.d.ts.map +1 -0
  58. package/dist/reqestResponse/ReqResType.d.ts +113 -0
  59. package/dist/reqestResponse/ReqResType.d.ts.map +1 -0
  60. package/dist/reqestResponse/RequestType.d.ts +247 -0
  61. package/dist/reqestResponse/RequestType.d.ts.map +1 -0
  62. package/dist/reqestResponse/RequestType.js +218 -173
  63. package/dist/reqestResponse/ResponseType.d.ts +85 -0
  64. package/dist/reqestResponse/ResponseType.d.ts.map +1 -0
  65. package/package.json +8 -1
  66. package/index.d.ts +0 -192
  67. package/src/PoolManager.ts +0 -48
  68. package/src/Service.ts +0 -284
  69. package/src/Utils/DateTimeUtil.ts +0 -146
  70. package/src/Utils/NumberUtil.ts +0 -23
  71. package/src/Utils/StringUtil.ts +0 -33
  72. package/src/clients/AwsS3Client.ts +0 -310
  73. package/src/clients/Base64Client.ts +0 -305
  74. package/src/clients/EncryptClient.ts +0 -100
  75. package/src/clients/StringClient.ts +0 -19
  76. package/src/cron/BaseCron.ts +0 -122
  77. package/src/cron/CronExecuter.ts +0 -34
  78. package/src/cron/CronType.ts +0 -25
  79. package/src/documents/Swagger.ts +0 -106
  80. package/src/exceptions/Exception.ts +0 -72
  81. package/src/models/ExpressionClient.ts +0 -72
  82. package/src/models/MigrateDatabase.ts +0 -135
  83. package/src/models/MigrateRollback.ts +0 -151
  84. package/src/models/MigrateTable.ts +0 -56
  85. package/src/models/SqlUtils/SelectExpression.ts +0 -102
  86. package/src/models/SqlUtils/UpdateExpression.ts +0 -29
  87. package/src/models/SqlUtils/ValidateValueUtil.ts +0 -354
  88. package/src/models/SqlUtils/WhereExpression.ts +0 -455
  89. package/src/models/TableDoc.ts +0 -372
  90. package/src/models/TableModel.ts +0 -749
  91. package/src/models/Type.ts +0 -62
  92. package/src/models/Utils/MessageUtil.ts +0 -60
  93. package/src/models/ValidateClient.ts +0 -182
  94. package/src/reqestResponse/ReqResType.ts +0 -241
  95. package/src/reqestResponse/RequestType.ts +0 -1588
  96. package/src/reqestResponse/ResponseType.ts +0 -549
  97. package/tsconfig.json +0 -14
@@ -1,749 +0,0 @@
1
- import { Pool, PoolClient } from 'pg';
2
- import { TAggregateFuncType, TColumn, TColumnArrayType, TColumnDetail, TColumnInfo, TColumnType, TKeyFormat, TNestedCondition, TOperator, TQuery, TSelectExpression, TSortKeyword } from "./Type";
3
- import ValidateValueUtil from './SqlUtils/ValidateValueUtil';
4
- import SelectExpression from './SqlUtils/SelectExpression';
5
- import { WhereExpression } from './SqlUtils/WhereExpression';
6
- import ValidateClient from './ValidateClient';
7
- import { DbConflictException, NotFoundException, UnprocessableException } from '../exceptions/Exception';
8
- import ExpressionClient from './ExpressionClient';
9
- import UpdateExpression from './SqlUtils/UpdateExpression';
10
- import MessageUtil, { TOptionErrorMessage } from './Utils/MessageUtil';
11
-
12
- export class TableModel {
13
-
14
- protected readonly id: string = "";
15
- get Id(): string { return this.id; }
16
- protected readonly dbName: string = "default";
17
- get DbName(): string { return this.dbName; }
18
- protected readonly tableName: string = "";
19
- get TableName(): string {
20
- if (this.tableName === "") {
21
- throw new Error("Please set the tableName for TableModel.");
22
- }
23
- return this.tableName;
24
- }
25
- protected readonly tableDescription: string = "";
26
- get TableDescription(): string { return this.tableDescription; }
27
- protected readonly comment: string = "";
28
- get Comment(): string { return this.comment; }
29
- protected readonly columns: { [key: string]: TColumn } = {};
30
- get Columns(): { [key: string]: TColumn } {
31
- if (Object.keys(this.columns).length === 0) {
32
- throw new Error("Please set the columns for TableModel.");
33
- }
34
- return this.columns;
35
- }
36
- public getColumn(key: string): TColumnDetail {
37
- if (key in this.Columns === false) {
38
- throw new Error(`${this.TableName} does not contain ${key}.`);
39
- }
40
-
41
- return {
42
- ...this.Columns[key],
43
- columnName: key,
44
- tableName: this.TableName,
45
- expression: `"${this.TableAlias}".${key}`
46
- };
47
- }
48
- protected readonly references: Array<{table: string, columns: Array<{target: string, ref: string}>}> = [];
49
- get References(): Array<{table: string, columns: Array<{target: string, ref: string}>}> { return this.references; }
50
- public GetReferences(columnName: string): Array<{table: string, columns: Array<{target: string, ref: string}>}> {
51
- const _ = this.getColumn(columnName); // 存在チェック用
52
- const references: Array<{table: string, columns: Array<{target: string, ref: string}>}> = [];
53
- for (const ref of this.References) {
54
- if (ref.columns.filter(col => col.target === columnName).length > 0) {
55
- references.push(ref);
56
- }
57
- }
58
-
59
- return references;
60
- }
61
-
62
- protected readonly tableAlias?: string;
63
- get TableAlias(): string {
64
- return this.tableAlias === undefined ? this.TableName : this.tableAlias;
65
- }
66
-
67
- public IsOutputLog: boolean = false;
68
- public SortKeyword: TSortKeyword = 'asc';
69
- public Offset?: number;
70
- public Limit?: number;
71
-
72
- private selectExpressions: Array<string> = [];
73
- private joinConditions: Array<{
74
- type: 'inner' | 'left' | 'full',
75
- model: TableModel,
76
- conditions: Array<TNestedCondition>
77
- }> = [];
78
- private whereExpressions: Array<string> = [];
79
- private groupExpression: Array<string> = [];
80
- private sortExpression: Array<string> = [];
81
- private vars: Array<any> = [];
82
-
83
- private get createSqlFromJoinWhere(): string {
84
- let sql = ` FROM ${this.TableName} as "${this.TableAlias}"`;
85
-
86
- for (const join of this.joinConditions) {
87
- const joins = {
88
- inner: ' INNER JOIN',
89
- left: ' LEFT OUTER JOIN',
90
- full: ' FULL OUTER JOIN',
91
- }
92
- sql += joins[join.type];
93
- sql += ` ${join.model.TableName} as "${join.model.TableAlias}" ON `;
94
- const query = WhereExpression.createCondition(join.conditions, this, this.vars.length + 1);
95
- sql += query.expression;
96
- if (query.vars !== undefined) {
97
- this.vars = [...this.vars, ...query.vars]
98
- }
99
- }
100
-
101
- if (this.whereExpressions.length > 0) {
102
- sql += " WHERE " + this.whereExpressions.join(" AND ");
103
- }
104
-
105
- if (this.groupExpression.length > 0) {
106
- sql += ` GROUP BY ${this.groupExpression.join(',')}`;
107
- }
108
-
109
- return sql;
110
- }
111
- private get createSqlFromJoinWhereSortLimit(): string {
112
- let sql = this.createSqlFromJoinWhere;
113
-
114
- if (this.sortExpression.length > 0) {
115
- sql += ` ORDER BY ${this.sortExpression.join(",")}`;
116
- }
117
-
118
- if (this.Limit !== undefined) {
119
- sql += ` LIMIT ${this.Limit}`;
120
- }
121
- if (this.Offset !== undefined) {
122
- sql += ` OFFSET ${this.Offset}`;
123
- }
124
- return sql;
125
- }
126
-
127
- private client: PoolClient | Pool;
128
- get Client(): PoolClient | Pool {
129
- return this.client;
130
- }
131
-
132
- constructor(client: Pool | PoolClient, tableAlias?: string) {
133
- this.client = client;
134
- if (tableAlias !== undefined && tableAlias.trim() !== '') {
135
- this.tableAlias = tableAlias;
136
- }
137
- }
138
-
139
- public find<T = {[key: string]: any}>(pk: {[key: string]: any}): Promise<T | null>;
140
- public find<T = {[key: string]: any}>(id: string | number | boolean): Promise<T | null>;
141
- public find<T = {[key: string]: any}>(pk: {[key: string]: any}, selectColumns: Array<string> | "*" | null): Promise<T | null>;
142
- public find<T = {[key: string]: any}>(id: string | number | boolean, selectColumns: Array<string> | "*" | null): Promise<T | null>;
143
- public find<T = {[key: string]: any}>(pk: {[key: string]: any}, selectColumns: Array<string> | "*" | null, selectExpressions: Array<TSelectExpression> | null): Promise<T | null>;
144
- public find<T = {[key: string]: any}>(id: string | number | boolean, selectColumns: Array<string> | "*" | null, selectExpressions: Array<TSelectExpression> | null): Promise<T | null>;
145
- public find<T = {[key: string]: any}>(pk: {[key: string]: any}, selectColumns: Array<string> | "*" | null, selectExpressions: Array<TSelectExpression> | null, keyFormat: TKeyFormat): Promise<T | null>;
146
- public find<T = {[key: string]: any}>(id: string | number | boolean, selectColumns: Array<string> | "*" | null, selectExpressions: Array<TSelectExpression> | null, keyFormat: TKeyFormat): Promise<T | null>;
147
- public async find<T = {[key: string]: any}>(
148
- pkOrId: string | number | boolean | {[key: string]: any},
149
- selectColumns: Array<string> | "*" | null = "*",
150
- selectExpressions: Array<TSelectExpression> | null = null,
151
- keyFormat: TKeyFormat = 'snake'): Promise<T | null> {
152
-
153
- let selects: Array<string> = [];
154
- if (selectColumns == "*") {
155
- for (const key of Object.keys(this.Columns)) {
156
- selects.push(SelectExpression.create({model: this, name: key}, null, null, keyFormat));
157
- }
158
- } else if (selectColumns != null) {
159
- for (const key of selectColumns) {
160
- selects.push(SelectExpression.create({model: this, name: key}, null, null, keyFormat));
161
- }
162
- }
163
-
164
- if (selectExpressions != null) {
165
- for (const expression of selectExpressions) {
166
- selects.push(`${expression.expression} as "${expression.alias}"`);
167
- }
168
- }
169
-
170
- let query: TQuery;
171
- if (typeof pkOrId === 'string' || typeof pkOrId === 'number' || typeof pkOrId === 'boolean') {
172
- ValidateValueUtil.validateId(this.Columns, pkOrId);
173
- query = WhereExpression.createConditionPk(this, {id: pkOrId});
174
- } else {
175
- query = WhereExpression.createConditionPk(this, pkOrId);
176
- }
177
-
178
- const sql = `SELECT ${selects.join(',')} FROM ${this.TableName} WHERE ${query.expression}`;
179
- let datas = await this.executeQuery(sql, query.vars);
180
-
181
- return datas.rowCount == 0 ? null : datas.rows[0] as T;
182
- }
183
-
184
- public select(): void;
185
- public select(columls: Array<string | {name: string, alias?: string, func?: TAggregateFuncType}> | '*'): void;
186
- public select(columls: Array<string | {name: string, alias?: string, func?: TAggregateFuncType}> | '*', model: TableModel): void;
187
- public select(columls: Array<string | {name: string, alias?: string, func?: TAggregateFuncType}> | '*', keyFormat: TKeyFormat): void;
188
- public select(columls: Array<string | {name: string, alias?: string, func?: TAggregateFuncType}> | '*', model: TableModel, keyFormat: TKeyFormat): void;
189
- public select(expression: string, alias: string): void;
190
- public select(param1: Array<string | {name: string, alias?: string, func?: TAggregateFuncType}> | "*" | string = "*", param2?: TableModel | string | TKeyFormat, param3?: TKeyFormat) {
191
- if (param1 === "*") {
192
- let model: TableModel = this;
193
- let keyFormat: TKeyFormat = 'snake';
194
- if (param2 instanceof TableModel) {
195
- model = param2;
196
- if (param3 === 'snake' || param3 === 'lowerCamel') {
197
- keyFormat = param3;
198
- }
199
- } else if (param2 === 'snake' || param2 === 'lowerCamel') {
200
- keyFormat = param2;
201
- }
202
-
203
- for (const key of Object.keys(model.Columns)) {
204
- this.selectExpressions.push(SelectExpression.create({model: model, name: key}, null, null, keyFormat));
205
- }
206
- return;
207
- }
208
-
209
- if (Array.isArray(param1)) {
210
- let model: TableModel = this;
211
- let keyFormat: TKeyFormat = 'snake';
212
- if (param2 instanceof TableModel) {
213
- model = param2;
214
- if (param3 === 'snake' || param3 === 'lowerCamel') {
215
- keyFormat = param3;
216
- }
217
- } else if (param2 === 'snake' || param2 === 'lowerCamel') {
218
- keyFormat = param2;
219
- }
220
-
221
- for (const key of param1) {
222
- if (typeof key === 'string') {
223
- this.selectExpressions.push(SelectExpression.create({model: model, name: key}, null, null, keyFormat));
224
- } else {
225
- this.selectExpressions.push(SelectExpression.create({model: model, name: key.name}, key.func ?? null, key.alias ?? null, keyFormat));
226
- }
227
- }
228
- return;
229
- }
230
-
231
- if (typeof param1 === 'string') {
232
- const expression = param1;
233
- if (typeof param2 !== 'string' || param2.trim() === '') {
234
- throw new Error('If the first argument is a string, the second argument must be a non-empty string.');
235
- }
236
- const alias = param2;
237
- this.selectExpressions.push(`(${expression}) as "${alias}"`);
238
- return;
239
- }
240
- }
241
-
242
- /**
243
- * 指定されたカラム情報がNULLの場合に、指定された値に変換して選択します。
244
- *
245
- * @param columnInfo カラム情報。文字列または{name: string, model: TableModel}のオブジェクト。
246
- * @param toValue NULLの場合に変換する値。
247
- * @param alias 結果セットで使用するエイリアス名。
248
- */
249
- public selectNullToValue(columnInfo: string | {name: string, model: TableModel}, toValue: any, alias: string) {
250
- this.vars.push(toValue);
251
-
252
- if (typeof columnInfo === 'string') {
253
- columnInfo = {name: columnInfo, model: this}
254
- }
255
-
256
- const column = columnInfo.model.getColumn(columnInfo.name);
257
- this.selectExpressions.push(`COALESCE(${column.expression}, $${this.vars.length}) as "${alias}"`)
258
- }
259
-
260
-
261
- /**
262
- * 指定されたカラムを特定のフォーマットの日付情報に変換し、SELECT句で使用します。
263
- *
264
- * @param column カラム情報。文字列または{name: string, model: TableModel}のオブジェクト。
265
- * @param to 変換先のフォーマットを指定します。'date'、'time'、'datetime'のいずれか。
266
- * @param alias 結果セットで使用するエイリアス名。
267
- */
268
- public selectDateAsFormat(column: string | {name: string, model: TableModel}, to: 'date' | 'time' | 'datetime', alias: string) {
269
- column = typeof column === 'string' ? {name: column, model: this} : column;
270
- const columnInfo = column.model.getColumn(column.name);
271
-
272
- if (['date', 'time', 'timestamp'].includes(columnInfo.type) === false) {
273
- throw new Error('The first argument of the selectDateAsFormat method must specify a column of type date, time, or timestamp.');
274
- }
275
- this.selectExpressions.push(`${SelectExpression.createDateTime(column, to)} as "${alias}"`);
276
- }
277
-
278
- /**
279
- * 指定された条件に基づいてテーブルを結合します。
280
- * @param joinType 結合の種類を指定します
281
- * @param joinBaseModel 結合する対象のBaseModelインスタンスを指定します。
282
- * @param conditions 結合条件を指定します。条件はオブジェクトまたは文字列で指定できます。
283
- */
284
- public join(joinType: 'left' | 'inner' | 'full', joinModel: TableModel, conditions: Array<TNestedCondition>): void {
285
- this.joinConditions.push({type: joinType, model: joinModel, conditions: conditions});
286
- }
287
-
288
- public where(expression: string): void;
289
- public where(expression: string, vars: Array<any>): void;
290
- public where(conditions: Array<TNestedCondition>): void;
291
- public where(left: string, operator: TOperator, right: TColumnInfo | any): void;
292
- public where(left: TColumnInfo, operator: TOperator, right: TColumnInfo | any): void;
293
- public where(param1: string | TColumnInfo | Array<TNestedCondition>, param2?: Array<any> | TOperator, right?: TColumnInfo | any): void {
294
- if (typeof param1 === 'string') {
295
- if (param2 === undefined || right === undefined || Array.isArray(param2)) {
296
- if (Array.isArray(param2)) {
297
- let expression = param1;
298
- const startIndex = this.vars.length + 1;
299
- expression = expression.replace(/\$(\d+)/g, (match, num) => {
300
- const originalNum = parseInt(num, 10);
301
- return `$${startIndex + originalNum - 1}`;
302
- });
303
- this.vars = [...this.vars, ...param2];
304
- this.whereExpressions.push(expression);
305
- } else {
306
- this.whereExpressions.push(param1);
307
- }
308
- } else {
309
- const query = WhereExpression.create({model: this, name: param1}, param2, right, this.vars.length + 1);
310
- this.whereExpressions.push(query.expression);
311
- if (query.vars !== undefined) {
312
- this.vars = [...this.vars, ...query.vars];
313
- }
314
- }
315
- return;
316
- }
317
-
318
- if ('model' in param1 && 'name' in param1) {
319
- if (param2 === undefined || right === undefined || Array.isArray(param2)) {
320
- throw new Error(`If left is TColumnInfo, please set operator and right. Do not pass an array to operator.`);
321
- } else {
322
- const query = WhereExpression.create(param1, param2, right, this.vars.length + 1);
323
- this.whereExpressions.push(query.expression);
324
- if (query.vars !== undefined) {
325
- this.vars = [...this.vars, ...query.vars];
326
- }
327
- }
328
- return;
329
- }
330
-
331
- if (Array.isArray(param1)) {
332
- const query = WhereExpression.createCondition(param1, this, this.vars.length + 1);
333
- this.whereExpressions.push(query.expression);
334
- if (query.vars !== undefined) {
335
- this.vars = [...this.vars, ...query.vars];
336
- }
337
- }
338
- }
339
-
340
- public groupBy(column: string | TColumnInfo): void {
341
- if (typeof column === 'string') {
342
- column = {model: this, name: column};
343
- }
344
- this.groupExpression.push(column.model.getColumn(column.name).expression);
345
- }
346
-
347
- public orderBy(column: string | TColumnInfo, sortKeyword: TSortKeyword) {
348
- if (typeof column === 'string') {
349
- column = { model: this, name: column };
350
- }
351
- this.sortExpression.push(`${column.model.getColumn(column.name).expression} ${sortKeyword}`);
352
- }
353
-
354
- public orderByList(column: string | TColumnInfo, list: Array<string | number | boolean | null>, sortKeyword: TSortKeyword): void {
355
- if (list.length === 0) {
356
- return;
357
- }
358
-
359
- if (typeof(column) == 'string') {
360
- column = {model: this, name: column};;
361
- }
362
- const columnInfo = column.model.getColumn(column.name);
363
-
364
- const orderConditions: Array<string> = [];
365
- for (let i = 0;i < list.length;i++) {
366
- const value = list[i];
367
- if (value === null) {
368
- if (columnInfo.attribute === 'nullable') {
369
- orderConditions.push(`WHEN ${columnInfo.expression} is null THEN ${i}`);
370
- continue;
371
- }
372
- throw new Error(`${this.TableName}.${columnInfo.columnName} is a non-nullable column.`);
373
- }
374
-
375
- ValidateValueUtil.validateValue(columnInfo, value);
376
- switch (columnInfo.type) {
377
- case 'integer':
378
- orderConditions.push(`WHEN ${columnInfo.expression} = ${value} THEN ${i}`);
379
- break;
380
- case 'uuid':
381
- case 'string':
382
- orderConditions.push(`WHEN ${columnInfo.expression} = '${value}' THEN ${i}`);
383
- break;
384
- case 'bool':
385
- const boolValue = value === true || value === 'true' || value === 1;
386
- orderConditions.push(`WHEN ${columnInfo.expression} = ${boolValue} THEN ${i}`);
387
- break;
388
- }
389
- }
390
-
391
- if (orderConditions.length === 0) {
392
- return;
393
- }
394
-
395
- this.sortExpression.push(`CASE ${orderConditions.join(' ')} ELSE ${list.length} END ${sortKeyword}`);
396
- }
397
-
398
- public orderBySentence(query: string, sortKeyword: TSortKeyword): void {
399
- this.sortExpression.push(`${query} ${sortKeyword}`);
400
- }
401
-
402
- public async executeSelect<T = {[key: string]: any}>(): Promise<Array<T>> {
403
- if (this.selectExpressions.length === 0) {
404
- this.select();
405
- }
406
-
407
- let sql = ` SELECT ${this.selectExpressions.join(",")} ${this.createSqlFromJoinWhereSortLimit}`;
408
- let data = await this.executeQuery(sql, this.vars);
409
- return data.rows as Array<T>;
410
- }
411
-
412
- public async executeSelectForPage<T = any>(pageCount: number, currentPage: number): Promise<{ datas: Array<T>, totalCount: number, lastPage: number, isLastData: boolean}> {
413
- if (this.selectExpressions.length == 0) {
414
- this.select();
415
- }
416
-
417
- this.Limit = pageCount;
418
- this.Offset = (currentPage - 1) * pageCount;
419
-
420
-
421
- const tempVars = [...this.vars];
422
- const tempWhereExpression = [...this.whereExpressions];
423
- const tempJoinConditions = [...this.joinConditions];
424
-
425
- let sql = ` SELECT ${this.selectExpressions.join(",")} ${this.createSqlFromJoinWhereSortLimit}`;
426
- const data = await this.executeQuery(sql, this.vars);
427
-
428
- this.vars = tempVars;
429
- this.whereExpressions = tempWhereExpression;
430
- this.joinConditions = tempJoinConditions;
431
- let countSql = ` SELECT COUNT(*) as "count" ${this.createSqlFromJoinWhere}`;
432
-
433
- const countData = await this.executeQuery(countSql, this.vars);
434
-
435
- const totalCount = Number(countData.rows[0].count);
436
- const lastPage = Math.ceil(Number(countData.rows[0].count) / pageCount);
437
- return {
438
- datas: data.rows as Array<T>,
439
- totalCount: totalCount,
440
- lastPage: lastPage,
441
- isLastData: currentPage >= lastPage
442
- };
443
- }
444
-
445
- protected readonly errorMessages: TOptionErrorMessage =
446
- process.env.TZ === 'Asia/Tokyo' ? MessageUtil.optionErrorMessageJapan : MessageUtil.optionErrorMessageEnglish;
447
-
448
- private throwException(code: string, type: TColumnType | TColumnArrayType | 'length' | 'null' | 'notInput' | 'fk', columnName: string, value: any): never {
449
- const column = this.getColumn(columnName);
450
-
451
- let message = this.errorMessages[type];
452
-
453
- const name = (column.alias === undefined || column.alias === '') ? columnName : column.alias;
454
- message = message.replace('{name}', name);
455
- if (message.includes("{length}") && (column.type === 'string' || column.type === 'string[]')) {
456
- message = message.replace('{length}', (column.length ?? '未設定').toString());
457
- }
458
-
459
- this.throwUnprocessableException(code, message);
460
- }
461
-
462
- protected throwDbCoflictException(code: string, message: string): never {
463
- throw new DbConflictException(`${this.id}-${code}`, message);
464
- }
465
-
466
- protected throwUnprocessableException(code: string, message: string): never {
467
- throw new UnprocessableException(`${this.id}-${code}`, message);
468
- }
469
-
470
- protected throwNotFoundException(code: string, message: string): never {
471
- throw new NotFoundException(`${this.id}-${code}`, message);
472
- }
473
-
474
- protected async validateOptions(options: {[key: string]: any}, isInsert: boolean, pkOrId?: string | number | boolean | {[key: string]: any}): Promise<void> {
475
- if (Object.keys(options).length === 0) {
476
- throw new Error('At least one key-value pair is required in options.');
477
- }
478
-
479
- for (const [key, value] of Object.entries(options)) {
480
- const column = this.getColumn(key);
481
- if (isInsert === false && column.attribute === 'primary') {
482
- throw new Error(`${this.TableName}.${key} cannot be modified because it is a primary key.`);
483
- }
484
-
485
- if (value === null) {
486
- if (column.attribute === 'nullable') {
487
- continue;
488
- }
489
- this.throwException("001", "null", key, value);
490
- }
491
-
492
- if (ValidateValueUtil.isErrorValue(column.type, value)) {
493
- this.throwException("002", column.type, key, value);
494
- }
495
-
496
- if (column.type === 'string') {
497
- if (Number.isInteger(column.length) === false) {
498
- throw new Error(`For strings, please specify the length of the column.(column: ${column.columnName})`);
499
- }
500
-
501
- if (value.toString().length > column.length) {
502
- this.throwException("003", "length", key, value);
503
- }
504
- } else if (column.type === 'string[]') {
505
- if (Number.isInteger(column.length) === false) {
506
- throw new Error(`For strings, please specify the length of the column.(column: ${column.columnName})`);
507
- }
508
-
509
- // ValidateValueUtil.isErrorValue(column.type, value)で型チェックしてるのでas []にしている
510
- for (const v of value as Array<string | number | boolean>) {
511
- if (v.toString().length > column.length) {
512
- this.throwException("004", "length", key, value);
513
- }
514
- }
515
- }
516
- }
517
-
518
- // 外部キー制約チェック
519
- if (isInsert) {
520
- for (const key in this.Columns) {
521
- const column = this.getColumn(key);
522
- const name = (column.alias === undefined || column.alias === '') ? key : column.alias;
523
- if (options[key] === undefined || options[key] === null) {
524
- // Null許容されていないカラムにNULLを入れようとしているか?
525
- if (column.attribute === "primary" || column.attribute === "noDefault") {
526
- this.throwException("005", "notInput", key, options[key]);
527
- }
528
- }
529
- }
530
-
531
- for (const ref of this.References) {
532
- const refValues = ref.columns.map(col => options[col.target]);
533
- // 全ての値がnullの場合はスキップ
534
- if (refValues.every(value => value === null || value === undefined)) {
535
- continue;
536
- }
537
-
538
- // 一部の値がnullの場合はエラー
539
- if (refValues.some(value => value === null || value === undefined)) {
540
- const name = ref.columns.map(col => this.getColumn(col.target).alias ?? this.getColumn(col.target).columnName).join(',');
541
- this.throwUnprocessableException("006", this.errorMessages.null.replace('{name}', name));
542
- }
543
-
544
- let refIndex = 1;
545
- const sql = `SELECT COUNT(*) as count FROM ${ref.table} WHERE ${ref.columns.map(col => `${col.ref} = $${refIndex++}`).join(" AND ")}`;
546
- const datas = await this.clientQuery(sql, refValues);
547
- if (datas.rows[0].count == "0") {
548
- const name = ref.columns.map(col => this.getColumn(col.target).alias ?? this.getColumn(col.target).columnName).join(',');
549
- this.throwUnprocessableException("007", this.errorMessages.fk.replace('{name}', name))
550
- }
551
- }
552
- }
553
- }
554
-
555
- public async insert(options: {[key: string]: any}) : Promise<void> {
556
- await this.validateOptions(options, true);
557
-
558
- const columns: Array<string> = [];
559
- const vars: Array<any> = [];
560
-
561
- for (const [key, value] of Object.entries(options)) {
562
- if (value === undefined) {
563
- throw new Error(`The insert option ${key} is undefined.`);
564
- }
565
-
566
- columns.push(key);
567
- vars.push(value)
568
- }
569
-
570
- const params = vars.map((_, index) => `$${index + 1}`);
571
- const sql = `INSERT INTO ${this.TableName} (${columns.join(",")}) VALUES (${params.join(",")});`;
572
- await this.executeQuery(sql, vars);
573
- }
574
-
575
- public async update(pkOrId: string | number | boolean | {[key: string]: any}, options: {[key: string]: any}) : Promise<void> {
576
- await this.validateOptions(options, false, pkOrId);
577
-
578
- const updateSetQuery = UpdateExpression.createUpdateSet(this, options);
579
- let whereQuery: TQuery;
580
- if (typeof pkOrId === 'string' || typeof pkOrId === 'number' || typeof pkOrId === 'boolean') {
581
- ValidateValueUtil.validateId(this.Columns, pkOrId);
582
- whereQuery = WhereExpression.createConditionPk(this, {id: pkOrId}, updateSetQuery.vars);
583
- } else {
584
- whereQuery = WhereExpression.createConditionPk(this, pkOrId, updateSetQuery.vars);
585
- }
586
-
587
- const sql = updateSetQuery.expression + ' WHERE ' + whereQuery.expression;
588
- const data = await this.executeQuery(sql, whereQuery.vars);
589
- if (data.rowCount !== 1) {
590
- this.throwUnprocessableException("201", this.errorMessages.find.replace('{pks}', (whereQuery.vars ?? []).join(',')));
591
- }
592
- }
593
-
594
- public async delete(pkOrId: string | number | boolean | {[key: string]: any}) : Promise<void> {
595
- let whereQuery: TQuery;
596
- if (typeof pkOrId === 'string' || typeof pkOrId === 'number' || typeof pkOrId === 'boolean') {
597
- ValidateValueUtil.validateId(this.Columns, pkOrId);
598
- whereQuery = WhereExpression.createConditionPk(this, {id: pkOrId});
599
- } else {
600
- whereQuery = WhereExpression.createConditionPk(this, pkOrId);
601
- }
602
-
603
- const sql = `DELETE FROM ${this.TableName} WHERE ${whereQuery.expression}`;
604
- const data = await this.executeQuery(sql, whereQuery.vars);
605
- if (data.rowCount !== 1) {
606
- this.throwUnprocessableException("301", this.errorMessages.find.replace('{pks}', (whereQuery.vars ?? []).join(',')));
607
- }
608
- }
609
-
610
- public async executeUpdate(options: {[key: string]: any}) : Promise<number> {
611
- await this.validateOptions(options, false);
612
-
613
- const updateExpressions: Array<string> = [];
614
- for (const [key, value] of Object.entries(options)) {
615
- const column = this.getColumn(key);
616
- ValidateValueUtil.validateValue(column, value);
617
- this.vars.push(value);
618
- updateExpressions.push(`${key} = $${this.vars.length}`)
619
- }
620
-
621
- let sql = `UPDATE ${this.TableName} "${this.TableAlias}" SET ${updateExpressions.join(',')} `;
622
-
623
- if (this.joinConditions.length > 0) {
624
- const tables: Array<string> = [];
625
- for (const join of this.joinConditions) {
626
- tables.push(`${join.model.TableName} as "${join.model.TableAlias}"`);
627
-
628
- const query = WhereExpression.createCondition(join.conditions, this, this.vars.length + 1);
629
- this.whereExpressions.push(query.expression);
630
- if (query.vars !== undefined) {
631
- this.vars = [...this.vars, ...query.vars]
632
- }
633
- }
634
- sql += `FROM ${tables.join(',')} `;
635
- }
636
-
637
- if (this.whereExpressions.length > 0) {
638
- sql += "WHERE " + this.whereExpressions.join(" AND ");
639
- }
640
-
641
- const data = await this.executeQuery(sql, this.vars);
642
- return data.rowCount;
643
- }
644
-
645
- public async executeDelete() : Promise<number> {
646
- let sql = `DELETE FROM ${this.TableName} "${this.TableAlias}" `;
647
-
648
- if (this.joinConditions.length > 0) {
649
- const tables: Array<string> = [];
650
- for (const join of this.joinConditions) {
651
- tables.push(`${join.model.TableName} as "${join.model.TableAlias}"`);
652
-
653
- const query = WhereExpression.createCondition(join.conditions, this, this.vars.length + 1);
654
- this.whereExpressions.push(query.expression);
655
- if (query.vars !== undefined) {
656
- this.vars = [...this.vars, ...query.vars]
657
- }
658
- sql += ` USING ${tables.join(',')} `;
659
- }
660
- }
661
-
662
- if (this.whereExpressions.length > 0) {
663
- sql += "WHERE " + this.whereExpressions.join(" AND ");
664
- }
665
-
666
- const datas = await this.executeQuery(sql, this.vars);
667
- return datas.rowCount;
668
- }
669
-
670
- protected executeQuery(param1: string, vars?: Array<any>) : Promise<any>;
671
- protected executeQuery(param1: TQuery) : Promise<any>;
672
- protected async executeQuery(param1: string | TQuery, vars?: Array<any>) : Promise<any> {
673
-
674
- // 初期化項目
675
- this.selectExpressions = [];
676
- this.whereExpressions = [];
677
- this.joinConditions = [];
678
- this.sortExpression = [];
679
- this.SortKeyword = 'asc';
680
- this.groupExpression = [];
681
- this.vars = [];
682
- this.Offset = undefined;
683
- this.Limit = undefined;
684
-
685
- let sql = '';
686
- if (typeof param1 === 'string') {
687
- sql = param1;
688
- } else {
689
- sql = param1.expression;
690
- vars = param1.vars;
691
- }
692
-
693
-
694
- return await this.clientQuery(sql, vars);
695
- }
696
-
697
- private async clientQuery(sql: string, vars?: Array<any>) {
698
- if (this.IsOutputLog) {
699
- console.log("--- Debug Sql ----------");
700
- console.log(sql);
701
- console.log(vars);
702
- }
703
-
704
- const data = await this.client.query(sql, vars ?? []);
705
- if (this.IsOutputLog) {
706
- console.log("- 実行結果");
707
- if (data.rowCount == 0) {
708
- console.log("データなし");
709
- } else {
710
- let log = "";
711
- for (let i = 0;i < data.fields.length;i++) {
712
- log += i == 0 ? "" : ",";
713
- log += data.fields[i].name;
714
- }
715
- console.log(log);
716
-
717
- for (let i = 0;i < data.rows.length;i++) {
718
- log = "";
719
- for (let j = 0;j < data.fields.length;j++) {
720
- let key = data.fields[j].name;
721
- log += j == 0 ? "" : ",";
722
- log += data.rows[i][key];
723
- }
724
- console.log(log);
725
- }
726
- }
727
- }
728
-
729
- return data;
730
- }
731
-
732
- private validateClient?: ValidateClient;
733
- get ValidateClient(): ValidateClient {
734
- if (this.validateClient === undefined) {
735
- this.validateClient = new ValidateClient(this);
736
- }
737
-
738
- return this.validateClient;
739
- }
740
-
741
- private expressionClient?: ExpressionClient;
742
- get ExpressionClient(): ExpressionClient {
743
- if (this.expressionClient === undefined) {
744
- this.expressionClient = new ExpressionClient(this);
745
- }
746
-
747
- return this.expressionClient;
748
- }
749
- }