[ https://issues.apache.org/jira/browse/HIVE-21964?page=com.atlassian.jira.plugin.system.issuetabpanels:comment-tabpanel&focusedCommentId=17199318#comment-17199318 ]
chenruotao edited comment on HIVE-21964 at 9/21/20, 10:35 AM: -------------------------------------------------------------- I has the same problem like this, but not Decimal. the type of date and timestramp would throw the same exception when job running, so I do not use the type provided by hive(org.apache.hadoop.hive.common.type), and it worked. the code like this : case DATE: // if (rowVal instanceof java.sql.Date){ // LocalDate localDate = ((java.sql.Date) rowVal).toLocalDate(); //rowVal=Date.of(localDate.getYear(),localDate.getMonthValue(),localDate.getDayOfMonth(); // }else{ // rowVal = Date.valueOf (rowVal.toString()); // } rowVal = Date.valueOf (rowVal.toString()); break; case TIMESTAMP: // if (rowVal instanceof java.sql.Timestamp){ // LocalDateTime localDateTime = ((java.sql.Timestamp) rowVal).toLocalDateTime(); //rowVal=Timestamp.ofEpochSecond(localDateTime.toEpochSecond(UTC),localDateTime.geNano()); // }else{ // rowVal = Timestamp.valueOf (rowVal.toString()); // } rowVal = Timestamp.valueOf (rowVal.toString()); was (Author: chenruotao): I has the same problem like this, but not Decimal. the type of date and timestramp would throw the same exception when job running, so I do not use the type provided by hive(org.apache.hadoop.hive.common.type), and it worked. the code like this : case DATE: // if (rowVal instanceof java.sql.Date) { // LocalDate localDate = ((java.sql.Date) rowVal).toLocalDate(); // rowVal = Date.of(localDate.getYear(), localDate.getMonthValue(), localDate.getDayOfMonth()); // } else { // rowVal = Date.valueOf (rowVal.toString()); // } rowVal = Date.valueOf (rowVal.toString()); break; case TIMESTAMP: // if (rowVal instanceof java.sql.Timestamp) { // LocalDateTime localDateTime = ((java.sql.Timestamp) rowVal).toLocalDateTime(); // rowVal = Timestamp.ofEpochSecond(localDateTime.toEpochSecond(UTC), localDateTime.getNano()); // } else { // rowVal = Timestamp.valueOf (rowVal.toString()); // } rowVal = Timestamp.valueOf (rowVal.toString()); > jdbc handler class cast exception > --------------------------------- > > Key: HIVE-21964 > URL: https://issues.apache.org/jira/browse/HIVE-21964 > Project: Hive > Issue Type: Improvement > Components: JDBC > Affects Versions: 3.1.1 > Reporter: Aloys Zhang > Priority: Major > > Using hive jdbc handler to query external mysql data source with type decimal > type, it throws class cast Exception : > > {code:java} > 2019-07-08T11:11:50,424 ERROR [7787918f-3111-4706-a3b3-0097fa1bc117 main] > CliDriver: Failed with exception > java.io.IOException:org.apache.hadoop.hive.ql.metadata.HiveException: > java.lang.ClassCastException: java.math.BigDecimal cannot be cast to > org.apache.hadoop.hive.common.type.HiveDecimal > java.io.IOException: org.apache.hadoop.hive.ql.metadata.HiveException: > java.lang.ClassCastException: java.math.BigDecimal cannot be cast to > org.apache.hadoop.hive.common.type.HiveDecimal > at org.apache.hadoop.hive.ql.exec.FetchTask.fetch(FetchTask.java:162) > at org.apache.hadoop.hive.ql.Driver.getResults(Driver.java:2691) > at > org.apache.hadoop.hive.ql.reexec.ReExecDriver.getResults(ReExecDriver.java:229) > at org.apache.hadoop.hive.cli.CliDriver.processLocalCmd(CliDriver.java:259) > at org.apache.hadoop.hive.cli.CliDriver.processCmd(CliDriver.java:188) > at org.apache.hadoop.hive.cli.CliDriver.processLine(CliDriver.java:402) > at org.apache.hadoop.hive.cli.CliDriver.executeDriver(CliDriver.java:821) > at org.apache.hadoop.hive.cli.CliDriver.run(CliDriver.java:759) > at org.apache.hadoop.hive.cli.CliDriver.main(CliDriver.java:683) > at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method) > at > sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62) > at > sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43) > at java.lang.reflect.Method.invoke(Method.java:498) > at org.apache.hadoop.util.RunJar.run(RunJar.java:226) > at org.apache.hadoop.util.RunJar.main(RunJar.java:141) > Caused by: org.apache.hadoop.hive.ql.metadata.HiveException: > java.lang.ClassCastException: java.math.BigDecimal cannot be cast to > org.apache.hadoop.hive.common.type.HiveDecimal > at > org.apache.hadoop.hive.ql.exec.ListSinkOperator.process(ListSinkOperator.java:98) > at org.apache.hadoop.hive.ql.exec.Operator.baseForward(Operator.java:995) > at org.apache.hadoop.hive.ql.exec.Operator.forward(Operator.java:941) > at org.apache.hadoop.hive.ql.exec.Operator.forward(Operator.java:928) > at > org.apache.hadoop.hive.ql.exec.SelectOperator.process(SelectOperator.java:95) > at org.apache.hadoop.hive.ql.exec.Operator.baseForward(Operator.java:995) > at org.apache.hadoop.hive.ql.exec.Operator.forward(Operator.java:941) > at > org.apache.hadoop.hive.ql.exec.TableScanOperator.process(TableScanOperator.java:125) > at > org.apache.hadoop.hive.ql.exec.FetchOperator.pushRow(FetchOperator.java:519) > at > org.apache.hadoop.hive.ql.exec.FetchOperator.pushRow(FetchOperator.java:511) > at org.apache.hadoop.hive.ql.exec.FetchTask.fetch(FetchTask.java:146) > ... 14 more > Caused by: java.lang.ClassCastException: java.math.BigDecimal cannot be cast > to org.apache.hadoop.hive.common.type.HiveDecimal > at > org.apache.hadoop.hive.serde2.objectinspector.primitive.JavaHiveDecimalObjectInspector.getPrimitiveJavaObject(JavaHiveDecimalObjectInspector.java:55) > at > org.apache.hadoop.hive.serde2.lazy.LazyUtils.writePrimitiveUTF8(LazyUtils.java:329) > at > org.apache.hadoop.hive.serde2.lazy.LazySimpleSerDe.serialize(LazySimpleSerDe.java:292) > at > org.apache.hadoop.hive.serde2.lazy.LazySimpleSerDe.serializeField(LazySimpleSerDe.java:247) > at > org.apache.hadoop.hive.serde2.DelimitedJSONSerDe.serializeField(DelimitedJSONSerDe.java:72) > at > org.apache.hadoop.hive.serde2.lazy.LazySimpleSerDe.doSerialize(LazySimpleSerDe.java:231) > at > org.apache.hadoop.hive.serde2.AbstractEncodingAwareSerDe.serialize(AbstractEncodingAwareSerDe.java:55) > at > org.apache.hadoop.hive.serde2.DefaultFetchFormatter.convert(DefaultFetchFormatter.java:67) > at > org.apache.hadoop.hive.serde2.DefaultFetchFormatter.convert(DefaultFetchFormatter.java:36) > at > org.apache.hadoop.hive.ql.exec.ListSinkOperator.process(ListSinkOperator.java:94) > ... 24 more > {code} > Same problem with type date and timestamp. > > I debug the code and find that was caused by hive-jdbc-handler return > result wity type > java.math.Decimal , but when serialize the result row by calling > JavaHiveDecimalObjectInspector#getPrimitiveJavaObject , java.math.Decimal > cann't cast to org.apache.hadoop.hive.common.type.HiveDecimal. > So, IMO, this is a bug in jdbc-handler code when processing decimal, date and > timestamp teyps. I think jdbc-handler should return result with type cast > like this : > {code:java} > @Override > public Map<String, Object> next() { > try { > ResultSetMetaData metadata = rs.getMetaData(); > int numColumns = metadata.getColumnCount(); > Map<String, Object> record = new HashMap<String, Object>(numColumns); > for (int i = 0; i < numColumns; i++) { > String key = metadata.getColumnName(i + 1); > Object value; > if (columnTypes!=null && columnTypes.get(i) instanceof > PrimitiveTypeInfo) { > // This is not a complete list, barely make information schema work > switch (((PrimitiveTypeInfo)columnTypes.get(i)).getTypeName()) { > case "int": > case "smallint": > case "tinyint": > value = rs.getInt(i + 1); > break; > case "bigint": > value = rs.getLong(i + 1); > break; > case "float": > value = rs.getFloat(i + 1); > break; > case "double": > value = rs.getDouble(i + 1); > break; > case "decimal": > case "bigdecimal": > value = HiveDecimal.create(rs.getBigDecimal(i + 1)); > break; > case "boolean": > value = rs.getBoolean(i + 1); > break; > case "string": > case "char": > case "varchar": > value = rs.getString(i + 1); > break; > case "date": > case "datetime": > value = new Date(rs.getDate(i + 1).toLocalDate()); > break; > case "timestamp": > value = new Timestamp((rs.getTimestamp(i + 1)).toLocalDateTime()); > break; > default: > value = rs.getObject(i + 1); > break; > } > } else { > value = rs.getObject(i + 1); > } > record.put(key, value); > } > return record; > } > catch (Exception e) { > LOGGER.warn("next() threw exception", e); > return null; > } > } > {code} > I want to know whether this change has other effects or not . > Any suggestions are appreciated. -- This message was sent by Atlassian Jira (v8.3.4#803005)