OPENJPA-946 - Commit contribution by Tim McConnell.

git-svn-id: https://svn.apache.org/repos/asf/openjpa/trunk@777649 13f79535-47bb-0310-9956-ffa450edef68
This commit is contained in:
Albert Lee 2009-05-22 18:32:26 +00:00
parent 9638a84e37
commit 3f28f44d3a
9 changed files with 567 additions and 12 deletions

View File

@ -127,7 +127,8 @@ public class DynamicSchemaFactory
return col;
// Ensure only valid column name(s) are added to the table
if (name.length() > _dict.maxColumnNameLength) {
if ((name.length() > _dict.maxColumnNameLength) ||
_dict.getInvalidColumnWordSet().contains(name.toUpperCase())) {
return addColumn(name,
_dict.getValidColumnName(name, this));
}

View File

@ -159,6 +159,11 @@ public class DB2Dictionary
"VOLUMES", "WHILE", "WLM", "YEARS",
}));
// reservedWordSet subset that can be used as valid column names
validColumnWordSet.addAll(Arrays.asList(new String[] {
"C", "COUNT", "DATE", "DATA", "LABEL", "LOCALE", "NAME", "NUMBER",
"TIMESTAMP", "VALUE", }));
super.setBatchLimit(defaultBatchLimit);
selectWordSet.add("WITH");

View File

@ -345,6 +345,10 @@ public class DBDictionary
protected boolean connected = false;
protected boolean isJDBC3 = false;
protected final Set reservedWordSet = new HashSet();
// reservedWordSet subset that can be used as valid column names
protected Set<String> validColumnWordSet = new HashSet<String>();
// reservedWordSet subset that cannot be used as valid column names
protected Set<String> invalidColumnWordSet = new HashSet<String>();
protected final Set systemSchemaSet = new HashSet();
protected final Set systemTableSet = new HashSet();
protected final Set fixedSizeTypeNameSet = new HashSet();
@ -2929,8 +2933,20 @@ public class DBDictionary
}
/**
* Make any necessary changes to the given table name to make it valid
* for the current DB.
* Return the subset of the words in reservedWordSet that cannot be used as
* valid column names for the current DB. If the column name is invalid the
* getValidColumnName method of the DB dictionary should be invoked to make
* it valid.
*
* @see getValidColumnName
*/
public final Set<String> getInvalidColumnWordSet() {
return invalidColumnWordSet;
}
/**
* Make any necessary changes to the given table name to make it valid for
* the current DB.
*/
public String getValidTableName(String name, Schema schema) {
while (name.startsWith("_"))
@ -4260,6 +4276,10 @@ public class DBDictionary
reservedWordSet.addAll(Arrays.asList(Strings.split
(reservedWords.toUpperCase(), ",", 0)));
// reservedWordSet subset that cannot be used as valid column names
invalidColumnWordSet = new HashSet(reservedWordSet);
invalidColumnWordSet.removeAll(validColumnWordSet);
// add system schemas set by user
if (systemSchemas != null)
systemSchemaSet.addAll(Arrays.asList(Strings.split

View File

@ -81,6 +81,11 @@ public class DerbyDictionary
"RUNTIMESTATISTICS", "STATEMENT", "STATISTICS",
"TIMING", "WAIT", "XML",
}));
// reservedWordSet subset that can be used as valid column names
validColumnWordSet.addAll(Arrays.asList(new String[] {
"C", "COUNT", "DATE", "DATA", "NAME", "NUMBER", "NULLABLE",
"TIMESTAMP", "TYPE", "VALUE",
}));
}
public void closeDataSource(DataSource dataSource) {

View File

@ -107,6 +107,11 @@ public class MySQLDictionary
"LOAD", "MEDIUMINT", "OPTION", "OUTFILE", "REPLACE",
"SET", "STARTING", "TEXT", "UNSIGNED", "ZEROFILL",
}));
// reservedWordSet subset that can be used as valid column names
validColumnWordSet.addAll(Arrays.asList(new String[]{
"C", "COUNT", "DATE", "DATA", "NAME", "NULLABLE", "NUMBER",
"TIMESTAMP", "TYPE", "VALUE",
}));
// MySQL requires double-escape for strings
searchStringEscape = "\\\\";

View File

@ -163,6 +163,11 @@ public class OracleDictionary
"LONG", "MAXEXTENTS", "MINUS", "MODE", "NOAUDIT", "NOCOMPRESS",
"NOWAIT", "OFFLINE", "ONLINE", "PCTFREE", "ROW",
}));
// reservedWordSet subset that can be used as valid column names
validColumnWordSet.addAll(Arrays.asList(new String[]{
"C", "COUNT", "DATA", "NAME", "NULLABLE", "STORE", "TIMESTAMP",
"TYPE", "VALUE", "VERSION",
}));
substringFunctionName = "SUBSTR";
super.setBatchLimit(defaultBatchLimit);

View File

@ -180,6 +180,11 @@ public class PostgresDictionary
"RETRIEVE", "RETURNS", "RULE", "SETOF", "STDIN", "STDOUT",
"STORE", "VACUUM", "VERBOSE", "VERSION",
}));
// reservedWordSet subset that can be used as valid column names
validColumnWordSet.addAll(Arrays.asList(new String[] {
"C", "COUNT", "DATE", "DATA", "NAME", "NULLABLE", "NUMBER", "OID",
"STORE", "TIMESTAMP", "TYPE", "VALUE", "VERSION",
}));
}
public Date getDate(ResultSet rs, int column)

View File

@ -0,0 +1,487 @@
/*
* 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.dynamicschema;
import java.io.Serializable;
import java.math.BigInteger;
import java.math.BigDecimal;
import java.sql.Date;
import java.sql.Time;
import java.sql.Timestamp;
import java.util.Calendar;
import javax.persistence.Entity;
import javax.persistence.Id;
/**
* Entity using reserved words for column names
*
* @see sql-keywords.rscs
* @author Tim McConnell
* @since 2.0.0
*/
@Entity
public class EntityReservedWords implements Serializable {
@Id
private int id;
private Integer add;
private int application;
private BigDecimal begin;
private BigInteger bigint;
private Calendar calendar;
private String character;
private Integer conditional;
private Date date;
private BigDecimal decimal;
private Time distinct;
private String exception;
private int each;
private String from;
private Integer file;
private String grant;
private BigDecimal global;
private String hour;
private String holdlock;
private BigInteger integer;
private int index;
private BigInteger join;
private String jar;
private Calendar key;
private Timestamp kill;
private Integer like;
private BigDecimal loop;
private int minute;
private Date merge;
private String number;
private Integer not;
private Date outer;
private String on;
private BigInteger primary;
private int purge;
private Integer quiesce;
private String quit;
private BigDecimal restrict;
private Time rename;
private String select;
private Integer savepoint;
private Time time;
private Timestamp timestamp;
private Calendar trigger;
private int update;
private String until;
private String varchar;
private Integer variable;
private Timestamp wait;
private BigDecimal where;
private BigInteger xml;
private int year;
private Integer years;
private Date zerofill;
private String zone;
public EntityReservedWords() {
}
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
public int getAdd() {
return add;
}
public void setAdd(int add) {
this.add = add;
}
public int getApplication() {
return application;
}
public void setApplication(int application) {
this.application = application;
}
public BigDecimal getBegin() {
return begin;
}
public void setBegin(BigDecimal begin) {
this.begin = begin;
}
public BigInteger getBigint() {
return bigint;
}
public void setBigint(BigInteger bigint) {
this.bigint = bigint;
}
public Calendar getCalendar() {
return calendar;
}
public void setCalendar(int Calendar) {
this.calendar = calendar;
}
public String getCharacter() {
return character;
}
public void setCharacter(String character) {
this.character = character;
}
public int getConditional() {
return conditional;
}
public void setConditional(int conditional) {
this.conditional = conditional;
}
public Date getDate() {
return date;
}
public void setDate(Date date) {
this.date = date;
}
public BigDecimal getDecimal() {
return decimal;
}
public void setDecimal(BigDecimal decimal) {
this.decimal = decimal;
}
public Time getDistinct() {
return distinct;
}
public void setDistinct(Time distinct) {
this.distinct = distinct;
}
public String getException() {
return exception;
}
public void setException(String exception) {
this.exception = exception;
}
public int getEach() {
return each;
}
public void setEach(int each) {
this.each = each;
}
public String getFrom() {
return from;
}
public void setFrom(String from) {
this.from = from;
}
public int getFile() {
return file;
}
public void setFile(int file) {
this.file = file;
}
public String getGrant() {
return grant;
}
public void setGrant(String grant) {
this.grant = grant;
}
public BigDecimal getGlobal() {
return global;
}
public void setGlobal(BigDecimal global) {
this.global = global;
}
public String getHour() {
return hour;
}
public void setHour(String hour) {
this.hour = hour;
}
public String getHoldlock() {
return holdlock;
}
public void setHoldlock(String holdlock) {
this.holdlock = holdlock;
}
public BigInteger getInteger() {
return integer;
}
public void setInteger(BigInteger integer) {
this.integer = integer;
}
public int getIndex() {
return index;
}
public void setIndex(int index) {
this.index = index;
}
public BigInteger getJoin() {
return join;
}
public void setJoin(BigInteger join) {
this.join = join;
}
public String getJar() {
return jar;
}
public void setJar(String jar) {
this.jar = jar;
}
public Calendar getKey() {
return key;
}
public void setKey(Calendar key) {
this.key = key;
}
public Timestamp getKill() {
return kill;
}
public void setKill(Timestamp kill) {
this.kill = kill;
}
public Integer getLike() {
return like;
}
public void setLike(Integer like) {
this.like = like;
}
public BigDecimal getLoop() {
return loop;
}
public void setLoop(BigDecimal loop) {
this.loop = loop;
}
public int getMinute() {
return minute;
}
public void setMinute(int minute) {
this.minute = minute;
}
public Date getMerge() {
return merge;
}
public void setMerge(Date merge) {
this.merge = merge;
}
public String getNumber() {
return number;
}
public void setNumber(String number) {
this.number = number;
}
public int getNot() {
return not;
}
public void setNot(int not) {
this.not = not;
}
public Date getOuter() {
return outer;
}
public void setOuter(Date outer) {
this.outer = outer;
}
public String getOn() {
return on;
}
public void setOn(String on) {
this.on = on;
}
public BigInteger getPrimary() {
return primary;
}
public void setPrimary(BigInteger primary) {
this.primary = primary;
}
public int getPurge() {
return purge;
}
public void setPurge(int purge) {
this.purge = purge;
}
public int getQuiesce() {
return quiesce;
}
public void setQuiesce(int quiesce) {
this.quiesce = quiesce;
}
public String getQuit() {
return quit;
}
public void setQuit(String quit) {
this.quit = quit;
}
public BigDecimal getRestrict() {
return restrict;
}
public void setRestrict(BigDecimal restrict) {
this.restrict = restrict;
}
public Time getRename() {
return rename;
}
public void setRename(Time rename) {
this.rename = rename;
}
public String getSelect() {
return select;
}
public void setSelect(String select) {
this.select = select;
}
public int getSavepoint() {
return savepoint;
}
public void setSavepoint(int savepoint) {
this.savepoint = savepoint;
}
public Time getTime() {
return time;
}
public void setTime(Time time) {
this.time = time;
}
public Timestamp getTimestamp() {
return timestamp;
}
public void setTimestamp(Timestamp timestamp) {
this.timestamp = timestamp;
}
public Calendar getTrigger() {
return trigger;
}
public void settrigger(Calendar trigger) {
this.trigger = trigger;
}
public int getUpdate() {
return update;
}
public void setUpdate(int update) {
this.update = update;
}
public String getUntil() {
return until;
}
public void setUntil(String until) {
this.until = until;
}
public String getVarchar() {
return varchar;
}
public void setVarchar(String varchar) {
this.varchar = varchar;
}
public int getVariable() {
return variable;
}
public void setVariable(int variable) {
this.variable = variable;
}
public Timestamp getWait() {
return wait;
}
public void setWait(Timestamp wait) {
this.wait = wait;
}
public BigDecimal getWhere() {
return where;
}
public void setwHere(BigDecimal where) {
this.where = where;
}
public BigInteger getXml() {
return xml;
}
public void setxml(BigInteger xml) {
this.xml = xml;
}
public int getYear() {
return year;
}
public void setyear(int year) {
this.year = year;
}
public int getYears() {
return years;
}
public void setyears(int years) {
this.years = years;
}
public Date getZerofill() {
return zerofill;
}
public void setZerofill(Date zerofill) {
this.zerofill = zerofill;
}
public String getZone() {
return zone;
}
public void setZone(String zone) {
this.zone = zone;
}
}

View File

@ -36,6 +36,7 @@ import org.apache.openjpa.persistence.test.SingleEMFTestCase;
* <ol>
* <li>maxTableNameLength
* <li>maxColumnNameLength
* <li>reservedWordsSet
* </ol>
*
* <b>Note(s):</b>
@ -58,7 +59,7 @@ public class TestDynamicSchemas extends SingleEMFTestCase {
public void testDerbyDynamicSchema() {
OpenJPAEntityManagerFactorySPI derbyEMF =
createEMF(EntityVeryLongNames.class,
createEMF(EntityVeryLongNames.class, EntityReservedWords.class,
"openjpa.ConnectionURL",
"jdbc:derby:net://host:1527/databaseName",
"openjpa.jdbc.SynchronizeMappings", "export",
@ -69,7 +70,7 @@ public class TestDynamicSchemas extends SingleEMFTestCase {
public void testDB2DynamicSchema() {
OpenJPAEntityManagerFactorySPI db2EMF =
createEMF(EntityVeryLongNames.class,
createEMF(EntityVeryLongNames.class, EntityReservedWords.class,
"openjpa.ConnectionURL",
"jdbc:db2://localhost:5000/db2",
"openjpa.jdbc.SynchronizeMappings", "export",
@ -80,7 +81,7 @@ public class TestDynamicSchemas extends SingleEMFTestCase {
public void testOracleDynamicSchema() {
OpenJPAEntityManagerFactorySPI oracleEMF =
createEMF(EntityVeryLongNames.class,
createEMF(EntityVeryLongNames.class, EntityReservedWords.class,
"openjpa.ConnectionURL",
"jdbc:oracle:thin:@host:1234:database_sid",
"openjpa.jdbc.SynchronizeMappings", "export",
@ -91,7 +92,7 @@ public class TestDynamicSchemas extends SingleEMFTestCase {
public void testAccessDynamicSchema() {
OpenJPAEntityManagerFactorySPI accessEMF =
createEMF(EntityVeryLongNames.class,
createEMF(EntityVeryLongNames.class, EntityReservedWords.class,
"openjpa.ConnectionURL",
"jdbc:odbc:Driver=Microsoft Access Driver (*.mdb);DBQ=c:",
"openjpa.jdbc.SynchronizeMappings", "export",
@ -102,7 +103,7 @@ public class TestDynamicSchemas extends SingleEMFTestCase {
public void testSQLServerDynamicSchema() {
OpenJPAEntityManagerFactorySPI sqlserverEMF =
createEMF(EntityVeryLongNames.class,
createEMF(EntityVeryLongNames.class, EntityReservedWords.class,
"openjpa.ConnectionURL",
"jdbc:microsoft:sqlserver:",
"openjpa.jdbc.SynchronizeMappings", "export",
@ -113,7 +114,7 @@ public class TestDynamicSchemas extends SingleEMFTestCase {
public void testMySQLDynamicSchema() {
OpenJPAEntityManagerFactorySPI mysqlEMF =
createEMF(EntityVeryLongNames.class,
createEMF(EntityVeryLongNames.class, EntityReservedWords.class,
"openjpa.ConnectionURL",
"jdbc:mysql://host1:1,host2:2/database?p1=v1&p2=v2",
"openjpa.jdbc.SynchronizeMappings", "export",
@ -124,7 +125,7 @@ public class TestDynamicSchemas extends SingleEMFTestCase {
public void testPostgresDynamicSchema() {
OpenJPAEntityManagerFactorySPI postgresEMF =
createEMF(EntityVeryLongNames.class,
createEMF(EntityVeryLongNames.class, EntityReservedWords.class,
"openjpa.ConnectionURL",
"jdbc:postgresql:database",
"openjpa.jdbc.SynchronizeMappings", "export",
@ -135,7 +136,7 @@ public class TestDynamicSchemas extends SingleEMFTestCase {
public void testInformixDynamicSchema() {
OpenJPAEntityManagerFactorySPI informixEMF =
createEMF(EntityVeryLongNames.class,
createEMF(EntityVeryLongNames.class, EntityReservedWords.class,
"openjpa.ConnectionURL",
"jdbc:informix-sqli:",
"openjpa.jdbc.SynchronizeMappings", "export",
@ -146,7 +147,7 @@ public class TestDynamicSchemas extends SingleEMFTestCase {
public void testSybaseDynamicSchema() {
OpenJPAEntityManagerFactorySPI sybaseEMF =
createEMF(EntityVeryLongNames.class,
createEMF(EntityVeryLongNames.class, EntityReservedWords.class,
"openjpa.ConnectionURL",
"jdbc:sybase:Tds:host:1234?ServiceName=db",
"openjpa.jdbc.SynchronizeMappings", "export",
@ -155,6 +156,17 @@ public class TestDynamicSchemas extends SingleEMFTestCase {
}
public void testFirebirdDynamicSchema() {
OpenJPAEntityManagerFactorySPI firebirdEMF =
createEMF(EntityVeryLongNames.class, EntityReservedWords.class,
"openjpa.ConnectionURL",
"jdbc:firebirdsql:host/1234:database",
"openjpa.jdbc.SynchronizeMappings", "export",
"openjpa.jdbc.SchemaFactory", "dynamic", RETAIN_DATA);
validateTableName( firebirdEMF );
}
private void validateTableName(OpenJPAEntityManagerFactorySPI emf) {
JDBCConfiguration conf = (JDBCConfiguration) emf.getConfiguration();
DBDictionary dict = conf.getDBDictionaryInstance();
@ -166,6 +178,14 @@ public class TestDynamicSchemas extends SingleEMFTestCase {
assertTrue(table.getName().length() > 0);
assertTrue(table.getName().length() <= dict.maxTableNameLength);
validateColumnNames(table, dict);
mapping = (ClassMapping)conf.
getMetaDataRepositoryInstance().
getMetaData(EntityReservedWords.class,getClass().
getClassLoader(), true);
table = mapping.getTable();
assertTrue(table.getName().length() > 0);
assertTrue(table.getName().length() <= dict.maxTableNameLength);
validateColumnNames(table, dict);
}
@ -174,6 +194,8 @@ public class TestDynamicSchemas extends SingleEMFTestCase {
for (Column column : columns) {
assertTrue(column.getName().length() > 0);
assertTrue(column.getName().length() <= dict.maxColumnNameLength);
assertFalse(dict.getInvalidColumnWordSet().
contains(column.getName().toUpperCase()));
}
}
}