@benjosivo/mysql 1.0.4 → 1.2.3
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 +28 -0
- package/dist/index.d.ts +22 -0
- package/dist/index.js +44 -0
- package/package.json +5 -1
package/README.md
CHANGED
|
@@ -51,6 +51,34 @@ executeMySQLQuery(query, values?, returnFieldTypes?, connKey?)
|
|
|
51
51
|
|
|
52
52
|
Returns the rows directly on success. On failure it returns `{ error, values, connKey }` instead of throwing (matches `mysql2`'s row-result shape so existing call sites don't need try/catch).
|
|
53
53
|
|
|
54
|
+
### Statements prepared statements can't run
|
|
55
|
+
|
|
56
|
+
`executeMySQLQuery` uses `execute()` (MySQL's prepared-statement protocol), and MySQL rejects a
|
|
57
|
+
number of statements there with *"This command is not supported in the prepared statement protocol
|
|
58
|
+
yet"* — `SET GLOBAL ...`, `USE ...`, `LOCK TABLES`, several `SHOW` variants, and so on. For those,
|
|
59
|
+
use `runMySQLQuery`, which goes through `query()` (text protocol) instead:
|
|
60
|
+
|
|
61
|
+
```ts
|
|
62
|
+
import { runMySQLQuery } from '@benjosivo/mysql';
|
|
63
|
+
|
|
64
|
+
await runMySQLQuery("SET GLOBAL general_log = 'OFF'");
|
|
65
|
+
|
|
66
|
+
// placeholders still work — mysql2 escapes and interpolates them client-side
|
|
67
|
+
await runMySQLQuery('SET GLOBAL general_log = ?', ['OFF']);
|
|
68
|
+
|
|
69
|
+
// optionally run inside an existing transaction
|
|
70
|
+
await runMySQLQuery('SELECT * FROM users WHERE id = ?', [userId], connKey);
|
|
71
|
+
```
|
|
72
|
+
|
|
73
|
+
```ts
|
|
74
|
+
runMySQLQuery(query, values?, connKey?)
|
|
75
|
+
```
|
|
76
|
+
|
|
77
|
+
Same result shape as `executeMySQLQuery`: rows on success, `{ error, values, connKey }` on failure.
|
|
78
|
+
It's deliberately simple — no deadlock/lock-timeout retry — so prefer `executeMySQLQuery` for
|
|
79
|
+
regular application queries and keep this one for statements the prepared-statement protocol
|
|
80
|
+
refuses.
|
|
81
|
+
|
|
54
82
|
### Transactions
|
|
55
83
|
|
|
56
84
|
```ts
|
package/dist/index.d.ts
CHANGED
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import mysql from 'mysql2/promise';
|
|
1
2
|
export interface MySQLClientConfig {
|
|
2
3
|
host: string;
|
|
3
4
|
user: string;
|
|
@@ -24,6 +25,27 @@ export declare function executeMySQLQuery2(opt: {
|
|
|
24
25
|
returnFieldTypes?: boolean;
|
|
25
26
|
returnListTables?: boolean | string;
|
|
26
27
|
}): Promise<any>;
|
|
28
|
+
/**
|
|
29
|
+
* Runs a statement through mysql2's `query()` (text protocol) instead of `execute()`
|
|
30
|
+
* (prepared-statement protocol).
|
|
31
|
+
*
|
|
32
|
+
* MySQL refuses a number of statements in the prepared-statement protocol
|
|
33
|
+
* ("This command is not supported in the prepared statement protocol yet") —
|
|
34
|
+
* `SET GLOBAL ...`, `USE ...`, `LOCK TABLES`, several `SHOW` variants, etc.
|
|
35
|
+
* Use this for those; keep using `executeMySQLQuery` for everything else, since
|
|
36
|
+
* that one adds deadlock/lock-timeout retries and prepared statements.
|
|
37
|
+
*
|
|
38
|
+
* Values are escaped and interpolated client-side by mysql2 (`?` placeholders),
|
|
39
|
+
* so parameters are still safe to pass.
|
|
40
|
+
*
|
|
41
|
+
* Returns the rows on success, or `{ error, values, connKey }` on failure —
|
|
42
|
+
* same shape as `executeMySQLQuery`.
|
|
43
|
+
*/
|
|
44
|
+
export declare function runMySQLQuery(query: string, values?: any[], connKey?: string): Promise<mysql.RowDataPacket[][] | mysql.OkPacket[] | mysql.ResultSetHeader[] | mysql.RowDataPacket[] | mysql.OkPacket | mysql.ResultSetHeader | {
|
|
45
|
+
error: any;
|
|
46
|
+
values: any[];
|
|
47
|
+
connKey: string | null;
|
|
48
|
+
} | [mysql.RowDataPacket[], mysql.ResultSetHeader]>;
|
|
27
49
|
export declare function connectionCommit(keyConn: string): Promise<{
|
|
28
50
|
error?: unknown;
|
|
29
51
|
}>;
|
package/dist/index.js
CHANGED
|
@@ -42,6 +42,7 @@ exports.loopKillOpenTRX = loopKillOpenTRX;
|
|
|
42
42
|
exports.stopLoopKillOpenTRX = stopLoopKillOpenTRX;
|
|
43
43
|
exports.executeMySQLQuery = executeMySQLQuery;
|
|
44
44
|
exports.executeMySQLQuery2 = executeMySQLQuery2;
|
|
45
|
+
exports.runMySQLQuery = runMySQLQuery;
|
|
45
46
|
exports.connectionCommit = connectionCommit;
|
|
46
47
|
exports.connectionRollback = connectionRollback;
|
|
47
48
|
const crypto_1 = require("crypto");
|
|
@@ -369,6 +370,49 @@ async function executeMySQLQuery2(opt) {
|
|
|
369
370
|
return { error: error?.message ?? error, values, connKey: connKey ?? null };
|
|
370
371
|
}
|
|
371
372
|
}
|
|
373
|
+
/**
|
|
374
|
+
* Runs a statement through mysql2's `query()` (text protocol) instead of `execute()`
|
|
375
|
+
* (prepared-statement protocol).
|
|
376
|
+
*
|
|
377
|
+
* MySQL refuses a number of statements in the prepared-statement protocol
|
|
378
|
+
* ("This command is not supported in the prepared statement protocol yet") —
|
|
379
|
+
* `SET GLOBAL ...`, `USE ...`, `LOCK TABLES`, several `SHOW` variants, etc.
|
|
380
|
+
* Use this for those; keep using `executeMySQLQuery` for everything else, since
|
|
381
|
+
* that one adds deadlock/lock-timeout retries and prepared statements.
|
|
382
|
+
*
|
|
383
|
+
* Values are escaped and interpolated client-side by mysql2 (`?` placeholders),
|
|
384
|
+
* so parameters are still safe to pass.
|
|
385
|
+
*
|
|
386
|
+
* Returns the rows on success, or `{ error, values, connKey }` on failure —
|
|
387
|
+
* same shape as `executeMySQLQuery`.
|
|
388
|
+
*/
|
|
389
|
+
async function runMySQLQuery(query, values = [], connKey) {
|
|
390
|
+
requireConfig();
|
|
391
|
+
let conn;
|
|
392
|
+
try {
|
|
393
|
+
if (connKey) {
|
|
394
|
+
const tr = listTransaction.get(connKey);
|
|
395
|
+
if (!tr) {
|
|
396
|
+
const msg = `Transaction key not found: ${connKey}`;
|
|
397
|
+
handleError(msg, 'MySQL: runMySQLQuery');
|
|
398
|
+
return { error: msg, values, connKey };
|
|
399
|
+
}
|
|
400
|
+
tr.lastUpdate = Date.now();
|
|
401
|
+
conn = tr.conn;
|
|
402
|
+
}
|
|
403
|
+
else if (lastConnectionCheck + 5 * 60000 <= Date.now()) {
|
|
404
|
+
await ensurePool();
|
|
405
|
+
}
|
|
406
|
+
const [rows] = await (conn ?? requirePool()).query(query, values);
|
|
407
|
+
return rows;
|
|
408
|
+
}
|
|
409
|
+
catch (error) {
|
|
410
|
+
const errorMsg = String(error?.message ?? error);
|
|
411
|
+
const queryStr = query.length > 200 ? `${query.substring(0, 200)}...` : query;
|
|
412
|
+
handleError(error, `MySQL${error?.code ? ` [${error.code}]` : ''}${connKey ? ' (using connection)' : ''}\n${errorMsg}\n\nparams: ${values}\n\nquery: ${queryStr}`);
|
|
413
|
+
return { error: error?.message ?? error, values, connKey: connKey ?? null };
|
|
414
|
+
}
|
|
415
|
+
}
|
|
372
416
|
async function createTransaction() {
|
|
373
417
|
const keyConn = (0, crypto_1.randomUUID)();
|
|
374
418
|
try {
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@benjosivo/mysql",
|
|
3
|
-
"version": "1.
|
|
3
|
+
"version": "1.2.3",
|
|
4
4
|
"main": "dist/index.js",
|
|
5
5
|
"types": "dist/index.d.ts",
|
|
6
6
|
"files": [
|
|
@@ -18,5 +18,9 @@
|
|
|
18
18
|
"@types/node": "^26.1.2",
|
|
19
19
|
"typescript": "^7.0.2"
|
|
20
20
|
},
|
|
21
|
+
"repository": {
|
|
22
|
+
"type": "git",
|
|
23
|
+
"url": "git+https://github.com/benjosivo/mysql.git"
|
|
24
|
+
},
|
|
21
25
|
"license": "MIT"
|
|
22
26
|
}
|