Bug 448 : Hash values for QueryPlan collide
Priority 
High
Reported Version 
 
Logged By 
jcreason
Status 
Fixed
Fixed Version 
3.3.1
Assigned To 
 
Product 
Ebean - core
Duplicate Of 
 
Created 
12/12/2013
Updated 
12/12/2013
Type 
Bug
 
Attachments 
No attachments

I'm using Play 2.2.1, which includes ebeanorm-3.2.2 which I tested against and found (what I believe) this bug.

I am getting PersistenceExceptions thrown when creating a large set (hundreds) of similar queries in a row. It seems to depend on the data I'm passing in, which unfortunately, I cannot disclose. The queries look very similar, but have varying numbers of parameters in each section. I traced this through the ebean source code (which I repackaged and replaced the jar in my Play repo), and it lead me to believe that the hashes were colliding. I printed the computed hashes of each query, and they did indeed match. It seems that because they hash the same, the same QueryPlan object it being used for both, even though they have differing numbers of bound parameters.

Both below errors hash to the value: 1336939366

Before I knew all of this, I attempted to explain what I was seeing over on stackoverflow if you'd like to take a look at that as well.
http://stackoverflow.com/questions/20501591/ebean-dynamic-query-prepared-statements-mismatched-parameter-count-error


Here are the two stack traces:

play.api.Application$$anon$1: Execution exception[[PersistenceException: Query threw SQLException:No value specified for parameter 19
Bind values:[SENT,1290,8988,13032,13052,1290,96,99,100,101,102,103,104,105,106,107,108,222]
Query was:
select distinct t0.contact_id c0, t0.contact_uuid c1, t0.bounce c2 from contact t0 join email_record u1 on u1.contact_id = t0.contact_id join contact_tag u2z_ on u2z_.contact_id = t0.contact_id join tag u2 on u2.tag_id = u2z_.tag_id where u1.status = ? and t0.unit_id = ? and u2.tag_id in (?,?) and t0.unit_id in (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ? ) and t0.campaign_id in (?,?,?,?,?,?,?,?,?,?,?,?)

]]
at play.api.Application$class.handleError(Application.scala:293) ~[play_2.10.jar:2.2.1]
at play.api.DefaultApplication.handleError(Application.scala:399) [play_2.10.jar:2.2.1]
at play.core.server.netty.PlayDefaultUpstreamHandler$$anonfun$2$$anonfun$applyOrElse$3.apply(PlayDefaultUpstreamHandler.scala:261) [play_2.10.jar:2.2.1]
at play.core.server.netty.PlayDefaultUpstreamHandler$$anonfun$2$$anonfun$applyOrElse$3.apply(PlayDefaultUpstreamHandler.scala:261) [play_2.10.jar:2.2.1]
at scala.Option.map(Option.scala:145) [scala-library.jar:na]
at play.core.server.netty.PlayDefaultUpstreamHandler$$anonfun$2.applyOrElse(PlayDefaultUpstreamHandler.scala:261) [play_2.10.jar:2.2.1]
Caused by: javax.persistence.PersistenceException: Query threw SQLException:No value specified for parameter 19
Bind values:[SENT,1290,8988,13032,13052,1290,96,99,100,101,102,103,104,105,106,107,108,222]
Query was:
select distinct t0.contact_id c0, t0.contact_uuid c1, t0.bounce c2 from contact t0 join email_record u1 on u1.contact_id = t0.contact_id join contact_tag u2z_ on u2z_.contact_id = t0.contact_id join tag u2 on u2.tag_id = u2z_.tag_id where u1.status = ? and t0.unit_id = ? and u2.tag_id in (?,?) and t0.unit_id in (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ? ) and t0.campaign_id in (?,?,?,?,?,?,?,?,?,?,?,?)


at com.avaje.ebeaninternal.server.query.CQuery.createPersistenceException(CQuery.java:798) ~[avaje-ebeanorm.jar:na]
at com.avaje.ebeaninternal.server.query.CQuery.createPersistenceException(CQuery.java:775) ~[avaje-ebeanorm.jar:na]
at com.avaje.ebeaninternal.server.query.CQueryEngine.findMany(CQueryEngine.java:205) ~[avaje-ebeanorm.jar:na]
at com.avaje.ebeaninternal.server.query.DefaultOrmQueryEngine.findMany(DefaultOrmQueryEngine.java:81) ~[avaje-ebeanorm.jar:na]
at com.avaje.ebeaninternal.server.core.OrmQueryRequest.findList(OrmQueryRequest.java:265) ~[avaje-ebeanorm.jar:na]
at com.avaje.ebeaninternal.server.core.DefaultServer.findList(DefaultServer.java:1469) ~[avaje-ebeanorm.jar:na]
Caused by: java.sql.SQLException: No value specified for parameter 19
at com.mysql.jdbc.SQLError.createSQLException(SQLError.java:1078) ~[mysql-connector-java-5.1.27.jar:na]
at com.mysql.jdbc.SQLError.createSQLException(SQLError.java:989) ~[mysql-connector-java-5.1.27.jar:na]
at com.mysql.jdbc.SQLError.createSQLException(SQLError.java:975) ~[mysql-connector-java-5.1.27.jar:na]
at com.mysql.jdbc.SQLError.createSQLException(SQLError.java:920) ~[mysql-connector-java-5.1.27.jar:na]
at com.mysql.jdbc.PreparedStatement.checkAllParametersSet(PreparedStatement.java:2612) ~[mysql-connector-java-5.1.27.jar:na]
at com.mysql.jdbc.PreparedStatement.fillSendPacket(PreparedStatement.java:2587) ~[mysql-connector-java-5.1.27.jar:na]


And the second:

play.api.Application$$anon$1: Execution exception[[PersistenceException: Error with property[19] dt[4]data[1464][java.lang.Integer]]]
at play.api.Application$class.handleError(Application.scala:293) ~[play_2.10.jar:2.2.1]
at play.api.DefaultApplication.handleError(Application.scala:399) [play_2.10.jar:2.2.1]
at play.core.server.netty.PlayDefaultUpstreamHandler$$anonfun$2$$anonfun$applyOrElse$3.apply(PlayDefaultUpstreamHandler.scala:261) [play_2.10.jar:2.2.1]
at play.core.server.netty.PlayDefaultUpstreamHandler$$anonfun$2$$anonfun$applyOrElse$3.apply(PlayDefaultUpstreamHandler.scala:261) [play_2.10.jar:2.2.1]
at scala.Option.map(Option.scala:145) [scala-library.jar:na]
at play.core.server.netty.PlayDefaultUpstreamHandler$$anonfun$2.applyOrElse(PlayDefaultUpstreamHandler.scala:261) [play_2.10.jar:2.2.1]
Caused by: javax.persistence.PersistenceException: Error with property[19] dt[4]data[1464][java.lang.Integer]
at com.avaje.ebeaninternal.server.persist.Binder.bindSimpleData(Binder.java:327) ~[avaje-ebeanorm.jar:na]
at com.avaje.ebeaninternal.server.persist.Binder.bindObject(Binder.java:216) ~[avaje-ebeanorm.jar:na]
at com.avaje.ebeaninternal.server.persist.Binder.bindObject(Binder.java:173) ~[avaje-ebeanorm.jar:na]
at com.avaje.ebeaninternal.server.query.CQueryPredicates.bind(CQueryPredicates.java:152) ~[avaje-ebeanorm.jar:na]
at com.avaje.ebeaninternal.server.query.CQuery.prepareBindExecuteQuery(CQuery.java:382) ~[avaje-ebeanorm.jar:na]
at com.avaje.ebeaninternal.server.query.CQueryEngine.findMany(CQueryEngine.java:165) ~[avaje-ebeanorm.jar:na]
Caused by: java.sql.SQLException: Parameter index out of range (19 > number of parameters, which is 18).
at com.mysql.jdbc.SQLError.createSQLException(SQLError.java:1078) ~[mysql-connector-java-5.1.27.jar:na]
at com.mysql.jdbc.SQLError.createSQLException(SQLError.java:989) ~[mysql-connector-java-5.1.27.jar:na]
at com.mysql.jdbc.SQLError.createSQLException(SQLError.java:975) ~[mysql-connector-java-5.1.27.jar:na]
at com.mysql.jdbc.SQLError.createSQLException(SQLError.java:920) ~[mysql-connector-java-5.1.27.jar:na]
at com.mysql.jdbc.PreparedStatement.checkBounds(PreparedStatement.java:3814) ~[mysql-connector-java-5.1.27.jar:na]
at com.mysql.jdbc.PreparedStatement.setInternal(PreparedStatement.java:3796) ~[mysql-connector-java-5.1.27.jar:na]

This is affecting our production environment so we need a fix ASAP, so I'm going to attempt to fix this in the ebean source, and if I can, I'll try to submit a patch to this ticket. However, I am very unfamiliar with this code, so if someone has the time I'd really appreciate the help.

I can provide more data on request.

 
woResponse

Upload a file