This is an automated email from the ASF dual-hosted git repository.

jooger pushed a commit to branch jdbc_over_thin_sql
in repository https://gitbox.apache.org/repos/asf/ignite-3.git


The following commit(s) were added to refs/heads/jdbc_over_thin_sql by this 
push:
     new eb7f248bfc8 IGNITE-26417 Jdbc. DatabaseMetadata for thin client backed 
connection (#6581)
eb7f248bfc8 is described below

commit eb7f248bfc8b0a80b17304bad70ddffc34cb30c1
Author: Max Zhuravkov <[email protected]>
AuthorDate: Mon Sep 15 14:41:56 2025 +0300

    IGNITE-26417 Jdbc. DatabaseMetadata for thin client backed connection 
(#6581)
---
 .../internal/jdbc/ItJdbcMetadataSelfTest.java      | 833 ++++++++++++++++-----
 .../jdbc/ItJdbcParameterMetadataSelfTest.java      | 149 ++++
 .../jdbc/ItJdbcResultSetMetadataSelfTest.java      | 100 +++
 .../ignite/jdbc/ItJdbcAuthenticationTest.java      |   6 +
 .../ignite/internal/jdbc/JdbcConnection.java       |   2 +-
 .../ignite/internal/jdbc/JdbcDatabaseMetadata.java | 150 ++--
 .../jdbc/JdbcDatabaseMetadataSelfTest.java         | 274 +++++++
 7 files changed, 1265 insertions(+), 249 deletions(-)

diff --git 
a/modules/jdbc/src/integrationTest/java/org/apache/ignite/internal/jdbc/ItJdbcMetadataSelfTest.java
 
b/modules/jdbc/src/integrationTest/java/org/apache/ignite/internal/jdbc/ItJdbcMetadataSelfTest.java
index 8b77feb3aaa..96988a37ffd 100644
--- 
a/modules/jdbc/src/integrationTest/java/org/apache/ignite/internal/jdbc/ItJdbcMetadataSelfTest.java
+++ 
b/modules/jdbc/src/integrationTest/java/org/apache/ignite/internal/jdbc/ItJdbcMetadataSelfTest.java
@@ -26,8 +26,6 @@ import java.math.BigDecimal;
 import java.sql.Connection;
 import java.sql.DatabaseMetaData;
 import java.sql.DriverManager;
-import java.sql.ParameterMetaData;
-import java.sql.PreparedStatement;
 import java.sql.ResultSet;
 import java.sql.ResultSetMetaData;
 import java.sql.SQLException;
@@ -38,19 +36,17 @@ import java.util.Arrays;
 import java.util.List;
 import java.util.StringJoiner;
 import java.util.UUID;
-import org.apache.ignite.internal.client.proto.ProtocolVersion;
 import org.apache.ignite.internal.jdbc.proto.event.JdbcColumnMeta;
 import org.apache.ignite.internal.sql.engine.util.SqlTestUtils;
 import org.apache.ignite.internal.type.NativeType;
 import org.apache.ignite.jdbc.AbstractJdbcSelfTest;
-import org.apache.ignite.jdbc.util.JdbcTestUtils;
 import org.apache.ignite.sql.ColumnType;
 import org.junit.jupiter.api.BeforeAll;
 import org.junit.jupiter.api.Disabled;
 import org.junit.jupiter.api.Test;
 
 /**
- * Metadata tests.
+ * Tests for {@link DatabaseMetaData}.
  */
 public class ItJdbcMetadataSelfTest extends AbstractJdbcSelfTest {
     /** Creates tables. */
@@ -74,56 +70,6 @@ public class ItJdbcMetadataSelfTest extends 
AbstractJdbcSelfTest {
         }
     }
 
-    @Test
-    public void testNullValuesMetaData() throws Exception {
-        ResultSet rs = stmt.executeQuery(
-                "select NULL, substring(null, 1, 2)");
-
-        assertNotNull(rs);
-
-        ResultSetMetaData meta = rs.getMetaData();
-
-        assertNotNull(meta);
-
-        assertEquals(2, meta.getColumnCount());
-
-        assertEquals(Types.NULL, meta.getColumnType(1));
-        assertEquals("NULL", meta.getColumnTypeName(1));
-        assertEquals("java.lang.Void", meta.getColumnClassName(1));
-
-        assertEquals(Types.NULL, meta.getColumnType(2));
-        assertEquals("NULL", meta.getColumnTypeName(2));
-        assertEquals("java.lang.Void", meta.getColumnClassName(2));
-    }
-
-    @Test
-    public void testResultSetMetaData() throws Exception {
-        ResultSet rs = stmt.executeQuery(
-                "select p.name, o.id as orgId, p.age from PERSON p, 
ORGANIZATION o where p.orgId = o.id");
-
-        assertNotNull(rs);
-
-        ResultSetMetaData meta = rs.getMetaData();
-
-        assertNotNull(meta);
-
-        assertEquals(3, meta.getColumnCount());
-
-        assertEquals("Person".toUpperCase(), 
meta.getTableName(1).toUpperCase());
-        assertEquals("name".toUpperCase(), 
meta.getColumnName(1).toUpperCase());
-        assertEquals("name".toUpperCase(), 
meta.getColumnLabel(1).toUpperCase());
-        assertEquals(Types.VARCHAR, meta.getColumnType(1));
-        assertEquals("VARCHAR", meta.getColumnTypeName(1));
-        assertEquals("java.lang.String", meta.getColumnClassName(1));
-
-        assertEquals("Organization".toUpperCase(), 
meta.getTableName(2).toUpperCase());
-        assertEquals("id".toUpperCase(), meta.getColumnName(2).toUpperCase());
-        assertEquals("orgId".toUpperCase(), 
meta.getColumnLabel(2).toUpperCase());
-        assertEquals(Types.INTEGER, meta.getColumnType(2));
-        assertEquals("INTEGER", meta.getColumnTypeName(2));
-        assertEquals("java.lang.Integer", meta.getColumnClassName(2));
-    }
-
     @Test
     public void testDatabaseMetaDataColumns() throws Exception {
         createMetaTable();
@@ -289,6 +235,21 @@ public class ItJdbcMetadataSelfTest extends 
AbstractJdbcSelfTest {
     public void testGetTables() throws Exception {
         DatabaseMetaData meta = conn.getMetaData();
 
+        try (ResultSet rs = meta.getTables(null, null, null, null)) {
+            ResultSetMetaData metaData = rs.getMetaData();
+
+            expectColumn(metaData, 1, "TABLE_CAT", Types.VARCHAR);
+            expectColumn(metaData, 2, "TABLE_SCHEM", Types.VARCHAR);
+            expectColumn(metaData, 3, "TABLE_NAME", Types.VARCHAR);
+            expectColumn(metaData, 4, "TABLE_TYPE", Types.VARCHAR);
+            expectColumn(metaData, 5, "REMARKS", Types.VARCHAR);
+            expectColumn(metaData, 6, "TYPE_CAT", Types.VARCHAR);
+            expectColumn(metaData, 7, "TYPE_SCHEM", Types.VARCHAR);
+            expectColumn(metaData, 8, "TYPE_NAME", Types.VARCHAR);
+            expectColumn(metaData, 9, "SELF_REFERENCING_COL_NAME", 
Types.VARCHAR);
+            expectColumn(metaData, 10, "REF_GENERATION", Types.VARCHAR);
+        }
+
         // PUBLIC tables.
         {
             try (ResultSet rs = meta.getTables("IGNITE", "PUBLIC", "%", new 
String[]{"TABLE"})) {
@@ -402,6 +363,37 @@ public class ItJdbcMetadataSelfTest extends 
AbstractJdbcSelfTest {
     public void testGetColumns() throws Exception {
         DatabaseMetaData meta = conn.getMetaData();
 
+        try (ResultSet rs = meta.getColumns(null, null, null, null)) {
+            ResultSetMetaData metaData = rs.getMetaData();
+
+            expectColumn(metaData, 1, "TABLE_CAT", Types.VARCHAR);
+            expectColumn(metaData, 2, "TABLE_SCHEM", Types.VARCHAR);
+            expectColumn(metaData, 3, "TABLE_NAME", Types.VARCHAR);
+            expectColumn(metaData, 4, "COLUMN_NAME", Types.VARCHAR);
+            expectColumn(metaData, 5, "DATA_TYPE", Types.SMALLINT);
+            expectColumn(metaData, 6, "TYPE_NAME", Types.VARCHAR);
+            expectColumn(metaData, 7, "COLUMN_SIZE", Types.INTEGER);
+            expectColumn(metaData, 8, "BUFFER_LENGTH", Types.INTEGER);
+            expectColumn(metaData, 9, "DECIMAL_DIGITS", Types.INTEGER);
+            expectColumn(metaData, 10, "NUM_PREC_RADIX", Types.SMALLINT);
+            expectColumn(metaData, 11, "NULLABLE", Types.SMALLINT);
+            expectColumn(metaData, 12, "REMARKS", Types.VARCHAR);
+            expectColumn(metaData, 13, "COLUMN_DEF", Types.VARCHAR);
+            expectColumn(metaData, 14, "SQL_DATA_TYPE", Types.INTEGER);
+            expectColumn(metaData, 15, "SQL_DATETIME_SUB", Types.INTEGER);
+            expectColumn(metaData, 16, "CHAR_OCTET_LENGTH", Types.INTEGER);
+            expectColumn(metaData, 17, "ORDINAL_POSITION", Types.INTEGER);
+            expectColumn(metaData, 18, "IS_NULLABLE", Types.VARCHAR);
+            expectColumn(metaData, 19, "SCOPE_CATLOG", Types.VARCHAR);
+            expectColumn(metaData, 20, "SCOPE_SCHEMA", Types.VARCHAR);
+            expectColumn(metaData, 21, "SCOPE_TABLE", Types.VARCHAR);
+            expectColumn(metaData, 22, "SOURCE_DATA_TYPE", Types.SMALLINT);
+            expectColumn(metaData, 23, "IS_AUTOINCREMENT", Types.VARCHAR);
+            expectColumn(metaData, 24, "IS_GENERATEDCOLUMN", Types.VARCHAR);
+
+            assertEquals(24, metaData.getColumnCount());
+        }
+
         // Tables.
         {
             ResultSet rs = meta.getColumns("IGNITE", "PUBLIC", "%", "%");
@@ -460,11 +452,130 @@ public class ItJdbcMetadataSelfTest extends 
AbstractJdbcSelfTest {
         }
     }
 
+    @Test
+    public void testGetColumnPrivileges() throws SQLException {
+        DatabaseMetaData meta = conn.getMetaData();
+
+        try (ResultSet rs = meta.getColumnPrivileges(null, null, null, null)) {
+            ResultSetMetaData metaData = rs.getMetaData();
+
+            expectColumn(metaData, 1, "TABLE_CAT", Types.VARCHAR);
+            expectColumn(metaData, 2, "TABLE_SCHEM", Types.VARCHAR);
+            expectColumn(metaData, 3, "TABLE_NAME", Types.VARCHAR);
+            expectColumn(metaData, 4, "COLUMN_NAME", Types.VARCHAR);
+            expectColumn(metaData, 5, "GRANTOR", Types.VARCHAR);
+            expectColumn(metaData, 6, "GRANTEE", Types.VARCHAR);
+            expectColumn(metaData, 7, "PRIVILEGE", Types.VARCHAR);
+            expectColumn(metaData, 8, "IS_GRANTABLE", Types.VARCHAR);
+
+            assertEquals(8, metaData.getColumnCount());
+
+            // The driver does not provide this information
+            assertFalse(rs.next());
+        }
+    }
+
+    @Test
+    public void testGetTablePrivileges() throws SQLException {
+        DatabaseMetaData meta = conn.getMetaData();
+
+        try (ResultSet rs = meta.getTablePrivileges(null, null, null)) {
+            ResultSetMetaData metaData = rs.getMetaData();
+
+            expectColumn(metaData, 1, "TABLE_CAT", Types.VARCHAR);
+            expectColumn(metaData, 2, "TABLE_SCHEM", Types.VARCHAR);
+            expectColumn(metaData, 3, "TABLE_NAME", Types.VARCHAR);
+            expectColumn(metaData, 4, "GRANTOR", Types.VARCHAR);
+            expectColumn(metaData, 5, "GRANTEE", Types.VARCHAR);
+            expectColumn(metaData, 6, "PRIVILEGE", Types.VARCHAR);
+            expectColumn(metaData, 7, "IS_GRANTABLE", Types.VARCHAR);
+
+            assertEquals(7, metaData.getColumnCount());
+
+            // The driver does not provide this information
+            assertFalse(rs.next());
+        }
+    }
+
+    @Test
+    public void testGetBestRowIdentifier() throws SQLException {
+        DatabaseMetaData meta = conn.getMetaData();
+
+        try (ResultSet rs = meta.getBestRowIdentifier(null, null, null, 
DatabaseMetaData.bestRowUnknown, true)) {
+            ResultSetMetaData metaData = rs.getMetaData();
+
+            expectColumn(metaData, 1, "SCOPE", Types.SMALLINT);
+            expectColumn(metaData, 2, "COLUMN_NAME", Types.VARCHAR);
+            expectColumn(metaData, 3, "DATA_TYPE", Types.INTEGER);
+            expectColumn(metaData, 4, "TYPE_NAME", Types.VARCHAR);
+            expectColumn(metaData, 5, "COLUMN_SIZE", Types.INTEGER);
+            expectColumn(metaData, 6, "BUFFER_LENGTH", Types.INTEGER);
+            expectColumn(metaData, 7, "DECIMAL_DIGITS", Types.SMALLINT);
+            expectColumn(metaData, 8, "PSEUDO_COLUMN", Types.SMALLINT);
+
+            assertEquals(8, metaData.getColumnCount());
+
+            // The driver does not provide this information
+            assertFalse(rs.next());
+        }
+    }
+
+    @Test
+    public void testGetVersionColumns() throws SQLException {
+        DatabaseMetaData meta = conn.getMetaData();
+
+        try (ResultSet rs = meta.getVersionColumns(null, null, null)) {
+            ResultSetMetaData metaData = rs.getMetaData();
+
+            expectColumn(metaData, 1, "SCOPE", Types.SMALLINT);
+            expectColumn(metaData, 2, "COLUMN_NAME", Types.VARCHAR);
+            expectColumn(metaData, 3, "DATA_TYPE", Types.INTEGER);
+            expectColumn(metaData, 4, "TYPE_NAME", Types.VARCHAR);
+            expectColumn(metaData, 5, "COLUMN_SIZE", Types.INTEGER);
+            expectColumn(metaData, 6, "BUFFER_LENGTH", Types.INTEGER);
+            expectColumn(metaData, 7, "DECIMAL_DIGITS", Types.SMALLINT);
+            expectColumn(metaData, 8, "PSEUDO_COLUMN", Types.SMALLINT);
+
+            assertEquals(8, metaData.getColumnCount());
+
+            // The driver does not provide this information
+            assertFalse(rs.next());
+        }
+    }
+
+    // getIndexInfo throws java.lang.UnsupportedOperationException: Index info 
is not supported yet.
+    @Disabled("https://issues.apache.org/jira/browse/IGNITE-26422";)
+    @Test
+    public void testGetIndexInfo() throws SQLException {
+        DatabaseMetaData meta = conn.getMetaData();
+
+        try (ResultSet rs = meta.getIndexInfo(null, null, null, false, false)) 
{
+            ResultSetMetaData metaData = rs.getMetaData();
+
+            expectColumn(metaData, 1, "TABLE_CAT", Types.VARCHAR);
+            expectColumn(metaData, 2, "TABLE_SCHEM", Types.VARCHAR);
+            expectColumn(metaData, 3, "TABLE_NAME", Types.VARCHAR);
+            expectColumn(metaData, 4, "NON_UNIQUE", Types.BOOLEAN);
+            expectColumn(metaData, 5, "INDEX_QUALIFIER", Types.VARCHAR);
+            expectColumn(metaData, 6, "INDEX_NAME", Types.VARCHAR);
+            expectColumn(metaData, 7, "TYPE", Types.SMALLINT);
+            expectColumn(metaData, 8, "ORDINAL_POSITION", Types.SMALLINT);
+            expectColumn(metaData, 9, "COLUMN_NAME", Types.VARCHAR);
+            expectColumn(metaData, 10, "ASC_OR_DESC", Types.VARCHAR);
+            expectColumn(metaData, 11, "CARDINALITY", Types.INTEGER);
+            expectColumn(metaData, 12, "PAGES", Types.INTEGER);
+            expectColumn(metaData, 13, "FILTER_CONDITION", Types.VARCHAR);
+
+            assertEquals(13, metaData.getColumnCount());
+        }
+    }
+
     /**
      * Checks organisation table column names and types.
      *
      * @param rs ResultSet.
-     * */
+     *
+     */
     private static void checkOrgTableColumns(ResultSet rs) throws SQLException 
{
         assertNotNull(rs);
 
@@ -493,7 +604,8 @@ public class ItJdbcMetadataSelfTest extends 
AbstractJdbcSelfTest {
      * Checks person table column names and types.
      *
      * @param rs ResultSet.
-     * */
+     *
+     */
     private static void checkPersonTableColumns(ResultSet rs) throws 
SQLException {
         assertNotNull(rs);
 
@@ -595,30 +707,18 @@ public class ItJdbcMetadataSelfTest extends 
AbstractJdbcSelfTest {
         assertFalse(rs.next());
     }
 
-    /**
-     * Check JDBC support flags.
-     */
     @Test
-    public void testCheckSupports() throws SQLException {
+    public void testSchemas() throws Exception {
         DatabaseMetaData meta = conn.getMetaData();
 
-        assertTrue(meta.supportsANSI92EntryLevelSQL());
-        assertTrue(meta.supportsAlterTableWithAddColumn());
-        assertTrue(meta.supportsAlterTableWithDropColumn());
-        assertTrue(meta.nullPlusNonNullIsNull());
-    }
+        try (ResultSet rs = meta.getSchemas()) {
+            ResultSetMetaData metaData = rs.getMetaData();
 
-    @Test
-    public void testVersions() throws Exception {
-        assertEquals(conn.getMetaData().getDatabaseProductVersion(), 
ProtocolVersion.LATEST_VER.toString(),
-                "Unexpected ignite database product version.");
-        assertEquals(conn.getMetaData().getDriverVersion(), 
ProtocolVersion.LATEST_VER.toString(),
-                "Unexpected ignite driver version.");
-    }
+            expectColumn(metaData, 1, "TABLE_SCHEM", Types.VARCHAR);
+            expectColumn(metaData, 2, "TABLE_CATALOG", Types.VARCHAR);
+        }
 
-    @Test
-    public void testSchemasMetadata() throws Exception {
-        try (ResultSet rs = conn.getMetaData().getSchemas()) {
+        try (ResultSet rs = meta.getSchemas()) {
             List<String> schemas = new ArrayList<>();
 
             while (rs.next()) {
@@ -628,7 +728,7 @@ public class ItJdbcMetadataSelfTest extends 
AbstractJdbcSelfTest {
             assertEquals(List.of("META", "PUBLIC", "SYSTEM", "USER1", "USER2", 
"user0"), schemas);
         }
 
-        try (ResultSet rs = conn.getMetaData().getSchemas("IGNITE", "USER%")) {
+        try (ResultSet rs = meta.getSchemas("IGNITE", "USER%")) {
             List<String> schemas = new ArrayList<>();
 
             while (rs.next()) {
@@ -637,53 +737,154 @@ public class ItJdbcMetadataSelfTest extends 
AbstractJdbcSelfTest {
 
             assertEquals(List.of("USER1", "USER2"), schemas);
         }
+
+        try (ResultSet rs = meta.getSchemas(null, "qqq")) {
+            assertFalse(rs.next(), "Empty result set is expected");
+        }
     }
 
     @Test
-    public void testEmptySchemasMetadata() throws Exception {
-        ResultSet rs = conn.getMetaData().getSchemas(null, "qqq");
+    public void testGetPrimaryKeys() throws Exception {
+        DatabaseMetaData meta = conn.getMetaData();
 
-        assertFalse(rs.next(), "Empty result set is expected");
-    }
+        try (ResultSet rs = meta.getPrimaryKeys(null, null, null)) {
+            ResultSetMetaData metaData = rs.getMetaData();
 
-    @Test
-    public void testPrimaryKeyMetadata() throws Exception {
-        ResultSet rs = conn.getMetaData().getPrimaryKeys(null, "PUBLIC", 
"PERSON");
+            expectColumn(metaData, 1, "TABLE_CAT", Types.VARCHAR);
+            expectColumn(metaData, 2, "TABLE_SCHEM", Types.VARCHAR);
+            expectColumn(metaData, 3, "TABLE_NAME", Types.VARCHAR);
+            expectColumn(metaData, 4, "COLUMN_NAME", Types.VARCHAR);
+            expectColumn(metaData, 5, "KEY_SEQ", Types.SMALLINT);
+            expectColumn(metaData, 6, "PK_NAME", Types.VARCHAR);
+
+            assertEquals(6, metaData.getColumnCount());
+        }
+
+        {
+            ResultSet rs = meta.getPrimaryKeys(null, "PUBLIC", "PERSON");
+
+            int cnt = 0;
 
-        int cnt = 0;
+            while (rs.next()) {
+                assertEquals("ORGID", rs.getString("COLUMN_NAME"));
 
-        while (rs.next()) {
-            assertEquals("ORGID", rs.getString("COLUMN_NAME"));
+                cnt++;
+            }
 
-            cnt++;
+            assertEquals(1, cnt);
         }
 
-        assertEquals(1, cnt);
+        {
+            ResultSet rs = meta.getPrimaryKeys(null, null, null);
+
+            List<String> expectedPks = Arrays.asList(
+                    "PUBLIC.ORGANIZATION.PK_ORGANIZATION.ID",
+                    "PUBLIC.PERSON.PK_PERSON.ORGID",
+                    "USER1.TABLE1.PK_TABLE1.ID",
+                    "USER2.table2.PK_table2.ID",
+                    "user0.TABLE0.PK_TABLE0.ID",
+                    "user0.table0.PK_table0.id"
+            );
+
+            List<String> actualPks = new ArrayList<>(expectedPks.size());
+
+            while (rs.next()) {
+                actualPks.add(rs.getString("TABLE_SCHEM")
+                        + '.' + rs.getString("TABLE_NAME")
+                        + '.' + rs.getString("PK_NAME")
+                        + '.' + rs.getString("COLUMN_NAME"));
+            }
+
+            assertEquals(expectedPks, actualPks, "Metadata contains unexpected 
primary keys info.");
+        }
     }
 
     @Test
-    public void testGetAllPrimaryKeys() throws Exception {
-        ResultSet rs = conn.getMetaData().getPrimaryKeys(null, null, null);
+    public void testGetExportedKeys() throws SQLException {
+        DatabaseMetaData meta = conn.getMetaData();
 
-        List<String> expectedPks = Arrays.asList(
-                "PUBLIC.ORGANIZATION.PK_ORGANIZATION.ID",
-                "PUBLIC.PERSON.PK_PERSON.ORGID",
-                "USER1.TABLE1.PK_TABLE1.ID",
-                "USER2.table2.PK_table2.ID",
-                "user0.TABLE0.PK_TABLE0.ID",
-                "user0.table0.PK_table0.id"
-        );
+        try (ResultSet rs = meta.getExportedKeys(null, null, null)) {
+            ResultSetMetaData metaData = rs.getMetaData();
+
+            // According to DatabaseMetaData#getExportedKeys javadoc
+            expectColumn(metaData, 1, "PKTABLE_CAT", Types.VARCHAR);
+            expectColumn(metaData, 2, "PKTABLE_SCHEM", Types.VARCHAR);
+            expectColumn(metaData, 3, "PKTABLE_NAME", Types.VARCHAR);
+            expectColumn(metaData, 4, "PKCOLUMN_NAME", Types.VARCHAR);
+            expectColumn(metaData, 5, "FKTABLE_CAT", Types.VARCHAR);
+            expectColumn(metaData, 6, "FKTABLE_SCHEM", Types.VARCHAR);
+            expectColumn(metaData, 7, "FKTABLE_NAME", Types.VARCHAR);
+            expectColumn(metaData, 8, "FKCOLUMN_NAME", Types.VARCHAR);
+            expectColumn(metaData, 9, "KEY_SEQ", Types.SMALLINT);
+            expectColumn(metaData, 10, "UPDATE_RULE", Types.SMALLINT);
+            expectColumn(metaData, 11, "DELETE_RULE", Types.SMALLINT);
+            expectColumn(metaData, 12, "FK_NAME", Types.VARCHAR);
+            expectColumn(metaData, 13, "PK_NAME", Types.VARCHAR);
+            expectColumn(metaData, 14, "DEFERRABILITY", Types.SMALLINT);
+
+            assertEquals(14, metaData.getColumnCount());
+
+            // The driver does not provide this information
+            assertFalse(rs.next());
+        }
+    }
 
-        List<String> actualPks = new ArrayList<>(expectedPks.size());
+    @Test
+    public void testGetImportedKeys() throws SQLException {
+        DatabaseMetaData meta = conn.getMetaData();
 
-        while (rs.next()) {
-            actualPks.add(rs.getString("TABLE_SCHEM")
-                    + '.' + rs.getString("TABLE_NAME")
-                    + '.' + rs.getString("PK_NAME")
-                    + '.' + rs.getString("COLUMN_NAME"));
+        try (ResultSet rs = meta.getImportedKeys(null, null, null)) {
+            ResultSetMetaData metaData = rs.getMetaData();
+
+            expectColumn(metaData, 1, "PKTABLE_CAT", Types.VARCHAR);
+            expectColumn(metaData, 2, "PKTABLE_SCHEM", Types.VARCHAR);
+            expectColumn(metaData, 3, "PKTABLE_NAME", Types.VARCHAR);
+            expectColumn(metaData, 4, "PKCOLUMN_NAME", Types.VARCHAR);
+            expectColumn(metaData, 5, "FKTABLE_CAT", Types.VARCHAR);
+            expectColumn(metaData, 6, "FKTABLE_SCHEM", Types.VARCHAR);
+            expectColumn(metaData, 7, "FKTABLE_NAME", Types.VARCHAR);
+            expectColumn(metaData, 8, "FKCOLUMN_NAME", Types.VARCHAR);
+            expectColumn(metaData, 9, "KEY_SEQ", Types.SMALLINT);
+            expectColumn(metaData, 10, "UPDATE_RULE", Types.SMALLINT);
+            expectColumn(metaData, 11, "DELETE_RULE", Types.SMALLINT);
+            expectColumn(metaData, 12, "FK_NAME", Types.VARCHAR);
+            expectColumn(metaData, 13, "PK_NAME", Types.VARCHAR);
+            expectColumn(metaData, 14, "DEFERRABILITY", Types.SMALLINT);
+
+            assertEquals(14, metaData.getColumnCount());
+
+            // The driver does not provide this information
+            assertFalse(rs.next());
         }
+    }
+
+    @Test
+    public void testGetCrossReference() throws SQLException {
+        try (ResultSet rs = conn.getMetaData().getCrossReference(null, null, 
null, null, null, null)) {
+            assertFalse(rs.next());
 
-        assertEquals(expectedPks, actualPks, "Metadata contains unexpected 
primary keys info.");
+            ResultSetMetaData metaData = rs.getMetaData();
+
+            expectColumn(metaData, 1, "PKTABLE_CAT", Types.VARCHAR);
+            expectColumn(metaData, 2, "PKTABLE_SCHEM", Types.VARCHAR);
+            expectColumn(metaData, 3, "PKTABLE_NAME", Types.VARCHAR);
+            expectColumn(metaData, 4, "PKCOLUMN_NAME", Types.VARCHAR);
+            expectColumn(metaData, 5, "FKTABLE_CAT", Types.VARCHAR);
+            expectColumn(metaData, 6, "FKTABLE_SCHEM", Types.VARCHAR);
+            expectColumn(metaData, 7, "FKTABLE_NAME", Types.VARCHAR);
+            expectColumn(metaData, 8, "FKCOLUMN_NAME", Types.VARCHAR);
+            expectColumn(metaData, 9, "KEY_SEQ", Types.SMALLINT);
+            expectColumn(metaData, 10, "UPDATE_RULE", Types.SMALLINT);
+            expectColumn(metaData, 11, "DELETE_RULE", Types.SMALLINT);
+            expectColumn(metaData, 12, "FK_NAME", Types.VARCHAR);
+            expectColumn(metaData, 13, "PK_NAME", Types.VARCHAR);
+            expectColumn(metaData, 14, "DEFERRABILITY", Types.SMALLINT);
+
+            assertEquals(14, metaData.getColumnCount());
+
+            // The driver does not provide this information
+            assertFalse(rs.next());
+        }
     }
 
     @Test
@@ -715,113 +916,44 @@ public class ItJdbcMetadataSelfTest extends 
AbstractJdbcSelfTest {
     public void testGetTableTypes() throws Exception {
         DatabaseMetaData meta = conn.getMetaData();
 
-        ResultSet rs = meta.getTableTypes();
-
-        assertTrue(rs.next());
-
-        assertEquals("TABLE", rs.getString("TABLE_TYPE"));
-
-        assertFalse(rs.next());
-    }
-
-    @Test
-    @Disabled("https://issues.apache.org/jira/browse/IGNITE-16203";)
-    public void testParametersMetadata() throws Exception {
-        // Perform checks few times due to query/plan caching.
-        for (int i = 0; i < 3; i++) {
-            // No parameters statement.
-            try (Connection conn = DriverManager.getConnection(URL)) {
-                conn.setSchema("\"pers\"");
-
-                PreparedStatement noParams = conn.prepareStatement("select * 
from Person;");
-                ParameterMetaData params = noParams.getParameterMetaData();
-
-                assertEquals(0, params.getParameterCount(), "Parameters should 
be empty.");
-            }
-
-            // Selects.
-            try (Connection conn = DriverManager.getConnection(URL)) {
-                conn.setSchema("\"pers\"");
-
-                PreparedStatement selectStmt = conn.prepareStatement("select 
orgId from Person p where p.name > ? and p.orgId > ?");
-
-                ParameterMetaData meta = selectStmt.getParameterMetaData();
-
-                assertNotNull(meta);
+        try (ResultSet rs = meta.getTableTypes()) {
+            ResultSetMetaData metaData = rs.getMetaData();
 
-                assertEquals(2, meta.getParameterCount());
+            expectColumn(metaData, 1, "TABLE_TYPE", Types.VARCHAR);
 
-                assertEquals(Types.VARCHAR, meta.getParameterType(1));
-                assertEquals(ParameterMetaData.parameterNullableUnknown, 
meta.isNullable(1));
-                assertEquals(Integer.MAX_VALUE, meta.getPrecision(1));
-
-                assertEquals(Types.INTEGER, meta.getParameterType(2));
-                assertEquals(ParameterMetaData.parameterNullableUnknown, 
meta.isNullable(2));
-            }
-
-            // Updates.
-            try (Connection conn = DriverManager.getConnection(URL)) {
-                conn.setSchema("\"pers\"");
-
-                PreparedStatement updateStmt = conn.prepareStatement("update 
Person p set orgId = 42 where p.name > ? and p.orgId > ?");
-
-                ParameterMetaData meta = updateStmt.getParameterMetaData();
-
-                assertNotNull(meta);
-
-                assertEquals(2, meta.getParameterCount());
-
-                assertEquals(Types.VARCHAR, meta.getParameterType(1));
-                assertEquals(ParameterMetaData.parameterNullableUnknown, 
meta.isNullable(1));
-                assertEquals(Integer.MAX_VALUE, meta.getPrecision(1));
-
-                assertEquals(Types.INTEGER, meta.getParameterType(2));
-                assertEquals(ParameterMetaData.parameterNullableUnknown, 
meta.isNullable(2));
-            }
-
-            // Multistatement
-            try (Connection conn = DriverManager.getConnection(URL)) {
-                conn.setSchema("\"pers\"");
-
-                PreparedStatement updateStmt = conn.prepareStatement(
-                        "update Person p set orgId = 42 where p.name > ? and 
p.orgId > ?;"
-                                + "select orgId from Person p where p.name > ? 
and p.orgId > ?");
-
-                ParameterMetaData meta = updateStmt.getParameterMetaData();
-
-                assertNotNull(meta);
-
-                assertEquals(4, meta.getParameterCount());
-
-                assertEquals(Types.VARCHAR, meta.getParameterType(1));
-                assertEquals(ParameterMetaData.parameterNullableUnknown, 
meta.isNullable(1));
-                assertEquals(Integer.MAX_VALUE, meta.getPrecision(1));
-
-                assertEquals(Types.INTEGER, meta.getParameterType(2));
-                assertEquals(ParameterMetaData.parameterNullableUnknown, 
meta.isNullable(2));
-
-                assertEquals(Types.VARCHAR, meta.getParameterType(3));
-                assertEquals(ParameterMetaData.parameterNullableUnknown, 
meta.isNullable(3));
-                assertEquals(Integer.MAX_VALUE, meta.getPrecision(3));
-
-                assertEquals(Types.INTEGER, meta.getParameterType(4));
-                assertEquals(ParameterMetaData.parameterNullableUnknown, 
meta.isNullable(4));
-            }
+            assertTrue(rs.next());
+            assertEquals("TABLE", rs.getString("TABLE_TYPE"));
+            assertFalse(rs.next());
         }
     }
 
-    /**
-     * Check that parameters metadata throws correct exception on non-parsable 
statement.
-     */
     @Test
-    @Disabled("https://issues.apache.org/jira/browse/IGNITE-16203";)
-    public void testParametersMetadataNegative() throws Exception {
-        try (Connection conn = DriverManager.getConnection(URL)) {
-            conn.setSchema("\"pers\"");
-
-            PreparedStatement notCorrect = conn.prepareStatement("select * 
from NotExistingTable;");
+    public void testGetTypeInfo() throws SQLException {
+        DatabaseMetaData meta = conn.getMetaData();
 
-            JdbcTestUtils.assertThrowsSqlException("Table NOTEXISTINGTABLE not 
found", notCorrect::getParameterMetaData);
+        try (ResultSet rs = meta.getTypeInfo()) {
+            ResultSetMetaData metaData = rs.getMetaData();
+
+            expectColumn(metaData, 1, "TYPE_NAME", Types.VARCHAR);
+            expectColumn(metaData, 2, "DATA_TYPE", Types.INTEGER);
+            expectColumn(metaData, 3, "PRECISION", Types.INTEGER);
+            expectColumn(metaData, 4, "LITERAL_PREFIX", Types.VARCHAR);
+            expectColumn(metaData, 5, "LITERAL_SUFFIX", Types.VARCHAR);
+            expectColumn(metaData, 6, "CREATE_PARAMS", Types.VARCHAR);
+            expectColumn(metaData, 7, "NULLABLE", Types.SMALLINT);
+            expectColumn(metaData, 8, "CASE_SENSITIVE", Types.BOOLEAN);
+            expectColumn(metaData, 9, "SEARCHABLE", Types.SMALLINT);
+            expectColumn(metaData, 10, "UNSIGNED_ATTRIBUTE", Types.BOOLEAN);
+            expectColumn(metaData, 11, "FIXED_PREC_SCALE", Types.BOOLEAN);
+            expectColumn(metaData, 12, "AUTO_INCREMENT", Types.BOOLEAN);
+            expectColumn(metaData, 13, "LOCAL_TYPE_NAME", Types.VARCHAR);
+            expectColumn(metaData, 14, "MINIMUM_SCALE", Types.SMALLINT);
+            expectColumn(metaData, 15, "MAXIMUM_SCALE", Types.SMALLINT);
+            expectColumn(metaData, 16, "SQL_DATA_TYPE", Types.INTEGER);
+            expectColumn(metaData, 17, "SQL_DATETIME_SUB", Types.INTEGER);
+            expectColumn(metaData, 18, "NUM_PREC_RADIX", Types.INTEGER);
+
+            assertEquals(18, metaData.getColumnCount());
         }
     }
 
@@ -873,4 +1005,293 @@ public class ItJdbcMetadataSelfTest extends 
AbstractJdbcSelfTest {
             assertTrue(empty, "Result should be empty because invalid catalog 
is specified.");
         }
     }
+
+    @Test
+    public void testGetProduces() throws SQLException {
+        DatabaseMetaData meta = conn.getMetaData();
+
+        try (ResultSet rs = meta.getProcedures(null, null, null)) {
+            ResultSetMetaData metaData = rs.getMetaData();
+
+            expectColumn(metaData, 1, "PROCEDURE_CAT", Types.VARCHAR);
+            expectColumn(metaData, 2, "PROCEDURE_SCHEM", Types.VARCHAR);
+            expectColumn(metaData, 3, "PROCEDURE_NAME", Types.VARCHAR);
+            // 4, 5, 6 are reserved for future use
+            expectColumn(metaData, 4, "", Types.NULL);
+            expectColumn(metaData, 5, "", Types.NULL);
+            expectColumn(metaData, 6, "", Types.NULL);
+            expectColumn(metaData, 7, "REMARKS", Types.VARCHAR);
+            expectColumn(metaData, 8, "PROCEDURE_TYPE", Types.SMALLINT);
+            expectColumn(metaData, 9, "SPECIFIC_NAME", Types.VARCHAR);
+
+            assertEquals(9, metaData.getColumnCount());
+
+            // The driver does not provide this information
+            assertFalse(rs.next());
+        }
+    }
+
+    @Test
+    public void testGetProcedureColumns() throws SQLException {
+        DatabaseMetaData meta = conn.getMetaData();
+
+        try (ResultSet rs = meta.getProcedureColumns(null, null, null, null)) {
+            ResultSetMetaData metaData = rs.getMetaData();
+
+            expectColumn(metaData, 1, "PROCEDURE_CAT", Types.VARCHAR);
+            expectColumn(metaData, 2, "PROCEDURE_SCHEM", Types.VARCHAR);
+            expectColumn(metaData, 3, "PROCEDURE_NAME", Types.VARCHAR);
+            expectColumn(metaData, 4, "COLUMN_NAME", Types.VARCHAR);
+            expectColumn(metaData, 5, "COLUMN_TYPE", Types.SMALLINT);
+            expectColumn(metaData, 6, "DATA_TYPE", Types.INTEGER);
+            expectColumn(metaData, 7, "TYPE_NAME", Types.VARCHAR);
+            expectColumn(metaData, 8, "PRECISION", Types.INTEGER);
+            expectColumn(metaData, 8, "PRECISION", Types.INTEGER);
+            expectColumn(metaData, 9, "LENGTH", Types.INTEGER);
+            expectColumn(metaData, 10, "SCALE", Types.SMALLINT);
+            expectColumn(metaData, 11, "RADIX", Types.SMALLINT);
+            expectColumn(metaData, 12, "NULLABLE", Types.SMALLINT);
+            expectColumn(metaData, 13, "REMARKS", Types.VARCHAR);
+            expectColumn(metaData, 14, "COLUMN_DEF", Types.VARCHAR);
+            expectColumn(metaData, 15, "SQL_DATA_TYPE", Types.INTEGER);
+            expectColumn(metaData, 16, "SQL_DATETIME_SUB", Types.INTEGER);
+            expectColumn(metaData, 17, "CHAR_OCTET_LENGTH", Types.INTEGER);
+            expectColumn(metaData, 18, "ORDINAL_POSITION", Types.INTEGER);
+            expectColumn(metaData, 19, "IS_NULLABLE", Types.VARCHAR);
+            expectColumn(metaData, 20, "SPECIFIC_NAME", Types.VARCHAR);
+
+            assertEquals(20, metaData.getColumnCount());
+
+            // The driver does not provide this information
+            assertFalse(rs.next());
+        }
+    }
+
+    @Test
+    public void testGetCatalogs() throws SQLException {
+        try (ResultSet rs = conn.getMetaData().getCatalogs()) {
+            ResultSetMetaData metaData = rs.getMetaData();
+            assertEquals("TABLE_CAT", metaData.getColumnName(1));
+            assertEquals(Types.VARCHAR, metaData.getColumnType(1));
+
+            assertEquals(1, metaData.getColumnCount());
+
+            assertTrue(rs.next());
+            assertEquals("IGNITE", rs.getString(1));
+            assertFalse(rs.next());
+        }
+    }
+
+    @Test
+    public void testGetUdts() throws SQLException {
+        DatabaseMetaData meta = conn.getMetaData();
+
+        try (ResultSet rs = meta.getUDTs(null, null, null, null)) {
+            ResultSetMetaData metaData = rs.getMetaData();
+
+            expectColumn(metaData, 1, "TYPE_CAT", Types.VARCHAR);
+            expectColumn(metaData, 2, "TYPE_SCHEM", Types.VARCHAR);
+            expectColumn(metaData, 3, "TYPE_NAME", Types.VARCHAR);
+            expectColumn(metaData, 4, "CLASS_NAME", Types.VARCHAR);
+            expectColumn(metaData, 5, "DATA_TYPE", Types.INTEGER);
+            expectColumn(metaData, 6, "REMARKS", Types.VARCHAR);
+            expectColumn(metaData, 7, "BASE_TYPE", Types.SMALLINT);
+
+            assertEquals(7, metaData.getColumnCount());
+
+            // The driver does not provide this information
+            assertFalse(rs.next());
+        }
+    }
+
+    @Test
+    public void testGetSuperTypes() throws SQLException {
+        DatabaseMetaData meta = conn.getMetaData();
+
+        try (ResultSet rs = meta.getSuperTypes(null, null, null)) {
+            ResultSetMetaData metaData = rs.getMetaData();
+
+            expectColumn(metaData, 1, "TYPE_CAT", Types.VARCHAR);
+            expectColumn(metaData, 2, "TYPE_SCHEM", Types.VARCHAR);
+            expectColumn(metaData, 3, "TYPE_NAME", Types.VARCHAR);
+            expectColumn(metaData, 4, "SUPERTYPE_CAT", Types.VARCHAR);
+            expectColumn(metaData, 5, "SUPERTYPE_SCHEM", Types.VARCHAR);
+            expectColumn(metaData, 6, "SUPERTYPE_NAME", Types.VARCHAR);
+
+            assertEquals(6, metaData.getColumnCount());
+
+            // The driver does not provide this information
+            assertFalse(rs.next());
+        }
+    }
+
+    @Test
+    public void testGetSuperTables() throws SQLException {
+        DatabaseMetaData meta = conn.getMetaData();
+
+        try (ResultSet rs = meta.getSuperTables(null, null, null)) {
+            ResultSetMetaData metaData = rs.getMetaData();
+
+            expectColumn(metaData, 1, "TABLE_CAT", Types.VARCHAR);
+            expectColumn(metaData, 2, "TABLE_SCHEM", Types.VARCHAR);
+            expectColumn(metaData, 3, "TABLE_NAME", Types.VARCHAR);
+            expectColumn(metaData, 4, "SUPERTABLE_NAME", Types.VARCHAR);
+
+            assertEquals(4, metaData.getColumnCount());
+
+            // The driver does not provide this information
+            assertFalse(rs.next());
+        }
+    }
+
+    @Test
+    public void testGetAttributes() throws SQLException {
+        DatabaseMetaData meta = conn.getMetaData();
+
+        try (ResultSet rs = meta.getAttributes(null, null, null, null)) {
+            ResultSetMetaData metaData = rs.getMetaData();
+
+            expectColumn(metaData, 1, "TYPE_CAT", Types.VARCHAR);
+            expectColumn(metaData, 2, "TYPE_SCHEM", Types.VARCHAR);
+            expectColumn(metaData, 3, "TYPE_NAME", Types.VARCHAR);
+            expectColumn(metaData, 4, "ATTR_NAME", Types.VARCHAR);
+            expectColumn(metaData, 5, "DATA_TYPE", Types.INTEGER);
+            expectColumn(metaData, 6, "ATTR_TYPE_NAME", Types.VARCHAR);
+            expectColumn(metaData, 7, "ATTR_SIZE", Types.INTEGER);
+            expectColumn(metaData, 8, "DECIMAL_DIGITS", Types.INTEGER);
+            expectColumn(metaData, 9, "NUM_PREC_RADIX", Types.INTEGER);
+            expectColumn(metaData, 10, "NULLABLE", Types.INTEGER);
+            expectColumn(metaData, 11, "REMARKS", Types.VARCHAR);
+            expectColumn(metaData, 12, "ATTR_DEF", Types.VARCHAR);
+            expectColumn(metaData, 13, "SQL_DATA_TYPE", Types.INTEGER);
+            expectColumn(metaData, 14, "SQL_DATETIME_SUB", Types.INTEGER);
+            expectColumn(metaData, 15, "CHAR_OCTET_LENGTH", Types.INTEGER);
+            expectColumn(metaData, 16, "ORDINAL_POSITION", Types.INTEGER);
+            expectColumn(metaData, 17, "IS_NULLABLE", Types.VARCHAR);
+            expectColumn(metaData, 18, "SCOPE_CATALOG", Types.VARCHAR);
+            expectColumn(metaData, 19, "SCOPE_SCHEMA", Types.VARCHAR);
+            expectColumn(metaData, 20, "SCOPE_TABLE", Types.VARCHAR);
+            expectColumn(metaData, 21, "SOURCE_DATA_TYPE", Types.SMALLINT);
+
+            assertEquals(21, metaData.getColumnCount());
+
+            // The driver does not provide this information
+            assertFalse(rs.next());
+        }
+    }
+
+    @Test
+    public void testGetClientInfoProperties() throws SQLException {
+        try (Connection connection = DriverManager.getConnection(URL)) {
+            DatabaseMetaData meta = connection.getMetaData();
+
+            try (ResultSet rs = meta.getClientInfoProperties()) {
+                ResultSetMetaData metaData = rs.getMetaData();
+
+                expectColumn(metaData, 1, "NAME", Types.VARCHAR);
+                expectColumn(metaData, 2, "MAX_LEN", Types.INTEGER);
+                expectColumn(metaData, 3, "DEFAULT_VALUE", Types.VARCHAR);
+                expectColumn(metaData, 4, "DESCRIPTION", Types.VARCHAR);
+
+                assertEquals(4, metaData.getColumnCount());
+
+                // The driver does not provide this information
+                assertFalse(rs.next());
+            }
+
+            connection.close();
+
+            // Works on a closed connection since this is a client-side 
operation.
+            try (ResultSet rs = meta.getClientInfoProperties()) {
+                ResultSetMetaData metaData = rs.getMetaData();
+                assertEquals(4, metaData.getColumnCount());
+            }
+        }
+    }
+
+    @Test
+    public void testGetFunctions() throws SQLException {
+        DatabaseMetaData meta = conn.getMetaData();
+
+        try (ResultSet rs = meta.getFunctions(null, null, null)) {
+            ResultSetMetaData metaData = rs.getMetaData();
+
+            expectColumn(metaData, 1, "FUNCTION_CAT", Types.VARCHAR);
+            expectColumn(metaData, 2, "FUNCTION_SCHEM", Types.VARCHAR);
+            expectColumn(metaData, 3, "FUNCTION_NAME", Types.VARCHAR);
+            expectColumn(metaData, 4, "REMARKS", Types.VARCHAR);
+            // Note: Implementation currently exposes FUNCTION_TYPE as VARCHAR
+            expectColumn(metaData, 5, "FUNCTION_TYPE", Types.VARCHAR);
+            expectColumn(metaData, 6, "SPECIFIC_NAME", Types.VARCHAR);
+
+            assertEquals(6, metaData.getColumnCount());
+
+            // The driver does not provide this information
+            assertFalse(rs.next());
+        }
+    }
+
+    @Test
+    public void testGetFunctionColumns() throws SQLException {
+        DatabaseMetaData meta = conn.getMetaData();
+
+        try (ResultSet rs = meta.getFunctionColumns(null, null, null, null)) {
+            ResultSetMetaData metaData = rs.getMetaData();
+
+            expectColumn(metaData, 1, "FUNCTION_CAT", Types.VARCHAR);
+            expectColumn(metaData, 2, "FUNCTION_SCHEM", Types.VARCHAR);
+            expectColumn(metaData, 3, "FUNCTION_NAME", Types.VARCHAR);
+            expectColumn(metaData, 4, "COLUMN_NAME", Types.VARCHAR);
+            expectColumn(metaData, 5, "COLUMN_TYPE", Types.SMALLINT);
+            expectColumn(metaData, 6, "DATA_TYPE", Types.INTEGER);
+            expectColumn(metaData, 7, "TYPE_NAME", Types.VARCHAR);
+            expectColumn(metaData, 8, "PRECISION", Types.INTEGER);
+            expectColumn(metaData, 9, "LENGTH", Types.INTEGER);
+            expectColumn(metaData, 10, "SCALE", Types.SMALLINT);
+            expectColumn(metaData, 11, "RADIX", Types.SMALLINT);
+            expectColumn(metaData, 12, "NULLABLE", Types.SMALLINT);
+            expectColumn(metaData, 13, "REMARKS", Types.VARCHAR);
+            expectColumn(metaData, 14, "CHAR_OCTET_LENGTH", Types.INTEGER);
+            expectColumn(metaData, 15, "ORDINAL_POSITION", Types.INTEGER);
+            expectColumn(metaData, 16, "IS_NULLABLE", Types.VARCHAR);
+            expectColumn(metaData, 17, "SPECIFIC_NAME", Types.VARCHAR);
+
+            assertEquals(17, metaData.getColumnCount());
+
+            // The driver does not provide this information
+            assertFalse(rs.next());
+        }
+    }
+
+    @Test
+    public void testGetPseudoColumns() throws SQLException {
+        DatabaseMetaData meta = conn.getMetaData();
+
+        try (ResultSet rs = meta.getPseudoColumns(null, null, null, null)) {
+            ResultSetMetaData metaData = rs.getMetaData();
+
+            expectColumn(metaData, 1, "TABLE_CAT", Types.VARCHAR);
+            expectColumn(metaData, 2, "TABLE_SCHEM", Types.VARCHAR);
+            expectColumn(metaData, 3, "TABLE_NAME", Types.VARCHAR);
+            expectColumn(metaData, 4, "COLUMN_NAME", Types.VARCHAR);
+            expectColumn(metaData, 5, "DATA_TYPE", Types.INTEGER);
+            expectColumn(metaData, 6, "COLUMN_SIZE", Types.INTEGER);
+            expectColumn(metaData, 7, "DECIMAL_DIGITS", Types.INTEGER);
+            expectColumn(metaData, 8, "NUM_PREC_RADIX", Types.INTEGER);
+            expectColumn(metaData, 9, "COLUMN_USAGE", Types.INTEGER);
+            expectColumn(metaData, 10, "REMARKS", Types.VARCHAR);
+            expectColumn(metaData, 11, "CHAR_OCTET_LENGTH", Types.INTEGER);
+            expectColumn(metaData, 12, "IS_NULLABLE", Types.VARCHAR);
+
+            assertEquals(12, metaData.getColumnCount());
+
+            // The driver does not provide this information
+            assertFalse(rs.next());
+        }
+    }
+
+    private static void expectColumn(ResultSetMetaData metaData, int column, 
String name, int type) throws SQLException {
+        assertEquals(name, metaData.getColumnName(column), column + " name");
+        assertEquals(type, metaData.getColumnType(column), column + " type");
+    }
 }
diff --git 
a/modules/jdbc/src/integrationTest/java/org/apache/ignite/internal/jdbc/ItJdbcParameterMetadataSelfTest.java
 
b/modules/jdbc/src/integrationTest/java/org/apache/ignite/internal/jdbc/ItJdbcParameterMetadataSelfTest.java
new file mode 100644
index 00000000000..34f9d34591f
--- /dev/null
+++ 
b/modules/jdbc/src/integrationTest/java/org/apache/ignite/internal/jdbc/ItJdbcParameterMetadataSelfTest.java
@@ -0,0 +1,149 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.ignite.internal.jdbc;
+
+import static org.junit.jupiter.api.Assertions.assertEquals;
+import static org.junit.jupiter.api.Assertions.assertNotNull;
+
+import java.sql.Connection;
+import java.sql.DriverManager;
+import java.sql.ParameterMetaData;
+import java.sql.PreparedStatement;
+import java.sql.SQLException;
+import java.sql.Statement;
+import java.sql.Types;
+import org.apache.ignite.jdbc.AbstractJdbcSelfTest;
+import org.apache.ignite.jdbc.util.JdbcTestUtils;
+import org.junit.jupiter.api.BeforeAll;
+import org.junit.jupiter.api.Disabled;
+import org.junit.jupiter.api.Test;
+
+/**
+ * Tests for {@link ParameterMetaData}.
+ */
+@Disabled("https://issues.apache.org/jira/browse/IGNITE-16203";)
+public class ItJdbcParameterMetadataSelfTest extends AbstractJdbcSelfTest {
+
+    @BeforeAll
+    public void beforeAll() throws SQLException {
+        try (Statement stmt = conn.createStatement()) {
+            stmt.execute("CREATE TABLE person(name VARCHAR(32), age INT, orgid 
INT PRIMARY KEY);");
+            stmt.execute("CREATE TABLE organization(id INT PRIMARY KEY, name 
VARCHAR, bigdata DECIMAL(20, 10));");
+        }
+    }
+
+    @Test
+    public void testParametersMetadata() throws Exception {
+        // Perform checks few times due to query/plan caching.
+        for (int i = 0; i < 3; i++) {
+            // No parameters statement.
+            try (Connection conn = DriverManager.getConnection(URL)) {
+                conn.setSchema("\"pers\"");
+
+                PreparedStatement noParams = conn.prepareStatement("select * 
from Person;");
+                ParameterMetaData params = noParams.getParameterMetaData();
+
+                assertEquals(0, params.getParameterCount(), "Parameters should 
be empty.");
+            }
+
+            // Selects.
+            try (Connection conn = DriverManager.getConnection(URL)) {
+                conn.setSchema("\"pers\"");
+
+                PreparedStatement selectStmt = conn.prepareStatement("select 
orgId from Person p where p.name > ? and p.orgId > ?");
+
+                ParameterMetaData meta = selectStmt.getParameterMetaData();
+
+                assertNotNull(meta);
+
+                assertEquals(2, meta.getParameterCount());
+
+                assertEquals(Types.VARCHAR, meta.getParameterType(1));
+                assertEquals(ParameterMetaData.parameterNullableUnknown, 
meta.isNullable(1));
+                assertEquals(Integer.MAX_VALUE, meta.getPrecision(1));
+
+                assertEquals(Types.INTEGER, meta.getParameterType(2));
+                assertEquals(ParameterMetaData.parameterNullableUnknown, 
meta.isNullable(2));
+            }
+
+            // Updates.
+            try (Connection conn = DriverManager.getConnection(URL)) {
+                conn.setSchema("\"pers\"");
+
+                PreparedStatement updateStmt = conn.prepareStatement("update 
Person p set orgId = 42 where p.name > ? and p.orgId > ?");
+
+                ParameterMetaData meta = updateStmt.getParameterMetaData();
+
+                assertNotNull(meta);
+
+                assertEquals(2, meta.getParameterCount());
+
+                assertEquals(Types.VARCHAR, meta.getParameterType(1));
+                assertEquals(ParameterMetaData.parameterNullableUnknown, 
meta.isNullable(1));
+                assertEquals(Integer.MAX_VALUE, meta.getPrecision(1));
+
+                assertEquals(Types.INTEGER, meta.getParameterType(2));
+                assertEquals(ParameterMetaData.parameterNullableUnknown, 
meta.isNullable(2));
+            }
+
+            // Multistatement
+            try (Connection conn = DriverManager.getConnection(URL)) {
+                conn.setSchema("\"pers\"");
+
+                PreparedStatement updateStmt = conn.prepareStatement(
+                        "update Person p set orgId = 42 where p.name > ? and 
p.orgId > ?;"
+                                + "select orgId from Person p where p.name > ? 
and p.orgId > ?");
+
+                ParameterMetaData meta = updateStmt.getParameterMetaData();
+
+                assertNotNull(meta);
+
+                assertEquals(4, meta.getParameterCount());
+
+                assertEquals(Types.VARCHAR, meta.getParameterType(1));
+                assertEquals(ParameterMetaData.parameterNullableUnknown, 
meta.isNullable(1));
+                assertEquals(Integer.MAX_VALUE, meta.getPrecision(1));
+
+                assertEquals(Types.INTEGER, meta.getParameterType(2));
+                assertEquals(ParameterMetaData.parameterNullableUnknown, 
meta.isNullable(2));
+
+                assertEquals(Types.VARCHAR, meta.getParameterType(3));
+                assertEquals(ParameterMetaData.parameterNullableUnknown, 
meta.isNullable(3));
+                assertEquals(Integer.MAX_VALUE, meta.getPrecision(3));
+
+                assertEquals(Types.INTEGER, meta.getParameterType(4));
+                assertEquals(ParameterMetaData.parameterNullableUnknown, 
meta.isNullable(4));
+            }
+        }
+    }
+
+    /**
+     * Check that parameters metadata throws correct exception on non-parsable 
statement.
+     */
+    @Test
+    @Disabled("https://issues.apache.org/jira/browse/IGNITE-16203";)
+    public void testParametersMetadataNegative() throws Exception {
+        try (Connection conn = DriverManager.getConnection(URL)) {
+            conn.setSchema("\"pers\"");
+
+            PreparedStatement notCorrect = conn.prepareStatement("select * 
from NotExistingTable;");
+
+            JdbcTestUtils.assertThrowsSqlException("Table NOTEXISTINGTABLE not 
found", notCorrect::getParameterMetaData);
+        }
+    }
+}
diff --git 
a/modules/jdbc/src/integrationTest/java/org/apache/ignite/internal/jdbc/ItJdbcResultSetMetadataSelfTest.java
 
b/modules/jdbc/src/integrationTest/java/org/apache/ignite/internal/jdbc/ItJdbcResultSetMetadataSelfTest.java
new file mode 100644
index 00000000000..d90a02a2a41
--- /dev/null
+++ 
b/modules/jdbc/src/integrationTest/java/org/apache/ignite/internal/jdbc/ItJdbcResultSetMetadataSelfTest.java
@@ -0,0 +1,100 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.ignite.internal.jdbc;
+
+import static org.junit.jupiter.api.Assertions.assertEquals;
+import static org.junit.jupiter.api.Assertions.assertNotNull;
+
+import java.sql.ResultSet;
+import java.sql.ResultSetMetaData;
+import java.sql.SQLException;
+import java.sql.Statement;
+import java.sql.Types;
+import java.util.concurrent.TimeUnit;
+import org.apache.ignite.jdbc.AbstractJdbcSelfTest;
+import org.junit.jupiter.api.BeforeAll;
+import org.junit.jupiter.api.Test;
+
+/**
+ * Tests for {@link ResultSet}.
+ */
+public class ItJdbcResultSetMetadataSelfTest extends AbstractJdbcSelfTest {
+
+    @BeforeAll
+    public void beforeAll() throws SQLException {
+        try (Statement stmt = conn.createStatement()) {
+            stmt.execute("CREATE TABLE person(name VARCHAR(32), age INT, orgid 
INT PRIMARY KEY);");
+            stmt.execute("CREATE TABLE organization(id INT PRIMARY KEY, name 
VARCHAR, bigdata DECIMAL(20, 10));");
+        }
+    }
+
+    @Test
+    public void testNullValuesMetaData() throws Exception {
+        ResultSet rs = stmt.executeQuery(
+                "select NULL, substring(null, 1, 2)");
+
+        assertNotNull(rs);
+
+        ResultSetMetaData meta = rs.getMetaData();
+
+        assertNotNull(meta);
+
+        assertEquals(2, meta.getColumnCount());
+
+        assertEquals(Types.NULL, meta.getColumnType(1));
+        assertEquals("NULL", meta.getColumnTypeName(1));
+        assertEquals("java.lang.Void", meta.getColumnClassName(1));
+
+        assertEquals(Types.NULL, meta.getColumnType(2));
+        assertEquals("NULL", meta.getColumnTypeName(2));
+        assertEquals("java.lang.Void", meta.getColumnClassName(2));
+    }
+
+    @Test
+    public void testResultSetMetaData() throws Exception {
+        // This delays make this test case less susceptible to 
https://issues.apache.org/jira/browse/IGNITE-25935
+        // Mandatory nodes was excluded from mapping: []
+        // TODO https://issues.apache.org/jira/browse/IGNITE-25935 Remove this 
delay.
+        TimeUnit.SECONDS.sleep(5);
+
+        ResultSet rs = stmt.executeQuery(
+                "select p.name, o.id as orgId, p.age from PERSON p, 
ORGANIZATION o where p.orgId = o.id");
+
+        assertNotNull(rs);
+
+        ResultSetMetaData meta = rs.getMetaData();
+
+        assertNotNull(meta);
+
+        assertEquals(3, meta.getColumnCount());
+
+        assertEquals("Person".toUpperCase(), 
meta.getTableName(1).toUpperCase());
+        assertEquals("name".toUpperCase(), 
meta.getColumnName(1).toUpperCase());
+        assertEquals("name".toUpperCase(), 
meta.getColumnLabel(1).toUpperCase());
+        assertEquals(Types.VARCHAR, meta.getColumnType(1));
+        assertEquals("VARCHAR", meta.getColumnTypeName(1));
+        assertEquals("java.lang.String", meta.getColumnClassName(1));
+
+        assertEquals("Organization".toUpperCase(), 
meta.getTableName(2).toUpperCase());
+        assertEquals("id".toUpperCase(), meta.getColumnName(2).toUpperCase());
+        assertEquals("orgId".toUpperCase(), 
meta.getColumnLabel(2).toUpperCase());
+        assertEquals(Types.INTEGER, meta.getColumnType(2));
+        assertEquals("INTEGER", meta.getColumnTypeName(2));
+        assertEquals("java.lang.Integer", meta.getColumnClassName(2));
+    }
+}
diff --git 
a/modules/jdbc/src/integrationTest/java/org/apache/ignite/jdbc/ItJdbcAuthenticationTest.java
 
b/modules/jdbc/src/integrationTest/java/org/apache/ignite/jdbc/ItJdbcAuthenticationTest.java
index 6cba4917ef7..d60774096d9 100644
--- 
a/modules/jdbc/src/integrationTest/java/org/apache/ignite/jdbc/ItJdbcAuthenticationTest.java
+++ 
b/modules/jdbc/src/integrationTest/java/org/apache/ignite/jdbc/ItJdbcAuthenticationTest.java
@@ -23,6 +23,7 @@ import static org.junit.jupiter.api.Assertions.assertFalse;
 import static org.junit.jupiter.api.Assertions.assertTrue;
 
 import java.sql.Connection;
+import java.sql.DatabaseMetaData;
 import java.sql.DriverManager;
 import java.sql.PreparedStatement;
 import java.sql.ResultSet;
@@ -154,5 +155,10 @@ class ItJdbcAuthenticationTest {
                 assertFalse(rs.next());
             }
         }
+
+        DatabaseMetaData metaData = conn.getMetaData();
+        // URL should not include neither username nor password
+        assertEquals("jdbc:ignite:thin://127.0.0.1:10800", metaData.getURL());
+        assertEquals(expectedUser, metaData.getUserName());
     }
 }
diff --git 
a/modules/jdbc/src/main/java/org/apache/ignite/internal/jdbc/JdbcConnection.java
 
b/modules/jdbc/src/main/java/org/apache/ignite/internal/jdbc/JdbcConnection.java
index f87e0faa4db..f73ec73c812 100644
--- 
a/modules/jdbc/src/main/java/org/apache/ignite/internal/jdbc/JdbcConnection.java
+++ 
b/modules/jdbc/src/main/java/org/apache/ignite/internal/jdbc/JdbcConnection.java
@@ -474,7 +474,7 @@ public class JdbcConnection implements Connection {
         ensureNotClosed();
 
         if (metadata == null) {
-            metadata = new JdbcDatabaseMetadata(this);
+            metadata = new JdbcDatabaseMetadata(this, handler, 
connProps.getUrl(), connProps.getUsername());
         }
 
         return metadata;
diff --git 
a/modules/jdbc/src/main/java/org/apache/ignite/internal/jdbc/JdbcDatabaseMetadata.java
 
b/modules/jdbc/src/main/java/org/apache/ignite/internal/jdbc/JdbcDatabaseMetadata.java
index 2f6e12e1790..262f149d721 100644
--- 
a/modules/jdbc/src/main/java/org/apache/ignite/internal/jdbc/JdbcDatabaseMetadata.java
+++ 
b/modules/jdbc/src/main/java/org/apache/ignite/internal/jdbc/JdbcDatabaseMetadata.java
@@ -17,13 +17,14 @@
 
 package org.apache.ignite.internal.jdbc;
 
-import static java.sql.Connection.TRANSACTION_NONE;
+import static java.sql.Connection.TRANSACTION_SERIALIZABLE;
 import static java.sql.ResultSet.CONCUR_READ_ONLY;
 import static java.sql.ResultSet.HOLD_CURSORS_OVER_COMMIT;
 import static java.sql.ResultSet.TYPE_FORWARD_ONLY;
 import static java.sql.RowIdLifetime.ROWID_UNSUPPORTED;
 import static java.util.Arrays.asList;
 import static java.util.Collections.singletonList;
+import static 
org.apache.ignite.internal.jdbc.proto.SqlStateCode.CONNECTION_CLOSED;
 
 import java.sql.Connection;
 import java.sql.DatabaseMetaData;
@@ -39,6 +40,7 @@ import java.util.concurrent.CancellationException;
 import java.util.concurrent.ExecutionException;
 import org.apache.ignite.internal.client.proto.ProtocolVersion;
 import org.apache.ignite.internal.jdbc.proto.IgniteQueryErrorCode;
+import org.apache.ignite.internal.jdbc.proto.JdbcQueryEventHandler;
 import org.apache.ignite.internal.jdbc.proto.SqlStateCode;
 import org.apache.ignite.internal.jdbc.proto.event.JdbcColumnMeta;
 import org.apache.ignite.internal.jdbc.proto.event.JdbcMetaColumnsRequest;
@@ -51,6 +53,7 @@ import 
org.apache.ignite.internal.jdbc.proto.event.JdbcMetaTablesRequest;
 import org.apache.ignite.internal.jdbc.proto.event.JdbcMetaTablesResult;
 import org.apache.ignite.internal.jdbc.proto.event.JdbcPrimaryKeyMeta;
 import org.apache.ignite.internal.jdbc.proto.event.JdbcTableMeta;
+import org.apache.ignite.internal.properties.IgniteProductVersion;
 import org.apache.ignite.sql.ColumnMetadata;
 import org.apache.ignite.sql.ColumnType;
 
@@ -70,16 +73,32 @@ public class JdbcDatabaseMetadata implements 
DatabaseMetaData {
     /** Name of system view type. */
     public static final String TYPE_VIEW = "VIEW";
 
-    /** Connection. */
-    private final JdbcConnection conn;
+    private final JdbcQueryEventHandler handler;
+
+    private final String url;
+
+    private final String userName;
+
+    private final Connection connection;
 
     /**
      * Constructor.
      *
-     * @param conn Connection.
+     * @param connection Connection
+     * @param handler Handler.
+     * @param url URL
+     * @param userName User name,
      */
-    JdbcDatabaseMetadata(JdbcConnection conn) {
-        this.conn = conn;
+    public JdbcDatabaseMetadata(
+            Connection connection,
+            JdbcQueryEventHandler handler,
+            String url,
+            String userName
+    ) {
+        this.handler = handler;
+        this.connection = connection;
+        this.url = url;
+        this.userName = userName;
     }
 
     /** {@inheritDoc} */
@@ -97,13 +116,13 @@ public class JdbcDatabaseMetadata implements 
DatabaseMetaData {
     /** {@inheritDoc} */
     @Override
     public String getURL() {
-        return conn.url();
+        return url;
     }
 
     /** {@inheritDoc} */
     @Override
     public String getUserName() {
-        return "";
+        return userName;
     }
 
     /** {@inheritDoc} */
@@ -157,19 +176,19 @@ public class JdbcDatabaseMetadata implements 
DatabaseMetaData {
     /** {@inheritDoc} */
     @Override
     public String getDriverVersion() {
-        return ProtocolVersion.LATEST_VER.toString();
+        return IgniteProductVersion.CURRENT_VERSION.toString();
     }
 
     /** {@inheritDoc} */
     @Override
     public int getDriverMajorVersion() {
-        return ProtocolVersion.LATEST_VER.major();
+        return IgniteProductVersion.CURRENT_VERSION.major();
     }
 
     /** {@inheritDoc} */
     @Override
     public int getDriverMinorVersion() {
-        return ProtocolVersion.LATEST_VER.minor();
+        return IgniteProductVersion.CURRENT_VERSION.minor();
     }
 
     /** {@inheritDoc} */
@@ -307,13 +326,13 @@ public class JdbcDatabaseMetadata implements 
DatabaseMetaData {
     /** {@inheritDoc} */
     @Override
     public boolean supportsConvert() {
-        return true;
+        return false;
     }
 
     /** {@inheritDoc} */
     @Override
     public boolean supportsConvert(int fromType, int toType) {
-        return true;
+        return false;
     }
 
     /** {@inheritDoc} */
@@ -373,19 +392,19 @@ public class JdbcDatabaseMetadata implements 
DatabaseMetaData {
     /** {@inheritDoc} */
     @Override
     public boolean supportsMultipleTransactions() {
-        return false;
+        return true;
     }
 
     /** {@inheritDoc} */
     @Override
     public boolean supportsNonNullableColumns() {
-        return false;
+        return true;
     }
 
     /** {@inheritDoc} */
     @Override
     public boolean supportsMinimumSQLGrammar() {
-        return false;
+        return true;
     }
 
     /** {@inheritDoc} */
@@ -397,7 +416,7 @@ public class JdbcDatabaseMetadata implements 
DatabaseMetaData {
     /** {@inheritDoc} */
     @Override
     public boolean supportsExtendedSQLGrammar() {
-        return false;
+        return true;
     }
 
     /** {@inheritDoc} */
@@ -410,7 +429,7 @@ public class JdbcDatabaseMetadata implements 
DatabaseMetaData {
     /** {@inheritDoc} */
     @Override
     public boolean supportsANSI92IntermediateSQL() {
-        return false;
+        return true;
     }
 
     /** {@inheritDoc} */
@@ -434,7 +453,7 @@ public class JdbcDatabaseMetadata implements 
DatabaseMetaData {
     /** {@inheritDoc} */
     @Override
     public boolean supportsFullOuterJoins() {
-        return false;
+        return true;
     }
 
     /** {@inheritDoc} */
@@ -446,7 +465,7 @@ public class JdbcDatabaseMetadata implements 
DatabaseMetaData {
     /** {@inheritDoc} */
     @Override
     public String getSchemaTerm() {
-        return "";
+        return "schema";
     }
 
     /** {@inheritDoc} */
@@ -488,7 +507,7 @@ public class JdbcDatabaseMetadata implements 
DatabaseMetaData {
     /** {@inheritDoc} */
     @Override
     public boolean supportsSchemasInTableDefinitions() {
-        return false;
+        return true;
     }
 
     /** {@inheritDoc} */
@@ -626,19 +645,19 @@ public class JdbcDatabaseMetadata implements 
DatabaseMetaData {
     /** {@inheritDoc} */
     @Override
     public int getMaxBinaryLiteralLength() {
-        return 0;
+        return Integer.MAX_VALUE;
     }
 
     /** {@inheritDoc} */
     @Override
     public int getMaxCharLiteralLength() {
-        return 0;
+        return Integer.MAX_VALUE;
     }
 
     /** {@inheritDoc} */
     @Override
     public int getMaxColumnNameLength() {
-        return 0;
+        return 128;
     }
 
     /** {@inheritDoc} */
@@ -692,7 +711,7 @@ public class JdbcDatabaseMetadata implements 
DatabaseMetaData {
     /** {@inheritDoc} */
     @Override
     public int getMaxSchemaNameLength() {
-        return 0;
+        return 128;
     }
 
     /** {@inheritDoc} */
@@ -752,19 +771,19 @@ public class JdbcDatabaseMetadata implements 
DatabaseMetaData {
     /** {@inheritDoc} */
     @Override
     public int getDefaultTransactionIsolation() {
-        return TRANSACTION_NONE;
+        return TRANSACTION_SERIALIZABLE;
     }
 
     /** {@inheritDoc} */
     @Override
     public boolean supportsTransactions() {
-        return false;
+        return true;
     }
 
     /** {@inheritDoc} */
     @Override
     public boolean supportsTransactionIsolationLevel(int level) {
-        return false;
+        return level == TRANSACTION_SERIALIZABLE;
     }
 
     /** {@inheritDoc} */
@@ -795,12 +814,17 @@ public class JdbcDatabaseMetadata implements 
DatabaseMetaData {
     @Override
     public ResultSet getProcedures(String catalog, String schemaPtrn,
             String procedureNamePtrn) throws SQLException {
+        ensureNotClosed();
+
         return new JdbcResultSet(Collections.emptyList(), asList(
                 new JdbcColumnMeta("PROCEDURE_CAT", ColumnType.STRING),
                 new JdbcColumnMeta("PROCEDURE_SCHEM", ColumnType.STRING),
                 new JdbcColumnMeta("PROCEDURE_NAME", ColumnType.STRING),
+                new JdbcColumnMeta("", ColumnType.NULL),
+                new JdbcColumnMeta("", ColumnType.NULL),
+                new JdbcColumnMeta("", ColumnType.NULL),
                 new JdbcColumnMeta("REMARKS", ColumnType.STRING),
-                new JdbcColumnMeta("PROCEDURE_TYPE", ColumnType.STRING),
+                new JdbcColumnMeta("PROCEDURE_TYPE", ColumnType.INT16),
                 new JdbcColumnMeta("SPECIFIC_NAME", ColumnType.STRING)
         ));
     }
@@ -809,13 +833,15 @@ public class JdbcDatabaseMetadata implements 
DatabaseMetaData {
     @Override
     public ResultSet getProcedureColumns(String catalog, String schemaPtrn, 
String procedureNamePtrn,
             String colNamePtrn) throws SQLException {
+        ensureNotClosed();
+
         return new JdbcResultSet(Collections.emptyList(), asList(
                 new JdbcColumnMeta("PROCEDURE_CAT", ColumnType.STRING),
                 new JdbcColumnMeta("PROCEDURE_SCHEM", ColumnType.STRING),
                 new JdbcColumnMeta("PROCEDURE_NAME", ColumnType.STRING),
                 new JdbcColumnMeta("COLUMN_NAME", ColumnType.STRING),
                 new JdbcColumnMeta("COLUMN_TYPE", ColumnType.INT16),
-                new JdbcColumnMeta("COLUMN_TYPE", ColumnType.INT32),
+                new JdbcColumnMeta("DATA_TYPE", ColumnType.INT32),
                 new JdbcColumnMeta("TYPE_NAME", ColumnType.STRING),
                 new JdbcColumnMeta("PRECISION", ColumnType.INT32),
                 new JdbcColumnMeta("LENGTH", ColumnType.INT32),
@@ -837,7 +863,7 @@ public class JdbcDatabaseMetadata implements 
DatabaseMetaData {
     @Override
     public ResultSet getTables(String catalog, String schemaPtrn, String 
tblNamePtrn, String[] tblTypes)
             throws SQLException {
-        conn.ensureNotClosed();
+        ensureNotClosed();
 
         final List<JdbcColumnMeta> meta = asList(
                 new JdbcColumnMeta("TABLE_CAT", ColumnType.STRING),
@@ -871,7 +897,7 @@ public class JdbcDatabaseMetadata implements 
DatabaseMetaData {
 
         try {
             JdbcMetaTablesResult res
-                    = conn.handler().tablesMetaAsync(new 
JdbcMetaTablesRequest(schemaPtrn, tblNamePtrn, tblTypes)).get();
+                    = handler.tablesMetaAsync(new 
JdbcMetaTablesRequest(schemaPtrn, tblNamePtrn, tblTypes)).get();
 
             if (!res.success()) {
                 throw IgniteQueryErrorCode.createJdbcSqlException(res.err(), 
res.status());
@@ -902,7 +928,7 @@ public class JdbcDatabaseMetadata implements 
DatabaseMetaData {
     /** {@inheritDoc} */
     @Override
     public ResultSet getSchemas(String catalog, String schemaPtrn) throws 
SQLException {
-        conn.ensureNotClosed();
+        ensureNotClosed();
 
         List<JdbcColumnMeta> meta = asList(
                 new JdbcColumnMeta("TABLE_SCHEM", ColumnType.STRING),
@@ -914,7 +940,7 @@ public class JdbcDatabaseMetadata implements 
DatabaseMetaData {
         }
 
         try {
-            JdbcMetaSchemasResult res = conn.handler().schemasMetaAsync(new 
JdbcMetaSchemasRequest(schemaPtrn)).get();
+            JdbcMetaSchemasResult res = handler.schemasMetaAsync(new 
JdbcMetaSchemasRequest(schemaPtrn)).get();
 
             if (!res.success()) {
                 throw IgniteQueryErrorCode.createJdbcSqlException(res.err(), 
res.status());
@@ -945,6 +971,8 @@ public class JdbcDatabaseMetadata implements 
DatabaseMetaData {
     @SuppressWarnings("ArraysAsListWithZeroOrOneArgument")
     @Override
     public ResultSet getCatalogs() throws SQLException {
+        ensureNotClosed();
+
         return new JdbcResultSet(singletonList(singletonList(CATALOG_NAME)),
                 asList(new JdbcColumnMeta("TABLE_CAT", ColumnType.STRING)));
     }
@@ -953,6 +981,8 @@ public class JdbcDatabaseMetadata implements 
DatabaseMetaData {
     @SuppressWarnings("ArraysAsListWithZeroOrOneArgument")
     @Override
     public ResultSet getTableTypes() throws SQLException {
+        ensureNotClosed();
+
         return new JdbcResultSet(
                 asList(List.of(TYPE_TABLE, TYPE_VIEW)),
                 asList(new JdbcColumnMeta("TABLE_TYPE", ColumnType.STRING)));
@@ -961,7 +991,7 @@ public class JdbcDatabaseMetadata implements 
DatabaseMetaData {
     /** {@inheritDoc} */
     @Override
     public ResultSet getColumns(String catalog, String schemaPtrn, String 
tblNamePtrn, String colNamePtrn) throws SQLException {
-        conn.ensureNotClosed();
+        ensureNotClosed();
 
         final List<JdbcColumnMeta> meta = asList(
                 new JdbcColumnMeta("TABLE_CAT", ColumnType.STRING),      // 1
@@ -995,7 +1025,7 @@ public class JdbcDatabaseMetadata implements 
DatabaseMetaData {
         }
 
         try {
-            JdbcMetaColumnsResult res = conn.handler().columnsMetaAsync(new 
JdbcMetaColumnsRequest(schemaPtrn, tblNamePtrn, colNamePtrn))
+            JdbcMetaColumnsResult res = handler.columnsMetaAsync(new 
JdbcMetaColumnsRequest(schemaPtrn, tblNamePtrn, colNamePtrn))
                     .get();
 
             if (!res.success()) {
@@ -1022,6 +1052,8 @@ public class JdbcDatabaseMetadata implements 
DatabaseMetaData {
     @Override
     public ResultSet getColumnPrivileges(String catalog, String schema, String 
tbl,
             String colNamePtrn) throws SQLException {
+        ensureNotClosed();
+
         return new JdbcResultSet(Collections.emptyList(), asList(
                 new JdbcColumnMeta("TABLE_CAT", ColumnType.STRING),
                 new JdbcColumnMeta("TABLE_SCHEM", ColumnType.STRING),
@@ -1038,6 +1070,8 @@ public class JdbcDatabaseMetadata implements 
DatabaseMetaData {
     @Override
     public ResultSet getTablePrivileges(String catalog, String schemaPtrn,
             String tblNamePtrn) throws SQLException {
+        ensureNotClosed();
+
         return new JdbcResultSet(Collections.emptyList(), asList(
                 new JdbcColumnMeta("TABLE_CAT", ColumnType.STRING),
                 new JdbcColumnMeta("TABLE_SCHEM", ColumnType.STRING),
@@ -1068,6 +1102,8 @@ public class JdbcDatabaseMetadata implements 
DatabaseMetaData {
     /** {@inheritDoc} */
     @Override
     public ResultSet getVersionColumns(String catalog, String schema, String 
tbl) throws SQLException {
+        ensureNotClosed();
+
         return new JdbcResultSet(Collections.emptyList(), asList(
                 new JdbcColumnMeta("SCOPE", ColumnType.INT16),
                 new JdbcColumnMeta("COLUMN_NAME", ColumnType.STRING),
@@ -1083,7 +1119,7 @@ public class JdbcDatabaseMetadata implements 
DatabaseMetaData {
     /** {@inheritDoc} */
     @Override
     public ResultSet getPrimaryKeys(String catalog, String schema, String tbl) 
throws SQLException {
-        conn.ensureNotClosed();
+        ensureNotClosed();
 
         final List<JdbcColumnMeta> meta = asList(
                 new JdbcColumnMeta("TABLE_CAT", ColumnType.STRING),
@@ -1098,7 +1134,7 @@ public class JdbcDatabaseMetadata implements 
DatabaseMetaData {
         }
 
         try {
-            JdbcMetaPrimaryKeysResult res = 
conn.handler().primaryKeysMetaAsync(new JdbcMetaPrimaryKeysRequest(schema, 
tbl)).get();
+            JdbcMetaPrimaryKeysResult res = handler.primaryKeysMetaAsync(new 
JdbcMetaPrimaryKeysRequest(schema, tbl)).get();
 
             if (!res.success()) {
                 throw IgniteQueryErrorCode.createJdbcSqlException(res.err(), 
res.status());
@@ -1123,6 +1159,8 @@ public class JdbcDatabaseMetadata implements 
DatabaseMetaData {
     /** {@inheritDoc} */
     @Override
     public ResultSet getImportedKeys(String catalog, String schema, String 
tbl) throws SQLException {
+        ensureNotClosed();
+
         return new JdbcResultSet(Collections.emptyList(), asList(
                 new JdbcColumnMeta("PKTABLE_CAT", ColumnType.STRING),
                 new JdbcColumnMeta("PKTABLE_SCHEM", ColumnType.STRING),
@@ -1144,6 +1182,8 @@ public class JdbcDatabaseMetadata implements 
DatabaseMetaData {
     /** {@inheritDoc} */
     @Override
     public ResultSet getExportedKeys(String catalog, String schema, String 
tbl) throws SQLException {
+        ensureNotClosed();
+
         return new JdbcResultSet(Collections.emptyList(), asList(
                 new JdbcColumnMeta("PKTABLE_CAT", ColumnType.STRING),
                 new JdbcColumnMeta("PKTABLE_SCHEM", ColumnType.STRING),
@@ -1166,6 +1206,8 @@ public class JdbcDatabaseMetadata implements 
DatabaseMetaData {
     @Override
     public ResultSet getCrossReference(String parentCatalog, String 
parentSchema, String parentTbl,
             String foreignCatalog, String foreignSchema, String foreignTbl) 
throws SQLException {
+        ensureNotClosed();
+
         return new JdbcResultSet(Collections.emptyList(), asList(
                 new JdbcColumnMeta("PKTABLE_CAT", ColumnType.STRING),
                 new JdbcColumnMeta("PKTABLE_SCHEM", ColumnType.STRING),
@@ -1187,6 +1229,8 @@ public class JdbcDatabaseMetadata implements 
DatabaseMetaData {
     /** {@inheritDoc} */
     @Override
     public ResultSet getTypeInfo() throws SQLException {
+        ensureNotClosed();
+
         List<List<Object>> types = new ArrayList<>(21);
 
         types.add(asList("BOOLEAN", Types.BOOLEAN, 1, null, null, null,
@@ -1305,7 +1349,7 @@ public class JdbcDatabaseMetadata implements 
DatabaseMetaData {
     @Override
     public ResultSet getIndexInfo(String catalog, String schema, String tbl, 
boolean unique,
             boolean approximate) throws SQLException {
-        conn.ensureNotClosed();
+        ensureNotClosed();
 
         final List<JdbcColumnMeta> meta = asList(
                 new JdbcColumnMeta("TABLE_CAT", ColumnType.STRING),
@@ -1405,6 +1449,8 @@ public class JdbcDatabaseMetadata implements 
DatabaseMetaData {
     @Override
     public ResultSet getUDTs(String catalog, String schemaPtrn, String 
typeNamePtrn,
             int[] types) throws SQLException {
+        ensureNotClosed();
+
         return new JdbcResultSet(Collections.emptyList(), asList(
                 new JdbcColumnMeta("TYPE_CAT", ColumnType.STRING),
                 new JdbcColumnMeta("TYPE_SCHEM", ColumnType.STRING),
@@ -1419,7 +1465,7 @@ public class JdbcDatabaseMetadata implements 
DatabaseMetaData {
     /** {@inheritDoc} */
     @Override
     public Connection getConnection() {
-        return conn;
+        return connection;
     }
 
     /** {@inheritDoc} */
@@ -1450,6 +1496,8 @@ public class JdbcDatabaseMetadata implements 
DatabaseMetaData {
     @Override
     public ResultSet getSuperTypes(String catalog, String schemaPtrn,
             String typeNamePtrn) throws SQLException {
+        ensureNotClosed();
+
         return new JdbcResultSet(Collections.emptyList(), asList(
                 new JdbcColumnMeta("TYPE_CAT", ColumnType.STRING),
                 new JdbcColumnMeta("TYPE_SCHEM", ColumnType.STRING),
@@ -1464,6 +1512,8 @@ public class JdbcDatabaseMetadata implements 
DatabaseMetaData {
     @Override
     public ResultSet getSuperTables(String catalog, String schemaPtrn,
             String tblNamePtrn) throws SQLException {
+        ensureNotClosed();
+
         return new JdbcResultSet(Collections.emptyList(), asList(
                 new JdbcColumnMeta("TABLE_CAT", ColumnType.STRING),
                 new JdbcColumnMeta("TABLE_SCHEM", ColumnType.STRING),
@@ -1476,6 +1526,8 @@ public class JdbcDatabaseMetadata implements 
DatabaseMetaData {
     @Override
     public ResultSet getAttributes(String catalog, String schemaPtrn, String 
typeNamePtrn,
             String attributeNamePtrn) throws SQLException {
+        ensureNotClosed();
+
         return new JdbcResultSet(Collections.emptyList(), asList(
                 new JdbcColumnMeta("TYPE_CAT", ColumnType.STRING),
                 new JdbcColumnMeta("TYPE_SCHEM", ColumnType.STRING),
@@ -1576,6 +1628,8 @@ public class JdbcDatabaseMetadata implements 
DatabaseMetaData {
     /** {@inheritDoc} */
     @Override
     public ResultSet getClientInfoProperties() throws SQLException {
+        // We do not check whether connection is closed as 
+        // this operation is not expected to do any server calls.  
         return new JdbcResultSet(Collections.emptyList(), asList(
                 new JdbcColumnMeta("NAME", ColumnType.STRING),
                 new JdbcColumnMeta("MAX_LEN", ColumnType.INT32),
@@ -1590,6 +1644,8 @@ public class JdbcDatabaseMetadata implements 
DatabaseMetaData {
     @Override
     public ResultSet getFunctions(String catalog, String schemaPtrn,
             String functionNamePtrn) throws SQLException {
+        ensureNotClosed();
+
         return new JdbcResultSet(Collections.emptyList(), asList(
                 new JdbcColumnMeta("FUNCTION_CAT", ColumnType.STRING),
                 new JdbcColumnMeta("FUNCTION_SCHEM", ColumnType.STRING),
@@ -1604,6 +1660,8 @@ public class JdbcDatabaseMetadata implements 
DatabaseMetaData {
     @Override
     public ResultSet getFunctionColumns(String catalog, String schemaPtrn, 
String functionNamePtrn,
             String colNamePtrn) throws SQLException {
+        ensureNotClosed();
+
         return new JdbcResultSet(Collections.emptyList(), asList(
                 new JdbcColumnMeta("FUNCTION_CAT", ColumnType.STRING),
                 new JdbcColumnMeta("FUNCTION_SCHEM", ColumnType.STRING),
@@ -1645,6 +1703,8 @@ public class JdbcDatabaseMetadata implements 
DatabaseMetaData {
     @Override
     public ResultSet getPseudoColumns(String catalog, String schemaPtrn, 
String tblNamePtrn,
             String colNamePtrn) throws SQLException {
+        ensureNotClosed();
+
         return new JdbcResultSet(Collections.emptyList(), asList(
                 new JdbcColumnMeta("TABLE_CAT", ColumnType.STRING),
                 new JdbcColumnMeta("TABLE_SCHEM", ColumnType.STRING),
@@ -1666,7 +1726,7 @@ public class JdbcDatabaseMetadata implements 
DatabaseMetaData {
      *
      * @param catalog Catalog name or {@code null}.
      * @return {@code true} If catalog equal ignoring case to {@link 
JdbcDatabaseMetadata#CATALOG_NAME} or null (which means any catalog),
-     *      otherwise returns {@code false}.
+     *         otherwise returns {@code false}.
      */
     private static boolean isValidCatalog(String catalog) {
         return catalog == null || catalog.equalsIgnoreCase(CATALOG_NAME);
@@ -1705,7 +1765,7 @@ public class JdbcDatabaseMetadata implements 
DatabaseMetaData {
      * Constructs a list of rows in jdbc format for a given column metadata.
      *
      * @param colMeta Column metadata.
-     * @param pos     Ordinal position.
+     * @param pos Ordinal position.
      * @return Column metadata row.
      */
     public static List<Object> columnRow(JdbcColumnMeta colMeta, int pos) {
@@ -1763,4 +1823,10 @@ public class JdbcDatabaseMetadata implements 
DatabaseMetaData {
 
         return rows;
     }
+
+    private void ensureNotClosed() throws SQLException {
+        if (connection.isClosed()) {
+            throw new SQLException("Connection is closed.", CONNECTION_CLOSED);
+        }
+    }
 }
diff --git 
a/modules/jdbc/src/test/java/org/apache/ignite/internal/jdbc/JdbcDatabaseMetadataSelfTest.java
 
b/modules/jdbc/src/test/java/org/apache/ignite/internal/jdbc/JdbcDatabaseMetadataSelfTest.java
new file mode 100644
index 00000000000..e9be3712d68
--- /dev/null
+++ 
b/modules/jdbc/src/test/java/org/apache/ignite/internal/jdbc/JdbcDatabaseMetadataSelfTest.java
@@ -0,0 +1,274 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.ignite.internal.jdbc;
+
+import static org.junit.jupiter.api.Assertions.assertEquals;
+import static org.junit.jupiter.api.Assertions.assertFalse;
+import static org.junit.jupiter.api.Assertions.assertSame;
+import static org.junit.jupiter.api.Assertions.assertTrue;
+
+import java.sql.Connection;
+import java.sql.DatabaseMetaData;
+import java.sql.ResultSet;
+import java.sql.RowIdLifetime;
+import java.sql.SQLException;
+import java.util.concurrent.ThreadLocalRandom;
+import org.apache.ignite.internal.client.proto.ProtocolVersion;
+import org.apache.ignite.internal.properties.IgniteProductVersion;
+import org.apache.ignite.internal.testframework.BaseIgniteAbstractTest;
+import org.junit.jupiter.api.Test;
+import org.mockito.Mockito;
+
+/**
+ * Tests for {@link JdbcDatabaseMetadata}.
+ */
+public class JdbcDatabaseMetadataSelfTest extends BaseIgniteAbstractTest {
+
+    @Test
+    public void constantMethods() throws SQLException {
+        String username = 
String.valueOf(ThreadLocalRandom.current().nextInt(128, 256));
+        String jdbcUrl = "jdbc:ignite://localhost:" + 
ThreadLocalRandom.current().nextInt(1000, 10800);
+
+        JdbcClientQueryEventHandler handler = 
Mockito.mock(JdbcClientQueryEventHandler.class);
+        Connection connection = Mockito.mock(Connection.class);
+        DatabaseMetaData metaData = new JdbcDatabaseMetadata(connection, 
handler, jdbcUrl, username);
+
+        // Basic info
+        assertTrue(metaData.allProceduresAreCallable());
+        assertTrue(metaData.allTablesAreSelectable());
+        assertEquals(jdbcUrl, metaData.getURL());
+        assertEquals(username, metaData.getUserName());
+        assertFalse(metaData.isReadOnly());
+
+        // Null ordering
+        assertFalse(metaData.nullsAreSortedHigh());
+        assertTrue(metaData.nullsAreSortedLow());
+        assertFalse(metaData.nullsAreSortedAtStart());
+        assertTrue(metaData.nullsAreSortedAtEnd());
+
+        // Product and driver info
+        assertEquals("Apache Ignite", metaData.getDatabaseProductName());
+        assertEquals(ProtocolVersion.LATEST_VER.toString(), 
metaData.getDatabaseProductVersion());
+        assertEquals("Apache Ignite JDBC Driver", metaData.getDriverName());
+        IgniteProductVersion productVersion = 
IgniteProductVersion.CURRENT_VERSION;
+        assertEquals(productVersion.toString(), metaData.getDriverVersion());
+        assertEquals(productVersion.major(), metaData.getDriverMajorVersion());
+        assertEquals(productVersion.minor(), metaData.getDriverMinorVersion());
+
+        // Files, identifiers, quotes
+        assertFalse(metaData.usesLocalFiles());
+        assertFalse(metaData.usesLocalFilePerTable());
+        assertFalse(metaData.supportsMixedCaseIdentifiers());
+        assertTrue(metaData.storesUpperCaseIdentifiers());
+        assertFalse(metaData.storesLowerCaseIdentifiers());
+        assertFalse(metaData.storesMixedCaseIdentifiers());
+        assertFalse(metaData.supportsMixedCaseQuotedIdentifiers());
+        assertTrue(metaData.storesUpperCaseQuotedIdentifiers());
+        assertFalse(metaData.storesLowerCaseQuotedIdentifiers());
+        assertTrue(metaData.storesMixedCaseQuotedIdentifiers());
+        assertEquals("\"", metaData.getIdentifierQuoteString());
+        assertEquals("", metaData.getSQLKeywords());
+        assertEquals("", metaData.getNumericFunctions());
+        assertEquals("", metaData.getStringFunctions());
+        assertEquals("", metaData.getSystemFunctions());
+        assertEquals("", metaData.getTimeDateFunctions());
+        assertEquals("\\", metaData.getSearchStringEscape());
+        assertEquals("", metaData.getExtraNameCharacters());
+
+        // Simple supports flags
+        assertTrue(metaData.supportsAlterTableWithAddColumn());
+        assertTrue(metaData.supportsAlterTableWithDropColumn());
+        assertTrue(metaData.supportsColumnAliasing());
+        assertTrue(metaData.nullPlusNonNullIsNull());
+        assertFalse(metaData.supportsConvert());
+        assertFalse(metaData.supportsConvert(0, 0));
+        assertTrue(metaData.supportsTableCorrelationNames());
+        assertTrue(metaData.supportsDifferentTableCorrelationNames());
+        assertTrue(metaData.supportsExpressionsInOrderBy());
+        assertTrue(metaData.supportsOrderByUnrelated());
+        assertTrue(metaData.supportsGroupBy());
+        assertTrue(metaData.supportsGroupByUnrelated());
+        assertTrue(metaData.supportsGroupByBeyondSelect());
+        assertTrue(metaData.supportsLikeEscapeClause());
+        assertTrue(metaData.supportsMultipleResultSets());
+        assertTrue(metaData.supportsMultipleTransactions());
+        assertTrue(metaData.supportsNonNullableColumns());
+
+        // SQL support
+        assertTrue(metaData.supportsMinimumSQLGrammar());
+        assertTrue(metaData.supportsCoreSQLGrammar());
+        assertTrue(metaData.supportsExtendedSQLGrammar());
+        assertTrue(metaData.supportsANSI92EntryLevelSQL());
+        assertTrue(metaData.supportsANSI92IntermediateSQL());
+        assertFalse(metaData.supportsANSI92FullSQL());
+        assertFalse(metaData.supportsIntegrityEnhancementFacility());
+        assertTrue(metaData.supportsOuterJoins());
+        assertTrue(metaData.supportsFullOuterJoins());
+        assertTrue(metaData.supportsFullOuterJoins());
+        assertTrue(metaData.supportsLimitedOuterJoins());
+
+        assertEquals("schema", metaData.getSchemaTerm());
+        assertEquals("", metaData.getProcedureTerm());
+        assertEquals("", metaData.getCatalogTerm());
+        assertFalse(metaData.isCatalogAtStart());
+        assertEquals("", metaData.getCatalogSeparator());
+
+        assertTrue(metaData.supportsSchemasInDataManipulation());
+        assertFalse(metaData.supportsSchemasInProcedureCalls());
+        assertTrue(metaData.supportsSchemasInTableDefinitions());
+        assertFalse(metaData.supportsSchemasInIndexDefinitions());
+        assertFalse(metaData.supportsSchemasInPrivilegeDefinitions());
+        assertFalse(metaData.supportsCatalogsInDataManipulation());
+        assertFalse(metaData.supportsCatalogsInProcedureCalls());
+        assertFalse(metaData.supportsCatalogsInTableDefinitions());
+        assertFalse(metaData.supportsCatalogsInIndexDefinitions());
+        assertFalse(metaData.supportsCatalogsInPrivilegeDefinitions());
+        assertFalse(metaData.supportsPositionedDelete());
+        assertFalse(metaData.supportsPositionedUpdate());
+        assertFalse(metaData.supportsSelectForUpdate());
+        assertFalse(metaData.supportsStoredProcedures());
+        assertTrue(metaData.supportsSubqueriesInComparisons());
+        assertTrue(metaData.supportsSubqueriesInExists());
+        assertTrue(metaData.supportsSubqueriesInIns());
+        assertTrue(metaData.supportsSubqueriesInQuantifieds());
+        assertTrue(metaData.supportsCorrelatedSubqueries());
+        assertTrue(metaData.supportsUnion());
+        assertTrue(metaData.supportsUnionAll());
+
+        // Statements
+        assertFalse(metaData.supportsOpenCursorsAcrossCommit());
+        assertFalse(metaData.supportsOpenCursorsAcrossRollback());
+        assertFalse(metaData.supportsOpenStatementsAcrossCommit());
+        assertFalse(metaData.supportsOpenStatementsAcrossCommit());
+        assertFalse(metaData.supportsOpenStatementsAcrossRollback());
+
+        // Lengths
+        assertEquals(Integer.MAX_VALUE, metaData.getMaxBinaryLiteralLength());
+        assertEquals(Integer.MAX_VALUE, metaData.getMaxCharLiteralLength());
+        assertEquals(128, metaData.getMaxColumnNameLength());
+        assertEquals(0, metaData.getMaxColumnsInGroupBy());
+        assertEquals(0, metaData.getMaxColumnsInIndex());
+        assertEquals(0, metaData.getMaxColumnsInOrderBy());
+        assertEquals(0, metaData.getMaxColumnsInSelect());
+        assertEquals(0, metaData.getMaxColumnsInTable());
+        assertEquals(0, metaData.getMaxConnections());
+        assertEquals(0, metaData.getMaxCursorNameLength());
+        assertEquals(0, metaData.getMaxIndexLength());
+        assertEquals(128, metaData.getMaxSchemaNameLength());
+        assertEquals(0, metaData.getMaxProcedureNameLength());
+        assertEquals(0, metaData.getMaxCatalogNameLength());
+        assertEquals(0, metaData.getMaxRowSize());
+        assertFalse(metaData.doesMaxRowSizeIncludeBlobs());
+        assertEquals(0, metaData.getMaxStatementLength());
+        assertEquals(0, metaData.getMaxStatements());
+        assertEquals(0, metaData.getMaxTablesInSelect());
+        assertEquals(0, metaData.getMaxUserNameLength());
+        assertEquals(0, metaData.getMaxUserNameLength());
+
+        // Transactions related constants
+        assertEquals(Connection.TRANSACTION_SERIALIZABLE, 
metaData.getDefaultTransactionIsolation());
+        assertTrue(metaData.supportsTransactions());
+
+        
assertFalse(metaData.supportsTransactionIsolationLevel(Connection.TRANSACTION_NONE));
+        
assertFalse(metaData.supportsTransactionIsolationLevel(Connection.TRANSACTION_READ_UNCOMMITTED));
+        
assertFalse(metaData.supportsTransactionIsolationLevel(Connection.TRANSACTION_READ_COMMITTED));
+        
assertFalse(metaData.supportsTransactionIsolationLevel(Connection.TRANSACTION_REPEATABLE_READ));
+        
assertTrue(metaData.supportsTransactionIsolationLevel(Connection.TRANSACTION_SERIALIZABLE));
+
+        
assertFalse(metaData.supportsDataDefinitionAndDataManipulationTransactions());
+        assertFalse(metaData.supportsDataManipulationTransactionsOnly());
+        assertFalse(metaData.dataDefinitionCausesTransactionCommit());
+        assertFalse(metaData.dataDefinitionIgnoredInTransactions());
+
+        // ResultSet support constants
+        
assertTrue(metaData.supportsResultSetType(ResultSet.TYPE_FORWARD_ONLY));
+        
assertFalse(metaData.supportsResultSetType(ResultSet.TYPE_SCROLL_INSENSITIVE));
+        
assertFalse(metaData.supportsResultSetType(ResultSet.TYPE_SCROLL_SENSITIVE));
+
+        
assertTrue(metaData.supportsResultSetConcurrency(ResultSet.TYPE_FORWARD_ONLY, 
ResultSet.CONCUR_READ_ONLY));
+        
assertFalse(metaData.supportsResultSetConcurrency(ResultSet.TYPE_FORWARD_ONLY, 
ResultSet.CONCUR_UPDATABLE));
+
+        // ResultSet own DML methods
+        
assertFalse(metaData.ownUpdatesAreVisible(ResultSet.TYPE_FORWARD_ONLY));
+        
assertFalse(metaData.ownUpdatesAreVisible(ResultSet.TYPE_SCROLL_SENSITIVE));
+        
assertFalse(metaData.ownUpdatesAreVisible(ResultSet.TYPE_SCROLL_INSENSITIVE));
+
+        
assertFalse(metaData.ownDeletesAreVisible(ResultSet.TYPE_FORWARD_ONLY));
+        
assertFalse(metaData.ownDeletesAreVisible(ResultSet.TYPE_SCROLL_SENSITIVE));
+        
assertFalse(metaData.ownDeletesAreVisible(ResultSet.TYPE_SCROLL_INSENSITIVE));
+
+        
assertFalse(metaData.ownInsertsAreVisible(ResultSet.TYPE_FORWARD_ONLY));
+        
assertFalse(metaData.ownInsertsAreVisible(ResultSet.TYPE_SCROLL_SENSITIVE));
+        
assertFalse(metaData.ownInsertsAreVisible(ResultSet.TYPE_SCROLL_INSENSITIVE));
+
+        // ResultSet other DML methods
+        
assertFalse(metaData.othersUpdatesAreVisible(ResultSet.TYPE_FORWARD_ONLY));
+        
assertFalse(metaData.othersUpdatesAreVisible(ResultSet.TYPE_SCROLL_SENSITIVE));
+        
assertFalse(metaData.othersUpdatesAreVisible(ResultSet.TYPE_SCROLL_INSENSITIVE));
+
+        
assertFalse(metaData.othersDeletesAreVisible(ResultSet.TYPE_FORWARD_ONLY));
+        
assertFalse(metaData.othersDeletesAreVisible(ResultSet.TYPE_SCROLL_SENSITIVE));
+        
assertFalse(metaData.othersDeletesAreVisible(ResultSet.TYPE_SCROLL_INSENSITIVE));
+
+        
assertFalse(metaData.othersInsertsAreVisible(ResultSet.TYPE_FORWARD_ONLY));
+        
assertFalse(metaData.othersInsertsAreVisible(ResultSet.TYPE_SCROLL_SENSITIVE));
+        
assertFalse(metaData.othersInsertsAreVisible(ResultSet.TYPE_SCROLL_INSENSITIVE));
+
+        // ResultSet DML ops detected
+        assertFalse(metaData.updatesAreDetected(ResultSet.TYPE_FORWARD_ONLY));
+        
assertFalse(metaData.updatesAreDetected(ResultSet.TYPE_SCROLL_SENSITIVE));
+        
assertFalse(metaData.updatesAreDetected(ResultSet.TYPE_SCROLL_INSENSITIVE));
+
+        assertFalse(metaData.deletesAreDetected(ResultSet.TYPE_FORWARD_ONLY));
+        
assertFalse(metaData.deletesAreDetected(ResultSet.TYPE_SCROLL_SENSITIVE));
+        
assertFalse(metaData.deletesAreDetected(ResultSet.TYPE_SCROLL_INSENSITIVE));
+
+        assertFalse(metaData.insertsAreDetected(ResultSet.TYPE_FORWARD_ONLY));
+        
assertFalse(metaData.insertsAreDetected(ResultSet.TYPE_SCROLL_SENSITIVE));
+        
assertFalse(metaData.insertsAreDetected(ResultSet.TYPE_SCROLL_INSENSITIVE));
+
+        // Holdability, JDBC and SQL state meta
+        
assertTrue(metaData.supportsResultSetHoldability(ResultSet.HOLD_CURSORS_OVER_COMMIT));
+        assertEquals(ResultSet.HOLD_CURSORS_OVER_COMMIT, 
metaData.getResultSetHoldability());
+        assertTrue(metaData.getDatabaseMajorVersion() >= 0);
+        assertTrue(metaData.getDatabaseMinorVersion() >= 0);
+        assertTrue(metaData.getJDBCMajorVersion() >= 0);
+        assertTrue(metaData.getJDBCMinorVersion() >= 0);
+        assertEquals(DatabaseMetaData.sqlStateSQL99, 
metaData.getSQLStateType());
+        assertFalse(metaData.locatorsUpdateCopy());
+        assertFalse(metaData.supportsStatementPooling());
+        assertEquals(RowIdLifetime.ROWID_UNSUPPORTED, 
metaData.getRowIdLifetime());
+        assertFalse(metaData.supportsStoredFunctionsUsingCallSyntax());
+        assertFalse(metaData.autoCommitFailureClosesAllResultSets());
+
+        // Wrapper and connection
+        assertTrue(metaData.isWrapperFor(JdbcDatabaseMetadata.class));
+        assertSame(connection, metaData.getConnection());
+        assertSame(metaData, metaData.unwrap(JdbcDatabaseMetadata.class));
+        assertSame(metaData, metaData.unwrap(DatabaseMetaData.class));
+
+        // Misc flags
+        assertTrue(metaData.supportsBatchUpdates());
+        assertFalse(metaData.supportsSavepoints());
+        assertFalse(metaData.supportsNamedParameters());
+        assertFalse(metaData.supportsMultipleOpenResults());
+        assertFalse(metaData.supportsGetGeneratedKeys());
+
+        assertFalse(metaData.generatedKeyAlwaysReturned());
+    }
+}


Reply via email to