mirror of https://github.com/apache/openjpa.git
OPENJPA-962 Committing code and tests contributed by Dianne Richards
git-svn-id: https://svn.apache.org/repos/asf/openjpa/trunk@774860 13f79535-47bb-0310-9956-ffa450edef68
This commit is contained in:
parent
df96cc6129
commit
e1ccb46414
|
@ -366,8 +366,18 @@ public class TableJDBCSeq
|
||||||
* Creates the object-level representation of the sequence table.
|
* Creates the object-level representation of the sequence table.
|
||||||
*/
|
*/
|
||||||
private void buildTable() {
|
private void buildTable() {
|
||||||
String tableName = Strings.getClassName(_table);
|
String tableName = null;
|
||||||
String schemaName = Strings.getPackageName(_table);
|
String schemaName = "";
|
||||||
|
if (StringUtils.contains(_table,'.')) {
|
||||||
|
String[] tableParts = StringUtils.split(_table, '.');
|
||||||
|
// TODO: do we need to check for length? Could we have xxx. or .xxx?
|
||||||
|
schemaName = tableParts[0];
|
||||||
|
tableName = tableParts[1];
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
tableName = _table;
|
||||||
|
}
|
||||||
|
|
||||||
if (schemaName.length() == 0)
|
if (schemaName.length() == 0)
|
||||||
schemaName = Schemas.getNewTableSchema(_conf);
|
schemaName = Schemas.getNewTableSchema(_conf);
|
||||||
|
|
||||||
|
|
|
@ -24,6 +24,7 @@ import java.util.Arrays;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
|
||||||
import org.apache.commons.lang.StringUtils;
|
import org.apache.commons.lang.StringUtils;
|
||||||
|
import org.apache.openjpa.conf.OpenJPAConfiguration;
|
||||||
import org.apache.openjpa.jdbc.conf.JDBCSeqValue;
|
import org.apache.openjpa.jdbc.conf.JDBCSeqValue;
|
||||||
import org.apache.openjpa.jdbc.kernel.ClassTableJDBCSeq;
|
import org.apache.openjpa.jdbc.kernel.ClassTableJDBCSeq;
|
||||||
import org.apache.openjpa.jdbc.kernel.TableJDBCSeq;
|
import org.apache.openjpa.jdbc.kernel.TableJDBCSeq;
|
||||||
|
@ -159,10 +160,37 @@ public class SequenceMapping
|
||||||
|
|
||||||
protected void addStandardProperties(StringBuffer props) {
|
protected void addStandardProperties(StringBuffer props) {
|
||||||
super.addStandardProperties(props);
|
super.addStandardProperties(props);
|
||||||
appendProperty(props, PROP_TABLE, _table);
|
// Quotes are conditionally added to the following because the props
|
||||||
appendProperty(props, PROP_SEQUENCE_COL, _sequenceColumn);
|
// are eventually passed to the Configurations.parseProperties()
|
||||||
appendProperty(props, PROP_PK_COL, _primaryKeyColumn);
|
// method, which strips off quotes. This is a problem when these
|
||||||
appendProperty(props, PROP_PK_VALUE, _primaryKeyValue);
|
// properties are intentionally delimited with quotes. So, an extra
|
||||||
|
// set preserves the intended ones. While this is an ugly solution,
|
||||||
|
// it's less ugly than other ones.
|
||||||
|
String table = _table;
|
||||||
|
if (table != null && table.startsWith("\"")
|
||||||
|
&& table.endsWith("\"")) {
|
||||||
|
table = "\"" + table + "\"";
|
||||||
|
}
|
||||||
|
String sequenceColumn = _sequenceColumn;
|
||||||
|
if (sequenceColumn != null && sequenceColumn.startsWith("\"")
|
||||||
|
&& sequenceColumn.endsWith("\"")) {
|
||||||
|
sequenceColumn = "\"" + sequenceColumn + "\"";
|
||||||
|
}
|
||||||
|
String primaryKeyColumn = _primaryKeyColumn;
|
||||||
|
if (primaryKeyColumn !=null && primaryKeyColumn.startsWith("\"")
|
||||||
|
&& primaryKeyColumn.endsWith("\"")) {
|
||||||
|
primaryKeyColumn = "\"" + primaryKeyColumn + "\"";
|
||||||
|
}
|
||||||
|
String primaryKeyValue = _primaryKeyValue;
|
||||||
|
if (primaryKeyValue != null && primaryKeyValue.startsWith("\"")
|
||||||
|
&& primaryKeyValue.endsWith("\"")) {
|
||||||
|
primaryKeyValue = "\"" + primaryKeyValue + "\"";
|
||||||
|
}
|
||||||
|
|
||||||
|
appendProperty(props, PROP_TABLE, table);
|
||||||
|
appendProperty(props, PROP_SEQUENCE_COL, sequenceColumn);
|
||||||
|
appendProperty(props, PROP_PK_COL, primaryKeyColumn);
|
||||||
|
appendProperty(props, PROP_PK_VALUE, primaryKeyValue);
|
||||||
// Array of unique column names are passed to configuration
|
// Array of unique column names are passed to configuration
|
||||||
// as a single string "x|y|z". The configurable (TableJDBCSeq) must
|
// as a single string "x|y|z". The configurable (TableJDBCSeq) must
|
||||||
// parse it back.
|
// parse it back.
|
||||||
|
|
|
@ -488,9 +488,17 @@ public class SchemaGenerator {
|
||||||
Table table;
|
Table table;
|
||||||
String tableSchema;
|
String tableSchema;
|
||||||
for (int i = 0; cols != null && i < cols.length; i++) {
|
for (int i = 0; cols != null && i < cols.length; i++) {
|
||||||
tableName = cols[i].getTableName();
|
// TODO: Is this where we should handle this?
|
||||||
tableSchema = StringUtils.trimToNull(cols[i].getSchemaName());
|
if (tableName == null || tableName.equals("%")) {
|
||||||
|
tableName = cols[i].getTableName();
|
||||||
|
}
|
||||||
|
if (schemaName == null) {
|
||||||
|
tableSchema = StringUtils.trimToNull(cols[i].getSchemaName());
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
tableSchema = schemaName;
|
||||||
|
}
|
||||||
|
|
||||||
// ignore special tables
|
// ignore special tables
|
||||||
if (!_openjpaTables &&
|
if (!_openjpaTables &&
|
||||||
(tableName.toUpperCase().startsWith("OPENJPA_")
|
(tableName.toUpperCase().startsWith("OPENJPA_")
|
||||||
|
|
|
@ -470,6 +470,7 @@ public class SchemaTool {
|
||||||
Table dbTable;
|
Table dbTable;
|
||||||
Column[] cols;
|
Column[] cols;
|
||||||
Column col;
|
Column col;
|
||||||
|
String delim = _dict.getDelimiter();
|
||||||
for (int i = 0; i < schemas.length; i++) {
|
for (int i = 0; i < schemas.length; i++) {
|
||||||
tabs = schemas[i].getTables();
|
tabs = schemas[i].getTables();
|
||||||
for (int j = 0; j < tabs.length; j++) {
|
for (int j = 0; j < tabs.length; j++) {
|
||||||
|
@ -477,14 +478,22 @@ public class SchemaTool {
|
||||||
dbTable = db.findTable(schemas[i], tabs[j].getFullName());
|
dbTable = db.findTable(schemas[i], tabs[j].getFullName());
|
||||||
for (int k = 0; k < cols.length; k++) {
|
for (int k = 0; k < cols.length; k++) {
|
||||||
if (dbTable != null) {
|
if (dbTable != null) {
|
||||||
col = dbTable.getColumn(cols[k].getName());
|
String colName = cols[k].getName();
|
||||||
|
boolean delimCol = false;
|
||||||
|
if (colName.startsWith(delim)
|
||||||
|
&& colName.endsWith(delim)) {
|
||||||
|
colName = colName.substring(1, colName.length()-1);
|
||||||
|
delimCol = true;
|
||||||
|
}
|
||||||
|
col = dbTable.getColumn(colName);
|
||||||
if (col == null) {
|
if (col == null) {
|
||||||
if (addColumn(cols[k]))
|
if (addColumn(cols[k]))
|
||||||
dbTable.importColumn(cols[k]);
|
dbTable.importColumn(cols[k]);
|
||||||
else
|
else
|
||||||
_log.warn(_loc.get("add-col", cols[k],
|
_log.warn(_loc.get("add-col", cols[k],
|
||||||
tabs[j]));
|
tabs[j]));
|
||||||
} else if (!cols[k].equalsColumn(col)) {
|
// TODO: Find a way to compare these with delimCol
|
||||||
|
} else if (!delimCol && !cols[k].equalsColumn(col)) {
|
||||||
_log.warn(_loc.get("bad-col", new Object[]{
|
_log.warn(_loc.get("bad-col", new Object[]{
|
||||||
col, dbTable, col.getDescription(),
|
col, dbTable, col.getDescription(),
|
||||||
cols[k].getDescription() }));
|
cols[k].getDescription() }));
|
||||||
|
|
|
@ -24,6 +24,7 @@ import java.sql.DatabaseMetaData;
|
||||||
import java.sql.SQLException;
|
import java.sql.SQLException;
|
||||||
import java.sql.Types;
|
import java.sql.Types;
|
||||||
import java.util.Arrays;
|
import java.util.Arrays;
|
||||||
|
import java.util.EnumSet;
|
||||||
import java.util.Set;
|
import java.util.Set;
|
||||||
import java.util.StringTokenizer;
|
import java.util.StringTokenizer;
|
||||||
|
|
||||||
|
@ -64,7 +65,7 @@ public class DB2Dictionary
|
||||||
public static final int db2ZOSV8xOrLater = 3;
|
public static final int db2ZOSV8xOrLater = 3;
|
||||||
public static final int db2UDBV82OrLater = 4;
|
public static final int db2UDBV82OrLater = 4;
|
||||||
public static final int db2ISeriesV5R4OrLater = 5;
|
public static final int db2ISeriesV5R4OrLater = 5;
|
||||||
protected static final String forUpdate = "FOR UPDATE";
|
protected static final String forUpdate = "FOR UPDATE";
|
||||||
protected static final String withURClause = "WITH UR";
|
protected static final String withURClause = "WITH UR";
|
||||||
protected static final String withCSClause = "WITH CS";
|
protected static final String withCSClause = "WITH CS";
|
||||||
protected static final String withRSClause = "WITH RS";
|
protected static final String withRSClause = "WITH RS";
|
||||||
|
@ -82,6 +83,9 @@ public class DB2Dictionary
|
||||||
protected int min = 0;
|
protected int min = 0;
|
||||||
|
|
||||||
private int defaultBatchLimit = 100;
|
private int defaultBatchLimit = 100;
|
||||||
|
|
||||||
|
private EnumSet<DBIdentifiers> unsupportedDelimitedIds =
|
||||||
|
EnumSet.of(DBIdentifiers.COLUMN_COLUMN_DEFINITION);
|
||||||
|
|
||||||
public DB2Dictionary() {
|
public DB2Dictionary() {
|
||||||
platform = "DB2";
|
platform = "DB2";
|
||||||
|
@ -244,9 +248,9 @@ public class DB2Dictionary
|
||||||
}
|
}
|
||||||
|
|
||||||
public void connectedConfiguration(Connection conn) throws SQLException {
|
public void connectedConfiguration(Connection conn) throws SQLException {
|
||||||
super.connectedConfiguration(conn);
|
super.connectedConfiguration(conn);
|
||||||
|
|
||||||
DatabaseMetaData metaData = conn.getMetaData();
|
DatabaseMetaData metaData = conn.getMetaData();
|
||||||
String driverName = metaData.getDriverName();
|
String driverName = metaData.getDriverName();
|
||||||
if (driverName != null && driverName.startsWith("IBM DB2"))
|
if (driverName != null && driverName.startsWith("IBM DB2"))
|
||||||
driverVendor = VENDOR_IBM;
|
driverVendor = VENDOR_IBM;
|
||||||
|
@ -267,21 +271,21 @@ public class DB2Dictionary
|
||||||
db2ServerType = db2ISeriesV5R4OrLater;
|
db2ServerType = db2ISeriesV5R4OrLater;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (db2ServerType == 0) {
|
if (db2ServerType == 0) {
|
||||||
if (isJDBC3) {
|
if (isJDBC3) {
|
||||||
maj = metaData.getDatabaseMajorVersion();
|
maj = metaData.getDatabaseMajorVersion();
|
||||||
min = metaData.getDatabaseMinorVersion();
|
min = metaData.getDatabaseMinorVersion();
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
getProductVersionMajorMinor();
|
getProductVersionMajorMinor();
|
||||||
|
|
||||||
// Determine the type of DB2 database for ZOS & UDB
|
// Determine the type of DB2 database for ZOS & UDB
|
||||||
if (isDB2UDBV81OrEarlier())
|
if (isDB2UDBV81OrEarlier())
|
||||||
db2ServerType = db2UDBV81OrEarlier;
|
db2ServerType = db2UDBV81OrEarlier;
|
||||||
else if (isDB2ZOSV8xOrLater())
|
else if (isDB2ZOSV8xOrLater())
|
||||||
db2ServerType = db2ZOSV8xOrLater;
|
db2ServerType = db2ZOSV8xOrLater;
|
||||||
else if (isDB2UDBV82OrLater())
|
else if (isDB2UDBV82OrLater())
|
||||||
db2ServerType = db2UDBV82OrLater;
|
db2ServerType = db2UDBV82OrLater;
|
||||||
}
|
}
|
||||||
|
|
||||||
// verify that database product is supported
|
// verify that database product is supported
|
||||||
|
@ -289,14 +293,14 @@ public class DB2Dictionary
|
||||||
throw new UnsupportedException(_loc.get("db-not-supported",
|
throw new UnsupportedException(_loc.get("db-not-supported",
|
||||||
new Object[] {databaseProductName, databaseProductVersion }));
|
new Object[] {databaseProductName, databaseProductVersion }));
|
||||||
|
|
||||||
if (maj >= 9 || (maj == 8 && min >= 2)) {
|
if (maj >= 9 || (maj == 8 && min >= 2)) {
|
||||||
supportsLockingWithMultipleTables = true;
|
supportsLockingWithMultipleTables = true;
|
||||||
supportsLockingWithInnerJoin = true;
|
supportsLockingWithInnerJoin = true;
|
||||||
supportsLockingWithOuterJoin = true;
|
supportsLockingWithOuterJoin = true;
|
||||||
forUpdateClause = "WITH RR USE AND KEEP UPDATE LOCKS";
|
forUpdateClause = "WITH RR USE AND KEEP UPDATE LOCKS";
|
||||||
if (maj >=9)
|
if (maj >=9)
|
||||||
supportsXMLColumn = true;
|
supportsXMLColumn = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
// platform specific settings
|
// platform specific settings
|
||||||
switch (db2ServerType) {
|
switch (db2ServerType) {
|
||||||
|
@ -843,10 +847,10 @@ public class DB2Dictionary
|
||||||
}
|
}
|
||||||
|
|
||||||
String nullSafe(String s) {
|
String nullSafe(String s) {
|
||||||
return s == null ? "" : s;
|
return s == null ? "" : s;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected Boolean matchErrorState(int subtype, Set<String> errorStates,
|
protected Boolean matchErrorState(int subtype, Set<String> errorStates,
|
||||||
SQLException ex) {
|
SQLException ex) {
|
||||||
Boolean recoverable = null;
|
Boolean recoverable = null;
|
||||||
|
@ -864,4 +868,17 @@ public class DB2Dictionary
|
||||||
}
|
}
|
||||||
return recoverable;
|
return recoverable;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @return the unsupportedDelimitedIds
|
||||||
|
*/
|
||||||
|
@Override
|
||||||
|
protected EnumSet<DBIdentifiers> getUnsupportedDelimitedIds() {
|
||||||
|
return unsupportedDelimitedIds;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected void setDelimitedCase(DatabaseMetaData metaData) {
|
||||||
|
delimitedCase = SCHEMA_CASE_PRESERVE;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -53,6 +53,7 @@ import java.util.Calendar;
|
||||||
import java.util.Collection;
|
import java.util.Collection;
|
||||||
import java.util.Collections;
|
import java.util.Collections;
|
||||||
import java.util.Date;
|
import java.util.Date;
|
||||||
|
import java.util.EnumSet;
|
||||||
import java.util.HashMap;
|
import java.util.HashMap;
|
||||||
import java.util.HashSet;
|
import java.util.HashSet;
|
||||||
import java.util.Iterator;
|
import java.util.Iterator;
|
||||||
|
@ -348,6 +349,36 @@ public class DBDictionary
|
||||||
protected final Set systemTableSet = new HashSet();
|
protected final Set systemTableSet = new HashSet();
|
||||||
protected final Set fixedSizeTypeNameSet = new HashSet();
|
protected final Set fixedSizeTypeNameSet = new HashSet();
|
||||||
protected final Set typeModifierSet = new HashSet();
|
protected final Set typeModifierSet = new HashSet();
|
||||||
|
|
||||||
|
private boolean delimitIds = false;
|
||||||
|
protected boolean supportsDelimitedIds = false;
|
||||||
|
protected String delimiter = "\"";
|
||||||
|
// Assume mixed case by default.
|
||||||
|
protected String delimitedCase = SCHEMA_CASE_PRESERVE;
|
||||||
|
|
||||||
|
// TODO: complete the list
|
||||||
|
public static enum DBIdentifiers {
|
||||||
|
TABLE_NAME,
|
||||||
|
TABLE_SCHEMA,
|
||||||
|
TABLE_CATALOG,
|
||||||
|
SECONDARY_TABLE_NAME,
|
||||||
|
SECONDARY_TABLE_SCHEMA,
|
||||||
|
SECONDARY_TABLE_CATALOG,
|
||||||
|
TABLE_GEN_TABLE,
|
||||||
|
TABLE_GEN_SCHEMA,
|
||||||
|
TABLE_GEN_PK_COLUMN,
|
||||||
|
TABLE_GEN_VALUE_COLUMN,
|
||||||
|
COLUMN_NAME,
|
||||||
|
COLUMN_COLUMN_DEFINITION,
|
||||||
|
COLUMN_TABLE
|
||||||
|
}
|
||||||
|
|
||||||
|
// TODO: describe; maybe make private
|
||||||
|
protected EnumSet<DBIdentifiers> unsupportedDelimitedIds =
|
||||||
|
EnumSet.noneOf(DBIdentifiers.class);
|
||||||
|
// TODO
|
||||||
|
// Should this be EnumSet.<DBIdentifiers>noneOf(....)
|
||||||
|
// or EnumSet<DBIdentifiers>.noneOf....?
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* If a native query begins with any of the values found here then it will
|
* If a native query begins with any of the values found here then it will
|
||||||
|
@ -418,6 +449,10 @@ public class DBDictionary
|
||||||
conn.getAutoCommit(), conn.getHoldability(),
|
conn.getAutoCommit(), conn.getHoldability(),
|
||||||
conn.getTransactionIsolation()}));
|
conn.getTransactionIsolation()}));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// While we have the metaData, set some values from it
|
||||||
|
setSupportsDelimitedIds(metaData);
|
||||||
|
setDelimitedCase(metaData);
|
||||||
}
|
}
|
||||||
connected = true;
|
connected = true;
|
||||||
}
|
}
|
||||||
|
@ -2972,7 +3007,18 @@ public class DBDictionary
|
||||||
name = name.substring(1);
|
name = name.substring(1);
|
||||||
String tableName = table.getName();
|
String tableName = table.getName();
|
||||||
int len = Math.min(tableName.length(), 7);
|
int len = Math.min(tableName.length(), 7);
|
||||||
name = "I_" + shorten(tableName, len) + "_" + name;
|
String shortTableName = shorten(tableName, len);
|
||||||
|
String delim = getDelimiter();
|
||||||
|
if (shortTableName.startsWith(delim)
|
||||||
|
&& shortTableName.endsWith(delim)) {
|
||||||
|
name = delim + "I_"
|
||||||
|
+ shortTableName.substring(1, shortTableName.length() - 1)
|
||||||
|
+ "_" + name + delim;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
name = "I_" + shortTableName + "_" + name;
|
||||||
|
}
|
||||||
|
|
||||||
return makeNameValid(name, table.getSchema().getSchemaGroup(),
|
return makeNameValid(name, table.getSchema().getSchemaGroup(),
|
||||||
maxIndexNameLength, NAME_ANY);
|
maxIndexNameLength, NAME_ANY);
|
||||||
}
|
}
|
||||||
|
@ -3052,17 +3098,26 @@ public class DBDictionary
|
||||||
* '1', etc.
|
* '1', etc.
|
||||||
* Note that the given max len may be 0 if the database metadata is
|
* Note that the given max len may be 0 if the database metadata is
|
||||||
* incomplete.
|
* incomplete.
|
||||||
|
*
|
||||||
|
* Note: If the name is delimited, make sure the ending delimiter is
|
||||||
|
* not stripped off.
|
||||||
*/
|
*/
|
||||||
protected String makeNameValid(String name, NameSet set, int maxLen,
|
protected String makeNameValid(String name, NameSet set, int maxLen,
|
||||||
int nameType, boolean checkForUniqueness) {
|
int nameType, boolean checkForUniqueness) {
|
||||||
|
boolean delimited = false;
|
||||||
|
String delimiter = getDelimiter();
|
||||||
|
if (name.startsWith(delimiter) && name.endsWith(delimiter)) {
|
||||||
|
delimited = true;
|
||||||
|
}
|
||||||
if (maxLen < 1)
|
if (maxLen < 1)
|
||||||
maxLen = 255;
|
maxLen = 255;
|
||||||
if (name.length() > maxLen)
|
if (name.length() > maxLen)
|
||||||
name = name.substring(0, maxLen);
|
name = removeEndingChars(name, name.length() - maxLen,
|
||||||
|
delimited, delimiter);
|
||||||
if (reservedWordSet.contains(name.toUpperCase())) {
|
if (reservedWordSet.contains(name.toUpperCase())) {
|
||||||
if (name.length() == maxLen)
|
if (name.length() == maxLen)
|
||||||
name = name.substring(0, name.length() - 1);
|
name = removeEndingChars(name, 1, delimited, delimiter);
|
||||||
name += "0";
|
name = addCharsToEnd(name, "0", delimited, delimiter);
|
||||||
}
|
}
|
||||||
|
|
||||||
// now make sure the name is unique
|
// now make sure the name is unique
|
||||||
|
@ -3088,16 +3143,65 @@ public class DBDictionary
|
||||||
// a single char for the version is probably enough, but might
|
// a single char for the version is probably enough, but might
|
||||||
// as well be general about it...
|
// as well be general about it...
|
||||||
if (version > 1)
|
if (version > 1)
|
||||||
name = name.substring(0, name.length() - chars);
|
name = removeEndingChars(name, chars, delimited, delimiter);
|
||||||
if (version >= Math.pow(10, chars))
|
if (version >= Math.pow(10, chars))
|
||||||
chars++;
|
chars++;
|
||||||
if (name.length() + chars > maxLen)
|
if (name.length() + chars > maxLen)
|
||||||
name = name.substring(0, maxLen - chars);
|
name = removeEndingChars(name,
|
||||||
name = name + version;
|
name.length() + chars - maxLen,
|
||||||
|
delimited, delimiter);
|
||||||
|
name = addCharsToEnd(name, new Integer(version).toString(),
|
||||||
|
delimited, delimiter);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (delimited) {
|
||||||
|
String delimCase = getDelimitedCase();
|
||||||
|
if (delimCase.equals(SCHEMA_CASE_LOWER)) {
|
||||||
|
return name.toLowerCase();
|
||||||
|
}
|
||||||
|
else if (delimCase.equals(SCHEMA_CASE_UPPER)) {
|
||||||
|
return name.toUpperCase();
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
return name;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// TODO: This is the original. Should the db supported case be checked?
|
||||||
return name.toUpperCase();
|
return name.toUpperCase();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private String removeEndingChars(String name,
|
||||||
|
int charsToRemove,
|
||||||
|
boolean delimited,
|
||||||
|
String delimiter) {
|
||||||
|
if (delimited) {
|
||||||
|
name = name.substring(0, name.length() - delimiter.length());
|
||||||
|
name = name.substring(0, name.length() - charsToRemove);
|
||||||
|
name = name + delimiter;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
name = name.substring(0, name.length() - charsToRemove);
|
||||||
|
}
|
||||||
|
|
||||||
|
return name;
|
||||||
|
}
|
||||||
|
|
||||||
|
private String addCharsToEnd(String name,
|
||||||
|
String charsToAdd,
|
||||||
|
boolean delimited,
|
||||||
|
String delimiter) {
|
||||||
|
if (delimited) {
|
||||||
|
name = name.substring(0, name.length() - delimiter.length());
|
||||||
|
name = name + charsToAdd;
|
||||||
|
name = name + delimiter;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
name = name + charsToAdd;
|
||||||
|
}
|
||||||
|
|
||||||
|
return name;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Return a series of SQL statements to create the given table, complete
|
* Return a series of SQL statements to create the given table, complete
|
||||||
|
@ -3997,6 +4101,25 @@ public class DBDictionary
|
||||||
if (objectName == null)
|
if (objectName == null)
|
||||||
return null;
|
return null;
|
||||||
|
|
||||||
|
// Handle delimited string differently. Return unquoted name.
|
||||||
|
if (delimitIds ||
|
||||||
|
objectName.startsWith(getDelimiter()) &&
|
||||||
|
objectName.endsWith(getDelimiter())) {
|
||||||
|
String delimCase = getDelimitedCase();
|
||||||
|
if (SCHEMA_CASE_UPPER.equals(delimCase)) {
|
||||||
|
objectName.toUpperCase();
|
||||||
|
}
|
||||||
|
else if (SCHEMA_CASE_LOWER.equals(delimCase)) {
|
||||||
|
objectName.toLowerCase();
|
||||||
|
}
|
||||||
|
|
||||||
|
// TODO: maybe have a different method to remove quotes and
|
||||||
|
// call it from the calling methods
|
||||||
|
int delimLen = getDelimiter().length();
|
||||||
|
return objectName.substring(delimLen,
|
||||||
|
objectName.length() - delimLen);
|
||||||
|
}
|
||||||
|
|
||||||
String scase = getSchemaCase();
|
String scase = getSchemaCase();
|
||||||
if (SCHEMA_CASE_LOWER.equals(scase))
|
if (SCHEMA_CASE_LOWER.equals(scase))
|
||||||
return objectName.toLowerCase();
|
return objectName.toLowerCase();
|
||||||
|
@ -4728,4 +4851,101 @@ public class DBDictionary
|
||||||
length));
|
length));
|
||||||
return name;
|
return name;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public String delimitString(String name, DBIdentifiers type) {
|
||||||
|
if (StringUtils.isEmpty(name)) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!getSupportsDelimitedIds()) {
|
||||||
|
// TODO: log (or maybe log in the method itself; so maybe
|
||||||
|
// merge with next if stmt
|
||||||
|
return name;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!delimitIds) {
|
||||||
|
return name;
|
||||||
|
}
|
||||||
|
// TODO: merge with if stmt above (maybe not, may want to log this)
|
||||||
|
if (!supportsDelimitedId(type)) {
|
||||||
|
// TODO: log
|
||||||
|
return name;
|
||||||
|
}
|
||||||
|
String delimitedString = delimiter + name + delimiter;
|
||||||
|
return delimitedString;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @return the unsupportedDelimitedIds
|
||||||
|
*/
|
||||||
|
protected EnumSet<DBIdentifiers> getUnsupportedDelimitedIds() {
|
||||||
|
return unsupportedDelimitedIds;
|
||||||
|
}
|
||||||
|
|
||||||
|
protected boolean supportsDelimitedId(DBIdentifiers type) {
|
||||||
|
if (getUnsupportedDelimitedIds().contains(type)) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @return the delimiter
|
||||||
|
*/
|
||||||
|
public String getDelimiter() {
|
||||||
|
return delimiter;
|
||||||
|
}
|
||||||
|
|
||||||
|
protected String getDelimitedCase() {
|
||||||
|
return delimitedCase;
|
||||||
|
}
|
||||||
|
|
||||||
|
protected void setDelimitedCase(DatabaseMetaData metaData) {
|
||||||
|
try {
|
||||||
|
if (metaData.storesMixedCaseQuotedIdentifiers()) {
|
||||||
|
delimitedCase = SCHEMA_CASE_PRESERVE;
|
||||||
|
}
|
||||||
|
else if (metaData.storesUpperCaseQuotedIdentifiers()) {
|
||||||
|
delimitedCase = SCHEMA_CASE_UPPER;
|
||||||
|
}
|
||||||
|
else if (metaData.storesLowerCaseQuotedIdentifiers()) {
|
||||||
|
delimitedCase = SCHEMA_CASE_LOWER;
|
||||||
|
}
|
||||||
|
} catch (SQLException e) {
|
||||||
|
// TODO log this
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @return the supportsDelimitedIds
|
||||||
|
*/
|
||||||
|
public boolean getSupportsDelimitedIds() {
|
||||||
|
return supportsDelimitedIds;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param supportsDelimitedIds the supportsDelimitedIds to set
|
||||||
|
*/
|
||||||
|
public void setSupportsDelimitedIds(DatabaseMetaData metaData) {
|
||||||
|
try {
|
||||||
|
supportsDelimitedIds =
|
||||||
|
metaData.supportsMixedCaseQuotedIdentifiers();
|
||||||
|
} catch (SQLException e) {
|
||||||
|
// TODO log this, or should we throw an exception?
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @return the delimitIds
|
||||||
|
*/
|
||||||
|
public boolean isDelimitIds() {
|
||||||
|
return delimitIds;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param delimitIds the delimitIds to set
|
||||||
|
*/
|
||||||
|
public void setDelimitIds(boolean delimitIds) {
|
||||||
|
this.delimitIds = delimitIds;
|
||||||
|
}
|
||||||
}
|
}
|
|
@ -20,9 +20,8 @@ package org.apache.openjpa.jdbc.sql;
|
||||||
|
|
||||||
import java.sql.DriverManager;
|
import java.sql.DriverManager;
|
||||||
import java.sql.SQLException;
|
import java.sql.SQLException;
|
||||||
import java.util.ArrayList;
|
|
||||||
import java.util.Arrays;
|
import java.util.Arrays;
|
||||||
import java.util.List;
|
import java.util.EnumSet;
|
||||||
import java.util.Set;
|
import java.util.Set;
|
||||||
|
|
||||||
import javax.sql.DataSource;
|
import javax.sql.DataSource;
|
||||||
|
@ -40,6 +39,9 @@ public class DerbyDictionary
|
||||||
* the DataSource.
|
* the DataSource.
|
||||||
*/
|
*/
|
||||||
public boolean shutdownOnClose = true;
|
public boolean shutdownOnClose = true;
|
||||||
|
|
||||||
|
private EnumSet<DBIdentifiers> unsupportedDelimitedIds =
|
||||||
|
EnumSet.of(DBIdentifiers.COLUMN_COLUMN_DEFINITION);
|
||||||
|
|
||||||
public DerbyDictionary() {
|
public DerbyDictionary() {
|
||||||
platform = "Apache Derby";
|
platform = "Apache Derby";
|
||||||
|
@ -120,4 +122,13 @@ public class DerbyDictionary
|
||||||
}
|
}
|
||||||
return recoverable;
|
return recoverable;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @return the unsupportedDelimitedIds
|
||||||
|
*/
|
||||||
|
@Override
|
||||||
|
protected EnumSet<DBIdentifiers> getUnsupportedDelimitedIds() {
|
||||||
|
return unsupportedDelimitedIds;
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -115,6 +115,8 @@ public class AnnotationPersistenceMappingParser
|
||||||
|
|
||||||
private static final Map<Class, MappingTag> _tags =
|
private static final Map<Class, MappingTag> _tags =
|
||||||
new HashMap<Class, MappingTag>();
|
new HashMap<Class, MappingTag>();
|
||||||
|
|
||||||
|
private DBDictionary _dict;
|
||||||
|
|
||||||
static {
|
static {
|
||||||
_tags.put(AssociationOverride.class, ASSOC_OVERRIDE);
|
_tags.put(AssociationOverride.class, ASSOC_OVERRIDE);
|
||||||
|
@ -199,6 +201,7 @@ public class AnnotationPersistenceMappingParser
|
||||||
|
|
||||||
public AnnotationPersistenceMappingParser(JDBCConfiguration conf) {
|
public AnnotationPersistenceMappingParser(JDBCConfiguration conf) {
|
||||||
super(conf);
|
super(conf);
|
||||||
|
_dict = conf.getDBDictionaryInstance();
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
@ -252,9 +255,17 @@ public class AnnotationPersistenceMappingParser
|
||||||
|
|
||||||
meta = (SequenceMapping) getRepository().addSequenceMetaData(name);
|
meta = (SequenceMapping) getRepository().addSequenceMetaData(name);
|
||||||
meta.setSequencePlugin(SequenceMapping.IMPL_VALUE_TABLE);
|
meta.setSequencePlugin(SequenceMapping.IMPL_VALUE_TABLE);
|
||||||
meta.setTable(toTableName(gen.schema(), gen.table()));
|
String schema = _dict.delimitString(gen.schema(),
|
||||||
meta.setPrimaryKeyColumn(gen.pkColumnName());
|
DBDictionary.DBIdentifiers.TABLE_GEN_SCHEMA);
|
||||||
meta.setSequenceColumn(gen.valueColumnName());
|
String table = _dict.delimitString(gen.table(),
|
||||||
|
DBDictionary.DBIdentifiers.TABLE_GEN_TABLE);
|
||||||
|
meta.setTable(toTableName(schema,table));
|
||||||
|
String pkColumnName = _dict.delimitString(gen.pkColumnName(),
|
||||||
|
DBDictionary.DBIdentifiers.TABLE_GEN_PK_COLUMN);
|
||||||
|
meta.setPrimaryKeyColumn(pkColumnName);
|
||||||
|
String valueColumnName = _dict.delimitString(gen.valueColumnName(),
|
||||||
|
DBDictionary.DBIdentifiers.TABLE_GEN_VALUE_COLUMN);
|
||||||
|
meta.setSequenceColumn(valueColumnName);
|
||||||
meta.setPrimaryKeyValue(gen.pkColumnValue());
|
meta.setPrimaryKeyValue(gen.pkColumnValue());
|
||||||
meta.setInitialValue(gen.initialValue());
|
meta.setInitialValue(gen.initialValue());
|
||||||
meta.setAllocate(gen.allocationSize());
|
meta.setAllocate(gen.allocationSize());
|
||||||
|
@ -494,13 +505,18 @@ public class AnnotationPersistenceMappingParser
|
||||||
Log log = getLog();
|
Log log = getLog();
|
||||||
|
|
||||||
String name;
|
String name;
|
||||||
|
String schema;
|
||||||
List<Column> joins = null;
|
List<Column> joins = null;
|
||||||
for (SecondaryTable table : tables) {
|
for (SecondaryTable table : tables) {
|
||||||
name = table.name();
|
name = _dict.delimitString(table.name(),
|
||||||
|
DBDictionary.DBIdentifiers.SECONDARY_TABLE_NAME) ;
|
||||||
if (StringUtils.isEmpty(name))
|
if (StringUtils.isEmpty(name))
|
||||||
throw new MetaDataException(_loc.get("second-name", cm));
|
throw new MetaDataException(_loc.get("second-name", cm));
|
||||||
if (!StringUtils.isEmpty(table.schema()))
|
if (!StringUtils.isEmpty(table.schema())) {
|
||||||
name = table.schema() + "." + name;
|
schema = _dict.delimitString(table.schema(),
|
||||||
|
DBDictionary.DBIdentifiers.SECONDARY_TABLE_SCHEMA);
|
||||||
|
name = schema + "." + name;
|
||||||
|
}
|
||||||
if (table.pkJoinColumns().length > 0) {
|
if (table.pkJoinColumns().length > 0) {
|
||||||
joins = new ArrayList<Column>(table.pkJoinColumns().length);
|
joins = new ArrayList<Column>(table.pkJoinColumns().length);
|
||||||
for (PrimaryKeyJoinColumn join : table.pkJoinColumns())
|
for (PrimaryKeyJoinColumn join : table.pkJoinColumns())
|
||||||
|
@ -517,42 +533,46 @@ public class AnnotationPersistenceMappingParser
|
||||||
* Set class table.
|
* Set class table.
|
||||||
*/
|
*/
|
||||||
private void parseTable(ClassMapping cm, Table table) {
|
private void parseTable(ClassMapping cm, Table table) {
|
||||||
String tableName = toTableName(table.schema(), table.name());
|
String tableName = _dict.delimitString(table.name(),
|
||||||
if (tableName != null)
|
DBDictionary.DBIdentifiers.TABLE_NAME);
|
||||||
cm.getMappingInfo().setTableName(tableName);
|
String schemaName = _dict.delimitString(table.schema(),
|
||||||
|
DBDictionary.DBIdentifiers.TABLE_SCHEMA);
|
||||||
|
String fullTableName = toTableName(schemaName, tableName);
|
||||||
|
if (fullTableName != null)
|
||||||
|
cm.getMappingInfo().setTableName(fullTableName);
|
||||||
|
|
||||||
addUniqueConstraints(tableName, cm, cm.getMappingInfo(),
|
addUniqueConstraints(fullTableName, cm, cm.getMappingInfo(),
|
||||||
table.uniqueConstraints());
|
table.uniqueConstraints());
|
||||||
}
|
}
|
||||||
|
|
||||||
Unique createUniqueConstraint(MetaDataContext ctx, UniqueConstraint anno) {
|
Unique createUniqueConstraint(MetaDataContext ctx, UniqueConstraint anno) {
|
||||||
String[] columnNames = anno.columnNames();
|
String[] columnNames = anno.columnNames();
|
||||||
if (columnNames == null || columnNames.length == 0)
|
if (columnNames == null || columnNames.length == 0)
|
||||||
throw new UserException(_loc.get("unique-no-column", ctx));
|
throw new UserException(_loc.get("unique-no-column", ctx));
|
||||||
Unique uniqueConstraint = new Unique();
|
Unique uniqueConstraint = new Unique();
|
||||||
for (int i=0; i<columnNames.length; i++) {
|
for (int i = 0; i < columnNames.length; i++) {
|
||||||
if (StringUtils.isEmpty(columnNames[i]))
|
if (StringUtils.isEmpty(columnNames[i]))
|
||||||
throw new UserException(_loc.get("unique-empty-column",
|
throw new UserException(_loc.get("unique-empty-column",
|
||||||
Arrays.toString(columnNames), ctx));
|
Arrays.toString(columnNames), ctx));
|
||||||
Column column = new Column();
|
Column column = new Column();
|
||||||
column.setName(columnNames[i]);
|
column.setName(columnNames[i]);
|
||||||
uniqueConstraint.addColumn(column);
|
uniqueConstraint.addColumn(column);
|
||||||
}
|
}
|
||||||
return uniqueConstraint;
|
return uniqueConstraint;
|
||||||
}
|
}
|
||||||
|
|
||||||
void addUniqueConstraints(String table, MetaDataContext ctx,
|
void addUniqueConstraints(String table, MetaDataContext ctx,
|
||||||
MappingInfo info, UniqueConstraint...uniqueConstraints) {
|
MappingInfo info, UniqueConstraint... uniqueConstraints) {
|
||||||
for (UniqueConstraint anno : uniqueConstraints) {
|
for (UniqueConstraint anno : uniqueConstraints) {
|
||||||
Unique unique = createUniqueConstraint(ctx, anno);
|
Unique unique = createUniqueConstraint(ctx, anno);
|
||||||
unique.setTableName(table);
|
unique.setTableName(table);
|
||||||
if (info instanceof ClassMappingInfo)
|
if (info instanceof ClassMappingInfo)
|
||||||
((ClassMappingInfo)info).addUnique(table, unique);
|
((ClassMappingInfo) info).addUnique(table, unique);
|
||||||
else if (info instanceof FieldMappingInfo)
|
else if (info instanceof FieldMappingInfo)
|
||||||
((FieldMappingInfo)info).addJoinTableUnique(unique);
|
((FieldMappingInfo) info).addJoinTableUnique(unique);
|
||||||
else
|
else
|
||||||
throw new InternalException();
|
throw new InternalException();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -735,16 +755,16 @@ public class AnnotationPersistenceMappingParser
|
||||||
}
|
}
|
||||||
|
|
||||||
void assertDefault(ForeignKey fk) {
|
void assertDefault(ForeignKey fk) {
|
||||||
boolean isDefault = StringUtils.isEmpty(fk.name())
|
boolean isDefault = StringUtils.isEmpty(fk.name())
|
||||||
&& fk.enabled()
|
&& fk.enabled()
|
||||||
&& !fk.deferred()
|
&& !fk.deferred()
|
||||||
&& fk.deleteAction() == ForeignKeyAction.RESTRICT
|
&& fk.deleteAction() == ForeignKeyAction.RESTRICT
|
||||||
&& fk.updateAction() == ForeignKeyAction.RESTRICT
|
&& fk.updateAction() == ForeignKeyAction.RESTRICT
|
||||||
&& fk.columnNames().length == 0
|
&& fk.columnNames().length == 0
|
||||||
&& fk.specified();
|
&& fk.specified();
|
||||||
if (!isDefault)
|
if (!isDefault)
|
||||||
throw new UserException(_loc.get("implicit-non-default-fk", _cls,
|
throw new UserException(_loc.get("implicit-non-default-fk", _cls,
|
||||||
getSourceFile()).getMessage());
|
getSourceFile()).getMessage());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -1449,11 +1469,11 @@ public class AnnotationPersistenceMappingParser
|
||||||
String secondary = null;
|
String secondary = null;
|
||||||
for (int i = 0; i < pcols.length; i++) {
|
for (int i = 0; i < pcols.length; i++) {
|
||||||
if (cols.size() > i)
|
if (cols.size() > i)
|
||||||
setupColumn((Column) cols.get(i), pcols[i]);
|
setupColumn((Column) cols.get(i), pcols[i], _dict);
|
||||||
else {
|
else {
|
||||||
if (cols.isEmpty())
|
if (cols.isEmpty())
|
||||||
cols = new ArrayList<Column>(pcols.length);
|
cols = new ArrayList<Column>(pcols.length);
|
||||||
cols.add(newColumn(pcols[i]));
|
cols.add(newColumn(pcols[i], _dict));
|
||||||
}
|
}
|
||||||
|
|
||||||
if (xmlTypeClass != null
|
if (xmlTypeClass != null
|
||||||
|
@ -1469,7 +1489,9 @@ public class AnnotationPersistenceMappingParser
|
||||||
}
|
}
|
||||||
|
|
||||||
unique |= (pcols[i].unique()) ? TRUE : FALSE;
|
unique |= (pcols[i].unique()) ? TRUE : FALSE;
|
||||||
secondary = trackSecondaryTable(fm, secondary, pcols[i].table(), i);
|
String secTable = _dict.delimitString(pcols[i].table(),
|
||||||
|
DBDictionary.DBIdentifiers.SECONDARY_TABLE_NAME);
|
||||||
|
secondary = trackSecondaryTable(fm, secondary, secTable, i);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (fm.isElementCollection())
|
if (fm.isElementCollection())
|
||||||
|
@ -1483,20 +1505,24 @@ public class AnnotationPersistenceMappingParser
|
||||||
/**
|
/**
|
||||||
* Create a new schema column with information from the given annotation.
|
* Create a new schema column with information from the given annotation.
|
||||||
*/
|
*/
|
||||||
private static Column newColumn(javax.persistence.Column anno) {
|
private static Column newColumn(javax.persistence.Column anno,
|
||||||
|
DBDictionary dict) {
|
||||||
Column col = new Column();
|
Column col = new Column();
|
||||||
setupColumn(col, anno);
|
setupColumn(col, anno, dict);
|
||||||
return col;
|
return col;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Setup the given column with information from the given annotation.
|
* Setup the given column with information from the given annotation.
|
||||||
*/
|
*/
|
||||||
private static void setupColumn(Column col, javax.persistence.Column anno) {
|
private static void setupColumn(Column col, javax.persistence.Column anno,
|
||||||
|
DBDictionary dict) {
|
||||||
if (!StringUtils.isEmpty(anno.name()))
|
if (!StringUtils.isEmpty(anno.name()))
|
||||||
col.setName(anno.name());
|
col.setName(dict.delimitString(anno.name(),
|
||||||
|
DBDictionary.DBIdentifiers.COLUMN_NAME));
|
||||||
if (!StringUtils.isEmpty(anno.columnDefinition()))
|
if (!StringUtils.isEmpty(anno.columnDefinition()))
|
||||||
col.setTypeName(anno.columnDefinition());
|
col.setTypeName(dict.delimitString(anno.columnDefinition(),
|
||||||
|
DBDictionary.DBIdentifiers.COLUMN_COLUMN_DEFINITION));
|
||||||
if (anno.precision() != 0)
|
if (anno.precision() != 0)
|
||||||
col.setSize(anno.precision());
|
col.setSize(anno.precision());
|
||||||
else if (anno.length() != 255)
|
else if (anno.length() != 255)
|
||||||
|
|
|
@ -89,9 +89,9 @@ public class PersistenceMappingDefaults
|
||||||
|
|
||||||
int nColumn = vers.getMappingInfo().getColumns().size();
|
int nColumn = vers.getMappingInfo().getColumns().size();
|
||||||
switch (nColumn) {
|
switch (nColumn) {
|
||||||
case 0 : return NoneVersionStrategy.getInstance();
|
case 0 : return NoneVersionStrategy.getInstance();
|
||||||
case 1 : return new NumberVersionStrategy();
|
case 1 : return new NumberVersionStrategy();
|
||||||
default: return new MultiColumnVersionStrategy();
|
default: return new MultiColumnVersionStrategy();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -135,7 +135,17 @@ public class PersistenceMappingDefaults
|
||||||
ClassMapping clm = fm.getDefiningMapping();
|
ClassMapping clm = fm.getDefiningMapping();
|
||||||
Table table = getTable(clm);
|
Table table = getTable(clm);
|
||||||
|
|
||||||
String name = table.getName() + "_";
|
String name = table.getName();
|
||||||
|
String delim = dict.getDelimiter();
|
||||||
|
boolean isDelimited = false;
|
||||||
|
if (name.startsWith(delim) && name.endsWith(delim)) {
|
||||||
|
isDelimited = true;
|
||||||
|
name = name.substring(0,name.length()-1) + "_";
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
name = name + "_";
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
// if this is an assocation table, spec says to suffix with table of
|
// if this is an assocation table, spec says to suffix with table of
|
||||||
// the related type. spec doesn't cover other cases; we're going to
|
// the related type. spec doesn't cover other cases; we're going to
|
||||||
|
@ -147,6 +157,11 @@ public class PersistenceMappingDefaults
|
||||||
name += rel.getTable().getName();
|
name += rel.getTable().getName();
|
||||||
else
|
else
|
||||||
name += fm.getName();
|
name += fm.getName();
|
||||||
|
|
||||||
|
if (isDelimited) {
|
||||||
|
name += "\"";
|
||||||
|
}
|
||||||
|
|
||||||
return name.replace('$', '_');
|
return name.replace('$', '_');
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -0,0 +1,199 @@
|
||||||
|
/*
|
||||||
|
* Licensed to the Apache Software Foundation (ASF) under one
|
||||||
|
* or more contributor license agreements. See the NOTICE file
|
||||||
|
* distributed with this work for additional information
|
||||||
|
* regarding copyright ownership. The ASF licenses this file
|
||||||
|
* to you under the Apache License, Version 2.0 (the
|
||||||
|
* "License"); you may not use this file except in compliance
|
||||||
|
* with the License. You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing,
|
||||||
|
* software distributed under the License is distributed on an
|
||||||
|
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
||||||
|
* KIND, either express or implied. See the License for the
|
||||||
|
* specific language governing permissions and limitations
|
||||||
|
* under the License.
|
||||||
|
*/
|
||||||
|
package org.apache.openjpa.persistence.delimited.identifiers;
|
||||||
|
|
||||||
|
import java.util.HashMap;
|
||||||
|
import java.util.HashSet;
|
||||||
|
import java.util.Map;
|
||||||
|
import java.util.Set;
|
||||||
|
|
||||||
|
import javax.persistence.CollectionTable;
|
||||||
|
import javax.persistence.Column;
|
||||||
|
import javax.persistence.ElementCollection;
|
||||||
|
import javax.persistence.Entity;
|
||||||
|
import javax.persistence.Id;
|
||||||
|
import javax.persistence.MapKeyColumn;
|
||||||
|
import javax.persistence.SecondaryTable;
|
||||||
|
import javax.persistence.Table;
|
||||||
|
|
||||||
|
@Entity
|
||||||
|
@Table(name="\"primary entityF\"", schema="\"delim id\"")
|
||||||
|
@SecondaryTable(name="\"secondary entityF\"", schema="\"delim id\"")
|
||||||
|
//@Table(name="primary_entityF", schema="delim_id")
|
||||||
|
public class EntityF {
|
||||||
|
@Id
|
||||||
|
private int id;
|
||||||
|
@Column(name="\"f name\"")
|
||||||
|
private String name;
|
||||||
|
@Column(name="f_nonDelimName")
|
||||||
|
private String nonDelimName;
|
||||||
|
@Column(name="\"secondary name\"", table="\"secondary entityF\"")
|
||||||
|
private String secName;
|
||||||
|
|
||||||
|
@ElementCollection
|
||||||
|
// CollectionTable with default name generation
|
||||||
|
@CollectionTable
|
||||||
|
private Set<String> collectionSet = new HashSet<String>();
|
||||||
|
|
||||||
|
@ElementCollection
|
||||||
|
@CollectionTable(name="\"collectionDelimSet\"", schema="\"delim id\"")
|
||||||
|
private Set<String> collectionDelimSet = new HashSet<String>();
|
||||||
|
|
||||||
|
@ElementCollection
|
||||||
|
@MapKeyColumn
|
||||||
|
private Map<String, String> collectionMap = new HashMap<String, String>();
|
||||||
|
|
||||||
|
@ElementCollection
|
||||||
|
@MapKeyColumn(name="\"mapKey\"")
|
||||||
|
private Map<String, String> delimCollectionMap = new HashMap<String, String>();
|
||||||
|
|
||||||
|
public EntityF(String name) {
|
||||||
|
this.name = name;
|
||||||
|
}
|
||||||
|
|
||||||
|
public EntityF(int id, String name) {
|
||||||
|
this.id = id;
|
||||||
|
this.name = name;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @return the id
|
||||||
|
*/
|
||||||
|
public int getId() {
|
||||||
|
return id;
|
||||||
|
}
|
||||||
|
/**
|
||||||
|
* @param id the id to set
|
||||||
|
*/
|
||||||
|
public void setId(int id) {
|
||||||
|
this.id = id;
|
||||||
|
}
|
||||||
|
/**
|
||||||
|
* @return the name
|
||||||
|
*/
|
||||||
|
public String getName() {
|
||||||
|
return name;
|
||||||
|
}
|
||||||
|
/**
|
||||||
|
* @param name the name to set
|
||||||
|
*/
|
||||||
|
public void setName(String name) {
|
||||||
|
this.name = name;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @return the nonDelimName
|
||||||
|
*/
|
||||||
|
public String getNonDelimName() {
|
||||||
|
return nonDelimName;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param nonDelimName the nonDelimName to set
|
||||||
|
*/
|
||||||
|
public void setNonDelimName(String nonDelimName) {
|
||||||
|
this.nonDelimName = nonDelimName;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @return the secName
|
||||||
|
*/
|
||||||
|
public String getSecName() {
|
||||||
|
return secName;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param secName the secName to set
|
||||||
|
*/
|
||||||
|
public void setSecName(String secName) {
|
||||||
|
this.secName = secName;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @return the collectionSet
|
||||||
|
*/
|
||||||
|
public Set<String> getCollectionSet() {
|
||||||
|
return collectionSet;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param collectionSet the collectionSet to set
|
||||||
|
*/
|
||||||
|
public void setCollectionSet(Set<String> collectionSet) {
|
||||||
|
this.collectionSet = collectionSet;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void addCollectionSet(String item) {
|
||||||
|
collectionSet.add(item);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @return the collectionNamedSet
|
||||||
|
*/
|
||||||
|
public Set<String> getCollectionDelimSet() {
|
||||||
|
return collectionDelimSet;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param collectionNamedSet the collectionNamedSet to set
|
||||||
|
*/
|
||||||
|
public void setCollectionDelimSet(Set<String> collectionDelimSet) {
|
||||||
|
this.collectionDelimSet = collectionDelimSet;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void addCollectionDelimSet(String item) {
|
||||||
|
this.collectionDelimSet.add(item);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @return the collectionMap
|
||||||
|
*/
|
||||||
|
public Map<String, String> getCollectionMap() {
|
||||||
|
return collectionMap;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param collectionMap the collectionMap to set
|
||||||
|
*/
|
||||||
|
public void setCollectionMap(Map<String, String> collectionMap) {
|
||||||
|
this.collectionMap = collectionMap;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void addCollectionMap(String key, String value) {
|
||||||
|
collectionMap.put(key, value);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @return the delimCollectionMap
|
||||||
|
*/
|
||||||
|
public Map<String, String> getDelimCollectionMap() {
|
||||||
|
return delimCollectionMap;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param delimCollectionMap the delimCollectionMap to set
|
||||||
|
*/
|
||||||
|
public void setDelimCollectionMap(Map<String, String> delimCollectionMap) {
|
||||||
|
this.delimCollectionMap = delimCollectionMap;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void addDelimCollectionMap(String key, String value) {
|
||||||
|
delimCollectionMap.put(key, value);
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,115 @@
|
||||||
|
package org.apache.openjpa.persistence.delimited.identifiers;
|
||||||
|
|
||||||
|
import java.sql.Connection;
|
||||||
|
import java.sql.DatabaseMetaData;
|
||||||
|
import java.sql.SQLException;
|
||||||
|
|
||||||
|
import org.apache.openjpa.jdbc.conf.JDBCConfiguration;
|
||||||
|
import org.apache.openjpa.jdbc.schema.Column;
|
||||||
|
import org.apache.openjpa.jdbc.sql.DBDictionary;
|
||||||
|
import org.apache.openjpa.persistence.OpenJPAEntityManager;
|
||||||
|
import org.apache.openjpa.persistence.test.SQLListenerTestCase;
|
||||||
|
|
||||||
|
public class TestManualDelimId extends SQLListenerTestCase {
|
||||||
|
OpenJPAEntityManager em;
|
||||||
|
int id = 0;
|
||||||
|
EntityF entityF;
|
||||||
|
JDBCConfiguration conf;
|
||||||
|
DBDictionary dict;
|
||||||
|
|
||||||
|
public void setUp() throws Exception {
|
||||||
|
// TODO: retest with DROP to figure out problem
|
||||||
|
// super.setUp(EntityF2.class,DROP_TABLES);
|
||||||
|
super.setUp(
|
||||||
|
org.apache.openjpa.persistence.delimited.identifiers.EntityF.class);
|
||||||
|
assertNotNull(emf);
|
||||||
|
|
||||||
|
em = emf.createEntityManager();
|
||||||
|
assertNotNull(em);
|
||||||
|
|
||||||
|
conf = (JDBCConfiguration) emf.getConfiguration();
|
||||||
|
dict = conf.getDBDictionaryInstance();
|
||||||
|
}
|
||||||
|
|
||||||
|
public void createEntityF(int id) {
|
||||||
|
entityF = new EntityF(id, "fName");
|
||||||
|
entityF.setNonDelimName("fNonDelimName");
|
||||||
|
entityF.setSecName("sec name");
|
||||||
|
entityF.addCollectionSet("xxx");
|
||||||
|
entityF.addCollectionSet("yyy");
|
||||||
|
entityF.addCollectionDelimSet("aaa");
|
||||||
|
entityF.addCollectionDelimSet("bbb");
|
||||||
|
entityF.addCollectionMap("aaa", "xxx");
|
||||||
|
entityF.addCollectionMap("bbb", "yyy");
|
||||||
|
entityF.addDelimCollectionMap("www", "xxx");
|
||||||
|
entityF.addDelimCollectionMap("yyy", "zzz");
|
||||||
|
}
|
||||||
|
|
||||||
|
// TODO: temp - test on multiple DBs
|
||||||
|
// public void testDBCapability() {
|
||||||
|
// Connection conn = (Connection)em.getConnection();
|
||||||
|
// try {
|
||||||
|
// DatabaseMetaData meta = conn.getMetaData();
|
||||||
|
// System.out.println("LC - " + meta.storesLowerCaseIdentifiers());
|
||||||
|
// System.out.println("LCQ - " + meta.storesLowerCaseQuotedIdentifiers());
|
||||||
|
// System.out.println("MC - " + meta.storesMixedCaseIdentifiers());
|
||||||
|
// System.out.println("MCQ - " + meta.storesMixedCaseQuotedIdentifiers());
|
||||||
|
// System.out.println("UC - " + meta.storesUpperCaseIdentifiers());
|
||||||
|
// System.out.println("UCQ - " + meta.storesUpperCaseQuotedIdentifiers());
|
||||||
|
// System.out.println("");
|
||||||
|
// System.out.println("db product name - " + meta.getDatabaseProductName());
|
||||||
|
// System.out.println("db product version - " + meta.getDatabaseProductVersion());
|
||||||
|
// System.out.println("driver name - " + meta.getDriverName());
|
||||||
|
// System.out.println("driver version - " + meta.getDriverVersion());
|
||||||
|
// } catch (SQLException e) {
|
||||||
|
// e.printStackTrace();
|
||||||
|
// }
|
||||||
|
// }
|
||||||
|
|
||||||
|
public void testCreateF() {
|
||||||
|
id++;
|
||||||
|
createEntityF(id);
|
||||||
|
|
||||||
|
em.getTransaction().begin();
|
||||||
|
em.persist(entityF);
|
||||||
|
em.getTransaction().commit();
|
||||||
|
|
||||||
|
System.out.println(super.toString(sql));
|
||||||
|
|
||||||
|
// getColumnInfo("\"primary_entityF\"", "\"f_name\"", "\"delim_id\"");
|
||||||
|
// getColumnInfo("\"primary entityF\"", null, "\"delim id\"");
|
||||||
|
// getColumnInfo("\"secondary entityF\"", null, "\"delim id\"");
|
||||||
|
}
|
||||||
|
|
||||||
|
// TODO: change to boolean return and remove assert
|
||||||
|
// private void getColumnInfo(String tableName, String columnName, String schemaName) {
|
||||||
|
// Connection conn = (Connection)em.getConnection();
|
||||||
|
// try {
|
||||||
|
// DatabaseMetaData meta = conn.getMetaData();
|
||||||
|
// // tableName = "\"" + tableName + "\"";
|
||||||
|
// Column[] columns = dict.getColumns(meta, conn.getCatalog(), schemaName, tableName, columnName, conn);
|
||||||
|
// System.out.println("columns.length - " + columns.length);
|
||||||
|
//
|
||||||
|
//// assertEquals(1, columns.length);
|
||||||
|
//
|
||||||
|
// for (Column column : columns) {
|
||||||
|
// System.out.println("column name - " + column.getName());
|
||||||
|
// System.out.println("column fullName - " + column.getFullName());
|
||||||
|
// System.out.println("column schemaName - " + column.getSchemaName());
|
||||||
|
// System.out.println("column tableName - " + column.getTableName());
|
||||||
|
// System.out.println("column description - " + column.getDescription());
|
||||||
|
// }
|
||||||
|
// } catch (SQLException e) {
|
||||||
|
// e.printStackTrace();
|
||||||
|
// }
|
||||||
|
// finally {
|
||||||
|
// try {
|
||||||
|
// conn.commit();
|
||||||
|
// conn.close();
|
||||||
|
// } catch (SQLException e) {
|
||||||
|
// e.printStackTrace();
|
||||||
|
// fail("problem closing connection");
|
||||||
|
// }
|
||||||
|
// }
|
||||||
|
// }
|
||||||
|
}
|
Loading…
Reference in New Issue