Skip to content

Commit 67fcd3f

Browse files
committed
Add tests for table joins and subqueries
1 parent 8adfb8b commit 67fcd3f

File tree

8 files changed

+212
-10
lines changed

8 files changed

+212
-10
lines changed

vertx-db2-client/.gitignore

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1 +1,2 @@
11
src/reference/
2+
src/main/examples/Scratch.java

vertx-db2-client/src/main/java/io/vertx/db2client/impl/codec/CommandCodec.java

Lines changed: 0 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -26,7 +26,6 @@ abstract class CommandCodec<R, C extends CommandBase<R>> {
2626
public Throwable failure;
2727
public R result;
2828
final C cmd;
29-
int sequenceId;
3029
DB2Encoder encoder;
3130

3231
CommandCodec(C cmd) {
@@ -48,7 +47,6 @@ ByteBuf allocateBuffer(int capacity) {
4847
}
4948

5049
void sendPacket(ByteBuf packet, int payloadLength) {
51-
// DB2Codec.dumpBuffer(packet);
5250
if (payloadLength >= DB2Codec.PACKET_PAYLOAD_LENGTH_LIMIT) {
5351
/*
5452
* The original packet exceeds the limit of packet length, split the packet
@@ -63,7 +61,6 @@ void sendPacket(ByteBuf packet, int payloadLength) {
6361
}
6462

6563
void sendNonSplitPacket(ByteBuf packet) {
66-
sequenceId++;
6764
encoder.chctx.writeAndFlush(packet);
6865
}
6966
}

vertx-db2-client/src/main/java/io/vertx/db2client/impl/codec/DB2Decoder.java

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -47,7 +47,7 @@ protected void decode(ChannelHandlerContext ctx, ByteBuf in, List<Object> out) t
4747
// wait until we have more bytes to read
4848
return;
4949
}
50-
decodePayload(in.readRetainedSlice(payloadLength), payloadLength, in.getShort(in.readerIndex() + 4));
50+
decodePayload(in.readRetainedSlice(payloadLength), payloadLength);
5151
}
5252

5353
private int computeLength(ByteBuf in) {
@@ -65,9 +65,8 @@ private int computeLength(ByteBuf in) {
6565
return index;
6666
}
6767

68-
private void decodePayload(ByteBuf payload, int payloadLength, int sequenceId) {
68+
private void decodePayload(ByteBuf payload, int payloadLength) {
6969
CommandCodec<?,?> ctx = inflight.peek();
70-
ctx.sequenceId = sequenceId + 1;
7170
int startIndex = payload.readerIndex();
7271
try {
7372
if (LOG.isDebugEnabled())

vertx-db2-client/src/main/java/io/vertx/db2client/impl/drda/ColumnMetaData.java

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -115,6 +115,8 @@ public List<String> getColumnNames() {
115115
}
116116

117117
public String getColumnName(int i) {
118+
if (i < 0)
119+
throw new IllegalArgumentException("Requested column name for negative index: " + i);
118120
// Prefer column names from SQLDXGRP if set
119121
if (sqlxName_ != null && i < sqlxName_.length && sqlxName_[i] != null)
120122
return sqlxName_[i];

vertx-db2-client/src/test/java/io/vertx/db2client/DB2TestBase.java

Lines changed: 17 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,13 @@
11
package io.vertx.db2client;
22

3+
import java.util.Collections;
4+
import java.util.List;
5+
36
import org.junit.After;
47
import org.junit.Before;
58
import org.junit.ClassRule;
9+
import org.junit.Rule;
10+
import org.junit.rules.TestName;
611

712
import io.vertx.core.AsyncResult;
813
import io.vertx.core.Handler;
@@ -21,12 +26,17 @@ public abstract class DB2TestBase {
2126
protected Vertx vertx;
2227
protected Connector<SqlConnection> connector;
2328
protected DB2ConnectOptions options;
29+
30+
@Rule
31+
public TestName testName = new TestName();
2432

2533
@Before
2634
public void setUp(TestContext ctx) throws Exception {
35+
System.out.println(">>> BEGIN " + testName.getMethodName());
2736
vertx = Vertx.vertx();
2837
initConnector();
29-
cleanTestTable(ctx);
38+
for (String table : tablesToClean())
39+
cleanTestTable(ctx, table);
3040
}
3141

3242
@After
@@ -44,12 +54,16 @@ protected void connect(Handler<AsyncResult<SqlConnection>> handler) {
4454
connector.connect(handler);
4555
}
4656

47-
protected void cleanTestTable(TestContext ctx) {
57+
protected void cleanTestTable(TestContext ctx, String table) {
4858
connect(ctx.asyncAssertSuccess(conn -> {
49-
conn.query("DELETE FROM mutable", ctx.asyncAssertSuccess(result -> {
59+
conn.query("DELETE FROM " + table, ctx.asyncAssertSuccess(result -> {
5060
conn.close();
5161
}));
5262
}));
5363
}
64+
65+
protected List<String> tablesToClean() {
66+
return Collections.emptyList();
67+
}
5468

5569
}
Lines changed: 90 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,90 @@
1+
package io.vertx.db2client;
2+
3+
import java.util.Arrays;
4+
5+
import org.junit.Test;
6+
import org.junit.runner.RunWith;
7+
8+
import io.vertx.ext.unit.TestContext;
9+
import io.vertx.ext.unit.junit.VertxUnitRunner;
10+
import io.vertx.sqlclient.Row;
11+
import io.vertx.sqlclient.RowIterator;
12+
import io.vertx.sqlclient.Tuple;
13+
14+
/**
15+
* Tests for subqueries which are documented here:
16+
* https://www.ibm.com/support/knowledgecenter/SSEPEK_10.0.0/intro/src/tpc/db2z_subqueries.html
17+
*/
18+
@RunWith(VertxUnitRunner.class)
19+
public class QueryVariationsTest extends DB2TestBase {
20+
21+
@Test
22+
public void testSubquery(TestContext ctx) {
23+
connect(ctx.asyncAssertSuccess(conn -> {
24+
conn.query("SELECT id,message FROM immutable " +
25+
"WHERE message IN " +
26+
"(SELECT message FROM immutable WHERE id = '4' OR id = '7')",
27+
ctx.asyncAssertSuccess(rowSet -> {
28+
ctx.assertEquals(2, rowSet.size());
29+
ctx.assertEquals(Arrays.asList("ID", "MESSAGE"), rowSet.columnsNames());
30+
RowIterator<Row> rows = rowSet.iterator();
31+
ctx.assertTrue(rows.hasNext());
32+
Row row = rows.next();
33+
ctx.assertEquals(4, row.getInteger(0));
34+
ctx.assertEquals("A bad random number generator: 1, 1, 1, 1, 1, 4.33e+67, 1, 1, 1", row.getString(1));
35+
ctx.assertTrue(rows.hasNext());
36+
row = rows.next();
37+
ctx.assertEquals(7, row.getInteger(0));
38+
ctx.assertEquals("Any program that runs right is obsolete.", row.getString(1));
39+
conn.close();
40+
}));
41+
}));
42+
}
43+
44+
@Test
45+
public void testSubqueryPrepared(TestContext ctx) {
46+
connect(ctx.asyncAssertSuccess(conn -> {
47+
conn.preparedQuery("SELECT id,message FROM immutable " +
48+
"WHERE message IN " +
49+
"(SELECT message FROM immutable WHERE id = ? OR id = ?)",
50+
Tuple.of(4, 7),
51+
ctx.asyncAssertSuccess(rowSet -> {
52+
ctx.assertEquals(2, rowSet.size());
53+
ctx.assertEquals(Arrays.asList("ID", "MESSAGE"), rowSet.columnsNames());
54+
RowIterator<Row> rows = rowSet.iterator();
55+
ctx.assertTrue(rows.hasNext());
56+
Row row = rows.next();
57+
ctx.assertEquals(4, row.getInteger(0));
58+
ctx.assertEquals("A bad random number generator: 1, 1, 1, 1, 1, 4.33e+67, 1, 1, 1", row.getString(1));
59+
ctx.assertTrue(rows.hasNext());
60+
row = rows.next();
61+
ctx.assertEquals(7, row.getInteger(0));
62+
ctx.assertEquals("Any program that runs right is obsolete.", row.getString(1));
63+
conn.close();
64+
}));
65+
}));
66+
}
67+
68+
@Test
69+
public void testLikeQuery(TestContext ctx) {
70+
connect(ctx.asyncAssertSuccess(conn -> {
71+
conn.query("SELECT id,message FROM immutable " +
72+
"WHERE message LIKE '%computer%'",
73+
ctx.asyncAssertSuccess(rowSet -> {
74+
ctx.assertEquals(2, rowSet.size());
75+
ctx.assertEquals(Arrays.asList("ID", "MESSAGE"), rowSet.columnsNames());
76+
RowIterator<Row> rows = rowSet.iterator();
77+
ctx.assertTrue(rows.hasNext());
78+
Row row = rows.next();
79+
ctx.assertEquals(2, row.getInteger(0));
80+
ctx.assertEquals("A computer scientist is someone who fixes things that aren't broken.", row.getString(1));
81+
ctx.assertTrue(rows.hasNext());
82+
row = rows.next();
83+
ctx.assertEquals(5, row.getInteger(0));
84+
ctx.assertEquals("A computer program does what you tell it to do, not what you want it to do.", row.getString(1));
85+
conn.close();
86+
}));
87+
}));
88+
}
89+
90+
}
Lines changed: 100 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,100 @@
1+
package io.vertx.db2client;
2+
3+
import java.util.Arrays;
4+
5+
import org.junit.Test;
6+
import org.junit.runner.RunWith;
7+
8+
import io.vertx.ext.unit.TestContext;
9+
import io.vertx.ext.unit.junit.VertxUnitRunner;
10+
import io.vertx.sqlclient.Row;
11+
12+
/**
13+
* Tests for table joins which are documented here:
14+
* https://www.ibm.com/support/knowledgecenter/SSEPEK_10.0.0/intro/src/tpc/db2z_joindatafromtables.html
15+
*/
16+
@RunWith(VertxUnitRunner.class)
17+
public class TableJoinTest extends DB2TestBase {
18+
19+
@Test
20+
public void testColumnRename(TestContext ctx) {
21+
connect(ctx.asyncAssertSuccess(conn -> {
22+
conn.query("SELECT immutable.id AS \"IMM ID\"," +
23+
"immutable.message AS IMM_MSG," +
24+
"Fortune.id AS FORT_ID," +
25+
"Fortune.message AS \"FORT ID\" FROM immutable " +
26+
"INNER JOIN Fortune ON (immutable.id + 1) = Fortune.id " +
27+
"WHERE immutable.id=1",
28+
ctx.asyncAssertSuccess(rowSet -> {
29+
ctx.assertEquals(1, rowSet.size());
30+
// TODO This is consistent with how JDBC behaves, but we may want to add an API
31+
// to retrieve column labels like JDBC has
32+
ctx.assertEquals(Arrays.asList("ID", "MESSAGE", "ID", "MESSAGE"), rowSet.columnsNames());
33+
Row row = rowSet.iterator().next();
34+
ctx.assertEquals(1, row.getInteger(0));
35+
ctx.assertEquals("fortune: No such file or directory", row.getString(1));
36+
ctx.assertEquals(2, row.getInteger(2));
37+
ctx.assertEquals("A computer scientist is someone who fixes things that aren't broken.", row.getString(3));
38+
conn.close();
39+
}));
40+
}));
41+
}
42+
43+
@Test
44+
public void testInnerJoin(TestContext ctx) {
45+
connect(ctx.asyncAssertSuccess(conn -> {
46+
conn.query("SELECT immutable.id,immutable.message,Fortune.id,Fortune.message FROM immutable " +
47+
"INNER JOIN Fortune ON (immutable.id + 1) = Fortune.id " +
48+
"WHERE immutable.id=1",
49+
ctx.asyncAssertSuccess(rowSet -> {
50+
ctx.assertEquals(1, rowSet.size());
51+
ctx.assertEquals(Arrays.asList("ID", "MESSAGE", "ID", "MESSAGE"), rowSet.columnsNames());
52+
Row row = rowSet.iterator().next();
53+
ctx.assertEquals(1, row.getInteger(0));
54+
ctx.assertEquals("fortune: No such file or directory", row.getString(1));
55+
ctx.assertEquals(2, row.getInteger(2));
56+
ctx.assertEquals("A computer scientist is someone who fixes things that aren't broken.", row.getString(3));
57+
conn.close();
58+
}));
59+
}));
60+
}
61+
62+
@Test
63+
public void testInnerJoinPrepared(TestContext ctx) {
64+
testJoin(ctx, "INNER JOIN");
65+
}
66+
67+
@Test
68+
public void testLeftOuterJoin(TestContext ctx) {
69+
testJoin(ctx, "LEFT OUTER JOIN");
70+
}
71+
72+
@Test
73+
public void testRightOuterJoin(TestContext ctx) {
74+
testJoin(ctx, "RIGHT OUTER JOIN");
75+
}
76+
77+
@Test
78+
public void testFullOuterJoin(TestContext ctx) {
79+
testJoin(ctx, "FULL OUTER JOIN");
80+
}
81+
82+
private void testJoin(TestContext ctx, String joinType) {
83+
connect(ctx.asyncAssertSuccess(conn -> {
84+
conn.preparedQuery("SELECT * FROM immutable " +
85+
joinType + " Fortune ON (immutable.id + 1) = Fortune.id " +
86+
"WHERE immutable.id=1",
87+
ctx.asyncAssertSuccess(rowSet -> {
88+
ctx.assertEquals(1, rowSet.size());
89+
ctx.assertEquals(Arrays.asList("ID", "MESSAGE", "ID", "MESSAGE"), rowSet.columnsNames());
90+
Row row = rowSet.iterator().next();
91+
ctx.assertEquals(1, row.getInteger(0));
92+
ctx.assertEquals("fortune: No such file or directory", row.getString(1));
93+
ctx.assertEquals(2, row.getInteger(2));
94+
ctx.assertEquals("A computer scientist is someone who fixes things that aren't broken.", row.getString(3));
95+
conn.close();
96+
}));
97+
}));
98+
}
99+
100+
}

vertx-sql-client/src/main/java/io/vertx/sqlclient/impl/ListTuple.java

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,6 @@
1919

2020
import io.vertx.sqlclient.Tuple;
2121

22-
import java.util.Iterator;
2322
import java.util.List;
2423

2524
public class ListTuple implements TupleInternal {

0 commit comments

Comments
 (0)