Skip to content

Commit 2ad5f0b

Browse files
authored
fix(types): extend QueryValues to callback-based methods (#4129)
* fix(types): extend `QueryValues` to callback methods * ci: add more case tests * ci: rename test file
1 parent b274e72 commit 2ad5f0b

File tree

8 files changed

+76
-43
lines changed

8 files changed

+76
-43
lines changed

test/global/test-load-infile.test.mts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,7 @@ await describe('Load Infile', async () => {
2222
.query<RowDataPacket[]>('SELECT @@GLOBAL.local_infile as backup');
2323
const originalLocalInfile = savedLocalInfile[0].backup;
2424

25+
// @ts-expect-error: strict.ifError is an assertion function incompatible with query callback type
2526
connection.query('SET GLOBAL local_infile = true', strict.ifError);
2627
connection.query(
2728
[
Lines changed: 48 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,48 @@
1+
import type { RowDataPacket } from '../../../index.js';
2+
import { describe, it, strict } from 'poku';
3+
import { createConnection } from '../../common.test.mjs';
4+
5+
await describe('Bind Undefined', async () => {
6+
const connection = createConnection().promise();
7+
8+
await it('execute: should throw TypeError for undefined parameter', async () => {
9+
await strict.rejects(
10+
// @ts-expect-error: testing that undefined bind parameter throws TypeError
11+
connection.execute('SELECT ? AS result', [undefined]),
12+
{
13+
name: 'TypeError',
14+
message:
15+
'Bind parameters must not contain undefined. To pass SQL NULL specify JS null',
16+
}
17+
);
18+
});
19+
20+
await it('execute: should accept undefined as values (no bind parameters)', async () => {
21+
const [results] = await connection.execute<RowDataPacket[]>(
22+
'SELECT 1 AS result',
23+
undefined
24+
);
25+
26+
strict.strictEqual(results[0].result, 1);
27+
});
28+
29+
await it('query: should accept undefined bind parameter as NULL', async () => {
30+
const [results] = await connection.query<RowDataPacket[]>(
31+
'SELECT ? AS result',
32+
[undefined]
33+
);
34+
35+
strict.strictEqual(results[0].result, null);
36+
});
37+
38+
await it('query: should accept undefined as values (no bind parameters)', async () => {
39+
const [results] = await connection.query<RowDataPacket[]>(
40+
'SELECT 1 AS result',
41+
undefined
42+
);
43+
44+
strict.strictEqual(results[0].result, 1);
45+
});
46+
47+
await connection.end();
48+
});

test/integration/connection/test-execute-bind-undefined.test.mts

Lines changed: 0 additions & 30 deletions
This file was deleted.

typings/mysql/lib/protocol/sequences/ExecutableBase.d.ts

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@ import {
33
Query,
44
QueryError,
55
QueryOptions,
6+
ExecuteValues,
67
QueryableConstructor,
78
} from './Query.js';
89

@@ -18,20 +19,20 @@ export declare function ExecutableBase<T extends QueryableConstructor>(
1819
): Query;
1920
execute<T extends QueryResult>(
2021
sql: string,
21-
values: any,
22+
values: ExecuteValues,
2223
callback?:
2324
| ((err: QueryError | null, result: T, fields: FieldPacket[]) => any)
2425
| undefined
2526
): Query;
2627
execute<T extends QueryResult>(
2728
options: QueryOptions,
2829
callback?:
29-
| ((err: QueryError | null, result: T, fields?: FieldPacket[]) => any)
30+
| ((err: QueryError | null, result: T, fields: FieldPacket[]) => any)
3031
| undefined
3132
): Query;
3233
execute<T extends QueryResult>(
3334
options: QueryOptions,
34-
values: any,
35+
values: ExecuteValues,
3536
callback?:
3637
| ((err: QueryError | null, result: T, fields: FieldPacket[]) => any)
3738
| undefined

typings/mysql/lib/protocol/sequences/Query.d.ts

Lines changed: 13 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@ import { Readable } from 'stream';
44
import { Timezone } from 'sql-escaper';
55
import { TypeCast } from '../../parsers/typeCast.js';
66

7-
export type QueryValues =
7+
export type ExecuteValues =
88
| string
99
| number
1010
| bigint
@@ -14,6 +14,18 @@ export type QueryValues =
1414
| Blob
1515
| Buffer
1616
| ({} | null)[]
17+
| { [key: string]: ExecuteValues };
18+
19+
export type QueryValues =
20+
| string
21+
| number
22+
| bigint
23+
| boolean
24+
| Date
25+
| null
26+
| Blob
27+
| Buffer
28+
| ({} | null | undefined)[]
1729
| { [key: string]: QueryValues };
1830

1931
export interface QueryOptions {

typings/mysql/lib/protocol/sequences/QueryableBase.d.ts

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@ import {
33
Query,
44
QueryError,
55
QueryOptions,
6+
QueryValues,
67
QueryableConstructor,
78
} from './Query.js';
89

@@ -18,20 +19,20 @@ export declare function QueryableBase<T extends QueryableConstructor>(
1819
): Query;
1920
query<T extends QueryResult>(
2021
sql: string,
21-
values: any,
22+
values: QueryValues,
2223
callback?:
2324
| ((err: QueryError | null, result: T, fields: FieldPacket[]) => any)
2425
| undefined
2526
): Query;
2627
query<T extends QueryResult>(
2728
options: QueryOptions,
2829
callback?:
29-
| ((err: QueryError | null, result: T, fields?: FieldPacket[]) => any)
30+
| ((err: QueryError | null, result: T, fields: FieldPacket[]) => any)
3031
| undefined
3132
): Query;
3233
query<T extends QueryResult>(
3334
options: QueryOptions,
34-
values: any,
35+
values: QueryValues,
3536
callback?:
3637
| ((err: QueryError | null, result: T, fields: FieldPacket[]) => any)
3738
| undefined
Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,17 +1,17 @@
11
import { FieldPacket, QueryResult } from '../../packets/index.js';
2-
import { QueryOptions, QueryableConstructor, QueryValues } from '../Query.js';
2+
import { QueryOptions, QueryableConstructor, ExecuteValues } from '../Query.js';
33

44
export declare function ExecutableBase<T extends QueryableConstructor>(
55
Base?: T
66
): {
77
new (...args: any[]): {
88
execute<T extends QueryResult>(
99
sql: string,
10-
values?: QueryValues
10+
values?: ExecuteValues
1111
): Promise<[T, FieldPacket[]]>;
1212
execute<T extends QueryResult>(
1313
options: QueryOptions,
14-
values?: QueryValues
14+
values?: ExecuteValues
1515
): Promise<[T, FieldPacket[]]>;
1616
};
1717
} & T;
Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,18 +1,18 @@
11
import { FieldPacket, QueryResult } from '../../packets/index.js';
2-
import { QueryOptions, QueryableConstructor } from '../Query.js';
2+
import { QueryOptions, QueryValues, QueryableConstructor } from '../Query.js';
33

44
export declare function QueryableBase<T extends QueryableConstructor>(
55
Base?: T
66
): {
77
new (...args: any[]): {
88
query<T extends QueryResult>(
99
sql: string,
10-
values?: any
10+
values?: QueryValues
1111
): Promise<[T, FieldPacket[]]>;
1212

1313
query<T extends QueryResult>(
1414
options: QueryOptions,
15-
values?: any
15+
values?: QueryValues
1616
): Promise<[T, FieldPacket[]]>;
1717
};
1818
} & T;

0 commit comments

Comments
 (0)