Skip to content

Commit 0ba4f87

Browse files
committed
Convert function into class to cache the field definition
1 parent 225c5c3 commit 0ba4f87

File tree

6 files changed

+74
-64
lines changed

6 files changed

+74
-64
lines changed

lib/commands/execute.js

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -85,10 +85,10 @@ class Execute extends Command {
8585
if (!packet.isEOF()) {
8686
return connection.protocolError('Expected EOF packet');
8787
}
88-
this._rowParser = this.buildParserFromFields(
88+
this._rowParser = new (this.buildParserFromFields(
8989
this._fields[this._resultIndex],
9090
connection
91-
);
91+
))();
9292
return Execute.prototype.row;
9393
}
9494
}

lib/commands/query.js

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -212,7 +212,7 @@ class Query extends Command {
212212
if (this._receivedFieldsCount === this._fieldCount) {
213213
const fields = this._fields[this._resultIndex];
214214
this.emit('fields', fields);
215-
this._rowParser = getTextParser(fields, this.options, connection.config);
215+
this._rowParser = new (getTextParser(fields, this.options, connection.config))();
216216
return Query.prototype.fieldsEOF;
217217
}
218218
return Query.prototype.readField;
@@ -238,7 +238,7 @@ class Query extends Command {
238238
}
239239
let row;
240240
try {
241-
row = this._rowParser(
241+
row = this._rowParser.next(
242242
packet,
243243
this._fields[this._resultIndex],
244244
this.options,

lib/parsers/binary_parser.js

Lines changed: 6 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -87,10 +87,12 @@ function compile(fields, options, config) {
8787
/* eslint-disable no-spaced-func */
8888
/* eslint-disable no-unexpected-multiline */
8989

90-
parserFn('(function(){')(
91-
'return function BinaryRow(packet, fields, options, CharsetToEncoding) {'
92-
);
90+
parserFn('(function(){');
91+
parserFn('return class BinaryRow {');
92+
parserFn('constructor() {');
93+
parserFn('}');
9394

95+
parserFn('next(packet, fields, options) {');
9496
if (options.rowsAsArray) {
9597
parserFn(`const result = new Array(${fields.length});`);
9698
} else {
@@ -161,7 +163,7 @@ function compile(fields, options, config) {
161163
}
162164

163165
parserFn('return result;');
164-
166+
parserFn('}');
165167
parserFn('};')('})()');
166168

167169
/* eslint-enable no-trailing-spaces */

lib/parsers/parser_cache.js

Lines changed: 1 addition & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -20,13 +20,7 @@ function keyFromFields(type, fields, options, config) {
2020
`/${options.dateStrings}`;
2121
for (let i = 0; i < fields.length; ++i) {
2222
const field = fields[i];
23-
res += `/${field.name}:${field.columnType}:${field.flags}:${
24-
field.characterSet
25-
}`;
26-
27-
if (options.nestTables) {
28-
res += `:${field.table}`
29-
}
23+
res += `/${field.name}:${field.columnType}:${field.length}:${field.schema}:${field.table}:${field.flags}:${field.characterSet}`;
3024
}
3125
return res;
3226
}

lib/parsers/text_parser.js

Lines changed: 58 additions & 46 deletions
Original file line numberDiff line numberDiff line change
@@ -70,27 +70,6 @@ function readCodeFor(type, charset, encodingExpr, config, options) {
7070
}
7171

7272
function compile(fields, options, config) {
73-
// node-mysql typeCast compatibility wrapper
74-
// see https://github.com/mysqljs/mysql/blob/96fdd0566b654436624e2375c7b6604b1f50f825/lib/protocol/packets/Field.js
75-
function wrap(field, type, packet, encoding) {
76-
return {
77-
type: type,
78-
length: field.columnLength,
79-
db: field.schema,
80-
table: field.table,
81-
name: field.name,
82-
string: function() {
83-
return packet.readLengthCodedString(encoding);
84-
},
85-
buffer: function() {
86-
return packet.readLengthCodedBuffer();
87-
},
88-
geometry: function() {
89-
return packet.parseGeometryValue();
90-
}
91-
};
92-
}
93-
9473
// use global typeCast if current query doesn't specify one
9574
if (
9675
typeof config.typeCast === 'function' &&
@@ -100,41 +79,78 @@ function compile(fields, options, config) {
10079
}
10180

10281
const parserFn = genFunc();
103-
let i = 0;
10482

10583
/* eslint-disable no-trailing-spaces */
10684
/* eslint-disable no-spaced-func */
10785
/* eslint-disable no-unexpected-multiline */
10886
parserFn('(function () {')(
109-
'return function TextRow(packet, fields, options, CharsetToEncoding) {'
87+
'return class TextRow {'
11088
);
11189

112-
if (options.rowsAsArray) {
113-
parserFn(`const result = new Array(${fields.length})`);
114-
} else {
115-
parserFn("const result = {}");
90+
// constructor method
91+
parserFn('constructor() {');
92+
// node-mysql typeCast compatibility wrapper
93+
// see https://github.com/mysqljs/mysql/blob/96fdd0566b654436624e2375c7b6604b1f50f825/lib/protocol/packets/Field.js
94+
if (typeof options.typeCast === 'function') {
95+
parserFn('const _this = this;');
96+
for(let i=0; i<fields.length; ++i) {
97+
const field = fields[i];
98+
const encodingExpr = `fields[${i}].encoding`;
99+
const readCode = readCodeFor(
100+
fields[i].columnType,
101+
fields[i].characterSet,
102+
encodingExpr,
103+
config,
104+
options
105+
);
106+
parserFn(`this.wrap${i} = {
107+
type: ${helpers.srcEscape(typeNames[field.columnType])},
108+
length: ${helpers.srcEscape(field.columnLength)},
109+
db: ${helpers.srcEscape(field.schema)},
110+
table: ${helpers.srcEscape(field.table)},
111+
name: ${helpers.srcEscape(field.name)},
112+
string: function() {
113+
return _this.packet.readLengthCodedString(${helpers.srcEscape(field.encoding)});
114+
},
115+
buffer: function() {
116+
return _this.packet.readLengthCodedBuffer();
117+
},
118+
geometry: function() {
119+
return _this.packet.parseGeometryValue();
120+
},
121+
readNext: function() {
122+
return _this.${readCode};
123+
}
124+
};`);
125+
}
116126
}
127+
parserFn('}');
117128

118-
if (typeof options.typeCast === 'function') {
119-
parserFn(`const wrap = ${wrap.toString()}`);
129+
// next method
130+
parserFn('next(packet, fields, options) {');
131+
parserFn("this.packet = packet;");
132+
if (options.rowsAsArray) {
133+
parserFn(`const result = new Array(${fields.length});`);
134+
} else {
135+
parserFn("const result = {};");
120136
}
121137

122138
const resultTables = {};
123139
let resultTablesArray = [];
124140

125141
if (options.nestTables === true) {
126-
for (i = 0; i < fields.length; i++) {
142+
for (let i=0; i < fields.length; i++) {
127143
resultTables[fields[i].table] = 1;
128144
}
129145
resultTablesArray = Object.keys(resultTables);
130-
for (i = 0; i < resultTablesArray.length; i++) {
146+
for (let i=0; i < resultTablesArray.length; i++) {
131147
parserFn(`result[${helpers.srcEscape(resultTablesArray[i])}] = {};`);
132148
}
133149
}
134150

135151
let lvalue = '';
136152
let fieldName = '';
137-
for (i = 0; i < fields.length; i++) {
153+
for (let i = 0; i < fields.length; i++) {
138154
fieldName = helpers.srcEscape(fields[i].name);
139155
parserFn(`// ${fieldName}: ${typeNames[fields[i].columnType]}`);
140156
if (typeof options.nestTables === 'string') {
@@ -148,29 +164,25 @@ function compile(fields, options, config) {
148164
} else {
149165
lvalue = `result[${fieldName}]`;
150166
}
151-
const encodingExpr = `CharsetToEncoding[fields[${i}].characterSet]`;
152-
const readCode = readCodeFor(
153-
fields[i].columnType,
154-
fields[i].characterSet,
155-
encodingExpr,
156-
config,
157-
options
158-
);
159167
if (typeof options.typeCast === 'function') {
160-
parserFn(
161-
`${lvalue} = options.typeCast(wrap(fields[${i}], ${helpers.srcEscape(
162-
typeNames[fields[i].columnType]
163-
)}, packet, ${encodingExpr}), function() { return ${readCode};})`
164-
);
168+
parserFn(`${lvalue} = options.typeCast(this.wrap${i}, this.wrap${i}.readNext);`);
165169
} else if (options.typeCast === false) {
166170
parserFn(`${lvalue} = packet.readLengthCodedBuffer();`);
167171
} else {
172+
const encodingExpr = `fields[${i}].encoding`;
173+
const readCode = readCodeFor(
174+
fields[i].columnType,
175+
fields[i].characterSet,
176+
encodingExpr,
177+
config,
178+
options
179+
);
168180
parserFn(`${lvalue} = ${readCode};`);
169181
}
170182
}
171183

172184
parserFn('return result;');
173-
185+
parserFn('}');
174186
parserFn('};')('})()');
175187

176188
/* eslint-enable no-trailing-spaces */

test/unit/commands/test-query.js

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -9,9 +9,11 @@ const testQuery = new Query({}, (err, res) => {
99
assert.equal(res, null);
1010
});
1111

12-
testQuery._rowParser = function FailingRowParser() {
13-
throw testError;
14-
}
12+
testQuery._rowParser = new class FailingRowParser {
13+
next() {
14+
throw testError;
15+
}
16+
}();
1517

1618
testQuery.row({
1719
isEOF: () => false

0 commit comments

Comments
 (0)