HHH-4553 - Hibernate doesn't support official JPA2 escape char for table name

git-svn-id: https://svn.jboss.org/repos/hibernate/core/trunk@18158 1b8cb986-b30d-0410-93ca-fae66ebed9b2
This commit is contained in:
Steve Ebersole 2009-12-08 13:14:47 +00:00
parent 25343680c9
commit 6b9e796074
11 changed files with 145 additions and 71 deletions

View File

@ -444,6 +444,9 @@ public class BinderHelper {
( (org.hibernate.mapping.Column) id.getColumnIterator().next() ).getName()
);
}
// YUCK! but cannot think of a clean way to do this given the string-config based scheme
params.put( PersistentIdentifierGenerator.IDENTIFIER_NORMALIZER, mappings.getObjectNameNormalizer() );
if ( !isDefault( generatorName ) ) {
//we have a named generator
IdGenerator gen = mappings.getGenerator( generatorName, localGenerators );

View File

@ -189,9 +189,15 @@ public class Ejb3Column {
}
protected void initMappingColumn(
String columnName, String propertyName, int length, int precision, int scale, boolean nullable,
String sqlType, boolean unique, boolean applyNamingStrategy
) {
String columnName,
String propertyName,
int length,
int precision,
int scale,
boolean nullable,
String sqlType,
boolean unique,
boolean applyNamingStrategy) {
if ( StringHelper.isNotEmpty( formulaString ) ) {
this.formula = new Formula();
this.formula.setFormula( formulaString );
@ -218,16 +224,25 @@ public class Ejb3Column {
if ( applyNamingStrategy ) {
if ( StringHelper.isEmpty( columnName ) ) {
if ( propertyName != null ) {
mappingColumn.setName( mappings.getNamingStrategy().propertyToColumnName( propertyName ) );
mappingColumn.setName(
mappings.getObjectNameNormalizer().normalizeIdentifierQuoting(
mappings.getNamingStrategy().propertyToColumnName( propertyName )
)
);
}
//Do nothing otherwise
}
else {
mappingColumn.setName( mappings.getNamingStrategy().columnName( columnName ) );
columnName = mappings.getObjectNameNormalizer().normalizeIdentifierQuoting( columnName );
columnName = mappings.getNamingStrategy().columnName( columnName );
columnName = mappings.getObjectNameNormalizer().normalizeIdentifierQuoting( columnName );
mappingColumn.setName( columnName );
}
}
else {
if ( StringHelper.isNotEmpty( columnName ) ) mappingColumn.setName( columnName );
if ( StringHelper.isNotEmpty( columnName ) ) {
mappingColumn.setName( mappings.getObjectNameNormalizer().normalizeIdentifierQuoting( columnName ) );
}
}
}
@ -383,31 +398,38 @@ public class Ejb3Column {
log.debug( "Column(s) overridden for property {}", inferredData.getPropertyName() );
}
if ( actualCols == null ) {
columns = buildImplicitColumn( inferredData,
columns = buildImplicitColumn(
inferredData,
suffixForDefaultColumnName,
secondaryTables,
propertyHolder,
nullability,
mappings );
mappings
);
}
else {
final int length = actualCols.length;
columns = new Ejb3Column[length];
for (int index = 0; index < length; index++) {
final ObjectNameNormalizer nameNormalizer = mappings.getObjectNameNormalizer();
javax.persistence.Column col = actualCols[index];
String sqlType = col.columnDefinition().equals( "" ) ? null : col.columnDefinition();
final String sqlType = col.columnDefinition().equals( "" )
? null
: nameNormalizer.normalizeIdentifierQuoting( col.columnDefinition() );
final String tableName = nameNormalizer.normalizeIdentifierQuoting( col.table() );
final String columnName = nameNormalizer.normalizeIdentifierQuoting( col.name() );
Ejb3Column column = new Ejb3Column();
column.setImplicit( false );
column.setSqlType( sqlType );
column.setLength( col.length() );
column.setPrecision( col.precision() );
column.setScale( col.scale() );
column.setLogicalColumnName( col.name() );
//support for explicit property name + suffix
if ( StringHelper.isEmpty( column.getLogicalColumnName() )
&& ! StringHelper.isEmpty( suffixForDefaultColumnName ) ) {
if ( StringHelper.isEmpty( columnName ) && ! StringHelper.isEmpty( suffixForDefaultColumnName ) ) {
column.setLogicalColumnName( inferredData.getPropertyName() + suffixForDefaultColumnName );
}
else {
column.setLogicalColumnName( columnName );
}
column.setPropertyName(
BinderHelper.getRelativePath( propertyHolder, inferredData.getPropertyName() )
@ -418,7 +440,7 @@ public class Ejb3Column {
column.setUnique( col.unique() );
column.setInsertable( col.insertable() );
column.setUpdatable( col.updatable() );
column.setSecondaryTableName( col.table() );
column.setSecondaryTableName( tableName );
column.setPropertyHolder( propertyHolder );
column.setJoins( secondaryTables );
column.setMappings( mappings );
@ -436,12 +458,11 @@ public class Ejb3Column {
Map<String, Join> secondaryTables,
PropertyHolder propertyHolder,
Nullability nullability,
ExtendedMappings mappings
) {
Ejb3Column[] columns;
columns = new Ejb3Column[1];
ExtendedMappings mappings) {
Ejb3Column column = new Ejb3Column();
column.setImplicit( false );
Ejb3Column[] columns = new Ejb3Column[1];
columns[0] = column;
//not following the spec but more clean
if ( nullability != Nullability.FORCED_NULL
&& inferredData.getClassOrElement().isPrimitive()
@ -466,7 +487,6 @@ public class Ejb3Column {
column.setImplicit( true );
}
column.bind();
columns[0] = column;
return columns;
}

View File

@ -332,8 +332,14 @@ public class Ejb3JoinColumn extends Ejb3Column {
columnDefinition = joinAnn.columnDefinition();
referencedColumnName = joinAnn.referencedColumnName();
}
String sqlType = "".equals( columnDefinition ) ? null : columnDefinition;
String name = "".equals( colName ) ? defaultName : colName;
String sqlType = "".equals( columnDefinition )
? null
: mappings.getObjectNameNormalizer().normalizeIdentifierQuoting( columnDefinition );
String name = "".equals( colName )
? defaultName
: colName;
name = mappings.getObjectNameNormalizer().normalizeIdentifierQuoting( name );
return new Ejb3JoinColumn(
sqlType,
name, false, false,
@ -344,6 +350,7 @@ public class Ejb3JoinColumn extends Ejb3Column {
);
}
else {
defaultName = mappings.getObjectNameNormalizer().normalizeIdentifierQuoting( defaultName );
return new Ejb3JoinColumn(
(String) null, defaultName,
false, false, true, true, null, (String) null,

View File

@ -48,7 +48,6 @@ import org.hibernate.mapping.PersistentClass;
import org.hibernate.mapping.Property;
import org.hibernate.mapping.ToOne;
import org.hibernate.mapping.Value;
import org.hibernate.util.CollectionHelper;
import org.hibernate.util.StringHelper;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
@ -78,9 +77,8 @@ public class ResultsetMappingSecondPass implements QuerySecondPass {
for (EntityResult entity : ann.entities()) {
//TODO parameterize lock mode?
List properties = new ArrayList();
List propertyNames = new ArrayList();
Map propertyresults = new HashMap();
List<FieldResult> properties = new ArrayList<FieldResult>();
List<String> propertyNames = new ArrayList<String>();
for (FieldResult field : entity.fields()) {
//use an ArrayList cause we might have several columns per root property
String name = field.name();
@ -120,18 +118,16 @@ public class ResultsetMappingSecondPass implements QuerySecondPass {
}
}
Set uniqueReturnProperty = new HashSet();
Iterator iterator = properties.iterator();
while ( iterator.hasNext() ) {
FieldResult propertyresult = (FieldResult) iterator.next();
String name = propertyresult.name();
Set<String> uniqueReturnProperty = new HashSet<String>();
Map<String, ArrayList<String>> propertyResultsTmp = new HashMap<String, ArrayList<String>>();
for ( Object property : properties ) {
final FieldResult propertyresult = ( FieldResult ) property;
final String name = propertyresult.name();
if ( "class".equals( name ) ) {
throw new MappingException(
"class is not a valid property name to use in a @FieldResult, use @Entity(discriminatorColumn) instead"
);
}
ArrayList allResultColumns = new ArrayList();
allResultColumns.add( propertyresult.column() );
if ( uniqueReturnProperty.contains( name ) ) {
throw new MappingException(
@ -140,38 +136,56 @@ public class ResultsetMappingSecondPass implements QuerySecondPass {
);
}
uniqueReturnProperty.add( name );
final String quotingNormalizedColumnName = mappings.getObjectNameNormalizer()
.normalizeIdentifierQuoting( propertyresult.column() );
String key = StringHelper.root( name );
ArrayList intermediateResults = (ArrayList) propertyresults.get( key );
ArrayList<String> intermediateResults = propertyResultsTmp.get( key );
if ( intermediateResults == null ) {
propertyresults.put( key, allResultColumns );
}
else {
intermediateResults.addAll( allResultColumns );
intermediateResults = new ArrayList<String>();
propertyResultsTmp.put( key, intermediateResults );
}
intermediateResults.add( quotingNormalizedColumnName );
}
Iterator entries = propertyresults.entrySet().iterator();
while ( entries.hasNext() ) {
Map.Entry entry = (Map.Entry) entries.next();
if ( entry.getValue() instanceof ArrayList ) {
ArrayList list = (ArrayList) entry.getValue();
entry.setValue( list.toArray( new String[list.size()] ) );
}
Map<String, String[]> propertyResults = new HashMap<String,String[]>();
for ( Map.Entry<String, ArrayList<String>> entry : propertyResultsTmp.entrySet() ) {
propertyResults.put(
entry.getKey(),
entry.getValue().toArray( new String[ entry.getValue().size() ] )
);
}
if ( !BinderHelper.isDefault( entity.discriminatorColumn() ) ) {
propertyresults.put( "class", new String[] { entity.discriminatorColumn() } );
final String quotingNormalizedName = mappings.getObjectNameNormalizer().normalizeIdentifierQuoting(
entity.discriminatorColumn()
);
propertyResults.put( "class", new String[] { quotingNormalizedName } );
}
propertyresults = propertyresults.isEmpty() ? CollectionHelper.EMPTY_MAP : propertyresults;
NativeSQLQueryRootReturn result =
new NativeSQLQueryRootReturn(
"alias" + entityAliasIndex++, entity.entityClass().getName(), propertyresults, LockMode.READ
);
if ( propertyResults.isEmpty() ) {
propertyResults = java.util.Collections.emptyMap();
}
NativeSQLQueryRootReturn result = new NativeSQLQueryRootReturn(
"alias" + entityAliasIndex++,
entity.entityClass().getName(),
propertyResults,
LockMode.READ
);
definition.addQueryReturn( result );
}
for (ColumnResult column : ann.columns()) {
definition.addQueryReturn( new NativeSQLQueryScalarReturn( column.name(), null ) );
for ( ColumnResult column : ann.columns() ) {
definition.addQueryReturn(
new NativeSQLQueryScalarReturn(
mappings.getObjectNameNormalizer().normalizeIdentifierQuoting(
column.name()
),
null
)
);
}
if ( isDefault ) {
@ -182,6 +196,7 @@ public class ResultsetMappingSecondPass implements QuerySecondPass {
}
}
@SuppressWarnings({ "unchecked" })
private List getFollowers(Iterator parentPropIter, String reducedName, String name) {
boolean hasFollowers = false;
List followers = new ArrayList();

View File

@ -1,10 +1,10 @@
/*
* Hibernate, Relational Persistence for Idiomatic Java
*
* Copyright (c) 2009, Red Hat Middleware LLC or third-party contributors as
* indicated by the @author tags or express copyright attribution
* statements applied by the authors. All third-party contributions are
* distributed under license by Red Hat Middleware LLC.
* Copyright (c) 2009 by Red Hat Inc and/or its affiliates or by
* third-party contributors as indicated by either @author tags or express
* copyright attribution statements applied by the authors. All
* third-party contributions are distributed under license by Red Hat Inc.
*
* This copyrighted material is made available to anyone wishing to use, modify,
* copy, or redistribute it subject to the terms and conditions of the GNU
@ -20,7 +20,6 @@
* Free Software Foundation, Inc.
* 51 Franklin Street, Fifth Floor
* Boston, MA 02110-1301 USA
*
*/
package org.hibernate;

View File

@ -2451,12 +2451,14 @@ public class Configuration implements Serializable {
String name,
String subselect,
boolean isAbstract) {
name = getObjectNameNormalizer().normalizeIdentifierQuoting( name );
schema = getObjectNameNormalizer().normalizeIdentifierQuoting( schema );
catalog = getObjectNameNormalizer().normalizeIdentifierQuoting( catalog );
String key = subselect == null ? Table.qualify( catalog, schema, name ) : subselect;
Table table = ( Table ) tables.get( key );
if ( table == null ) {
schema = getObjectNameNormalizer().normalizeIdentifierQuoting( schema );
catalog = getObjectNameNormalizer().normalizeIdentifierQuoting( catalog );
table = new Table();
table.setAbstract( isAbstract );
table.setName( name );
@ -2481,14 +2483,15 @@ public class Configuration implements Serializable {
boolean isAbstract,
String subselect,
Table includedTable) throws DuplicateMappingException {
name = getObjectNameNormalizer().normalizeIdentifierQuoting( name );
schema = getObjectNameNormalizer().normalizeIdentifierQuoting( schema );
catalog = getObjectNameNormalizer().normalizeIdentifierQuoting( catalog );
String key = subselect == null ? Table.qualify(catalog, schema, name) : subselect;
if ( tables.containsKey( key ) ) {
throw new DuplicateMappingException( "table", name );
}
schema = getObjectNameNormalizer().normalizeIdentifierQuoting( schema );
catalog = getObjectNameNormalizer().normalizeIdentifierQuoting( catalog );
Table table = new DenormalizedTable( includedTable );
table.setAbstract( isAbstract );
table.setName( name );

View File

@ -100,8 +100,12 @@ public abstract class Constraint implements RelationalModel, Serializable {
public String sqlDropString(Dialect dialect, String defaultCatalog, String defaultSchema) {
if ( isGenerated( dialect ) ) {
return "alter table " + getTable()
.getQualifiedName( dialect, defaultCatalog, defaultSchema ) + " drop constraint " + getName();
return new StringBuffer()
.append( "alter table " )
.append( getTable().getQualifiedName( dialect, defaultCatalog, defaultSchema ) )
.append( " drop constraint " )
.append( dialect.quote( getName() ) )
.toString();
}
else {
return null;

View File

@ -39,22 +39,29 @@ public class UniqueKey extends Constraint {
public String sqlConstraintString(Dialect dialect) {
StringBuffer buf = new StringBuffer( "unique (" );
boolean hadNullableColumn = false;
Iterator iter = getColumnIterator();
boolean nullable = false;
while ( iter.hasNext() ) {
Column column = (Column) iter.next();
if ( !nullable && column.isNullable() ) nullable = true;
if ( !hadNullableColumn && column.isNullable() ) {
hadNullableColumn = true;
}
buf.append( column.getQuotedName( dialect ) );
if ( iter.hasNext() ) buf.append( ", " );
if ( iter.hasNext() ) {
buf.append( ", " );
}
}
//do not add unique constraint on DB not supporting unique and nullable columns
return !nullable || dialect.supportsNotNullUnique() ?
return !hadNullableColumn || dialect.supportsNotNullUnique() ?
buf.append( ')' ).toString() :
null;
}
public String sqlConstraintString(Dialect dialect, String constraintName, String defaultCatalog,
String defaultSchema) {
public String sqlConstraintString(
Dialect dialect,
String constraintName,
String defaultCatalog,
String defaultSchema) {
StringBuffer buf = new StringBuffer(
dialect.getAddPrimaryKeyConstraintString( constraintName )
).append( '(' );

View File

@ -188,6 +188,9 @@ public class Ejb3Configuration implements Serializable, Referenceable {
this.setProperty( Environment.DATASOURCE, metadata.getNonJtaDatasource() );
}
defineTransactionType( metadata.getTransactionType(), workingVars );
if ( metadata.isUseQuotedIdentifiers() ) {
this.setProperty( Environment.GLOBALLY_QUOTED_IDENTIFIERS, "true" );
}
if ( metadata.getClasses().size() > 0 ) {
workingVars.put( HibernatePersistence.CLASS_NAMES, metadata.getClasses() );
}

View File

@ -43,6 +43,7 @@ public class PersistenceMetadata {
private String jtaDatasource;
private String provider;
private PersistenceUnitTransactionType transactionType;
private boolean useQuotedIdentifiers = false; // the spec (erroneously?) calls this delimited-identifiers
private List<String> classes = new ArrayList<String>();
private List<String> packages = new ArrayList<String>();
private List<String> mappingFiles = new ArrayList<String>();
@ -94,6 +95,14 @@ public class PersistenceMetadata {
this.provider = provider;
}
public boolean isUseQuotedIdentifiers() {
return useQuotedIdentifiers;
}
public void setUseQuotedIdentifiers(boolean useQuotedIdentifiers) {
this.useQuotedIdentifiers = useQuotedIdentifiers;
}
public List<String> getClasses() {
return classes;
}
@ -162,6 +171,7 @@ public class PersistenceMetadata {
.append("\tnonJtaDataSource: ").append(nonJtaDatasource).append("\n")
.append("\ttransactionType: ").append(transactionType).append("\n")
.append("\tprovider: ").append(provider).append("\n")
.append("\tuseQuotedIdentifiers: ").append(useQuotedIdentifiers).append("\n")
.append("\tclasses[\n");
if (classes != null) {
for (String elt : classes) {

View File

@ -209,6 +209,9 @@ public final class PersistenceXmlLoader {
else if ( tag.equals( "exclude-unlisted-classes" ) ) {
metadata.setExcludeUnlistedClasses( true );
}
else if ( tag.equals( "delimited-identifiers" ) ) {
metadata.setUseQuotedIdentifiers( true );
}
else if ( tag.equals( "properties" ) ) {
NodeList props = element.getChildNodes();
for ( int j = 0; j < props.getLength() ; j++ ) {