Methods Summary |
---|
private boolean | areCompatible(org.hibernate.type.Type target, org.hibernate.type.Type source)Determine whether the two types are "assignment compatible".
if ( target.equals( source ) ) {
// if the types report logical equivalence, return true...
return true;
}
// otherwise, perform a "deep equivalence" check...
if ( !target.getReturnedClass().isAssignableFrom( source.getReturnedClass() ) ) {
return false;
}
int[] targetDatatypes = target.sqlTypes( getSessionFactoryHelper().getFactory() );
int[] sourceDatatypes = source.sqlTypes( getSessionFactoryHelper().getFactory() );
if ( targetDatatypes.length != sourceDatatypes.length ) {
return false;
}
for ( int i = 0; i < targetDatatypes.length; i++ ) {
if ( !areSqlTypesCompatible( targetDatatypes[i], sourceDatatypes[i] ) ) {
return false;
}
}
return true;
|
private boolean | areSqlTypesCompatible(int target, int source)
switch ( target ) {
case Types.TIMESTAMP:
return source == Types.DATE || source == Types.TIME || source == Types.TIMESTAMP;
case Types.DATE:
return source == Types.DATE || source == Types.TIMESTAMP;
case Types.TIME:
return source == Types.TIME || source == Types.TIMESTAMP;
default:
return target == source;
}
|
public java.lang.String | getDisplayText()Returns additional display text for the AST node.
StringBuffer buf = new StringBuffer();
buf.append( "IntoClause{" );
buf.append( "entityName=" ).append( getEntityName() );
buf.append( ",tableName=" ).append( getTableName() );
buf.append( ",columns={" ).append( columnSpec ).append( "}" );
buf.append( "}" );
return buf.toString();
|
public java.lang.String | getEntityName()
return persister.getEntityName();
|
public org.hibernate.type.Type[] | getInsertionTypes()
return types;
|
public org.hibernate.persister.entity.Queryable | getQueryable()
return persister;
|
public java.lang.String | getTableName()
return persister.getSubclassTableName( 0 );
|
public void | initialize(org.hibernate.persister.entity.Queryable persister)
if ( persister.isAbstract() ) {
throw new QueryException( "cannot insert into abstract class (no table)" );
}
this.persister = persister;
initializeColumns();
if ( getWalker().getSessionFactoryHelper().hasPhysicalDiscriminatorColumn( persister ) ) {
discriminated = true;
columnSpec += ", " + persister.getDiscriminatorColumnName();
}
resetText();
|
private void | initializeColumns()
AST propertySpec = getFirstChild();
List types = new ArrayList();
visitPropertySpecNodes( propertySpec.getFirstChild(), types );
this.types = ArrayHelper.toTypeArray( types );
columnSpec = columnSpec.substring( 0, columnSpec.length() - 2 );
|
public boolean | isDiscriminated()
return discriminated;
|
public boolean | isExplicitIdInsertion()
return explicitIdInsertion;
|
public boolean | isExplicitVersionInsertion()
return explicitVersionInsertion;
|
private boolean | isSuperclassProperty(java.lang.String propertyName)
// really there are two situations where it should be ok to allow the insertion
// into properties defined on a superclass:
// 1) union-subclass with an abstract root entity
// 2) discrim-subclass
//
// #1 is handled already because of the fact that
// UnionSubclassPersister alreay always returns 0
// for this call...
//
// we may want to disallow it for discrim-subclass just for
// consistency-sake (currently does not work anyway)...
return persister.getSubclassPropertyTableNumber( propertyName ) != 0;
|
public void | prependIdColumnSpec()
columnSpec = persister.getIdentifierColumnNames()[0] + ", " + columnSpec;
resetText();
|
public void | prependVersionColumnSpec()
columnSpec = persister.getPropertyColumnNames( persister.getVersionProperty() )[0] + ", " + columnSpec;
resetText();
|
private void | renderColumns(java.lang.String[] columnNames)
for ( int i = 0; i < columnNames.length; i++ ) {
columnSpec += columnNames[i] + ", ";
}
|
private void | resetText()
setText( "into " + getTableName() + " ( " + columnSpec + " )" );
|
public void | validateTypes(SelectClause selectClause)
Type[] selectTypes = selectClause.getQueryReturnTypes();
if ( selectTypes.length != types.length ) {
throw new QueryException( "number of select types did not match those for insert" );
}
for ( int i = 0; i < types.length; i++ ) {
if ( !areCompatible( types[i], selectTypes[i] ) ) {
throw new QueryException(
"insertion type [" + types[i] + "] and selection type [" +
selectTypes[i] + "] at position " + i + " are not compatible"
);
}
}
// otherwise, everything ok.
|
private void | visitPropertySpecNodes(antlr.collections.AST propertyNode, java.util.List types)
if ( propertyNode == null ) {
return;
}
// TODO : we really need to be able to deal with component paths here also;
// this is difficult because the hql-sql grammar expects all those node types
// to be FromReferenceNodes. One potential fix here would be to convert the
// IntoClause to just use a FromClause/FromElement combo (as a child of the
// InsertStatement) and move all this logic into the InsertStatement. That's
// probably the easiest approach (read: least amount of changes to the grammar
// and code), but just doesn't feel right as then an insert would contain
// 2 from-clauses
String name = propertyNode.getText();
if ( isSuperclassProperty( name ) ) {
throw new QueryException( "INSERT statements cannot refer to superclass/joined properties [" + name + "]" );
}
if ( name.equals( persister.getIdentifierPropertyName() ) ) {
explicitIdInsertion = true;
}
if ( persister.isVersioned() ) {
if ( name.equals( persister.getPropertyNames()[ persister.getVersionProperty() ] ) ) {
explicitVersionInsertion = true;
}
}
String[] columnNames = persister.toColumns( name );
renderColumns( columnNames );
types.add( persister.toType( name ) );
// visit width-first, then depth
visitPropertySpecNodes( propertyNode.getNextSibling(), types );
visitPropertySpecNodes( propertyNode.getFirstChild(), types );
|