[ 
https://issues.apache.org/jira/browse/OPENJPA-1420?page=com.atlassian.jira.plugin.system.issuetabpanels:all-tabpanel
 ]

Heath Thomann updated OPENJPA-1420:
-----------------------------------

    Attachment: OPENJPA-1420.diff.txt

I've been working on a fix for this issue with assistance by Mike Dick.  I've 
provided a patch with the changes we propose.  Let me describe the changes and 
the rational behind the changes:

MappingInfo.java:
In method 'mergeColumn', the 'template Column' is merged with the 'given 
Column', where 'given' is what the user has specified in the @Column 
annotation.  Within the 'mergeColumn' method, the column's 'type' and 'size' 
are determine and set.  This is important because to fix this issue we need 
both the column type and size (i.e. when the column type is VARCHAR, and the 
size is greater than 255 we need to change the type).  This method is about the 
only place I could find where we know both 'type' and 'size' at the same time 
and can influence their values.  Ideally we want to keep the logic for this 
issue contained within InformixDictionary or at least DBDictionary.  However, 
neither class necessarily knows a columns type and size or has the opportunity 
to set the values.  As such, minor changes are needed in the 'mergeColumn' 
method to allow the InformixDictionary to influence the type and size.  To that 
end, we have moved the call to 'dict.getPreferredType' to a different spot AND 
we also overloaded this method.  'getPreferredType' already takes the 'type' as 
a parameter and returns the preferred type, as such this is a natural place to 
influence the type.  However, we also need the size in order to influence the 
type so we overloaded this method to take the 'size'.  'getPreferredType' is 
not defined on InformixDictionary as such the call is made on DBDictionary.  
However, as you will see below, with my changes InformixDictionary overrides 
'getPreferredType'.  

DBDictionary.java:
As was stated above, method 'getPreferredType' was overloaded to allow the 
'size' to be passed as a parameter.  The existing 'getPreferredType' method, 
which takes only the 'type', delegates to the new 'getPreferredType' method, 
which takes the 'type' and 'size'.  Thus, if a subclass wants to influence the 
type based on the size, it can simple override this method. 

InformixDictionary.java:
First, in this class I added/override the new 'getPreferredType' method.  
Within this method we can change the type of 'VARCHAR' to 'LONGVARCHAR' when 
the size is greater than 255.
Second, I noticed that in the method 'getColumns', there is logic to make a 
LONGVARCHAR a CLOB.  Given the changes proposed above, I do not think we want 
to always change a LONGVARCHAR to a CLOB.  As such, I created a new variable 
called 'useClobsForLongVarChar' which the user can set when they want the code 
to apply.

Finally, note that when the type is 'LONGVARCHAR', the longVarcharTypeName this 
maps to in InformixDictionary is this:
         longVarcharTypeName = "TEXT";

It was stated that LVARCHAR should be used, rather than TEXT.  However, for 
regression purposes, we'd like to leave the type name as TEXT, and allow the 
user to override it if necessary by setting the following property:
<propery name="openjpa.jdbc.DBDictionary" 
value="org.apache.openjpa.jdbc.sql.InformixDictionary(longVarcharTypeName=LVARCHAR)"/>

Thanks,

Heath

> Long strings are improperly mapped on Informix
> ----------------------------------------------
>
>                 Key: OPENJPA-1420
>                 URL: https://issues.apache.org/jira/browse/OPENJPA-1420
>             Project: OpenJPA
>          Issue Type: Bug
>          Components: jdbc
>    Affects Versions: 1.2.1
>         Environment: Windows XP 32-bit, Informix 11.5 database
>            Reporter: Marc Boudreau
>            Priority: Minor
>         Attachments: OPENJPA-1420.diff.txt
>
>
> The field:
> @Basic
> @Column(length=4000)
> private String description;
> gets mapped to VARCHAR(4000) which is illegal on Informix.  The limit for 
> VARCHAR on Informix is 255.  The field should be mapped to LVARCHAR, which 
> supports up to 32767 characters on Informix. TEXT  should only be used if the 
> @Lob annotation is included, because this type can't be indexed.
> This is my test entity:
> MyEntity.java: 
> @Entity 
> public class MyEntity { 
>       @Id 
>       private int id; 
>       @Basic 
>       @Column(length=4000) 
>       private String description; 
>       public int getId() { 
>             return id; 
>       } 
>       public void setId(int value) { 
>             id = value; 
>       } 
>       public String getDescription() { 
>             return description; 
>       } 
>       public void setDescription(String value) { 
>             description = value; 
>       } 
> }
> This is what is dumped to the console:
> 2737  isvi  INFO   [main] openjpa.Runtime - Starting OpenJPA 1.2.1, 
> 2951  isvi  INFO   [main] openjpa.jdbc.JDBC - Using dictionary class 
> "org.apache.openjpa.jdbc.sql.InformixDictionary". 
> Exception in thread "main" <openjpa-1.2.1-r752877:753278 nonfatal general 
> error> org.apache.openjpa.persistence.PersistenceException: IDS SQL Error: 
> SQLCODE=-650, SQLSTATE=IX000, SQLERRMC=null, DRIVER=3.51.90 {stmnt 
> 809054265 CREATE TABLE MyEntity (id INTEGER NOT NULL, description VARCHAR 
> (4000), PRIMARY KEY (id)) LOCK MODE ROW} [code=-650, state=IX000] 
>       at org.apache.openjpa.jdbc.meta.MappingTool.record 
> (MappingTool.java:553) 
>       at org.apache.openjpa.jdbc.meta.MappingTool.record 
> (MappingTool.java:453) 
>       at 
> org.apache.openjpa.jdbc.kernel.JDBCBrokerFactory.synchronizeMappings 
> (JDBCBrokerFactory.java:159) 
>       at org.apache.openjpa.jdbc.kernel.JDBCBrokerFactory.newBrokerImpl 
> (JDBCBrokerFactory.java:119) 
>       at org.apache.openjpa.kernel.AbstractBrokerFactory.newBroker 
> (AbstractBrokerFactory.java:189)) 
>       at org.apache.openjpa.kernel.DelegatingBrokerFactory.newBroker 
> (DelegatingBrokerFactory.java:142) 
>       at 
> org.apache.openjpa.persistence.EntityManagerFactoryImpl.createEntityManager 
> (EntityManagerFactoryImpl.java:192) 
>       at 
> org.apache.openjpa.persistence.EntityManagerFactoryImpl.createEntityManager 
> (EntityManagerFactoryImpl.java:145) 
>       at 
> org.apache.openjpa.persistence.EntityManagerFactoryImpl.createEntityManager 
> (EntityManagerFactoryImpl.java:56)) 
>       at jpa.test.isvi.Main.run(Main.java:12) 
>       at jpa.test.isvi.Main.main(Main.java:53) 
> Caused by: org.apache.openjpa.lib.jdbc.ReportingSQLException: IDS SQL 
> Error: SQLCODE=-650, SQLSTATE=IX000, SQLERRMC=null, DRIVER=3.51.90 {stmnt 
> 809054265 CREATE TABLE MyEntity (id INTEGER NOT NULL, description VARCHAR 
> (4000), PRIMARY KEY (id)) LOCK MODE ROW} [code=-650, state=IX000] 
>       at org.apache.openjpa.lib.jdbc.LoggingConnectionDecorator.wrap 
> (LoggingConnectionDecorator.java:192) 
>       at org.apache.openjpa.lib.jdbc.LoggingConnectionDecorator.access$700 
> (LoggingConnectionDecorator.java:57), 
>       at org.apache.openjpa.lib.jdbc.LoggingConnectionDecorator 
> $LoggingConnection$LoggingStatement.executeUpdate 
> (LoggingConnectionDecorator.java:762) 
>       at org.apache.openjpa.lib.jdbc.DelegatingStatement.executeUpdate 
> (DelegatingStatement.java:114) 
>       at org.apache.openjpa.jdbc.schema.SchemaTool.executeSQL 
> (SchemaTool.java:1191) 
>       at org.apache.openjpa.jdbc.schema.SchemaTool.createTable 
> (SchemaTool.java:949) 
>       at org.apache.openjpa.jdbc.schema.SchemaTool.add(SchemaTool.java:526) 
>       at org.apache.openjpa.jdbc.schema.SchemaTool.add(SchemaTool.java:344) 
>       at org.apache.openjpa.jdbc.schema.SchemaTool.run(SchemaTool.java:321) 
>       at org.apache.openjpa.jdbc.meta.MappingTool.record 
> (MappingTool.java:501): 
>       ... 10 more 

-- 
This message is automatically generated by JIRA.
-
You can reply to this email to add a comment to the issue online.

Reply via email to