OPENJPA-1308:

Remove extraneous cast of VARCHAR to VARCHAR for DB2.
Submitted By: B.J. Reed

git-svn-id: https://svn.apache.org/repos/asf/openjpa/trunk@828772 13f79535-47bb-0310-9956-ffa450edef68
This commit is contained in:
Michael Dick 2009-10-22 16:19:17 +00:00
parent 5d793884e6
commit 105d46c6ea
9 changed files with 220 additions and 72 deletions

View File

@ -43,7 +43,11 @@ public class ToLowerCase
DBDictionary dict = ctx.store.getDBDictionary();
String func = dict.toLowerCaseFunction;
dict.assertSupport(func != null, "ToLowerCaseFunction");
func = dict.getCastFunction(getValue(), func);
if (getValue() instanceof PCPath) {
func = dict.getCastFunction(getValue(), func, ((PCPath) getValue()).getFieldMapping(state).getColumns()[0]);
} else {
func = dict.getCastFunction(getValue(), func);
}
int idx = func.indexOf("{0}");
buf.append(func.substring(0, idx));

View File

@ -43,7 +43,11 @@ public class ToUpperCase
DBDictionary dict = ctx.store.getDBDictionary();
String func = dict.toUpperCaseFunction;
dict.assertSupport(func != null, "ToUpperCaseFunction");
func = dict.getCastFunction(getValue(), func);
if (getValue() instanceof PCPath) {
func = dict.getCastFunction(getValue(), func, ((PCPath) getValue()).getFieldMapping(state).getColumns()[0]);
} else {
func = dict.getCastFunction(getValue(), func);
}
int idx = func.indexOf("{0}");
buf.append(func.substring(0, idx));

View File

@ -38,13 +38,9 @@ public abstract class AbstractDB2Dictionary
// DB2-based databases have restrictions on having uncast parameters
// in string functions
toUpperCaseFunction = "UPPER(CAST({0} AS VARCHAR(" + varcharCastLength
+ ")))";
toLowerCaseFunction = "LOWER(CAST({0} AS VARCHAR(" + varcharCastLength
+ ")))";
stringLengthFunction = "LENGTH({0})";
concatenateFunction = "(CAST({0} AS VARCHAR(" + varcharCastLength
+ ")) || CAST({1} AS VARCHAR(1000)))";
+ ")) || CAST({1} AS VARCHAR(" + varcharCastLength + ")))";
trimLeadingFunction = "LTRIM({0})";
trimTrailingFunction = "RTRIM({0})";
@ -60,6 +56,7 @@ public abstract class AbstractDB2Dictionary
supportsLockingWithOuterJoin = false;
supportsLockingWithInnerJoin = false;
supportsLockingWithSelectRange = true;
supportsCaseConversionForLob = true;
requiresAutoCommitForMetaData = true;
requiresAliasForSubselect = true;

View File

@ -763,9 +763,36 @@ public class DB2Dictionary
* @return a String with the correct CAST function syntax
*/
public String getCastFunction(Val val, String func) {
if (val instanceof Lit || val instanceof Param)
if (func.indexOf("VARCHAR") == -1)
func = addCastAsString(func, "{0}", " AS VARCHAR(1000)");
if (val instanceof Lit || val instanceof Param) {
if (func.indexOf("VARCHAR") == -1) {
func = addCastAsString(func, "{0}", " AS VARCHAR(" + varcharCastLength + ")");
}
}
return func;
}
/**
* Return the correct CAST function syntax
*
* @param val operand of cast
* @param func original string
* @param col database column
* @return a String with the correct CAST function syntax
*/
public String getCastFunction(Val val, String func, Column col) {
boolean doCast = false;
if (val instanceof Lit || val instanceof Param) {
doCast = true;
}
// cast anything not already a VARCHAR to VARCHAR
if (col.getType() != Types.VARCHAR) {
doCast = true;
}
if (doCast == true) {
if (func.indexOf("VARCHAR") == -1) {
func = addCastAsString(func, "{0}", " AS VARCHAR(" + varcharCastLength + ")");
}
}
return func;
}

View File

@ -240,6 +240,7 @@ public class DBDictionary
public boolean requiresCastForComparisons = false;
public boolean supportsModOperator = false;
public boolean supportsXMLColumn = false;
public boolean supportsCaseConversionForLob = false;
public boolean reportsSuccessNoInfoOnBatchUpdates = false;
public boolean supportsSelectFromFinalTable = false;
public boolean supportsSimpleCaseExpression = true;
@ -4798,6 +4799,19 @@ public class DBDictionary
public String getCastFunction(Val val, String func) {
return func;
}
/**
* Return the correct CAST function syntax. This should be overriden by subclasses
* that need access to the Column information.
*
* @param val operand of cast
* @param func original string
* @param col database column
* @return a String with the correct CAST function syntax
*/
public String getCastFunction(Val val, String func, Column col) {
return getCastFunction (val, func);
}
/**
* Create an index if necessary for some database tables

View File

@ -45,6 +45,8 @@ public class DerbyDictionary
validationSQL = "VALUES(1)";
stringLengthFunction = "LENGTH({0})";
substringFunctionName = "SUBSTR";
toUpperCaseFunction = "UPPER(CAST({0} AS VARCHAR(" + varcharCastLength + ")))";
toLowerCaseFunction = "LOWER(CAST({0} AS VARCHAR(" + varcharCastLength + ")))";
// Derby name length restriction has been relaxed
//http://www.archivum.info/derby-dev@db.apache.org/2004-12/msg00270.html

View File

@ -18,94 +18,135 @@
*/
package org.apache.openjpa.persistence.common.apps;
import javax.persistence.*;
import org.apache.openjpa.persistence.*;
import javax.persistence.Basic;
import javax.persistence.CascadeType;
import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.Enumerated;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;
import javax.persistence.Inheritance;
import javax.persistence.InheritanceType;
import javax.persistence.JoinColumn;
import javax.persistence.Lob;
import javax.persistence.OneToOne;
import java.util.*;
import org.apache.openjpa.persistence.PersistentCollection;
@Entity
@Inheritance(strategy=InheritanceType.SINGLE_TABLE)
public class CompUser
{
@Basic
@Column(length=50)
private String name;
@Inheritance(strategy = InheritanceType.SINGLE_TABLE)
public class CompUser {
@Basic
@Column(length = 50)
private String name;
@Basic
private int age;
@Basic
private int age;
@Basic
@Column(name="compName", length=50)
private String computerName;
@Basic
@Column(name = "compName", length = 50)
private String computerName;
@PersistentCollection
private String[] nicknames = new String[0];
@Basic
@Lob
private String nameAsLob;
@OneToOne(cascade={CascadeType.PERSIST, CascadeType.REMOVE})
@JoinColumn(name="ADD_ID")
private Address address;
@PersistentCollection
private String[] nicknames = new String[0];
@OneToOne(cascade = { CascadeType.PERSIST, CascadeType.REMOVE })
@JoinColumn(name = "ADD_ID")
private Address address;
@Id
@GeneratedValue(strategy = GenerationType.AUTO)
public int userid;
@Id
@GeneratedValue(strategy=GenerationType.AUTO)
public int userid;
@Enumerated
@Basic
private CreditRating creditRating;
public CompUser(){}
public CompUser(String name, String cName, Address address, int age)
{
this.name = name;
this.computerName = cName;
this.address = address;
this.age = age;
}
public CompUser() {
}
public String getComputerName() {
return computerName;
}
public CompUser(String name, String cName, Address address, int age) {
this.name = name;
this.computerName = cName;
this.address = address;
this.age = age;
this.nameAsLob = name;
}
public void setComputerName(String computerName) {
this.computerName = computerName;
}
public String getComputerName() {
return computerName;
}
public String getName() {
return name;
}
public void setComputerName(String computerName) {
this.computerName = computerName;
}
public void setName(String name) {
this.name = name;
}
public String getName() {
return name;
}
public int getUserid() {
return userid;
}
public void setName(String name) {
this.name = name;
}
public Address getAddress() {
return address;
}
public int getUserid() {
return userid;
}
public void setAddress(Address address) {
this.address = address;
}
public Address getAddress() {
return address;
}
public int getAge() {
return age;
}
public void setAddress(Address address) {
this.address = address;
}
public void setAge(int age) {
this.age = age;
}
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
public String getNameAsLob() {
return nameAsLob;
}
public void setNameAsLob(String nameAsLob) {
this.nameAsLob = nameAsLob;
}
public CreditRating getRating() {
return creditRating;
}
public void setRating(CreditRating rating) {
this.creditRating = rating;
}
public enum CreditRating { POOR, GOOD, EXCELLENT };
public enum CreditRating {
POOR, GOOD, EXCELLENT
};
public String[] getNicknames() {
return nicknames;
}
public void setNicknames(String[] nicknames) {
this.nicknames = nicknames;
}
public CreditRating getCreditRating() {
return creditRating;
}
public void setCreditRating(CreditRating creditRating) {
this.creditRating = creditRating;
}
}

View File

@ -313,12 +313,14 @@ public class TestEJBQLCondExpression extends AbstractTestCase {
user.setComputerName(cName);
user.setAddress(add);
user.setAge(age);
user.setNameAsLob(name);
} else {
user = new FemaleUser();
user.setName(name);
user.setComputerName(cName);
user.setAddress(add);
user.setAge(age);
user.setNameAsLob(name);
}
return user;
}

View File

@ -24,6 +24,7 @@ import javax.persistence.EntityManager;
import org.apache.openjpa.jdbc.conf.JDBCConfiguration;
import org.apache.openjpa.jdbc.sql.DBDictionary;
import org.apache.openjpa.jdbc.sql.OracleDictionary;
import org.apache.openjpa.persistence.OpenJPAEntityManagerSPI;
import org.apache.openjpa.persistence.common.apps.Address;
import org.apache.openjpa.persistence.common.apps.CompUser;
import org.apache.openjpa.persistence.common.apps.FemaleUser;
@ -196,6 +197,33 @@ public class TestEJBQLFunction extends AbstractTestCase {
endEm(em);
}
public void testLowerClobFunc() {
OpenJPAEntityManagerSPI em = (OpenJPAEntityManagerSPI) currentEntityManager();
// some databases do not support case conversion on LOBs,
// just skip this test case
DBDictionary dict = ((JDBCConfiguration) em.getConfiguration()).getDBDictionaryInstance();
if (!dict.supportsCaseConversionForLob) {
return;
}
startTx(em);
CompUser user = em.find(CompUser.class, userid5);
assertNotNull(user);
assertEquals("Famzy", user.getName());
String query = "UPDATE CompUser e SET e.name = LOWER(e.name) WHERE LOWER(e.nameAsLob)='famzy'";
int result = em.createQuery(query).executeUpdate();
user = em.find(CompUser.class, userid5);
em.refresh(user);
assertNotNull(user);
assertEquals("famzy", user.getName());
endTx(em);
endEm(em);
}
public void testUpperFunc() {
EntityManager em = currentEntityManager();
startTx(em);
@ -218,6 +246,33 @@ public class TestEJBQLFunction extends AbstractTestCase {
endEm(em);
}
public void testUpperClobFunc() {
OpenJPAEntityManagerSPI em = (OpenJPAEntityManagerSPI) currentEntityManager();
// some databases do not support case conversion on LOBs,
// just skip this test case
DBDictionary dict = ((JDBCConfiguration) em.getConfiguration()).getDBDictionaryInstance();
if (!dict.supportsCaseConversionForLob) {
return;
}
startTx(em);
CompUser user = em.find(CompUser.class, userid5);
assertNotNull(user);
assertEquals("Famzy", user.getName());
String query = "UPDATE CompUser e SET e.name = UPPER(e.name) WHERE UPPER(e.nameAsLob)='FAMZY'";
int result = em.createQuery(query).executeUpdate();
user = em.find(CompUser.class, userid5);
em.refresh(user);
assertNotNull(user);
assertEquals("FAMZY", user.getName());
endTx(em);
endEm(em);
}
public void testLengthFunc() {
EntityManager em = currentEntityManager();
@ -415,12 +470,14 @@ public class TestEJBQLFunction extends AbstractTestCase {
user.setComputerName(cName);
user.setAddress(add);
user.setAge(age);
user.setNameAsLob(name);
} else {
user = new FemaleUser();
user.setName(name);
user.setComputerName(cName);
user.setAddress(add);
user.setAge(age);
user.setNameAsLob(name);
}
return user;
}