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 4b3d155  IGNITE-13075 NPE on request JDBC metadata. (#7851)
4b3d155 is described below

commit 4b3d155f4f38f5cf0d520752a440cc43ebfe42cd
Author: korlov42 <kor...@gridgain.com>
AuthorDate: Fri May 29 16:25:33 2020 +0300

    IGNITE-13075 NPE on request JDBC metadata. (#7851)
---
 .../ignite/jdbc/thin/JdbcThinMetadataSelfTest.java | 105 +++++++++++++++++++++
 .../internal/processors/query/QueryUtils.java      |  26 ++---
 .../apache/ignite/internal/util/lang/GridFunc.java |  14 +++
 3 files changed, 126 insertions(+), 19 deletions(-)

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 e8aeb58..a2c1eff 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
@@ -62,7 +62,10 @@ import static java.sql.Types.VARCHAR;
 import static org.apache.ignite.cache.CacheMode.PARTITIONED;
 import static org.apache.ignite.cache.CacheWriteSynchronizationMode.FULL_SYNC;
 import static 
org.apache.ignite.internal.processors.query.QueryUtils.DFLT_SCHEMA;
+import static 
org.apache.ignite.internal.processors.query.QueryUtils.KEY_FIELD_NAME;
 import static 
org.apache.ignite.internal.processors.query.QueryUtils.SCHEMA_SYS;
+import static 
org.apache.ignite.internal.processors.query.QueryUtils.VAL_FIELD_NAME;
+import static org.apache.ignite.internal.util.lang.GridFunc.asMap;
 
 /**
  * Metadata tests.
@@ -204,6 +207,84 @@ public class JdbcThinMetadataSelfTest extends 
JdbcThinAbstractSelfTest {
     }
 
     /**
+     * Ensure metadata returned for cache without explicit query entities: <ul>
+     *     <li>create a cache with indexed types and without explicit query 
entities</li>
+     *     <li>request metadata for columns from the cache</li>
+     *     <li>verify returned result</li>
+     * </ul>
+     *
+     * @throws SQLException
+     */
+    @Test
+    public void testMetadataPresentedForAutogeneratedColumns() throws 
SQLException {
+        final String cacheName = "testCache";
+
+        IgniteCache<?, ?> cache = grid(0).createCache(
+            new CacheConfiguration<>(cacheName).setIndexedTypes(Integer.class, 
String.class)
+        );
+
+        try (Connection conn = DriverManager.getConnection(URL)) {
+            DatabaseMetaData meta = conn.getMetaData();
+
+            ResultSet rs = meta.getColumns(null, cacheName, null, null);
+
+            assertTrue(rs.next());
+            assertEquals(cacheName, 
rs.getString(MetadataColumn.TABLE_SCHEMA.columnName()));
+            assertEquals(KEY_FIELD_NAME, 
rs.getString(MetadataColumn.COLUMN_NAME.columnName()));
+
+            assertTrue(rs.next());
+            assertEquals(cacheName, 
rs.getString(MetadataColumn.TABLE_SCHEMA.columnName()));
+            assertEquals(VAL_FIELD_NAME, 
rs.getString(MetadataColumn.COLUMN_NAME.columnName()));
+
+            assertFalse(rs.next());
+        }
+        finally {
+            cache.destroy();
+        }
+    }
+
+    /**
+     * Ensure metadata returned for cache with explicit query entities has no 
duplicate columns: <ul>
+     *     <li>create a cache with indexed types and explicit query entity</li>
+     *     <li>request metadata for columns from the cache</li>
+     *     <li>verify returned result</li>
+     * </ul>
+     *
+     * @throws SQLException
+     */
+    @Test
+    public void testMetadataNotDublicatedIfFieldsSetExplicitly() throws 
SQLException {
+        final String cacheName = "testCache";
+
+        IgniteCache<?, ?> cache = grid(0).createCache(
+            new CacheConfiguration<>(cacheName)
+                .setQueryEntities(Collections.singleton(
+                    new QueryEntity()
+                        .setKeyType(Integer.class.getName())
+                        .setKeyFieldName("my_key")
+                        .setValueType(String.class.getName())
+                        .setFields(new LinkedHashMap<>(asMap("my_key", 
Integer.class.getName())))
+                ))
+                .setIndexedTypes(Integer.class, String.class)
+        );
+
+        try (Connection conn = DriverManager.getConnection(URL)) {
+            DatabaseMetaData meta = conn.getMetaData();
+
+            ResultSet rs = meta.getColumns(null, cacheName, null, null);
+
+            assertTrue(rs.next());
+            assertEquals(cacheName, 
rs.getString(MetadataColumn.TABLE_SCHEMA.columnName()));
+            assertEquals("MY_KEY", 
rs.getString(MetadataColumn.COLUMN_NAME.columnName()));
+
+            assertFalse(rs.next());
+        }
+        finally {
+            cache.destroy();
+        }
+    }
+
+    /**
      * @throws Exception If failed.
      */
     @Test
@@ -1341,4 +1422,28 @@ public class JdbcThinMetadataSelfTest extends 
JdbcThinAbstractSelfTest {
             this.name = name;
         }
     }
+
+    /** */
+    private enum MetadataColumn {
+        /** */
+        TABLE_SCHEMA("TABLE_SCHEM"),
+
+        /** */
+        COLUMN_NAME("COLUMN_NAME");
+
+        /** Column name. */
+        private final String colName;
+
+        /**
+         * @param colName Column name.
+         */
+        MetadataColumn(String colName) {
+            this.colName = colName;
+        }
+
+        /** */
+        public String columnName() {
+            return colName;
+        }
+    }
 }
diff --git 
a/modules/core/src/main/java/org/apache/ignite/internal/processors/query/QueryUtils.java
 
b/modules/core/src/main/java/org/apache/ignite/internal/processors/query/QueryUtils.java
index 8487d78..5edb492 100644
--- 
a/modules/core/src/main/java/org/apache/ignite/internal/processors/query/QueryUtils.java
+++ 
b/modules/core/src/main/java/org/apache/ignite/internal/processors/query/QueryUtils.java
@@ -625,25 +625,13 @@ public class QueryUtils {
         }
 
         // Sql-typed key/value doesn't have field property, but they may have 
precision and scale constraints.
-        String keyFieldName = qryEntity.getKeyFieldName();
+        // Also if fields are not set then _KEY and _VAL will be created as 
visible,
+        // so we have to add binary properties for them
+        if ((qryEntity.getKeyFieldName() == null && 
F.mapContainsKey(precision, KEY_FIELD_NAME)) || F.isEmpty(fields))
+            addKeyValueProperty(ctx, qryEntity, d, KEY_FIELD_NAME, true);
 
-        if (keyFieldName == null)
-            keyFieldName = KEY_FIELD_NAME;
-
-        if (!F.isEmpty(precision) && precision.containsKey(keyFieldName) &&
-            !fields.containsKey(keyFieldName)) {
-            addKeyValueValidationProperty(ctx, qryEntity, d, keyFieldName, 
true);
-        }
-
-        String valFieldName = qryEntity.getValueFieldName();
-
-        if (valFieldName == null)
-            valFieldName = VAL_FIELD_NAME;
-
-        if (!F.isEmpty(precision) && precision.containsKey(valFieldName) &&
-            !fields.containsKey(valFieldName)) {
-            addKeyValueValidationProperty(ctx, qryEntity, d, valFieldName, 
false);
-        }
+        if ((qryEntity.getValueFieldName() == null && 
F.mapContainsKey(precision, VAL_FIELD_NAME)) || F.isEmpty(fields))
+            addKeyValueProperty(ctx, qryEntity, d, VAL_FIELD_NAME, false);
 
         processIndexes(qryEntity, d);
     }
@@ -657,7 +645,7 @@ public class QueryUtils {
      * @param name Field name.
      * @throws IgniteCheckedException
      */
-    private static void addKeyValueValidationProperty(GridKernalContext ctx, 
QueryEntity qryEntity, QueryTypeDescriptorImpl d,
+    private static void addKeyValueProperty(GridKernalContext ctx, QueryEntity 
qryEntity, QueryTypeDescriptorImpl d,
         String name, boolean isKey) throws IgniteCheckedException {
 
         Map<String, Object> dfltVals = qryEntity.getDefaultFieldValues();
diff --git 
a/modules/core/src/main/java/org/apache/ignite/internal/util/lang/GridFunc.java 
b/modules/core/src/main/java/org/apache/ignite/internal/util/lang/GridFunc.java
index e8d156c..cb53ac4 100755
--- 
a/modules/core/src/main/java/org/apache/ignite/internal/util/lang/GridFunc.java
+++ 
b/modules/core/src/main/java/org/apache/ignite/internal/util/lang/GridFunc.java
@@ -2799,6 +2799,20 @@ public class GridFunc {
     }
 
     /**
+     * Checks if key is contained in the map passed in. If the map
+     * is {@code null}, then {@code false} is returned.
+     *
+     * @param m Map to check.
+     * @param k Key to check for containment.
+     * @param <T> Key type.
+     * @return {@code true} if map is not {@code null} and contains given
+     *      key, {@code false} otherwise.
+     */
+    public static <T> boolean mapContainsKey(@Nullable final Map<T, ?> m, 
final T k) {
+        return m != null && m.containsKey(k);
+    }
+
+    /**
      * Check's that {@code val} contains ignore case in collection {@code col}.
      *
      * @param col Collection of values.

Reply via email to