deephaven / deephaven-core

Deephaven Community Core
Other
254 stars 80 forks source link

groovy with leftover python syntax has a painfully obfuscated error message #3569

Open rachelmbrubaker opened 1 year ago

rachelmbrubaker commented 1 year ago

Description

Groovy with leftover python syntax has a painfully obfuscated error message. The use case is common... though potentially for internal users only (prod support), so pulling this issue out separately to allow for lower-priority triaging.

justification for frequent annoyance/inefficiency support/qa workflow:

  1. doing a thing in python
  2. hit an error
  3. convert to groovy (in an effort to debug, seeing if it is a python-only bug or also exists in groovy)
  4. miss some [ and ] syntax to remove during the conversion
  5. get an obfuscated error message

Steps to reproduce In a groovy DnD console

t = db.historicalTable("LearnDeephaven", "StockTrades").where("Date=`2017-08-25`").update("Price=Last").sort("Timestamp")

myTrades = t.where("Exchange=`Nasdaq`").update("Price=Last")

j1 = myTrades.aj(t, "Timestamp=Timestamp", "PriceBeforeMyTrade=Price").view(["Sym", "Price", "PriceBeforeMyTrade", "Timestamp"])

Expected results

An error message indicating that there should not be an array input to the view method. Items to potentially highlight:

Actual results

java.lang.ClassCastException: class java.lang.String cannot be cast to class io.deephaven.api.Selectable (java.lang.String is in module java.base of loader 'bootstrap'; io.deephaven.api.Selectable is in unnamed module of loader 'app')
        at java.util.stream.ReferencePipeline$3$1.accept(ReferencePipeline.java:197)
        at java.util.ArrayList$ArrayListSpliterator.forEachRemaining(ArrayList.java:1625)
        at java.util.stream.AbstractPipeline.copyInto(AbstractPipeline.java:509)
        at java.util.stream.AbstractPipeline.wrapAndCopyInto(AbstractPipeline.java:499)
        at java.util.stream.AbstractPipeline.evaluate(AbstractPipeline.java:575)
        at java.util.stream.AbstractPipeline.evaluateToArrayNode(AbstractPipeline.java:260)
        at java.util.stream.ReferencePipeline.toArray(ReferencePipeline.java:616)
        at io.deephaven.engine.table.impl.select.SelectColumn.from(SelectColumn.java:35)
        at io.deephaven.engine.table.impl.QueryTable.view(QueryTable.java:1350)
        at io.deephaven.engine.table.impl.QueryTable.view(QueryTable.java:100)
        at io.deephaven.api.TableOperations$view.call(null:-1)
        at org.codehaus.groovy.runtime.callsite.CallSiteArray.defaultCall(CallSiteArray.java:47)
        at org.codehaus.groovy.runtime.callsite.AbstractCallSite.call(AbstractCallSite.java:125)
        at org.codehaus.groovy.runtime.callsite.AbstractCallSite.call(AbstractCallSite.java:139)
        at io.deephaven.dynamic.Script_22.run(Script_22.groovy:44)
        at groovy.lang.GroovyShell.evaluate(GroovyShell.java:427)
        at groovy.lang.GroovyShell.evaluate(GroovyShell.java:461)
        at groovy.lang.GroovyShell.evaluate(GroovyShell.java:436)
        at io.deephaven.engine.util.GroovyDeephavenSession.evaluateCommand(GroovyDeephavenSession.java:206)
        at io.deephaven.engine.util.GroovyDeephavenSession.lambda$evaluate$0(GroovyDeephavenSession.java:228)
        at io.deephaven.util.locks.FunctionalLock.doLockedInterruptibly(FunctionalLock.java:50)
        at io.deephaven.engine.util.GroovyDeephavenSession.evaluate(GroovyDeephavenSession.java:228)
        at io.deephaven.engine.util.AbstractScriptSession.lambda$evaluateScript$1(AbstractScriptSession.java:145)
        at io.deephaven.engine.context.ExecutionContext.lambda$apply$0(ExecutionContext.java:129)
        at io.deephaven.engine.context.ExecutionContext.apply(ExecutionContext.java:140)
        at io.deephaven.engine.context.ExecutionContext.apply(ExecutionContext.java:128)
        at io.deephaven.engine.util.AbstractScriptSession.evaluateScript(AbstractScriptSession.java:145)
        at io.deephaven.engine.util.DelegatingScriptSession.evaluateScript(DelegatingScriptSession.java:87)
        at io.deephaven.engine.util.ScriptSession.evaluateScript(ScriptSession.java:113)
        at io.deephaven.server.console.ConsoleServiceGrpcImpl.lambda$executeCommand$7(ConsoleServiceGrpcImpl.java:168)
        at io.deephaven.server.session.SessionState$ExportBuilder.lambda$submit$2(SessionState.java:1348)
        at io.deephaven.server.session.SessionState$ExportObject.doExport(SessionState.java:891)
        at java.util.concurrent.Executors$RunnableAdapter.call(Executors.java:539)
        at java.util.concurrent.FutureTask.run(FutureTask.java:264)
        at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1136)
        at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:635)
        at io.deephaven.server.runner.DeephavenApiServerModule$ThreadFactory.lambda$newThread$0(DeephavenApiServerModule.java:162)
        at java.lang.Thread.run(Thread.java:833)

Additional details and attachments

If we fix https://github.com/deephaven/deephaven-core/issues/3568 arguably the priority/need for this ticket to be addressed is greatly reduced.

Versions

niloc132 commented 1 year ago

In terms of the API itself, and "doing what you meant" (not "better feedback", which is what the issue is actually about):

java.lang.ClassCastException: class java.lang.String cannot be cast to class io.deephaven.api.Selectable (java.lang.String is in module java.base of loader 'bootstrap'; io.deephaven.api.Selectable is in unnamed module of loader 'app')
        at java.util.stream.ReferencePipeline$3$1.accept(ReferencePipeline.java:197)
        at java.util.ArrayList$ArrayListSpliterator.forEachRemaining(ArrayList.java:1625)
        at java.util.stream.AbstractPipeline.copyInto(AbstractPipeline.java:509)
        at java.util.stream.AbstractPipeline.wrapAndCopyInto(AbstractPipeline.java:499)
        at java.util.stream.AbstractPipeline.evaluate(AbstractPipeline.java:575)
        at java.util.stream.AbstractPipeline.evaluateToArrayNode(AbstractPipeline.java:260)
        at java.util.stream.ReferencePipeline.toArray(ReferencePipeline.java:616)
        at io.deephaven.engine.table.impl.select.SelectColumn.from(SelectColumn.java:35)
        at io.deephaven.engine.table.impl.QueryTable.view(QueryTable.java:1350)
        at io.deephaven.engine.table.impl.QueryTable.view(QueryTable.java:100)

This is pretty close to "the best that groovy/java can do here" - a List was passed to Table.view(Collection<? extends Selectable), which is totally allowed, but until we start walking the contents we can't see that it happened to be a List<String>.

Table has another overload that takes Strings instead of Selectables, but it is declared as var-args, which is an array: Table.view(String...).

Groovy is very happy to leave things a bit fuzzy, which is sort of the point of it. One of its preferences is that a [...] is a list rather than an array, since usually that's what you mean as a user. You can fix this error by telling groovy that this is an array, but I don't think we can tell it to assume this:

table.view(["Sym", "Price", "PriceBeforeMyTrade", "Timestamp"] as String[])