Skip to content

Commit 432051a

Browse files
committed
[CONJS-215] Executing after prepare close throw a wrong error
1 parent 7972f08 commit 432051a

File tree

4 files changed

+141
-0
lines changed

4 files changed

+141
-0
lines changed

lib/cmd/class/prepare-result-packet.js

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
'use strict';
22
const CommandParameter = require('../../command-parameter');
3+
const Errors = require('../../misc/errors');
34

45
/**
56
* Prepare result
@@ -28,6 +29,24 @@ class PrepareResultPacket {
2829
_cb = _opts;
2930
_opts = undefined;
3031
}
32+
33+
if (this.closed) {
34+
const error = Errors.createError(
35+
`Execute fails, prepare command as already been closed`,
36+
Errors.ER_PREPARE_CLOSED,
37+
null,
38+
'22000',
39+
this.query
40+
);
41+
42+
if (!_cb) {
43+
return Promise.reject(error);
44+
} else {
45+
_cb(error);
46+
return;
47+
}
48+
}
49+
3150
const cmdParam = new CommandParameter(this.query, values, _opts, cb);
3251
if (stack) cmdParam.stack = stack;
3352
const promise = new Promise((resolve, reject) => this.#connExecutePromise(cmdParam, this, resolve, reject));

lib/misc/errors.js

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -132,6 +132,7 @@ module.exports.ER_NOT_SUPPORTED_AUTH_PLUGIN = 45047;
132132
module.exports.ER_COMPRESSION_NOT_SUPPORTED = 45048;
133133
module.exports.ER_UNDEFINED_SQL = 45049;
134134
module.exports.ER_PARSING_PRECISION = 45050;
135+
module.exports.ER_PREPARE_CLOSED = 45051;
135136

136137
const keys = Object.keys(module.exports);
137138
const errByNo = {};

test/integration/test-execute-callback.js

Lines changed: 73 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -124,6 +124,79 @@ describe('prepare and execute callback', () => {
124124
});
125125
});
126126

127+
it('prepare after prepare close - no cache', (done) => {
128+
const conn = base.createCallbackConnection({ prepareCacheLength: 0 });
129+
conn.connect((err) => {
130+
if (err) return done(err);
131+
conn.prepare('select ?', (err, prepare) => {
132+
prepare.execute('1', (res) => {
133+
prepare.close();
134+
prepare.execute('1', (err, res) => {
135+
if (!err) {
136+
done(new Error('must have thrown error'));
137+
} else {
138+
assert.isTrue(err.message.includes('Execute fails, prepare command as already been closed'));
139+
conn.prepare('select ?', (err, prepare2) => {
140+
if (err) {
141+
done(err);
142+
} else {
143+
prepare2.execute('1', (res) => {
144+
prepare2.close();
145+
conn.end();
146+
done();
147+
});
148+
}
149+
});
150+
}
151+
});
152+
});
153+
});
154+
});
155+
});
156+
157+
it('prepare after prepare close - with cache', (done) => {
158+
const conn = base.createCallbackConnection({ prepareCacheLength: 2 });
159+
conn.connect((err) => {
160+
if (err) return done(err);
161+
conn.prepare('select ?', (err, prepare) => {
162+
prepare.execute('1', (res) => {
163+
prepare.close();
164+
prepare.execute('1', (err, res) => {
165+
if (err) {
166+
done(err);
167+
} else {
168+
//remove from cache
169+
conn.execute('select 1, ?', ['2']);
170+
conn.execute('select 2, ?', ['2']);
171+
conn.execute('select 3, ?', ['2']);
172+
conn.execute('select 4, ?', ['2'], (err, res) => {
173+
//removed from cache, must really be closed
174+
prepare.execute('1', (err, res) => {
175+
if (!err) {
176+
done(new Error('must have thrown error'));
177+
} else {
178+
assert.isTrue(err.message.includes('Execute fails, prepare command as already been closed'));
179+
conn.prepare('select ?', (err, prepare2) => {
180+
if (err) {
181+
done(err);
182+
} else {
183+
prepare2.execute('1', (res) => {
184+
prepare2.close();
185+
conn.end();
186+
done();
187+
});
188+
}
189+
});
190+
}
191+
});
192+
});
193+
}
194+
});
195+
});
196+
});
197+
});
198+
});
199+
127200
it('prepare cache reuse', (done) => {
128201
const conn = base.createCallbackConnection({ prepareCacheLength: 2 });
129202
conn.connect((err) => {

test/integration/test-execute.js

Lines changed: 48 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -73,6 +73,54 @@ describe('prepare and execute', () => {
7373
conn.end();
7474
});
7575

76+
it('prepare after prepare close - no cache', async () => {
77+
const conn = await base.createConnection({ prepareCacheLength: 0 });
78+
const prepare = await conn.prepare('select ?');
79+
await prepare.execute('1');
80+
await prepare.close();
81+
try {
82+
await prepare.execute('1');
83+
throw new Error('must have thrown error');
84+
} catch (e) {
85+
assert.isTrue(e.message.includes('Execute fails, prepare command as already been closed'));
86+
}
87+
88+
const prepare2 = await conn.prepare('select ?');
89+
await prepare2.execute('2');
90+
await prepare2.close();
91+
92+
conn.end();
93+
});
94+
95+
it('prepare after prepare close - with cache', async () => {
96+
const conn = await base.createConnection({ prepareCacheLength: 2 });
97+
const prepare = await conn.prepare('select ?');
98+
await prepare.execute('1');
99+
await prepare.close();
100+
101+
//in cache, so must still work
102+
await prepare.execute('1');
103+
104+
await conn.execute('select 1, ?', ['2']);
105+
await conn.execute('select 2, ?', ['2']);
106+
await conn.execute('select 3, ?', ['2']);
107+
await conn.execute('select 4, ?', ['2']);
108+
109+
//removed from cache, must really be closed
110+
try {
111+
await prepare.execute('1');
112+
throw new Error('must have thrown error');
113+
} catch (e) {
114+
assert.isTrue(e.message.includes('Execute fails, prepare command as already been closed'));
115+
}
116+
//not in cache, so re-prepare
117+
const prepare2 = await conn.prepare('select ?');
118+
await prepare2.execute('2');
119+
await prepare2.close();
120+
121+
conn.end();
122+
});
123+
76124
it('prepare cache reuse', async () => {
77125
const conn = await base.createConnection({ prepareCacheLength: 2 });
78126
let prepare = await conn.prepare('select ?', [1]);

0 commit comments

Comments
 (0)