Skip to content

Commit 9c632cd

Browse files
authored
Sql Server Client may report an IndexOutOfBoundsException when using cursor (#1583)
See #1582 When using cursors, and the number of columns in the query result is a multiple of 8, and some of them have the NULL value, the client may report an IndexOutOfBoundsException. This happens because with cursors, there is an extra ROWSTAT column on the wire that wasn't accounted for by the NBCROW decoder. Signed-off-by: Thomas Segismont <[email protected]>
1 parent d1a5928 commit 9c632cd

File tree

3 files changed

+45
-1
lines changed

3 files changed

+45
-1
lines changed

vertx-mssql-client/src/main/java/io/vertx/mssqlclient/impl/codec/RowResultDecoder.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -68,7 +68,7 @@ private boolean ifNotMissing(ByteBuf in, Row row) {
6868

6969
private boolean decodeMssqlNbcRow(ByteBuf in, Row row) {
7070
int len = desc.size();
71-
int nullBitmapByteCount = ((len - 1) >> 3) + 1;
71+
int nullBitmapByteCount = (len - (desc.hasRowStat() ? 0 : 1) >> 3) + 1;
7272
int nullBitMapStartIdx = in.readerIndex();
7373
in.skipBytes(nullBitmapByteCount);
7474

vertx-mssql-client/src/test/java/io/vertx/tests/mssqlclient/tck/MSSQLPreparedQueryTestBase.java

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -101,5 +101,28 @@ public void failureWhenPreparingCursor(TestContext ctx) {
101101
}));
102102
}));
103103
}
104+
105+
@Test
106+
public void testNbcRowWithCursor(TestContext ctx) {
107+
Async async = ctx.async();
108+
connect(ctx.asyncAssertSuccess(conn -> {
109+
conn.prepare("SELECT * FROM nbcrow_with_rowstat").onComplete(ctx.asyncAssertSuccess(ps -> {
110+
ps.createStream(50)
111+
.exceptionHandler(ctx::fail)
112+
.handler(row -> {
113+
// Make sure NbcRow handling is correct when the number of columns is a multiple of 8
114+
ctx.assertEquals(0, row.size() % 8);
115+
for (int i = 1; i <= 8; i++) {
116+
if (i % 2 != 0) {
117+
ctx.assertEquals(String.valueOf(i), row.getString(i - 1));
118+
} else {
119+
ctx.assertNull(row.getString(i - 1));
120+
}
121+
}
122+
})
123+
.endHandler(v -> async.complete());
124+
}));
125+
}));
126+
}
104127
}
105128

vertx-mssql-client/src/test/resources/init.sql

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -310,3 +310,24 @@ VALUES (2, 32767, 2147483647, 9223372036854775807, 123.456, 1.234567, 'hello,wor
310310
GO
311311

312312
-- TCK usage --
313+
314+
-- Table for testing NBCROW with a cursor
315+
DROP TABLE IF EXISTS nbcrow_with_rowstat;
316+
CREATE TABLE nbcrow_with_rowstat
317+
(
318+
test_varchar_1 VARCHAR(20),
319+
test_varchar_2 VARCHAR(20),
320+
test_varchar_3 VARCHAR(20),
321+
test_varchar_4 VARCHAR(20),
322+
test_varchar_5 VARCHAR(20),
323+
test_varchar_6 VARCHAR(20),
324+
test_varchar_7 VARCHAR(20),
325+
test_varchar_8 VARCHAR(20),
326+
);
327+
328+
INSERT INTO nbcrow_with_rowstat
329+
VALUES ('1', NULL, '3', NULL, '5', NULL, '7', NULL);
330+
331+
GO
332+
333+
-- Table for testing NBCROW with a cursor

0 commit comments

Comments
 (0)