You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@geode.apache.org by ds...@apache.org on 2019/01/23 01:13:13 UTC

[geode] branch feature/GEODE-6291 updated: implemented computeFieldType WIP: still need testing of precondition function WIP: still need describe to show the field mappings

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

dschneider pushed a commit to branch feature/GEODE-6291
in repository https://gitbox.apache.org/repos/asf/geode.git


The following commit(s) were added to refs/heads/feature/GEODE-6291 by this push:
     new 0181f4d  implemented computeFieldType WIP: still need testing of precondition function WIP: still need describe to show the field mappings
0181f4d is described below

commit 0181f4d420fe09b80422f90c13b74007f884b2bf
Author: Darrel Schneider <ds...@pivotal.io>
AuthorDate: Tue Jan 22 17:11:56 2019 -0800

    implemented computeFieldType
    WIP: still need testing of precondition function
    WIP: still need describe to show the field mappings
---
 .../jdbc/internal/cli/CreateMappingCommand.java    |   8 +-
 .../CreateMappingPreconditionCheckFunction.java    | 261 ++++++++++++++-------
 .../internal/cli/CreateMappingCommandTest.java     |  22 +-
 3 files changed, 203 insertions(+), 88 deletions(-)

diff --git a/geode-connectors/src/main/java/org/apache/geode/connectors/jdbc/internal/cli/CreateMappingCommand.java b/geode-connectors/src/main/java/org/apache/geode/connectors/jdbc/internal/cli/CreateMappingCommand.java
index 3010ba8..6a0966f 100644
--- a/geode-connectors/src/main/java/org/apache/geode/connectors/jdbc/internal/cli/CreateMappingCommand.java
+++ b/geode-connectors/src/main/java/org/apache/geode/connectors/jdbc/internal/cli/CreateMappingCommand.java
@@ -131,8 +131,12 @@ public class CreateMappingCommand extends SingleGfshCommand {
         executeFunctionAndGetFunctionResult(new CreateMappingPreconditionCheckFunction(), mapping,
             targetMembers.iterator().next());
     if (preconditionCheckResult.isSuccessful()) {
-      ArrayList<FieldMapping> fieldMappings =
-          (ArrayList<FieldMapping>) preconditionCheckResult.getResultObject();
+      Object[] preconditionOutput = (Object[]) preconditionCheckResult.getResultObject();
+      String computedIds = (String) preconditionOutput[0];
+      if (computedIds != null) {
+        mapping.setIds(computedIds);
+      }
+      ArrayList<FieldMapping> fieldMappings = (ArrayList<FieldMapping>) preconditionOutput[1];
       for (FieldMapping fieldMapping : fieldMappings) {
         mapping.addFieldMapping(fieldMapping);
       }
diff --git a/geode-connectors/src/main/java/org/apache/geode/connectors/jdbc/internal/cli/CreateMappingPreconditionCheckFunction.java b/geode-connectors/src/main/java/org/apache/geode/connectors/jdbc/internal/cli/CreateMappingPreconditionCheckFunction.java
index d171f03..e863432 100644
--- a/geode-connectors/src/main/java/org/apache/geode/connectors/jdbc/internal/cli/CreateMappingPreconditionCheckFunction.java
+++ b/geode-connectors/src/main/java/org/apache/geode/connectors/jdbc/internal/cli/CreateMappingPreconditionCheckFunction.java
@@ -16,7 +16,9 @@ package org.apache.geode.connectors.jdbc.internal.cli;
 
 import java.sql.Connection;
 import java.sql.JDBCType;
+import java.sql.SQLException;
 import java.util.ArrayList;
+import java.util.List;
 
 import javax.sql.DataSource;
 
@@ -57,107 +59,196 @@ public class CreateMappingPreconditionCheckFunction extends CliFunction<RegionMa
           new TableMetaDataManager().getTableMetaDataView(connection, regionMapping);
       PdxInstanceFactory pdxInstanceFactory =
           context.getCache().createPdxInstanceFactory(regionMapping.getPdxName());
+      Object[] output = new Object[2];
       ArrayList<FieldMapping> fieldMappings = new ArrayList<>();
+      output[1] = fieldMappings;
       for (String jdbcName : tableMetaData.getColumnNames()) {
         boolean isNullable = tableMetaData.isColumnNullable(jdbcName);
         JDBCType jdbcType = tableMetaData.getColumnDataType(jdbcName);
         String pdxName = jdbcName;
+        // TODO: look for existing pdx types to picked pdxName
+        // It seems very unlikely that when a mapping is being
+        // created that a pdx type will already exist. So I'm not
+        // sure trying to look for an existing type is worth the effort.
+        // But that does mean that the pdx field name will always be the
+        // same as the column name. If we added a gfsh command that allowed
+        // you to create a pdx type (pretty easy to implement using PdxInstanceFactory)
+        // then it would be much more likely that a pdx type could exist
+        // when the mapping is created. In that case we should then do
+        // some extra work here to look at existing types.
         FieldType pdxType = computeFieldType(isNullable, jdbcType);
         pdxInstanceFactory.writeField(pdxName, null, pdxType.getFieldClass());
         fieldMappings.add(new FieldMapping(pdxName, pdxType.name(), jdbcName, jdbcType.getName()));
       }
       PdxInstance pdxInstance = pdxInstanceFactory.create();
-      // TODO look for existing PdxType in the registry whose names differ in case
-      // TODO use this code when we create the field mapping
-      // Set<String> columnNames = tableMetaDataView.getColumnNames();
-      // if (columnNames.contains(fieldName)) {
-      // return fieldName;
-      // }
-      //
-      // List<String> ignoreCaseMatch = columnNames.stream().filter(c ->
-      // c.equalsIgnoreCase(fieldName))
-      // .collect(Collectors.toList());
-      // if (ignoreCaseMatch.size() > 1) {
-      // throw new JdbcConnectorException(
-      // "The SQL table has at least two columns that match the PDX field: " + fieldName);
-      // }
-      //
-      // if (ignoreCaseMatch.size() == 1) {
-      // return ignoreCaseMatch.get(0);
-      // }
-      //
-      // // there is no match either in the configured mapping or the table columns
-      // return fieldName;
-
-      // TODO use the following code when we create the mapping
-      // Set<PdxType> pdxTypes = getPdxTypesForClassName(typeRegistry);
-      // String fieldName = findExactMatch(columnName, pdxTypes);
-      // if (fieldName == null) {
-      // fieldName = findCaseInsensitiveMatch(columnName, pdxTypes);
-      // }
-      // return fieldName;
-
-      // private Set<PdxType> getPdxTypesForClassName(TypeRegistry typeRegistry) {
-      // Set<PdxType> pdxTypes = typeRegistry.getPdxTypesForClassName(getPdxName());
-      // if (pdxTypes.isEmpty()) {
-      // throw new JdbcConnectorException(
-      // "The class " + getPdxName() + " has not been pdx serialized.");
-      // }
-      // return pdxTypes;
-      // }
-
-      // /**
-      // * Given a column name and a set of pdx types, find the field name in those types that
-      // match,
-      // * ignoring case, the column name.
-      // *
-      // * @return the matching field name or null if no match
-      // * @throws JdbcConnectorException if no fields match
-      // * @throws JdbcConnectorException if more than one field matches
-      // */
-      // private String findCaseInsensitiveMatch(String columnName, Set<PdxType> pdxTypes) {
-      // HashSet<String> matchingFieldNames = new HashSet<>();
-      // for (PdxType pdxType : pdxTypes) {
-      // for (String existingFieldName : pdxType.getFieldNames()) {
-      // if (existingFieldName.equalsIgnoreCase(columnName)) {
-      // matchingFieldNames.add(existingFieldName);
-      // }
-      // }
-      // }
-      // if (matchingFieldNames.isEmpty()) {
-      // throw new JdbcConnectorException("The class " + getPdxName()
-      // + " does not have a field that matches the column " + columnName);
-      // } else if (matchingFieldNames.size() > 1) {
-      // throw new JdbcConnectorException(
-      // "Could not determine what pdx field to use for the column name " + columnName
-      // + " because the pdx fields " + matchingFieldNames + " all match it.");
-      // }
-      // return matchingFieldNames.iterator().next();
-      // }
-      //
-      // /**
-      // * Given a column name, search the given pdxTypes for a field whose name exactly matches the
-      // * column name.
-      // *
-      // * @return the matching field name or null if no match
-      // */
-      // private String findExactMatch(String columnName, Set<PdxType> pdxTypes) {
-      // for (PdxType pdxType : pdxTypes) {
-      // if (pdxType.getPdxField(columnName) != null) {
-      // return columnName;
-      // }
-      // }
-      // return null;
-      // }
+      if (regionMapping.getIds() == null || regionMapping.getIds().isEmpty()) {
+        List<String> keyColummnNames = tableMetaData.getKeyColumnNames();
+        output[0] = String.join(",", keyColummnNames);
+      }
 
       String member = context.getMemberName();
-      return new CliFunctionResult(member, fieldMappings);
+      return new CliFunctionResult(member, output);
+    } catch (SQLException e) {
+      throw JdbcConnectorException.createException(e);
     }
   }
 
   private FieldType computeFieldType(boolean isNullable, JDBCType jdbcType) {
-    // TODO Auto-generated method stub
-    return null;
+    switch (jdbcType) {
+      case BIT: // 1 bit
+        return computeType(isNullable, FieldType.BOOLEAN);
+      case TINYINT: // unsigned 8 bits
+        return computeType(isNullable, FieldType.SHORT);
+      case SMALLINT: // signed 16 bits
+        return computeType(isNullable, FieldType.SHORT);
+      case INTEGER: // signed 32 bits
+        return computeType(isNullable, FieldType.INT);
+      case BIGINT: // signed 64 bits
+        return computeType(isNullable, FieldType.LONG);
+      case FLOAT:
+        return computeType(isNullable, FieldType.DOUBLE);
+      case REAL:
+        return computeType(isNullable, FieldType.FLOAT);
+      case DOUBLE:
+        return computeType(isNullable, FieldType.DOUBLE);
+      case NUMERIC:
+        return FieldType.OBJECT;
+      case DECIMAL:
+        return FieldType.OBJECT;
+      case CHAR:
+        return FieldType.STRING;
+      case VARCHAR:
+        return FieldType.STRING;
+      case LONGVARCHAR:
+        return FieldType.STRING;
+      case DATE:
+        return computeDate(isNullable);
+      case TIME:
+        return computeDate(isNullable);
+      case TIMESTAMP:
+        return computeDate(isNullable);
+      case BINARY:
+        return FieldType.BYTE_ARRAY;
+      case VARBINARY:
+        return FieldType.BYTE_ARRAY;
+      case LONGVARBINARY:
+        return FieldType.BYTE_ARRAY;
+      case NULL:
+        throw new IllegalStateException("unexpected NULL jdbc column type");
+      case OTHER:
+        return FieldType.OBJECT;
+      case JAVA_OBJECT:
+        return FieldType.OBJECT;
+      case DISTINCT:
+        return FieldType.OBJECT;
+      case STRUCT:
+        return FieldType.OBJECT;
+      case ARRAY:
+        return FieldType.OBJECT;
+      case BLOB:
+        return FieldType.BYTE_ARRAY;
+      case CLOB:
+        return FieldType.OBJECT;
+      case REF:
+        return FieldType.OBJECT;
+      case DATALINK:
+        return FieldType.OBJECT;
+      case BOOLEAN:
+        return computeType(isNullable, FieldType.BOOLEAN);
+      case ROWID:
+        return FieldType.OBJECT;
+      case NCHAR:
+        return FieldType.STRING;
+      case NVARCHAR:
+        return FieldType.STRING;
+      case LONGNVARCHAR:
+        return FieldType.STRING;
+      case NCLOB:
+        return FieldType.OBJECT;
+      case SQLXML:
+        return FieldType.OBJECT;
+      case REF_CURSOR:
+        return FieldType.OBJECT;
+      case TIME_WITH_TIMEZONE:
+        return computeDate(isNullable);
+      case TIMESTAMP_WITH_TIMEZONE:
+        return computeDate(isNullable);
+      default:
+        return FieldType.OBJECT;
+    }
+  }
+
+  private FieldType computeType(boolean isNullable, FieldType nonNullType) {
+    if (isNullable) {
+      return FieldType.OBJECT;
+    }
+    return nonNullType;
+
   }
 
+  private FieldType computeDate(boolean isNullable) {
+    return computeType(isNullable, FieldType.DATE);
+  }
+
+  // Set<PdxType> pdxTypes = getPdxTypesForClassName(typeRegistry);
+  // String fieldName = findExactMatch(columnName, pdxTypes);
+  // if (fieldName == null) {
+  // fieldName = findCaseInsensitiveMatch(columnName, pdxTypes);
+  // }
+  // return fieldName;
+
+  // private Set<PdxType> getPdxTypesForClassName(TypeRegistry typeRegistry) {
+  // Set<PdxType> pdxTypes = typeRegistry.getPdxTypesForClassName(getPdxName());
+  // if (pdxTypes.isEmpty()) {
+  // throw new JdbcConnectorException(
+  // "The class " + getPdxName() + " has not been pdx serialized.");
+  // }
+  // return pdxTypes;
+  // }
+
+  // /**
+  // * Given a column name and a set of pdx types, find the field name in those types that
+  // match,
+  // * ignoring case, the column name.
+  // *
+  // * @return the matching field name or null if no match
+  // * @throws JdbcConnectorException if no fields match
+  // * @throws JdbcConnectorException if more than one field matches
+  // */
+  // private String findCaseInsensitiveMatch(String columnName, Set<PdxType> pdxTypes) {
+  // HashSet<String> matchingFieldNames = new HashSet<>();
+  // for (PdxType pdxType : pdxTypes) {
+  // for (String existingFieldName : pdxType.getFieldNames()) {
+  // if (existingFieldName.equalsIgnoreCase(columnName)) {
+  // matchingFieldNames.add(existingFieldName);
+  // }
+  // }
+  // }
+  // if (matchingFieldNames.isEmpty()) {
+  // throw new JdbcConnectorException("The class " + getPdxName()
+  // + " does not have a field that matches the column " + columnName);
+  // } else if (matchingFieldNames.size() > 1) {
+  // throw new JdbcConnectorException(
+  // "Could not determine what pdx field to use for the column name " + columnName
+  // + " because the pdx fields " + matchingFieldNames + " all match it.");
+  // }
+  // return matchingFieldNames.iterator().next();
+  // }
+  //
+  // /**
+  // * Given a column name, search the given pdxTypes for a field whose name exactly matches the
+  // * column name.
+  // *
+  // * @return the matching field name or null if no match
+  // */
+  // private String findExactMatch(String columnName, Set<PdxType> pdxTypes) {
+  // for (PdxType pdxType : pdxTypes) {
+  // if (pdxType.getPdxField(columnName) != null) {
+  // return columnName;
+  // }
+  // }
+  // return null;
+  // }
+
+
 }
diff --git a/geode-connectors/src/test/java/org/apache/geode/connectors/jdbc/internal/cli/CreateMappingCommandTest.java b/geode-connectors/src/test/java/org/apache/geode/connectors/jdbc/internal/cli/CreateMappingCommandTest.java
index 46dd01d..6c90302 100644
--- a/geode-connectors/src/test/java/org/apache/geode/connectors/jdbc/internal/cli/CreateMappingCommandTest.java
+++ b/geode-connectors/src/test/java/org/apache/geode/connectors/jdbc/internal/cli/CreateMappingCommandTest.java
@@ -62,6 +62,7 @@ public class CreateMappingCommandTest {
   private Set<InternalDistributedMember> members;
   private CliFunctionResult preconditionCheckResults;
   private ArrayList<FieldMapping> fieldMappings = new ArrayList<>();
+  private Object[] preconditionOutput = new Object[] {null, fieldMappings};
   private List<CliFunctionResult> results;
   private CliFunctionResult successFunctionResult;
   private RegionMapping mapping;
@@ -86,7 +87,7 @@ public class CreateMappingCommandTest {
     when(successFunctionResult.isSuccessful()).thenReturn(true);
     preconditionCheckResults = mock(CliFunctionResult.class);
     when(preconditionCheckResults.isSuccessful()).thenReturn(true);
-    when(preconditionCheckResults.getResultObject()).thenReturn(fieldMappings);
+    when(preconditionCheckResults.getResultObject()).thenReturn(preconditionOutput);
     doReturn(preconditionCheckResults).when(createRegionMappingCommand)
         .executeFunctionAndGetFunctionResult(any(), any(), any());
     doReturn(results).when(createRegionMappingCommand).executeAndGetFunctionResult(any(), any(),
@@ -166,6 +167,25 @@ public class CreateMappingCommandTest {
   }
 
   @Test
+  public void createsMappingReturnsRegionMappingWithComputedIds() {
+    setupRequiredPreconditions();
+    results.add(successFunctionResult);
+    String ids = "does not matter";
+    String catalog = "catalog";
+    String schema = "schema";
+    String computedIds = "id1,id2";
+    preconditionOutput[0] = computedIds;
+
+    ResultModel result = createRegionMappingCommand.createMapping(regionName, dataSourceName,
+        tableName, pdxClass, false, ids, catalog, schema);
+
+    assertThat(result.getStatus()).isSameAs(Result.Status.OK);
+    Object[] results = (Object[]) result.getConfigObject();
+    RegionMapping regionMapping = (RegionMapping) results[0];
+    assertThat(regionMapping.getIds()).isEqualTo(computedIds);
+  }
+
+  @Test
   public void createsMappingReturnsErrorIfPreconditionCheckErrors() {
     setupRequiredPreconditions();
     results.add(successFunctionResult);