Skip to content

Commit 78ce495

Browse files
authored
fix(types): add missing types to TypeCast (#2390)
* fix(types): add missing types to TypeCast * chore: add comment on typeCast for execute * ci: create strict tests for typeCast option
1 parent 8dd11b2 commit 78ce495

File tree

4 files changed

+281
-28
lines changed

4 files changed

+281
-28
lines changed
Lines changed: 154 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,154 @@
1+
import { QueryOptions, ConnectionOptions } from '../../../index.js';
2+
import {
3+
QueryOptions as QueryOptionsP,
4+
ConnectionOptions as ConnectionOptionsP,
5+
} from '../../../promise.js';
6+
import { access, sql } from '../promise/baseConnection.js';
7+
8+
// Callback: QueryOptions
9+
{
10+
const options1: QueryOptions = {
11+
sql,
12+
typeCast: true,
13+
};
14+
15+
const options2: QueryOptions = {
16+
sql,
17+
typeCast: false,
18+
};
19+
20+
const options3: QueryOptions = {
21+
sql,
22+
typeCast: (field, next) => {
23+
const db: string = field.db;
24+
const length: number = field.length;
25+
const name: string = field.name;
26+
const table: string = field.table;
27+
const type: string = field.type;
28+
const buffer: Buffer | null = field.buffer();
29+
const string: string | null = field.string();
30+
const geometry:
31+
| { x: number; y: number }
32+
| { x: number; y: number }[]
33+
| null = field.geometry();
34+
35+
console.log(db, length, name, table, type);
36+
console.log(buffer, string, geometry);
37+
38+
return next();
39+
},
40+
};
41+
42+
console.log(options1, options2, options3);
43+
}
44+
45+
// Callback: ConnectionOptions
46+
{
47+
const options1: ConnectionOptions = {
48+
...access,
49+
typeCast: true,
50+
};
51+
52+
const options2: ConnectionOptions = {
53+
...access,
54+
typeCast: false,
55+
};
56+
57+
const options3: ConnectionOptions = {
58+
...access,
59+
typeCast: (field, next) => {
60+
const db: string = field.db;
61+
const length: number = field.length;
62+
const name: string = field.name;
63+
const table: string = field.table;
64+
const type: string = field.type;
65+
const buffer: Buffer | null = field.buffer();
66+
const string: string | null = field.string();
67+
const geometry:
68+
| { x: number; y: number }
69+
| { x: number; y: number }[]
70+
| null = field.geometry();
71+
72+
console.log(db, length, name, table, type);
73+
console.log(buffer, string, geometry);
74+
75+
return next();
76+
},
77+
};
78+
79+
console.log(options1, options2, options3);
80+
}
81+
82+
// Promise: QueryOptions
83+
{
84+
const options1: QueryOptionsP = {
85+
sql,
86+
typeCast: true,
87+
};
88+
89+
const options2: QueryOptionsP = {
90+
sql,
91+
typeCast: false,
92+
};
93+
94+
const options3: QueryOptionsP = {
95+
sql,
96+
typeCast: (field, next) => {
97+
const db: string = field.db;
98+
const length: number = field.length;
99+
const name: string = field.name;
100+
const table: string = field.table;
101+
const type: string = field.type;
102+
const buffer: Buffer | null = field.buffer();
103+
const string: string | null = field.string();
104+
const geometry:
105+
| { x: number; y: number }
106+
| { x: number; y: number }[]
107+
| null = field.geometry();
108+
109+
console.log(db, length, name, table, type);
110+
console.log(buffer, string, geometry);
111+
112+
return next();
113+
},
114+
};
115+
116+
console.log(options1, options2, options3);
117+
}
118+
119+
// Promise: ConnectionOptions
120+
{
121+
const options1: ConnectionOptionsP = {
122+
...access,
123+
typeCast: true,
124+
};
125+
126+
const options2: ConnectionOptionsP = {
127+
...access,
128+
typeCast: false,
129+
};
130+
131+
const options3: ConnectionOptionsP = {
132+
...access,
133+
typeCast: (field, next) => {
134+
const db: string = field.db;
135+
const length: number = field.length;
136+
const name: string = field.name;
137+
const table: string = field.table;
138+
const type: string = field.type;
139+
const buffer: Buffer | null = field.buffer();
140+
const string: string | null = field.string();
141+
const geometry:
142+
| { x: number; y: number }
143+
| { x: number; y: number }[]
144+
| null = field.geometry();
145+
146+
console.log(db, length, name, table, type);
147+
console.log(buffer, string, geometry);
148+
149+
return next();
150+
},
151+
};
152+
153+
console.log(options1, options2, options3);
154+
}

typings/mysql/lib/Connection.d.ts

Lines changed: 36 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,7 @@ import { Connection as PromiseConnection } from '../../../promise.js';
1919
import { AuthPlugin } from './Auth.js';
2020
import { QueryableBase } from './protocol/sequences/QueryableBase.js';
2121
import { ExecutableBase } from './protocol/sequences/ExecutableBase.js';
22+
import { TypeCast } from './parsers/typeCast.js';
2223

2324
export interface SslOptions {
2425
/**
@@ -172,26 +173,48 @@ export interface ConnectionOptions {
172173
infileStreamFactory?: (path: string) => Readable;
173174

174175
/**
175-
* Determines if column values should be converted to native JavaScript types. It is not recommended (and may go away / change in the future)
176-
* to disable type casting, but you can currently do so on either the connection or query level. (Default: true)
176+
* Determines if column values should be converted to native JavaScript types.
177177
*
178-
* You can also specify a function (field: any, next: () => void) => {} to do the type casting yourself.
178+
* @default true
179179
*
180-
* WARNING: YOU MUST INVOKE the parser using one of these three field functions in your custom typeCast callback. They can only be called once.
180+
* It is not recommended (and may go away / change in the future) to disable type casting, but you can currently do so on either the connection or query level.
181181
*
182-
* field.string()
183-
* field.buffer()
184-
* field.geometry()
182+
* ---
185183
*
186-
* are aliases for
184+
* You can also specify a function to do the type casting yourself:
185+
* ```ts
186+
* (field: Field, next: () => void) => {
187+
* return next();
188+
* }
189+
* ```
187190
*
188-
* parser.parseLengthCodedString()
189-
* parser.parseLengthCodedBuffer()
190-
* parser.parseGeometryValue()
191+
* ---
191192
*
192-
* You can find which field function you need to use by looking at: RowDataPacket.prototype._typeCast
193+
* **WARNING:**
194+
*
195+
* YOU MUST INVOKE the parser using one of these three field functions in your custom typeCast callback. They can only be called once:
196+
*
197+
* ```js
198+
* field.string();
199+
* field.buffer();
200+
* field.geometry();
201+
* ```
202+
203+
* Which are aliases for:
204+
*
205+
* ```js
206+
* parser.parseLengthCodedString();
207+
* parser.parseLengthCodedBuffer();
208+
* parser.parseGeometryValue();
209+
* ```
210+
*
211+
* You can find which field function you need to use by looking at `RowDataPacket.prototype._typeCast`.
212+
*
213+
* ---
214+
*
215+
* For `execute`, please see: [typeCast not supported with .execute #649](https://github.com/sidorares/node-mysql2/issues/649).
193216
*/
194-
typeCast?: boolean | ((field: any, next: () => void) => any);
217+
typeCast?: TypeCast;
195218

196219
/**
197220
* A custom query format function
Lines changed: 53 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,53 @@
1+
type Geometry = {
2+
x: number;
3+
y: number;
4+
};
5+
6+
type Type = {
7+
type:
8+
| 'DECIMAL'
9+
| 'TINY'
10+
| 'SHORT'
11+
| 'LONG'
12+
| 'FLOAT'
13+
| 'DOUBLE'
14+
| 'NULL'
15+
| 'TIMESTAMP'
16+
| 'TIMESTAMP2'
17+
| 'LONGLONG'
18+
| 'INT24'
19+
| 'DATE'
20+
| 'TIME'
21+
| 'TIME2'
22+
| 'DATETIME'
23+
| 'DATETIME2'
24+
| 'YEAR'
25+
| 'NEWDATE'
26+
| 'VARCHAR'
27+
| 'BIT'
28+
| 'JSON'
29+
| 'NEWDECIMAL'
30+
| 'ENUM'
31+
| 'SET'
32+
| 'TINY_BLOB'
33+
| 'MEDIUM_BLOB'
34+
| 'LONG_BLOB'
35+
| 'BLOB'
36+
| 'VAR_STRING'
37+
| 'STRING'
38+
| 'GEOMETRY';
39+
};
40+
41+
type Field = Type & {
42+
length: number;
43+
db: string;
44+
table: string;
45+
name: string;
46+
string: () => string | null;
47+
buffer: () => Buffer | null;
48+
geometry: () => Geometry | Geometry[] | null;
49+
};
50+
51+
type Next = () => void;
52+
53+
export type TypeCast = ((field: Field, next: Next) => any) | boolean;

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

Lines changed: 38 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
import { Sequence } from './Sequence.js';
22
import { OkPacket, RowDataPacket, FieldPacket } from '../packets/index.js';
33
import { Readable } from 'stream';
4+
import { TypeCast } from '../../parsers/typeCast.js';
45

56
export interface QueryOptions {
67
/**
@@ -33,26 +34,48 @@ export interface QueryOptions {
3334
nestTables?: any;
3435

3536
/**
36-
* Determines if column values should be converted to native JavaScript types. It is not recommended (and may go away / change in the future)
37-
* to disable type casting, but you can currently do so on either the connection or query level. (Default: true)
37+
* Determines if column values should be converted to native JavaScript types.
3838
*
39-
* You can also specify a function (field: any, next: () => void) => {} to do the type casting yourself.
39+
* @default true
4040
*
41-
* WARNING: YOU MUST INVOKE the parser using one of these three field functions in your custom typeCast callback. They can only be called once.
41+
* It is not recommended (and may go away / change in the future) to disable type casting, but you can currently do so on either the connection or query level.
4242
*
43-
* field.string()
44-
* field.buffer()
45-
* field.geometry()
43+
* ---
4644
*
47-
* are aliases for
45+
* You can also specify a function to do the type casting yourself:
46+
* ```ts
47+
* (field: Field, next: () => void) => {
48+
* return next();
49+
* }
50+
* ```
4851
*
49-
* parser.parseLengthCodedString()
50-
* parser.parseLengthCodedBuffer()
51-
* parser.parseGeometryValue()
52+
* ---
5253
*
53-
* You can find which field function you need to use by looking at: RowDataPacket.prototype._typeCast
54+
* **WARNING:**
55+
*
56+
* YOU MUST INVOKE the parser using one of these three field functions in your custom typeCast callback. They can only be called once:
57+
*
58+
* ```js
59+
* field.string();
60+
* field.buffer();
61+
* field.geometry();
62+
* ```
63+
64+
* Which are aliases for:
65+
*
66+
* ```js
67+
* parser.parseLengthCodedString();
68+
* parser.parseLengthCodedBuffer();
69+
* parser.parseGeometryValue();
70+
* ```
71+
*
72+
* You can find which field function you need to use by looking at `RowDataPacket.prototype._typeCast`.
73+
*
74+
* ---
75+
*
76+
* For `execute`, please see: [typeCast not supported with .execute #649](https://github.com/sidorares/node-mysql2/issues/649).
5477
*/
55-
typeCast?: any;
78+
typeCast?: TypeCast;
5679

5780
/**
5881
* This overrides the same option set at the connection level.
@@ -137,11 +160,11 @@ declare class Query extends Sequence {
137160
on(event: 'error', listener: (err: QueryError) => any): this;
138161
on(
139162
event: 'fields',
140-
listener: (fields: FieldPacket, index: number) => any
163+
listener: (fields: FieldPacket, index: number) => any,
141164
): this;
142165
on(
143166
event: 'result',
144-
listener: (result: RowDataPacket | OkPacket, index: number) => any
167+
listener: (result: RowDataPacket | OkPacket, index: number) => any,
145168
): this;
146169
on(event: 'end', listener: () => any): this;
147170
}

0 commit comments

Comments
 (0)