OPENJPA-271, add DB2 JDBC driver 2 support

- datePrecision set to MICRO, (Timesptamp in micro-second in DB2)
- save version strategy in Column (needed for specialized TimestampVersionStrategy)
- set storeCharsAsNumbers to false (DB2 default - store chars as chars)

git-svn-id: https://svn.apache.org/repos/asf/openjpa/trunk@552078 13f79535-47bb-0310-9956-ffa450edef68
This commit is contained in:
David J. Wisneski 2007-06-30 02:33:35 +00:00
parent 5c4a8c7e73
commit 9975362f1f
4 changed files with 161 additions and 75 deletions

View File

@ -101,6 +101,7 @@ public abstract class ColumnVersionStrategy
tmplate.setName("versn"); tmplate.setName("versn");
Column[] cols = info.getColumns(vers, new Column[]{ tmplate }, adapt); Column[] cols = info.getColumns(vers, new Column[]{ tmplate }, adapt);
cols[0].setVersionStrategy(this);
vers.setColumns(cols); vers.setColumns(cols);
vers.setColumnIO(info.getColumnIO()); vers.setColumnIO(info.getColumnIO());

View File

@ -28,6 +28,7 @@ import java.sql.Types;
import org.apache.commons.lang.StringUtils; import org.apache.commons.lang.StringUtils;
import org.apache.openjpa.jdbc.meta.JavaSQLTypes; import org.apache.openjpa.jdbc.meta.JavaSQLTypes;
import org.apache.openjpa.jdbc.meta.VersionStrategy;
import org.apache.openjpa.meta.JavaTypes; import org.apache.openjpa.meta.JavaTypes;
import serp.util.Numbers; import serp.util.Numbers;
@ -70,7 +71,8 @@ public class Column
private int _index = 0; private int _index = 0;
private boolean _pk = false; private boolean _pk = false;
private VersionStrategy _versionStrategy = null;
/** /**
* Default constructor. * Default constructor.
*/ */
@ -715,4 +717,12 @@ public class Column
public boolean isXML() { public boolean isXML() {
return _typeName != null && _typeName.startsWith("XML"); return _typeName != null && _typeName.startsWith("XML");
} }
public VersionStrategy getVersionStrategy() {
return _versionStrategy;
}
public void setVersionStrategy(VersionStrategy strategy) {
this._versionStrategy = strategy;
}
} }

View File

@ -26,22 +26,26 @@ import java.util.Arrays;
import java.util.StringTokenizer; import java.util.StringTokenizer;
import org.apache.openjpa.jdbc.kernel.JDBCFetchConfiguration; import org.apache.openjpa.jdbc.kernel.JDBCFetchConfiguration;
import org.apache.openjpa.jdbc.schema.Sequence; import org.apache.openjpa.jdbc.schema.Sequence;
import org.apache.openjpa.lib.util.Localizer;
import org.apache.openjpa.util.OpenJPAException; import org.apache.openjpa.util.OpenJPAException;
import org.apache.openjpa.util.UnsupportedException;
/** /**
* Dictionary for IBM DB2 database. * Dictionary for IBM DB2 database.
*/ */
public class DB2Dictionary public class DB2Dictionary
extends AbstractDB2Dictionary { extends AbstractDB2Dictionary {
private static final Localizer _loc = Localizer.forPackage
(DB2Dictionary.class);
public String optimizeClause = "optimize for"; public String optimizeClause = "optimize for";
public String rowClause = "row"; public String rowClause = "row";
private int db2ServerType = 0; protected int db2ServerType = 0;
private static final int db2ISeriesV5R3OrEarlier = 1; protected static final int db2ISeriesV5R3OrEarlier = 1;
private static final int db2UDBV81OrEarlier = 2; protected static final int db2UDBV81OrEarlier = 2;
private static final int db2ZOSV8xOrLater = 3; protected static final int db2ZOSV8xOrLater = 3;
private static final int db2UDBV82OrLater = 4; protected static final int db2UDBV82OrLater = 4;
private static final int db2ISeriesV5R4OrLater = 5; protected static final int db2ISeriesV5R4OrLater = 5;
private static final String forUpdateOfClause = "FOR UPDATE OF"; private static final String forUpdateOfClause = "FOR UPDATE OF";
private static final String withRSClause = "WITH RS"; private static final String withRSClause = "WITH RS";
private static final String withRRClause = "WITH RR"; private static final String withRRClause = "WITH RR";
@ -50,6 +54,10 @@ public class DB2Dictionary
private static final String useKeepExclusiveLockClause private static final String useKeepExclusiveLockClause
= "USE AND KEEP EXCLUSIVE LOCKS"; = "USE AND KEEP EXCLUSIVE LOCKS";
private static final String forReadOnlyClause = "FOR READ ONLY"; private static final String forReadOnlyClause = "FOR READ ONLY";
protected String databaseProductName = null;
protected String databaseProductVersion = null;
protected int maj = 0;
protected int min = 0;
public DB2Dictionary() { public DB2Dictionary() {
platform = "DB2"; platform = "DB2";
@ -70,6 +78,8 @@ public class DB2Dictionary
varbinaryTypeName = "BLOB(1M)"; varbinaryTypeName = "BLOB(1M)";
clobTypeName = "CLOB(1M)"; clobTypeName = "CLOB(1M)";
longVarcharTypeName = "LONG VARCHAR"; longVarcharTypeName = "LONG VARCHAR";
datePrecision = MICRO;
storeCharsAsNumbers = false;
fixedSizeTypeNameSet.addAll(Arrays.asList(new String[]{ fixedSizeTypeNameSet.addAll(Arrays.asList(new String[]{
"LONG VARCHAR FOR BIT DATA", "LONG VARCHAR", "LONG VARGRAPHIC", "LONG VARCHAR FOR BIT DATA", "LONG VARCHAR", "LONG VARGRAPHIC",
@ -186,48 +196,78 @@ public class DB2Dictionary
super.connectedConfiguration(conn); super.connectedConfiguration(conn);
DatabaseMetaData metaData = conn.getMetaData(); DatabaseMetaData metaData = conn.getMetaData();
if (isJDBC3(metaData)) { databaseProductName = metaData.getDatabaseProductName();
int maj = metaData.getDatabaseMajorVersion(); databaseProductVersion = metaData.getDatabaseProductVersion();
int min = metaData.getDatabaseMinorVersion();
// Determine the type of DB2 database
// First check for AS/400
getProductVersionMajorMinorForISeries();
// Determine the type of DB2 database if (maj > 0) {
if (isDB2ISeriesV5R3OrEarlier(metaData)) if (isDB2ISeriesV5R3OrEarlier())
db2ServerType = db2ISeriesV5R3OrEarlier; db2ServerType = db2ISeriesV5R3OrEarlier;
else if (isDB2UDBV81OrEarlier(metaData,maj,min)) else if (isDB2ISeriesV5R4OrLater())
db2ServerType = db2UDBV81OrEarlier; db2ServerType = db2ISeriesV5R4OrLater;
else if (isDB2ZOSV8xOrLater(metaData,maj)) }
db2ServerType = db2ZOSV8xOrLater;
else if (isDB2UDBV82OrLater(metaData,maj,min)) if (db2ServerType == 0) {
db2ServerType = db2UDBV82OrLater; if (isJDBC3(metaData)) {
else if (isDB2ISeriesV5R4OrLater(metaData)) maj = metaData.getDatabaseMajorVersion();
db2ServerType = db2ISeriesV5R4OrLater; min = metaData.getDatabaseMinorVersion();
}
else
getProductVersionMajorMinor();
if (maj >= 9 || (maj == 8 && min >= 2)) { // Determine the type of DB2 database for ZOS & UDB
supportsLockingWithMultipleTables = true; if (isDB2UDBV81OrEarlier())
supportsLockingWithInnerJoin = true; db2ServerType = db2UDBV81OrEarlier;
supportsLockingWithOuterJoin = true; else if (isDB2ZOSV8xOrLater())
forUpdateClause = "WITH RR USE AND KEEP UPDATE LOCKS"; db2ServerType = db2ZOSV8xOrLater;
if (maj >=9) else if (isDB2UDBV82OrLater())
supportsXMLColumn = true; db2ServerType = db2UDBV82OrLater;
} }
if (metaData.getDatabaseProductVersion().indexOf("DSN") != -1) { // verify that databae product is supported
// DB2 Z/OS if (db2ServerType == 0 || maj == 0)
characterColumnSize = 255; throw new UnsupportedException(_loc.get("db-not-supported",
lastGeneratedKeyQuery = "SELECT IDENTITY_VAL_LOCAL() FROM " new Object[] {databaseProductName, databaseProductVersion }));
+ "SYSIBM.SYSDUMMY1";
nextSequenceQuery = "SELECT NEXTVAL FOR {0} FROM " if (maj >= 9 || (maj == 8 && min >= 2)) {
+ "SYSIBM.SYSDUMMY1"; supportsLockingWithMultipleTables = true;
sequenceSQL = "SELECT SCHEMA AS SEQUENCE_SCHEMA, " supportsLockingWithInnerJoin = true;
+ "NAME AS SEQUENCE_NAME FROM SYSIBM.SYSSEQUENCES"; supportsLockingWithOuterJoin = true;
sequenceSchemaSQL = "SCHEMA = ?"; forUpdateClause = "WITH RR USE AND KEEP UPDATE LOCKS";
sequenceNameSQL = "NAME = ?"; if (maj >=9)
if (maj == 8) { supportsXMLColumn = true;
// DB2 Z/OS Version 8: no bigint support, hence map Java }
// long to decimal
bigintTypeName = "DECIMAL(31,0)"; // platform specific settings
} switch (db2ServerType) {
} case db2ZOSV8xOrLater:
// DB2 Z/OS
characterColumnSize = 255;
lastGeneratedKeyQuery = "SELECT IDENTITY_VAL_LOCAL() FROM "
+ "SYSIBM.SYSDUMMY1";
nextSequenceQuery = "SELECT NEXTVAL FOR {0} FROM "
+ "SYSIBM.SYSDUMMY1";
sequenceSQL = "SELECT SCHEMA AS SEQUENCE_SCHEMA, "
+ "NAME AS SEQUENCE_NAME FROM SYSIBM.SYSSEQUENCES";
sequenceSchemaSQL = "SCHEMA = ?";
sequenceNameSQL = "NAME = ?";
if (maj == 8)
// DB2 Z/OS Version 8: no bigint support, hence map Java
// long to decimal
bigintTypeName = "DECIMAL(31,0)";
break;
case db2ISeriesV5R3OrEarlier:
case db2ISeriesV5R4OrLater:
validationSQL = "SELECT DISTINCT(CURRENT TIMESTAMP) FROM "
+ "QSYS2.SYSTABLES";
sequenceSQL = "SELECT SEQUENCE_SCHEMA, "
+ "SEQUENCE_NAME FROM QSYS2.SYSSEQUENCES";
sequenceSchemaSQL = "SEQUENCE_SCHEMA = ?";
sequenceNameSQL = "SEQUENCE_NAME = ?";
break;
} }
} }
@ -291,68 +331,101 @@ public class DB2Dictionary
return forUpdateString.toString(); return forUpdateString.toString();
} }
public boolean isDB2UDBV82OrLater(DatabaseMetaData metadata, int maj, public boolean isDB2UDBV82OrLater() throws SQLException {
int min) throws SQLException {
boolean match = false; boolean match = false;
if (metadata.getDatabaseProductVersion().indexOf("SQL") != -1 if ((databaseProductVersion.indexOf("SQL") != -1
|| databaseProductName.indexOf("DB2/") != -1)
&& ((maj == 8 && min >= 2) ||(maj >= 8))) && ((maj == 8 && min >= 2) ||(maj >= 8)))
match = true; match = true;
return match; return match;
} }
public boolean isDB2ZOSV8xOrLater(DatabaseMetaData metadata, int maj) public boolean isDB2ZOSV8xOrLater()
throws SQLException { throws SQLException {
boolean match = false; boolean match = false;
if (metadata.getDatabaseProductVersion().indexOf("DSN") != -1 if ((databaseProductVersion.indexOf("DSN") != -1
|| databaseProductName.indexOf("DB2/") == -1)
&& maj >= 8) && maj >= 8)
match = true; match = true;
return match; return match;
} }
public boolean isDB2ISeriesV5R3OrEarlier(DatabaseMetaData metadata) public boolean isDB2ISeriesV5R3OrEarlier()
throws SQLException { throws SQLException {
boolean match = false; boolean match = false;
if (metadata.getDatabaseProductVersion().indexOf("AS") != -1 if (databaseProductName.indexOf("AS") != -1
&& generateVersionNumber(metadata.getDatabaseProductVersion()) && maj == 5 && min <=3)
<= 530)
match = true; match = true;
return match; return match;
} }
public boolean isDB2ISeriesV5R4OrLater(DatabaseMetaData metadata) public boolean isDB2ISeriesV5R4OrLater()
throws SQLException { throws SQLException {
boolean match = false; boolean match = false;
if (metadata.getDatabaseProductVersion().indexOf("AS") != -1 if (databaseProductName.indexOf("AS") != -1
&& generateVersionNumber(metadata.getDatabaseProductVersion()) && maj >= 5 && min >=4)
>= 540)
match = true; match = true;
return match; return match;
} }
public boolean isDB2UDBV81OrEarlier(DatabaseMetaData metadata, int maj, public boolean isDB2UDBV81OrEarlier() throws SQLException {
int min) throws SQLException {
boolean match = false; boolean match = false;
if (metadata.getDatabaseProductVersion().indexOf("SQL") != -1 && if ((databaseProductVersion.indexOf("SQL") != -1
|| databaseProductName.indexOf("DB2/") != -1) &&
((maj == 8 && min <= 1)|| maj < 8)) ((maj == 8 && min <= 1)|| maj < 8))
match = true; match = true;
return match; return match;
} }
/** Get the version number for the ISeries /** Get the version Major/Minor for the ISeries
*/ */
protected int generateVersionNumber(String versionString) { private void getProductVersionMajorMinorForISeries() {
String s = versionString.substring(versionString.indexOf('V')); // ISeries DBProdName DB2 UDB for AS/400
s = s.toUpperCase(); // (Toolbox)DBProdVersion 05.04.0000 V5R4m0
int i = -1; // ISeries DB2 UDB for AS/400
StringTokenizer stringtokenizer = new StringTokenizer(s, "VRM", false); // (Native) V5R4M0
if (stringtokenizer.countTokens() == 3) if (databaseProductName.indexOf("AS") != -1) {
{ String s = databaseProductVersion.substring(databaseProductVersion
String s1 = stringtokenizer.nextToken(); .indexOf('V'));
s1 = s1 + stringtokenizer.nextToken(); s = s.toUpperCase();
s1 = s1 + stringtokenizer.nextToken();
i = Integer.parseInt(s1); StringTokenizer stringtokenizer = new StringTokenizer(s, "VRM"
, false);
if (stringtokenizer.countTokens() == 3) {
String s1 = stringtokenizer.nextToken();
maj = Integer.parseInt(s1);
String s2 = stringtokenizer.nextToken();
min = Integer.parseInt(s2);
}
}
}
private void getProductVersionMajorMinor() {
// Incase JDBC driver version is lower than 3
// use following info to determine Major and Minor
// CLI vs JCC
// ZDBV8 DBProdName DB2 DB2
// DBProdVersion 08.01.0005 DSN08015
// ZDBV9 DB2 DB2
// 09.01.0005 DSN09015
// WinV9 DB2/NT DB2/NT
// 09.01.0000 SQL09010
// SolarisV9 DB2/SUN64
// SQL0901
// Linux DB2/LINUX DB2/LINUX
// 09.01.0000 SQL0901
if (databaseProductVersion.indexOf("09") != -1) {
maj = 9;
if (databaseProductVersion.indexOf("01") != -1) {
min = 1;
}
} else if (databaseProductVersion.indexOf("08") != -1) {
maj = 8;
min = 2;
if (databaseProductVersion.indexOf("01") != -1) {
min = 1;
}
} }
return i;
} }
public SQLBuffer toSelect(Select sel, boolean forUpdate, public SQLBuffer toSelect(Select sel, boolean forUpdate,

View File

@ -889,6 +889,8 @@ public class DBDictionary
setDate(stmnt, idx, new java.sql.Date(val.getTime()), null, col); setDate(stmnt, idx, new java.sql.Date(val.getTime()), null, col);
else if (col != null && col.getType() == Types.TIME) else if (col != null && col.getType() == Types.TIME)
setTime(stmnt, idx, new Time(val.getTime()), null, col); setTime(stmnt, idx, new Time(val.getTime()), null, col);
else if (val instanceof Timestamp)
setTimestamp(stmnt, idx,(Timestamp)val, null, col);
else else
setTimestamp(stmnt, idx, new Timestamp(val.getTime()), null, col); setTimestamp(stmnt, idx, new Timestamp(val.getTime()), null, col);
} }