Bug 286206 - default byte[] -> BLOB mapping for Derby incorrect
Summary: default byte[] -> BLOB mapping for Derby incorrect
Status: NEW
Alias: None
Product: z_Archived
Classification: Eclipse Foundation
Component: Eclipselink (show other bugs)
Version: unspecified   Edit
Hardware: PC All
: P3 normal (vote)
Target Milestone: ---   Edit
Assignee: Nobody - feel free to take it CLA
QA Contact:
URL:
Whiteboard: submitted_patch, derby
Keywords:
Depends on:
Blocks:
 
Reported: 2009-08-11 04:11 EDT by Dies Koper CLA
Modified: 2022-06-09 10:28 EDT (History)
4 users (show)

See Also:


Attachments
proposed patch (based on current EclipseLink source) (1.69 KB, patch)
2009-08-11 04:22 EDT, Dies Koper CLA
no flags Details | Diff
previous patch had a problem, as this data type does NOT allow size to be specified (1.37 KB, patch)
2009-09-07 03:55 EDT, Dies Koper CLA
no flags Details | Diff

Note You need to log in before you can comment on or make changes to this bug.
Description Dies Koper CLA 2009-08-11 04:11:17 EDT
EclipseLink uses columns of SQL Type BLOB in generated tables for Java fields of type byte[] for Derby.

This is not correct. Derby's equivalent to JDBC's LONGVARBINARY type is "LONG VARCHAR FOR BIT DATA".
Note that in the case of @Lob there is no issue, EclipseLink maps byte[] correctly to BLOB.

The current mapping of (non-@Lob) byte[] causes an issue when migrating applications from Derby 10.2.x to Derby 10.4.x as Derby's JDBC setters became more strict: when persisting a POJO with an uninitialized byte[] field on Derby 10.4.x, the following error occurs (reproducible on both TLE and EclipseLink 2.0):

Caused by: java.sql.SQLException: An attempt was made to get a data
value of type 'LONGVARBINARY' from a data value of type 'BLOB'.
    at
org.apache.derby.client.am.SQLExceptionFactory.getSQLException(Unknown
Source)
    at org.apache.derby.client.am.SqlException.getSQLException(Unknown Source)
    at org.apache.derby.client.am.PreparedStatement.setNull(Unknown Source)
    at
oracle.toplink.essentials.internal.databaseaccess.DatabasePlatform.setComplexParameterValue(DatabasePlatform.java:1438) 

See also:
http://www.nabble.com/default-byte----%3E-BLOB-mapping-for-JavaDB-td24213970.html
Comment 1 Dies Koper CLA 2009-08-11 04:22:35 EDT
Created attachment 144008 [details]
proposed patch (based on current EclipseLink source)

- fixing the mapping for both byte[] and Byte[]
- using the maximum column size according to Derby manual at http://db.apache.org/derby/docs/10.5/ref/refderby.pdf (size setting for this type is optional)
Comment 2 Tom Ware CLA 2009-08-31 09:25:59 EDT
Setting target and priority.  See the following page for the meanings of these fields:

http://wiki.eclipse.org/EclipseLink/Development/Bugs/Guidelines
Comment 3 Dies Koper CLA 2009-09-07 03:55:13 EDT
Created attachment 146588 [details]
previous patch had a problem, as this data type does NOT allow size to be specified

The Derby manual I referred to said "you do not have to specify a maximum length when creating columns of this type". What they actually meant is "you cannot specify a maximum length"!
Fixed the patch accordingly.

Still, I see a failure when running jpa JUnit tests: testCreatePrimitiveByteArrayType.
The problem seems to be that when a byte[] is marked as @Lob, it should map to BLOB and use its corresponding API, and when it is not marked as @Lob, it should map to (LONG) VARCHAR FOR BIT DATA and use getBytes/setBytes, and this distinction is currently not made.

Caused by: java.sql.SQLDataException: An attempt was made to get a data value of type 'LONG VARCHAR FOR BIT DATA' from a data value of type 'BLOB'.
at org.apache.derby.impl.jdbc.SQLExceptionFactory40.getSQLException(Unknown Source)
at org.apache.derby.impl.jdbc.Util.newEmbedSQLException(Unknown Source)
at org.apache.derby.impl.jdbc.Util.newEmbedSQLException(Unknown Source)
at org.apache.derby.impl.jdbc.Util.generateCsSQLException(Unknown Source)
at org.apache.derby.impl.jdbc.EmbedConnection.newSQLException(Unknown Source)
at org.apache.derby.impl.jdbc.ConnectionChild.newSQLException(Unknown Source)
at org.apache.derby.impl.jdbc.EmbedPreparedStatement.dataTypeConversion(Unknown Source)
at org.apache.derby.impl.jdbc.EmbedPreparedStatement.setNull(Unknown Source)
at org.eclipse.persistence.internal.databaseaccess.DatabasePlatform.setParameterValueInDatabaseCall(DatabasePlatform.java:1935)
at org.eclipse.persistence.internal.databaseaccess.DatabaseCall.prepareStatement(DatabaseCall.java:665)
Comment 4 Tom Ware CLA 2010-06-15 10:29:33 EDT
The attached fix breaks our DDL generation testing model.  It causes an exception of the following form when we generate tables using the updated patch and then try to insert into the tables:

javax.persistence.RollbackException: Exception [EclipseLink-4002] (Eclipse Persistence Services - @VERSION@.@QUALIFIER@): org.eclipse.persistence.exceptions.DatabaseException
Internal Exception: java.sql.SQLDataException: An attempt was made to get a data value of type 'BLOB' from a data value of type 'LONGVARBINARY'.
Error Code: 20000
Call: INSERT INTO DDL_COMMENT (ID, TEXT, FLAG, AUDIO, PHOTO) VALUES (?, ?, ?, ?, ?)
	bind => [2, comment 2, null, null, null]
Query: InsertObjectQuery(org.eclipse.persistence.testing.models.jpa.ddlgeneration.Comment@1c1f2)
	at org.eclipse.persistence.internal.jpa.transaction.EntityTransactionImpl.commitInternal(EntityTransactionImpl.java:102)
	at org.eclipse.persistence.internal.jpa.transaction.EntityTransactionImpl.commit(EntityTransactionImpl.java:63)
	at org.eclipse.persistence.testing.framework.junit.JUnitTestCase.commitTransaction(JUnitTestCase.java:296)
	at org.eclipse.persistence.testing.tests.jpa.ddlgeneration.DDLGenerationJUnitTestSuite.testDDLUnidirectionalOneToMany(DDLGenerationJUnitTestSuite.java:581)
	at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
	at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:39)
	at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25)
	at java.lang.reflect.Method.invoke(Method.java:597)
	at junit.framework.TestCase.runTest(TestCase.java:168)
	at junit.framework.TestCase.runBare(TestCase.java:134)
	at org.eclipse.persistence.testing.framework.junit.JUnitTestCase.runBare(JUnitTestCase.java:454)
	at junit.framework.TestResult$1.protect(TestResult.java:110)
	at junit.framework.TestResult.runProtected(TestResult.java:128)
	at junit.framework.TestResult.run(TestResult.java:113)
	at junit.framework.TestCase.run(TestCase.java:124)
	at junit.framework.TestSuite.runTest(TestSuite.java:232)
	at junit.framework.TestSuite.run(TestSuite.java:227)
	at org.eclipse.jdt.internal.junit.runner.junit3.JUnit3TestReference.run(JUnit3TestReference.java:130)
	at org.eclipse.jdt.internal.junit.runner.TestExecution.run(TestExecution.java:38)
	at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.runTests(RemoteTestRunner.java:467)
	at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.runTests(RemoteTestRunner.java:683)
	at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.run(RemoteTestRunner.java:390)
	at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.main(RemoteTestRunner.java:197)
Caused by: Exception [EclipseLink-4002] (Eclipse Persistence Services - @VERSION@.@QUALIFIER@): org.eclipse.persistence.exceptions.DatabaseException
Internal Exception: java.sql.SQLDataException: An attempt was made to get a data value of type 'BLOB' from a data value of type 'LONGVARBINARY'.
Error Code: 20000
Call: INSERT INTO DDL_COMMENT (ID, TEXT, FLAG, AUDIO, PHOTO) VALUES (?, ?, ?, ?, ?)
	bind => [2, comment 2, null, null, null]
Query: InsertObjectQuery(org.eclipse.persistence.testing.models.jpa.ddlgeneration.Comment@1c1f2)
	at org.eclipse.persistence.exceptions.DatabaseException.sqlException(DatabaseException.java:333)
	at org.eclipse.persistence.internal.databaseaccess.DatabaseAccessor.basicExecuteCall(DatabaseAccessor.java:683)
	at org.eclipse.persistence.internal.databaseaccess.DatabaseAccessor.executeCall(DatabaseAccessor.java:526)
	at org.eclipse.persistence.internal.sessions.AbstractSession.executeCall(AbstractSession.java:980)
	at org.eclipse.persistence.internal.queries.DatasourceCallQueryMechanism.executeCall(DatasourceCallQueryMechanism.java:206)
	at org.eclipse.persistence.internal.queries.DatasourceCallQueryMechanism.executeCall(DatasourceCallQueryMechanism.java:192)
	at org.eclipse.persistence.internal.queries.DatasourceCallQueryMechanism.insertObject(DatasourceCallQueryMechanism.java:341)
	at org.eclipse.persistence.internal.queries.StatementQueryMechanism.insertObject(StatementQueryMechanism.java:162)
	at org.eclipse.persistence.internal.queries.StatementQueryMechanism.insertObject(StatementQueryMechanism.java:177)
	at org.eclipse.persistence.internal.queries.DatabaseQueryMechanism.insertObjectForWrite(DatabaseQueryMechanism.java:465)
	at org.eclipse.persistence.queries.InsertObjectQuery.executeCommit(InsertObjectQuery.java:80)
	at org.eclipse.persistence.queries.InsertObjectQuery.executeCommitWithChangeSet(InsertObjectQuery.java:90)
	at org.eclipse.persistence.internal.queries.DatabaseQueryMechanism.executeWriteWithChangeSet(DatabaseQueryMechanism.java:290)
	at org.eclipse.persistence.queries.WriteObjectQuery.executeDatabaseQuery(WriteObjectQuery.java:58)
	at org.eclipse.persistence.queries.DatabaseQuery.execute(DatabaseQuery.java:736)
	at org.eclipse.persistence.queries.DatabaseQuery.executeInUnitOfWork(DatabaseQuery.java:643)
	at org.eclipse.persistence.queries.ObjectLevelModifyQuery.executeInUnitOfWorkObjectLevelModifyQuery(ObjectLevelModifyQuery.java:108)
	at org.eclipse.persistence.queries.ObjectLevelModifyQuery.executeInUnitOfWork(ObjectLevelModifyQuery.java:85)
	at org.eclipse.persistence.internal.sessions.UnitOfWorkImpl.internalExecuteQuery(UnitOfWorkImpl.java:2909)
	at org.eclipse.persistence.internal.sessions.AbstractSession.executeQuery(AbstractSession.java:1291)
	at org.eclipse.persistence.internal.sessions.AbstractSession.executeQuery(AbstractSession.java:1273)
	at org.eclipse.persistence.internal.sessions.AbstractSession.executeQuery(AbstractSession.java:1233)
	at org.eclipse.persistence.internal.sessions.CommitManager.commitNewObjectsForClassWithChangeSet(CommitManager.java:224)
	at org.eclipse.persistence.internal.sessions.CommitManager.commitAllObjectsForClassWithChangeSet(CommitManager.java:191)
	at org.eclipse.persistence.internal.sessions.CommitManager.commitAllObjectsWithChangeSet(CommitManager.java:136)
	at org.eclipse.persistence.internal.sessions.AbstractSession.writeAllObjectsWithChangeSet(AbstractSession.java:3348)
	at org.eclipse.persistence.internal.sessions.UnitOfWorkImpl.commitToDatabase(UnitOfWorkImpl.java:1422)
	at org.eclipse.persistence.internal.sessions.RepeatableWriteUnitOfWork.commitToDatabase(RepeatableWriteUnitOfWork.java:546)
	at org.eclipse.persistence.internal.sessions.UnitOfWorkImpl.commitToDatabaseWithChangeSet(UnitOfWorkImpl.java:1527)
	at org.eclipse.persistence.internal.sessions.RepeatableWriteUnitOfWork.commitRootUnitOfWork(RepeatableWriteUnitOfWork.java:200)
	at org.eclipse.persistence.internal.sessions.UnitOfWorkImpl.commitAndResume(UnitOfWorkImpl.java:1148)
	at org.eclipse.persistence.internal.jpa.transaction.EntityTransactionImpl.commitInternal(EntityTransactionImpl.java:84)
	... 22 more
Caused by: java.sql.SQLDataException: An attempt was made to get a data value of type 'BLOB' from a data value of type 'LONGVARBINARY'.
	at org.apache.derby.client.am.SQLExceptionFactory40.getSQLException(Unknown Source)
	at org.apache.derby.client.am.SqlException.getSQLException(Unknown Source)
	at org.apache.derby.client.am.PreparedStatement.setNull(Unknown Source)
	at org.eclipse.persistence.internal.databaseaccess.DatabasePlatform.setParameterValueInDatabaseCall(DatabasePlatform.java:2080)
	at org.eclipse.persistence.internal.databaseaccess.DatabaseCall.prepareStatement(DatabaseCall.java:671)
	at org.eclipse.persistence.internal.databaseaccess.DatabaseAccessor.basicExecuteCall(DatabaseAccessor.java:576)
	... 52 more
Caused by: org.apache.derby.client.am.SqlException: An attempt was made to get a data value of type 'BLOB' from a data value of type 'LONGVARBINARY'.
	at org.apache.derby.client.am.PreparedStatement$PossibleTypes.throw22005Exception(Unknown Source)
	... 56 more


	at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25)
	at java.lang.reflect.Method.invoke(Method.java:597)
	at junit.framework.TestCase.runTest(TestCase.java:168)
	at junit.framework.TestCase.runBare(TestCase.java:134)
	at org.eclipse.persistence.testing.framework.junit.JUnitTestCase.runBare(JUnitTestCase.java:454)
	at junit.framework.TestResult$1.protect(TestResult.java:110)
	at junit.framework.TestResult.runProtected(TestResult.java:128)
	at junit.framework.TestResult.run(TestResult.java:113)
	at junit.framework.TestCase.run(TestCase.java:124)
	at junit.framework.TestSuite.runTest(TestSuite.java:232)
	at junit.framework.TestSuite.run(TestSuite.java:227)
	at org.eclipse.jdt.internal.junit.runner.junit3.JUnit3TestReference.run(JUnit3TestReference.java:130)
	at org.eclipse.jdt.internal.junit.runner.TestExecution.run(TestExecution.java:38)
	at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.runTests(RemoteTestRunner.java:467)
	at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.runTests(RemoteTestRunner.java:683)
	at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.run(RemoteTestRunner.java:390)
	at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.main(RemoteTestRunner.java:197)

The following mappings exist in Comment:


    @Lob
    @Column(name="PHOTO", length=80000)
    private Byte[] photo;
    
    @Lob
    @Column(name="AUDIO")
    private Byte[] audio;
Comment 5 Eclipse Webmaster CLA 2022-06-09 10:28:43 EDT
The Eclipselink project has moved to Github: https://github.com/eclipse-ee4j/eclipselink