You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@ignite.apache.org by vo...@apache.org on 2017/10/05 08:55:35 UTC
ignite git commit: IGNITE-6529 JDBC: support column metadata
'nullable' property. This closes #2793.
Repository: ignite
Updated Branches:
refs/heads/master e98e392e2 -> c116bfc68
IGNITE-6529 JDBC: support column metadata 'nullable' property. This closes #2793.
Project: http://git-wip-us.apache.org/repos/asf/ignite/repo
Commit: http://git-wip-us.apache.org/repos/asf/ignite/commit/c116bfc6
Tree: http://git-wip-us.apache.org/repos/asf/ignite/tree/c116bfc6
Diff: http://git-wip-us.apache.org/repos/asf/ignite/diff/c116bfc6
Branch: refs/heads/master
Commit: c116bfc68a05376285946b8eae10ed6e51f848e0
Parents: e98e392
Author: tledkov-gridgain <tl...@gridgain.com>
Authored: Thu Oct 5 11:55:26 2017 +0300
Committer: devozerov <vo...@gridgain.com>
Committed: Thu Oct 5 11:55:26 2017 +0300
----------------------------------------------------------------------
.../internal/jdbc2/JdbcMetadataSelfTest.java | 28 ++--
.../jdbc/thin/JdbcThinMetadataSelfTest.java | 33 ++--
.../jdbc/thin/JdbcThinDatabaseMetadata.java | 3 +-
.../internal/jdbc/thin/JdbcThinTcpIo.java | 4 +-
.../internal/jdbc2/JdbcDatabaseMetadata.java | 70 +++++++--
.../cache/query/GridCacheQueryManager.java | 87 ++++++++++-
.../query/GridCacheQuerySqlMetadataJobV2.java | 154 +++++++++++++++++++
.../query/GridCacheQuerySqlMetadataV2.java | 101 ++++++++++++
.../cache/query/GridCacheSqlMetadata.java | 8 +
.../processors/odbc/jdbc/JdbcColumnMeta.java | 10 ++
.../processors/odbc/jdbc/JdbcColumnMetaV2.java | 74 +++++++++
.../odbc/jdbc/JdbcConnectionContext.java | 4 +-
.../odbc/jdbc/JdbcMetaColumnsResult.java | 28 +++-
.../odbc/jdbc/JdbcMetaColumnsResultV2.java | 50 ++++++
.../odbc/jdbc/JdbcRequestHandler.java | 32 +++-
.../processors/odbc/jdbc/JdbcResult.java | 8 +
16 files changed, 642 insertions(+), 52 deletions(-)
----------------------------------------------------------------------
http://git-wip-us.apache.org/repos/asf/ignite/blob/c116bfc6/modules/clients/src/test/java/org/apache/ignite/internal/jdbc2/JdbcMetadataSelfTest.java
----------------------------------------------------------------------
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 6020a3a..bdc6644 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
@@ -42,7 +42,7 @@ import org.apache.ignite.configuration.CacheConfiguration;
import org.apache.ignite.configuration.ConnectorConfiguration;
import org.apache.ignite.configuration.IgniteConfiguration;
import org.apache.ignite.internal.IgniteVersionUtils;
-import org.apache.ignite.internal.binary.BinaryMarshaller;
+import org.apache.ignite.internal.processors.query.QueryEntityEx;
import org.apache.ignite.internal.util.typedef.F;
import org.apache.ignite.spi.discovery.tcp.TcpDiscoverySpi;
import org.apache.ignite.spi.discovery.tcp.ipfinder.TcpDiscoveryIpFinder;
@@ -78,11 +78,16 @@ public class JdbcMetadataSelfTest extends GridCommonAbstractTest {
cfg.setCacheConfiguration(
cacheConfiguration("pers").setQueryEntities(Arrays.asList(
- new QueryEntity(AffinityKey.class, Person.class)
- .setIndexes(Arrays.asList(
- new QueryIndex("orgId"),
- new QueryIndex().setFields(persFields))))
- ),
+ new QueryEntityEx(
+ new QueryEntity(AffinityKey.class.getName(), Person.class.getName())
+ .addQueryField("name", String.class.getName(), null)
+ .addQueryField("age", Integer.class.getName(), null)
+ .addQueryField("orgId", Integer.class.getName(), null)
+ .setIndexes(Arrays.asList(
+ new QueryIndex("orgId"),
+ new QueryIndex().setFields(persFields))))
+ .setNotNullFields(new HashSet<>(Arrays.asList("age", "name")))
+ )),
cacheConfiguration("org").setQueryEntities(Arrays.asList(
new QueryEntity(AffinityKey.class, Organization.class))));
@@ -208,7 +213,6 @@ public class JdbcMetadataSelfTest extends GridCommonAbstractTest {
* @throws Exception If failed.
*/
public void testGetColumns() throws Exception {
- final boolean primitivesInformationIsLostAfterStore = ignite(0).configuration().getMarshaller() instanceof BinaryMarshaller;
try (Connection conn = DriverManager.getConnection(BASE_URL)) {
DatabaseMetaData meta = conn.getMetaData();
@@ -232,11 +236,15 @@ public class JdbcMetadataSelfTest extends GridCommonAbstractTest {
if ("NAME".equals(name)) {
assertEquals(VARCHAR, rs.getInt("DATA_TYPE"));
assertEquals("VARCHAR", rs.getString("TYPE_NAME"));
- assertEquals(1, rs.getInt("NULLABLE"));
- } else if ("AGE".equals(name) || "ORGID".equals(name)) {
+ assertEquals(0, rs.getInt("NULLABLE"));
+ } else if ("AGE".equals(name)) {
+ assertEquals(INTEGER, rs.getInt("DATA_TYPE"));
+ assertEquals("INTEGER", rs.getString("TYPE_NAME"));
+ assertEquals(0, rs.getInt("NULLABLE"));
+ } else if ("ORGID".equals(name)) {
assertEquals(INTEGER, rs.getInt("DATA_TYPE"));
assertEquals("INTEGER", rs.getString("TYPE_NAME"));
- assertEquals(primitivesInformationIsLostAfterStore ? 1 : 0, rs.getInt("NULLABLE"));
+ assertEquals(1, rs.getInt("NULLABLE"));
}
cnt++;
http://git-wip-us.apache.org/repos/asf/ignite/blob/c116bfc6/modules/clients/src/test/java/org/apache/ignite/jdbc/thin/JdbcThinMetadataSelfTest.java
----------------------------------------------------------------------
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 01b2e8a..abbe4e1 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
@@ -41,7 +41,7 @@ import org.apache.ignite.cache.affinity.AffinityKey;
import org.apache.ignite.configuration.CacheConfiguration;
import org.apache.ignite.configuration.IgniteConfiguration;
import org.apache.ignite.internal.IgniteVersionUtils;
-import org.apache.ignite.internal.binary.BinaryMarshaller;
+import org.apache.ignite.internal.processors.query.QueryEntityEx;
import org.apache.ignite.internal.util.typedef.F;
import org.apache.ignite.spi.discovery.tcp.TcpDiscoverySpi;
import org.apache.ignite.spi.discovery.tcp.ipfinder.TcpDiscoveryIpFinder;
@@ -118,13 +118,15 @@ public class JdbcThinMetadataSelfTest extends JdbcThinAbstractSelfTest {
persFields.put("age", false);
IgniteCache<AffinityKey, Person> personCache = jcache(grid(0), cacheConfiguration(
- new QueryEntity(AffinityKey.class.getName(), Person.class.getName())
- .addQueryField("name", String.class.getName(), null)
- .addQueryField("age", Integer.class.getName(), null)
- .addQueryField("orgId", Integer.class.getName(), null)
- .setIndexes(Arrays.asList(
- new QueryIndex("orgId"),
- new QueryIndex().setFields(persFields)))
+ new QueryEntityEx(
+ new QueryEntity(AffinityKey.class.getName(), Person.class.getName())
+ .addQueryField("name", String.class.getName(), null)
+ .addQueryField("age", Integer.class.getName(), null)
+ .addQueryField("orgId", Integer.class.getName(), null)
+ .setIndexes(Arrays.asList(
+ new QueryIndex("orgId"),
+ new QueryIndex().setFields(persFields))))
+ .setNotNullFields(new HashSet<>(Arrays.asList("age", "name")))
), "pers");
assert personCache != null;
@@ -251,9 +253,6 @@ public class JdbcThinMetadataSelfTest extends JdbcThinAbstractSelfTest {
* @throws Exception If failed.
*/
public void testGetColumns() throws Exception {
- final boolean primitivesInformationIsLostAfterStore = ignite(0).configuration().getMarshaller()
- instanceof BinaryMarshaller;
-
try (Connection conn = DriverManager.getConnection(URL)) {
conn.setSchema("pers");
@@ -279,18 +278,22 @@ public class JdbcThinMetadataSelfTest extends JdbcThinAbstractSelfTest {
if ("NAME".equals(name)) {
assert rs.getInt("DATA_TYPE") == VARCHAR;
assert "VARCHAR".equals(rs.getString("TYPE_NAME"));
+ assert rs.getInt("NULLABLE") == 0;
+ } else if ("ORGID".equals(name)) {
+ assert rs.getInt("DATA_TYPE") == INTEGER;
+ assert "INTEGER".equals(rs.getString("TYPE_NAME"));
assert rs.getInt("NULLABLE") == 1;
- } else if ("AGE".equals(name) || "ORGID".equals(name)) {
+ } else if ("AGE".equals(name)) {
assert rs.getInt("DATA_TYPE") == INTEGER;
assert "INTEGER".equals(rs.getString("TYPE_NAME"));
- assertEquals(primitivesInformationIsLostAfterStore ? 1 : 0, rs.getInt("NULLABLE"));
+ assert rs.getInt("NULLABLE") == 0;
}
- if ("_KEY".equals(name)) {
+ else if ("_KEY".equals(name)) {
assert rs.getInt("DATA_TYPE") == OTHER;
assert "OTHER".equals(rs.getString("TYPE_NAME"));
assert rs.getInt("NULLABLE") == 0;
}
- if ("_VAL".equals(name)) {
+ else if ("_VAL".equals(name)) {
assert rs.getInt("DATA_TYPE") == OTHER;
assert "OTHER".equals(rs.getString("TYPE_NAME"));
assert rs.getInt("NULLABLE") == 0;
http://git-wip-us.apache.org/repos/asf/ignite/blob/c116bfc6/modules/core/src/main/java/org/apache/ignite/internal/jdbc/thin/JdbcThinDatabaseMetadata.java
----------------------------------------------------------------------
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 2ce7983..8b26900 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
@@ -29,7 +29,6 @@ import java.util.Collections;
import java.util.LinkedList;
import java.util.List;
import org.apache.ignite.internal.IgniteVersionUtils;
-import org.apache.ignite.internal.jdbc2.JdbcUtils;
import org.apache.ignite.internal.processors.odbc.jdbc.JdbcColumnMeta;
import org.apache.ignite.internal.processors.odbc.jdbc.JdbcIndexMeta;
import org.apache.ignite.internal.processors.odbc.jdbc.JdbcMetaColumnsRequest;
@@ -845,7 +844,7 @@ public class JdbcThinDatabaseMetadata implements DatabaseMetaData {
row.add((Integer)null);
row.add((Integer)null);
row.add(10);
- row.add(JdbcUtils.nullable(colMeta.columnName(), colMeta.dataTypeClass()) ? 1 : 0 );
+ row.add(colMeta.isNullable() ? 1 : 0);
row.add((String)null);
row.add((String)null);
row.add(Integer.MAX_VALUE);
http://git-wip-us.apache.org/repos/asf/ignite/blob/c116bfc6/modules/core/src/main/java/org/apache/ignite/internal/jdbc/thin/JdbcThinTcpIo.java
----------------------------------------------------------------------
diff --git a/modules/core/src/main/java/org/apache/ignite/internal/jdbc/thin/JdbcThinTcpIo.java b/modules/core/src/main/java/org/apache/ignite/internal/jdbc/thin/JdbcThinTcpIo.java
index 7ac9c2c..688f908 100644
--- a/modules/core/src/main/java/org/apache/ignite/internal/jdbc/thin/JdbcThinTcpIo.java
+++ b/modules/core/src/main/java/org/apache/ignite/internal/jdbc/thin/JdbcThinTcpIo.java
@@ -50,10 +50,10 @@ public class JdbcThinTcpIo {
private static final ClientListenerProtocolVersion VER_2_1_0 = ClientListenerProtocolVersion.create(2, 1, 0);
/** Version 2.3.1. */
- private static final ClientListenerProtocolVersion VER_2_3_1 = ClientListenerProtocolVersion.create(2, 3, 1);
+ private static final ClientListenerProtocolVersion VER_2_3_0 = ClientListenerProtocolVersion.create(2, 3, 0);
/** Current version. */
- private static final ClientListenerProtocolVersion CURRENT_VER = VER_2_3_1;
+ private static final ClientListenerProtocolVersion CURRENT_VER = VER_2_3_0;
/** Initial output stream capacity for handshake. */
private static final int HANDSHAKE_MSG_SIZE = 13;
http://git-wip-us.apache.org/repos/asf/ignite/blob/c116bfc6/modules/core/src/main/java/org/apache/ignite/internal/jdbc2/JdbcDatabaseMetadata.java
----------------------------------------------------------------------
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 4c21cbd..03fde79 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
@@ -26,6 +26,7 @@ import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collection;
import java.util.Collections;
+import java.util.LinkedHashMap;
import java.util.LinkedList;
import java.util.List;
import java.util.Map;
@@ -59,7 +60,7 @@ public class JdbcDatabaseMetadata implements DatabaseMetaData {
private final JdbcConnection conn;
/** Metadata. */
- private Map<String, Map<String, Map<String, String>>> meta;
+ private Map<String, Map<String, Map<String, ColumnInfo>>> meta;
/** Index info. */
private Collection<List<Object>> indexes;
@@ -714,7 +715,7 @@ public class JdbcDatabaseMetadata implements DatabaseMetaData {
List<List<?>> rows = new LinkedList<>();
if (validCatalogPattern(catalog) && (tblTypes == null || Arrays.asList(tblTypes).contains("TABLE"))) {
- for (Map.Entry<String, Map<String, Map<String, String>>> schema : meta.entrySet()) {
+ for (Map.Entry<String, Map<String, Map<String, ColumnInfo>>> schema : meta.entrySet()) {
if (matches(schema.getKey(), schemaPtrn)) {
for (String tbl : schema.getValue().keySet()) {
if (matches(tbl, tblNamePtrn))
@@ -796,14 +797,14 @@ public class JdbcDatabaseMetadata implements DatabaseMetaData {
int cnt = 0;
if (validCatalogPattern(catalog)) {
- for (Map.Entry<String, Map<String, Map<String, String>>> schema : meta.entrySet()) {
+ for (Map.Entry<String, Map<String, Map<String, ColumnInfo>>> schema : meta.entrySet()) {
if (matches(schema.getKey(), schemaPtrn)) {
- for (Map.Entry<String, Map<String, String>> tbl : schema.getValue().entrySet()) {
+ for (Map.Entry<String, Map<String, ColumnInfo>> tbl : schema.getValue().entrySet()) {
if (matches(tbl.getKey(), tblNamePtrn)) {
- for (Map.Entry<String, String> col : tbl.getValue().entrySet()) {
+ for (Map.Entry<String, ColumnInfo> col : tbl.getValue().entrySet()) {
rows.add(columnRow(schema.getKey(), tbl.getKey(), col.getKey(),
- JdbcUtils.type(col.getValue()), JdbcUtils.typeName(col.getValue()),
- JdbcUtils.nullable(col.getKey(), col.getValue()), ++cnt));
+ JdbcUtils.type(col.getValue().typeName()), JdbcUtils.typeName(col.getValue().typeName()),
+ !col.getValue().isNotNull(), ++cnt));
}
}
}
@@ -925,9 +926,9 @@ public class JdbcDatabaseMetadata implements DatabaseMetaData {
List<List<?>> rows = new LinkedList<>();
if (validCatalogPattern(catalog)) {
- for (Map.Entry<String, Map<String, Map<String, String>>> schema : meta.entrySet()) {
+ for (Map.Entry<String, Map<String, Map<String, ColumnInfo>>> schema : meta.entrySet()) {
if (matches(schema.getKey(), schemaPtrn)) {
- for (Map.Entry<String, Map<String, String>> tbl : schema.getValue().entrySet()) {
+ for (Map.Entry<String, Map<String, ColumnInfo>> tbl : schema.getValue().entrySet()) {
if (matches(tbl.getKey(), tblNamePtrn))
rows.add(Arrays.<Object>asList(null, schema.getKey(), tbl.getKey(), "_KEY", 1, "_KEY"));
}
@@ -1361,10 +1362,21 @@ public class JdbcDatabaseMetadata implements DatabaseMetaData {
Collection<String> types = m.types();
- Map<String, Map<String, String>> typesMap = U.newHashMap(types.size());
+ Map<String, Map<String, ColumnInfo>> typesMap = U.newHashMap(types.size());
for (String type : types) {
- typesMap.put(type.toUpperCase(), m.fields(type));
+ Collection<String> notNullFields = m.notNullFields(type);
+
+ Map<String, ColumnInfo> fields = new LinkedHashMap<>();
+
+ for (Map.Entry<String, String> fld : m.fields(type).entrySet()) {
+ ColumnInfo colInfo = new ColumnInfo(fld.getValue(),
+ notNullFields == null ? false : notNullFields.contains(fld.getKey()));
+
+ fields.put(fld.getKey(), colInfo);
+ }
+
+ typesMap.put(type.toUpperCase(), fields);
for (GridCacheSqlIndexMetadata idx : m.indexes(type)) {
int cnt = 0;
@@ -1435,7 +1447,41 @@ public class JdbcDatabaseMetadata implements DatabaseMetaData {
@Override public Collection<GridCacheSqlMetadata> call() throws Exception {
IgniteCache cache = ignite.cache(cacheName);
- return ((IgniteCacheProxy)cache).context().queries().sqlMetadata();
+ return ((IgniteCacheProxy)cache).context().queries().sqlMetadataV2();
+ }
+ }
+
+ /**
+ * Column info.
+ */
+ private static class ColumnInfo {
+ /** Class name. */
+ private final String typeName;
+
+ /** Not null flag. */
+ private final boolean notNull;
+
+ /**
+ * @param typeName Type name.
+ * @param notNull Not null flag.
+ */
+ private ColumnInfo(String typeName, boolean notNull) {
+ this.typeName = typeName;
+ this.notNull = notNull;
+ }
+
+ /**
+ * @return Type name.
+ */
+ public String typeName() {
+ return typeName;
+ }
+
+ /**
+ * @return Not null flag.
+ */
+ public boolean isNotNull() {
+ return notNull;
}
}
}
http://git-wip-us.apache.org/repos/asf/ignite/blob/c116bfc6/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/query/GridCacheQueryManager.java
----------------------------------------------------------------------
diff --git a/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/query/GridCacheQueryManager.java b/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/query/GridCacheQueryManager.java
index f873461..64e74fb 100644
--- a/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/query/GridCacheQueryManager.java
+++ b/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/query/GridCacheQueryManager.java
@@ -113,6 +113,7 @@ import org.apache.ignite.lang.IgniteBiPredicate;
import org.apache.ignite.lang.IgniteBiTuple;
import org.apache.ignite.lang.IgniteCallable;
import org.apache.ignite.lang.IgniteClosure;
+import org.apache.ignite.lang.IgniteProductVersion;
import org.apache.ignite.lang.IgniteReducer;
import org.apache.ignite.lang.IgniteUuid;
import org.apache.ignite.resources.IgniteInstanceResource;
@@ -145,6 +146,9 @@ public abstract class GridCacheQueryManager<K, V> extends GridCacheManagerAdapte
/** Maximum number of query detail metrics to evict at once. */
private static final int QRY_DETAIL_METRICS_EVICTION_LIMIT = 10_000;
+ /** Support 'not null' field constraint since v 2.3.0. */
+ private static final IgniteProductVersion NOT_NULLS_SUPPORT_VER = IgniteProductVersion.fromString("2.3.0");
+
/** Comparator for priority queue with query detail metrics with priority to new metrics. */
private static final Comparator<GridCacheQueryDetailMetricsAdapter> QRY_DETAIL_METRICS_PRIORITY_NEW_CMP =
new Comparator<GridCacheQueryDetailMetricsAdapter>() {
@@ -1908,6 +1912,79 @@ public abstract class GridCacheQueryManager<K, V> extends GridCacheManagerAdapte
}
/**
+ * Gets SQL metadata with not nulls fields.
+ *
+ * @return SQL metadata.
+ * @throws IgniteCheckedException In case of error.
+ */
+ public Collection<GridCacheSqlMetadata> sqlMetadataV2() throws IgniteCheckedException {
+ if (!enterBusy())
+ throw new IllegalStateException("Failed to get metadata (grid is stopping).");
+
+ try {
+ Callable<Collection<CacheSqlMetadata>> job = new GridCacheQuerySqlMetadataJobV2();
+
+ // Remote nodes that have current cache.
+ Collection<ClusterNode> nodes = CU.affinityNodes(cctx, AffinityTopologyVersion.NONE);
+
+ Collection<Collection<CacheSqlMetadata>> res = new ArrayList<>(nodes.size() + 1);
+
+ IgniteInternalFuture<Collection<Collection<CacheSqlMetadata>>> rmtFut = null;
+
+ // Get metadata from remote nodes.
+ if (!nodes.isEmpty()) {
+ boolean allNodesNew = true;
+
+ for (ClusterNode n : nodes) {
+ if (n.version().compareTo(NOT_NULLS_SUPPORT_VER) < 0)
+ allNodesNew = false;
+ }
+
+ if (!allNodesNew)
+ return sqlMetadata();
+
+ rmtFut = cctx.closures().callAsyncNoFailover(BROADCAST, Collections.singleton(job), nodes, true, 0);
+ }
+
+ // Get local metadata.
+ IgniteInternalFuture<Collection<CacheSqlMetadata>> locFut = cctx.closures().callLocalSafe(job, true);
+
+ if (rmtFut != null)
+ res.addAll(rmtFut.get());
+
+ res.add(locFut.get());
+
+ Map<String, Collection<CacheSqlMetadata>> map = new HashMap<>();
+
+ for (Collection<CacheSqlMetadata> col : res) {
+ for (CacheSqlMetadata meta : col) {
+ String name = meta.cacheName();
+
+ Collection<CacheSqlMetadata> cacheMetas = map.get(name);
+
+ if (cacheMetas == null)
+ map.put(name, cacheMetas = new LinkedList<>());
+
+ cacheMetas.add(meta);
+ }
+ }
+
+ Collection<GridCacheSqlMetadata> col = new ArrayList<>(map.size());
+
+ // Metadata for current cache must be first in list.
+ col.add(new GridCacheQuerySqlMetadataV2(map.remove(cacheName)));
+
+ for (Collection<CacheSqlMetadata> metas : map.values())
+ col.add(new GridCacheQuerySqlMetadataV2(metas));
+
+ return col;
+ }
+ finally {
+ leaveBusy();
+ }
+ }
+
+ /**
* @param <K> Key type.
* @param <V> Value type.
* @param includeBackups Include backups.
@@ -2079,7 +2156,7 @@ public abstract class GridCacheQueryManager<K, V> extends GridCacheManagerAdapte
/**
* Cache metadata.
*/
- private static class CacheSqlMetadata implements GridCacheSqlMetadata {
+ public static class CacheSqlMetadata implements GridCacheSqlMetadata {
/** */
private static final long serialVersionUID = 0L;
@@ -2183,6 +2260,11 @@ public abstract class GridCacheQueryManager<K, V> extends GridCacheManagerAdapte
}
/** {@inheritDoc} */
+ @Override public Collection<String> notNullFields(String type) {
+ return null;
+ }
+
+ /** {@inheritDoc} */
@Override public Map<String, String> keyClasses() {
return keyClasses;
}
@@ -2236,7 +2318,7 @@ public abstract class GridCacheQueryManager<K, V> extends GridCacheManagerAdapte
/**
* Cache metadata index.
*/
- private static class CacheSqlIndexMetadata implements GridCacheSqlIndexMetadata {
+ public static class CacheSqlIndexMetadata implements GridCacheSqlIndexMetadata {
/** */
private static final long serialVersionUID = 0L;
@@ -2371,6 +2453,7 @@ public abstract class GridCacheQueryManager<K, V> extends GridCacheManagerAdapte
/**
* @return Metadata.
+ * @throws IgniteCheckedException On error.
*/
public List<GridQueryFieldMetadata> metaData() throws IgniteCheckedException {
get(); // Ensure that result is ready.
http://git-wip-us.apache.org/repos/asf/ignite/blob/c116bfc6/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/query/GridCacheQuerySqlMetadataJobV2.java
----------------------------------------------------------------------
diff --git a/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/query/GridCacheQuerySqlMetadataJobV2.java b/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/query/GridCacheQuerySqlMetadataJobV2.java
new file mode 100644
index 0000000..9907d1a
--- /dev/null
+++ b/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/query/GridCacheQuerySqlMetadataJobV2.java
@@ -0,0 +1,154 @@
+/*
+ * 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.cache.query;
+
+import org.apache.ignite.Ignite;
+import org.apache.ignite.cache.QueryIndexType;
+import org.apache.ignite.internal.GridKernalContext;
+import org.apache.ignite.internal.IgniteKernal;
+import org.apache.ignite.internal.processors.cache.IgniteInternalCache;
+import org.apache.ignite.internal.processors.datastructures.DataStructuresProcessor;
+import org.apache.ignite.internal.processors.query.GridQueryIndexDescriptor;
+import org.apache.ignite.internal.processors.query.GridQueryTypeDescriptor;
+import org.apache.ignite.internal.processors.task.GridInternal;
+import org.apache.ignite.internal.util.typedef.C1;
+import org.apache.ignite.internal.util.typedef.F;
+import org.apache.ignite.internal.util.typedef.P1;
+import org.apache.ignite.internal.util.typedef.internal.CU;
+import org.apache.ignite.internal.util.typedef.internal.U;
+import org.apache.ignite.lang.IgniteCallable;
+import org.apache.ignite.resources.IgniteInstanceResource;
+
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.HashSet;
+import java.util.LinkedList;
+import java.util.Map;
+import java.util.Set;
+
+/**
+ * Metadata job.
+ */
+@GridInternal
+class GridCacheQuerySqlMetadataJobV2 implements IgniteCallable<Collection<GridCacheQueryManager.CacheSqlMetadata>> {
+ /** */
+ private static final long serialVersionUID = 0L;
+
+ /** Number of fields to report when no fields defined. Includes _key and _val columns. */
+ private static final int NO_FIELDS_COLUMNS_COUNT = 2;
+
+ /** Grid */
+ @IgniteInstanceResource
+ private Ignite ignite;
+
+ /** {@inheritDoc} */
+ @Override public Collection<GridCacheQueryManager.CacheSqlMetadata> call() {
+ final GridKernalContext ctx = ((IgniteKernal)ignite).context();
+
+ Collection<String> cacheNames = F.viewReadOnly(ctx.cache().caches(),
+ new C1<IgniteInternalCache<?, ?>, String>() {
+ @Override public String apply(IgniteInternalCache<?, ?> c) {
+ return c.name();
+ }
+ },
+ new P1<IgniteInternalCache<?, ?>>() {
+ @Override public boolean apply(IgniteInternalCache<?, ?> c) {
+ return !CU.isSystemCache(c.name()) && !DataStructuresProcessor.isDataStructureCache(c.name());
+ }
+ }
+ );
+
+ return F.transform(cacheNames, new C1<String, GridCacheQueryManager.CacheSqlMetadata>() {
+ @Override public GridCacheQueryManager.CacheSqlMetadata apply(String cacheName) {
+ Collection<GridQueryTypeDescriptor> types = ctx.query().types(cacheName);
+
+ Collection<String> names = U.newHashSet(types.size());
+ Map<String, String> keyClasses = U.newHashMap(types.size());
+ Map<String, String> valClasses = U.newHashMap(types.size());
+ Map<String, Map<String, String>> fields = U.newHashMap(types.size());
+ Map<String, Collection<GridCacheSqlIndexMetadata>> indexes = U.newHashMap(types.size());
+ Map<String, Set<String>> notNullFields = U.newHashMap(types.size());
+
+ for (GridQueryTypeDescriptor type : types) {
+ // Filter internal types (e.g., data structures).
+ if (type.name().startsWith("GridCache"))
+ continue;
+
+ names.add(type.name());
+
+ keyClasses.put(type.name(), type.keyClass().getName());
+ valClasses.put(type.name(), type.valueClass().getName());
+
+ int size = type.fields().isEmpty() ? NO_FIELDS_COLUMNS_COUNT : type.fields().size();
+
+ Map<String, String> fieldsMap = U.newLinkedHashMap(size);
+ HashSet<String> notNullFieldsSet = U.newHashSet(1);
+
+ // _KEY and _VAL are not included in GridIndexingTypeDescriptor.valueFields
+ if (type.fields().isEmpty()) {
+ fieldsMap.put("_KEY", type.keyClass().getName());
+ fieldsMap.put("_VAL", type.valueClass().getName());
+ }
+
+ for (Map.Entry<String, Class<?>> e : type.fields().entrySet()) {
+ String fieldName = e.getKey();
+
+ fieldsMap.put(fieldName.toUpperCase(), e.getValue().getName());
+
+ if (type.property(fieldName).notNull())
+ notNullFieldsSet.add(fieldName.toUpperCase());
+ }
+
+ fields.put(type.name(), fieldsMap);
+ notNullFields.put(type.name(), notNullFieldsSet);
+
+ Map<String, GridQueryIndexDescriptor> idxs = type.indexes();
+
+ Collection<GridCacheSqlIndexMetadata> indexesCol = new ArrayList<>(idxs.size());
+
+ for (Map.Entry<String, GridQueryIndexDescriptor> e : idxs.entrySet()) {
+ GridQueryIndexDescriptor desc = e.getValue();
+
+ // Add only SQL indexes.
+ if (desc.type() == QueryIndexType.SORTED) {
+ Collection<String> idxFields = new LinkedList<>();
+ Collection<String> descendings = new LinkedList<>();
+
+ for (String idxField : e.getValue().fields()) {
+ String idxFieldUpper = idxField.toUpperCase();
+
+ idxFields.add(idxFieldUpper);
+
+ if (desc.descending(idxField))
+ descendings.add(idxFieldUpper);
+ }
+
+ indexesCol.add(new GridCacheQueryManager.CacheSqlIndexMetadata(e.getKey().toUpperCase(),
+ idxFields, descendings, false));
+ }
+ }
+
+ indexes.put(type.name(), indexesCol);
+ }
+
+ return new GridCacheQuerySqlMetadataV2(cacheName, names, keyClasses, valClasses, fields, indexes,
+ notNullFields);
+ }
+ });
+ }
+}
http://git-wip-us.apache.org/repos/asf/ignite/blob/c116bfc6/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/query/GridCacheQuerySqlMetadataV2.java
----------------------------------------------------------------------
diff --git a/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/query/GridCacheQuerySqlMetadataV2.java b/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/query/GridCacheQuerySqlMetadataV2.java
new file mode 100644
index 0000000..66821c9
--- /dev/null
+++ b/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/query/GridCacheQuerySqlMetadataV2.java
@@ -0,0 +1,101 @@
+/*
+ * 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.cache.query;
+
+import org.apache.ignite.internal.util.typedef.internal.U;
+import org.jetbrains.annotations.Nullable;
+
+import java.io.Externalizable;
+import java.io.IOException;
+import java.io.ObjectInput;
+import java.io.ObjectOutput;
+import java.util.Collection;
+import java.util.HashMap;
+import java.util.Map;
+import java.util.Set;
+
+/**
+ * Cache metadata with not null field.
+ */
+public class GridCacheQuerySqlMetadataV2 extends GridCacheQueryManager.CacheSqlMetadata {
+ /** */
+ private static final long serialVersionUID = 0L;
+
+ /** Not null fields. */
+ private Map<String, Set<String>> notNullFields;
+
+ /**
+ * Required by {@link Externalizable}.
+ */
+ public GridCacheQuerySqlMetadataV2() {
+ // No-op.
+ }
+
+ /**
+ * @param cacheName Cache name.
+ * @param types Types.
+ * @param keyClasses Key classes map.
+ * @param valClasses Value classes map.
+ * @param fields Fields maps.
+ * @param indexes Indexes.
+ * @param notNullFields Not null fields.
+ */
+ GridCacheQuerySqlMetadataV2(@Nullable String cacheName, Collection<String> types, Map<String, String> keyClasses,
+ Map<String, String> valClasses, Map<String, Map<String, String>> fields,
+ Map<String, Collection<GridCacheSqlIndexMetadata>> indexes, Map<String, Set<String>> notNullFields) {
+ super(cacheName, types, keyClasses, valClasses, fields, indexes);
+
+ this.notNullFields = notNullFields;
+ }
+
+ /**
+ * @param metas Meta data instances from different nodes.
+ */
+ GridCacheQuerySqlMetadataV2(Iterable<GridCacheQueryManager.CacheSqlMetadata> metas) {
+ super(metas);
+
+ notNullFields = new HashMap<>();
+
+ for (GridCacheQueryManager.CacheSqlMetadata meta : metas) {
+ if (meta instanceof GridCacheQuerySqlMetadataV2) {
+ GridCacheQuerySqlMetadataV2 metaV2 = (GridCacheQuerySqlMetadataV2)meta;
+
+ notNullFields.putAll(metaV2.notNullFields);
+ }
+ }
+ }
+
+ /** {@inheritDoc} */
+ @Override public Collection<String> notNullFields(String type) {
+ return notNullFields.get(type);
+ }
+
+ /** {@inheritDoc} */
+ @Override public void writeExternal(ObjectOutput out) throws IOException {
+ super.writeExternal(out);
+
+ U.writeMap(out, notNullFields);
+ }
+
+ /** {@inheritDoc} */
+ @Override public void readExternal(ObjectInput in) throws IOException, ClassNotFoundException {
+ super.readExternal(in);
+
+ notNullFields = U.readHashMap(in);
+ }
+}
http://git-wip-us.apache.org/repos/asf/ignite/blob/c116bfc6/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/query/GridCacheSqlMetadata.java
----------------------------------------------------------------------
diff --git a/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/query/GridCacheSqlMetadata.java b/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/query/GridCacheSqlMetadata.java
index 724962e..ddc2860 100644
--- a/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/query/GridCacheSqlMetadata.java
+++ b/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/query/GridCacheSqlMetadata.java
@@ -78,6 +78,14 @@ public interface GridCacheSqlMetadata extends Externalizable {
@Nullable public Map<String, String> fields(String type);
/**
+ * Gets not null fields.
+ *
+ * @param type Type name.
+ * @return Not null fields collection map or {@code null} if type name is unknown.
+ */
+ Collection<String> notNullFields(String type);
+
+ /**
* @return Key classes.
*/
public Map<String, String> keyClasses();
http://git-wip-us.apache.org/repos/asf/ignite/blob/c116bfc6/modules/core/src/main/java/org/apache/ignite/internal/processors/odbc/jdbc/JdbcColumnMeta.java
----------------------------------------------------------------------
diff --git a/modules/core/src/main/java/org/apache/ignite/internal/processors/odbc/jdbc/JdbcColumnMeta.java b/modules/core/src/main/java/org/apache/ignite/internal/processors/odbc/jdbc/JdbcColumnMeta.java
index 9f145e0..d927c26 100644
--- a/modules/core/src/main/java/org/apache/ignite/internal/processors/odbc/jdbc/JdbcColumnMeta.java
+++ b/modules/core/src/main/java/org/apache/ignite/internal/processors/odbc/jdbc/JdbcColumnMeta.java
@@ -20,6 +20,7 @@ package org.apache.ignite.internal.processors.odbc.jdbc;
import org.apache.ignite.internal.binary.BinaryReaderExImpl;
import org.apache.ignite.internal.binary.BinaryWriterExImpl;
import org.apache.ignite.internal.jdbc.thin.JdbcThinUtils;
+import org.apache.ignite.internal.jdbc2.JdbcUtils;
import org.apache.ignite.internal.processors.query.GridQueryFieldMetadata;
import org.apache.ignite.internal.util.typedef.F;
import org.apache.ignite.internal.util.typedef.internal.S;
@@ -126,6 +127,15 @@ public class JdbcColumnMeta implements JdbcRawBinarylizable {
return dataTypeClass;
}
+ /**
+ * Return 'nullable' flag in compatibility mode (according with column name and column type).
+ *
+ * @return {@code true} in case the column allows null values. Otherwise returns {@code false}
+ */
+ public boolean isNullable() {
+ return JdbcUtils.nullable(colName, dataTypeClass);
+ }
+
/** {@inheritDoc} */
@Override public void writeBinary(BinaryWriterExImpl writer) {
writer.writeString(schemaName);
http://git-wip-us.apache.org/repos/asf/ignite/blob/c116bfc6/modules/core/src/main/java/org/apache/ignite/internal/processors/odbc/jdbc/JdbcColumnMetaV2.java
----------------------------------------------------------------------
diff --git a/modules/core/src/main/java/org/apache/ignite/internal/processors/odbc/jdbc/JdbcColumnMetaV2.java b/modules/core/src/main/java/org/apache/ignite/internal/processors/odbc/jdbc/JdbcColumnMetaV2.java
new file mode 100644
index 0000000..a2b4acf
--- /dev/null
+++ b/modules/core/src/main/java/org/apache/ignite/internal/processors/odbc/jdbc/JdbcColumnMetaV2.java
@@ -0,0 +1,74 @@
+/*
+ * 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.odbc.jdbc;
+
+import org.apache.ignite.internal.binary.BinaryReaderExImpl;
+import org.apache.ignite.internal.binary.BinaryWriterExImpl;
+import org.apache.ignite.internal.util.typedef.internal.S;
+
+/**
+ * JDBC column metadata.
+ */
+public class JdbcColumnMetaV2 extends JdbcColumnMeta{
+ /** Allow nulls . */
+ private boolean nullable;
+
+ /**
+ * Default constructor is used for serialization.
+ */
+ JdbcColumnMetaV2() {
+ // No-op.
+ }
+
+ /**
+ * @param schemaName Schema.
+ * @param tblName Table.
+ * @param colName Column.
+ * @param cls Type.
+ * @param nullable Allow nulls.
+ */
+ public JdbcColumnMetaV2(String schemaName, String tblName, String colName, Class<?> cls, boolean nullable) {
+ super(schemaName, tblName, colName, cls);
+
+ this.nullable = nullable;
+ }
+
+ /** {@inheritDoc} */
+ @Override public boolean isNullable() {
+ return nullable;
+ }
+
+ /** {@inheritDoc} */
+ @Override public void writeBinary(BinaryWriterExImpl writer) {
+ super.writeBinary(writer);
+
+ writer.writeBoolean(nullable);
+ }
+
+ /** {@inheritDoc} */
+ @Override public void readBinary(BinaryReaderExImpl reader) {
+ super.readBinary(reader);
+
+ nullable = reader.readBoolean();
+ }
+
+ /** {@inheritDoc} */
+ @Override public String toString() {
+ return S.toString(JdbcColumnMetaV2.class, this);
+ }
+}
http://git-wip-us.apache.org/repos/asf/ignite/blob/c116bfc6/modules/core/src/main/java/org/apache/ignite/internal/processors/odbc/jdbc/JdbcConnectionContext.java
----------------------------------------------------------------------
diff --git a/modules/core/src/main/java/org/apache/ignite/internal/processors/odbc/jdbc/JdbcConnectionContext.java b/modules/core/src/main/java/org/apache/ignite/internal/processors/odbc/jdbc/JdbcConnectionContext.java
index 38d1972..a6a7aa5 100644
--- a/modules/core/src/main/java/org/apache/ignite/internal/processors/odbc/jdbc/JdbcConnectionContext.java
+++ b/modules/core/src/main/java/org/apache/ignite/internal/processors/odbc/jdbc/JdbcConnectionContext.java
@@ -38,10 +38,10 @@ public class JdbcConnectionContext implements ClientListenerConnectionContext {
private static final ClientListenerProtocolVersion VER_2_1_5 = ClientListenerProtocolVersion.create(2, 1, 5);
/** Version 2.3.1: added "multiple statements query" feature. */
- public static final ClientListenerProtocolVersion VER_2_3_1 = ClientListenerProtocolVersion.create(2, 3, 1);
+ public static final ClientListenerProtocolVersion VER_2_3_0 = ClientListenerProtocolVersion.create(2, 3, 0);
/** Current version. */
- private static final ClientListenerProtocolVersion CURRENT_VER = VER_2_3_1;
+ private static final ClientListenerProtocolVersion CURRENT_VER = VER_2_3_0;
/** Supported versions. */
private static final Set<ClientListenerProtocolVersion> SUPPORTED_VERS = new HashSet<>();
http://git-wip-us.apache.org/repos/asf/ignite/blob/c116bfc6/modules/core/src/main/java/org/apache/ignite/internal/processors/odbc/jdbc/JdbcMetaColumnsResult.java
----------------------------------------------------------------------
diff --git a/modules/core/src/main/java/org/apache/ignite/internal/processors/odbc/jdbc/JdbcMetaColumnsResult.java b/modules/core/src/main/java/org/apache/ignite/internal/processors/odbc/jdbc/JdbcMetaColumnsResult.java
index da270de..9931ce0 100644
--- a/modules/core/src/main/java/org/apache/ignite/internal/processors/odbc/jdbc/JdbcMetaColumnsResult.java
+++ b/modules/core/src/main/java/org/apache/ignite/internal/processors/odbc/jdbc/JdbcMetaColumnsResult.java
@@ -51,6 +51,25 @@ public class JdbcMetaColumnsResult extends JdbcResult {
}
/**
+ * Used by children classes.
+ * @param type Type ID.
+ */
+ protected JdbcMetaColumnsResult(byte type) {
+ super(type);
+ }
+
+ /**
+ * Used by children classes.
+ * @param type Type ID.
+ * @param meta Columns metadata.
+ */
+ protected JdbcMetaColumnsResult(byte type, Collection<JdbcColumnMeta> meta) {
+ super(type);
+
+ this.meta = new ArrayList<>(meta);
+ }
+
+ /**
* @return Columns metadata.
*/
public List<JdbcColumnMeta> meta() {
@@ -83,7 +102,7 @@ public class JdbcMetaColumnsResult extends JdbcResult {
meta = new ArrayList<>(size);
for (int i = 0; i < size; ++i) {
- JdbcColumnMeta m = new JdbcColumnMeta();
+ JdbcColumnMeta m = createMetaColumn();
m.readBinary(reader);
@@ -92,6 +111,13 @@ public class JdbcMetaColumnsResult extends JdbcResult {
}
}
+ /**
+ * @return Empty columns metadata to deserialization.
+ */
+ protected JdbcColumnMeta createMetaColumn() {
+ return new JdbcColumnMeta();
+ }
+
/** {@inheritDoc} */
@Override public String toString() {
return S.toString(JdbcMetaColumnsResult.class, this);
http://git-wip-us.apache.org/repos/asf/ignite/blob/c116bfc6/modules/core/src/main/java/org/apache/ignite/internal/processors/odbc/jdbc/JdbcMetaColumnsResultV2.java
----------------------------------------------------------------------
diff --git a/modules/core/src/main/java/org/apache/ignite/internal/processors/odbc/jdbc/JdbcMetaColumnsResultV2.java b/modules/core/src/main/java/org/apache/ignite/internal/processors/odbc/jdbc/JdbcMetaColumnsResultV2.java
new file mode 100644
index 0000000..2673a13
--- /dev/null
+++ b/modules/core/src/main/java/org/apache/ignite/internal/processors/odbc/jdbc/JdbcMetaColumnsResultV2.java
@@ -0,0 +1,50 @@
+/*
+ * 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.odbc.jdbc;
+
+import java.util.Collection;
+import org.apache.ignite.internal.util.typedef.internal.S;
+
+/**
+ * JDBC columns metadata result.
+ */
+public class JdbcMetaColumnsResultV2 extends JdbcMetaColumnsResult {
+ /**
+ * Default constructor is used for deserialization.
+ */
+ JdbcMetaColumnsResultV2() {
+ super(META_COLUMNS_V2);
+ }
+
+ /**
+ * @param meta Columns metadata.
+ */
+ JdbcMetaColumnsResultV2(Collection<JdbcColumnMeta> meta) {
+ super(META_COLUMNS_V2, meta);
+ }
+
+ /** {@inheritDoc} */
+ @Override protected JdbcColumnMeta createMetaColumn() {
+ return new JdbcColumnMetaV2();
+ }
+
+ /** {@inheritDoc} */
+ @Override public String toString() {
+ return S.toString(JdbcMetaColumnsResultV2.class, this);
+ }
+}
http://git-wip-us.apache.org/repos/asf/ignite/blob/c116bfc6/modules/core/src/main/java/org/apache/ignite/internal/processors/odbc/jdbc/JdbcRequestHandler.java
----------------------------------------------------------------------
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 202f813..166402f 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
@@ -23,6 +23,7 @@ import java.util.Arrays;
import java.util.Collection;
import java.util.Collections;
import java.util.HashSet;
+import java.util.LinkedHashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;
@@ -43,6 +44,7 @@ import org.apache.ignite.internal.processors.odbc.ClientListenerRequestHandler;
import org.apache.ignite.internal.processors.odbc.ClientListenerResponse;
import org.apache.ignite.internal.processors.odbc.odbc.OdbcQueryGetColumnsMetaRequest;
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.IgniteSQLException;
import org.apache.ignite.internal.processors.query.QueryUtils;
@@ -51,6 +53,7 @@ import org.apache.ignite.internal.util.typedef.F;
import org.apache.ignite.internal.util.typedef.internal.S;
import org.apache.ignite.internal.util.typedef.internal.U;
+import static org.apache.ignite.internal.processors.odbc.jdbc.JdbcConnectionContext.VER_2_3_0;
import static org.apache.ignite.internal.processors.odbc.jdbc.JdbcRequest.BATCH_EXEC;
import static org.apache.ignite.internal.processors.odbc.jdbc.JdbcRequest.META_COLUMNS;
import static org.apache.ignite.internal.processors.odbc.jdbc.JdbcRequest.META_INDEXES;
@@ -291,7 +294,7 @@ public class JdbcRequestHandler implements ClientListenerRequestHandler {
qry.setSchema(schemaName);
List<FieldsQueryCursor<List<?>>> results = ctx.query().querySqlFieldsNoCache(qry, true,
- protocolVer.compareTo(JdbcConnectionContext.VER_2_3_1) < 0);
+ protocolVer.compareTo(VER_2_3_0) < 0);
if (results.size() == 1) {
FieldsQueryCursor<List<?>> qryCur = results.get(0);
@@ -559,9 +562,10 @@ public class JdbcRequestHandler implements ClientListenerRequestHandler {
* @param req Get columns metadata request.
* @return Response.
*/
+ @SuppressWarnings("unchecked")
private JdbcResponse getColumnsMeta(JdbcMetaColumnsRequest req) {
try {
- Collection<JdbcColumnMeta> meta = new HashSet<>();
+ Collection<JdbcColumnMeta> meta = new LinkedHashSet<>();
for (String cacheName : ctx.cache().publicCacheNames()) {
for (GridQueryTypeDescriptor table : ctx.query().types(cacheName)) {
@@ -572,11 +576,22 @@ public class JdbcRequestHandler implements ClientListenerRequestHandler {
continue;
for (Map.Entry<String, Class<?>> field : table.fields().entrySet()) {
- if (!matches(field.getKey(), req.columnName()))
+ String colName = field.getKey();
+
+ if (!matches(colName, req.columnName()))
continue;
- JdbcColumnMeta columnMeta = new JdbcColumnMeta(table.schemaName(), table.tableName(),
- field.getKey(), field.getValue());
+ JdbcColumnMeta columnMeta;
+
+ if (protocolVer.compareTo(VER_2_3_0) >= 0) {
+ GridQueryProperty prop = table.property(colName);
+
+ columnMeta = new JdbcColumnMetaV2(table.schemaName(), table.tableName(),
+ field.getKey(), field.getValue(), !prop.notNull());
+ }
+ else
+ columnMeta = new JdbcColumnMeta(table.schemaName(), table.tableName(),
+ field.getKey(), field.getValue());
if (!meta.contains(columnMeta))
meta.add(columnMeta);
@@ -584,7 +599,12 @@ public class JdbcRequestHandler implements ClientListenerRequestHandler {
}
}
- JdbcMetaColumnsResult res = new JdbcMetaColumnsResult(meta);
+ JdbcMetaColumnsResult res;
+
+ if (protocolVer.compareTo(VER_2_3_0) >= 0)
+ res = new JdbcMetaColumnsResultV2(meta);
+ else
+ res = new JdbcMetaColumnsResult(meta);
return new JdbcResponse(res);
}
http://git-wip-us.apache.org/repos/asf/ignite/blob/c116bfc6/modules/core/src/main/java/org/apache/ignite/internal/processors/odbc/jdbc/JdbcResult.java
----------------------------------------------------------------------
diff --git a/modules/core/src/main/java/org/apache/ignite/internal/processors/odbc/jdbc/JdbcResult.java b/modules/core/src/main/java/org/apache/ignite/internal/processors/odbc/jdbc/JdbcResult.java
index c6c7438..6d460e6 100644
--- a/modules/core/src/main/java/org/apache/ignite/internal/processors/odbc/jdbc/JdbcResult.java
+++ b/modules/core/src/main/java/org/apache/ignite/internal/processors/odbc/jdbc/JdbcResult.java
@@ -59,6 +59,9 @@ public class JdbcResult implements JdbcRawBinarylizable {
/** Multiple statements query results. */
static final byte QRY_EXEC_MULT = 13;
+ /** Columns metadata result V2. */
+ static final byte META_COLUMNS_V2 = 14;
+
/** Success status. */
private byte type;
@@ -147,6 +150,11 @@ public class JdbcResult implements JdbcRawBinarylizable {
break;
+ case META_COLUMNS_V2:
+ res = new JdbcMetaColumnsResultV2();
+
+ break;
+
default:
throw new IgniteException("Unknown SQL listener request ID: [request ID=" + resId + ']');
}