lucidsoftware / relate

Performant database access in Scala
http://lucidsoftware.github.io/relate/
Apache License 2.0
161 stars 15 forks source link

Add List[Array[Byte]] and Array[Array[Byte]] tests #76

Closed palanga closed 11 months ago

palanga commented 1 year ago

The conversion of a List of byte array doesn't work as expected (it did in previous versions (2.1.1 with scala 2.12)).

Instead of opening an issue explaining the bug I preferred to send a pull request with a couple of tests explaining it.

The first test works, the second fails.

tmccombs commented 1 year ago

Would you be able to include a fix in your PR?

palanga commented 1 year ago

@tmccombs

I did a quick try with no success. But I wanted to at least share this with you. You have way more context than me to fix this. And I allowed edits by maintainers so you can push to this branch if you want.

palanga commented 1 year ago

Set[Array[Byte]] works ok too. I think the problem is just the List

tmccombs commented 1 year ago

That is pretty strange,

https://github.com/lucidsoftware/relate/blob/master/relate/src/main/scala/com/lucidchart/relate/Parameters.scala#L50

should make it so that List works, and what is even weirder is that that is the same mechanism that would cause Set[Array[Byte]] to work.

gregghz commented 1 year ago

Instead of . . . explaining the bug I preferred to send a pull request

Can you explain it as well? A failing test case is great but atm I have no idea how it's failing. Just copy/pasting the failure error here would help a lot.

palanga commented 1 year ago

@gregghz sure! This is the message I get when I run the last test I added:

'INSERT INTO myTable (foo) VALUES ((?,?),(?,?))' != 'INSERT INTO myTable (foo) VALUES (?,?)'
Expected :INSERT INTO myTable (foo) VALUES (?,?)
Actual   :INSERT INTO myTable (foo) VALUES ((?,?),(?,?))
<Click to see difference>

java.lang.Exception: 'INSERT INTO myTable (foo) VALUES ((?,?),(?,?))' != 'INSERT INTO myTable (foo) VALUES (?,?)'
    at org.specs2.matcher.MatchResultStackTrace$class.setStacktrace(Expectations.scala:57)
    at org.specs2.mutable.Specification.setStacktrace(Specification.scala:15)
    at org.specs2.matcher.ExpectationsCreation$class.checkFailure(Expectations.scala:37)
    at org.specs2.mutable.Specification.checkFailure(Specification.scala:15)
    at org.specs2.matcher.MustThrownExpectationsCreation$$anon$4.check(MustExpectations.scala:68)
    at org.specs2.matcher.Expectable.applyMatcher(Expectable.scala:51)
    at org.specs2.matcher.MustThrownExpectationsCreation$$anon$4.applyMatcher(MustExpectations.scala:67)
    at org.specs2.matcher.MustExpectable.mustEqual(MustExpectable.scala:17)
    at com.lucidchart.relate.ParameterizationTest$$anonfun$1$$anonfun$apply$10.apply(ParameterizationTest.scala:29)
    at com.lucidchart.relate.ParameterizationTest$$anonfun$1$$anonfun$apply$10.apply(ParameterizationTest.scala:26)
    at org.specs2.matcher.MatchResult$$anon$12$$anonfun$asResult$1.apply(MatchResult.scala:344)
    at org.specs2.matcher.MatchResult$$anon$12$$anonfun$asResult$1.apply(MatchResult.scala:344)
    at org.specs2.execute.ResultExecution$class.execute(ResultExecution.scala:22)
    at org.specs2.execute.ResultExecution$.execute(ResultExecution.scala:123)
    at org.specs2.execute.Result$$anon$11.asResult(Result.scala:246)
    at org.specs2.execute.AsResult$.apply(AsResult.scala:32)
    at org.specs2.matcher.MatchResult$$anon$12.asResult(MatchResult.scala:344)
    at org.specs2.execute.AsResult$.apply(AsResult.scala:32)
    at org.specs2.specification.core.AsExecution$$anon$1$$anonfun$execute$1.apply(AsExecution.scala:17)
    at org.specs2.specification.core.AsExecution$$anon$1$$anonfun$execute$1.apply(AsExecution.scala:17)
    at org.specs2.execute.ResultExecution$class.execute(ResultExecution.scala:22)
    at org.specs2.execute.ResultExecution$.execute(ResultExecution.scala:123)
    at org.specs2.execute.Result$$anon$11.asResult(Result.scala:246)
    at org.specs2.execute.AsResult$.apply(AsResult.scala:32)
    at org.specs2.execute.AsResult$$anonfun$safely$1.apply(AsResult.scala:40)
    at org.specs2.execute.AsResult$$anonfun$safely$1.apply(AsResult.scala:40)
    at org.specs2.execute.ResultExecution$class.execute(ResultExecution.scala:22)
    at org.specs2.execute.ResultExecution$.execute(ResultExecution.scala:123)
    at org.specs2.execute.AsResult$.safely(AsResult.scala:40)
    at org.specs2.specification.core.Execution$$anonfun$result$1.apply(Execution.scala:340)
    at org.specs2.specification.core.Execution$$anonfun$result$1.apply(Execution.scala:340)
    at org.specs2.specification.core.Execution$$anonfun$withEnvSync$1$$anonfun$apply$22$$anonfun$apply$23.apply(Execution.scala:358)
    at org.specs2.execute.ResultExecution$class.execute(ResultExecution.scala:22)
    at org.specs2.execute.ResultExecution$.execute(ResultExecution.scala:123)
    at org.specs2.execute.Result$$anon$11.asResult(Result.scala:246)
    at org.specs2.execute.AsResult$.apply(AsResult.scala:32)
    at org.specs2.execute.AsResult$$anonfun$safely$1.apply(AsResult.scala:40)
    at org.specs2.execute.AsResult$$anonfun$safely$1.apply(AsResult.scala:40)
    at org.specs2.execute.ResultExecution$class.execute(ResultExecution.scala:22)
    at org.specs2.execute.ResultExecution$.execute(ResultExecution.scala:123)
    at org.specs2.execute.AsResult$.safely(AsResult.scala:40)
    at org.specs2.specification.core.Execution$$anonfun$withEnvSync$1$$anonfun$apply$22.apply(Execution.scala:358)
    at org.specs2.specification.core.Execution$$anonfun$withEnvSync$1$$anonfun$apply$22.apply(Execution.scala:358)
    at org.specs2.specification.core.Execution$$anonfun$3$$anonfun$apply$4.apply(Execution.scala:142)
    at org.specs2.specification.core.Execution$$anonfun$3$$anonfun$apply$4.apply(Execution.scala:142)
    at scala.util.Success$$anonfun$map$1.apply(Try.scala:237)
    at scala.util.Try$.apply(Try.scala:192)
    at scala.util.Success.map(Try.scala:237)
    at scala.concurrent.Future$$anonfun$map$1.apply(Future.scala:237)
    at scala.concurrent.Future$$anonfun$map$1.apply(Future.scala:237)
    at scala.concurrent.impl.CallbackRunnable.run(Promise.scala:36)
    at java.base/java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1128)
    at java.base/java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:628)
    at java.base/java.lang.Thread.run(Thread.java:829)
palanga commented 1 year ago

@gregghz

Byte arrays has a special converter to a single parameter. So a byte array of length 8 corresponds to a single BINARY(8) element in the database. That's ok. If you have a Set or an Array of byte arrays, it is converted to a list of single BINARY(8) parameters. That's ok too. But if you have a List of byte arrays, every single element in the array is converted to a single parameter. That behavior is so unexpected.

palanga commented 1 year ago

@tmccombs yeah. It is so weird.