diff --git a/src/connection.ts b/src/connection.ts index e6d273d45..ffb825a93 100644 --- a/src/connection.ts +++ b/src/connection.ts @@ -3176,6 +3176,7 @@ class Connection extends EventEmitter { request.rowCount! = 0; request.rows! = []; request.rst! = []; + request.error = undefined; const onCancel = () => { payloadStream.unpipe(message); diff --git a/test/integration/prepare-execute-statements-test.ts b/test/integration/prepare-execute-statements-test.ts index af08839f2..8f8db4532 100644 --- a/test/integration/prepare-execute-statements-test.ts +++ b/test/integration/prepare-execute-statements-test.ts @@ -156,6 +156,89 @@ describe('Prepare Execute Statement', function() { }); }); + it('should not persist error state between executions of prepared statement (GH#1712)', function(done) { + const config = getConfig(); + + const connection = new Connection(config); + if (process.env.TEDIOUS_DEBUG) { + connection.on('debug', console.log); + } + + // Prepare a statement that can cause a divide by zero error depending on the parameter + const request = new Request('select 1 / @divisor as result', function() {}); + request.addParameter('divisor', TYPES.Int); + + let executionCount = 0; + const results: (number | null)[] = []; + const errors: (Error | undefined)[] = []; + + request.on('row', function(columns) { + results.push(columns[0].value); + }); + + request.on('prepared', function() { + assert.ok(request.handle); + + // First execution: should succeed with divisor = 1 + request.once('requestCompleted', function() { + executionCount++; + errors.push(request.error); + + // Second execution: should fail with divisor = 0 (divide by zero) + request.once('requestCompleted', function() { + executionCount++; + errors.push(request.error); + + // Third execution: should succeed with divisor = 2 + // Before the fix, this would report the error from the second execution + request.once('requestCompleted', function() { + executionCount++; + errors.push(request.error); + + // Unprepare the statement and wait for it to complete before closing + request.once('requestCompleted', function() { + connection.close(); + }); + connection.unprepare(request); + }); + + connection.execute(request, { divisor: 2 }); + }); + + connection.execute(request, { divisor: 0 }); + }); + + connection.execute(request, { divisor: 1 }); + }); + + connection.connect(function(err) { + if (err) { + return done(err); + } + + connection.prepare(request); + }); + + connection.on('end', function() { + // Verify the behavior + assert.strictEqual(executionCount, 3, 'Should have completed 3 executions'); + + // First execution succeeded + assert.isUndefined(errors[0], 'First execution should have no error'); + assert.strictEqual(results[0], 1, 'First execution should return 1'); + + // Second execution failed with divide by zero + assert.isDefined(errors[1], 'Second execution should have an error'); + assert.include(errors[1]!.message, 'Divide by zero', 'Error should be divide by zero'); + + // Third execution succeeded - this is the key assertion for GH#1712 + assert.isUndefined(errors[2], 'Third execution should have no error (error state should be cleared)'); + assert.strictEqual(results[1], 0, 'Third execution should return 0 (1/2 truncated to int)'); + + done(); + }); + }); + it('should test unprepare', function(done) { const config = getConfig(); const request = new Request('select 3', function(err) {