Skip to content

Commit

Permalink
Fix DB2 storage of binary data in char column (#1307)
Browse files Browse the repository at this point in the history
See #1304

Signed-off-by: Thomas Segismont <[email protected]>
  • Loading branch information
tsegismont committed Apr 11, 2023
1 parent 1d283bb commit 634100d
Show file tree
Hide file tree
Showing 4 changed files with 110 additions and 67 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -67,6 +67,7 @@ private static boolean canConvert(Object val, int type) {
return clazz == Numeric.class;
case ClientTypes.VARCHAR:
return Enum.class.isAssignableFrom(clazz) || Buffer.class.isAssignableFrom(clazz);
case ClientTypes.BINARY:
case ClientTypes.VARBINARY:
return Buffer.class.isAssignableFrom(clazz);
}
Expand Down
122 changes: 81 additions & 41 deletions vertx-db2-client/src/test/java/io/vertx/db2client/DB2DataTypeTest.java
Original file line number Diff line number Diff line change
Expand Up @@ -15,34 +15,35 @@
*/
package io.vertx.db2client;

import static org.junit.Assume.assumeTrue;
import io.vertx.core.buffer.Buffer;
import io.vertx.ext.unit.TestContext;
import io.vertx.ext.unit.junit.VertxUnitRunner;
import io.vertx.sqlclient.Row;
import io.vertx.sqlclient.RowSet;
import io.vertx.sqlclient.Tuple;
import org.junit.Test;
import org.junit.runner.RunWith;

import java.sql.RowId;
import java.time.LocalDateTime;
import java.time.temporal.ChronoField;
import java.util.Arrays;
import java.util.Collections;
import java.util.List;
import java.util.UUID;

import org.junit.Test;
import org.junit.runner.RunWith;

import io.vertx.core.buffer.Buffer;
import io.vertx.ext.unit.TestContext;
import io.vertx.ext.unit.junit.VertxUnitRunner;
import io.vertx.sqlclient.Row;
import io.vertx.sqlclient.RowSet;
import io.vertx.sqlclient.Tuple;
import static org.junit.Assume.assumeTrue;

@RunWith(VertxUnitRunner.class)
public class DB2DataTypeTest extends DB2TestBase {


// Enum for enum testing
// Enum for enum testing
enum Days {
MONDAY, TUESDAY, WEDNESDAY, THURSDAY, FRIDAY, SATURDAY, SUNDAY
}


/**
* In DB2 the FLOAT and DOUBLE column types both map to an 8-byte
* double-precision column (i.e. Java double). Ensure that a Java
Expand Down Expand Up @@ -85,41 +86,75 @@ public void testByteIntoSmallIntColumn(TestContext ctx) {
}));
}

@Test
public void testByteArrayIntoChar(TestContext ctx) {
byte[] param = "hello world".getBytes();
byte[] expected = new byte[255];
Arrays.fill(expected, (byte) 32);
System.arraycopy(param, 0, expected, 0, param.length);
testByteArrayInto(ctx, "test_bytes", param, expected);
}

@Test
public void testByteArrayIntoVarchar(TestContext ctx) {
byte[] expected = "hello world".getBytes();
byte[] param = "hello world".getBytes();
testByteArrayInto(ctx, "test_vbytes", param, param);
}

private void testByteArrayInto(TestContext ctx, String colName, byte[] param, byte[] expected) {
connect(ctx.asyncAssertSuccess(conn -> {
conn.preparedQuery("INSERT INTO db2_types (id,test_bytes) VALUES (?, ?)")
.execute(Tuple.of(3, "hello world".getBytes()), ctx.asyncAssertSuccess(insertResult -> {
conn.preparedQuery("SELECT id,test_bytes FROM db2_types WHERE id = 3")
.execute(ctx.asyncAssertSuccess(rows -> {
ctx.assertEquals(1, rows.size());
Row row = rows.iterator().next();
ctx.assertEquals(3, row.getInteger(0));
ctx.assertTrue(Arrays.equals(expected, row.getBuffer(1).getBytes()),
"Expecting " + Arrays.toString(expected) + " but got "
+ Arrays.toString(row.getBuffer(1).getBytes()));
}));
}));
conn
.preparedQuery("INSERT INTO db2_types (id," + colName + ") VALUES (?, ?)")
.execute(Tuple.of(3, param))
.onComplete(ctx.asyncAssertSuccess(insertResult -> {
conn
.preparedQuery("SELECT id," + colName + " FROM db2_types WHERE id = 3")
.execute()
.onComplete(ctx.asyncAssertSuccess(rows -> {
ctx.assertEquals(1, rows.size());
Row row = rows.iterator().next();
ctx.assertEquals(3, row.getInteger(0));
ctx.assertTrue(Arrays.equals(expected, row.getBuffer(1).getBytes()),
"Expecting " + Arrays.toString(expected) + " but got "
+ Arrays.toString(row.getBuffer(1).getBytes()));
}));
}));
}));
}

@Test
public void testByteBufIntoVarchar(TestContext ctx) {
byte[] expected = "hello world".getBytes();
public void testBufferIntoChar(TestContext ctx) {
byte[] param = "hello world".getBytes();
byte[] expected = new byte[255];
Arrays.fill(expected, (byte) 32);
System.arraycopy(param, 0, expected, 0, param.length);
testBufferInto(ctx, "test_bytes", param, expected);
}

@Test
public void testBufferIntoVarchar(TestContext ctx) {
byte[] param = "hello world".getBytes();
testBufferInto(ctx, "test_vbytes", param, param);
}

private void testBufferInto(TestContext ctx, String colName, byte[] param, byte[] expected) {
connect(ctx.asyncAssertSuccess(conn -> {
conn.preparedQuery("INSERT INTO db2_types (id,test_bytes) VALUES (?, ?)")
.execute(Tuple.of(4, Buffer.buffer(expected)), ctx.asyncAssertSuccess(insertResult -> {
conn.preparedQuery("SELECT id,test_bytes FROM db2_types WHERE id = 4")
.execute(ctx.asyncAssertSuccess(rows -> {
ctx.assertEquals(1, rows.size());
Row row = rows.iterator().next();
ctx.assertEquals(4, row.getInteger(0));
ctx.assertTrue(Arrays.equals(expected, row.getBuffer(1).getBytes()),
"Expecting " + Arrays.toString(expected) + " but got "
+ Arrays.toString(row.getBuffer(1).getBytes()));
}));
}));
conn
.preparedQuery("INSERT INTO db2_types (id," + colName + ") VALUES (?, ?)")
.execute(Tuple.of(4, Buffer.buffer(param)))
.onComplete(ctx.asyncAssertSuccess(insertResult -> {
conn
.preparedQuery("SELECT id," + colName + " FROM db2_types WHERE id = 4")
.execute()
.onComplete(ctx.asyncAssertSuccess(rows -> {
ctx.assertEquals(1, rows.size());
Row row = rows.iterator().next();
ctx.assertEquals(4, row.getInteger(0));
ctx.assertTrue(Arrays.equals(expected, row.getBuffer(1).getBytes()),
"Expecting " + Arrays.toString(expected) + " but got "
+ Arrays.toString(row.getBuffer(1).getBytes()));
}));
}));
}));
}

Expand Down Expand Up @@ -183,7 +218,7 @@ public void testRowId(TestContext ctx) {
}));
}));
}

/**
* Test to support using enum string values in the Row and Tuple methods.
*/
Expand Down Expand Up @@ -221,7 +256,7 @@ public void testUsingEnumOrdinalValue(TestContext ctx) {
}));
}));
}

private RowId verifyRowId(TestContext ctx, RowSet<Row> rows, String msg) {
ctx.assertEquals(1, rows.size());
Row row = rows.iterator().next();
Expand All @@ -231,4 +266,9 @@ private RowId verifyRowId(TestContext ctx, RowSet<Row> rows, String msg) {
ctx.assertEquals(22, rowid.getBytes().length);
return rowid;
}

@Override
protected List<String> tablesToClean() {
return Collections.singletonList("db2_types");
}
}
39 changes: 20 additions & 19 deletions vertx-db2-client/src/test/resources/init.sql
Original file line number Diff line number Diff line change
Expand Up @@ -70,21 +70,21 @@ CREATE TABLE basicdatatype
test_date DATE,
test_time TIME
);
INSERT INTO basicdatatype(id, test_int_2, test_int_4, test_int_8,
test_float_4, test_float_8, test_numeric, test_decimal,
test_boolean, test_char, test_varchar,
INSERT INTO basicdatatype(id, test_int_2, test_int_4, test_int_8,
test_float_4, test_float_8, test_numeric, test_decimal,
test_boolean, test_char, test_varchar,
test_date, test_time)
VALUES (1, 32767, 2147483647, 9223372036854775807,
3.40282E38, 1.7976931348623157E308, 999.99, 12345,
TRUE, 'testchar', 'testvarchar',
VALUES (1, 32767, 2147483647, 9223372036854775807,
3.40282E38, 1.7976931348623157E308, 999.99, 12345,
TRUE, 'testchar', 'testvarchar',
'2019-01-01', '18:45:02');
INSERT INTO basicdatatype(id, test_int_2, test_int_4, test_int_8,
test_float_4, test_float_8, test_numeric, test_decimal,
test_boolean, test_char, test_varchar,
INSERT INTO basicdatatype(id, test_int_2, test_int_4, test_int_8,
test_float_4, test_float_8, test_numeric, test_decimal,
test_boolean, test_char, test_varchar,
test_date, test_time)
VALUES (2, 32767, 2147483647, 9223372036854775807,
3.40282E38, 1.7976931348623157E308, 999.99, 12345,
TRUE, 'testchar', 'testvarchar',
VALUES (2, 32767, 2147483647, 9223372036854775807,
3.40282E38, 1.7976931348623157E308, 999.99, 12345,
TRUE, 'testchar', 'testvarchar',
'2019-01-01', '18:45:02');
INSERT INTO basicdatatype(id, test_int_2, test_int_4, test_int_8, test_float_4, test_float_8, test_numeric, test_decimal, test_boolean, test_char, test_varchar, test_date, test_time)
VALUES (3, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL);
Expand All @@ -109,13 +109,14 @@ INSERT INTO collector_test VALUES (2, 32767, 2147483647, 9223372036854775807, 12
DROP TABLE IF EXISTS db2_types;
CREATE TABLE db2_types
(
id INT,
test_byte SMALLINT,
test_float FLOAT,
test_bytes VARCHAR(255) for bit data,
test_tstamp TIMESTAMP,
test_vchar VARCHAR(255),
test_int INT
id INT,
test_byte SMALLINT,
test_float FLOAT,
test_bytes CHAR(255) for bit data,
test_vbytes VARCHAR(255) for bit data,
test_tstamp TIMESTAMP,
test_vchar VARCHAR(255),
test_int INT
);

-- Sequence used by QueryVariationsTest
Expand Down
15 changes: 8 additions & 7 deletions vertx-db2-client/src/test/resources/init.zos.sql
Original file line number Diff line number Diff line change
Expand Up @@ -119,13 +119,14 @@ CREATE TABLE ROWTEST(
DROP TABLE db2_types;
CREATE TABLE db2_types
(
id INT,
test_byte SMALLINT,
test_float FLOAT,
test_bytes VARCHAR(255) for bit data,
test_tstamp TIMESTAMP,
test_vchar VARCHAR(255),
test_int INT
id INT,
test_byte SMALLINT,
test_float FLOAT,
test_bytes CHAR(255) for bit data,
test_vbytes VARCHAR(255) for bit data,
test_tstamp TIMESTAMP,
test_vchar VARCHAR(255),
test_int INT
);

-- Sequence used by QueryVariationsTest
Expand Down

0 comments on commit 634100d

Please sign in to comment.