You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@ignite.apache.org by am...@apache.org on 2019/08/27 14:37:18 UTC

[ignite] branch master updated: IGNITE-11470: Views don't show in Dbeaver. This closes #6456.

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

amashenkov pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/ignite.git


The following commit(s) were added to refs/heads/master by this push:
     new ff87804  IGNITE-11470: Views don't show in Dbeaver. This closes #6456.
ff87804 is described below

commit ff8780405c27db6be409934246a68cffbae8cf61
Author: Yury Gerzhedovich <yg...@gridgain.com>
AuthorDate: Tue Aug 27 17:36:45 2019 +0300

    IGNITE-11470: Views don't show in Dbeaver. This closes #6456.
---
 .../internal/jdbc2/JdbcMetadataSelfTest.java       |  67 ++++-
 .../JdbcThinConnectionMultipleAddressesTest.java   |   8 +-
 .../ignite/jdbc/thin/JdbcThinMetadataSelfTest.java | 316 +++++++++++++++++++--
 .../jdbc/thin/JdbcThinDatabaseMetadata.java        |  67 +++--
 .../internal/jdbc2/JdbcDatabaseMetadata.java       |  68 +++--
 .../apache/ignite/internal/jdbc2/JdbcUtils.java    |   8 +-
 .../odbc/jdbc/JdbcMetaTablesRequest.java           |  26 +-
 .../processors/odbc/jdbc/JdbcMetadataInfo.java     | 169 ++++++-----
 .../processors/odbc/jdbc/JdbcRequestHandler.java   |   2 +-
 .../processors/odbc/jdbc/JdbcTableMeta.java        |  30 +-
 .../processors/query/ColumnInformation.java        | 182 ++++++++++++
 .../processors/query/GridQueryIndexing.java        |  23 ++
 .../processors/query/TableInformation.java         | 236 +++++++++++++++
 .../IgniteClientCacheInitializationFailTest.java   |  15 +
 .../processors/query/DummyQueryIndexing.java       |  16 ++
 .../processors/query/h2/IgniteH2Indexing.java      | 120 ++++++++
 .../processors/query/h2/SchemaManager.java         |  15 +-
 .../processors/query/h2/opt/GridH2Table.java       |  11 +
 .../processors/query/h2/sys/SqlSystemIndex.java    |   8 +-
 .../query/h2/sys/SqlSystemTableEngine.java         |   2 +-
 ...qlSystemTable.java => SystemViewH2Adapter.java} |   8 +-
 .../query/h2/sys/view/SqlSystemViewTables.java     |  93 ++----
 22 files changed, 1220 insertions(+), 270 deletions(-)

diff --git a/modules/clients/src/test/java/org/apache/ignite/internal/jdbc2/JdbcMetadataSelfTest.java b/modules/clients/src/test/java/org/apache/ignite/internal/jdbc2/JdbcMetadataSelfTest.java
index 6011ad4..cf4b774 100755
--- a/modules/clients/src/test/java/org/apache/ignite/internal/jdbc2/JdbcMetadataSelfTest.java
+++ b/modules/clients/src/test/java/org/apache/ignite/internal/jdbc2/JdbcMetadataSelfTest.java
@@ -35,6 +35,7 @@ import java.util.Arrays;
 import java.util.Collection;
 import java.util.HashSet;
 import java.util.LinkedHashMap;
+import java.util.List;
 import java.util.Set;
 import org.apache.ignite.IgniteCache;
 import org.apache.ignite.cache.QueryEntity;
@@ -46,6 +47,7 @@ import org.apache.ignite.configuration.ConnectorConfiguration;
 import org.apache.ignite.configuration.IgniteConfiguration;
 import org.apache.ignite.internal.IgniteVersionUtils;
 import org.apache.ignite.internal.processors.query.QueryEntityEx;
+import org.apache.ignite.internal.processors.query.QueryUtils;
 import org.apache.ignite.internal.util.typedef.F;
 import org.apache.ignite.testframework.GridTestUtils;
 import org.apache.ignite.testframework.junits.common.GridCommonAbstractTest;
@@ -296,6 +298,69 @@ public class JdbcMetadataSelfTest extends GridCommonAbstractTest {
      * @throws Exception If failed.
      */
     @Test
+    public void testGetTableTypes() throws Exception {
+        try (Connection conn = DriverManager.getConnection(BASE_URL)) {
+            DatabaseMetaData meta = conn.getMetaData();
+
+            ResultSet rs = meta.getTableTypes();
+
+            assertTrue(rs.next());
+
+            assertEquals("TABLE", rs.getString("TABLE_TYPE"));
+
+            assertTrue(rs.next());
+
+            assertEquals("VIEW", rs.getString("TABLE_TYPE"));
+        }
+    }
+
+
+    /**
+     * @throws Exception If failed.
+     */
+    @Test
+    public void testGetAllView() throws Exception {
+        List<String> expViews = Arrays.asList(
+            "BASELINE_NODES",
+            "CACHES",
+            "CACHE_GROUPS",
+            "INDEXES",
+            "LOCAL_CACHE_GROUPS_IO",
+            "LOCAL_SQL_QUERY_HISTORY",
+            "LOCAL_SQL_RUNNING_QUERIES",
+            "NODES",
+            "NODE_ATTRIBUTES",
+            "NODE_METRICS",
+            "SCHEMAS",
+            "TABLES"
+        );
+
+        try (Connection conn = DriverManager.getConnection(BASE_URL)) {
+            DatabaseMetaData meta = conn.getMetaData();
+
+            ResultSet rs = meta.getTables(null, null, "%", new String[]{"VIEW"});
+
+            for (String viewName : expViews) {
+                assertTrue(rs.next());
+
+                assertEquals("VIEW", rs.getString("TABLE_TYPE"));
+
+                assertEquals(JdbcUtils.CATALOG_NAME, rs.getString("TABLE_CAT"));
+
+                assertEquals(QueryUtils.SCHEMA_SYS, rs.getString("TABLE_SCHEM"));
+
+                assertEquals(viewName, rs.getString("TABLE_NAME"));
+            }
+
+            assertFalse(rs.next());
+        }
+    }
+
+
+    /**
+     * @throws Exception If failed.
+     */
+    @Test
     public void testGetTables() throws Exception {
         try (Connection conn = DriverManager.getConnection(BASE_URL)) {
             DatabaseMetaData meta = conn.getMetaData();
@@ -575,7 +640,7 @@ public class JdbcMetadataSelfTest extends GridCommonAbstractTest {
             // No parameters statement.
             try(Connection conn = DriverManager.getConnection(BASE_URL)) {
                 conn.setSchema("\"pers\"");
-                
+
                 PreparedStatement noParams = conn.prepareStatement("select * from Person;");
                 ParameterMetaData params = noParams.getParameterMetaData();
 
diff --git a/modules/clients/src/test/java/org/apache/ignite/jdbc/thin/JdbcThinConnectionMultipleAddressesTest.java b/modules/clients/src/test/java/org/apache/ignite/jdbc/thin/JdbcThinConnectionMultipleAddressesTest.java
index 1edae3a..2019cc1 100644
--- a/modules/clients/src/test/java/org/apache/ignite/jdbc/thin/JdbcThinConnectionMultipleAddressesTest.java
+++ b/modules/clients/src/test/java/org/apache/ignite/jdbc/thin/JdbcThinConnectionMultipleAddressesTest.java
@@ -347,7 +347,7 @@ public class JdbcThinConnectionMultipleAddressesTest extends JdbcThinAbstractSel
     }
 
     /**
-     * Check failover on restart cluster ar stop one node.
+     * Check failover on restart cluster or stop one node.
      *
      * @param url Connection URL.
      * @param allNodes Restart all nodes flag.
@@ -357,7 +357,9 @@ public class JdbcThinConnectionMultipleAddressesTest extends JdbcThinAbstractSel
         try (Connection conn = DriverManager.getConnection(url)) {
             DatabaseMetaData meta = conn.getMetaData();
 
-            ResultSet rs0 = meta.getTables(null, null, null, null);
+            final String[] types = {"TABLES"};
+
+            ResultSet rs0 = meta.getTables(null, null, null, types);
 
             assertFalse(rs0.next());
 
@@ -373,7 +375,7 @@ public class JdbcThinConnectionMultipleAddressesTest extends JdbcThinAbstractSel
 
             restart(allNodes);
 
-            rs0 = meta.getTables(null, null, null, null);
+            rs0 = meta.getTables(null, null, null, types);
             assertFalse(rs0.next());
         }
     }
diff --git a/modules/clients/src/test/java/org/apache/ignite/jdbc/thin/JdbcThinMetadataSelfTest.java b/modules/clients/src/test/java/org/apache/ignite/jdbc/thin/JdbcThinMetadataSelfTest.java
index e36e6d9..322339d 100644
--- a/modules/clients/src/test/java/org/apache/ignite/jdbc/thin/JdbcThinMetadataSelfTest.java
+++ b/modules/clients/src/test/java/org/apache/ignite/jdbc/thin/JdbcThinMetadataSelfTest.java
@@ -35,6 +35,7 @@ import java.util.Collections;
 import java.util.HashMap;
 import java.util.HashSet;
 import java.util.LinkedHashMap;
+import java.util.List;
 import java.util.Map;
 import java.util.Set;
 import org.apache.ignite.IgniteCache;
@@ -47,7 +48,9 @@ import org.apache.ignite.configuration.IgniteConfiguration;
 import org.apache.ignite.internal.IgniteVersionUtils;
 import org.apache.ignite.internal.jdbc2.JdbcUtils;
 import org.apache.ignite.internal.processors.query.QueryEntityEx;
+import org.apache.ignite.internal.processors.query.QueryUtils;
 import org.apache.ignite.internal.util.typedef.F;
+import org.junit.Assert;
 import org.apache.ignite.testframework.GridTestUtils;
 import org.junit.Test;
 
@@ -225,6 +228,27 @@ public class JdbcThinMetadataSelfTest extends JdbcThinAbstractSelfTest {
         }
     }
 
+
+    /**
+     * @throws Exception If failed.
+     */
+    @Test
+    public void testGetTableTypes() throws Exception {
+        try (Connection conn = DriverManager.getConnection(URL)) {
+            DatabaseMetaData meta = conn.getMetaData();
+
+            ResultSet rs = meta.getTableTypes();
+
+            assertTrue(rs.next());
+
+            assertEquals("TABLE", rs.getString("TABLE_TYPE"));
+
+            assertTrue(rs.next());
+
+            assertEquals("VIEW", rs.getString("TABLE_TYPE"));
+        }
+    }
+
     /**
      * @throws Exception If failed.
      */
@@ -279,12 +303,9 @@ public class JdbcThinMetadataSelfTest extends JdbcThinAbstractSelfTest {
      */
     @Test
     public void testGetAllTables() throws Exception {
-        try (Connection conn = DriverManager.getConnection(URL)) {
-            DatabaseMetaData meta = conn.getMetaData();
-
-            ResultSet rs = meta.getTables(null, null, null, null);
-
-            Set<String> expectedTbls = new HashSet<>(Arrays.asList(
+        testGetTables(
+            new String[] {"TABLE"},
+            new HashSet<>(Arrays.asList(
                 "org.ORGANIZATION",
                 "pers.PERSON",
                 "dep.DEPARTMENT",
@@ -292,16 +313,51 @@ public class JdbcThinMetadataSelfTest extends JdbcThinAbstractSelfTest {
                 "PUBLIC.Quoted",
                 "PUBLIC.TEST_DECIMAL_COLUMN",
                 "PUBLIC.TEST_DECIMAL_COLUMN_PRECISION",
-                "PUBLIC.TEST_DECIMAL_DATE_COLUMN_META"));
+                "PUBLIC.TEST_DECIMAL_DATE_COLUMN_META"))
+        );
+    }
 
-            Set<String> actualTbls = new HashSet<>(expectedTbls.size());
+    /**
+     * @throws Exception If failed.
+     */
+    @Test
+    public void testGetAllView() throws Exception {
+        testGetTables(
+            new String[] {"VIEW"},
+            new HashSet<>(Arrays.asList(
+                "SYS.LOCAL_SQL_QUERY_HISTORY",
+                "SYS.NODES",
+                "SYS.SCHEMAS",
+                "SYS.CACHE_GROUPS",
+                "SYS.NODE_METRICS",
+                "SYS.BASELINE_NODES",
+                "SYS.INDEXES",
+                "SYS.LOCAL_CACHE_GROUPS_IO",
+                "SYS.LOCAL_SQL_RUNNING_QUERIES",
+                "SYS.NODE_ATTRIBUTES",
+                "SYS.CACHES",
+                "SYS.TABLES"
+            ))
+        );
+    }
 
-            while(rs.next()) {
+    /**
+     * @throws Exception If failed.
+     */
+    private void testGetTables(String[] tblTypes, Set<String> expTbls) throws Exception {
+        try (Connection conn = DriverManager.getConnection(URL)) {
+            DatabaseMetaData meta = conn.getMetaData();
+
+            ResultSet rs = meta.getTables(null, null, null, tblTypes);
+
+            Set<String> actualTbls = new HashSet<>(expTbls.size());
+
+            while (rs.next()) {
                 actualTbls.add(rs.getString("TABLE_SCHEM") + '.'
                     + rs.getString("TABLE_NAME"));
             }
 
-            assert expectedTbls.equals(actualTbls) : "expectedTbls=" + expectedTbls +
+            assert expTbls.equals(actualTbls) : "expectedTbls=" + expTbls +
                 ", actualTbls" + actualTbls;
         }
     }
@@ -335,7 +391,7 @@ public class JdbcThinMetadataSelfTest extends JdbcThinAbstractSelfTest {
             while (rs.next()) {
                 String name = rs.getString("COLUMN_NAME");
 
-                assert names.remove(name);
+                assert names.remove(name) : "Unexpected column name " + name;
 
                 if ("NAME".equals(name)) {
                     assert rs.getInt("DATA_TYPE") == VARCHAR;
@@ -429,47 +485,247 @@ public class JdbcThinMetadataSelfTest extends JdbcThinAbstractSelfTest {
 
             ResultSet rs = meta.getColumns(null, null, null, null);
 
-            Set<String> expectedCols = new HashSet<>(Arrays.asList(
-                "org.ORGANIZATION.ID.null",
-                "org.ORGANIZATION.NAME.null.42",
-                "pers.PERSON.ORGID.null",
-                "pers.PERSON.AGE.null",
-                "pers.PERSON.NAME.null",
-                "dep.DEPARTMENT.ID.null",
-                "dep.DEPARTMENT.NAME.null.43",
+            List<String> expectedCols = Arrays.asList(
+                "PUBLIC.Quoted.Id.null",
+                "PUBLIC.Quoted.Name.null.50",
                 "PUBLIC.TEST.ID.null",
                 "PUBLIC.TEST.NAME.'default name'.50",
-                "PUBLIC.TEST.VAL.null.50",
                 "PUBLIC.TEST.AGE.21",
-                "PUBLIC.Quoted.Id.null",
-                "PUBLIC.Quoted.Name.null.50",
+                "PUBLIC.TEST.VAL.null.50",
                 "PUBLIC.TEST_DECIMAL_COLUMN.ID.null",
                 "PUBLIC.TEST_DECIMAL_COLUMN.DEC_COL.null.8.3",
                 "PUBLIC.TEST_DECIMAL_COLUMN_PRECISION.ID.null",
                 "PUBLIC.TEST_DECIMAL_COLUMN_PRECISION.DEC_COL.null.8",
                 "PUBLIC.TEST_DECIMAL_DATE_COLUMN_META.ID.null",
                 "PUBLIC.TEST_DECIMAL_DATE_COLUMN_META.DEC_COL.null.8",
-                "PUBLIC.TEST_DECIMAL_DATE_COLUMN_META.DATE_COL.null"
-            ));
+                "PUBLIC.TEST_DECIMAL_DATE_COLUMN_META.DATE_COL.null",
+                "dep.DEPARTMENT.ID.null",
+                "dep.DEPARTMENT.NAME.null.43",
+                "org.ORGANIZATION.ID.null",
+                "org.ORGANIZATION.NAME.null.42",
+                "pers.PERSON.NAME.null",
+                "pers.PERSON.AGE.null",
+                "pers.PERSON.ORGID.null"
+            );
 
-            Set<String> actualCols = new HashSet<>(expectedCols.size());
+            List<String> actualUserCols = new ArrayList<>(expectedCols.size());
+
+            List<String> actualSystemCols = new ArrayList<>();
 
             while(rs.next()) {
                 int precision = rs.getInt("COLUMN_SIZE");
 
                 int scale = rs.getInt("DECIMAL_DIGITS");
 
-                actualCols.add(rs.getString("TABLE_SCHEM") + '.'
+                String schemaName = rs.getString("TABLE_SCHEM");
+
+                String colDefinition = schemaName + '.'
                     + rs.getString("TABLE_NAME") + "."
                     + rs.getString("COLUMN_NAME") + "."
                     + rs.getString("COLUMN_DEF")
                     + (precision == 0 ? "" : ("." + precision))
-                    + (scale == 0 ? "" : ("." + scale))
-                );
+                    + (scale == 0 ? "" : ("." + scale));
+
+                if (!schemaName.equals(QueryUtils.SCHEMA_SYS))
+                    actualUserCols.add(colDefinition);
+                else
+                    actualSystemCols.add(colDefinition);
             }
 
-            assert expectedCols.equals(actualCols) : "expectedCols=" + expectedCols +
-                ", actualCols" + actualCols;
+            Assert.assertEquals(expectedCols, actualUserCols);
+
+            expectedCols = Arrays.asList(
+                "SYS.BASELINE_NODES.CONSISTENT_ID.null.2147483647",
+                "SYS.BASELINE_NODES.ONLINE.null.1",
+                "SYS.CACHES.CACHE_GROUP_ID.null.10",
+                "SYS.CACHES.CACHE_GROUP_NAME.null.2147483647",
+                "SYS.CACHES.CACHE_ID.null.10",
+                "SYS.CACHES.CACHE_NAME.null.2147483647",
+                "SYS.CACHES.CACHE_TYPE.null.2147483647",
+                "SYS.CACHES.CACHE_MODE.null.2147483647",
+                "SYS.CACHES.ATOMICITY_MODE.null.2147483647",
+                "SYS.CACHES.IS_ONHEAP_CACHE_ENABLED.null.1",
+                "SYS.CACHES.IS_COPY_ON_READ.null.1",
+                "SYS.CACHES.IS_LOAD_PREVIOUS_VALUE.null.1",
+                "SYS.CACHES.IS_READ_FROM_BACKUP.null.1",
+                "SYS.CACHES.PARTITION_LOSS_POLICY.null.2147483647",
+                "SYS.CACHES.NODE_FILTER.null.2147483647",
+                "SYS.CACHES.TOPOLOGY_VALIDATOR.null.2147483647",
+                "SYS.CACHES.IS_EAGER_TTL.null.1",
+                "SYS.CACHES.WRITE_SYNCHRONIZATION_MODE.null.2147483647",
+                "SYS.CACHES.IS_INVALIDATE.null.1",
+                "SYS.CACHES.IS_EVENTS_DISABLED.null.1",
+                "SYS.CACHES.IS_STATISTICS_ENABLED.null.1",
+                "SYS.CACHES.IS_MANAGEMENT_ENABLED.null.1",
+                "SYS.CACHES.BACKUPS.null.10",
+                "SYS.CACHES.AFFINITY.null.2147483647",
+                "SYS.CACHES.AFFINITY_MAPPER.null.2147483647",
+                "SYS.CACHES.REBALANCE_MODE.null.2147483647",
+                "SYS.CACHES.REBALANCE_BATCH_SIZE.null.10",
+                "SYS.CACHES.REBALANCE_TIMEOUT.null.19",
+                "SYS.CACHES.REBALANCE_DELAY.null.19",
+                "SYS.CACHES.REBALANCE_THROTTLE.null.19",
+                "SYS.CACHES.REBALANCE_BATCHES_PREFETCH_COUNT.null.19",
+                "SYS.CACHES.REBALANCE_ORDER.null.10",
+                "SYS.CACHES.EVICTION_FILTER.null.2147483647",
+                "SYS.CACHES.EVICTION_POLICY_FACTORY.null.2147483647",
+                "SYS.CACHES.IS_NEAR_CACHE_ENABLED.null.1",
+                "SYS.CACHES.NEAR_CACHE_EVICTION_POLICY_FACTORY.null.2147483647",
+                "SYS.CACHES.NEAR_CACHE_START_SIZE.null.10",
+                "SYS.CACHES.DEFAULT_LOCK_TIMEOUT.null.19",
+                "SYS.CACHES.CACHE_INTERCEPTOR.null.2147483647",
+                "SYS.CACHES.CACHE_STORE_FACTORY.null.2147483647",
+                "SYS.CACHES.IS_STORE_KEEP_BINARY.null.1",
+                "SYS.CACHES.IS_READ_THROUGH.null.1",
+                "SYS.CACHES.IS_WRITE_THROUGH.null.1",
+                "SYS.CACHES.IS_WRITE_BEHIND_ENABLED.null.1",
+                "SYS.CACHES.WRITE_BEHIND_COALESCING.null.1",
+                "SYS.CACHES.WRITE_BEHIND_FLUSH_SIZE.null.10",
+                "SYS.CACHES.WRITE_BEHIND_FLUSH_FREQUENCY.null.19",
+                "SYS.CACHES.WRITE_BEHIND_FLUSH_THREAD_COUNT.null.10",
+                "SYS.CACHES.WRITE_BEHIND_FLUSH_BATCH_SIZE.null.10",
+                "SYS.CACHES.MAX_CONCURRENT_ASYNC_OPERATIONS.null.10",
+                "SYS.CACHES.CACHE_LOADER_FACTORY.null.2147483647",
+                "SYS.CACHES.CACHE_WRITER_FACTORY.null.2147483647",
+                "SYS.CACHES.EXPIRY_POLICY_FACTORY.null.2147483647",
+                "SYS.CACHES.IS_SQL_ESCAPE_ALL.null.1",
+                "SYS.CACHES.SQL_SCHEMA.null.2147483647",
+                "SYS.CACHES.SQL_INDEX_MAX_INLINE_SIZE.null.10",
+                "SYS.CACHES.IS_SQL_ONHEAP_CACHE_ENABLED.null.1",
+                "SYS.CACHES.SQL_ONHEAP_CACHE_MAX_SIZE.null.10",
+                "SYS.CACHES.QUERY_DETAILS_METRICS_SIZE.null.10",
+                "SYS.CACHES.QUERY_PARALLELISM.null.10",
+                "SYS.CACHES.MAX_QUERY_ITERATORS_COUNT.null.10",
+                "SYS.CACHES.DATA_REGION_NAME.null.2147483647",
+                "SYS.CACHE_GROUPS.CACHE_GROUP_ID.null.10",
+                "SYS.CACHE_GROUPS.CACHE_GROUP_NAME.null.2147483647",
+                "SYS.CACHE_GROUPS.IS_SHARED.null.1",
+                "SYS.CACHE_GROUPS.CACHE_COUNT.null.10",
+                "SYS.CACHE_GROUPS.CACHE_MODE.null.2147483647",
+                "SYS.CACHE_GROUPS.ATOMICITY_MODE.null.2147483647",
+                "SYS.CACHE_GROUPS.AFFINITY.null.2147483647",
+                "SYS.CACHE_GROUPS.PARTITIONS_COUNT.null.10",
+                "SYS.CACHE_GROUPS.NODE_FILTER.null.2147483647",
+                "SYS.CACHE_GROUPS.DATA_REGION_NAME.null.2147483647",
+                "SYS.CACHE_GROUPS.TOPOLOGY_VALIDATOR.null.2147483647",
+                "SYS.CACHE_GROUPS.PARTITION_LOSS_POLICY.null.2147483647",
+                "SYS.CACHE_GROUPS.REBALANCE_MODE.null.2147483647",
+                "SYS.CACHE_GROUPS.REBALANCE_DELAY.null.19",
+                "SYS.CACHE_GROUPS.REBALANCE_ORDER.null.10",
+                "SYS.CACHE_GROUPS.BACKUPS.null.10",
+                "SYS.INDEXES.CACHE_GROUP_ID.null.10",
+                "SYS.INDEXES.CACHE_GROUP_NAME.null.2147483647",
+                "SYS.INDEXES.CACHE_ID.null.10",
+                "SYS.INDEXES.CACHE_NAME.null.2147483647",
+                "SYS.INDEXES.SCHEMA_NAME.null.2147483647",
+                "SYS.INDEXES.TABLE_NAME.null.2147483647",
+                "SYS.INDEXES.INDEX_NAME.null.2147483647",
+                "SYS.INDEXES.INDEX_TYPE.null.2147483647",
+                "SYS.INDEXES.COLUMNS.null.2147483647",
+                "SYS.INDEXES.IS_PK.null.1",
+                "SYS.INDEXES.IS_UNIQUE.null.1",
+                "SYS.INDEXES.INLINE_SIZE.null.10",
+                "SYS.LOCAL_CACHE_GROUPS_IO.CACHE_GROUP_ID.null.10",
+                "SYS.LOCAL_CACHE_GROUPS_IO.CACHE_GROUP_NAME.null.2147483647",
+                "SYS.LOCAL_CACHE_GROUPS_IO.PHYSICAL_READS.null.19",
+                "SYS.LOCAL_CACHE_GROUPS_IO.LOGICAL_READS.null.19",
+                "SYS.LOCAL_SQL_QUERY_HISTORY.SCHEMA_NAME.null.2147483647",
+                "SYS.LOCAL_SQL_QUERY_HISTORY.SQL.null.2147483647",
+                "SYS.LOCAL_SQL_QUERY_HISTORY.LOCAL.null.1",
+                "SYS.LOCAL_SQL_QUERY_HISTORY.EXECUTIONS.null.19",
+                "SYS.LOCAL_SQL_QUERY_HISTORY.FAILURES.null.19",
+                "SYS.LOCAL_SQL_QUERY_HISTORY.DURATION_MIN.null.19",
+                "SYS.LOCAL_SQL_QUERY_HISTORY.DURATION_MAX.null.19",
+                "SYS.LOCAL_SQL_QUERY_HISTORY.LAST_START_TIME.null.26.6",
+                "SYS.LOCAL_SQL_RUNNING_QUERIES.QUERY_ID.null.2147483647",
+                "SYS.LOCAL_SQL_RUNNING_QUERIES.SQL.null.2147483647",
+                "SYS.LOCAL_SQL_RUNNING_QUERIES.SCHEMA_NAME.null.2147483647",
+                "SYS.LOCAL_SQL_RUNNING_QUERIES.LOCAL.null.1",
+                "SYS.LOCAL_SQL_RUNNING_QUERIES.START_TIME.null.26.6",
+                "SYS.LOCAL_SQL_RUNNING_QUERIES.DURATION.null.19",
+                "SYS.NODES.NODE_ID.null.2147483647",
+                "SYS.NODES.CONSISTENT_ID.null.2147483647",
+                "SYS.NODES.VERSION.null.2147483647",
+                "SYS.NODES.IS_CLIENT.null.1",
+                "SYS.NODES.IS_DAEMON.null.1",
+                "SYS.NODES.NODE_ORDER.null.10",
+                "SYS.NODES.ADDRESSES.null.2147483647",
+                "SYS.NODES.HOSTNAMES.null.2147483647",
+                "SYS.NODE_ATTRIBUTES.NODE_ID.null.2147483647",
+                "SYS.NODE_ATTRIBUTES.NAME.null.2147483647",
+                "SYS.NODE_ATTRIBUTES.VALUE.null.2147483647",
+                "SYS.NODE_METRICS.NODE_ID.null.2147483647",
+                "SYS.NODE_METRICS.LAST_UPDATE_TIME.null.26.6",
+                "SYS.NODE_METRICS.MAX_ACTIVE_JOBS.null.10",
+                "SYS.NODE_METRICS.CUR_ACTIVE_JOBS.null.10",
+                "SYS.NODE_METRICS.AVG_ACTIVE_JOBS.null.7",
+                "SYS.NODE_METRICS.MAX_WAITING_JOBS.null.10",
+                "SYS.NODE_METRICS.CUR_WAITING_JOBS.null.10",
+                "SYS.NODE_METRICS.AVG_WAITING_JOBS.null.7",
+                "SYS.NODE_METRICS.MAX_REJECTED_JOBS.null.10",
+                "SYS.NODE_METRICS.CUR_REJECTED_JOBS.null.10",
+                "SYS.NODE_METRICS.AVG_REJECTED_JOBS.null.7",
+                "SYS.NODE_METRICS.TOTAL_REJECTED_JOBS.null.10",
+                "SYS.NODE_METRICS.MAX_CANCELED_JOBS.null.10",
+                "SYS.NODE_METRICS.CUR_CANCELED_JOBS.null.10",
+                "SYS.NODE_METRICS.AVG_CANCELED_JOBS.null.7",
+                "SYS.NODE_METRICS.TOTAL_CANCELED_JOBS.null.10",
+                "SYS.NODE_METRICS.MAX_JOBS_WAIT_TIME.null.19",
+                "SYS.NODE_METRICS.CUR_JOBS_WAIT_TIME.null.19",
+                "SYS.NODE_METRICS.AVG_JOBS_WAIT_TIME.null.19",
+                "SYS.NODE_METRICS.MAX_JOBS_EXECUTE_TIME.null.19",
+                "SYS.NODE_METRICS.CUR_JOBS_EXECUTE_TIME.null.19",
+                "SYS.NODE_METRICS.AVG_JOBS_EXECUTE_TIME.null.19",
+                "SYS.NODE_METRICS.TOTAL_JOBS_EXECUTE_TIME.null.19",
+                "SYS.NODE_METRICS.TOTAL_EXECUTED_JOBS.null.10",
+                "SYS.NODE_METRICS.TOTAL_EXECUTED_TASKS.null.10",
+                "SYS.NODE_METRICS.TOTAL_BUSY_TIME.null.19",
+                "SYS.NODE_METRICS.TOTAL_IDLE_TIME.null.19",
+                "SYS.NODE_METRICS.CUR_IDLE_TIME.null.19",
+                "SYS.NODE_METRICS.BUSY_TIME_PERCENTAGE.null.7",
+                "SYS.NODE_METRICS.IDLE_TIME_PERCENTAGE.null.7",
+                "SYS.NODE_METRICS.TOTAL_CPU.null.10",
+                "SYS.NODE_METRICS.CUR_CPU_LOAD.null.17",
+                "SYS.NODE_METRICS.AVG_CPU_LOAD.null.17",
+                "SYS.NODE_METRICS.CUR_GC_CPU_LOAD.null.17",
+                "SYS.NODE_METRICS.HEAP_MEMORY_INIT.null.19",
+                "SYS.NODE_METRICS.HEAP_MEMORY_USED.null.19",
+                "SYS.NODE_METRICS.HEAP_MEMORY_COMMITED.null.19",
+                "SYS.NODE_METRICS.HEAP_MEMORY_MAX.null.19",
+                "SYS.NODE_METRICS.HEAP_MEMORY_TOTAL.null.19",
+                "SYS.NODE_METRICS.NONHEAP_MEMORY_INIT.null.19",
+                "SYS.NODE_METRICS.NONHEAP_MEMORY_USED.null.19",
+                "SYS.NODE_METRICS.NONHEAP_MEMORY_COMMITED.null.19",
+                "SYS.NODE_METRICS.NONHEAP_MEMORY_MAX.null.19",
+                "SYS.NODE_METRICS.NONHEAP_MEMORY_TOTAL.null.19",
+                "SYS.NODE_METRICS.UPTIME.null.19",
+                "SYS.NODE_METRICS.JVM_START_TIME.null.26.6",
+                "SYS.NODE_METRICS.NODE_START_TIME.null.26.6",
+                "SYS.NODE_METRICS.LAST_DATA_VERSION.null.19",
+                "SYS.NODE_METRICS.CUR_THREAD_COUNT.null.10",
+                "SYS.NODE_METRICS.MAX_THREAD_COUNT.null.10",
+                "SYS.NODE_METRICS.TOTAL_THREAD_COUNT.null.19",
+                "SYS.NODE_METRICS.CUR_DAEMON_THREAD_COUNT.null.10",
+                "SYS.NODE_METRICS.SENT_MESSAGES_COUNT.null.10",
+                "SYS.NODE_METRICS.SENT_BYTES_COUNT.null.19",
+                "SYS.NODE_METRICS.RECEIVED_MESSAGES_COUNT.null.10",
+                "SYS.NODE_METRICS.RECEIVED_BYTES_COUNT.null.19",
+                "SYS.NODE_METRICS.OUTBOUND_MESSAGES_QUEUE.null.10",
+                "SYS.SCHEMAS.SCHEMA_NAME.null.2147483647",
+                "SYS.TABLES.CACHE_GROUP_ID.null.10",
+                "SYS.TABLES.CACHE_GROUP_NAME.null.2147483647",
+                "SYS.TABLES.CACHE_ID.null.10",
+                "SYS.TABLES.CACHE_NAME.null.2147483647",
+                "SYS.TABLES.SCHEMA_NAME.null.2147483647",
+                "SYS.TABLES.TABLE_NAME.null.2147483647",
+                "SYS.TABLES.AFFINITY_KEY_COLUMN.null.2147483647",
+                "SYS.TABLES.KEY_ALIAS.null.2147483647",
+                "SYS.TABLES.VALUE_ALIAS.null.2147483647",
+                "SYS.TABLES.KEY_TYPE_NAME.null.2147483647",
+                "SYS.TABLES.VALUE_TYPE_NAME.null.2147483647"
+            );
+            Assert.assertEquals(expectedCols, actualSystemCols);
+
         }
     }
 
diff --git a/modules/core/src/main/java/org/apache/ignite/internal/jdbc/thin/JdbcThinDatabaseMetadata.java b/modules/core/src/main/java/org/apache/ignite/internal/jdbc/thin/JdbcThinDatabaseMetadata.java
index 71c5fd3..35b2c14 100644
--- a/modules/core/src/main/java/org/apache/ignite/internal/jdbc/thin/JdbcThinDatabaseMetadata.java
+++ b/modules/core/src/main/java/org/apache/ignite/internal/jdbc/thin/JdbcThinDatabaseMetadata.java
@@ -51,7 +51,11 @@ 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.jdbc2.JdbcUtils.CATALOG_NAME;
+import static org.apache.ignite.internal.jdbc2.JdbcUtils.TYPE_TABLE;
+import static org.apache.ignite.internal.jdbc2.JdbcUtils.TYPE_VIEW;
 import static org.apache.ignite.internal.jdbc2.JdbcUtils.columnRow;
 import static org.apache.ignite.internal.jdbc2.JdbcUtils.indexRows;
 import static org.apache.ignite.internal.jdbc2.JdbcUtils.primaryKeyRows;
@@ -673,7 +677,7 @@ public class JdbcThinDatabaseMetadata implements DatabaseMetaData {
     /** {@inheritDoc} */
     @Override public ResultSet getProcedures(String catalog, String schemaPtrn,
         String procedureNamePtrn) throws SQLException {
-        return new JdbcThinResultSet(Collections.<List<Object>>emptyList(), Arrays.asList(
+        return new JdbcThinResultSet(Collections.<List<Object>>emptyList(), asList(
             new JdbcColumnMeta(null, null, "PROCEDURE_CAT", String.class),
             new JdbcColumnMeta(null, null, "PROCEDURE_SCHEM", String.class),
             new JdbcColumnMeta(null, null, "PROCEDURE_NAME", String.class),
@@ -686,7 +690,7 @@ public class JdbcThinDatabaseMetadata implements DatabaseMetaData {
     /** {@inheritDoc} */
     @Override public ResultSet getProcedureColumns(String catalog, String schemaPtrn, String procedureNamePtrn,
         String colNamePtrn) throws SQLException {
-        return new JdbcThinResultSet(Collections.<List<Object>>emptyList(), Arrays.asList(
+        return new JdbcThinResultSet(Collections.<List<Object>>emptyList(), asList(
             new JdbcColumnMeta(null, null, "PROCEDURE_CAT", String.class),
             new JdbcColumnMeta(null, null, "PROCEDURE_SCHEM", String.class),
             new JdbcColumnMeta(null, null, "PROCEDURE_NAME", String.class),
@@ -715,7 +719,7 @@ public class JdbcThinDatabaseMetadata implements DatabaseMetaData {
         throws SQLException {
         conn.ensureNotClosed();
 
-        final List<JdbcColumnMeta> meta = Arrays.asList(
+        final List<JdbcColumnMeta> meta = asList(
             new JdbcColumnMeta(null, null, "TABLE_CAT", String.class),
             new JdbcColumnMeta(null, null, "TABLE_SCHEM", String.class),
             new JdbcColumnMeta(null, null, "TABLE_NAME", String.class),
@@ -733,7 +737,7 @@ public class JdbcThinDatabaseMetadata implements DatabaseMetaData {
             tblTypeMatch = true;
         else {
             for (String type : tblTypes) {
-                if ("TABLE".equals(type)) {
+                if (TYPE_TABLE.equals(type) || TYPE_VIEW.equals(type)) {
                     tblTypeMatch = true;
 
                     break;
@@ -744,8 +748,8 @@ public class JdbcThinDatabaseMetadata implements DatabaseMetaData {
         if (!isValidCatalog(catalog) || !tblTypeMatch)
             return new JdbcThinResultSet(Collections.<List<Object>>emptyList(), meta);
 
-        JdbcMetaTablesResult res = conn.sendRequest(new JdbcMetaTablesRequest(schemaPtrn, tblNamePtrn)).
-            response();
+        JdbcMetaTablesResult res = conn.sendRequest(new JdbcMetaTablesRequest(schemaPtrn, tblNamePtrn, tblTypes))
+            .response();
 
         List<List<Object>> rows = new LinkedList<>();
 
@@ -763,15 +767,16 @@ public class JdbcThinDatabaseMetadata implements DatabaseMetaData {
     /** {@inheritDoc} */
     @SuppressWarnings("ArraysAsListWithZeroOrOneArgument")
     @Override public ResultSet getCatalogs() throws SQLException {
-        return new JdbcThinResultSet(Collections.singletonList(Collections.singletonList(CATALOG_NAME)),
-            Arrays.asList(new JdbcColumnMeta(null, null, "TABLE_CAT", String.class)));
+        return new JdbcThinResultSet(singletonList(singletonList(CATALOG_NAME)),
+            asList(new JdbcColumnMeta(null, null, "TABLE_CAT", String.class)));
     }
 
     /** {@inheritDoc} */
     @SuppressWarnings("ArraysAsListWithZeroOrOneArgument")
     @Override public ResultSet getTableTypes() throws SQLException {
-        return new JdbcThinResultSet(Collections.singletonList(Collections.<Object>singletonList("TABLE")),
-            Arrays.asList(new JdbcColumnMeta(null, null, "TABLE_TYPE", String.class)));
+        return new JdbcThinResultSet(
+            asList(singletonList(TYPE_TABLE), singletonList(TYPE_VIEW) ),
+            asList(new JdbcColumnMeta(null, null, "TABLE_TYPE", String.class)));
     }
 
     /** {@inheritDoc} */
@@ -779,7 +784,7 @@ public class JdbcThinDatabaseMetadata implements DatabaseMetaData {
         throws SQLException {
         conn.ensureNotClosed();
 
-        final List<JdbcColumnMeta> meta = Arrays.asList(
+        final List<JdbcColumnMeta> meta = asList(
             new JdbcColumnMeta(null, null, "TABLE_CAT", String.class),      // 1
             new JdbcColumnMeta(null, null, "TABLE_SCHEM", String.class),    // 2
             new JdbcColumnMeta(null, null, "TABLE_NAME", String.class),     // 3
@@ -807,7 +812,7 @@ public class JdbcThinDatabaseMetadata implements DatabaseMetaData {
         );
 
         if (!isValidCatalog(catalog))
-            return new JdbcThinResultSet(Collections.<List<Object>>emptyList(), meta);
+            return new JdbcThinResultSet(Collections.emptyList(), meta);
 
         JdbcMetaColumnsResult res = conn.sendRequest(new JdbcMetaColumnsRequest(schemaPtrn, tblNamePtrn, colNamePtrn)).response();
 
@@ -822,7 +827,7 @@ public class JdbcThinDatabaseMetadata implements DatabaseMetaData {
     /** {@inheritDoc} */
     @Override public ResultSet getColumnPrivileges(String catalog, String schema, String tbl,
         String colNamePtrn) throws SQLException {
-        return new JdbcThinResultSet(Collections.<List<Object>>emptyList(), Arrays.asList(
+        return new JdbcThinResultSet(Collections.<List<Object>>emptyList(), asList(
             new JdbcColumnMeta(null, null, "TABLE_CAT", String.class),
             new JdbcColumnMeta(null, null, "TABLE_SCHEM", String.class),
             new JdbcColumnMeta(null, null, "TABLE_NAME", String.class),
@@ -837,7 +842,7 @@ public class JdbcThinDatabaseMetadata implements DatabaseMetaData {
     /** {@inheritDoc} */
     @Override public ResultSet getTablePrivileges(String catalog, String schemaPtrn,
         String tblNamePtrn) throws SQLException {
-        return new JdbcThinResultSet(Collections.<List<Object>>emptyList(), Arrays.asList(
+        return new JdbcThinResultSet(Collections.<List<Object>>emptyList(), asList(
             new JdbcColumnMeta(null, null, "TABLE_CAT", String.class),
             new JdbcColumnMeta(null, null, "TABLE_SCHEM", String.class),
             new JdbcColumnMeta(null, null, "TABLE_NAME", String.class),
@@ -851,7 +856,7 @@ public class JdbcThinDatabaseMetadata implements DatabaseMetaData {
     /** {@inheritDoc} */
     @Override public ResultSet getBestRowIdentifier(String catalog, String schema, String tbl, int scope,
         boolean nullable) throws SQLException {
-        return new JdbcThinResultSet(Collections.<List<Object>>emptyList(), Arrays.asList(
+        return new JdbcThinResultSet(Collections.<List<Object>>emptyList(), asList(
             new JdbcColumnMeta(null, null, "SCOPE", Short.class),
             new JdbcColumnMeta(null, null, "COLUMN_NAME", String.class),
             new JdbcColumnMeta(null, null, "DATA_TYPE", Integer.class),
@@ -865,7 +870,7 @@ public class JdbcThinDatabaseMetadata implements DatabaseMetaData {
 
     /** {@inheritDoc} */
     @Override public ResultSet getVersionColumns(String catalog, String schema, String tbl) throws SQLException {
-        return new JdbcThinResultSet(Collections.<List<Object>>emptyList(), Arrays.asList(
+        return new JdbcThinResultSet(Collections.<List<Object>>emptyList(), asList(
             new JdbcColumnMeta(null, null, "SCOPE", Short.class),
             new JdbcColumnMeta(null, null, "COLUMN_NAME", String.class),
             new JdbcColumnMeta(null, null, "DATA_TYPE", Integer.class),
@@ -881,7 +886,7 @@ public class JdbcThinDatabaseMetadata implements DatabaseMetaData {
     @Override public ResultSet getPrimaryKeys(String catalog, String schema, String tbl) throws SQLException {
         conn.ensureNotClosed();
 
-        final List<JdbcColumnMeta> meta = Arrays.asList(
+        final List<JdbcColumnMeta> meta = asList(
             new JdbcColumnMeta(null, null, "TABLE_CAT", String.class),
             new JdbcColumnMeta(null, null, "TABLE_SCHEM", String.class),
             new JdbcColumnMeta(null, null, "TABLE_NAME", String.class),
@@ -905,7 +910,7 @@ public class JdbcThinDatabaseMetadata implements DatabaseMetaData {
 
     /** {@inheritDoc} */
     @Override public ResultSet getImportedKeys(String catalog, String schema, String tbl) throws SQLException {
-        return new JdbcThinResultSet(Collections.<List<Object>>emptyList(), Arrays.asList(
+        return new JdbcThinResultSet(Collections.<List<Object>>emptyList(), asList(
             new JdbcColumnMeta(null, null, "PKTABLE_CAT", String.class),
             new JdbcColumnMeta(null, null, "PKTABLE_SCHEM", String.class),
             new JdbcColumnMeta(null, null, "PKTABLE_NAME", String.class),
@@ -925,7 +930,7 @@ public class JdbcThinDatabaseMetadata implements DatabaseMetaData {
 
     /** {@inheritDoc} */
     @Override public ResultSet getExportedKeys(String catalog, String schema, String tbl) throws SQLException {
-        return new JdbcThinResultSet(Collections.<List<Object>>emptyList(), Arrays.asList(
+        return new JdbcThinResultSet(Collections.<List<Object>>emptyList(), asList(
             new JdbcColumnMeta(null, null, "PKTABLE_CAT", String.class),
             new JdbcColumnMeta(null, null, "PKTABLE_SCHEM", String.class),
             new JdbcColumnMeta(null, null, "PKTABLE_NAME", String.class),
@@ -946,7 +951,7 @@ public class JdbcThinDatabaseMetadata implements DatabaseMetaData {
     /** {@inheritDoc} */
     @Override public ResultSet getCrossReference(String parentCatalog, String parentSchema, String parentTbl,
         String foreignCatalog, String foreignSchema, String foreignTbl) throws SQLException {
-        return new JdbcThinResultSet(Collections.<List<Object>>emptyList(), Arrays.asList(
+        return new JdbcThinResultSet(Collections.<List<Object>>emptyList(), asList(
             new JdbcColumnMeta(null, null, "PKTABLE_CAT", String.class),
             new JdbcColumnMeta(null, null, "PKTABLE_SCHEM", String.class),
             new JdbcColumnMeta(null, null, "PKTABLE_NAME", String.class),
@@ -1052,7 +1057,7 @@ public class JdbcThinDatabaseMetadata implements DatabaseMetaData {
             (short)typeNullable, false, (short)typeSearchable, false, false, false, "ARRAY", 0, 0,
             Types.ARRAY, 0, null));
 
-        return new JdbcThinResultSet(types, Arrays.asList(
+        return new JdbcThinResultSet(types, asList(
             new JdbcColumnMeta(null, null, "TYPE_NAME", String.class),
             new JdbcColumnMeta(null, null, "DATA_TYPE", Integer.class),
             new JdbcColumnMeta(null, null, "PRECISION", Integer.class),
@@ -1079,7 +1084,7 @@ public class JdbcThinDatabaseMetadata implements DatabaseMetaData {
         boolean approximate) throws SQLException {
         conn.ensureNotClosed();
 
-        final List<JdbcColumnMeta> meta = Arrays.asList(
+        final List<JdbcColumnMeta> meta = asList(
             new JdbcColumnMeta(null, null, "TABLE_CAT", String.class),
             new JdbcColumnMeta(null, null, "TABLE_SCHEM", String.class),
             new JdbcColumnMeta(null, null, "TABLE_NAME", String.class),
@@ -1170,7 +1175,7 @@ public class JdbcThinDatabaseMetadata implements DatabaseMetaData {
     /** {@inheritDoc} */
     @Override public ResultSet getUDTs(String catalog, String schemaPtrn, String typeNamePtrn,
         int[] types) throws SQLException {
-        return new JdbcThinResultSet(Collections.<List<Object>>emptyList(), Arrays.asList(
+        return new JdbcThinResultSet(Collections.<List<Object>>emptyList(), asList(
             new JdbcColumnMeta(null, null, "TYPE_CAT", String.class),
             new JdbcColumnMeta(null, null, "TYPE_SCHEM", String.class),
             new JdbcColumnMeta(null, null, "TYPE_NAME", String.class),
@@ -1209,7 +1214,7 @@ public class JdbcThinDatabaseMetadata implements DatabaseMetaData {
     /** {@inheritDoc} */
     @Override public ResultSet getSuperTypes(String catalog, String schemaPtrn,
         String typeNamePtrn) throws SQLException {
-        return new JdbcThinResultSet(Collections.<List<Object>>emptyList(), Arrays.asList(
+        return new JdbcThinResultSet(Collections.<List<Object>>emptyList(), asList(
             new JdbcColumnMeta(null, null, "TYPE_CAT", String.class),
             new JdbcColumnMeta(null, null, "TYPE_SCHEM", String.class),
             new JdbcColumnMeta(null, null, "TYPE_NAME", String.class),
@@ -1222,7 +1227,7 @@ public class JdbcThinDatabaseMetadata implements DatabaseMetaData {
     /** {@inheritDoc} */
     @Override public ResultSet getSuperTables(String catalog, String schemaPtrn,
         String tblNamePtrn) throws SQLException {
-        return new JdbcThinResultSet(Collections.<List<Object>>emptyList(), Arrays.asList(
+        return new JdbcThinResultSet(Collections.<List<Object>>emptyList(), asList(
             new JdbcColumnMeta(null, null, "TABLE_CAT", String.class),
             new JdbcColumnMeta(null, null, "TABLE_SCHEM", String.class),
             new JdbcColumnMeta(null, null, "TABLE_NAME", String.class),
@@ -1233,7 +1238,7 @@ public class JdbcThinDatabaseMetadata implements DatabaseMetaData {
     /** {@inheritDoc} */
     @Override public ResultSet getAttributes(String catalog, String schemaPtrn, String typeNamePtrn,
         String attributeNamePtrn) throws SQLException {
-        return new JdbcThinResultSet(Collections.<List<Object>>emptyList(), Arrays.asList(
+        return new JdbcThinResultSet(Collections.<List<Object>>emptyList(), asList(
             new JdbcColumnMeta(null, null, "TYPE_CAT", String.class),
             new JdbcColumnMeta(null, null, "TYPE_SCHEM", String.class),
             new JdbcColumnMeta(null, null, "TYPE_NAME", String.class),
@@ -1312,7 +1317,7 @@ public class JdbcThinDatabaseMetadata implements DatabaseMetaData {
     @Override public ResultSet getSchemas(String catalog, String schemaPtrn) throws SQLException {
         conn.ensureNotClosed();
 
-        final List<JdbcColumnMeta> meta = Arrays.asList(
+        final List<JdbcColumnMeta> meta = asList(
             new JdbcColumnMeta(null, null, "TABLE_SCHEM", String.class),
             new JdbcColumnMeta(null, null, "TABLE_CATALOG", String.class)
         );
@@ -1348,7 +1353,7 @@ public class JdbcThinDatabaseMetadata implements DatabaseMetaData {
 
     /** {@inheritDoc} */
     @Override public ResultSet getClientInfoProperties() throws SQLException {
-        return new JdbcThinResultSet(Collections.<List<Object>>emptyList(), Arrays.asList(
+        return new JdbcThinResultSet(Collections.<List<Object>>emptyList(), asList(
             new JdbcColumnMeta(null, null, "NAME", String.class),
             new JdbcColumnMeta(null, null, "MAX_LEN", Integer.class),
             new JdbcColumnMeta(null, null, "DEFAULT_VALUE", String.class),
@@ -1360,7 +1365,7 @@ public class JdbcThinDatabaseMetadata implements DatabaseMetaData {
     @Override public ResultSet getFunctions(String catalog, String schemaPtrn,
         String functionNamePtrn) throws SQLException {
         // TODO: IGNITE-6028
-        return new JdbcThinResultSet(Collections.<List<Object>>emptyList(), Arrays.asList(
+        return new JdbcThinResultSet(Collections.<List<Object>>emptyList(), asList(
             new JdbcColumnMeta(null, null, "FUNCTION_CAT", String.class),
             new JdbcColumnMeta(null, null, "FUNCTION_SCHEM", String.class),
             new JdbcColumnMeta(null, null, "FUNCTION_NAME", String.class),
@@ -1374,7 +1379,7 @@ public class JdbcThinDatabaseMetadata implements DatabaseMetaData {
     @Override public ResultSet getFunctionColumns(String catalog, String schemaPtrn, String functionNamePtrn,
         String colNamePtrn) throws SQLException {
         // TODO: IGNITE-6028
-        return new JdbcThinResultSet(Collections.<List<Object>>emptyList(), Arrays.asList(
+        return new JdbcThinResultSet(Collections.<List<Object>>emptyList(), asList(
             new JdbcColumnMeta(null, null, "FUNCTION_CAT", String.class),
             new JdbcColumnMeta(null, null, "FUNCTION_SCHEM", String.class),
             new JdbcColumnMeta(null, null, "FUNCTION_NAME", String.class),
@@ -1411,7 +1416,7 @@ public class JdbcThinDatabaseMetadata implements DatabaseMetaData {
     /** {@inheritDoc} */
     @Override public ResultSet getPseudoColumns(String catalog, String schemaPtrn, String tblNamePtrn,
         String colNamePtrn) throws SQLException {
-        return new JdbcThinResultSet(Collections.<List<Object>>emptyList(), Arrays.asList(
+        return new JdbcThinResultSet(Collections.<List<Object>>emptyList(), asList(
             new JdbcColumnMeta(null, null, "TABLE_CAT", String.class),
             new JdbcColumnMeta(null, null, "TABLE_SCHEM", String.class),
             new JdbcColumnMeta(null, null, "TABLE_NAME", String.class),
diff --git a/modules/core/src/main/java/org/apache/ignite/internal/jdbc2/JdbcDatabaseMetadata.java b/modules/core/src/main/java/org/apache/ignite/internal/jdbc2/JdbcDatabaseMetadata.java
index cc58780..a2604a0 100644
--- a/modules/core/src/main/java/org/apache/ignite/internal/jdbc2/JdbcDatabaseMetadata.java
+++ b/modules/core/src/main/java/org/apache/ignite/internal/jdbc2/JdbcDatabaseMetadata.java
@@ -46,7 +46,11 @@ import static java.sql.Connection.TRANSACTION_NONE;
 import static java.sql.ResultSet.CONCUR_READ_ONLY;
 import static java.sql.ResultSet.HOLD_CURSORS_OVER_COMMIT;
 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.jdbc2.JdbcUtils.CATALOG_NAME;
+import static org.apache.ignite.internal.jdbc2.JdbcUtils.TYPE_TABLE;
+import static org.apache.ignite.internal.jdbc2.JdbcUtils.TYPE_VIEW;
 import static org.apache.ignite.internal.jdbc2.JdbcUtils.columnRow;
 import static org.apache.ignite.internal.jdbc2.JdbcUtils.indexRows;
 import static org.apache.ignite.internal.jdbc2.JdbcUtils.primaryKeyRows;
@@ -679,9 +683,9 @@ public class JdbcDatabaseMetadata implements DatabaseMetaData {
         return new JdbcResultSet(true, null,
             conn.createStatement0(),
             Collections.<String>emptyList(),
-            Arrays.asList("PROCEDURE_CAT", "PROCEDURE_SCHEM", "PROCEDURE_NAME",
+            asList("PROCEDURE_CAT", "PROCEDURE_SCHEM", "PROCEDURE_NAME",
                 "REMARKS", "PROCEDURE_TYPE", "SPECIFIC_NAME"),
-            Arrays.asList(String.class.getName(), String.class.getName(), String.class.getName(),
+            asList(String.class.getName(), String.class.getName(), String.class.getName(),
                 String.class.getName(), Short.class.getName(), String.class.getName()),
             Collections.<List<?>>emptyList(), true
         );
@@ -693,12 +697,12 @@ public class JdbcDatabaseMetadata implements DatabaseMetaData {
         return new JdbcResultSet(true, null,
             conn.createStatement0(),
             Collections.<String>emptyList(),
-            Arrays.asList("PROCEDURE_CAT", "PROCEDURE_SCHEM", "PROCEDURE_NAME",
+            asList("PROCEDURE_CAT", "PROCEDURE_SCHEM", "PROCEDURE_NAME",
                 "COLUMN_NAME", "COLUMN_TYPE", "DATA_TYPE", "TYPE_NAME", "PRECISION",
                 "LENGTH", "SCALE", "RADIX", "NULLABLE", "REMARKS", "COLUMN_DEF",
                 "SQL_DATA_TYPE", "SQL_DATETIME_SUB", "CHAR_OCTET_LENGTH",
                 "ORDINAL_POSITION", "IS_NULLABLE", "SPECIFIC_NAME"),
-            Arrays.asList(String.class.getName(), String.class.getName(), String.class.getName(),
+            asList(String.class.getName(), String.class.getName(), String.class.getName(),
                 String.class.getName(), Short.class.getName(), Integer.class.getName(), String.class.getName(),
                 Integer.class.getName(), Integer.class.getName(), Short.class.getName(), Short.class.getName(),
                 Short.class.getName(), String.class.getName(), String.class.getName(), Integer.class.getName(),
@@ -715,10 +719,22 @@ public class JdbcDatabaseMetadata implements DatabaseMetaData {
 
         List<List<?>> rows = Collections.emptyList();
 
-        boolean areTypesValid = tblTypes == null || Arrays.asList(tblTypes).contains("TABLE");
+        boolean areTypesValid = false;
+
+        if(tblTypes == null)
+            areTypesValid = true;
+        else {
+            for (String type : tblTypes) {
+                if (TYPE_TABLE.equals(type) || TYPE_VIEW.equals(type)) {
+                    areTypesValid = true;
+
+                    break;
+                }
+            }
+        }
 
         if (isValidCatalog(catalog) && areTypesValid) {
-            List<JdbcTableMeta> tabMetas = meta.getTablesMeta(schemaPtrn, tblNamePtrn);
+            List<JdbcTableMeta> tabMetas = meta.getTablesMeta(schemaPtrn, tblNamePtrn, tblTypes);
 
             rows = new ArrayList<>(tabMetas.size());
 
@@ -729,9 +745,9 @@ public class JdbcDatabaseMetadata implements DatabaseMetaData {
         return new JdbcResultSet(true, null,
             conn.createStatement0(),
             Collections.<String>emptyList(),
-            Arrays.asList("TABLE_CAT", "TABLE_SCHEM", "TABLE_NAME", "TABLE_TYPE", "REMARKS", "TYPE_CAT",
+            asList("TABLE_CAT", "TABLE_SCHEM", "TABLE_NAME", "TABLE_TYPE", "REMARKS", "TYPE_CAT",
                 "TYPE_SCHEM", "TYPE_NAME", "SELF_REFERENCING_COL_NAME", "REF_GENERATION"),
-            Arrays.asList(String.class.getName(), String.class.getName(), String.class.getName(),
+            asList(String.class.getName(), String.class.getName(), String.class.getName(),
                 String.class.getName(), String.class.getName(), String.class.getName(), String.class.getName(),
                 String.class.getName(), String.class.getName(), String.class.getName()),
             rows, true
@@ -748,9 +764,9 @@ public class JdbcDatabaseMetadata implements DatabaseMetaData {
         return new JdbcResultSet(true, null,
             conn.createStatement0(),
             Collections.<String>emptyList(),
-            Collections.singletonList("TABLE_CAT"),
-            Collections.singletonList(String.class.getName()),
-            Collections.singletonList(Collections.singletonList(CATALOG_NAME)),
+            singletonList("TABLE_CAT"),
+            singletonList(String.class.getName()),
+            singletonList(singletonList(CATALOG_NAME)),
             true
         );
     }
@@ -760,9 +776,9 @@ public class JdbcDatabaseMetadata implements DatabaseMetaData {
         return new JdbcResultSet(true, null,
             conn.createStatement0(),
             Collections.<String>emptyList(),
-            Collections.singletonList("TABLE_TYPE"),
-            Collections.singletonList(String.class.getName()),
-            Collections.<List<?>>singletonList(Collections.singletonList("TABLE")),
+            singletonList("TABLE_TYPE"),
+            singletonList(String.class.getName()),
+            asList(singletonList(TYPE_TABLE), singletonList(TYPE_VIEW) ),
             true);
     }
 
@@ -789,7 +805,7 @@ public class JdbcDatabaseMetadata implements DatabaseMetaData {
         return new JdbcResultSet(true, null,
             conn.createStatement0(),
             Collections.<String>emptyList(),
-            Arrays.asList(
+            asList(
                 "TABLE_CAT",        // 1
                 "TABLE_SCHEM",      // 2
                 "TABLE_NAME",       // 3
@@ -814,7 +830,7 @@ public class JdbcDatabaseMetadata implements DatabaseMetaData {
                 "SOURCE_DATA_TYPE", // 22
                 "IS_AUTOINCREMENT", // 23
                 "IS_GENERATEDCOLUMN"), // 23
-            Arrays.asList(
+            asList(
                 String.class.getName(),     // 1
                 String.class.getName(),     // 2
                 String.class.getName(),     // 3
@@ -916,8 +932,8 @@ public class JdbcDatabaseMetadata implements DatabaseMetaData {
         return new JdbcResultSet(true, null,
             conn.createStatement0(),
             Collections.<String>emptyList(),
-            Arrays.asList("TABLE_CAT", "TABLE_SCHEM", "TABLE_NAME", "COLUMN_NAME", "KEY_SEQ", "PK_NAME"),
-            Arrays.asList(String.class.getName(), String.class.getName(), String.class.getName(),
+            asList("TABLE_CAT", "TABLE_SCHEM", "TABLE_NAME", "COLUMN_NAME", "KEY_SEQ", "PK_NAME"),
+            asList(String.class.getName(), String.class.getName(), String.class.getName(),
                 String.class.getName(), Short.class.getName(), String.class.getName()),
             rows, true
         );
@@ -992,10 +1008,10 @@ public class JdbcDatabaseMetadata implements DatabaseMetaData {
         return new JdbcResultSet(true, null,
             conn.createStatement0(),
             Collections.<String>emptyList(),
-            Arrays.asList("TABLE_CAT", "TABLE_SCHEM", "TABLE_NAME", "NON_UNIQUE", "INDEX_QUALIFIER",
+            asList("TABLE_CAT", "TABLE_SCHEM", "TABLE_NAME", "NON_UNIQUE", "INDEX_QUALIFIER",
                 "INDEX_NAME", "TYPE", "ORDINAL_POSITION", "COLUMN_NAME", "ASC_OR_DESC", "CARDINALITY",
                 "PAGES", "FILTER_CONDITION"),
-            Arrays.asList(String.class.getName(), String.class.getName(), String.class.getName(),
+            asList(String.class.getName(), String.class.getName(), String.class.getName(),
                 Boolean.class.getName(), String.class.getName(), String.class.getName(), Short.class.getName(),
                 Short.class.getName(), String.class.getName(), String.class.getName(), Integer.class.getName(),
                 Integer.class.getName(), String.class.getName()),
@@ -1200,8 +1216,8 @@ public class JdbcDatabaseMetadata implements DatabaseMetaData {
         return new JdbcResultSet(true, null,
             conn.createStatement0(),
             Collections.<String>emptyList(),
-            Arrays.asList("TABLE_SCHEM", "TABLE_CATALOG"),
-            Arrays.asList(String.class.getName(), String.class.getName()),
+            asList("TABLE_SCHEM", "TABLE_CATALOG"),
+            asList(String.class.getName(), String.class.getName()),
             rows, true
         );
     }
@@ -1239,9 +1255,9 @@ public class JdbcDatabaseMetadata implements DatabaseMetaData {
         return new JdbcResultSet(true, null,
             conn.createStatement0(),
             Collections.<String>emptyList(),
-            Arrays.asList("FUNCTION_CAT", "FUNCTION_SCHEM", "FUNCTION_NAME",
+            asList("FUNCTION_CAT", "FUNCTION_SCHEM", "FUNCTION_NAME",
                 "REMARKS", "FUNCTION_TYPE", "SPECIFIC_NAME"),
-            Arrays.asList(String.class.getName(), String.class.getName(), String.class.getName(),
+            asList(String.class.getName(), String.class.getName(), String.class.getName(),
                 String.class.getName(), Short.class.getName(), String.class.getName()),
             Collections.<List<?>>emptyList(), true
         );
@@ -1253,11 +1269,11 @@ public class JdbcDatabaseMetadata implements DatabaseMetaData {
         return new JdbcResultSet(true, null,
             conn.createStatement0(),
             Collections.<String>emptyList(),
-            Arrays.asList("FUNCTION_CAT", "FUNCTION_SCHEM", "FUNCTION_NAME",
+            asList("FUNCTION_CAT", "FUNCTION_SCHEM", "FUNCTION_NAME",
                 "COLUMN_NAME", "COLUMN_TYPE", "DATA_TYPE", "TYPE_NAME", "PRECISION",
                 "LENGTH", "SCALE", "RADIX", "NULLABLE", "REMARKS", "CHAR_OCTET_LENGTH",
                 "ORDINAL_POSITION", "IS_NULLABLE", "SPECIFIC_NAME"),
-            Arrays.asList(String.class.getName(), String.class.getName(), String.class.getName(),
+            asList(String.class.getName(), String.class.getName(), String.class.getName(),
                 String.class.getName(), Short.class.getName(), Integer.class.getName(), String.class.getName(),
                 Integer.class.getName(), Integer.class.getName(), Short.class.getName(), Short.class.getName(),
                 Short.class.getName(), String.class.getName(), Integer.class.getName(), Integer.class.getName(),
diff --git a/modules/core/src/main/java/org/apache/ignite/internal/jdbc2/JdbcUtils.java b/modules/core/src/main/java/org/apache/ignite/internal/jdbc2/JdbcUtils.java
index f49cbfa..961c7dd 100644
--- a/modules/core/src/main/java/org/apache/ignite/internal/jdbc2/JdbcUtils.java
+++ b/modules/core/src/main/java/org/apache/ignite/internal/jdbc2/JdbcUtils.java
@@ -60,6 +60,12 @@ public class JdbcUtils {
     /** The only possible name for catalog. */
     public static final String CATALOG_NAME = "IGNITE";
 
+    /** Name of TABLE type. */
+    public static final String TYPE_TABLE = "TABLE";
+
+    /** Name of VIEW type. */
+    public static final String TYPE_VIEW = "VIEW";
+
     /**
      * Converts Java class name to type from {@link Types}.
      *
@@ -300,7 +306,7 @@ public class JdbcUtils {
         row.add(CATALOG_NAME);
         row.add(tblMeta.schemaName());
         row.add(tblMeta.tableName());
-        row.add("TABLE");
+        row.add(tblMeta.tableType());
         row.add(null);
         row.add(null);
         row.add(null);
diff --git a/modules/core/src/main/java/org/apache/ignite/internal/processors/odbc/jdbc/JdbcMetaTablesRequest.java b/modules/core/src/main/java/org/apache/ignite/internal/processors/odbc/jdbc/JdbcMetaTablesRequest.java
index fe936ae..109bea1 100644
--- a/modules/core/src/main/java/org/apache/ignite/internal/processors/odbc/jdbc/JdbcMetaTablesRequest.java
+++ b/modules/core/src/main/java/org/apache/ignite/internal/processors/odbc/jdbc/JdbcMetaTablesRequest.java
@@ -23,6 +23,8 @@ import org.apache.ignite.internal.binary.BinaryWriterExImpl;
 import org.apache.ignite.internal.processors.odbc.ClientListenerProtocolVersion;
 import org.apache.ignite.internal.util.typedef.internal.S;
 
+import static org.apache.ignite.internal.processors.odbc.jdbc.JdbcConnectionContext.VER_2_8_0;
+
 /**
  * JDBC tables metadata request.
  */
@@ -33,6 +35,9 @@ public class JdbcMetaTablesRequest extends JdbcRequest {
     /** Table search pattern. */
     private String tblName;
 
+    /** Table types. */
+    private String[] tblTypes;
+
     /**
      * Default constructor is used for deserialization.
      */
@@ -43,12 +48,14 @@ public class JdbcMetaTablesRequest extends JdbcRequest {
     /**
      * @param schemaName Schema search pattern.
      * @param tblName Table search pattern.
+     * @param tblTypes Table types.
      */
-    public JdbcMetaTablesRequest(String schemaName, String tblName) {
+    public JdbcMetaTablesRequest(String schemaName, String tblName, String[] tblTypes) {
         super(META_TABLES);
 
         this.schemaName = schemaName;
         this.tblName = tblName;
+        this.tblTypes = tblTypes;
     }
 
     /**
@@ -65,6 +72,13 @@ public class JdbcMetaTablesRequest extends JdbcRequest {
         return tblName;
     }
 
+    /**
+     * @return Table types.
+     */
+    public String[] tableTypes() {
+        return tblTypes;
+    }
+
     /** {@inheritDoc} */
     @Override public void writeBinary(BinaryWriterExImpl writer,
         ClientListenerProtocolVersion ver) throws BinaryObjectException {
@@ -72,6 +86,9 @@ public class JdbcMetaTablesRequest extends JdbcRequest {
 
         writer.writeString(schemaName);
         writer.writeString(tblName);
+
+        if (ver.compareTo(VER_2_8_0) >= 0)
+            writer.writeStringArray(tblTypes);
     }
 
     /** {@inheritDoc} */
@@ -79,8 +96,11 @@ public class JdbcMetaTablesRequest extends JdbcRequest {
         ClientListenerProtocolVersion ver) throws BinaryObjectException {
         super.readBinary(reader, ver);
 
-        this.schemaName = reader.readString();
-        this.tblName = reader.readString();
+        schemaName = reader.readString();
+        tblName = reader.readString();
+
+        if (ver.compareTo(VER_2_8_0) >= 0)
+            tblTypes = reader.readStringArray();
     }
 
     /** {@inheritDoc} */
diff --git a/modules/core/src/main/java/org/apache/ignite/internal/processors/odbc/jdbc/JdbcMetadataInfo.java b/modules/core/src/main/java/org/apache/ignite/internal/processors/odbc/jdbc/JdbcMetadataInfo.java
index a9ce8a8..9450fa1 100644
--- a/modules/core/src/main/java/org/apache/ignite/internal/processors/odbc/jdbc/JdbcMetadataInfo.java
+++ b/modules/core/src/main/java/org/apache/ignite/internal/processors/odbc/jdbc/JdbcMetadataInfo.java
@@ -25,15 +25,16 @@ import java.util.Comparator;
 import java.util.HashSet;
 import java.util.LinkedHashSet;
 import java.util.List;
-import java.util.Map;
 import java.util.SortedSet;
 import java.util.TreeSet;
+import java.util.stream.Collectors;
 import org.apache.ignite.internal.GridKernalContext;
 import org.apache.ignite.internal.processors.odbc.ClientListenerProtocolVersion;
+import org.apache.ignite.internal.processors.query.ColumnInformation;
 import org.apache.ignite.internal.processors.query.GridQueryIndexDescriptor;
-import org.apache.ignite.internal.processors.query.GridQueryProperty;
 import org.apache.ignite.internal.processors.query.GridQueryTypeDescriptor;
 import org.apache.ignite.internal.processors.query.QueryUtils;
+import org.apache.ignite.internal.processors.query.TableInformation;
 import org.jetbrains.annotations.Nullable;
 
 import static org.apache.ignite.internal.processors.odbc.jdbc.JdbcConnectionContext.VER_2_3_0;
@@ -48,8 +49,40 @@ public class JdbcMetadataInfo {
     /** Root context. Used to get all the database metadata. */
     private final GridKernalContext ctx;
 
-    /** The only one possible value of table type. */
-    public static final String TABLE_TYPE = "TABLE";
+    /** Comparator for {@link ColumnInformation} by schema then table name then column order. */
+    private static final Comparator<ColumnInformation> bySchemaThenTabNameThenColOrder = new Comparator<ColumnInformation>() {
+        @Override public int compare(ColumnInformation o1, ColumnInformation o2) {
+            int schemaCmp = o1.schemaName().compareTo(o2.schemaName());
+
+            if (schemaCmp != 0)
+                return schemaCmp;
+
+            int tblNameCmp = o1.tableName().compareTo(o2.tableName());
+
+            if (tblNameCmp != 0)
+                return tblNameCmp;
+
+            return Integer.compare(o1.columnId(), o2.columnId());
+        }
+    };
+
+    /** Comparator for {@link JdbcTableMeta} by table type then schema then table name. */
+    private static final Comparator<TableInformation> byTblTypeThenSchemaThenTblName =
+        new Comparator<TableInformation>() {
+            @Override public int compare(TableInformation o1, TableInformation o2) {
+                int tblTypeCmp = o1.tableType().compareTo(o2.tableType());
+
+                if (tblTypeCmp != 0)
+                    return tblTypeCmp;
+
+                int schemCmp = o1.schemaName().compareTo(o2.schemaName());
+
+                if (schemCmp != 0)
+                    return schemCmp;
+
+                return o1.tableName().compareTo(o2.tableName());
+            }
+        };
 
     /**
      * Initializes info.
@@ -67,7 +100,7 @@ public class JdbcMetadataInfo {
      *
      * @return Collection of primary keys information for tables that matches specified schema and table name patterns.
      */
-    public Collection<JdbcPrimaryKeyMeta> getPrimaryKeys(String schemaNamePtrn, String tableNamePtrn) {
+    public Collection<JdbcPrimaryKeyMeta> getPrimaryKeys(String schemaNamePtrn, String tblNamePtrn) {
         Collection<JdbcPrimaryKeyMeta> meta = new HashSet<>();
 
         for (String cacheName : ctx.cache().publicCacheNames()) {
@@ -75,7 +108,7 @@ public class JdbcMetadataInfo {
                 if (!matches(table.schemaName(), schemaNamePtrn))
                     continue;
 
-                if (!matches(table.tableName(), tableNamePtrn))
+                if (!matches(table.tableName(), tblNamePtrn))
                     continue;
 
                 List<String> fields = new ArrayList<>();
@@ -112,39 +145,19 @@ public class JdbcMetadataInfo {
      *
      * Result is ordered by (schema name, table name).
      *
-     * @param schemaPtrn sql pattern for schema name.
-     * @param tabPtrn sql pattern for table name.
-     * @return List of metadatas of tables that matches .
+     * @param schemaNamePtrn sql pattern for schema name.
+     * @param tblNamePtrn sql pattern for table name.
+     * @param tblTypes Requested table types.
+     * @return List of metadatas of tables that matches.
      */
-    public List<JdbcTableMeta> getTablesMeta(String schemaPtrn, String tabPtrn) {
-        Comparator<JdbcTableMeta> bySchemaThenTabname = new Comparator<JdbcTableMeta>() {
-            @Override public int compare(JdbcTableMeta o1, JdbcTableMeta o2) {
-                int schemCmp = o1.schemaName().compareTo(o2.schemaName());
-
-                if (schemCmp != 0)
-                    return schemCmp;
-
-                return o1.tableName().compareTo(o2.tableName());
-            }
-        };
-
-        TreeSet<JdbcTableMeta> tabMetas = new TreeSet<>(bySchemaThenTabname);
-
-        for (String cacheName : ctx.cache().publicCacheNames()) {
-            for (GridQueryTypeDescriptor table : ctx.query().types(cacheName)) {
-                if (!matches(table.schemaName(), schemaPtrn))
-                    continue;
-
-                if (!matches(table.tableName(), tabPtrn))
-                    continue;
-
-                JdbcTableMeta tableMeta = new JdbcTableMeta(table.schemaName(), table.tableName(), TABLE_TYPE);
-
-                tabMetas.add(tableMeta);
-            }
-        }
-
-        return new ArrayList<>(tabMetas);
+    public List<JdbcTableMeta> getTablesMeta(String schemaNamePtrn, String tblNamePtrn, String[] tblTypes) {
+        Collection<TableInformation> tblsMeta = ctx.query().getIndexing()
+            .tablesInformation(schemaNamePtrn, tblNamePtrn, tblTypes);
+
+        return tblsMeta.stream()
+            .sorted(byTblTypeThenSchemaThenTblName)
+            .map(t -> new JdbcTableMeta(t.schemaName(), t.tableName(), t.tableType()))
+            .collect(Collectors.toList());
     }
 
     /**
@@ -152,63 +165,43 @@ public class JdbcMetadataInfo {
      *
      * Ignite has only one possible CATALOG_NAME, it is handled on the client (driver) side.
      *
-     * @param protocolVer for what version of protocol to generate metadata. Early versions of protocol don't support
-     * some features like default values or precision/scale. If {@code null}, current version will be used.
+     * @param protoVer for what version of protocol to generate metadata. Early versions of protocol don't support some
+     * features like default values or precision/scale. If {@code null}, current version will be used.
      * @return List of metadatas about columns that match specified schema/tablename/columnname criterias.
      */
-    public Collection<JdbcColumnMeta> getColumnsMeta(@Nullable ClientListenerProtocolVersion protocolVer,
-        String schemaNamePtrn, String tableNamePtrn, String columnNamePtrn) {
+    public Collection<JdbcColumnMeta> getColumnsMeta(@Nullable ClientListenerProtocolVersion protoVer,
+        String schemaNamePtrn, String tblNamePtrn, String colNamePtrn) {
 
-        boolean useNewest = protocolVer == null;
+        boolean useNewest = protoVer == null;
 
         Collection<JdbcColumnMeta> metas = new LinkedHashSet<>();
 
-        for (String cacheName : ctx.cache().publicCacheNames()) {
-            for (GridQueryTypeDescriptor table : ctx.query().types(cacheName)) {
-                if (!matches(table.schemaName(), schemaNamePtrn))
-                    continue;
-
-                if (!matches(table.tableName(), tableNamePtrn))
-                    continue;
+        Collection<ColumnInformation> colsInfo = ctx.query().getIndexing()
+            .columnsInformation(schemaNamePtrn, tblNamePtrn, colNamePtrn);
 
-                for (Map.Entry<String, Class<?>> field : table.fields().entrySet()) {
-                    String colName = field.getKey();
+        colsInfo.stream().sorted(bySchemaThenTabNameThenColOrder)
+            .forEachOrdered(info -> {
+                JdbcColumnMeta colMeta;
 
-                    Class<?> fieldCls = field.getValue();
-
-                    if (!matches(colName, columnNamePtrn))
-                        continue;
-
-                    JdbcColumnMeta columnMeta;
-
-                    if (useNewest || protocolVer.compareTo(VER_2_7_0) >= 0) {
-                        GridQueryProperty prop = table.property(colName);
-
-                        columnMeta = new JdbcColumnMetaV4(table.schemaName(), table.tableName(),
-                            colName, fieldCls, !prop.notNull(), prop.defaultValue(),
-                            prop.precision(), prop.scale());
-                    }
-                    else if (protocolVer.compareTo(VER_2_4_0) >= 0) {
-                        GridQueryProperty prop = table.property(colName);
-
-                        columnMeta = new JdbcColumnMetaV3(table.schemaName(), table.tableName(),
-                            colName, fieldCls, !prop.notNull(), prop.defaultValue());
-                    }
-                    else if (protocolVer.compareTo(VER_2_3_0) >= 0) {
-                        GridQueryProperty prop = table.property(colName);
-
-                        columnMeta = new JdbcColumnMetaV2(table.schemaName(), table.tableName(),
-                            colName, fieldCls, !prop.notNull());
-                    }
-                    else
-                        columnMeta = new JdbcColumnMeta(table.schemaName(), table.tableName(),
-                            colName, fieldCls);
-
-                    if (!metas.contains(columnMeta))
-                        metas.add(columnMeta);
+                if (useNewest || protoVer.compareTo(VER_2_7_0) >= 0) {
+                    colMeta = new JdbcColumnMetaV4(info.schemaName(), info.tableName(), info.columnName(),
+                        info.fieldClass(), info.nullable(), info.defaultValue(), info.precision(), info.scale());
                 }
-            }
-        }
+                else if (protoVer.compareTo(VER_2_4_0) >= 0) {
+                    colMeta = new JdbcColumnMetaV3(info.schemaName(), info.tableName(), info.columnName(),
+                        info.fieldClass(), info.nullable(), info.defaultValue());
+                }
+                else if (protoVer.compareTo(VER_2_3_0) >= 0) {
+                    colMeta = new JdbcColumnMetaV2(info.schemaName(), info.tableName(), info.columnName(),
+                        info.fieldClass(), info.nullable());
+                }
+                else
+                    colMeta = new JdbcColumnMeta(info.schemaName(), info.tableName(), info.columnName(),
+                        info.fieldClass());
+
+                if (!metas.contains(colMeta))
+                    metas.add(colMeta);
+            });
 
         return metas;
     }
@@ -240,7 +233,7 @@ public class JdbcMetadataInfo {
      *
      * @return Sorted by index name collection of index info, filtered according to specified criterias.
      */
-    public SortedSet<JdbcIndexMeta> getIndexesMeta(String schemaNamePtrn, String tableNamePtrn) {
+    public SortedSet<JdbcIndexMeta> getIndexesMeta(String schemaNamePtrn, String tblNamePtrn) {
         final Comparator<JdbcIndexMeta> byIndexName = new Comparator<JdbcIndexMeta>() {
             @Override public int compare(JdbcIndexMeta o1, JdbcIndexMeta o2) {
                 return o1.indexName().compareTo(o2.indexName());
@@ -254,7 +247,7 @@ public class JdbcMetadataInfo {
                 if (!matches(table.schemaName(), schemaNamePtrn))
                     continue;
 
-                if (!matches(table.tableName(), tableNamePtrn))
+                if (!matches(table.tableName(), tblNamePtrn))
                     continue;
 
                 for (GridQueryIndexDescriptor idxDesc : table.indexes().values())
diff --git a/modules/core/src/main/java/org/apache/ignite/internal/processors/odbc/jdbc/JdbcRequestHandler.java b/modules/core/src/main/java/org/apache/ignite/internal/processors/odbc/jdbc/JdbcRequestHandler.java
index 5f1de25..a0ba2d4 100644
--- a/modules/core/src/main/java/org/apache/ignite/internal/processors/odbc/jdbc/JdbcRequestHandler.java
+++ b/modules/core/src/main/java/org/apache/ignite/internal/processors/odbc/jdbc/JdbcRequestHandler.java
@@ -1071,7 +1071,7 @@ public class JdbcRequestHandler implements ClientListenerRequestHandler {
      */
     private JdbcResponse getTablesMeta(JdbcMetaTablesRequest req) {
         try {
-            List<JdbcTableMeta> tabMetas = meta.getTablesMeta(req.schemaName(), req.tableName());
+            List<JdbcTableMeta> tabMetas = meta.getTablesMeta(req.schemaName(), req.tableName(), req.tableTypes());
 
             JdbcMetaTablesResult res = new JdbcMetaTablesResult(tabMetas);
 
diff --git a/modules/core/src/main/java/org/apache/ignite/internal/processors/odbc/jdbc/JdbcTableMeta.java b/modules/core/src/main/java/org/apache/ignite/internal/processors/odbc/jdbc/JdbcTableMeta.java
index d4324d6..c546ff9 100644
--- a/modules/core/src/main/java/org/apache/ignite/internal/processors/odbc/jdbc/JdbcTableMeta.java
+++ b/modules/core/src/main/java/org/apache/ignite/internal/processors/odbc/jdbc/JdbcTableMeta.java
@@ -25,6 +25,9 @@ import org.apache.ignite.internal.processors.odbc.ClientListenerProtocolVersion;
 import org.apache.ignite.internal.util.typedef.F;
 import org.apache.ignite.internal.util.typedef.internal.S;
 
+import static org.apache.ignite.internal.jdbc2.JdbcUtils.TYPE_TABLE;
+import static org.apache.ignite.internal.processors.odbc.jdbc.JdbcConnectionContext.VER_2_8_0;
+
 /**
  * JDBC table metadata.
  */
@@ -35,11 +38,14 @@ public class JdbcTableMeta implements JdbcRawBinarylizable {
     /** Table name. */
     private String tblName;
 
+    /** Table type. */
+    private String tblType;
+
     /**
      * Default constructor is used for deserialization.
      */
     JdbcTableMeta() {
-        // No-op.
+        tblType = TYPE_TABLE;
     }
 
     /**
@@ -50,6 +56,7 @@ public class JdbcTableMeta implements JdbcRawBinarylizable {
     JdbcTableMeta(String schemaName, String tblName, String tblType) {
         this.schemaName = schemaName;
         this.tblName = tblName;
+        this.tblType = tblType;
     }
 
     /**
@@ -66,11 +73,21 @@ public class JdbcTableMeta implements JdbcRawBinarylizable {
         return tblName;
     }
 
+    /**
+     * @return Table type.
+     */
+    public String tableType() {
+        return tblType;
+    }
+
     /** {@inheritDoc} */
     @Override public void writeBinary(BinaryWriterExImpl writer,
         ClientListenerProtocolVersion ver) throws BinaryObjectException {
         writer.writeString(schemaName);
         writer.writeString(tblName);
+
+        if (ver.compareTo(VER_2_8_0) >= 0)
+            writer.writeString(tblType);
     }
 
     /** {@inheritDoc} */
@@ -78,11 +95,9 @@ public class JdbcTableMeta implements JdbcRawBinarylizable {
         ClientListenerProtocolVersion ver) throws BinaryObjectException {
         schemaName = reader.readString();
         tblName = reader.readString();
-    }
 
-    /** {@inheritDoc} */
-    @Override public String toString() {
-        return S.toString(JdbcTableMeta.class, this);
+        if (ver.compareTo(VER_2_8_0) >= 0)
+            tblType = reader.readString();
     }
 
     /** {@inheritDoc} */
@@ -102,4 +117,9 @@ public class JdbcTableMeta implements JdbcRawBinarylizable {
     @Override public int hashCode() {
         return Objects.hash(schemaName, tblName);
     }
+
+    /** {@inheritDoc} */
+    @Override public String toString() {
+        return S.toString(JdbcTableMeta.class, this);
+    }
 }
diff --git a/modules/core/src/main/java/org/apache/ignite/internal/processors/query/ColumnInformation.java b/modules/core/src/main/java/org/apache/ignite/internal/processors/query/ColumnInformation.java
new file mode 100644
index 0000000..fe97e04
--- /dev/null
+++ b/modules/core/src/main/java/org/apache/ignite/internal/processors/query/ColumnInformation.java
@@ -0,0 +1,182 @@
+/*
+ * 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.processors.query;
+
+import org.apache.ignite.internal.util.typedef.F;
+import org.apache.ignite.internal.util.typedef.internal.S;
+
+/**
+ * Information about table column.
+ */
+public class ColumnInformation {
+    /** */
+    private final int ordinalPosition;
+
+    /** */
+    private final String schemaName;
+
+    /** */
+    private final String tblName;
+
+    /** */
+    private final String colName;
+
+    /** */
+    private final Class<?> fieldCls;
+
+    /** */
+    private final boolean nullable;
+
+    /** */
+    private final Object dfltVal;
+
+    /** */
+    private final int precision;
+
+    /** */
+    private final int scale;
+
+    /** */
+    private final boolean affinityCol;
+
+
+    /**
+     * @param ordinalPosition Ordinal column position.
+     * @param schemaName Schema name.
+     * @param tblName Table name.
+     * @param colName Column name.
+     * @param fieldCls Field class.
+     * @param nullable Nullable.
+     * @param dfltVal Default value.
+     * @param precision Precision for a column or -1 if not applicable.
+     * @param scale Scale for a column or -1 if not applicable.
+     */
+    public ColumnInformation(int ordinalPosition, String schemaName, String tblName, String colName, Class<?> fieldCls,
+        boolean nullable, Object dfltVal, int precision, int scale, boolean affinityCol) {
+        this.ordinalPosition = ordinalPosition;
+        this.schemaName = schemaName;
+        this.tblName = tblName;
+        this.colName = colName;
+        this.fieldCls = fieldCls;
+        this.nullable = nullable;
+        this.dfltVal = dfltVal;
+        this.precision = precision;
+        this.scale = scale;
+        this.affinityCol = affinityCol;
+    }
+
+    /**
+     * @return Column id.
+     */
+    public int columnId() {
+        return ordinalPosition;
+    }
+
+    /**
+     * @return Schema name.
+     */
+    public String schemaName() {
+        return schemaName;
+    }
+
+    /**
+     * @return Table name.
+     */
+    public String tableName() {
+        return tblName;
+    }
+
+    /**
+     * @return Column name.
+     */
+    public String columnName() {
+        return colName;
+    }
+
+    /**
+     * @return Class of column type.
+     */
+    public Class<?> fieldClass() {
+        return fieldCls;
+    }
+
+    /**
+     * @return {@code true} For nullabe column
+     */
+    public boolean nullable() {
+        return nullable;
+    }
+
+    /**
+     * @return Default value for column or {@code null} in case dafault value wasn't set
+     */
+    public Object defaultValue() {
+        return dfltVal;
+    }
+
+    /**
+     * @return Precision.
+     */
+    public int precision() {
+        return precision;
+    }
+
+    /**
+     * @return Scale.
+     */
+    public int scale() {
+        return scale;
+    }
+
+    /**
+     * @return {@code true} For affinity column.
+     */
+    public boolean affinityColumn() {
+        return affinityCol;
+    }
+
+    /** {@inheritDoc} */
+    @Override public boolean equals(Object o) {
+        if (this == o)
+            return true;
+
+        if (o == null || getClass() != o.getClass())
+            return false;
+
+        ColumnInformation info = (ColumnInformation)o;
+
+        return F.eq(schemaName, info.schemaName) && F.eq(tblName, info.tblName) && F.eq(colName, info.colName);
+    }
+
+    /** {@inheritDoc} */
+    @Override public int hashCode() {
+        int res = schemaName != null ? schemaName.hashCode() : 0;
+
+        res = 31 * res + (tblName != null ? tblName.hashCode() : 0);
+
+        res = 31 * res + colName.hashCode();
+
+        return res;
+    }
+
+    /** {@inheritDoc} */
+    @Override public String toString() {
+        return S.toString(ColumnInformation.class, this);
+    }
+}
diff --git a/modules/core/src/main/java/org/apache/ignite/internal/processors/query/GridQueryIndexing.java b/modules/core/src/main/java/org/apache/ignite/internal/processors/query/GridQueryIndexing.java
index dc2bc0f..bc62eff 100644
--- a/modules/core/src/main/java/org/apache/ignite/internal/processors/query/GridQueryIndexing.java
+++ b/modules/core/src/main/java/org/apache/ignite/internal/processors/query/GridQueryIndexing.java
@@ -432,4 +432,27 @@ public interface GridQueryIndexing {
      * @throws IgniteCheckedException On bean registration error.
      */
     void registerMxBeans(IgniteMBeansManager mbMgr) throws IgniteCheckedException;
+
+    /**
+     * Return table information filtered by given patterns.
+     *
+     * @param schemaNamePtrn Filter by schema name. Can be {@code null} to don't use the filter.
+     * @param tblNamePtrn Filter by table name. Can be {@code null} to don't use the filter.
+     * @param tblTypes Filter by table type. As Of now supported only 'TABLES' and 'VIEWS'.
+     * Can be {@code null} or empty to don't use the filter.
+     *
+     * @return Column information filtered by given patterns.
+     */
+    Collection<TableInformation> tablesInformation(String schemaNamePtrn, String tblNamePtrn, String... tblTypes);
+
+    /**
+     * Return column information filtered by given patterns.
+     *
+     * @param schemaNamePtrn Filter by schema name. Can be {@code null} to don't use the filter.
+     * @param tblNamePtrn Filter by table name. Can be {@code null} to don't use the filter.
+     * @param colNamePtrn Filter by column name. Can be {@code null} to don't use the filter.
+     *
+     * @return Column information filtered by given patterns.
+     */
+    Collection<ColumnInformation> columnsInformation(String schemaNamePtrn, String tblNamePtrn, String colNamePtrn);
 }
diff --git a/modules/core/src/main/java/org/apache/ignite/internal/processors/query/TableInformation.java b/modules/core/src/main/java/org/apache/ignite/internal/processors/query/TableInformation.java
new file mode 100644
index 0000000..cefe6e3
--- /dev/null
+++ b/modules/core/src/main/java/org/apache/ignite/internal/processors/query/TableInformation.java
@@ -0,0 +1,236 @@
+/*
+ * 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.processors.query;
+
+import org.apache.ignite.internal.util.typedef.internal.S;
+import org.jetbrains.annotations.Nullable;
+
+/**
+ * Information about table.
+ */
+public class TableInformation {
+    /** Cache group id. */
+    private final int cacheGrpId;
+
+    /** Cache group name. */
+    private final String cacheGrpName;
+
+    /** Cache id. */
+    private final int cacheId;
+
+    /** Cache name. */
+    private final String cacheName;
+
+    /** Affinity Key column. */
+    private final String affinityKeyCol;
+
+    /** Key alias. */
+    private final String keyAlias;
+
+    /** Value alias. */
+    private final String valAlias;
+
+    /** Key type name. */
+    private final String keyTypeName;
+
+    /** Value type name. */
+    private final String valTypeName;
+
+    /** Schema name. */
+    private final String schemaName;
+
+    /** Table name. */
+    private final String tblName;
+
+    /** Table type. */
+    private final String tblType;
+
+
+    /**
+     * @param schemaName Schema name.
+     * @param tblName Table name.
+     * @param tblType Table type.
+     * @param cacheGrpId Cache group id.
+     * @param cacheGrpName Cache group name.
+     * @param cacheId Cache id.
+     * @param cacheName Cache name.
+     * @param affinityKeyCol Affinity key column name.
+     * @param keyAlias Key alias.
+     * @param valAlias Value alias.
+     * @param keyTypeName Key type name.
+     * @param valTypeName Value type name.
+     */
+    public TableInformation(String schemaName, String tblName,
+        String tblType, int cacheGrpId, String cacheGrpName, int cacheId, String cacheName, String affinityKeyCol,
+        String keyAlias, String valAlias, String keyTypeName, String valTypeName) {
+        assert schemaName != null;
+        assert tblName != null;
+        assert tblType != null;
+
+        this.schemaName = schemaName;
+        this.tblName = tblName;
+        this.tblType = tblType;
+
+        this.cacheGrpId = cacheGrpId;
+        this.cacheGrpName = cacheGrpName;
+        this.cacheId = cacheId;
+        this.cacheName = cacheName;
+        this.affinityKeyCol = affinityKeyCol;
+        this.keyAlias = keyAlias;
+        this.valAlias = valAlias;
+        this.keyTypeName = keyTypeName;
+        this.valTypeName = valTypeName;
+    }
+
+    /**
+     * @param schemaName Schema name.
+     * @param tblName Table name.
+     * @param tblType Table type.
+     */
+    public TableInformation(String schemaName, String tblName, String tblType){
+        assert schemaName != null;
+        assert tblName != null;
+        assert tblType != null;
+
+        this.schemaName = schemaName;
+        this.tblName = tblName;
+        this.tblType = tblType;
+
+        cacheGrpId = -1;
+        cacheGrpName = null;
+        cacheId = -1;
+        cacheName = null;
+        affinityKeyCol = null;
+        keyAlias = null;
+        valAlias = null;
+        keyTypeName = null;
+        valTypeName = null;
+    }
+
+    /**
+     * @return Schema name.
+     */
+    public String schemaName() {
+        return schemaName;
+    }
+
+    /**
+     * @return Table name.
+     */
+    public String tableName() {
+        return tblName;
+    }
+
+    /**
+     * @return Table type.
+     */
+    public String tableType() {
+        return tblType;
+    }
+
+    /**
+     * @return Cache Group id or {@code -1} if not applicable.
+     */
+    public int cacheGrpId() {
+        return cacheGrpId;
+    }
+
+    /**
+     * @return Cache group name or {@code null} if not applicable.
+     */
+    public String cacheGrpName() {
+        return cacheGrpName;
+    }
+
+    /**
+     * @return Cache id or {@code -1} if not applicable.
+     */
+    public int cacheId() {
+        return cacheId;
+    }
+
+    /**
+     * @return Cache name or {@code null} if not applicable.
+     */
+    public String cacheName() {
+        return cacheName;
+    }
+
+    /**
+     * @return Affinity key column name or {@code null} if not applicable.
+     */
+    @Nullable public String affinityKeyColumn() {
+        return affinityKeyCol;
+    }
+
+    /**
+     * @return Key alias or {@code null} if not applicable.
+     */
+    public String keyAlias() {
+        return keyAlias;
+    }
+
+    /**
+     * @return Value alias or {@code null} if not applicable.
+     */
+    public String valueAlias() {
+        return valAlias;
+    }
+
+    /**
+     * @return Key type name or {@code null} if not applicable.
+     */
+    public String keyTypeName() {
+        return keyTypeName;
+    }
+
+    /**
+     * @return Value type name or {@code null} if not applicable.
+     */
+    public String valueTypeName() {
+        return valTypeName;
+    }
+
+    /** {@inheritDoc} */
+    @Override public boolean equals(Object o) {
+        if (this == o)
+            return true;
+
+        if (o == null || getClass() != o.getClass())
+            return false;
+
+        TableInformation tblInfo = (TableInformation)o;
+
+        return schemaName.equals(tblInfo.schemaName) && tblName.equals(tblInfo.tblName);
+    }
+
+    /** {@inheritDoc} */
+    @Override public int hashCode() {
+        int res = schemaName.hashCode();
+
+        res = 31 * res + tblName.hashCode();
+
+        return res;
+    }
+
+    /** {@inheritDoc} */
+    @Override public String toString() {
+        return S.toString(TableInformation.class, this);
+    }
+}
diff --git a/modules/core/src/test/java/org/apache/ignite/internal/processors/cache/IgniteClientCacheInitializationFailTest.java b/modules/core/src/test/java/org/apache/ignite/internal/processors/cache/IgniteClientCacheInitializationFailTest.java
index cb3a509..e1768d1 100644
--- a/modules/core/src/test/java/org/apache/ignite/internal/processors/cache/IgniteClientCacheInitializationFailTest.java
+++ b/modules/core/src/test/java/org/apache/ignite/internal/processors/cache/IgniteClientCacheInitializationFailTest.java
@@ -17,6 +17,7 @@
 
 package org.apache.ignite.internal.processors.cache;
 
+import java.util.Collection;
 import java.util.Collections;
 import java.util.HashSet;
 import java.util.Random;
@@ -31,8 +32,10 @@ import org.apache.ignite.configuration.CacheConfiguration;
 import org.apache.ignite.configuration.IgniteConfiguration;
 import org.apache.ignite.configuration.NearCacheConfiguration;
 import org.apache.ignite.internal.IgniteKernal;
+import org.apache.ignite.internal.processors.query.ColumnInformation;
 import org.apache.ignite.internal.processors.query.DummyQueryIndexing;
 import org.apache.ignite.internal.processors.query.GridQueryProcessor;
+import org.apache.ignite.internal.processors.query.TableInformation;
 import org.apache.ignite.testframework.GridTestUtils;
 import org.apache.ignite.testframework.junits.common.GridCommonAbstractTest;
 import org.junit.Ignore;
@@ -249,5 +252,17 @@ public class IgniteClientCacheInitializationFailTest extends GridCommonAbstractT
 
             return true;
         }
+
+        /** {@inheritDoc} */
+        @Override public Collection<TableInformation> tablesInformation(String schemaNamePtrn, String tblNamePtrn,
+            String[] tblTypes) {
+            return null;
+        }
+
+        /** {@inheritDoc} */
+        @Override public Collection<ColumnInformation> columnsInformation(String schemaNamePtrn, String tblNamePtrn,
+            String colNamePtrn){
+            return null;
+        }
     }
 }
diff --git a/modules/core/src/test/java/org/apache/ignite/internal/processors/query/DummyQueryIndexing.java b/modules/core/src/test/java/org/apache/ignite/internal/processors/query/DummyQueryIndexing.java
index a65232c..ff60501 100644
--- a/modules/core/src/test/java/org/apache/ignite/internal/processors/query/DummyQueryIndexing.java
+++ b/modules/core/src/test/java/org/apache/ignite/internal/processors/query/DummyQueryIndexing.java
@@ -311,4 +311,20 @@ public class DummyQueryIndexing implements GridQueryIndexing {
     @Override public void registerMxBeans(IgniteMBeansManager mbMgr) {
 
     }
+
+    /** {@inheritDoc} */
+    @Override public Collection<TableInformation> tablesInformation(
+        String schemaNamePtrn,
+        String tblNamePtrn,
+        String... tblTypes) {
+        return null;
+    }
+
+    /** {@inheritDoc} */
+    @Override public Collection<ColumnInformation> columnsInformation(
+        String schemaNamePtrn,
+        String tblNamePtrn,
+        String colNamePtrn) {
+        return null;
+    }
 }
diff --git a/modules/indexing/src/main/java/org/apache/ignite/internal/processors/query/h2/IgniteH2Indexing.java b/modules/indexing/src/main/java/org/apache/ignite/internal/processors/query/h2/IgniteH2Indexing.java
index 92656aa..5ac88d4 100644
--- a/modules/indexing/src/main/java/org/apache/ignite/internal/processors/query/h2/IgniteH2Indexing.java
+++ b/modules/indexing/src/main/java/org/apache/ignite/internal/processors/query/h2/IgniteH2Indexing.java
@@ -26,13 +26,17 @@ import java.sql.Statement;
 import java.util.ArrayList;
 import java.util.Arrays;
 import java.util.Collection;
+import java.util.Collections;
+import java.util.HashSet;
 import java.util.Iterator;
 import java.util.LinkedHashMap;
 import java.util.List;
 import java.util.Map;
+import java.util.Objects;
 import java.util.Set;
 import java.util.UUID;
 import java.util.concurrent.TimeUnit;
+import java.util.stream.Stream;
 import org.apache.ignite.IgniteCheckedException;
 import org.apache.ignite.IgniteDataStreamer;
 import org.apache.ignite.IgniteException;
@@ -59,6 +63,7 @@ import org.apache.ignite.internal.mxbean.SqlQueryMXBeanImpl;
 import org.apache.ignite.internal.pagemem.PageMemory;
 import org.apache.ignite.internal.pagemem.store.IgnitePageStoreManager;
 import org.apache.ignite.internal.processors.affinity.AffinityTopologyVersion;
+import org.apache.ignite.internal.processors.cache.CacheGroupDescriptor;
 import org.apache.ignite.internal.processors.cache.CacheObjectValueContext;
 import org.apache.ignite.internal.processors.cache.CacheOperationContext;
 import org.apache.ignite.internal.processors.cache.DynamicCacheDescriptor;
@@ -88,6 +93,7 @@ import org.apache.ignite.internal.processors.cache.query.RegisteredQueryCursor;
 import org.apache.ignite.internal.processors.cache.transactions.IgniteTxAdapter;
 import org.apache.ignite.internal.processors.cache.tree.CacheDataTree;
 import org.apache.ignite.internal.processors.odbc.SqlStateCode;
+import org.apache.ignite.internal.processors.query.ColumnInformation;
 import org.apache.ignite.internal.processors.odbc.jdbc.JdbcParameterMeta;
 import org.apache.ignite.internal.processors.query.EnlistOperation;
 import org.apache.ignite.internal.processors.query.GridQueryCacheObjectsIterator;
@@ -96,6 +102,7 @@ import org.apache.ignite.internal.processors.query.GridQueryFieldMetadata;
 import org.apache.ignite.internal.processors.query.GridQueryFieldsResult;
 import org.apache.ignite.internal.processors.query.GridQueryFieldsResultAdapter;
 import org.apache.ignite.internal.processors.query.GridQueryIndexing;
+import org.apache.ignite.internal.processors.query.GridQueryProperty;
 import org.apache.ignite.internal.processors.query.GridQueryRowCacheCleaner;
 import org.apache.ignite.internal.processors.query.GridQueryTypeDescriptor;
 import org.apache.ignite.internal.processors.query.GridRunningQueryInfo;
@@ -105,6 +112,7 @@ import org.apache.ignite.internal.processors.query.QueryIndexDescriptorImpl;
 import org.apache.ignite.internal.processors.query.QueryUtils;
 import org.apache.ignite.internal.processors.query.RunningQueryManager;
 import org.apache.ignite.internal.processors.query.SqlClientContext;
+import org.apache.ignite.internal.processors.query.TableInformation;
 import org.apache.ignite.internal.processors.query.UpdateSourceIterator;
 import org.apache.ignite.internal.processors.query.h2.affinity.H2PartitionResolver;
 import org.apache.ignite.internal.processors.query.h2.affinity.PartitionExtractor;
@@ -173,8 +181,11 @@ import org.h2.api.ErrorCode;
 import org.h2.api.JavaObjectSerializer;
 import org.h2.engine.Session;
 import org.h2.engine.SysProperties;
+import org.h2.table.Column;
 import org.h2.table.IndexColumn;
+import org.h2.table.TableType;
 import org.h2.util.JdbcUtils;
+import org.h2.value.DataType;
 import org.jetbrains.annotations.Nullable;
 
 import static java.util.Collections.singletonList;
@@ -186,6 +197,7 @@ import static org.apache.ignite.internal.processors.cache.mvcc.MvccUtils.request
 import static org.apache.ignite.internal.processors.cache.mvcc.MvccUtils.tx;
 import static org.apache.ignite.internal.processors.cache.mvcc.MvccUtils.txStart;
 import static org.apache.ignite.internal.processors.cache.query.GridCacheQueryType.TEXT;
+import static org.apache.ignite.internal.processors.query.QueryUtils.matches;
 import static org.apache.ignite.internal.processors.query.h2.H2Utils.UPDATE_RESULT_META;
 import static org.apache.ignite.internal.processors.query.h2.H2Utils.generateFieldsQueryString;
 import static org.apache.ignite.internal.processors.query.h2.H2Utils.session;
@@ -1771,6 +1783,114 @@ public class IgniteH2Indexing implements GridQueryIndexing {
     }
 
     /** {@inheritDoc} */
+    @Override public Collection<TableInformation> tablesInformation(String schemaNamePtrn, String tblNamePtrn,
+        String... tblTypes) {
+        Set<String> types = F.isEmpty(tblTypes) ? Collections.emptySet() : new HashSet<>(Arrays.asList(tblTypes));
+
+        Collection<TableInformation> infos = new ArrayList<>();
+
+        boolean allTypes = F.isEmpty(tblTypes);
+
+        if (allTypes || types.contains(TableType.TABLE.name())) {
+            schemaMgr.dataTables().stream()
+                .filter(t -> matches(t.getSchema().getName(), schemaNamePtrn))
+                .filter(t -> matches(t.getName(), tblNamePtrn))
+                .map(t -> {
+                    int cacheGrpId = t.cacheInfo().groupId();
+
+                    CacheGroupDescriptor cacheGrpDesc = ctx.cache().cacheGroupDescriptors().get(cacheGrpId);
+
+                    // We should skip table in case regarding cache group has been removed.
+                    if (cacheGrpDesc == null)
+                        return null;
+
+                    GridQueryTypeDescriptor type = t.rowDescriptor().type();
+
+                    IndexColumn affCol = t.getExplicitAffinityKeyColumn();
+
+                    String affinityKeyCol = affCol != null ? affCol.columnName : null;
+
+                    return new TableInformation(t.getSchema().getName(), t.getName(), TableType.TABLE.name(), cacheGrpId,
+                        cacheGrpDesc.cacheOrGroupName(), t.cacheId(), t.cacheName(), affinityKeyCol,
+                        type.keyFieldAlias(), type.valueFieldAlias(), type.keyTypeName(), type.valueTypeName());
+                })
+                .filter(Objects::nonNull)
+                .forEach(infos::add);
+        }
+
+        if ((allTypes || types.contains(TableType.VIEW.name()))
+            && matches(QueryUtils.SCHEMA_SYS, schemaNamePtrn)) {
+            schemaMgr.systemViews().stream()
+                .filter(t -> matches(t.getTableName(), tblNamePtrn))
+                .map(v -> new TableInformation(QueryUtils.SCHEMA_SYS, v.getTableName(), TableType.VIEW.name()))
+                .forEach(infos::add);
+        }
+
+        return infos;
+    }
+
+    /** {@inheritDoc} */
+    @Override public Collection<ColumnInformation> columnsInformation(String schemaNamePtrn, String tblNamePtrn,
+        String colNamePtrn) {
+        Collection<ColumnInformation> infos = new ArrayList<>();
+
+        // Gather information about tables.
+        schemaMgr.dataTables().stream()
+            .filter(t -> matches(t.getSchema().getName(), schemaNamePtrn))
+            .filter(t -> matches(t.getName(), tblNamePtrn))
+            .flatMap(
+                tbl -> {
+                    IndexColumn affCol = tbl.getAffinityKeyColumn();
+
+                    return Stream.of(tbl.getColumns())
+                        .filter(Column::getVisible)
+                        .filter(c -> matches(c.getName(), colNamePtrn))
+                        .map(c -> {
+                            GridQueryProperty prop = tbl.rowDescriptor().type().property(c.getName());
+
+                            boolean isAff = affCol != null && c.getColumnId() == affCol.column.getColumnId();
+
+                            return new ColumnInformation(
+                                c.getColumnId() - QueryUtils.DEFAULT_COLUMNS_COUNT + 1,
+                                tbl.getSchema().getName(),
+                                tbl.getName(),
+                                c.getName(),
+                                prop.type(),
+                                c.isNullable(),
+                                prop.defaultValue(),
+                                prop.precision(),
+                                prop.scale(),
+                                isAff);
+                        });
+                }
+            ).forEach(infos::add);
+
+        // Gather information about system views.
+        if (matches(QueryUtils.SCHEMA_SYS, schemaNamePtrn)) {
+            schemaMgr.systemViews().stream()
+                .filter(v -> matches(v.getTableName(), tblNamePtrn))
+                .flatMap(
+                    view ->
+                        Stream.of(view.getColumns())
+                            .filter(c -> matches(c.getName(), colNamePtrn))
+                            .map(c -> new ColumnInformation(
+                                c.getColumnId() + 1,
+                                QueryUtils.SCHEMA_SYS,
+                                view.getTableName(),
+                                c.getName(),
+                                IgniteUtils.classForName(DataType.getTypeClassName(c.getType()), Object.class),
+                                c.isNullable(),
+                                null,
+                                (int)c.getPrecision(),
+                                c.getScale(),
+                                false))
+                ).forEach(infos::add);
+        }
+
+        return infos;
+    }
+
+    /** {@inheritDoc} */
     @Override public boolean isStreamableInsertStatement(String schemaName, SqlFieldsQuery qry) throws SQLException{
         QueryParserResult parsed = parser.parse(schemaName, qry, true);
 
diff --git a/modules/indexing/src/main/java/org/apache/ignite/internal/processors/query/h2/SchemaManager.java b/modules/indexing/src/main/java/org/apache/ignite/internal/processors/query/h2/SchemaManager.java
index 25c0155..4e102b3 100644
--- a/modules/indexing/src/main/java/org/apache/ignite/internal/processors/query/h2/SchemaManager.java
+++ b/modules/indexing/src/main/java/org/apache/ignite/internal/processors/query/h2/SchemaManager.java
@@ -64,6 +64,7 @@ import org.apache.ignite.internal.processors.query.h2.sys.view.SqlSystemViewRunn
 import org.apache.ignite.internal.processors.query.h2.sys.view.SqlSystemViewSchemas;
 import org.apache.ignite.internal.processors.query.h2.sys.view.SqlSystemViewTables;
 import org.apache.ignite.internal.processors.query.schema.SchemaIndexCacheVisitor;
+import org.apache.ignite.internal.util.GridConcurrentHashSet;
 import org.apache.ignite.internal.util.typedef.F;
 import org.apache.ignite.internal.util.typedef.internal.U;
 import org.h2.index.Index;
@@ -85,6 +86,9 @@ public class SchemaManager {
     /** Data tables. */
     private final ConcurrentMap<QueryTable, GridH2Table> dataTables = new ConcurrentHashMap<>();
 
+    /** System VIEW collection. */
+    private final Set<SqlSystemView> systemViews = new GridConcurrentHashSet<>();
+
     /** Mutex to synchronize schema operations. */
     private final Object schemaMux = new Object();
 
@@ -155,6 +159,8 @@ public class SchemaManager {
 
             try (Connection c = connMgr.connectionNoCache(schema)) {
                 SqlSystemTableEngine.registerView(c, view);
+
+                    systemViews.add(view);
             }
         }
         catch (IgniteCheckedException | SQLException e) {
@@ -186,7 +192,7 @@ public class SchemaManager {
         views.add(new SqlSystemViewCacheGroupsIOStatistics(ctx));
         views.add(new SqlSystemViewRunningQueries(ctx));
         views.add(new SqlSystemViewQueryHistoryMetrics(ctx));
-        views.add(new SqlSystemViewTables(ctx, this));
+        views.add(new SqlSystemViewTables(ctx));
         views.add(new SqlSystemViewIndexes(ctx, this));
         views.add(new SqlSystemViewSchemas(ctx, this));
 
@@ -739,6 +745,13 @@ public class SchemaManager {
     }
 
     /**
+     * @return all known system views.
+     */
+    public Collection<SqlSystemView> systemViews() {
+        return Collections.unmodifiableSet(systemViews);
+    }
+
+    /**
      * Find table for index.
      *
      * @param schemaName Schema name.
diff --git a/modules/indexing/src/main/java/org/apache/ignite/internal/processors/query/h2/opt/GridH2Table.java b/modules/indexing/src/main/java/org/apache/ignite/internal/processors/query/h2/opt/GridH2Table.java
index dfc3e02..dc4ee1a 100644
--- a/modules/indexing/src/main/java/org/apache/ignite/internal/processors/query/h2/opt/GridH2Table.java
+++ b/modules/indexing/src/main/java/org/apache/ignite/internal/processors/query/h2/opt/GridH2Table.java
@@ -344,6 +344,17 @@ public class GridH2Table extends TableBase {
     }
 
     /**
+     * @return Explicit affinity key column or {@code null} if not available (skip _KEY column or it's alias).
+     */
+    @Nullable public IndexColumn getExplicitAffinityKeyColumn() {
+        // Only explicit affinity column should be shown. Do not do this for _KEY or it's alias.
+        if (affKeyCol == null || affKeyColIsKey)
+            return null;
+
+        return affKeyCol;
+    }
+
+    /**
      * Check whether passed column can be used for partition pruning.
      *
      * @param col Column.
diff --git a/modules/indexing/src/main/java/org/apache/ignite/internal/processors/query/h2/sys/SqlSystemIndex.java b/modules/indexing/src/main/java/org/apache/ignite/internal/processors/query/h2/sys/SqlSystemIndex.java
index 2b4896e..1962342 100644
--- a/modules/indexing/src/main/java/org/apache/ignite/internal/processors/query/h2/sys/SqlSystemIndex.java
+++ b/modules/indexing/src/main/java/org/apache/ignite/internal/processors/query/h2/sys/SqlSystemIndex.java
@@ -44,7 +44,7 @@ public class SqlSystemIndex extends BaseIndex {
      * @param tbl Table.
      * @param col Column.
      */
-    SqlSystemIndex(SqlSystemTable tbl, Column... col) {
+    SqlSystemIndex(SystemViewH2Adapter tbl, Column... col) {
         IndexColumn[] idxCols;
 
         if (col != null && col.length > 0)
@@ -72,9 +72,9 @@ public class SqlSystemIndex extends BaseIndex {
 
     /** {@inheritDoc} */
     @Override public Cursor find(Session ses, SearchRow first, SearchRow last) {
-        assert table instanceof SqlSystemTable;
+        assert table instanceof SystemViewH2Adapter;
 
-        Iterator<Row> rows = ((SqlSystemTable)table).getRows(ses, first, last);
+        Iterator<Row> rows = ((SystemViewH2Adapter)table).getRows(ses, first, last);
 
         return new GridH2Cursor(rows);
     }
@@ -86,7 +86,7 @@ public class SqlSystemIndex extends BaseIndex {
 
         double baseCost = getCostRangeIndex(masks, rowCnt, filters, filter, sortOrder, false, allColsSet);
 
-        if (((SqlSystemTable)table).view.isDistributed())
+        if (((SystemViewH2Adapter)table).view.isDistributed())
             baseCost = baseCost * DISTRIBUTED_MUL;
 
         return baseCost;
diff --git a/modules/indexing/src/main/java/org/apache/ignite/internal/processors/query/h2/sys/SqlSystemTableEngine.java b/modules/indexing/src/main/java/org/apache/ignite/internal/processors/query/h2/sys/SqlSystemTableEngine.java
index 23d7739..4c3b5b5 100644
--- a/modules/indexing/src/main/java/org/apache/ignite/internal/processors/query/h2/sys/SqlSystemTableEngine.java
+++ b/modules/indexing/src/main/java/org/apache/ignite/internal/processors/query/h2/sys/SqlSystemTableEngine.java
@@ -55,6 +55,6 @@ public class SqlSystemTableEngine implements TableEngine {
 
     /** {@inheritDoc} */
     @Override public Table createTable(CreateTableData data) {
-        return new SqlSystemTable(data, curView);
+        return new SystemViewH2Adapter(data, curView);
     }
 }
diff --git a/modules/indexing/src/main/java/org/apache/ignite/internal/processors/query/h2/sys/SqlSystemTable.java b/modules/indexing/src/main/java/org/apache/ignite/internal/processors/query/h2/sys/SystemViewH2Adapter.java
similarity index 96%
rename from modules/indexing/src/main/java/org/apache/ignite/internal/processors/query/h2/sys/SqlSystemTable.java
rename to modules/indexing/src/main/java/org/apache/ignite/internal/processors/query/h2/sys/SystemViewH2Adapter.java
index 664da0f..91e120b 100644
--- a/modules/indexing/src/main/java/org/apache/ignite/internal/processors/query/h2/sys/SqlSystemTable.java
+++ b/modules/indexing/src/main/java/org/apache/ignite/internal/processors/query/h2/sys/SystemViewH2Adapter.java
@@ -35,7 +35,7 @@ import org.h2.table.TableType;
 /**
  * System H2 table over a view.
  */
-public class SqlSystemTable extends TableBase {
+public class SystemViewH2Adapter extends TableBase {
     /** Scan index. */
     protected final SqlSystemIndex scanIdx;
 
@@ -53,14 +53,14 @@ public class SqlSystemTable extends TableBase {
      * @param data Data.
      * @param view Meta view.
      */
-    public SqlSystemTable(CreateTableData data, SqlSystemView view) {
+    public SystemViewH2Adapter(CreateTableData data, SqlSystemView view) {
         super(data);
 
         assert view != null;
 
         this.view = view;
 
-        this.setColumns(view.getColumns());
+        setColumns(view.getColumns());
 
         scanIdx = new SqlSystemIndex(this);
 
@@ -159,7 +159,7 @@ public class SqlSystemTable extends TableBase {
 
     /** {@inheritDoc} */
     @Override public TableType getTableType() {
-        return TableType.SYSTEM_TABLE;
+        return TableType.VIEW;
     }
 
     /** {@inheritDoc} */
diff --git a/modules/indexing/src/main/java/org/apache/ignite/internal/processors/query/h2/sys/view/SqlSystemViewTables.java b/modules/indexing/src/main/java/org/apache/ignite/internal/processors/query/h2/sys/view/SqlSystemViewTables.java
index 4ce9bc5..78577ba 100644
--- a/modules/indexing/src/main/java/org/apache/ignite/internal/processors/query/h2/sys/view/SqlSystemViewTables.java
+++ b/modules/indexing/src/main/java/org/apache/ignite/internal/processors/query/h2/sys/view/SqlSystemViewTables.java
@@ -17,20 +17,15 @@
 
 package org.apache.ignite.internal.processors.query.h2.sys.view;
 
-import java.util.ArrayList;
 import java.util.Iterator;
 import java.util.List;
-import java.util.function.Predicate;
+import java.util.stream.Collectors;
 import org.apache.ignite.internal.GridKernalContext;
-import org.apache.ignite.internal.processors.cache.CacheGroupDescriptor;
-import org.apache.ignite.internal.processors.query.h2.SchemaManager;
-import org.apache.ignite.internal.processors.query.h2.opt.GridH2Table;
 import org.h2.engine.Session;
 import org.h2.result.Row;
 import org.h2.result.SearchRow;
-import org.h2.table.IndexColumn;
+import org.h2.table.TableType;
 import org.h2.value.Value;
-import org.jetbrains.annotations.Nullable;
 
 /**
  * View that contains information about all the sql tables in the cluster.
@@ -39,15 +34,12 @@ public class SqlSystemViewTables extends SqlAbstractLocalSystemView {
     /** Name of the column that contains names of sql tables. */
     private static final String TABLE_NAME = "TABLE_NAME";
 
-    /** Schema manager. */
-    private final SchemaManager schemaMgr;
-
     /**
      * Creates view with columns.
      *
      * @param ctx kernal context.
      */
-    public SqlSystemViewTables(GridKernalContext ctx, SchemaManager schemaMgr) {
+    public SqlSystemViewTables(GridKernalContext ctx) {
         super("TABLES", "Ignite tables", ctx, TABLE_NAME,
             newColumn("CACHE_GROUP_ID", Value.INT),
             newColumn("CACHE_GROUP_NAME"),
@@ -61,78 +53,37 @@ public class SqlSystemViewTables extends SqlAbstractLocalSystemView {
             newColumn("KEY_TYPE_NAME"),
             newColumn("VALUE_TYPE_NAME")
         );
-
-        this.schemaMgr = schemaMgr;
     }
 
     /** {@inheritDoc} */
     @Override public Iterator<Row> getRows(Session ses, SearchRow first, SearchRow last) {
         SqlSystemViewColumnCondition nameCond = conditionForColumn(TABLE_NAME, first, last);
 
-        Predicate<GridH2Table> filter;
-
-        if (nameCond.isEquality()) {
-            String tblName = nameCond.valueForEquality().getString();
-
-            filter = tbl -> tblName.equals(tbl.getName());
-        }
-        else
-            filter = tab -> true;
-
-        List<Row> rows = new ArrayList<>();
+        String tblNamePtrn = nameCond.isEquality() ? nameCond.valueForEquality().getString() : null;
 
-        schemaMgr.dataTables().stream()
-            .filter(filter)
-            .forEach(tbl -> {
-                    int cacheGrpId = tbl.cacheInfo().groupId();
-
-                    CacheGroupDescriptor cacheGrpDesc = ctx.cache().cacheGroupDescriptors().get(cacheGrpId);
-
-                    // We should skip table in case in case regarding cache group has been removed.
-                    if (cacheGrpDesc == null)
-                        return;
-
-                    Object[] data = new Object[] {
-                        cacheGrpId,
-                        cacheGrpDesc.cacheOrGroupName(),
+        List<Row> rows = ctx.query().getIndexing().tablesInformation(null, tblNamePtrn, TableType.TABLE.name())
+            .stream()
+            .map(tbl ->
+                createRow(ses,
+                    new Object[] {
+                        tbl.cacheGrpId(),
+                        tbl.cacheGrpName(),
                         tbl.cacheId(),
                         tbl.cacheName(),
-                        tbl.getSchema().getName(),
-                        tbl.getName(),
-                        computeAffinityColumn(tbl),
-                        tbl.rowDescriptor().type().keyFieldAlias(),
-                        tbl.rowDescriptor().type().valueFieldAlias(),
-                        tbl.rowDescriptor().type().keyTypeName(),
-                        tbl.rowDescriptor().type().valueTypeName()
-                    };
-
-                    rows.add(createRow(ses, data));
-                }
-            );
+                        tbl.schemaName(),
+                        tbl.tableName(),
+                        tbl.affinityKeyColumn(),
+                        tbl.keyAlias(),
+                        tbl.valueAlias(),
+                        tbl.keyTypeName(),
+                        tbl.valueTypeName()
+                    }
+                )
+            ).collect(Collectors.toList());
 
         return rows.iterator();
     }
 
-    /**
-     * Computes affinity column for the specified table.
-     *
-     * @param tbl Table.
-     * @return "_KEY" for default (all PK), {@code null} if custom mapper specified or name of the desired column
-     * otherwise.
-     */
-    private @Nullable String computeAffinityColumn(GridH2Table tbl) {
-        IndexColumn affCol = tbl.getAffinityKeyColumn();
-
-        if (affCol == null)
-            return null;
-
-        // Only explicit affinity column should be shown. Do not do this for _KEY or it's alias.
-        if (tbl.rowDescriptor().isKeyColumn(affCol.column.getColumnId()))
-            return null;
-
-        return affCol.columnName;
-    }
-
     /** {@inheritDoc} */
     @Override public boolean canGetRowCount() {
         return true;
@@ -140,6 +91,6 @@ public class SqlSystemViewTables extends SqlAbstractLocalSystemView {
 
     /** {@inheritDoc} */
     @Override public long getRowCount() {
-        return schemaMgr.dataTables().size();
+        return ctx.query().getIndexing().tablesInformation(null, null, TableType.TABLE.name()).size();
     }
 }