[tarantool-patches] Re: [PATCH] jdbc: fix NPE in update

Sergei Kalashnikov ztarvos at gmail.com
Tue Sep 18 12:17:51 MSK 2018


Hi Alexander,

Thank you for the review. Please find my replies inline below.
I also put corrected patch at the very end of this mail.

--
Best Regards,
Sergei Kalashnikov

On Tue, Sep 18, 2018 at 02:06:08AM +0300, Alexander Turenko wrote:
> Hi Sergei!
> 
> The patch looks good for me in general. Minor comments are below.
> 
> WBR, Alexander Turenko.
> 
> On Mon, Sep 17, 2018 at 06:09:14PM +0300, Sergei Kalashnikov wrote:
> > Updated constants to be in sync with tarantool IPROTO.
> > Added integration tests for the working JDBC functionality.
> > Fixed travis script to use tarantool 2.0 which is required for SQL.
> > Fixed failing user permission calls in tarantool initialization script.
> > 
> > Closes #39
> > ---
> > https://github.com/tarantool/tarantool-java/issues/39
> > https://github.com/ztarvos/tarantool-java/commits/ztarvos/gh-39-fix-update-npe
> > 
> > diff --git a/.travis.yml b/.travis.yml
> > index e0f434f..852807c 100644
> > --- a/.travis.yml
> > +++ b/.travis.yml
> > @@ -11,5 +11,5 @@ before_script:
> >    - src/test/travis.pre.sh
> >  
> >  script:
> > -  - mvn test
> > +  - mvn verify
> 
> Maybe we should run both unit and integration tests. The master barnch
> now have one unit test so maybe it worth to leave it here to don't
> forget during future rebase on master.
> 

The 'mvn verify' will execute all the phases prior to 'verify', that includes 'test' goal.
So unit tests will be executed automatically when added/merged.

> > +            "INSERT INTO test_types VALUES(" +
> > +                    "1," +
> > +                    "'abcd'," + //CHAR
> > +                    "'000000000000000000001'," + //VARCHAR
> > +                    "'0000000000000000000000000000000001'," + //LONGVARCHAR
> > +                    "100," + // NUMERIC
> > +                    "100.1," + // DECIMAL
> > +                    "1," + //BIT
> > +                    "7," + //TINYINT
> > +                    "1000," + //SMALLINT
> > +                    "100," + //INTEGER
> > +                    "100000000000000000," + //BIGINT
> > +                    "-100.2," + //REAL
> > +                    "100.3," + //FLOAT
> > +                    "X'01020304'," + //BINARY
> > +                    "X'0102030405'," +//VARBINARY
> > +                    "X'010203040506'," + //LONGVARBINARY
> > +                    "'1983-03-14'," + //DATE
> > +                    "'12:01:06'," + //TIME
> > +                    "129479994)" //TIMESTAMP
> > +    };
> > +
> 
> Can we also store expected values for
> JdbcResultSetIT.{testGetColumnByIdx,testGetColumnByName}() somewhere
> within this class to improve code locality?

Good idea! Done.

Please find below the corrected patch.


>From a34b011acb5d0591758bd0ea3d1a0a967d095fb3 Mon Sep 17 00:00:00 2001
From: Sergei Kalashnikov <ztarvos at gmail.com>
Date: Mon, 17 Sep 2018 13:45:31 +0300
Subject: [PATCH] jdbc: fix NPE in update

Updated constants to be in sync with tarantool IPROTO.
Added integration tests for the working JDBC functionality.
Fixed travis script to use tarantool 2.0 which is required for SQL.
Fixed failing user permission calls in tarantool initialization script.

Closes #39
---
https://github.com/tarantool/tarantool-java/issues/39
https://github.com/ztarvos/tarantool-java/commits/ztarvos/gh-39-fix-update-npe

 .travis.yml                                        |   2 +-
 pom.xml                                            |  13 ++
 src/main/java/org/tarantool/Key.java               |   6 +-
 src/test/instance.lua                              |   4 +-
 .../java/org/tarantool/jdbc/AbstractJdbcIT.java    | 176 +++++++++++++++++++++
 .../java/org/tarantool/jdbc/JdbcConnectionIT.java  |  42 +++++
 .../org/tarantool/jdbc/JdbcDatabaseMetaDataIT.java | 106 +++++++++++++
 .../tarantool/jdbc/JdbcPreparedStatementIT.java    |  67 ++++++++
 .../java/org/tarantool/jdbc/JdbcResultSetIT.java   | 114 +++++++++++++
 .../tarantool/jdbc/JdbcResultSetMetaDataIT.java    |  33 ++++
 .../java/org/tarantool/jdbc/JdbcStatementIT.java   |  66 ++++++++
 src/test/travis.pre.sh                             |   9 +-
 12 files changed, 628 insertions(+), 10 deletions(-)
 create mode 100644 src/test/java/org/tarantool/jdbc/AbstractJdbcIT.java
 create mode 100644 src/test/java/org/tarantool/jdbc/JdbcConnectionIT.java
 create mode 100644 src/test/java/org/tarantool/jdbc/JdbcDatabaseMetaDataIT.java
 create mode 100644 src/test/java/org/tarantool/jdbc/JdbcPreparedStatementIT.java
 create mode 100644 src/test/java/org/tarantool/jdbc/JdbcResultSetIT.java
 create mode 100644 src/test/java/org/tarantool/jdbc/JdbcResultSetMetaDataIT.java
 create mode 100644 src/test/java/org/tarantool/jdbc/JdbcStatementIT.java

diff --git a/.travis.yml b/.travis.yml
index e0f434f..852807c 100644
--- a/.travis.yml
+++ b/.travis.yml
@@ -11,5 +11,5 @@ before_script:
   - src/test/travis.pre.sh
 
 script:
-  - mvn test
+  - mvn verify
   - sudo cat /var/log/tarantool/jdk-testing.log
diff --git a/pom.xml b/pom.xml
index fcabe72..9cf0716 100644
--- a/pom.xml
+++ b/pom.xml
@@ -50,6 +50,19 @@
                 <artifactId>maven-surefire-plugin</artifactId>
                 <version>2.22.0</version>
             </plugin>
+            <plugin>
+                <groupId>org.apache.maven.plugins</groupId>
+                <artifactId>maven-failsafe-plugin</artifactId>
+                <version>2.22.0</version>
+                <executions>
+                    <execution>
+                        <goals>
+                            <goal>integration-test</goal>
+                            <goal>verify</goal>
+                        </goals>
+                    </execution>
+                </executions>
+            </plugin>
         </plugins>
     </build>
 
diff --git a/src/main/java/org/tarantool/Key.java b/src/main/java/org/tarantool/Key.java
index 35a91cd..32e761f 100644
--- a/src/main/java/org/tarantool/Key.java
+++ b/src/main/java/org/tarantool/Key.java
@@ -18,13 +18,13 @@ public enum Key implements Callable<Integer> {
     UPSERT_OPS(0x28),
     DATA(0x30), ERROR(0x31),
 
-    SQL_FIELD_NAME(0x29),
+    SQL_FIELD_NAME(0),
     SQL_METADATA(0x32),
     SQL_TEXT(0x40),
     SQL_BIND(0x41),
     SQL_OPTIONS(0x42),
-    SQL_INFO(0x43),
-    SQL_ROW_COUNT(0x44);
+    SQL_INFO(0x42),
+    SQL_ROW_COUNT(0);
 
     int id;
 
diff --git a/src/test/instance.lua b/src/test/instance.lua
index fe8a80b..a763841 100644
--- a/src/test/instance.lua
+++ b/src/test/instance.lua
@@ -16,7 +16,7 @@ box.once('init', function()
     box.schema.user.create('test_ordin', { password = '2HWRXHfa' })
     box.schema.user.create('test_admin', { password = '4pWBZmLEgkmKK5WP' })
 
-    box.schema.user.grant('test_ordin', 'read,write', 'user')
-    box.schema.user.grant('test_admin', 'execute',    'super')
+    box.schema.user.grant('test_ordin', 'read,write', 'space', 'user')
+    box.schema.user.grant('test_admin', 'super')
 end)
 
diff --git a/src/test/java/org/tarantool/jdbc/AbstractJdbcIT.java b/src/test/java/org/tarantool/jdbc/AbstractJdbcIT.java
new file mode 100644
index 0000000..21e3f53
--- /dev/null
+++ b/src/test/java/org/tarantool/jdbc/AbstractJdbcIT.java
@@ -0,0 +1,176 @@
+package org.tarantool.jdbc;
+
+import org.junit.jupiter.api.AfterAll;
+import org.junit.jupiter.api.AfterEach;
+import org.junit.jupiter.api.BeforeAll;
+import org.junit.jupiter.api.BeforeEach;
+import org.tarantool.TarantoolConnection;
+
+import java.io.IOException;
+import java.math.BigDecimal;
+import java.math.BigInteger;
+import java.net.InetSocketAddress;
+import java.net.Socket;
+import java.sql.Connection;
+import java.sql.Date;
+import java.sql.DriverManager;
+import java.sql.SQLException;
+import java.sql.Time;
+import java.sql.Timestamp;
+import java.util.Arrays;
+import java.util.Collections;
+import java.util.List;
+
+import static org.junit.jupiter.api.Assertions.assertNotNull;
+
+//mvn -DtntHost=localhost -DtntPort=3301 -DtntUser=test -DtntPass=test verify
+public abstract class AbstractJdbcIT {
+    private static final String host = System.getProperty("tntHost", "localhost");
+    private static final Integer port = Integer.valueOf(System.getProperty("tntPort", "3301"));
+    private static final String user = System.getProperty("tntUser", "test_admin");
+    private static final String pass = System.getProperty("tntPass", "4pWBZmLEgkmKK5WP");
+    private static String URL = String.format("tarantool://%s:%d?user=%s&password=%s", host, port, user, pass);
+
+    private static String[] initSql = new String[] {
+            "DROP TABLE IF EXISTS test",
+            "DROP TABLE IF EXISTS test_types",
+
+            "CREATE TABLE test(id INT PRIMARY KEY, val VARCHAR(100))",
+            "INSERT INTO test VALUES (1, 'one'), (2, 'two'), (3, 'three')",
+
+            "CREATE TABLE test_types(" +
+                    "f1 INT PRIMARY KEY, " +
+                    "f2 CHAR(4), " +
+                    "f3 VARCHAR(100), " +
+                    "f4 LONGVARCHAR(100), " +
+                    "f5 NUMERIC, " +
+                    "f6 DECIMAL, " +
+                    "f7 BIT, " +
+                    "f8 TINYINT, " +
+                    "f9 SMALLINT, " +
+                    "f10 INTEGER, " +
+                    "f11 BIGINT," +
+                    "f12 REAL, " +
+                    "f13 FLOAT, " +
+                    "f14 BINARY(4), " +
+                    "f15 VARBINARY(128), " +
+                    "f16 LONGVARBINARY(2048), " +
+                    "f17 DATE, " +
+                    "f18 TIME, " +
+                    "f19 TIMESTAMP)",
+
+            "INSERT INTO test_types VALUES(" +
+                    "1," +
+                    "'abcd'," + //CHAR
+                    "'000000000000000000001'," + //VARCHAR
+                    "'0000000000000000000000000000000001'," + //LONGVARCHAR
+                    "100," + // NUMERIC
+                    "100.1," + // DECIMAL
+                    "1," + //BIT
+                    "7," + //TINYINT
+                    "1000," + //SMALLINT
+                    "100," + //INTEGER
+                    "100000000000000000," + //BIGINT
+                    "-100.2," + //REAL
+                    "100.3," + //FLOAT
+                    "X'01020304'," + //BINARY
+                    "X'0102030405'," +//VARBINARY
+                    "X'010203040506'," + //LONGVARBINARY
+                    "'1983-03-14'," + //DATE
+                    "'12:01:06'," + //TIME
+                    "129479994)" //TIMESTAMP
+    };
+
+    private static String[] cleanSql = new String[] {
+            "DROP TABLE IF EXISTS test",
+            "DROP TABLE IF EXISTS test_types"
+    };
+
+    static Object[] testRow = new Object[] {
+        1,
+        "abcd",
+        "000000000000000000001",
+        "0000000000000000000000000000000001",
+        BigDecimal.valueOf(100),
+        BigDecimal.valueOf(100.1),
+        Boolean.FALSE,
+        (byte)7,
+        (short)1000,
+        100,
+        100000000000000000L,
+        -100.2f,
+        100.3d,
+        new BigInteger("01020304", 16).toByteArray(),
+        new BigInteger("0102030405", 16).toByteArray(),
+        new BigInteger("010203040506", 16).toByteArray(),
+        Date.valueOf("1983-03-14"),
+        Time.valueOf("12:01:06"),
+        new Timestamp(129479994)
+    };
+
+    Connection conn;
+
+    @BeforeAll
+    public static void setupEnv() throws Exception {
+        sqlExec(initSql);
+    }
+
+    @AfterAll
+    public static void teardownEnv() throws Exception {
+        sqlExec(cleanSql);
+    }
+
+    @BeforeEach
+    public void setUpConnection() throws SQLException {
+        conn = DriverManager.getConnection(URL);
+        assertNotNull(conn);
+    }
+
+    @AfterEach
+    public void tearDownConnection() throws SQLException {
+        if (conn != null && !conn.isClosed())
+            conn.close();
+    }
+
+    private static void sqlExec(String[] text) throws IOException {
+        Socket socket = new Socket();
+        try {
+            socket.connect(new InetSocketAddress(host, port));
+            TarantoolConnection con = new TarantoolConnection(user, pass, socket);
+            try {
+                for (String cmd : text)
+                    con.eval("box.sql.execute(\"" + cmd + "\")");
+            }
+            finally {
+                con.close();
+                socket = null;
+            }
+        }
+        finally {
+            if (socket != null)
+                socket.close();
+        }
+    }
+
+    static List<?> getRow(String space, Object key) throws IOException {
+        Socket socket = new Socket();
+        try {
+            socket.connect(new InetSocketAddress(host, port));
+            TarantoolConnection con = new TarantoolConnection(user, pass, socket);
+            try {
+                List<?> l = con.select(281, 2, Arrays.asList(space.toUpperCase()), 0, 1, 0);
+                Integer spaceId = (Integer) ((List) l.get(0)).get(0);
+                l = con.select(spaceId, 0, Arrays.asList(key), 0, 1, 0);
+                return (l == null || l.size() == 0) ? Collections.emptyList() : (List<?>) l.get(0);
+            }
+            finally {
+                con.close();
+                socket = null;
+            }
+        }
+        finally {
+            if (socket != null)
+                socket.close();
+        }
+    }
+}
diff --git a/src/test/java/org/tarantool/jdbc/JdbcConnectionIT.java b/src/test/java/org/tarantool/jdbc/JdbcConnectionIT.java
new file mode 100644
index 0000000..cc6bfb9
--- /dev/null
+++ b/src/test/java/org/tarantool/jdbc/JdbcConnectionIT.java
@@ -0,0 +1,42 @@
+package org.tarantool.jdbc;
+
+import org.junit.jupiter.api.Test;
+
+import java.sql.DatabaseMetaData;
+import java.sql.PreparedStatement;
+import java.sql.SQLException;
+import java.sql.Statement;
+
+import static org.junit.jupiter.api.Assertions.assertFalse;
+import static org.junit.jupiter.api.Assertions.assertNotNull;
+import static org.junit.jupiter.api.Assertions.assertTrue;
+
+public class JdbcConnectionIT extends AbstractJdbcIT {
+    @Test
+    public void testCreateStatement() throws SQLException {
+        Statement stmt = conn.createStatement();
+        assertNotNull(stmt);
+        stmt.close();
+    }
+
+    @Test
+    public void testPrepareStatement() throws SQLException {
+        PreparedStatement prep = conn.prepareStatement("INSERT INTO test(id, val) VALUES(?, ?)");
+        assertNotNull(prep);
+        prep.close();
+    }
+
+    @Test
+    public void testCloseIsClosed() throws SQLException {
+        assertFalse(conn.isClosed());
+        conn.close();
+        assertTrue(conn.isClosed());
+        conn.close();
+    }
+
+    @Test
+    public void testGetMetaData() throws SQLException {
+        DatabaseMetaData meta = conn.getMetaData();
+        assertNotNull(meta);
+    }
+}
\ No newline at end of file
diff --git a/src/test/java/org/tarantool/jdbc/JdbcDatabaseMetaDataIT.java b/src/test/java/org/tarantool/jdbc/JdbcDatabaseMetaDataIT.java
new file mode 100644
index 0000000..b934bbe
--- /dev/null
+++ b/src/test/java/org/tarantool/jdbc/JdbcDatabaseMetaDataIT.java
@@ -0,0 +1,106 @@
+package org.tarantool.jdbc;
+
+import org.junit.jupiter.api.Disabled;
+import org.junit.jupiter.api.Test;
+import org.junit.jupiter.api.BeforeEach;
+
+import java.sql.DatabaseMetaData;
+import java.sql.ResultSet;
+import java.sql.SQLException;
+
+import static org.junit.jupiter.api.Assertions.assertEquals;
+import static org.junit.jupiter.api.Assertions.assertFalse;
+import static org.junit.jupiter.api.Assertions.assertNotNull;
+import static org.junit.jupiter.api.Assertions.assertNull;
+import static org.junit.jupiter.api.Assertions.assertTrue;
+
+public class JdbcDatabaseMetaDataIT extends AbstractJdbcIT {
+    private DatabaseMetaData meta;
+
+    @BeforeEach
+    public void setUp() throws Exception {
+        meta = conn.getMetaData();
+    }
+
+    @Test
+    public void testGetTableTypes() throws SQLException {
+        ResultSet rs = meta.getTableTypes();
+        assertNotNull(rs);
+
+        assertTrue(rs.next());
+        assertEquals("TABLE", rs.getString("TABLE_TYPE"));
+        assertFalse(rs.next());
+
+        rs.close();
+    }
+
+    @Test
+    public void testGetAllTables() throws SQLException {
+        ResultSet rs = meta.getTables(null, null, null, new String[] {"TABLE"});
+        assertNotNull(rs);
+
+        assertTrue(rs.next());
+        assertEquals("TEST", rs.getString("TABLE_NAME"));
+
+        assertTrue(rs.next());
+        assertEquals("TEST_TYPES", rs.getString("TABLE_NAME"));
+
+        assertFalse(rs.next());
+
+        rs.close();
+    }
+
+    @Test
+    public void testGetTable() throws SQLException {
+        ResultSet rs = meta.getTables(null, null, "TEST", new String[] {"TABLE"});
+        assertNotNull(rs);
+        assertTrue(rs.next());
+        assertEquals("TEST", rs.getString("TABLE_NAME"));
+
+        assertFalse(rs.next());
+
+        rs.close();
+    }
+
+    @Test
+    public void testGetColumns() throws SQLException {
+        ResultSet rs = meta.getColumns(null, null, "TEST", null);
+        assertNotNull(rs);
+
+        assertTrue(rs.next());
+
+        assertEquals("TEST", rs.getString("TABLE_NAME"));
+        assertEquals("ID", rs.getString("COLUMN_NAME"));
+        assertEquals(1, rs.getInt("ORDINAL_POSITION"));
+
+        assertTrue(rs.next());
+
+        assertEquals("TEST", rs.getString("TABLE_NAME"));
+        assertEquals("VAL", rs.getString("COLUMN_NAME"));
+        assertEquals(2, rs.getInt("ORDINAL_POSITION"));
+
+        assertFalse(rs.next());
+
+        rs.close();
+    }
+
+    @Disabled(value="Test ignored, issue#41")
+    @Test
+    public void testGetPrimaryKeys() throws SQLException {
+        ResultSet rs = meta.getPrimaryKeys(null, null, "TEST");
+
+        assertNotNull(rs);
+        assertTrue(rs.next());
+
+        assertNull(rs.getString("TABLE_CAT"));
+        assertNull(rs.getString("TABLE_SCHEM"));
+        assertEquals("TEST", rs.getString("TABLE_NAME"));
+        assertEquals("ID", rs.getString("COLUMN_NAME"));
+        assertEquals(1, rs.getInt("KEY_SEQ"));
+        assertEquals("pk_unnamed_TEST_1", rs.getString("PK_NAME"));
+
+        assertFalse(rs.next());
+
+        rs.close();
+    }
+}
diff --git a/src/test/java/org/tarantool/jdbc/JdbcPreparedStatementIT.java b/src/test/java/org/tarantool/jdbc/JdbcPreparedStatementIT.java
new file mode 100644
index 0000000..f356f6b
--- /dev/null
+++ b/src/test/java/org/tarantool/jdbc/JdbcPreparedStatementIT.java
@@ -0,0 +1,67 @@
+package org.tarantool.jdbc;
+
+import org.junit.jupiter.api.Test;
+import org.junit.jupiter.api.AfterEach;
+
+import java.sql.PreparedStatement;
+import java.sql.ResultSet;
+import java.sql.SQLException;
+
+import static org.junit.jupiter.api.Assertions.assertEquals;
+import static org.junit.jupiter.api.Assertions.assertFalse;
+import static org.junit.jupiter.api.Assertions.assertNotNull;
+import static org.junit.jupiter.api.Assertions.assertTrue;
+
+public class JdbcPreparedStatementIT extends AbstractJdbcIT {
+    private PreparedStatement prep;
+
+    @AfterEach
+    public void tearDown() throws SQLException {
+        if (prep != null && !prep.isClosed())
+            prep.close();
+    }
+
+    @Test
+    public void testExecuteQuery() throws SQLException {
+        prep = conn.prepareStatement("SELECT val FROM test WHERE id=?");
+        assertNotNull(prep);
+
+        prep.setInt(1, 1);
+        ResultSet rs = prep.executeQuery();
+        assertNotNull(rs);
+        assertTrue(rs.next());
+        assertEquals("one", rs.getString(1));
+        assertFalse(rs.next());
+        rs.close();
+
+        // Reuse the prepared statement.
+        prep.setInt(1, 2);
+        rs = prep.executeQuery();
+        assertNotNull(rs);
+        assertTrue(rs.next());
+        assertEquals("two", rs.getString(1));
+        assertFalse(rs.next());
+        rs.close();
+    }
+
+    @Test
+    public void testExecuteUpdate() throws Exception {
+        prep = conn.prepareStatement("INSERT INTO test VALUES(?, ?)");
+        assertNotNull(prep);
+
+        prep.setInt(1, 100);
+        prep.setString(2, "hundred");
+        int count = prep.executeUpdate();
+        assertEquals(1, count);
+
+        assertEquals("hundred", getRow("test", 100).get(1));
+
+        // Reuse the prepared statement.
+        prep.setInt(1, 1000);
+        prep.setString(2, "thousand");
+        count = prep.executeUpdate();
+        assertEquals(1, count);
+
+        assertEquals("thousand", getRow("test", 1000).get(1));
+    }
+}
diff --git a/src/test/java/org/tarantool/jdbc/JdbcResultSetIT.java b/src/test/java/org/tarantool/jdbc/JdbcResultSetIT.java
new file mode 100644
index 0000000..4709fba
--- /dev/null
+++ b/src/test/java/org/tarantool/jdbc/JdbcResultSetIT.java
@@ -0,0 +1,114 @@
+package org.tarantool.jdbc;
+
+import org.junit.jupiter.api.AfterEach;
+import org.junit.jupiter.api.Test;
+import org.junit.jupiter.api.BeforeEach;
+
+import java.sql.ResultSet;
+import java.sql.SQLException;
+import java.sql.Statement;
+import java.util.Arrays;
+
+import static org.junit.jupiter.api.Assertions.assertEquals;
+import static org.junit.jupiter.api.Assertions.assertFalse;
+import static org.junit.jupiter.api.Assertions.assertNotNull;
+import static org.junit.jupiter.api.Assertions.assertTrue;
+
+public class JdbcResultSetIT extends AbstractJdbcIT {
+    private Statement stmt;
+
+    @BeforeEach
+    public void setUp() throws Exception {
+        stmt = conn.createStatement();
+    }
+
+    @AfterEach
+    public void tearDown() throws Exception {
+        if (stmt != null && !stmt.isClosed())
+            stmt.close();
+    }
+
+    @Test
+    public void testEmpty() throws SQLException {
+        ResultSet rs = stmt.executeQuery("SELECT * FROM test WHERE id < 0");
+        assertNotNull(rs);
+        assertFalse(rs.next());
+        rs.close();
+    }
+
+    @Test
+    public void testIteration() throws SQLException {
+        ResultSet rs = stmt.executeQuery("SELECT * FROM test WHERE id IN (1,2,3) ORDER BY id");
+        assertNotNull(rs);
+        assertTrue(rs.next());
+        assertEquals(1, rs.getInt(1));
+        assertTrue(rs.next());
+        assertEquals(2, rs.getInt(1));
+        assertTrue(rs.next());
+        assertEquals(3, rs.getInt(1));
+        assertFalse(rs.next());
+        rs.close();
+    }
+
+    @Test
+    public void testGetColumnByIdx() throws SQLException {
+        ResultSet rs = stmt.executeQuery("SELECT * FROM test_types");
+        assertNotNull(rs);
+        assertTrue(rs.next());
+
+        assertEquals(testRow[0], rs.getInt(1));//INT
+        assertEquals(testRow[1], rs.getString(2));//CHAR
+        assertEquals(testRow[2], rs.getString(3));//VARCHAR
+        assertEquals(testRow[3], rs.getString(4)); //LONGVARCHAR
+        assertEquals(testRow[4], rs.getBigDecimal(5));// NUMERIC
+        assertEquals(testRow[5], rs.getBigDecimal(6));// DECIMAL
+        assertEquals(testRow[6], rs.getBoolean(7));//BIT
+        assertEquals(testRow[7], rs.getByte(8));//TINYINT
+        assertEquals(testRow[8], rs.getShort(9));//SMALLINT
+        assertEquals(testRow[9], rs.getInt(10));//INTEGER
+        assertEquals(testRow[10], rs.getLong(11));//BIGINT
+        assertEquals((Float)testRow[11], rs.getFloat(12), 1e-10f);//REAL
+        assertEquals((Double)testRow[12], rs.getDouble(13), 1e-10d);//FLOAT
+        assertTrue(Arrays.equals((byte[])testRow[13], rs.getBytes(14)));//BINARY
+        assertTrue(Arrays.equals((byte[])testRow[14], rs.getBytes(15)));//VARBINARY
+        assertTrue(Arrays.equals((byte[])testRow[15], rs.getBytes(16)));//LONGVARBINARY
+
+        //Issue#44
+        //assertEquals(testRow[16], rs.getDate(17));//DATE
+        //assertEquals(testRow[17], rs.getTime(18));//TIME
+        assertEquals(testRow[18], rs.getTimestamp(19)); //TIMESTAMP
+
+        rs.close();
+    }
+
+    @Test
+    public void testGetColumnByName() throws SQLException {
+        ResultSet rs = stmt.executeQuery("SELECT * FROM test_types");
+        assertNotNull(rs);
+        assertTrue(rs.next());
+
+        assertEquals(testRow[0], rs.getInt("F1"));//INT
+        assertEquals(testRow[1], rs.getString("F2"));//CHAR
+        assertEquals(testRow[2], rs.getString("F3"));//VARCHAR
+        assertEquals(testRow[3], rs.getString("F4")); //LONGVARCHAR
+        assertEquals(testRow[4], rs.getBigDecimal("F5"));// NUMERIC
+        assertEquals(testRow[5], rs.getBigDecimal("F6"));// DECIMAL
+        assertEquals(testRow[6], rs.getBoolean("F7"));//BIT
+        assertEquals(testRow[7], rs.getByte("F8"));//TINYINT
+        assertEquals(testRow[8], rs.getShort("F9"));//SMALLINT
+        assertEquals(testRow[9], rs.getInt("F10"));//INTEGER
+        assertEquals(testRow[10], rs.getLong("F11"));//BIGINT
+        assertEquals((Float)testRow[11], rs.getFloat("F12"), 1e-10f);//REAL
+        assertEquals((Double)testRow[12], rs.getDouble("F13"), 1e-10d);//FLOAT
+        assertTrue(Arrays.equals((byte[])testRow[13], rs.getBytes("F14")));//BINARY
+        assertTrue(Arrays.equals((byte[])testRow[14], rs.getBytes("F15")));//VARBINARY
+        assertTrue(Arrays.equals((byte[])testRow[15], rs.getBytes("F16")));//LONGVARBINARY
+
+        //Issue#44
+        //assertEquals(testRow[16], rs.getDate("F17"));//DATE
+        //assertEquals(testRow[17], rs.getTime("F18"));//TIME
+        assertEquals(testRow[18], rs.getTimestamp("F19")); //TIMESTAMP
+
+        rs.close();
+    }
+}
diff --git a/src/test/java/org/tarantool/jdbc/JdbcResultSetMetaDataIT.java b/src/test/java/org/tarantool/jdbc/JdbcResultSetMetaDataIT.java
new file mode 100644
index 0000000..f90d5b1
--- /dev/null
+++ b/src/test/java/org/tarantool/jdbc/JdbcResultSetMetaDataIT.java
@@ -0,0 +1,33 @@
+package org.tarantool.jdbc;
+
+import org.junit.jupiter.api.Test;
+
+import java.sql.ResultSet;
+import java.sql.ResultSetMetaData;
+import java.sql.SQLException;
+import java.sql.Statement;
+
+import static org.junit.jupiter.api.Assertions.assertEquals;
+import static org.junit.jupiter.api.Assertions.assertNotNull;
+import static org.junit.jupiter.api.Assertions.assertTrue;
+
+public class JdbcResultSetMetaDataIT extends AbstractJdbcIT {
+    @Test
+    public void testColumnNames() throws SQLException {
+        Statement stmt = conn.createStatement();
+        assertNotNull(stmt);
+        ResultSet rs = stmt.executeQuery("SELECT * FROM test_types");
+        assertNotNull(rs);
+        assertTrue(rs.next());
+
+        ResultSetMetaData rsMeta = rs.getMetaData();
+
+        assertEquals(19, rsMeta.getColumnCount());
+
+        for (int i = 1; i <= 19; i++)
+            assertEquals("F" + i, rsMeta.getColumnName(i));
+
+        rs.close();
+        stmt.close();
+    }
+}
diff --git a/src/test/java/org/tarantool/jdbc/JdbcStatementIT.java b/src/test/java/org/tarantool/jdbc/JdbcStatementIT.java
new file mode 100644
index 0000000..925556d
--- /dev/null
+++ b/src/test/java/org/tarantool/jdbc/JdbcStatementIT.java
@@ -0,0 +1,66 @@
+package org.tarantool.jdbc;
+
+import org.junit.jupiter.api.AfterEach;
+import org.junit.jupiter.api.BeforeEach;
+import org.junit.jupiter.api.Test;
+
+import java.sql.ResultSet;
+import java.sql.SQLException;
+import java.sql.Statement;
+
+import static org.junit.jupiter.api.Assertions.assertFalse;
+import static org.junit.jupiter.api.Assertions.assertNotNull;
+import static org.junit.jupiter.api.Assertions.assertTrue;
+import static org.junit.jupiter.api.Assertions.assertEquals;
+
+public class JdbcStatementIT extends AbstractJdbcIT {
+    private Statement stmt;
+
+    @BeforeEach
+    public void setUp() throws SQLException {
+        stmt = conn.createStatement();
+    }
+
+    @AfterEach
+    public void tearDown() throws SQLException {
+        if (stmt != null && !stmt.isClosed())
+            stmt.close();
+    }
+
+    @Test
+    public void testExecuteQuery() throws SQLException {
+        ResultSet rs = stmt.executeQuery("SELECT val FROM test WHERE id=1");
+        assertNotNull(rs);
+        assertTrue(rs.next());
+        assertEquals("one", rs.getString(1));
+        assertFalse(rs.next());
+        rs.close();
+    }
+
+    @Test
+    public void testExecuteUpdate() throws Exception {
+        assertEquals(2, stmt.executeUpdate("INSERT INTO test(id, val) VALUES (10, 'ten'), (20, 'twenty')"));
+        assertEquals("ten", getRow("test", 10).get(1));
+        assertEquals("twenty", getRow("test", 20).get(1));
+    }
+
+    @Test
+    public void testExecuteReturnsResultSet() throws SQLException {
+        assertTrue(stmt.execute("SELECT val FROM test WHERE id=1"));
+        ResultSet rs = stmt.getResultSet();
+        assertNotNull(rs);
+        assertTrue(rs.next());
+        assertEquals("one", rs.getString(1));
+        assertFalse(rs.next());
+        rs.close();
+    }
+
+    @Test
+    public void testExecuteReturnsUpdateCount() throws Exception {
+        assertFalse(stmt.execute("INSERT INTO test(id, val) VALUES (100, 'hundred'), (1000, 'thousand')"));
+        assertEquals(2, stmt.getUpdateCount());
+
+        assertEquals("hundred", getRow("test", 100).get(1));
+        assertEquals("thousand", getRow("test", 1000).get(1));
+    }
+}
\ No newline at end of file
diff --git a/src/test/travis.pre.sh b/src/test/travis.pre.sh
index 86ecdd3..152e75c 100755
--- a/src/test/travis.pre.sh
+++ b/src/test/travis.pre.sh
@@ -2,13 +2,14 @@
 
 set -e 
 
-curl http://download.tarantool.org/tarantool/1.9/gpgkey | sudo apt-key add -
+# We need tarantool 2.0 for jdbc/sql.
+curl http://download.tarantool.org/tarantool/2.0/gpgkey | sudo apt-key add -
 release=`lsb_release -c -s`
 
 sudo rm -f /etc/apt/sources.list.d/*tarantool*.list
-sudo tee /etc/apt/sources.list.d/tarantool_1.9.list <<- EOF
-deb http://download.tarantool.org/tarantool/1.9/ubuntu/ $release main
-deb-src http://download.tarantool.org/tarantool/1.9/ubuntu/ $release main
+sudo tee /etc/apt/sources.list.d/tarantool_2.0.list <<- EOF
+deb http://download.tarantool.org/tarantool/2.0/ubuntu/ $release main
+deb-src http://download.tarantool.org/tarantool/2.0/ubuntu/ $release main
 EOF
 
 sudo apt-get update
-- 
1.8.3.1





More information about the Tarantool-patches mailing list