[ 
https://issues.apache.org/jira/browse/CALCITE-3506?page=com.atlassian.jira.plugin.system.issuetabpanels:comment-tabpanel&focusedCommentId=16975243#comment-16975243
 ] 

Josh Elser commented on CALCITE-3506:
-------------------------------------

I've spent some time messing around with this. TypedValue is a mess because 
it's trying to reconcile all of these different representations of the same 
data.

I can see the issue as you describe it, but the code snippet you suggest to add 
to TypedValueTest doesn't really test what the code itself is actually doing. 
It would be better to get a unit test reproducing the issue using a {{Frame}} 
or a real query. For example, the following test which I added to 
RemoteMetaTest.java passes without your change:
{code:java}
  @Test public void testFloats() throws Exception {
        final float floatValue = 3.14159f;
    ConnectionSpec.getDatabaseLock().lock();
    try (final Connection conn = DriverManager.getConnection(url);
        final Statement stmt = conn.createStatement()) {
      stmt.execute("DROP TABLE IF EXISTS testFloats");
      stmt.execute("CREATE TABLE testFloats(id integer primary key, f float)");
      try (final PreparedStatement pstmt = conn.prepareStatement("INSERT INTO 
testFloats values(?,?)")) {
        pstmt.setInt(1, 1);
        pstmt.setFloat(2, floatValue);
        assertEquals(1, pstmt.executeUpdate());
      }
      ResultSet results = stmt.executeQuery("SELECT * from testFloats");
      assertNotNull(results);
      assertTrue(results.next());
      assertEquals(1, results.getInt(1));
      float actual = results.getFloat(2);
      assertTrue("Expected float values to be equal, but was " + actual, 
floatValue == actual);
    } finally {
      ConnectionSpec.getDatabaseLock().unlock();
    }
  } {code}

> ClassCastException in TypedValue.writetoProtoWithType when a boxed Float is 
> used
> --------------------------------------------------------------------------------
>
>                 Key: CALCITE-3506
>                 URL: https://issues.apache.org/jira/browse/CALCITE-3506
>             Project: Calcite
>          Issue Type: Bug
>          Components: avatica
>    Affects Versions: avatica-1.12.0
>            Reporter: Enrique Saurez
>            Priority: Major
>
>  am using Apache Calcite-Avatica version 1.12 (but the relevant code
>  sections are not different from the master branch), and I am getting
>  the following exception on the client side (but the actual error in on
>  the server side):
> ||Exception||
> |org.apache.calcite.avatica.AvaticaSqlException: Error -1 (00000) :
>  Remote driver error: ClassCastException: java.lang.Long cannot be cast
>  to java.lang.Float
>          at org.apache.calcite.avatica.Helper.createException(Helper.java:54)
>          at org.apache.calcite.avatica.Helper.createException(Helper.java:41)
>          at 
> org.apache.calcite.avatica.AvaticaConnection.executeQueryInternal(AvaticaConnection.java:557)
>          at 
> org.apache.calcite.avatica.AvaticaPreparedStatement.executeQuery(AvaticaPreparedStatement.java:137)
>          at 
> com.oltpbenchmark.benchmarks.tpcc.procedures.Payment.getCustomerByName(Payment.java:400)
>          at 
> com.oltpbenchmark.benchmarks.tpcc.procedures.Payment.run(Payment.java:221)
>          at 
> com.oltpbenchmark.benchmarks.tpcc.TPCCWorker.executeWork(TPCCWorker.java:74)
>          at com.oltpbenchmark.api.Worker.doWork(Worker.java:386)
>          at com.oltpbenchmark.api.Worker.run(Worker.java:296)
>          at java.lang.Thread.run(Thread.java:748)
>  java.lang.ClassCastException: java.lang.Long cannot be cast to 
> java.lang.Float
>          at 
> org.apache.calcite.avatica.remote.TypedValue.writeToProtoWithType(TypedValue.java:594)
>          at 
> org.apache.calcite.avatica.remote.TypedValue.toProto(TypedValue.java:799)
>          at 
> org.apache.calcite.avatica.Meta$Frame.serializeScalar(Meta.java:985)
>          at org.apache.calcite.avatica.Meta$Frame.parseColumn(Meta.java:971)
>          at org.apache.calcite.avatica.Meta$Frame.toProto(Meta.java:936)
>          at 
> org.apache.calcite.avatica.remote.Service$ResultSetResponse.serialize(Service.java:841)
>          at 
> org.apache.calcite.avatica.remote.Service$ExecuteResponse.serialize(Service.java:1158)
>          at 
> org.apache.calcite.avatica.remote.Service$ExecuteResponse.serialize(Service.java:1113)
>          at 
> org.apache.calcite.avatica.remote.ProtobufTranslationImpl.serializeResponse(ProtobufTranslationImpl.java:348)
>          at 
> org.apache.calcite.avatica.remote.ProtobufHandler.encode(ProtobufHandler.java:57)
>          at 
> org.apache.calcite.avatica.remote.ProtobufHandler.encode(ProtobufHandler.java:31)
>          at 
> org.apache.calcite.avatica.remote.AbstractHandler.apply(AbstractHandler.java:95)
>          at 
> org.apache.calcite.avatica.remote.ProtobufHandler.apply(ProtobufHandler.java:46)
>          at 
> org.apache.calcite.avatica.server.AvaticaProtobufHandler.handle(AvaticaProtobufHandler.java:127)
>          at 
> org.eclipse.jetty.server.handler.HandlerList.handle(HandlerList.java:52)
>          at 
> org.eclipse.jetty.server.handler.HandlerWrapper.handle(HandlerWrapper.java:97)
>          at org.eclipse.jetty.server.Server.handle(Server.java:499)
>          at org.eclipse.jetty.server.HttpChannel.handle(HttpChannel.java:311)
>          at 
> org.eclipse.jetty.server.HttpConnection.onFillable(HttpConnection.java:257)
>          at 
> [org.eclipse.jetty.io|http://org.eclipse.jetty.io/].AbstractConnection$2.run(AbstractConnection.java:544)
>          at 
> org.eclipse.jetty.util.thread.QueuedThreadPool.runJob(QueuedThreadPool.java:635)
>          at 
> org.eclipse.jetty.util.thread.QueuedThreadPool$3.run(QueuedThreadPool.java:555)
>          at java.lang.Thread.run(Thread.java:748)|
> From the code, it seems like when the function "writeToProtoWithType"
>  is called from "toProto", there is a boxing conversion from long
>  (primitive) to Long (object), this is because
>  for floats, "toProto" is using "((Float) o).longValue()" which returns
>  a long. Then in "writeToProtoWithType" is being casted to float, which
>  I think causes the CastClassException.
> If I add this code to the testFloat() function in the
>  "core/src/test/java/org/apache/calcite/avatica/remote/TypedValueTest.java"
>  file:
> {code:java}
> Common.TypedValue.Builder builder = Common.TypedValue.newBuilder();
>  Common.Rep val = TypedValue.toProto(builder, Float.valueOf(3.14159f));
>  Common.TypedValue typedVal = builder.build();{code}
>  
> it replicates the exception. I am not sure why are you using the longValue() 
> on the float within the toProto function? Doesn't this cast lose information? 
> Please let me know if you need any more information. I send an email to the 
> dev mailing list, but somebody suggested to create the issue here.
> Thanks a lot for help!



--
This message was sent by Atlassian Jira
(v8.3.4#803005)

Reply via email to