Community
Participate
Working Groups
DB2 and TimesTen platform classes both override the writeParameterMarker method to implement casting parameters: "CAST (? AS " + castType + " )". The castType on DB2Platform is hardcoded and on TimesTen it is pulled from the fieldTypeDefinitions map, but in both cases based on the java class type provided when defining the argument. This needs to be changed to allow the parameter to be cast to something other than the default for the java class - for instance when a String needs to be cast to VARCHAR(255) or VARCHAR instead of the VARCHAR(32672) used in the DB2 platform.
Changed version to unspecified
Created attachment 119383 [details] Proposed Fix for the DB2Platform.writeParameterMarker We met this bug when working with DB2 V8 and GlassFish 9.1_02 on Windows Vista. Changing the hardcoded value (32672) for the cast is a must for us. Depending on the DB2-Tablespace-size defined for the choosen Table the current implementation may result in an SQLException: SqlException: DB2 SQL error: SQLCODE: -132, SQLSTATE: 42824, SQLERRMC: null In our case we could not perform a very simple Like-Query. A statement like: SELECT MY_STRING FROM MY_TABLE WHERE (MY_STRING LIKE CAST (? AS VARCHAR(32672) )) ORDER BY NAME_PGM ASC bind => [TEST%] resulted in the above error. By experimenting around we found that due to our Tablespace-Definition we could at maximum cast to VARCHAR(4000). In addtion from a DB Admin point of view it is not really desired to to cast to a length of 32672 in order to query an column of length 8. A prerequisite to get the proposed fix to work properly is that the length-Field on the DatabaseField associated with the ParameterExpression is filled properly at runtime. In our case we found that it is always filled with the default value (255)
Created attachment 129399 [details] proposed fix for DB2MainframePlatform Here's a proposed fix for mainframe platform which specifies the value 4000 or 32672 (depending on whether or not its called for the mainframe platform). Patch is against the following SVN URL: http://dev.eclipse.org/svnroot/rt/org.eclipse.persistence/trunk/foundation Thanks in advance.
Updating priority due to revised bug categorization process. See the following page for details: http://wiki.eclipse.org/EclipseLink/Development/Bugs/Guidelines#Priority_and_Target_Milestone If you feel the updated priority is incorrect, please send an email to eclipselink-users@eclipse.org.
I don't think P5 is the right prio for this bug. We're using GlassFish 2.0 right now. In all of our projects we had to overwrite to replace the DB2Platform by our own Subclass containing a fix for the problem. This fix is also just a hack, as casting to VARCHAR(4000) is not guranteed to work in our case. According to our DB admin it is a question of how the corresponding DB is configured. Our hope was to get rid of this hack when moving to EclipseLink. If this is not the case we'll most likely use Hibernate as JPA-Provider in the near future.
Thank you for the feedback. Targetting for 2.0 and setting priority to P3. Note: It is our goal to deal with bugs with "submitted_patch" in a prioritized manner. At the moment, there is a bit of a backlog, but will will work to clear it up.
After a bit of investigation: 1. The issue does not recreate on my version of DB2, so it must be configuration or version dependant 2. (Because of #1)For backwards compatibility reasons, there will likely have to be an addition to the fix that checks to see if Length has been explicitly set on ParameterExpression's DatabaseField. (i.e. If length is left as the Default, the current behavior will remain, but if setLength has been called on the DatabaseField, the modified length will remain) 3. It looks like the DB2Platform fix will cover the DB2MainframePlatform as well.
> 1. The issue does not recreate on my version of DB2, so it must be > configuration or version dependant I can confirm that: our DB Admin told me, that we can only cast to VARCHAR(4000) - not to longer ones - because of our configuration > 2. (Because of #1)For backwards compatibility reasons, there will likely have > to be an addition to the fix that checks to see if Length has been explicitly > set on ParameterExpression's DatabaseField. (i.e. If length is left as the > Default, the current behavior will remain, but if setLength has been called on > the DatabaseField, the modified length will remain) Sounds good. > 3. It looks like the DB2Platform fix will cover the DB2MainframePlatform as > well. That would be my guess as well.
Created attachment 138183 [details] proposed fix Attaching the proposed fix. The change is actually somewhat different than described above. The setting that overrides the max value is now on the DatabasePlatform class and can be set with a setter.
Fix checked in. To make use of it, call databasePlatform.setCastSizeForVarcharParameter(int) on the databasePlatform held by your session. Tested manually due to the fact that I cannot recreate the issue.
Also... Code reviewed by Peter Krogh. IPLog updated
(In reply to comment #10) > Fix checked in. > > To make use of it, call databasePlatform.setCastSizeForVarcharParameter(int) on > the databasePlatform held by your session. > Can you elaborate on the use of the fix (its unclear)? I was thinking more along the lines of a call to setCastSizeForVarcharParameter(4000) inside the constructor for DB2MainframePlatform. > > Tested manually due to the fact that I cannot recreate the issue. >
As the 4000 limitation on varchar length was mentioned to be a specific db setup limitation, changing the platform for everyone was not an option - it would break anyone relying on the current default of 32672. What was implemented was adding a setCastSizeForVarcharParameter method on the database platform, so you can customize the length used as required. The default will remain 32672 if it is not set.
The suggested way to make use of this fix is to make a call to databasePlatform.setCastSizeForVarcharParameter(int) in a SessionCustomizer() (or if you are not in JPA, in a postLogin() event). Here is the documentation for SessionCustomizer(): http://wiki.eclipse.org/Using_EclipseLink_JPA_Extensions_%28ELUG%29#Using_EclipseLink_JPA_Extensions_for_Customization_and_Optimization Information can be found under the "eclipselink.session.customizer" heading in the table. You would write a method something like this: public class CaseSizeSessionCustomizer implements SessionCustomizer { public void customize(Sesssion session) { session.getPlatform().setCastSizeForVarcharParameter(4000); } }
(In reply to comment #14) > The suggested way to make use of this fix is to make a call to > databasePlatform.setCastSizeForVarcharParameter(int) in a SessionCustomizer() > (or if you are not in JPA, in a postLogin() event). > > Here is the documentation for SessionCustomizer(): > > http://wiki.eclipse.org/Using_EclipseLink_JPA_Extensions_%28ELUG%29#Using_EclipseLink_JPA_Extensions_for_Customization_and_Optimization > > Information can be found under the "eclipselink.session.customizer" heading in > the table. > > You would write a method something like this: > > public class CaseSizeSessionCustomizer implements SessionCustomizer { > > public void customize(Sesssion session) { > session.getPlatform().setCastSizeForVarcharParameter(4000); > } > } > Perfect. Thanks for the speedy reply.
Mass update to change fixed in target.
The Eclipselink project has moved to Github: https://github.com/eclipse-ee4j/eclipselink