pg-mvc-service 1.0.26 → 1.0.27
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/dist/models/SqlUtils/UpdateExpression.js +24 -0
- package/dist/models/SqlUtils/WhereExpression.js +37 -18
- package/dist/models/TableModel.js +32 -37
- package/dist/models/Utils/MessageUtil.js +1 -0
- package/package.json +1 -1
- package/src/models/SqlUtils/UpdateExpression.ts +29 -0
- package/src/models/SqlUtils/WhereExpression.ts +42 -18
- package/src/models/TableModel.ts +35 -43
- package/src/models/Type.ts +1 -1
- package/src/models/Utils/MessageUtil.ts +0 -0
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
class UpdateExpression {
|
|
4
|
+
static createUpdateSet(model, options) {
|
|
5
|
+
const expressions = [];
|
|
6
|
+
const vars = [];
|
|
7
|
+
for (const [key, value] of Object.entries(options)) {
|
|
8
|
+
if (value === undefined) {
|
|
9
|
+
throw new Error(`The update option ${key} is undefined.`);
|
|
10
|
+
}
|
|
11
|
+
const column = model.getColumn(key);
|
|
12
|
+
if (column.attribute === 'primary') {
|
|
13
|
+
throw new Error(`The primary key ${model.TableName}.${key} cannot be changed.`);
|
|
14
|
+
}
|
|
15
|
+
vars.push(value);
|
|
16
|
+
expressions.push(`${key} = $${vars.length}`);
|
|
17
|
+
}
|
|
18
|
+
return {
|
|
19
|
+
expression: `UPDATE ${model.TableName} SET ${expressions.join(',')}`,
|
|
20
|
+
vars: vars
|
|
21
|
+
};
|
|
22
|
+
}
|
|
23
|
+
}
|
|
24
|
+
exports.default = UpdateExpression;
|
|
@@ -5,6 +5,25 @@ var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
|
5
5
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
6
|
const ValidateValueUtil_1 = __importDefault(require("./ValidateValueUtil"));
|
|
7
7
|
class WhereExpression {
|
|
8
|
+
static createConditionPk(model, pk, vars = null, isSetAlias = false) {
|
|
9
|
+
const conditions = [];
|
|
10
|
+
const newVars = vars === null ? [] : [...vars];
|
|
11
|
+
for (const [keyColumn, column] of Object.entries(model.Columns)) {
|
|
12
|
+
if (column.attribute !== 'primary') {
|
|
13
|
+
continue;
|
|
14
|
+
}
|
|
15
|
+
if (pk[keyColumn] === undefined || pk[keyColumn] === null) {
|
|
16
|
+
throw new Error(`No value is set for the primary key "${model.TableName}".${keyColumn}.`);
|
|
17
|
+
}
|
|
18
|
+
ValidateValueUtil_1.default.validateValue(column, pk[keyColumn]);
|
|
19
|
+
newVars.push(pk[keyColumn]);
|
|
20
|
+
conditions.push(`"${isSetAlias ? model.TableAlias : model.TableName}".${keyColumn} = $${newVars.length}`);
|
|
21
|
+
}
|
|
22
|
+
return {
|
|
23
|
+
expression: conditions.join(' AND '),
|
|
24
|
+
vars: newVars
|
|
25
|
+
};
|
|
26
|
+
}
|
|
8
27
|
/**
|
|
9
28
|
* Helper method to create OR conditions
|
|
10
29
|
* @param conditions Array of conditions that make up the OR condition
|
|
@@ -12,12 +31,12 @@ class WhereExpression {
|
|
|
12
31
|
*/
|
|
13
32
|
static createCondition(conditions, model, varLength) {
|
|
14
33
|
if (conditions.length === 0) {
|
|
15
|
-
return {
|
|
34
|
+
return { expression: '' };
|
|
16
35
|
}
|
|
17
36
|
let logicalOperator = 'AND';
|
|
18
37
|
if (conditions[0] === 'AND' || conditions[0] === 'OR') {
|
|
19
38
|
if (conditions.length === 1) {
|
|
20
|
-
return {
|
|
39
|
+
return { expression: '' };
|
|
21
40
|
}
|
|
22
41
|
logicalOperator = conditions[0];
|
|
23
42
|
conditions.shift();
|
|
@@ -28,7 +47,7 @@ class WhereExpression {
|
|
|
28
47
|
if (Array.isArray(condition)) {
|
|
29
48
|
// If it's an array, it's a nested condition, so call this function recursively
|
|
30
49
|
const query = this.createCondition(condition, model, varLength + vars.length);
|
|
31
|
-
expression.push(query.
|
|
50
|
+
expression.push(query.expression);
|
|
32
51
|
if (query.vars !== undefined) {
|
|
33
52
|
vars = [...vars, ...query.vars];
|
|
34
53
|
}
|
|
@@ -41,20 +60,20 @@ class WhereExpression {
|
|
|
41
60
|
}
|
|
42
61
|
if (typeof condition.l === 'string') {
|
|
43
62
|
const query = this.create({ model: model, name: condition.l }, condition.o, condition.r, varLength + vars.length);
|
|
44
|
-
expression.push(query.
|
|
63
|
+
expression.push(query.expression);
|
|
45
64
|
if (query.vars !== undefined) {
|
|
46
65
|
vars = [...vars, ...query.vars];
|
|
47
66
|
}
|
|
48
67
|
continue;
|
|
49
68
|
}
|
|
50
69
|
const query = this.create(condition.l, condition.o, condition.r, varLength + vars.length);
|
|
51
|
-
expression.push(query.
|
|
70
|
+
expression.push(query.expression);
|
|
52
71
|
if (query.vars !== undefined) {
|
|
53
72
|
vars = [...vars, ...query.vars];
|
|
54
73
|
}
|
|
55
74
|
}
|
|
56
75
|
return {
|
|
57
|
-
|
|
76
|
+
expression: `(${expression.filter(condition => condition !== null && condition !== void 0 ? condition : '' !== '').join(` ${logicalOperator} `)})`,
|
|
58
77
|
vars: vars
|
|
59
78
|
};
|
|
60
79
|
}
|
|
@@ -93,12 +112,12 @@ class WhereExpression {
|
|
|
93
112
|
}
|
|
94
113
|
if (operator == "=") {
|
|
95
114
|
return {
|
|
96
|
-
|
|
115
|
+
expression: `${leftColumn.expression} is null`
|
|
97
116
|
};
|
|
98
117
|
}
|
|
99
118
|
else if (operator == "!=") {
|
|
100
119
|
return {
|
|
101
|
-
|
|
120
|
+
expression: `${leftColumn.expression} is not null`
|
|
102
121
|
};
|
|
103
122
|
}
|
|
104
123
|
else {
|
|
@@ -120,14 +139,14 @@ class WhereExpression {
|
|
|
120
139
|
}
|
|
121
140
|
if (right.length == 0) {
|
|
122
141
|
// Creating in, not in with 0 elements will cause an error, but since the data to be passed is correct and the expected return value does not change, do not search if there are 0 elements
|
|
123
|
-
return {
|
|
142
|
+
return { expression: '' };
|
|
124
143
|
}
|
|
125
144
|
// Validate values
|
|
126
145
|
for (const value of right) {
|
|
127
146
|
ValidateValueUtil_1.default.validateValue(leftColumn, value);
|
|
128
147
|
}
|
|
129
148
|
return {
|
|
130
|
-
|
|
149
|
+
expression: `${leftColumn.expression} ${operator === 'in' ? '=' : '!='} ANY($${varLength})`,
|
|
131
150
|
vars: [right]
|
|
132
151
|
};
|
|
133
152
|
}
|
|
@@ -145,16 +164,16 @@ class WhereExpression {
|
|
|
145
164
|
case 'like':
|
|
146
165
|
case 'ilike':
|
|
147
166
|
return {
|
|
148
|
-
|
|
167
|
+
expression: `${leftColumn.expression} ${operator} '%' || ${rightColumn.expression} || '%'`
|
|
149
168
|
};
|
|
150
169
|
case 'h2f_like': // half to full like
|
|
151
170
|
case 'h2f_ilike': // half to full ilike
|
|
152
171
|
return {
|
|
153
|
-
|
|
172
|
+
expression: `${this.makeSqlReplaceHalfToFull(leftColumn.expression)} ${operator.replace("h2f_", "")} ${this.makeSqlReplaceHalfToFull(`'%' || ${rightColumn.expression} || '%'`)}`
|
|
154
173
|
};
|
|
155
174
|
}
|
|
156
175
|
return {
|
|
157
|
-
|
|
176
|
+
expression: `${leftColumn.expression} ${operator} ${rightColumn.expression}`
|
|
158
177
|
};
|
|
159
178
|
}
|
|
160
179
|
ValidateValueUtil_1.default.validateValue(leftColumn, right);
|
|
@@ -163,18 +182,18 @@ class WhereExpression {
|
|
|
163
182
|
case 'like':
|
|
164
183
|
case 'ilike':
|
|
165
184
|
return {
|
|
166
|
-
|
|
185
|
+
expression: `${leftColumn.expression} ${operator} $${varLength}`,
|
|
167
186
|
vars: [`%${right}%`]
|
|
168
187
|
};
|
|
169
188
|
case 'h2f_like': // half to full like
|
|
170
189
|
case 'h2f_ilike': // half to full ilike
|
|
171
190
|
return {
|
|
172
|
-
|
|
191
|
+
expression: `${this.makeSqlReplaceHalfToFull(leftColumn.expression)} ${operator.replace("h2f_", "")} ${this.makeSqlReplaceHalfToFull(`$${varLength}`)}`,
|
|
173
192
|
vars: [`%${right}%`]
|
|
174
193
|
};
|
|
175
194
|
}
|
|
176
195
|
return {
|
|
177
|
-
|
|
196
|
+
expression: `${leftColumn.expression} ${operator} $${varLength}`,
|
|
178
197
|
vars: [right]
|
|
179
198
|
};
|
|
180
199
|
}
|
|
@@ -199,12 +218,12 @@ class WhereExpression {
|
|
|
199
218
|
case '=':
|
|
200
219
|
// バリデーションチェックをする
|
|
201
220
|
return {
|
|
202
|
-
|
|
221
|
+
expression: `${leftColumn.expression} ${operator} $${varLength}`,
|
|
203
222
|
vars: [right]
|
|
204
223
|
};
|
|
205
224
|
}
|
|
206
225
|
return {
|
|
207
|
-
|
|
226
|
+
expression: `${leftColumn.expression} ${operator} $${varLength}`,
|
|
208
227
|
vars: [right]
|
|
209
228
|
};
|
|
210
229
|
}
|
|
@@ -19,6 +19,7 @@ const WhereExpression_1 = __importDefault(require("./SqlUtils/WhereExpression"))
|
|
|
19
19
|
const ValidateClient_1 = __importDefault(require("./ValidateClient"));
|
|
20
20
|
const Exception_1 = require("../exceptions/Exception");
|
|
21
21
|
const ExpressionClient_1 = __importDefault(require("./ExpressionClient"));
|
|
22
|
+
const UpdateExpression_1 = __importDefault(require("./SqlUtils/UpdateExpression"));
|
|
22
23
|
class TableModel {
|
|
23
24
|
get DbName() { return this.dbName; }
|
|
24
25
|
get TableName() {
|
|
@@ -61,7 +62,7 @@ class TableModel {
|
|
|
61
62
|
sql += join.type === 'left' ? ' LEFT OUTER JOIN' : ' INNER JOIN';
|
|
62
63
|
sql += ` ${join.model.TableName} as "${join.model.TableAlias}" ON `;
|
|
63
64
|
const query = WhereExpression_1.default.createCondition(join.conditions, this, this.vars.length + 1);
|
|
64
|
-
sql += query.
|
|
65
|
+
sql += query.expression;
|
|
65
66
|
if (query.vars !== undefined) {
|
|
66
67
|
this.vars = [...this.vars, ...query.vars];
|
|
67
68
|
}
|
|
@@ -138,6 +139,7 @@ class TableModel {
|
|
|
138
139
|
'notInput': 'Please enter {name}.',
|
|
139
140
|
'fk': 'The value of {name} does not exist in the table.',
|
|
140
141
|
'idNotExist': 'The specified ID({id}) does not exist in the table.',
|
|
142
|
+
'find': 'The specified data does not exist in the table. ({pks})'
|
|
141
143
|
};
|
|
142
144
|
this.errorMessageJapan = {
|
|
143
145
|
'string': '{name}はstringかnumberで入力してください。',
|
|
@@ -165,6 +167,7 @@ class TableModel {
|
|
|
165
167
|
'notInput': '{name}を入力してください。',
|
|
166
168
|
'fk': '{name}の値がテーブルに存在しません。',
|
|
167
169
|
'idNotExist': '指定されたID({id})はテーブルに存在しません。',
|
|
170
|
+
'find': '指定されたデータはテーブルに存在しません。({pks})'
|
|
168
171
|
};
|
|
169
172
|
this.errorMessages = process.env.TZ === 'Asia/Tokyo' ? this.errorMessageJapan : this.errorMessageEnglish;
|
|
170
173
|
this.client = client;
|
|
@@ -214,20 +217,8 @@ class TableModel {
|
|
|
214
217
|
selects.push(`${expression.expression} as "${expression.alias}"`);
|
|
215
218
|
}
|
|
216
219
|
}
|
|
217
|
-
const
|
|
218
|
-
const
|
|
219
|
-
for (const [keyColumn, column] of Object.entries(this.Columns)) {
|
|
220
|
-
if (column.attribute !== 'primary') {
|
|
221
|
-
continue;
|
|
222
|
-
}
|
|
223
|
-
if (pk[keyColumn] === undefined || pk[keyColumn] === null) {
|
|
224
|
-
throw new Error(`No value is set for the primary key "${this.TableName}".${keyColumn}. Please set it in the first argument.`);
|
|
225
|
-
}
|
|
226
|
-
ValidateValueUtil_1.default.validateValue(column, pk[keyColumn]);
|
|
227
|
-
vars.push(pk[keyColumn]);
|
|
228
|
-
conditions.push(`${keyColumn} = $${vars.length}`);
|
|
229
|
-
}
|
|
230
|
-
const sql = `SELECT ${selects.join(',')} FROM ${this.TableName} WHERE ${conditions.join(' AND ')}`;
|
|
220
|
+
const { expression, vars } = WhereExpression_1.default.createConditionPk(this, pk);
|
|
221
|
+
const sql = `SELECT ${selects.join(',')} FROM ${this.TableName} WHERE ${expression}`;
|
|
231
222
|
let datas = yield this.executeQuery(sql, vars);
|
|
232
223
|
return datas.rowCount == 0 ? null : datas.rows[0];
|
|
233
224
|
});
|
|
@@ -299,7 +290,7 @@ class TableModel {
|
|
|
299
290
|
}
|
|
300
291
|
else {
|
|
301
292
|
const query = WhereExpression_1.default.create({ model: this, name: left }, operator, right, this.vars.length + 1);
|
|
302
|
-
this.whereExpressions.push(query.
|
|
293
|
+
this.whereExpressions.push(query.expression);
|
|
303
294
|
if (query.vars !== undefined) {
|
|
304
295
|
this.vars = [...this.vars, ...query.vars];
|
|
305
296
|
}
|
|
@@ -312,7 +303,7 @@ class TableModel {
|
|
|
312
303
|
}
|
|
313
304
|
else {
|
|
314
305
|
const query = WhereExpression_1.default.create(left, operator, right, this.vars.length + 1);
|
|
315
|
-
this.whereExpressions.push(query.
|
|
306
|
+
this.whereExpressions.push(query.expression);
|
|
316
307
|
if (query.vars !== undefined) {
|
|
317
308
|
this.vars = [...this.vars, ...query.vars];
|
|
318
309
|
}
|
|
@@ -321,7 +312,7 @@ class TableModel {
|
|
|
321
312
|
}
|
|
322
313
|
if (Array.isArray(left)) {
|
|
323
314
|
const query = WhereExpression_1.default.createCondition(left, this, this.vars.length + 1);
|
|
324
|
-
this.whereExpressions.push(query.
|
|
315
|
+
this.whereExpressions.push(query.expression);
|
|
325
316
|
if (query.vars !== undefined) {
|
|
326
317
|
this.vars = [...this.vars, ...query.vars];
|
|
327
318
|
}
|
|
@@ -539,7 +530,7 @@ class TableModel {
|
|
|
539
530
|
for (const join of this.joinConditions) {
|
|
540
531
|
tables.push(`${join.model.TableName} as "${join.model.TableAlias}"`);
|
|
541
532
|
const query = WhereExpression_1.default.createCondition(join.conditions, this, this.vars.length);
|
|
542
|
-
this.whereExpressions.push(query.
|
|
533
|
+
this.whereExpressions.push(query.expression);
|
|
543
534
|
if (query.vars !== undefined) {
|
|
544
535
|
this.vars = [...this.vars, ...query.vars];
|
|
545
536
|
}
|
|
@@ -555,28 +546,32 @@ class TableModel {
|
|
|
555
546
|
}
|
|
556
547
|
executeUpdateId(id, options) {
|
|
557
548
|
return __awaiter(this, void 0, void 0, function* () {
|
|
549
|
+
var _a;
|
|
558
550
|
ValidateValueUtil_1.default.validateId(this.Columns, id);
|
|
559
551
|
yield this.validateOptions(options, false);
|
|
560
552
|
yield this.validateUpdateId(id, options);
|
|
561
553
|
yield this.validateUpdate(options);
|
|
562
|
-
const
|
|
563
|
-
const
|
|
564
|
-
|
|
565
|
-
|
|
566
|
-
|
|
567
|
-
}
|
|
568
|
-
const column = this.getColumn(key);
|
|
569
|
-
if (column.attribute === 'primary') {
|
|
570
|
-
throw new Error(`The primary key ${this.TableName}.${key} cannot be changed.`);
|
|
571
|
-
}
|
|
572
|
-
vars.push(value);
|
|
573
|
-
updateExpressions.push(`${key} = $${vars.length}`);
|
|
554
|
+
const updateSetQuery = UpdateExpression_1.default.createUpdateSet(this, options);
|
|
555
|
+
const whereQuery = WhereExpression_1.default.createConditionPk(this, { id: id }, updateSetQuery.vars);
|
|
556
|
+
const sql = updateSetQuery.expression + ' ' + whereQuery.expression;
|
|
557
|
+
const data = yield this.executeQuery(sql, whereQuery.vars);
|
|
558
|
+
if (data.rowCount !== 1) {
|
|
559
|
+
throw new Exception_1.UnprocessableException("201", this.errorMessages.find.replace('{pks}', ((_a = whereQuery.vars) !== null && _a !== void 0 ? _a : []).join(',')));
|
|
574
560
|
}
|
|
575
|
-
|
|
576
|
-
|
|
577
|
-
|
|
561
|
+
});
|
|
562
|
+
}
|
|
563
|
+
executeUpdateByPk(pk, options) {
|
|
564
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
565
|
+
var _a;
|
|
566
|
+
yield this.validateOptions(options, false);
|
|
567
|
+
// await this.validateUpdateId(id, options);
|
|
568
|
+
yield this.validateUpdate(options);
|
|
569
|
+
const updateSetQuery = UpdateExpression_1.default.createUpdateSet(this, options);
|
|
570
|
+
const whereQuery = WhereExpression_1.default.createConditionPk(this, pk, updateSetQuery.vars);
|
|
571
|
+
const sql = updateSetQuery.expression + ' ' + whereQuery.expression;
|
|
572
|
+
const data = yield this.executeQuery(sql, whereQuery.vars);
|
|
578
573
|
if (data.rowCount !== 1) {
|
|
579
|
-
throw new Exception_1.UnprocessableException("
|
|
574
|
+
throw new Exception_1.UnprocessableException("401", this.errorMessages.find.replace('{pks}', ((_a = whereQuery.vars) !== null && _a !== void 0 ? _a : []).join(',')));
|
|
580
575
|
}
|
|
581
576
|
});
|
|
582
577
|
}
|
|
@@ -589,7 +584,7 @@ class TableModel {
|
|
|
589
584
|
for (const join of this.joinConditions) {
|
|
590
585
|
tables.push(`${join.model.TableName} as "${join.model.TableAlias}"`);
|
|
591
586
|
const query = WhereExpression_1.default.createCondition(join.conditions, this, this.vars.length);
|
|
592
|
-
this.whereExpressions.push(query.
|
|
587
|
+
this.whereExpressions.push(query.expression);
|
|
593
588
|
if (query.vars !== undefined) {
|
|
594
589
|
this.vars = [...this.vars, ...query.vars];
|
|
595
590
|
}
|
|
@@ -632,7 +627,7 @@ class TableModel {
|
|
|
632
627
|
sql = param1;
|
|
633
628
|
}
|
|
634
629
|
else {
|
|
635
|
-
sql = param1.
|
|
630
|
+
sql = param1.expression;
|
|
636
631
|
vars = param1.vars;
|
|
637
632
|
}
|
|
638
633
|
return yield this.clientQuery(sql, vars);
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
"use strict";
|
package/package.json
CHANGED
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
import { TableModel } from "../TableModel";
|
|
2
|
+
import { TQuery } from "../Type";
|
|
3
|
+
|
|
4
|
+
export default class UpdateExpression {
|
|
5
|
+
|
|
6
|
+
static createUpdateSet(model: TableModel, options: {[key: string]: any}): TQuery {
|
|
7
|
+
const expressions = [];
|
|
8
|
+
const vars = [];
|
|
9
|
+
for (const [key, value] of Object.entries(options)) {
|
|
10
|
+
if (value === undefined) {
|
|
11
|
+
throw new Error(`The update option ${key} is undefined.`);
|
|
12
|
+
}
|
|
13
|
+
|
|
14
|
+
const column = model.getColumn(key);
|
|
15
|
+
if (column.attribute === 'primary') {
|
|
16
|
+
throw new Error(`The primary key ${model.TableName}.${key} cannot be changed.`);
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
vars.push(value);
|
|
20
|
+
expressions.push(`${key} = $${vars.length}`);
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
return {
|
|
24
|
+
expression: `UPDATE ${model.TableName} SET ${expressions.join(',')}`,
|
|
25
|
+
vars: vars
|
|
26
|
+
}
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
}
|
|
@@ -4,6 +4,30 @@ import ValidateValueUtil from "./ValidateValueUtil";
|
|
|
4
4
|
|
|
5
5
|
export default class WhereExpression {
|
|
6
6
|
|
|
7
|
+
public static createConditionPk(model: TableModel, pk: {[key: string]: any}, vars: Array<any> | null = null, isSetAlias: boolean = false): TQuery {
|
|
8
|
+
const conditions = [];
|
|
9
|
+
const newVars = vars === null ? [] : [...vars];
|
|
10
|
+
|
|
11
|
+
for (const [keyColumn, column] of Object.entries(model.Columns)) {
|
|
12
|
+
if (column.attribute !== 'primary') {
|
|
13
|
+
continue;
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
if (pk[keyColumn] === undefined || pk[keyColumn] === null) {
|
|
17
|
+
throw new Error(`No value is set for the primary key "${model.TableName}".${keyColumn}.`);
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
ValidateValueUtil.validateValue(column, pk[keyColumn]);
|
|
21
|
+
newVars.push(pk[keyColumn]);
|
|
22
|
+
conditions.push(`"${isSetAlias ? model.TableAlias : model.TableName}".${keyColumn} = $${newVars.length}`);
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
return {
|
|
26
|
+
expression: conditions.join(' AND '),
|
|
27
|
+
vars: newVars
|
|
28
|
+
}
|
|
29
|
+
}
|
|
30
|
+
|
|
7
31
|
/**
|
|
8
32
|
* Helper method to create OR conditions
|
|
9
33
|
* @param conditions Array of conditions that make up the OR condition
|
|
@@ -12,13 +36,13 @@ export default class WhereExpression {
|
|
|
12
36
|
public static createCondition(conditions: Array<TNestedCondition>, model: TableModel, varLength: number): TQuery {
|
|
13
37
|
|
|
14
38
|
if (conditions.length === 0) {
|
|
15
|
-
return {
|
|
39
|
+
return { expression: '' };
|
|
16
40
|
}
|
|
17
41
|
|
|
18
42
|
let logicalOperator = 'AND';
|
|
19
43
|
if (conditions[0] === 'AND' || conditions[0] === 'OR') {
|
|
20
44
|
if (conditions.length === 1) {
|
|
21
|
-
return {
|
|
45
|
+
return { expression: '' };
|
|
22
46
|
}
|
|
23
47
|
|
|
24
48
|
logicalOperator = conditions[0];
|
|
@@ -31,7 +55,7 @@ export default class WhereExpression {
|
|
|
31
55
|
if (Array.isArray(condition)) {
|
|
32
56
|
// If it's an array, it's a nested condition, so call this function recursively
|
|
33
57
|
const query = this.createCondition(condition, model, varLength + vars.length);
|
|
34
|
-
expression.push(query.
|
|
58
|
+
expression.push(query.expression);
|
|
35
59
|
if (query.vars !== undefined) {
|
|
36
60
|
vars = [...vars, ...query.vars];
|
|
37
61
|
}
|
|
@@ -46,7 +70,7 @@ export default class WhereExpression {
|
|
|
46
70
|
|
|
47
71
|
if (typeof condition.l === 'string') {
|
|
48
72
|
const query = this.create({ model: model, name: condition.l}, condition.o, condition.r, varLength + vars.length);
|
|
49
|
-
expression.push(query.
|
|
73
|
+
expression.push(query.expression);
|
|
50
74
|
if (query.vars !== undefined) {
|
|
51
75
|
vars = [...vars, ...query.vars];
|
|
52
76
|
}
|
|
@@ -54,14 +78,14 @@ export default class WhereExpression {
|
|
|
54
78
|
}
|
|
55
79
|
|
|
56
80
|
const query = this.create(condition.l, condition.o, condition.r, varLength + vars.length);
|
|
57
|
-
expression.push(query.
|
|
81
|
+
expression.push(query.expression);
|
|
58
82
|
if (query.vars !== undefined) {
|
|
59
83
|
vars = [...vars, ...query.vars];
|
|
60
84
|
}
|
|
61
85
|
}
|
|
62
86
|
|
|
63
87
|
return {
|
|
64
|
-
|
|
88
|
+
expression: `(${expression.filter(condition => condition ?? '' !== '').join(` ${logicalOperator} `)})`,
|
|
65
89
|
vars: vars
|
|
66
90
|
}
|
|
67
91
|
}
|
|
@@ -106,11 +130,11 @@ export default class WhereExpression {
|
|
|
106
130
|
|
|
107
131
|
if (operator == "=") {
|
|
108
132
|
return {
|
|
109
|
-
|
|
133
|
+
expression: `${leftColumn.expression} is null`
|
|
110
134
|
}
|
|
111
135
|
} else if (operator == "!=") {
|
|
112
136
|
return {
|
|
113
|
-
|
|
137
|
+
expression: `${leftColumn.expression} is not null`
|
|
114
138
|
}
|
|
115
139
|
} else {
|
|
116
140
|
throw new Error(`When comparing with null, operators other than =, != cannot be used. (${operator})`);
|
|
@@ -133,7 +157,7 @@ export default class WhereExpression {
|
|
|
133
157
|
|
|
134
158
|
if (right.length == 0) {
|
|
135
159
|
// Creating in, not in with 0 elements will cause an error, but since the data to be passed is correct and the expected return value does not change, do not search if there are 0 elements
|
|
136
|
-
return {
|
|
160
|
+
return { expression: '' };
|
|
137
161
|
}
|
|
138
162
|
|
|
139
163
|
// Validate values
|
|
@@ -141,7 +165,7 @@ export default class WhereExpression {
|
|
|
141
165
|
ValidateValueUtil.validateValue(leftColumn, value);
|
|
142
166
|
}
|
|
143
167
|
return {
|
|
144
|
-
|
|
168
|
+
expression: `${leftColumn.expression} ${operator === 'in' ? '=' : '!='} ANY($${varLength})`,
|
|
145
169
|
vars: [right]
|
|
146
170
|
}
|
|
147
171
|
} else if (Array.isArray(right)) {
|
|
@@ -161,17 +185,17 @@ export default class WhereExpression {
|
|
|
161
185
|
case 'like':
|
|
162
186
|
case 'ilike':
|
|
163
187
|
return {
|
|
164
|
-
|
|
188
|
+
expression: `${leftColumn.expression} ${operator} '%' || ${rightColumn.expression} || '%'`
|
|
165
189
|
}
|
|
166
190
|
case 'h2f_like': // half to full like
|
|
167
191
|
case 'h2f_ilike': // half to full ilike
|
|
168
192
|
return {
|
|
169
|
-
|
|
193
|
+
expression: `${this.makeSqlReplaceHalfToFull(leftColumn.expression)} ${operator.replace("h2f_", "")} ${this.makeSqlReplaceHalfToFull(`'%' || ${rightColumn.expression} || '%'`)}`
|
|
170
194
|
}
|
|
171
195
|
}
|
|
172
196
|
|
|
173
197
|
return {
|
|
174
|
-
|
|
198
|
+
expression: `${leftColumn.expression} ${operator} ${rightColumn.expression}`
|
|
175
199
|
}
|
|
176
200
|
}
|
|
177
201
|
|
|
@@ -181,19 +205,19 @@ export default class WhereExpression {
|
|
|
181
205
|
case 'like':
|
|
182
206
|
case 'ilike':
|
|
183
207
|
return {
|
|
184
|
-
|
|
208
|
+
expression: `${leftColumn.expression} ${operator} $${varLength}`,
|
|
185
209
|
vars: [`%${right}%`]
|
|
186
210
|
}
|
|
187
211
|
case 'h2f_like': // half to full like
|
|
188
212
|
case 'h2f_ilike': // half to full ilike
|
|
189
213
|
return {
|
|
190
|
-
|
|
214
|
+
expression: `${this.makeSqlReplaceHalfToFull(leftColumn.expression)} ${operator.replace("h2f_", "")} ${this.makeSqlReplaceHalfToFull(`$${varLength}`)}`,
|
|
191
215
|
vars: [`%${right}%`]
|
|
192
216
|
}
|
|
193
217
|
}
|
|
194
218
|
|
|
195
219
|
return {
|
|
196
|
-
|
|
220
|
+
expression: `${leftColumn.expression} ${operator} $${varLength}`,
|
|
197
221
|
vars: [right]
|
|
198
222
|
}
|
|
199
223
|
}
|
|
@@ -222,14 +246,14 @@ export default class WhereExpression {
|
|
|
222
246
|
// バリデーションチェックをする
|
|
223
247
|
|
|
224
248
|
return {
|
|
225
|
-
|
|
249
|
+
expression: `${leftColumn.expression} ${operator} $${varLength}`,
|
|
226
250
|
vars: [right]
|
|
227
251
|
}
|
|
228
252
|
}
|
|
229
253
|
|
|
230
254
|
|
|
231
255
|
return {
|
|
232
|
-
|
|
256
|
+
expression: `${leftColumn.expression} ${operator} $${varLength}`,
|
|
233
257
|
vars: [right]
|
|
234
258
|
}
|
|
235
259
|
}
|
package/src/models/TableModel.ts
CHANGED
|
@@ -6,6 +6,7 @@ import WhereExpression from './SqlUtils/WhereExpression';
|
|
|
6
6
|
import ValidateClient from './ValidateClient';
|
|
7
7
|
import { DbConflictException, UnprocessableException } from '../exceptions/Exception';
|
|
8
8
|
import ExpressionClient from './ExpressionClient';
|
|
9
|
+
import UpdateExpression from './SqlUtils/UpdateExpression';
|
|
9
10
|
|
|
10
11
|
export class TableModel {
|
|
11
12
|
|
|
@@ -84,7 +85,7 @@ export class TableModel {
|
|
|
84
85
|
sql += join.type === 'left' ? ' LEFT OUTER JOIN' : ' INNER JOIN';
|
|
85
86
|
sql += ` ${join.model.TableName} as "${join.model.TableAlias}" ON `;
|
|
86
87
|
const query = WhereExpression.createCondition(join.conditions, this, this.vars.length + 1);
|
|
87
|
-
sql += query.
|
|
88
|
+
sql += query.expression;
|
|
88
89
|
if (query.vars !== undefined) {
|
|
89
90
|
this.vars = [...this.vars, ...query.vars]
|
|
90
91
|
}
|
|
@@ -190,22 +191,9 @@ export class TableModel {
|
|
|
190
191
|
}
|
|
191
192
|
}
|
|
192
193
|
|
|
193
|
-
const
|
|
194
|
-
const vars = [];
|
|
195
|
-
for (const [keyColumn, column] of Object.entries(this.Columns)) {
|
|
196
|
-
if (column.attribute !== 'primary') {
|
|
197
|
-
continue;
|
|
198
|
-
}
|
|
199
|
-
|
|
200
|
-
if (pk[keyColumn] === undefined || pk[keyColumn] === null) {
|
|
201
|
-
throw new Error(`No value is set for the primary key "${this.TableName}".${keyColumn}. Please set it in the first argument.`);
|
|
202
|
-
}
|
|
203
|
-
ValidateValueUtil.validateValue(column, pk[keyColumn]);
|
|
204
|
-
vars.push(pk[keyColumn]);
|
|
205
|
-
conditions.push(`${keyColumn} = $${vars.length}`);
|
|
206
|
-
}
|
|
194
|
+
const {expression, vars} = WhereExpression.createConditionPk(this, pk);
|
|
207
195
|
|
|
208
|
-
const sql = `SELECT ${selects.join(',')} FROM ${this.TableName} WHERE ${
|
|
196
|
+
const sql = `SELECT ${selects.join(',')} FROM ${this.TableName} WHERE ${expression}`;
|
|
209
197
|
let datas = await this.executeQuery(sql, vars);
|
|
210
198
|
|
|
211
199
|
return datas.rowCount == 0 ? null : datas.rows[0] as T;
|
|
@@ -289,7 +277,7 @@ export class TableModel {
|
|
|
289
277
|
this.whereExpressions.push(left);
|
|
290
278
|
} else {
|
|
291
279
|
const query = WhereExpression.create({model: this, name: left}, operator, right, this.vars.length + 1);
|
|
292
|
-
this.whereExpressions.push(query.
|
|
280
|
+
this.whereExpressions.push(query.expression);
|
|
293
281
|
if (query.vars !== undefined) {
|
|
294
282
|
this.vars = [...this.vars, ...query.vars];
|
|
295
283
|
}
|
|
@@ -302,7 +290,7 @@ export class TableModel {
|
|
|
302
290
|
throw new Error(`If left is TColumnInfo, please set operator and right.`);
|
|
303
291
|
} else {
|
|
304
292
|
const query = WhereExpression.create(left, operator, right, this.vars.length + 1);
|
|
305
|
-
this.whereExpressions.push(query.
|
|
293
|
+
this.whereExpressions.push(query.expression);
|
|
306
294
|
if (query.vars !== undefined) {
|
|
307
295
|
this.vars = [...this.vars, ...query.vars];
|
|
308
296
|
}
|
|
@@ -312,7 +300,7 @@ export class TableModel {
|
|
|
312
300
|
|
|
313
301
|
if (Array.isArray(left)) {
|
|
314
302
|
const query = WhereExpression.createCondition(left, this, this.vars.length + 1);
|
|
315
|
-
this.whereExpressions.push(query.
|
|
303
|
+
this.whereExpressions.push(query.expression);
|
|
316
304
|
if (query.vars !== undefined) {
|
|
317
305
|
this.vars = [...this.vars, ...query.vars];
|
|
318
306
|
}
|
|
@@ -405,7 +393,7 @@ export class TableModel {
|
|
|
405
393
|
return { datas: data.rows as Array<T>, count: Number(countData.rows[0].count), lastPage: Math.ceil(Number(countData.rows[0].count) / this.PageCount)};
|
|
406
394
|
}
|
|
407
395
|
|
|
408
|
-
private readonly errorMessageEnglish: Record<TColumnType | TColumnArrayType | 'length' | 'null' | 'notInput' | 'fk' | 'idNotExist', string> = {
|
|
396
|
+
private readonly errorMessageEnglish: Record<TColumnType | TColumnArrayType | 'length' | 'null' | 'notInput' | 'fk' | 'idNotExist' | 'find', string> = {
|
|
409
397
|
'string': '{name} should be entered as a string or number type.',
|
|
410
398
|
'string[]': '{name} should be entered as an array of string or number types.',
|
|
411
399
|
'uuid': '{name} should be entered as a UUID.',
|
|
@@ -431,8 +419,9 @@ export class TableModel {
|
|
|
431
419
|
'notInput': 'Please enter {name}.',
|
|
432
420
|
'fk': 'The value of {name} does not exist in the table.',
|
|
433
421
|
'idNotExist': 'The specified ID({id}) does not exist in the table.',
|
|
422
|
+
'find': 'The specified data does not exist in the table. ({pks})'
|
|
434
423
|
}
|
|
435
|
-
private readonly errorMessageJapan: Record<TColumnType | TColumnArrayType | 'length' | 'null' | 'notInput' | 'fk' | 'idNotExist', string> = {
|
|
424
|
+
private readonly errorMessageJapan: Record<TColumnType | TColumnArrayType | 'length' | 'null' | 'notInput' | 'fk' | 'idNotExist' | 'find', string> = {
|
|
436
425
|
'string': '{name}はstringかnumberで入力してください。',
|
|
437
426
|
'string[]': '{name}はstringかnumberの配列で入力してください。',
|
|
438
427
|
'uuid': '{name}はuuidで入力してください。',
|
|
@@ -458,6 +447,7 @@ export class TableModel {
|
|
|
458
447
|
'notInput': '{name}を入力してください。',
|
|
459
448
|
'fk': '{name}の値がテーブルに存在しません。',
|
|
460
449
|
'idNotExist': '指定されたID({id})はテーブルに存在しません。',
|
|
450
|
+
'find': '指定されたデータはテーブルに存在しません。({pks})'
|
|
461
451
|
}
|
|
462
452
|
|
|
463
453
|
private throwException(code: string, type: TColumnType | TColumnArrayType | 'length' | 'null' | 'notInput' | 'fk' | 'idNotExist', columnName: string, vallue: any): never {
|
|
@@ -474,7 +464,7 @@ export class TableModel {
|
|
|
474
464
|
throw new UnprocessableException(code, message);
|
|
475
465
|
}
|
|
476
466
|
|
|
477
|
-
protected readonly errorMessages: Record<TColumnType | TColumnArrayType | 'length' | 'null' | 'notInput' | 'fk' | 'idNotExist', string> =
|
|
467
|
+
protected readonly errorMessages: Record<TColumnType | TColumnArrayType | 'length' | 'null' | 'notInput' | 'fk' | 'idNotExist' | 'find', string> =
|
|
478
468
|
process.env.TZ === 'Asia/Tokyo' ? this.errorMessageJapan : this.errorMessageEnglish;
|
|
479
469
|
|
|
480
470
|
protected async validateOptions(options: {[key: string]: any}, isInsert: boolean): Promise<void> {
|
|
@@ -606,7 +596,7 @@ export class TableModel {
|
|
|
606
596
|
tables.push(`${join.model.TableName} as "${join.model.TableAlias}"`);
|
|
607
597
|
|
|
608
598
|
const query = WhereExpression.createCondition(join.conditions, this, this.vars.length);
|
|
609
|
-
this.whereExpressions.push(query.
|
|
599
|
+
this.whereExpressions.push(query.expression);
|
|
610
600
|
if (query.vars !== undefined) {
|
|
611
601
|
this.vars = [...this.vars, ...query.vars]
|
|
612
602
|
}
|
|
@@ -628,28 +618,30 @@ export class TableModel {
|
|
|
628
618
|
await this.validateUpdateId(id, options);
|
|
629
619
|
await this.validateUpdate(options);
|
|
630
620
|
|
|
631
|
-
const
|
|
632
|
-
const
|
|
621
|
+
const updateSetQuery = UpdateExpression.createUpdateSet(this, options);
|
|
622
|
+
const whereQuery = WhereExpression.createConditionPk(this, {id: id}, updateSetQuery.vars);
|
|
633
623
|
|
|
634
|
-
|
|
635
|
-
if (value === undefined) {
|
|
636
|
-
throw new Error(`The update option ${key} is undefined.`);
|
|
637
|
-
}
|
|
624
|
+
const sql = updateSetQuery.expression + ' ' + whereQuery.expression;
|
|
638
625
|
|
|
639
|
-
|
|
640
|
-
|
|
641
|
-
|
|
642
|
-
}
|
|
643
|
-
|
|
644
|
-
vars.push(value);
|
|
645
|
-
updateExpressions.push(`${key} = $${vars.length}`);
|
|
626
|
+
const data = await this.executeQuery(sql, whereQuery.vars);
|
|
627
|
+
if (data.rowCount !== 1) {
|
|
628
|
+
throw new UnprocessableException("201", this.errorMessages.find.replace('{pks}', (whereQuery.vars ?? []).join(',')));
|
|
646
629
|
}
|
|
647
|
-
|
|
648
|
-
|
|
649
|
-
|
|
650
|
-
|
|
630
|
+
}
|
|
631
|
+
|
|
632
|
+
public async executeUpdateByPk(pk: {[key: string]: any}, options: {[key: string]: any}) : Promise<void> {
|
|
633
|
+
await this.validateOptions(options, false);
|
|
634
|
+
// await this.validateUpdateId(id, options);
|
|
635
|
+
await this.validateUpdate(options);
|
|
636
|
+
|
|
637
|
+
const updateSetQuery = UpdateExpression.createUpdateSet(this, options);
|
|
638
|
+
const whereQuery = WhereExpression.createConditionPk(this, pk, updateSetQuery.vars);
|
|
639
|
+
|
|
640
|
+
const sql = updateSetQuery.expression + ' ' + whereQuery.expression;
|
|
641
|
+
|
|
642
|
+
const data = await this.executeQuery(sql, whereQuery.vars);
|
|
651
643
|
if (data.rowCount !== 1) {
|
|
652
|
-
throw new UnprocessableException("
|
|
644
|
+
throw new UnprocessableException("401", this.errorMessages.find.replace('{pks}', (whereQuery.vars ?? []).join(',')));
|
|
653
645
|
}
|
|
654
646
|
}
|
|
655
647
|
|
|
@@ -663,7 +655,7 @@ export class TableModel {
|
|
|
663
655
|
tables.push(`${join.model.TableName} as "${join.model.TableAlias}"`);
|
|
664
656
|
|
|
665
657
|
const query = WhereExpression.createCondition(join.conditions, this, this.vars.length);
|
|
666
|
-
this.whereExpressions.push(query.
|
|
658
|
+
this.whereExpressions.push(query.expression);
|
|
667
659
|
if (query.vars !== undefined) {
|
|
668
660
|
this.vars = [...this.vars, ...query.vars]
|
|
669
661
|
}
|
|
@@ -710,7 +702,7 @@ export class TableModel {
|
|
|
710
702
|
if (typeof param1 === 'string') {
|
|
711
703
|
sql = param1;
|
|
712
704
|
} else {
|
|
713
|
-
sql = param1.
|
|
705
|
+
sql = param1.expression;
|
|
714
706
|
vars = param1.vars;
|
|
715
707
|
}
|
|
716
708
|
|
package/src/models/Type.ts
CHANGED
|
@@ -49,7 +49,7 @@ export type TColumnDetail = TColumn & {
|
|
|
49
49
|
|
|
50
50
|
export type TOperator = "=" | "!=" | ">" | ">=" | "<" | "<=" | "like" | "ilike" | "h2f_like" | "h2f_ilike" | "in" | "not in";
|
|
51
51
|
export type TColumnInfo = { model: TableModel, name: string }
|
|
52
|
-
export type TQuery = {
|
|
52
|
+
export type TQuery = {expression: string, vars?: Array<any>};
|
|
53
53
|
export type TSelectExpression = { expression: string, alias: string }
|
|
54
54
|
export type TAggregateFuncType = 'sum' | 'avg' | 'max' | 'min' | 'count';
|
|
55
55
|
export type TCondition = string | {
|
|
File without changes
|