@axiosleo/orm-mysql 0.5.0 → 0.5.2
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/README.md +11 -1
- package/package.json +1 -1
- package/src/builder.js +19 -3
- package/.env +0 -6
- package/.prettierignore +0 -1
- package/runtimes/hook.js +0 -104
- package/runtimes/test.js +0 -73
package/README.md
CHANGED
|
@@ -164,10 +164,20 @@ const conn = createPromiseClient({
|
|
|
164
164
|
database: process.env.MYSQL_DB,
|
|
165
165
|
});
|
|
166
166
|
|
|
167
|
-
const transaction = new TransactionHandler(
|
|
167
|
+
const transaction = new TransactionHandler(conn, {
|
|
168
|
+
/*
|
|
169
|
+
level = 'READ UNCOMMITTED' | 'RU'
|
|
170
|
+
| 'READ COMMITTED' | 'RC'
|
|
171
|
+
| 'REPEATABLE READ' | 'RR'
|
|
172
|
+
| 'SERIALIZABLE' | 'S'
|
|
173
|
+
*/
|
|
174
|
+
level: "SERIALIZABLE", // 'SERIALIZABLE' as default value
|
|
175
|
+
});
|
|
176
|
+
await transaction.begin();
|
|
168
177
|
|
|
169
178
|
try {
|
|
170
179
|
// insert user info
|
|
180
|
+
// will not really create a record.
|
|
171
181
|
let row = await transaction.table("users").insert({
|
|
172
182
|
name: "Joe",
|
|
173
183
|
age: 18,
|
package/package.json
CHANGED
package/src/builder.js
CHANGED
|
@@ -192,6 +192,21 @@ class Builder {
|
|
|
192
192
|
return null;
|
|
193
193
|
}
|
|
194
194
|
|
|
195
|
+
_buildContidionIn(condition, isNot = false) {
|
|
196
|
+
if (!Array.isArray(condition.value) && !(condition.value instanceof Query)) {
|
|
197
|
+
throw new Error('Value must be an array for "IN" condition');
|
|
198
|
+
}
|
|
199
|
+
if (condition.key.indexOf('$') !== -1) {
|
|
200
|
+
let res = this._buildConditionValues(condition.value);
|
|
201
|
+
let sql = res ? `JSON_CONTAINS(JSON_ARRAY(${res}), ${this._buildFieldKey(condition.key)})` :
|
|
202
|
+
`JSON_CONTAINS(JSON_ARRAY(?), ${this._buildFieldKey(condition.key)})`;
|
|
203
|
+
return isNot ? `${sql}=0` : sql;
|
|
204
|
+
}
|
|
205
|
+
let res = this._buildConditionValues(condition.value);
|
|
206
|
+
const opt = isNot ? 'NOT IN' : 'IN';
|
|
207
|
+
return res ? `${this._buildFieldKey(condition.key)} ${opt} (${res})` : `${this._buildFieldKey(condition.key)} ${opt} (?)`;
|
|
208
|
+
}
|
|
209
|
+
|
|
195
210
|
_buildContidion(conditions, prefix) {
|
|
196
211
|
if (!conditions || !conditions.length) {
|
|
197
212
|
return '';
|
|
@@ -216,9 +231,10 @@ class Builder {
|
|
|
216
231
|
], '');
|
|
217
232
|
}
|
|
218
233
|
const opt = c.opt.toLowerCase();
|
|
219
|
-
if (opt === 'in'
|
|
220
|
-
|
|
221
|
-
|
|
234
|
+
if (opt === 'in') {
|
|
235
|
+
return this._buildContidionIn(c);
|
|
236
|
+
} else if (opt === 'not in') {
|
|
237
|
+
return this._buildContidionIn(c, true);
|
|
222
238
|
} else if (opt === 'group' && Array.isArray(c.value)) {
|
|
223
239
|
return `(${this._buildContidion(c.value, '')})`;
|
|
224
240
|
}
|
package/.env
DELETED
package/.prettierignore
DELETED
|
@@ -1 +0,0 @@
|
|
|
1
|
-
README.md
|
package/runtimes/hook.js
DELETED
|
@@ -1,104 +0,0 @@
|
|
|
1
|
-
/* eslint-disable no-console */
|
|
2
|
-
'use strict';
|
|
3
|
-
|
|
4
|
-
const EventEmitter = require('events');
|
|
5
|
-
const { debug } = require('@axiosleo/cli-tool');
|
|
6
|
-
const events = {}; // event tree
|
|
7
|
-
const hook = new EventEmitter();
|
|
8
|
-
|
|
9
|
-
const pushEvent = ({ label, table, opt, callback }) => {
|
|
10
|
-
label = label || '*';
|
|
11
|
-
if (!events[label]) {
|
|
12
|
-
events[label] = {};
|
|
13
|
-
}
|
|
14
|
-
table = table || '*';
|
|
15
|
-
if (!events[label][table]) {
|
|
16
|
-
events[label][table] = {};
|
|
17
|
-
}
|
|
18
|
-
opt = opt || '*';
|
|
19
|
-
if (!events[label][table][opt]) {
|
|
20
|
-
events[label][table][opt] = 0;
|
|
21
|
-
}
|
|
22
|
-
events[label][table][opt]++;
|
|
23
|
-
hook.on(`${label}::${table}::${opt}`, callback);
|
|
24
|
-
return { label, table, opt, callback };
|
|
25
|
-
};
|
|
26
|
-
|
|
27
|
-
const eventRecur = (curr, trace, step, paths, args) => {
|
|
28
|
-
if (step === trace.length) {
|
|
29
|
-
hook.emit(paths.join('::'), ...args);
|
|
30
|
-
return;
|
|
31
|
-
}
|
|
32
|
-
const t = trace[step];
|
|
33
|
-
if (curr['*']) {
|
|
34
|
-
paths[step] = '*';
|
|
35
|
-
eventRecur(curr[t], trace, step + 1, paths, args);
|
|
36
|
-
}
|
|
37
|
-
if (curr[t]) {
|
|
38
|
-
paths[step] = t;
|
|
39
|
-
eventRecur(curr[t], trace, step + 1, paths, args);
|
|
40
|
-
}
|
|
41
|
-
return;
|
|
42
|
-
};
|
|
43
|
-
|
|
44
|
-
const handleEvent = (label, table, opt, ...args) => {
|
|
45
|
-
let curr = events;
|
|
46
|
-
let step = 0;
|
|
47
|
-
let trace = [label, table, opt];
|
|
48
|
-
eventRecur(curr, trace, step, [], args);
|
|
49
|
-
};
|
|
50
|
-
|
|
51
|
-
pushEvent({
|
|
52
|
-
label: 'before',
|
|
53
|
-
table: 'table1',
|
|
54
|
-
opt: 'insert',
|
|
55
|
-
callback: (...args) => {
|
|
56
|
-
debug.log(args);
|
|
57
|
-
}
|
|
58
|
-
});
|
|
59
|
-
pushEvent({
|
|
60
|
-
table: 'table1',
|
|
61
|
-
opt: 'insert',
|
|
62
|
-
callback: (...args) => {
|
|
63
|
-
debug.log(args);
|
|
64
|
-
}
|
|
65
|
-
});
|
|
66
|
-
pushEvent({
|
|
67
|
-
label: 'before',
|
|
68
|
-
table: 'table1',
|
|
69
|
-
callback: (...args) => {
|
|
70
|
-
debug.log(args);
|
|
71
|
-
}
|
|
72
|
-
});
|
|
73
|
-
pushEvent({
|
|
74
|
-
label: 'before',
|
|
75
|
-
opt: 'insert',
|
|
76
|
-
callback: (...args) => {
|
|
77
|
-
debug.log(args);
|
|
78
|
-
}
|
|
79
|
-
});
|
|
80
|
-
pushEvent({
|
|
81
|
-
label: 'before',
|
|
82
|
-
callback: (...args) => {
|
|
83
|
-
debug.log(args);
|
|
84
|
-
}
|
|
85
|
-
});
|
|
86
|
-
pushEvent({
|
|
87
|
-
table: 'table1',
|
|
88
|
-
callback: (...args) => {
|
|
89
|
-
debug.log(args);
|
|
90
|
-
}
|
|
91
|
-
});
|
|
92
|
-
pushEvent({
|
|
93
|
-
opt: 'insert',
|
|
94
|
-
callback: (...args) => {
|
|
95
|
-
debug.log(args);
|
|
96
|
-
}
|
|
97
|
-
});
|
|
98
|
-
pushEvent({
|
|
99
|
-
callback: (...args) => {
|
|
100
|
-
debug.log(args);
|
|
101
|
-
}
|
|
102
|
-
});
|
|
103
|
-
debug.log(JSON.stringify(events, null, 2));
|
|
104
|
-
handleEvent('before', 'table1', 'insert', 1, 2, 3);
|
package/runtimes/test.js
DELETED
|
@@ -1,73 +0,0 @@
|
|
|
1
|
-
/* eslint-disable no-unused-vars */
|
|
2
|
-
/* eslint-disable no-console */
|
|
3
|
-
'use strict';
|
|
4
|
-
|
|
5
|
-
const path = require('path');
|
|
6
|
-
const dotenv = require('dotenv');
|
|
7
|
-
dotenv.config({
|
|
8
|
-
path: path.join(__dirname, '../.env')
|
|
9
|
-
});
|
|
10
|
-
const { debug } = require('@axiosleo/cli-tool');
|
|
11
|
-
|
|
12
|
-
const mysql = require('mysql2/promise');
|
|
13
|
-
|
|
14
|
-
const { TransactionHandler } = require('../src/transaction');
|
|
15
|
-
|
|
16
|
-
async function main() {
|
|
17
|
-
const items = ['RI0002', 'CB0004'];
|
|
18
|
-
const config = {
|
|
19
|
-
user: process.env.MYSQL_USER,
|
|
20
|
-
password: process.env.MYSQL_PASS,
|
|
21
|
-
host: process.env.MYSQL_HOST,
|
|
22
|
-
port: process.env.MYSQL_PORT,
|
|
23
|
-
database: process.env.MYSQL_DB,
|
|
24
|
-
};
|
|
25
|
-
const connection = await mysql.createConnection(config);
|
|
26
|
-
const transaction = new TransactionHandler(connection);
|
|
27
|
-
await transaction.begin();
|
|
28
|
-
console.log('Finished setting the isolation level to read committed');
|
|
29
|
-
try {
|
|
30
|
-
await transaction.table('product').attr('id', 'name').where('sku', items, 'IN').append('FOR UPDATE').select();
|
|
31
|
-
console.log(`Locked rows for skus ${items.join()}`);
|
|
32
|
-
const [itemsToOrder] = await transaction.table('product').attr('name', 'quantity', 'price').where('sku', items, 'IN').orderBy('id').select();
|
|
33
|
-
console.log('Selected quantities for items');
|
|
34
|
-
let orderTotal = 0;
|
|
35
|
-
let orderItems = [];
|
|
36
|
-
for (let itemToOrder of itemsToOrder) {
|
|
37
|
-
if (itemToOrder.quantity < 1) {
|
|
38
|
-
throw new Error(`One of the items is out of stock ${itemToOrder.name}`);
|
|
39
|
-
}
|
|
40
|
-
console.log(`Quantity for ${itemToOrder.name} is ${itemToOrder.quantity}`);
|
|
41
|
-
orderTotal += itemToOrder.price;
|
|
42
|
-
orderItems.push(itemToOrder.name);
|
|
43
|
-
}
|
|
44
|
-
const res = await transaction.table('sales_order').insert({
|
|
45
|
-
items: orderItems.join(),
|
|
46
|
-
total: orderTotal,
|
|
47
|
-
});
|
|
48
|
-
// const lastInsertId = res[0].insertId;
|
|
49
|
-
debug.log('result', res);
|
|
50
|
-
await debug.pause('pause', {
|
|
51
|
-
items: orderItems.join(),
|
|
52
|
-
total: orderTotal,
|
|
53
|
-
});
|
|
54
|
-
console.log('Order created');
|
|
55
|
-
await transaction.execute(
|
|
56
|
-
'UPDATE product SET quantity=quantity - 1 WHERE sku IN (?, ?)',
|
|
57
|
-
items
|
|
58
|
-
);
|
|
59
|
-
console.log(`Deducted quantities by 1 for ${items.join()}`);
|
|
60
|
-
await transaction.commit();
|
|
61
|
-
const lastInsertId = await transaction.lastInsertId('order_id');
|
|
62
|
-
debug.log(`order created with id ${lastInsertId}`);
|
|
63
|
-
return `order created with id ${lastInsertId}`;
|
|
64
|
-
} catch (err) {
|
|
65
|
-
console.error(`Error occurred while creating order: ${err.message}`, err);
|
|
66
|
-
transaction.rollback();
|
|
67
|
-
console.info('Rollback successful');
|
|
68
|
-
debug.log('error creating order');
|
|
69
|
-
return 'error creating order';
|
|
70
|
-
}
|
|
71
|
-
}
|
|
72
|
-
|
|
73
|
-
main();
|