HHH-530 : filters + subqueries;
HHH-3506 : filters + HQL update/delete git-svn-id: https://svn.jboss.org/repos/hibernate/core/branches/Branch_3_2@15240 1b8cb986-b30d-0410-93ca-fae66ebed9b2
This commit is contained in:
parent
9c37f6ad83
commit
43056f021c
|
@ -1,14 +1,13 @@
|
||||||
//$Id$
|
//$Id$
|
||||||
package org.hibernate.criterion;
|
package org.hibernate.criterion;
|
||||||
|
|
||||||
import java.util.HashMap;
|
|
||||||
|
|
||||||
import org.hibernate.Criteria;
|
import org.hibernate.Criteria;
|
||||||
import org.hibernate.EntityMode;
|
import org.hibernate.EntityMode;
|
||||||
import org.hibernate.HibernateException;
|
import org.hibernate.HibernateException;
|
||||||
import org.hibernate.engine.QueryParameters;
|
import org.hibernate.engine.QueryParameters;
|
||||||
import org.hibernate.engine.SessionFactoryImplementor;
|
import org.hibernate.engine.SessionFactoryImplementor;
|
||||||
import org.hibernate.engine.TypedValue;
|
import org.hibernate.engine.TypedValue;
|
||||||
|
import org.hibernate.engine.SessionImplementor;
|
||||||
import org.hibernate.impl.CriteriaImpl;
|
import org.hibernate.impl.CriteriaImpl;
|
||||||
import org.hibernate.loader.criteria.CriteriaJoinWalker;
|
import org.hibernate.loader.criteria.CriteriaJoinWalker;
|
||||||
import org.hibernate.loader.criteria.CriteriaQueryTranslator;
|
import org.hibernate.loader.criteria.CriteriaQueryTranslator;
|
||||||
|
@ -19,7 +18,7 @@ import org.hibernate.type.Type;
|
||||||
* @author Gavin King
|
* @author Gavin King
|
||||||
*/
|
*/
|
||||||
public abstract class SubqueryExpression implements Criterion {
|
public abstract class SubqueryExpression implements Criterion {
|
||||||
|
|
||||||
private CriteriaImpl criteriaImpl;
|
private CriteriaImpl criteriaImpl;
|
||||||
private String quantifier;
|
private String quantifier;
|
||||||
private String op;
|
private String op;
|
||||||
|
@ -30,49 +29,67 @@ public abstract class SubqueryExpression implements Criterion {
|
||||||
protected Type[] getTypes() {
|
protected Type[] getTypes() {
|
||||||
return types;
|
return types;
|
||||||
}
|
}
|
||||||
|
|
||||||
protected SubqueryExpression(String op, String quantifier, DetachedCriteria dc) {
|
protected SubqueryExpression(String op, String quantifier, DetachedCriteria dc) {
|
||||||
this.criteriaImpl = dc.getCriteriaImpl();
|
this.criteriaImpl = dc.getCriteriaImpl();
|
||||||
this.quantifier = quantifier;
|
this.quantifier = quantifier;
|
||||||
this.op = op;
|
this.op = op;
|
||||||
}
|
}
|
||||||
|
|
||||||
protected abstract String toLeftSqlString(Criteria criteria, CriteriaQuery outerQuery);
|
protected abstract String toLeftSqlString(Criteria criteria, CriteriaQuery outerQuery);
|
||||||
|
|
||||||
public String toSqlString(Criteria criteria, CriteriaQuery criteriaQuery)
|
public String toSqlString(Criteria criteria, CriteriaQuery criteriaQuery) throws HibernateException {
|
||||||
throws HibernateException {
|
|
||||||
|
|
||||||
final SessionFactoryImplementor factory = criteriaQuery.getFactory();
|
final SessionFactoryImplementor factory = criteriaQuery.getFactory();
|
||||||
final OuterJoinLoadable persister = (OuterJoinLoadable) factory.getEntityPersister( criteriaImpl.getEntityOrClassName() );
|
final OuterJoinLoadable persister =
|
||||||
|
( OuterJoinLoadable ) factory.getEntityPersister( criteriaImpl.getEntityOrClassName() );
|
||||||
|
|
||||||
createAndSetInnerQuery( criteriaQuery, factory );
|
createAndSetInnerQuery( criteriaQuery, factory );
|
||||||
|
criteriaImpl.setSession( deriveRootSession( criteria ) );
|
||||||
|
|
||||||
CriteriaJoinWalker walker = new CriteriaJoinWalker(
|
CriteriaJoinWalker walker = new CriteriaJoinWalker(
|
||||||
persister,
|
persister,
|
||||||
innerQuery,
|
innerQuery,
|
||||||
factory,
|
factory,
|
||||||
criteriaImpl,
|
criteriaImpl,
|
||||||
criteriaImpl.getEntityOrClassName(),
|
criteriaImpl.getEntityOrClassName(),
|
||||||
new HashMap(),
|
criteriaImpl.getSession().getEnabledFilters(),
|
||||||
innerQuery.getRootSQLALias());
|
innerQuery.getRootSQLALias()
|
||||||
|
);
|
||||||
|
|
||||||
String sql = walker.getSQLString();
|
String sql = walker.getSQLString();
|
||||||
|
|
||||||
final StringBuffer buf = new StringBuffer()
|
final StringBuffer buf = new StringBuffer( toLeftSqlString(criteria, criteriaQuery) );
|
||||||
.append( toLeftSqlString(criteria, criteriaQuery) );
|
if ( op != null ) {
|
||||||
if (op!=null) buf.append(' ').append(op).append(' ');
|
buf.append( ' ' ).append( op ).append( ' ' );
|
||||||
if (quantifier!=null) buf.append(quantifier).append(' ');
|
}
|
||||||
return buf.append('(').append(sql).append(')')
|
if ( quantifier != null ) {
|
||||||
.toString();
|
buf.append( quantifier ).append( ' ' );
|
||||||
|
}
|
||||||
|
return buf.append( '(' ).append( sql ).append( ')' )
|
||||||
|
.toString();
|
||||||
}
|
}
|
||||||
|
|
||||||
public TypedValue[] getTypedValues(Criteria criteria, CriteriaQuery criteriaQuery)
|
private SessionImplementor deriveRootSession(Criteria criteria) {
|
||||||
|
if ( criteria instanceof CriteriaImpl ) {
|
||||||
|
return ( ( CriteriaImpl ) criteria ).getSession();
|
||||||
|
}
|
||||||
|
else if ( criteria instanceof CriteriaImpl.Subcriteria ) {
|
||||||
|
return deriveRootSession( ( ( CriteriaImpl.Subcriteria ) criteria ).getParent() );
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
// could happen for custom Criteria impls. Not likely, but...
|
||||||
|
// for long term solution, see HHH-3514
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public TypedValue[] getTypedValues(Criteria criteria, CriteriaQuery criteriaQuery)
|
||||||
throws HibernateException {
|
throws HibernateException {
|
||||||
//the following two lines were added to ensure that this.params is not null, which
|
//the following two lines were added to ensure that this.params is not null, which
|
||||||
//can happen with two-deep nested subqueries
|
//can happen with two-deep nested subqueries
|
||||||
SessionFactoryImplementor factory = criteriaQuery.getFactory();
|
SessionFactoryImplementor factory = criteriaQuery.getFactory();
|
||||||
createAndSetInnerQuery(criteriaQuery, factory);
|
createAndSetInnerQuery(criteriaQuery, factory);
|
||||||
|
|
||||||
Type[] ppTypes = params.getPositionalParameterTypes();
|
Type[] ppTypes = params.getPositionalParameterTypes();
|
||||||
Object[] ppValues = params.getPositionalParameterValues();
|
Object[] ppValues = params.getPositionalParameterValues();
|
||||||
TypedValue[] tv = new TypedValue[ppTypes.length];
|
TypedValue[] tv = new TypedValue[ppTypes.length];
|
||||||
|
@ -83,12 +100,12 @@ public abstract class SubqueryExpression implements Criterion {
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Creates the inner query used to extract some useful information about
|
* Creates the inner query used to extract some useful information about types, since it is needed in both methods.
|
||||||
* types, since it is needed in both methods.
|
*
|
||||||
* @param criteriaQuery
|
* @param criteriaQuery The criteria query
|
||||||
* @param factory
|
* @param factory The session factory.
|
||||||
*/
|
*/
|
||||||
private void createAndSetInnerQuery(CriteriaQuery criteriaQuery, final SessionFactoryImplementor factory) {
|
private void createAndSetInnerQuery(CriteriaQuery criteriaQuery, SessionFactoryImplementor factory) {
|
||||||
if ( innerQuery == null ) {
|
if ( innerQuery == null ) {
|
||||||
//with two-deep subqueries, the same alias would get generated for
|
//with two-deep subqueries, the same alias would get generated for
|
||||||
//both using the old method (criteriaQuery.generateSQLAlias()), so
|
//both using the old method (criteriaQuery.generateSQLAlias()), so
|
||||||
|
|
|
@ -3,7 +3,6 @@ package org.hibernate.engine;
|
||||||
|
|
||||||
import java.io.Serializable;
|
import java.io.Serializable;
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.Arrays;
|
|
||||||
import java.util.Collection;
|
import java.util.Collection;
|
||||||
import java.util.Iterator;
|
import java.util.Iterator;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
@ -16,6 +15,7 @@ import org.apache.commons.logging.LogFactory;
|
||||||
import org.hibernate.HibernateException;
|
import org.hibernate.HibernateException;
|
||||||
import org.hibernate.QueryException;
|
import org.hibernate.QueryException;
|
||||||
import org.hibernate.ScrollMode;
|
import org.hibernate.ScrollMode;
|
||||||
|
import org.hibernate.impl.FilterImpl;
|
||||||
import org.hibernate.dialect.Dialect;
|
import org.hibernate.dialect.Dialect;
|
||||||
import org.hibernate.hql.classic.ParserHelper;
|
import org.hibernate.hql.classic.ParserHelper;
|
||||||
import org.hibernate.pretty.Printer;
|
import org.hibernate.pretty.Printer;
|
||||||
|
@ -46,29 +46,28 @@ public final class QueryParameters {
|
||||||
private boolean callable = false;
|
private boolean callable = false;
|
||||||
private boolean autodiscovertypes = false;
|
private boolean autodiscovertypes = false;
|
||||||
private boolean isNaturalKeyLookup;
|
private boolean isNaturalKeyLookup;
|
||||||
|
|
||||||
private final ResultTransformer resultTransformer; // why is all others non final ?
|
private final ResultTransformer resultTransformer; // why is all others non final ?
|
||||||
|
|
||||||
private String processedSQL;
|
private String processedSQL;
|
||||||
private Type[] processedPositionalParameterTypes;
|
private Type[] processedPositionalParameterTypes;
|
||||||
private Object[] processedPositionalParameterValues;
|
private Object[] processedPositionalParameterValues;
|
||||||
|
|
||||||
public QueryParameters() {
|
public QueryParameters() {
|
||||||
this( ArrayHelper.EMPTY_TYPE_ARRAY, ArrayHelper.EMPTY_OBJECT_ARRAY );
|
this( ArrayHelper.EMPTY_TYPE_ARRAY, ArrayHelper.EMPTY_OBJECT_ARRAY );
|
||||||
}
|
}
|
||||||
|
|
||||||
public QueryParameters(Type type, Object value) {
|
public QueryParameters(Type type, Object value) {
|
||||||
this( new Type[] {type}, new Object[] {value} );
|
this( new Type[] { type }, new Object[] { value } );
|
||||||
}
|
}
|
||||||
|
|
||||||
public QueryParameters(
|
public QueryParameters(
|
||||||
final Type[] positionalParameterTypes,
|
final Type[] positionalParameterTypes,
|
||||||
final Object[] postionalParameterValues,
|
final Object[] postionalParameterValues,
|
||||||
final Object optionalObject,
|
final Object optionalObject,
|
||||||
final String optionalEntityName,
|
final String optionalEntityName,
|
||||||
final Serializable optionalObjectId
|
final Serializable optionalObjectId) {
|
||||||
) {
|
this( positionalParameterTypes, postionalParameterValues );
|
||||||
this(positionalParameterTypes, postionalParameterValues);
|
|
||||||
this.optionalObject = optionalObject;
|
this.optionalObject = optionalObject;
|
||||||
this.optionalId = optionalObjectId;
|
this.optionalId = optionalObjectId;
|
||||||
this.optionalEntityName = optionalEntityName;
|
this.optionalEntityName = optionalEntityName;
|
||||||
|
@ -76,42 +75,24 @@ public final class QueryParameters {
|
||||||
}
|
}
|
||||||
|
|
||||||
public QueryParameters(
|
public QueryParameters(
|
||||||
final Type[] positionalParameterTypes,
|
final Type[] positionalParameterTypes,
|
||||||
final Object[] postionalParameterValues
|
final Object[] postionalParameterValues) {
|
||||||
) {
|
this( positionalParameterTypes, postionalParameterValues, null, null, false, null, null, false, null );
|
||||||
this(
|
|
||||||
positionalParameterTypes,
|
|
||||||
postionalParameterValues,
|
|
||||||
null,
|
|
||||||
null,
|
|
||||||
false,
|
|
||||||
null,
|
|
||||||
null,
|
|
||||||
false,
|
|
||||||
null
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public QueryParameters(
|
public QueryParameters(
|
||||||
final Type[] positionalParameterTypes,
|
final Type[] positionalParameterTypes,
|
||||||
final Object[] postionalParameterValues,
|
final Object[] postionalParameterValues,
|
||||||
final Serializable[] collectionKeys
|
final Serializable[] collectionKeys) {
|
||||||
) {
|
this( positionalParameterTypes, postionalParameterValues, null, collectionKeys );
|
||||||
this(
|
|
||||||
positionalParameterTypes,
|
|
||||||
postionalParameterValues,
|
|
||||||
null,
|
|
||||||
collectionKeys
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public QueryParameters(
|
public QueryParameters(
|
||||||
final Type[] positionalParameterTypes,
|
final Type[] positionalParameterTypes,
|
||||||
final Object[] postionalParameterValues,
|
final Object[] postionalParameterValues,
|
||||||
final Map namedParameters,
|
final Map namedParameters,
|
||||||
final Serializable[] collectionKeys
|
final Serializable[] collectionKeys) {
|
||||||
) {
|
this(
|
||||||
this(
|
|
||||||
positionalParameterTypes,
|
positionalParameterTypes,
|
||||||
postionalParameterValues,
|
postionalParameterValues,
|
||||||
namedParameters,
|
namedParameters,
|
||||||
|
@ -119,37 +100,36 @@ public final class QueryParameters {
|
||||||
null,
|
null,
|
||||||
false,
|
false,
|
||||||
false,
|
false,
|
||||||
null,
|
null,
|
||||||
null,
|
null,
|
||||||
collectionKeys,
|
collectionKeys,
|
||||||
null
|
null
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
public QueryParameters(
|
public QueryParameters(
|
||||||
final Type[] positionalParameterTypes,
|
final Type[] positionalParameterTypes,
|
||||||
final Object[] positionalParameterValues,
|
final Object[] positionalParameterValues,
|
||||||
final Map lockModes,
|
final Map lockModes,
|
||||||
final RowSelection rowSelection,
|
final RowSelection rowSelection,
|
||||||
final boolean cacheable,
|
final boolean cacheable,
|
||||||
final String cacheRegion,
|
final String cacheRegion,
|
||||||
//final boolean forceCacheRefresh,
|
//final boolean forceCacheRefresh,
|
||||||
final String comment,
|
final String comment,
|
||||||
final boolean isLookupByNaturalKey,
|
final boolean isLookupByNaturalKey,
|
||||||
final ResultTransformer transformer
|
final ResultTransformer transformer) {
|
||||||
) {
|
|
||||||
this(
|
this(
|
||||||
positionalParameterTypes,
|
positionalParameterTypes,
|
||||||
positionalParameterValues,
|
positionalParameterValues,
|
||||||
null,
|
null,
|
||||||
lockModes,
|
lockModes,
|
||||||
rowSelection,
|
rowSelection,
|
||||||
false,
|
false,
|
||||||
cacheable,
|
cacheable,
|
||||||
cacheRegion,
|
cacheRegion,
|
||||||
comment,
|
comment,
|
||||||
null,
|
null,
|
||||||
transformer
|
transformer
|
||||||
);
|
);
|
||||||
isNaturalKeyLookup = isLookupByNaturalKey;
|
isNaturalKeyLookup = isLookupByNaturalKey;
|
||||||
}
|
}
|
||||||
|
@ -166,8 +146,7 @@ public final class QueryParameters {
|
||||||
//final boolean forceCacheRefresh,
|
//final boolean forceCacheRefresh,
|
||||||
final String comment,
|
final String comment,
|
||||||
final Serializable[] collectionKeys,
|
final Serializable[] collectionKeys,
|
||||||
ResultTransformer transformer
|
ResultTransformer transformer) {
|
||||||
) {
|
|
||||||
this.positionalParameterTypes = positionalParameterTypes;
|
this.positionalParameterTypes = positionalParameterTypes;
|
||||||
this.positionalParameterValues = positionalParameterValues;
|
this.positionalParameterValues = positionalParameterValues;
|
||||||
this.namedParameters = namedParameters;
|
this.namedParameters = namedParameters;
|
||||||
|
@ -181,36 +160,35 @@ public final class QueryParameters {
|
||||||
this.readOnly = readOnly;
|
this.readOnly = readOnly;
|
||||||
this.resultTransformer = transformer;
|
this.resultTransformer = transformer;
|
||||||
}
|
}
|
||||||
|
|
||||||
public QueryParameters(
|
public QueryParameters(
|
||||||
final Type[] positionalParameterTypes,
|
final Type[] positionalParameterTypes,
|
||||||
final Object[] positionalParameterValues,
|
final Object[] positionalParameterValues,
|
||||||
final Map namedParameters,
|
final Map namedParameters,
|
||||||
final Map lockModes,
|
final Map lockModes,
|
||||||
final RowSelection rowSelection,
|
final RowSelection rowSelection,
|
||||||
final boolean readOnly,
|
final boolean readOnly,
|
||||||
final boolean cacheable,
|
final boolean cacheable,
|
||||||
final String cacheRegion,
|
final String cacheRegion,
|
||||||
//final boolean forceCacheRefresh,
|
//final boolean forceCacheRefresh,
|
||||||
final String comment,
|
final String comment,
|
||||||
final Serializable[] collectionKeys,
|
final Serializable[] collectionKeys,
|
||||||
final Object optionalObject,
|
final Object optionalObject,
|
||||||
final String optionalEntityName,
|
final String optionalEntityName,
|
||||||
final Serializable optionalId,
|
final Serializable optionalId,
|
||||||
final ResultTransformer transformer
|
final ResultTransformer transformer) {
|
||||||
) {
|
|
||||||
this(
|
this(
|
||||||
positionalParameterTypes,
|
positionalParameterTypes,
|
||||||
positionalParameterValues,
|
positionalParameterValues,
|
||||||
namedParameters,
|
namedParameters,
|
||||||
lockModes,
|
lockModes,
|
||||||
rowSelection,
|
rowSelection,
|
||||||
readOnly,
|
readOnly,
|
||||||
cacheable,
|
cacheable,
|
||||||
cacheRegion,
|
cacheRegion,
|
||||||
comment,
|
comment,
|
||||||
collectionKeys,
|
collectionKeys,
|
||||||
transformer
|
transformer
|
||||||
);
|
);
|
||||||
this.optionalEntityName = optionalEntityName;
|
this.optionalEntityName = optionalEntityName;
|
||||||
this.optionalId = optionalId;
|
this.optionalId = optionalId;
|
||||||
|
@ -218,7 +196,7 @@ public final class QueryParameters {
|
||||||
}
|
}
|
||||||
|
|
||||||
public boolean hasRowSelection() {
|
public boolean hasRowSelection() {
|
||||||
return rowSelection!=null;
|
return rowSelection != null;
|
||||||
}
|
}
|
||||||
|
|
||||||
public Map getNamedParameters() {
|
public Map getNamedParameters() {
|
||||||
|
@ -236,7 +214,7 @@ public final class QueryParameters {
|
||||||
public RowSelection getRowSelection() {
|
public RowSelection getRowSelection() {
|
||||||
return rowSelection;
|
return rowSelection;
|
||||||
}
|
}
|
||||||
|
|
||||||
public ResultTransformer getResultTransformer() {
|
public ResultTransformer getResultTransformer() {
|
||||||
return resultTransformer;
|
return resultTransformer;
|
||||||
}
|
}
|
||||||
|
@ -266,15 +244,15 @@ public final class QueryParameters {
|
||||||
}
|
}
|
||||||
|
|
||||||
public void traceParameters(SessionFactoryImplementor factory) throws HibernateException {
|
public void traceParameters(SessionFactoryImplementor factory) throws HibernateException {
|
||||||
Printer print = new Printer(factory);
|
Printer print = new Printer( factory );
|
||||||
if (positionalParameterValues.length!=0) {
|
if ( positionalParameterValues.length != 0 ) {
|
||||||
log.trace(
|
log.trace(
|
||||||
"parameters: " +
|
"parameters: " +
|
||||||
print.toString(positionalParameterTypes, positionalParameterValues)
|
print.toString( positionalParameterTypes, positionalParameterValues )
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
if (namedParameters!=null) {
|
if ( namedParameters != null ) {
|
||||||
log.trace( "named parameters: " + print.toString(namedParameters) );
|
log.trace( "named parameters: " + print.toString( namedParameters ) );
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -295,13 +273,13 @@ public final class QueryParameters {
|
||||||
}
|
}
|
||||||
|
|
||||||
public void validateParameters() throws QueryException {
|
public void validateParameters() throws QueryException {
|
||||||
int types = positionalParameterTypes==null ? 0 : positionalParameterTypes.length;
|
int types = positionalParameterTypes == null ? 0 : positionalParameterTypes.length;
|
||||||
int values = positionalParameterValues==null ? 0 : positionalParameterValues.length;
|
int values = positionalParameterValues == null ? 0 : positionalParameterValues.length;
|
||||||
if (types!=values) {
|
if ( types != values ) {
|
||||||
throw new QueryException(
|
throw new QueryException(
|
||||||
"Number of positional parameter types:" + types +
|
"Number of positional parameter types:" + types +
|
||||||
" does not match number of positional parameters: " + values
|
" does not match number of positional parameters: " + values
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -362,44 +340,49 @@ public final class QueryParameters {
|
||||||
}
|
}
|
||||||
|
|
||||||
public void setCallable(boolean callable) {
|
public void setCallable(boolean callable) {
|
||||||
this.callable = callable;
|
this.callable = callable;
|
||||||
}
|
}
|
||||||
|
|
||||||
public boolean isCallable() {
|
public boolean isCallable() {
|
||||||
return callable;
|
return callable;
|
||||||
}
|
}
|
||||||
|
|
||||||
public boolean hasAutoDiscoverScalarTypes() {
|
public boolean hasAutoDiscoverScalarTypes() {
|
||||||
return autodiscovertypes;
|
return autodiscovertypes;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void processFilters(String sql, SessionImplementor session) {
|
public void processFilters(String sql, SessionImplementor session) {
|
||||||
|
processFilters( sql, session.getEnabledFilters(), session.getFactory() );
|
||||||
if ( session.getEnabledFilters().size()==0 || sql.indexOf(ParserHelper.HQL_VARIABLE_PREFIX)<0 ) {
|
}
|
||||||
|
|
||||||
|
public void processFilters(String sql, Map filters, SessionFactoryImplementor factory) {
|
||||||
|
if ( filters.size() == 0 || sql.indexOf( ParserHelper.HQL_VARIABLE_PREFIX ) < 0 ) {
|
||||||
// HELLA IMPORTANT OPTIMIZATION!!!
|
// HELLA IMPORTANT OPTIMIZATION!!!
|
||||||
processedPositionalParameterValues = getPositionalParameterValues();
|
processedPositionalParameterValues = getPositionalParameterValues();
|
||||||
processedPositionalParameterTypes = getPositionalParameterTypes();
|
processedPositionalParameterTypes = getPositionalParameterTypes();
|
||||||
processedSQL = sql;
|
processedSQL = sql;
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
|
final Dialect dialect = factory.getDialect();
|
||||||
Dialect dialect = session.getFactory().getDialect();
|
|
||||||
String symbols = new StringBuffer().append( ParserHelper.HQL_SEPARATORS )
|
String symbols = new StringBuffer().append( ParserHelper.HQL_SEPARATORS )
|
||||||
.append( dialect.openQuote() )
|
.append( dialect.openQuote() )
|
||||||
.append( dialect.closeQuote() )
|
.append( dialect.closeQuote() )
|
||||||
.toString();
|
.toString();
|
||||||
StringTokenizer tokens = new StringTokenizer( sql, symbols, true );
|
StringTokenizer tokens = new StringTokenizer( sql, symbols, true );
|
||||||
StringBuffer result = new StringBuffer();
|
StringBuffer result = new StringBuffer();
|
||||||
|
|
||||||
List parameters = new ArrayList();
|
List parameters = new ArrayList();
|
||||||
List parameterTypes = new ArrayList();
|
List parameterTypes = new ArrayList();
|
||||||
|
|
||||||
|
int positionalIndex = 0;
|
||||||
while ( tokens.hasMoreTokens() ) {
|
while ( tokens.hasMoreTokens() ) {
|
||||||
final String token = tokens.nextToken();
|
final String token = tokens.nextToken();
|
||||||
if ( token.startsWith( ParserHelper.HQL_VARIABLE_PREFIX ) ) {
|
if ( token.startsWith( ParserHelper.HQL_VARIABLE_PREFIX ) ) {
|
||||||
String filterParameterName = token.substring( 1 );
|
final String filterParameterName = token.substring( 1 );
|
||||||
Object value = session.getFilterParameterValue( filterParameterName );
|
final String[] parts = parseFilterParameterName( filterParameterName );
|
||||||
Type type = session.getFilterParameterType( filterParameterName );
|
final FilterImpl filter = ( FilterImpl ) filters.get( parts[0] );
|
||||||
|
final Object value = filter.getParameter( parts[1] );
|
||||||
|
final Type type = filter.getFilterDefinition().getParameterType( parts[1] );
|
||||||
if ( value != null && Collection.class.isAssignableFrom( value.getClass() ) ) {
|
if ( value != null && Collection.class.isAssignableFrom( value.getClass() ) ) {
|
||||||
Iterator itr = ( ( Collection ) value ).iterator();
|
Iterator itr = ( ( Collection ) value ).iterator();
|
||||||
while ( itr.hasNext() ) {
|
while ( itr.hasNext() ) {
|
||||||
|
@ -419,15 +402,17 @@ public final class QueryParameters {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
|
if ( "?".equals( token ) && positionalIndex < getPositionalParameterValues().length ) {
|
||||||
|
parameters.add( getPositionalParameterValues()[positionalIndex] );
|
||||||
|
parameterTypes.add( getPositionalParameterTypes()[positionalIndex] );
|
||||||
|
positionalIndex++;
|
||||||
|
}
|
||||||
result.append( token );
|
result.append( token );
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
parameters.addAll( Arrays.asList( getPositionalParameterValues() ) );
|
|
||||||
parameterTypes.addAll( Arrays.asList( getPositionalParameterTypes() ) );
|
|
||||||
processedPositionalParameterValues = parameters.toArray();
|
processedPositionalParameterValues = parameters.toArray();
|
||||||
processedPositionalParameterTypes = ( Type[] ) parameterTypes.toArray( new Type[0] );
|
processedPositionalParameterTypes = ( Type[] ) parameterTypes.toArray( new Type[parameterTypes.size()] );
|
||||||
processedSQL = result.toString();
|
processedSQL = result.toString();
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -458,16 +443,16 @@ public final class QueryParameters {
|
||||||
public QueryParameters createCopyUsing(RowSelection selection) {
|
public QueryParameters createCopyUsing(RowSelection selection) {
|
||||||
QueryParameters copy = new QueryParameters(
|
QueryParameters copy = new QueryParameters(
|
||||||
this.positionalParameterTypes,
|
this.positionalParameterTypes,
|
||||||
this.positionalParameterValues,
|
this.positionalParameterValues,
|
||||||
this.namedParameters,
|
this.namedParameters,
|
||||||
this.lockModes,
|
this.lockModes,
|
||||||
selection,
|
selection,
|
||||||
this.readOnly,
|
this.readOnly,
|
||||||
this.cacheable,
|
this.cacheable,
|
||||||
this.cacheRegion,
|
this.cacheRegion,
|
||||||
this.comment,
|
this.comment,
|
||||||
this.collectionKeys,
|
this.collectionKeys,
|
||||||
this.optionalObject,
|
this.optionalObject,
|
||||||
this.optionalEntityName,
|
this.optionalEntityName,
|
||||||
this.optionalId,
|
this.optionalId,
|
||||||
this.resultTransformer
|
this.resultTransformer
|
||||||
|
@ -478,5 +463,13 @@ public final class QueryParameters {
|
||||||
return copy;
|
return copy;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public static String[] parseFilterParameterName(String filterParameterName) {
|
||||||
|
int dot = filterParameterName.indexOf( '.' );
|
||||||
|
if ( dot <= 0 ) {
|
||||||
|
throw new IllegalArgumentException( "Invalid filter-parameter name format" );
|
||||||
|
}
|
||||||
|
String filterName = filterParameterName.substring( 0, dot );
|
||||||
|
String parameterName = filterParameterName.substring( dot + 1 );
|
||||||
|
return new String[] { filterName, parameterName };
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -209,6 +209,10 @@ public class HqlSqlWalker extends HqlSqlBaseWalker implements ErrorReporter, Par
|
||||||
return collectionFilterRole != null;
|
return collectionFilterRole != null;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public String getCollectionFilterRole() {
|
||||||
|
return collectionFilterRole;
|
||||||
|
}
|
||||||
|
|
||||||
public SessionFactoryHelper getSessionFactoryHelper() {
|
public SessionFactoryHelper getSessionFactoryHelper() {
|
||||||
return sessionFactoryHelper;
|
return sessionFactoryHelper;
|
||||||
}
|
}
|
||||||
|
@ -531,8 +535,8 @@ public class HqlSqlWalker extends HqlSqlBaseWalker implements ErrorReporter, Par
|
||||||
|
|
||||||
// After that, process the JOINs.
|
// After that, process the JOINs.
|
||||||
// Invoke a delegate to do the work, as this is farily complex.
|
// Invoke a delegate to do the work, as this is farily complex.
|
||||||
JoinProcessor joinProcessor = new JoinProcessor( astFactory, queryTranslatorImpl );
|
JoinProcessor joinProcessor = new JoinProcessor( this );
|
||||||
joinProcessor.processJoins( qn, isSubQuery() );
|
joinProcessor.processJoins( qn );
|
||||||
|
|
||||||
// Attach any mapping-defined "ORDER BY" fragments
|
// Attach any mapping-defined "ORDER BY" fragments
|
||||||
Iterator itr = qn.getFromClause().getProjectionList().iterator();
|
Iterator itr = qn.getFromClause().getProjectionList().iterator();
|
||||||
|
@ -570,13 +574,21 @@ public class HqlSqlWalker extends HqlSqlBaseWalker implements ErrorReporter, Par
|
||||||
// Make #@%$^#^&# sure no alias is applied to the table name
|
// Make #@%$^#^&# sure no alias is applied to the table name
|
||||||
fromElement.setText( persister.getTableName() );
|
fromElement.setText( persister.getTableName() );
|
||||||
|
|
||||||
// append any filter fragments; the EMPTY_MAP is used under the assumption that
|
// // append any filter fragments; the EMPTY_MAP is used under the assumption that
|
||||||
// currently enabled filters should not affect this process
|
// // currently enabled filters should not affect this process
|
||||||
if ( persister.getDiscriminatorType() != null ) {
|
// if ( persister.getDiscriminatorType() != null ) {
|
||||||
new SyntheticAndFactory( getASTFactory() ).addDiscriminatorWhereFragment(
|
// new SyntheticAndFactory( getASTFactory() ).addDiscriminatorWhereFragment(
|
||||||
|
// statement,
|
||||||
|
// persister,
|
||||||
|
// java.util.Collections.EMPTY_MAP,
|
||||||
|
// fromElement.getTableAlias()
|
||||||
|
// );
|
||||||
|
// }
|
||||||
|
if ( persister.getDiscriminatorType() != null || ! queryTranslatorImpl.getEnabledFilters().isEmpty() ) {
|
||||||
|
new SyntheticAndFactory( this ).addDiscriminatorWhereFragment(
|
||||||
statement,
|
statement,
|
||||||
persister,
|
persister,
|
||||||
java.util.Collections.EMPTY_MAP,
|
queryTranslatorImpl.getEnabledFilters(),
|
||||||
fromElement.getTableAlias()
|
fromElement.getTableAlias()
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
|
@ -74,6 +74,8 @@ public class QueryTranslatorImpl implements FilterTranslator {
|
||||||
private String sql;
|
private String sql;
|
||||||
|
|
||||||
private ParameterTranslations paramTranslations;
|
private ParameterTranslations paramTranslations;
|
||||||
|
private List collectedParameterSpecifications;
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Creates a new AST-based query translator.
|
* Creates a new AST-based query translator.
|
||||||
|
@ -217,6 +219,7 @@ public class QueryTranslatorImpl implements FilterTranslator {
|
||||||
log.debug( "SQL: " + sql );
|
log.debug( "SQL: " + sql );
|
||||||
}
|
}
|
||||||
gen.getParseErrorHandler().throwQueryException();
|
gen.getParseErrorHandler().throwQueryException();
|
||||||
|
collectedParameterSpecifications = gen.getCollectedParameters();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -540,10 +543,15 @@ public class QueryTranslatorImpl implements FilterTranslator {
|
||||||
public ParameterTranslations getParameterTranslations() {
|
public ParameterTranslations getParameterTranslations() {
|
||||||
if ( paramTranslations == null ) {
|
if ( paramTranslations == null ) {
|
||||||
paramTranslations = new ParameterTranslationsImpl( getWalker().getParameters() );
|
paramTranslations = new ParameterTranslationsImpl( getWalker().getParameters() );
|
||||||
|
// paramTranslations = new ParameterTranslationsImpl( collectedParameterSpecifications );
|
||||||
}
|
}
|
||||||
return paramTranslations;
|
return paramTranslations;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public List getCollectedParameterSpecifications() {
|
||||||
|
return collectedParameterSpecifications;
|
||||||
|
}
|
||||||
|
|
||||||
public static class JavaConstantConverter implements NodeTraverser.VisitationStrategy {
|
public static class JavaConstantConverter implements NodeTraverser.VisitationStrategy {
|
||||||
private AST dotRoot;
|
private AST dotRoot;
|
||||||
public void visit(AST node) {
|
public void visit(AST node) {
|
||||||
|
|
|
@ -4,16 +4,20 @@ package org.hibernate.hql.ast;
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.LinkedList;
|
import java.util.LinkedList;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
import java.util.Arrays;
|
||||||
|
|
||||||
import antlr.RecognitionException;
|
import antlr.RecognitionException;
|
||||||
import antlr.collections.AST;
|
import antlr.collections.AST;
|
||||||
import org.hibernate.QueryException;
|
import org.hibernate.QueryException;
|
||||||
|
import org.hibernate.param.ParameterSpecification;
|
||||||
import org.hibernate.dialect.function.SQLFunction;
|
import org.hibernate.dialect.function.SQLFunction;
|
||||||
import org.hibernate.engine.SessionFactoryImplementor;
|
import org.hibernate.engine.SessionFactoryImplementor;
|
||||||
import org.hibernate.hql.antlr.SqlGeneratorBase;
|
import org.hibernate.hql.antlr.SqlGeneratorBase;
|
||||||
import org.hibernate.hql.ast.tree.MethodNode;
|
import org.hibernate.hql.ast.tree.MethodNode;
|
||||||
import org.hibernate.hql.ast.tree.FromElement;
|
import org.hibernate.hql.ast.tree.FromElement;
|
||||||
import org.hibernate.hql.ast.tree.Node;
|
import org.hibernate.hql.ast.tree.Node;
|
||||||
|
import org.hibernate.hql.ast.tree.ParameterNode;
|
||||||
|
import org.hibernate.hql.ast.tree.ParameterContainer;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Generates SQL by overriding callback methods in the base class, which does
|
* Generates SQL by overriding callback methods in the base class, which does
|
||||||
|
@ -41,6 +45,12 @@ public class SqlGenerator extends SqlGeneratorBase implements ErrorReporter {
|
||||||
|
|
||||||
private LinkedList outputStack = new LinkedList();
|
private LinkedList outputStack = new LinkedList();
|
||||||
|
|
||||||
|
private List collectedParameters = new ArrayList();
|
||||||
|
|
||||||
|
public List getCollectedParameters() {
|
||||||
|
return collectedParameters;
|
||||||
|
}
|
||||||
|
|
||||||
protected void out(String s) {
|
protected void out(String s) {
|
||||||
writer.clause( s );
|
writer.clause( s );
|
||||||
}
|
}
|
||||||
|
@ -52,6 +62,18 @@ public class SqlGenerator extends SqlGeneratorBase implements ErrorReporter {
|
||||||
else {
|
else {
|
||||||
super.out( n );
|
super.out( n );
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if ( n instanceof ParameterNode ) {
|
||||||
|
collectedParameters.add( ( ( ParameterNode ) n ).getHqlParameterSpecification() );
|
||||||
|
}
|
||||||
|
else if ( n instanceof ParameterContainer ) {
|
||||||
|
if ( ( ( ParameterContainer ) n ).hasEmbeddedParameters() ) {
|
||||||
|
ParameterSpecification[] specifications = ( ( ParameterContainer ) n ).getEmbeddedParameters();
|
||||||
|
if ( specifications != null ) {
|
||||||
|
collectedParameters.addAll( Arrays.asList( specifications ) );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
protected void commaBetweenParameters(String comma) {
|
protected void commaBetweenParameters(String comma) {
|
||||||
|
|
|
@ -4,6 +4,8 @@ package org.hibernate.hql.ast.exec;
|
||||||
import java.sql.PreparedStatement;
|
import java.sql.PreparedStatement;
|
||||||
import java.sql.Connection;
|
import java.sql.Connection;
|
||||||
import java.sql.Statement;
|
import java.sql.Statement;
|
||||||
|
import java.util.Collections;
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
import org.hibernate.HibernateException;
|
import org.hibernate.HibernateException;
|
||||||
import org.hibernate.action.BulkOperationCleanupAction;
|
import org.hibernate.action.BulkOperationCleanupAction;
|
||||||
|
@ -34,6 +36,7 @@ public abstract class AbstractStatementExecutor implements StatementExecutor {
|
||||||
|
|
||||||
private final Log log;
|
private final Log log;
|
||||||
private final HqlSqlWalker walker;
|
private final HqlSqlWalker walker;
|
||||||
|
private List idSelectParameterSpecifications = Collections.EMPTY_LIST;
|
||||||
|
|
||||||
public AbstractStatementExecutor(HqlSqlWalker walker, Log log) {
|
public AbstractStatementExecutor(HqlSqlWalker walker, Log log) {
|
||||||
this.walker = walker;
|
this.walker = walker;
|
||||||
|
@ -48,6 +51,10 @@ public abstract class AbstractStatementExecutor implements StatementExecutor {
|
||||||
return walker.getSessionFactoryHelper().getFactory();
|
return walker.getSessionFactoryHelper().getFactory();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
protected List getIdSelectParameterSpecifications() {
|
||||||
|
return idSelectParameterSpecifications;
|
||||||
|
}
|
||||||
|
|
||||||
protected abstract Queryable[] getAffectedQueryables();
|
protected abstract Queryable[] getAffectedQueryables();
|
||||||
|
|
||||||
protected String generateIdInsertSelect(Queryable persister, String tableAlias, AST whereClause) {
|
protected String generateIdInsertSelect(Queryable persister, String tableAlias, AST whereClause) {
|
||||||
|
@ -80,6 +87,7 @@ public abstract class AbstractStatementExecutor implements StatementExecutor {
|
||||||
SqlGenerator sqlGenerator = new SqlGenerator( getFactory() );
|
SqlGenerator sqlGenerator = new SqlGenerator( getFactory() );
|
||||||
sqlGenerator.whereClause( whereClause );
|
sqlGenerator.whereClause( whereClause );
|
||||||
userWhereClause = sqlGenerator.getSQL().substring( 7 ); // strip the " where "
|
userWhereClause = sqlGenerator.getSQL().substring( 7 ); // strip the " where "
|
||||||
|
idSelectParameterSpecifications = sqlGenerator.getCollectedParameters();
|
||||||
}
|
}
|
||||||
catch ( RecognitionException e ) {
|
catch ( RecognitionException e ) {
|
||||||
throw new HibernateException( "Unable to generate id select for DML operation", e );
|
throw new HibernateException( "Unable to generate id select for DML operation", e );
|
||||||
|
|
|
@ -4,6 +4,7 @@ package org.hibernate.hql.ast.exec;
|
||||||
import java.sql.PreparedStatement;
|
import java.sql.PreparedStatement;
|
||||||
import java.sql.SQLException;
|
import java.sql.SQLException;
|
||||||
import java.util.Iterator;
|
import java.util.Iterator;
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
import org.hibernate.HibernateException;
|
import org.hibernate.HibernateException;
|
||||||
import org.hibernate.engine.QueryParameters;
|
import org.hibernate.engine.QueryParameters;
|
||||||
|
@ -31,6 +32,7 @@ public class BasicExecutor extends AbstractStatementExecutor {
|
||||||
|
|
||||||
private final Queryable persister;
|
private final Queryable persister;
|
||||||
private final String sql;
|
private final String sql;
|
||||||
|
private final List parameterSpecifications;
|
||||||
|
|
||||||
public BasicExecutor(HqlSqlWalker walker, Queryable persister) {
|
public BasicExecutor(HqlSqlWalker walker, Queryable persister) {
|
||||||
super( walker, log );
|
super( walker, log );
|
||||||
|
@ -40,6 +42,7 @@ public class BasicExecutor extends AbstractStatementExecutor {
|
||||||
gen.statement( walker.getAST() );
|
gen.statement( walker.getAST() );
|
||||||
sql = gen.getSQL();
|
sql = gen.getSQL();
|
||||||
gen.getParseErrorHandler().throwQueryException();
|
gen.getParseErrorHandler().throwQueryException();
|
||||||
|
parameterSpecifications = gen.getCollectedParameters();
|
||||||
}
|
}
|
||||||
catch ( RecognitionException e ) {
|
catch ( RecognitionException e ) {
|
||||||
throw QuerySyntaxException.convert( e );
|
throw QuerySyntaxException.convert( e );
|
||||||
|
@ -60,10 +63,10 @@ public class BasicExecutor extends AbstractStatementExecutor {
|
||||||
try {
|
try {
|
||||||
try {
|
try {
|
||||||
st = session.getBatcher().prepareStatement( sql );
|
st = session.getBatcher().prepareStatement( sql );
|
||||||
Iterator paramSpecifications = getWalker().getParameters().iterator();
|
Iterator parameterSpecifications = this.parameterSpecifications.iterator();
|
||||||
int pos = 1;
|
int pos = 1;
|
||||||
while ( paramSpecifications.hasNext() ) {
|
while ( parameterSpecifications.hasNext() ) {
|
||||||
final ParameterSpecification paramSpec = ( ParameterSpecification ) paramSpecifications.next();
|
final ParameterSpecification paramSpec = ( ParameterSpecification ) parameterSpecifications.next();
|
||||||
pos += paramSpec.bind( st, parameters, session, pos );
|
pos += paramSpec.bind( st, parameters, session, pos );
|
||||||
}
|
}
|
||||||
if ( selection != null ) {
|
if ( selection != null ) {
|
||||||
|
|
|
@ -84,7 +84,7 @@ public class MultiTableDeleteExecutor extends AbstractStatementExecutor {
|
||||||
try {
|
try {
|
||||||
try {
|
try {
|
||||||
ps = session.getBatcher().prepareStatement( idInsertSelect );
|
ps = session.getBatcher().prepareStatement( idInsertSelect );
|
||||||
Iterator paramSpecifications = getWalker().getParameters().iterator();
|
Iterator paramSpecifications = getIdSelectParameterSpecifications().iterator();
|
||||||
int pos = 1;
|
int pos = 1;
|
||||||
while ( paramSpecifications.hasNext() ) {
|
while ( paramSpecifications.hasNext() ) {
|
||||||
final ParameterSpecification paramSpec = ( ParameterSpecification ) paramSpecifications.next();
|
final ParameterSpecification paramSpec = ( ParameterSpecification ) paramSpecifications.next();
|
||||||
|
|
|
@ -109,7 +109,7 @@ public class MultiTableUpdateExecutor extends AbstractStatementExecutor {
|
||||||
try {
|
try {
|
||||||
ps = session.getBatcher().prepareStatement( idInsertSelect );
|
ps = session.getBatcher().prepareStatement( idInsertSelect );
|
||||||
int parameterStart = getWalker().getNumberOfParametersInSetClause();
|
int parameterStart = getWalker().getNumberOfParametersInSetClause();
|
||||||
List allParams = getWalker().getParameters();
|
List allParams = getIdSelectParameterSpecifications();
|
||||||
Iterator whereParams = allParams.subList( parameterStart, allParams.size() ).iterator();
|
Iterator whereParams = allParams.subList( parameterStart, allParams.size() ).iterator();
|
||||||
int sum = 1; // jdbc params are 1-based
|
int sum = 1; // jdbc params are 1-based
|
||||||
while ( whereParams.hasNext() ) {
|
while ( whereParams.hasNext() ) {
|
||||||
|
|
|
@ -3,8 +3,10 @@ package org.hibernate.hql.ast.tree;
|
||||||
|
|
||||||
import java.util.LinkedList;
|
import java.util.LinkedList;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
import java.util.ArrayList;
|
||||||
|
|
||||||
import org.hibernate.QueryException;
|
import org.hibernate.QueryException;
|
||||||
|
import org.hibernate.param.ParameterSpecification;
|
||||||
import org.hibernate.engine.JoinSequence;
|
import org.hibernate.engine.JoinSequence;
|
||||||
import org.hibernate.hql.QueryTranslator;
|
import org.hibernate.hql.QueryTranslator;
|
||||||
import org.hibernate.hql.CollectionProperties;
|
import org.hibernate.hql.CollectionProperties;
|
||||||
|
@ -36,7 +38,7 @@ import org.apache.commons.logging.LogFactory;
|
||||||
* Date: Dec 6, 2003<br>
|
* Date: Dec 6, 2003<br>
|
||||||
* Time: 10:28:17 AM<br>
|
* Time: 10:28:17 AM<br>
|
||||||
*/
|
*/
|
||||||
public class FromElement extends HqlSqlWalkerNode implements DisplayableNode {
|
public class FromElement extends HqlSqlWalkerNode implements DisplayableNode, ParameterContainer {
|
||||||
private static final Log log = LogFactory.getLog( FromElement.class );
|
private static final Log log = LogFactory.getLog( FromElement.class );
|
||||||
|
|
||||||
private String className;
|
private String className;
|
||||||
|
@ -548,4 +550,23 @@ public class FromElement extends HqlSqlWalkerNode implements DisplayableNode {
|
||||||
public boolean isDereferencedBySubclassProperty() {
|
public boolean isDereferencedBySubclassProperty() {
|
||||||
return dereferencedBySubclassProperty;
|
return dereferencedBySubclassProperty;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// ParameterContainer impl ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||||
|
private List embeddedParameters;
|
||||||
|
|
||||||
|
public void addEmbeddedParameter(ParameterSpecification specification) {
|
||||||
|
if ( embeddedParameters == null ) {
|
||||||
|
embeddedParameters = new ArrayList();
|
||||||
|
}
|
||||||
|
embeddedParameters.add( specification );
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean hasEmbeddedParameters() {
|
||||||
|
return embeddedParameters != null && ! embeddedParameters.isEmpty();
|
||||||
|
}
|
||||||
|
|
||||||
|
public ParameterSpecification[] getEmbeddedParameters() {
|
||||||
|
return ( ParameterSpecification[] ) embeddedParameters.toArray( new ParameterSpecification[ embeddedParameters.size() ] );
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -0,0 +1,77 @@
|
||||||
|
/*
|
||||||
|
* Hibernate, Relational Persistence for Idiomatic Java
|
||||||
|
*
|
||||||
|
* Copyright (c) 2008, 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.
|
||||||
|
*
|
||||||
|
* 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
|
||||||
|
* Lesser General Public License, as published by the Free Software Foundation.
|
||||||
|
*
|
||||||
|
* This program is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
|
||||||
|
* or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License
|
||||||
|
* for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU Lesser General Public License
|
||||||
|
* along with this distribution; if not, write to:
|
||||||
|
* Free Software Foundation, Inc.
|
||||||
|
* 51 Franklin Street, Fifth Floor
|
||||||
|
* Boston, MA 02110-1301 USA
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
package org.hibernate.hql.ast.tree;
|
||||||
|
|
||||||
|
import org.hibernate.param.ParameterSpecification;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Currently this is needed in order to deal with {@link FromElement FromElements} which
|
||||||
|
* conatin "hidden" JDBC parameters from applying filters.
|
||||||
|
* <p/>
|
||||||
|
* Would love for this to go away, but that would require that Hibernate's
|
||||||
|
* internal {@link org.hibernate.engine.JoinSequence join handling} be able to either:<ul>
|
||||||
|
* <li>render the same AST structures</li>
|
||||||
|
* <li>render structures capable of being converted to these AST structures</li>
|
||||||
|
* </ul>
|
||||||
|
* <p/>
|
||||||
|
* In the interim, this allows us to at least treat these "hidden" parameters properly which is
|
||||||
|
* the most pressing need.
|
||||||
|
*
|
||||||
|
* @deprecated
|
||||||
|
* @author Steve Ebersole
|
||||||
|
*/
|
||||||
|
public interface ParameterContainer {
|
||||||
|
/**
|
||||||
|
* Set the renderable text of this node.
|
||||||
|
*
|
||||||
|
* @param text The renderable text
|
||||||
|
*/
|
||||||
|
public void setText(String text);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Adds a parameter specification for a parameter encountered within this node. We use the term 'embedded' here
|
||||||
|
* because of the fact that the parameter was simply encountered as part of the node's text; it does not exist
|
||||||
|
* as part of a subtree as it might in a true AST.
|
||||||
|
*
|
||||||
|
* @param specification The generated specification.
|
||||||
|
*/
|
||||||
|
public void addEmbeddedParameter(ParameterSpecification specification);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Determine whether this node contans embedded parameters. The implication is that
|
||||||
|
* {@link #getEmbeddedParameters()} is allowed to return null if this method returns false.
|
||||||
|
*
|
||||||
|
* @return True if this node contains embedded parameters; false otherwise.
|
||||||
|
*/
|
||||||
|
public boolean hasEmbeddedParameters();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Retrieve all embedded parameter specifications.
|
||||||
|
*
|
||||||
|
* @return All embedded parameter specifications; may return null.
|
||||||
|
* @see #hasEmbeddedParameters()
|
||||||
|
*/
|
||||||
|
public ParameterSpecification[] getEmbeddedParameters();
|
||||||
|
}
|
|
@ -1,14 +1,41 @@
|
||||||
// $Id$
|
/*
|
||||||
|
* Hibernate, Relational Persistence for Idiomatic Java
|
||||||
|
*
|
||||||
|
* Copyright (c) 2008, 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.
|
||||||
|
*
|
||||||
|
* 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
|
||||||
|
* Lesser General Public License, as published by the Free Software Foundation.
|
||||||
|
*
|
||||||
|
* This program is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
|
||||||
|
* or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License
|
||||||
|
* for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU Lesser General Public License
|
||||||
|
* along with this distribution; if not, write to:
|
||||||
|
* Free Software Foundation, Inc.
|
||||||
|
* 51 Franklin Street, Fifth Floor
|
||||||
|
* Boston, MA 02110-1301 USA
|
||||||
|
*
|
||||||
|
*/
|
||||||
package org.hibernate.hql.ast.tree;
|
package org.hibernate.hql.ast.tree;
|
||||||
|
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.ArrayList;
|
||||||
|
|
||||||
import org.hibernate.sql.JoinFragment;
|
import org.hibernate.sql.JoinFragment;
|
||||||
|
import org.hibernate.param.ParameterSpecification;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Represents an SQL fragment in the AST.
|
* Represents an SQL fragment in the AST.
|
||||||
*
|
*
|
||||||
* @author josh Dec 5, 2004 9:01:52 AM
|
* @author josh
|
||||||
*/
|
*/
|
||||||
public class SqlFragment extends Node {
|
public class SqlFragment extends Node implements ParameterContainer {
|
||||||
private JoinFragment joinFragment;
|
private JoinFragment joinFragment;
|
||||||
private FromElement fromElement;
|
private FromElement fromElement;
|
||||||
|
|
||||||
|
@ -27,4 +54,23 @@ public class SqlFragment extends Node {
|
||||||
public FromElement getFromElement() {
|
public FromElement getFromElement() {
|
||||||
return fromElement;
|
return fromElement;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// ParameterContainer impl ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||||
|
private List embeddedParameters;
|
||||||
|
|
||||||
|
public void addEmbeddedParameter(ParameterSpecification specification) {
|
||||||
|
if ( embeddedParameters == null ) {
|
||||||
|
embeddedParameters = new ArrayList();
|
||||||
|
}
|
||||||
|
embeddedParameters.add( specification );
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean hasEmbeddedParameters() {
|
||||||
|
return embeddedParameters != null && ! embeddedParameters.isEmpty();
|
||||||
|
}
|
||||||
|
|
||||||
|
public ParameterSpecification[] getEmbeddedParameters() {
|
||||||
|
return ( ParameterSpecification[] ) embeddedParameters.toArray( new ParameterSpecification[ embeddedParameters.size() ] );
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -4,21 +4,28 @@ package org.hibernate.hql.ast.util;
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.Iterator;
|
import java.util.Iterator;
|
||||||
import java.util.ListIterator;
|
import java.util.ListIterator;
|
||||||
import java.util.Collections;
|
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
import java.util.StringTokenizer;
|
||||||
|
import java.util.Collection;
|
||||||
|
|
||||||
import org.hibernate.AssertionFailure;
|
import org.hibernate.AssertionFailure;
|
||||||
|
import org.hibernate.param.DynamicFilterParameterSpecification;
|
||||||
|
import org.hibernate.type.Type;
|
||||||
|
import org.hibernate.impl.FilterImpl;
|
||||||
|
import org.hibernate.dialect.Dialect;
|
||||||
import org.hibernate.engine.JoinSequence;
|
import org.hibernate.engine.JoinSequence;
|
||||||
|
import org.hibernate.engine.QueryParameters;
|
||||||
import org.hibernate.hql.antlr.SqlTokenTypes;
|
import org.hibernate.hql.antlr.SqlTokenTypes;
|
||||||
import org.hibernate.hql.ast.QueryTranslatorImpl;
|
import org.hibernate.hql.ast.HqlSqlWalker;
|
||||||
import org.hibernate.hql.ast.tree.FromClause;
|
import org.hibernate.hql.ast.tree.FromClause;
|
||||||
import org.hibernate.hql.ast.tree.FromElement;
|
import org.hibernate.hql.ast.tree.FromElement;
|
||||||
import org.hibernate.hql.ast.tree.QueryNode;
|
import org.hibernate.hql.ast.tree.QueryNode;
|
||||||
import org.hibernate.hql.ast.tree.DotNode;
|
import org.hibernate.hql.ast.tree.DotNode;
|
||||||
|
import org.hibernate.hql.ast.tree.ParameterContainer;
|
||||||
|
import org.hibernate.hql.classic.ParserHelper;
|
||||||
import org.hibernate.sql.JoinFragment;
|
import org.hibernate.sql.JoinFragment;
|
||||||
import org.hibernate.util.StringHelper;
|
import org.hibernate.util.StringHelper;
|
||||||
|
import org.hibernate.util.ArrayHelper;
|
||||||
import antlr.ASTFactory;
|
|
||||||
|
|
||||||
import org.apache.commons.logging.Log;
|
import org.apache.commons.logging.Log;
|
||||||
import org.apache.commons.logging.LogFactory;
|
import org.apache.commons.logging.LogFactory;
|
||||||
|
@ -34,18 +41,17 @@ public class JoinProcessor implements SqlTokenTypes {
|
||||||
|
|
||||||
private static final Log log = LogFactory.getLog( JoinProcessor.class );
|
private static final Log log = LogFactory.getLog( JoinProcessor.class );
|
||||||
|
|
||||||
private QueryTranslatorImpl queryTranslatorImpl;
|
private final HqlSqlWalker walker;
|
||||||
private SyntheticAndFactory andFactory;
|
private final SyntheticAndFactory syntheticAndFactory;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Constructs a new JoinProcessor.
|
* Constructs a new JoinProcessor.
|
||||||
*
|
*
|
||||||
* @param astFactory The factory for AST node creation.
|
* @param walker The walker to which we are bound, giving us access to needed resources.
|
||||||
* @param queryTranslatorImpl The query translator.
|
|
||||||
*/
|
*/
|
||||||
public JoinProcessor(ASTFactory astFactory, QueryTranslatorImpl queryTranslatorImpl) {
|
public JoinProcessor(HqlSqlWalker walker) {
|
||||||
this.andFactory = new SyntheticAndFactory( astFactory );
|
this.walker = walker;
|
||||||
this.queryTranslatorImpl = queryTranslatorImpl;
|
this.syntheticAndFactory = new SyntheticAndFactory( walker );
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -69,7 +75,7 @@ public class JoinProcessor implements SqlTokenTypes {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public void processJoins(QueryNode query, boolean inSubquery) {
|
public void processJoins(QueryNode query) {
|
||||||
final FromClause fromClause = query.getFromClause();
|
final FromClause fromClause = query.getFromClause();
|
||||||
|
|
||||||
final List fromElements;
|
final List fromElements;
|
||||||
|
@ -108,22 +114,21 @@ public class JoinProcessor implements SqlTokenTypes {
|
||||||
log.trace( "forcing inclusion of extra joins [alias=" + alias + ", containsTableAlias=" + containsTableAlias + "]" );
|
log.trace( "forcing inclusion of extra joins [alias=" + alias + ", containsTableAlias=" + containsTableAlias + "]" );
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
boolean shallowQuery = queryTranslatorImpl.isShallowQuery();
|
boolean shallowQuery = walker.isShallowQuery();
|
||||||
boolean includeSubclasses = fromElement.isIncludeSubclasses();
|
boolean includeSubclasses = fromElement.isIncludeSubclasses();
|
||||||
boolean subQuery = fromClause.isSubQuery();
|
boolean subQuery = fromClause.isSubQuery();
|
||||||
return includeSubclasses && containsTableAlias && !subQuery && !shallowQuery;
|
return includeSubclasses && containsTableAlias && !subQuery && !shallowQuery;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
);
|
);
|
||||||
addJoinNodes( query, join, fromElement, inSubquery );
|
addJoinNodes( query, join, fromElement );
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private void addJoinNodes(QueryNode query, JoinSequence join, FromElement fromElement, boolean inSubquery) {
|
private void addJoinNodes(QueryNode query, JoinSequence join, FromElement fromElement) {
|
||||||
// Generate FROM and WHERE fragments for the from element.
|
|
||||||
JoinFragment joinFragment = join.toJoinFragment(
|
JoinFragment joinFragment = join.toJoinFragment(
|
||||||
inSubquery ? Collections.EMPTY_MAP : queryTranslatorImpl.getEnabledFilters(),
|
walker.getEnabledFilters(),
|
||||||
fromElement.useFromFragment() || fromElement.isDereferencedBySuperclassOrSubclassProperty(),
|
fromElement.useFromFragment() || fromElement.isDereferencedBySuperclassOrSubclassProperty(),
|
||||||
fromElement.getWithClauseFragment(),
|
fromElement.getWithClauseFragment(),
|
||||||
fromElement.getWithClauseJoinAlias()
|
fromElement.getWithClauseJoinAlias()
|
||||||
|
@ -143,13 +148,24 @@ public class JoinProcessor implements SqlTokenTypes {
|
||||||
|
|
||||||
// If there is a FROM fragment and the FROM element is an explicit, then add the from part.
|
// If there is a FROM fragment and the FROM element is an explicit, then add the from part.
|
||||||
if ( fromElement.useFromFragment() /*&& StringHelper.isNotEmpty( frag )*/ ) {
|
if ( fromElement.useFromFragment() /*&& StringHelper.isNotEmpty( frag )*/ ) {
|
||||||
String fromFragment = processFromFragment( frag, join );
|
String fromFragment = processFromFragment( frag, join ).trim();
|
||||||
if ( log.isDebugEnabled() ) {
|
if ( log.isDebugEnabled() ) {
|
||||||
log.debug( "Using FROM fragment [" + fromFragment + "]" );
|
log.debug( "Using FROM fragment [" + fromFragment + "]" );
|
||||||
}
|
}
|
||||||
fromElement.setText( fromFragment.trim() ); // Set the text of the fromElement.
|
processDynamicFilterParameters(
|
||||||
|
fromFragment,
|
||||||
|
fromElement,
|
||||||
|
walker
|
||||||
|
);
|
||||||
}
|
}
|
||||||
andFactory.addWhereFragment( joinFragment, whereFrag, query, fromElement );
|
|
||||||
|
syntheticAndFactory.addWhereFragment(
|
||||||
|
joinFragment,
|
||||||
|
whereFrag,
|
||||||
|
query,
|
||||||
|
fromElement,
|
||||||
|
walker
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
private String processFromFragment(String frag, JoinSequence join) {
|
private String processFromFragment(String frag, JoinSequence join) {
|
||||||
|
@ -161,4 +177,56 @@ public class JoinProcessor implements SqlTokenTypes {
|
||||||
return fromFragment;
|
return fromFragment;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public static void processDynamicFilterParameters(
|
||||||
|
final String sqlFragment,
|
||||||
|
final ParameterContainer container,
|
||||||
|
final HqlSqlWalker walker) {
|
||||||
|
if ( walker.getEnabledFilters().isEmpty()
|
||||||
|
&& ( ! hasDynamicFilterParam( sqlFragment ) )
|
||||||
|
&& ( ! ( hasCollectionFilterParam( sqlFragment ) ) ) ) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
Dialect dialect = walker.getSessionFactoryHelper().getFactory().getDialect();
|
||||||
|
String symbols = new StringBuffer().append( ParserHelper.HQL_SEPARATORS )
|
||||||
|
.append( dialect.openQuote() )
|
||||||
|
.append( dialect.closeQuote() )
|
||||||
|
.toString();
|
||||||
|
StringTokenizer tokens = new StringTokenizer( sqlFragment, symbols, true );
|
||||||
|
StringBuffer result = new StringBuffer();
|
||||||
|
|
||||||
|
while ( tokens.hasMoreTokens() ) {
|
||||||
|
final String token = tokens.nextToken();
|
||||||
|
if ( token.startsWith( ParserHelper.HQL_VARIABLE_PREFIX ) ) {
|
||||||
|
final String filterParameterName = token.substring( 1 );
|
||||||
|
final String[] parts = QueryParameters.parseFilterParameterName( filterParameterName );
|
||||||
|
final FilterImpl filter = ( FilterImpl ) walker.getEnabledFilters().get( parts[0] );
|
||||||
|
final Object value = filter.getParameter( parts[1] );
|
||||||
|
final Type type = filter.getFilterDefinition().getParameterType( parts[1] );
|
||||||
|
final String typeBindFragment = StringHelper.join(
|
||||||
|
",",
|
||||||
|
ArrayHelper.fillArray( "?", type.getColumnSpan( walker.getSessionFactoryHelper().getFactory() ) )
|
||||||
|
);
|
||||||
|
final String bindFragment = ( value != null && Collection.class.isInstance( value ) )
|
||||||
|
? StringHelper.join( ",", ArrayHelper.fillArray( typeBindFragment, ( ( Collection ) value ).size() ) )
|
||||||
|
: typeBindFragment;
|
||||||
|
result.append( bindFragment );
|
||||||
|
container.addEmbeddedParameter( new DynamicFilterParameterSpecification( parts[0], parts[1], type ) );
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
result.append( token );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
container.setText( result.toString() );
|
||||||
|
}
|
||||||
|
|
||||||
|
private static boolean hasDynamicFilterParam(String sqlFragment) {
|
||||||
|
return sqlFragment.indexOf( ParserHelper.HQL_VARIABLE_PREFIX ) < 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
private static boolean hasCollectionFilterParam(String sqlFragment) {
|
||||||
|
return sqlFragment.indexOf( "?" ) < 0;
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -2,18 +2,20 @@
|
||||||
package org.hibernate.hql.ast.util;
|
package org.hibernate.hql.ast.util;
|
||||||
|
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
import java.util.StringTokenizer;
|
|
||||||
|
|
||||||
import org.hibernate.hql.antlr.HqlSqlTokenTypes;
|
import org.hibernate.hql.antlr.HqlSqlTokenTypes;
|
||||||
import org.hibernate.hql.ast.tree.FromElement;
|
import org.hibernate.hql.ast.tree.FromElement;
|
||||||
import org.hibernate.hql.ast.tree.QueryNode;
|
import org.hibernate.hql.ast.tree.QueryNode;
|
||||||
import org.hibernate.hql.ast.tree.RestrictableStatement;
|
import org.hibernate.hql.ast.tree.RestrictableStatement;
|
||||||
import org.hibernate.hql.ast.tree.SqlFragment;
|
import org.hibernate.hql.ast.tree.SqlFragment;
|
||||||
|
import org.hibernate.hql.ast.tree.Node;
|
||||||
|
import org.hibernate.hql.ast.HqlSqlWalker;
|
||||||
import org.hibernate.persister.entity.Queryable;
|
import org.hibernate.persister.entity.Queryable;
|
||||||
import org.hibernate.sql.JoinFragment;
|
import org.hibernate.sql.JoinFragment;
|
||||||
import org.hibernate.util.StringHelper;
|
import org.hibernate.util.StringHelper;
|
||||||
|
import org.hibernate.type.Type;
|
||||||
|
import org.hibernate.param.CollectionFilterKeyParameterSpecification;
|
||||||
|
|
||||||
import antlr.ASTFactory;
|
|
||||||
import antlr.collections.AST;
|
import antlr.collections.AST;
|
||||||
|
|
||||||
import org.apache.commons.logging.Log;
|
import org.apache.commons.logging.Log;
|
||||||
|
@ -27,27 +29,36 @@ import org.apache.commons.logging.LogFactory;
|
||||||
public class SyntheticAndFactory implements HqlSqlTokenTypes {
|
public class SyntheticAndFactory implements HqlSqlTokenTypes {
|
||||||
private static final Log log = LogFactory.getLog( SyntheticAndFactory.class );
|
private static final Log log = LogFactory.getLog( SyntheticAndFactory.class );
|
||||||
|
|
||||||
private ASTFactory astFactory;
|
private HqlSqlWalker hqlSqlWalker;
|
||||||
private AST thetaJoins;
|
private AST thetaJoins;
|
||||||
private AST filters;
|
private AST filters;
|
||||||
|
|
||||||
public SyntheticAndFactory(ASTFactory astFactory) {
|
public SyntheticAndFactory(HqlSqlWalker hqlSqlWalker) {
|
||||||
this.astFactory = astFactory;
|
this.hqlSqlWalker = hqlSqlWalker;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void addWhereFragment(JoinFragment joinFragment, String whereFragment, QueryNode query, FromElement fromElement) {
|
private Node create(int tokenType, String text) {
|
||||||
|
return ( Node ) ASTUtil.create( hqlSqlWalker.getASTFactory(), tokenType, text );
|
||||||
|
}
|
||||||
|
|
||||||
|
public void addWhereFragment(
|
||||||
|
JoinFragment joinFragment,
|
||||||
|
String whereFragment,
|
||||||
|
QueryNode query,
|
||||||
|
FromElement fromElement,
|
||||||
|
HqlSqlWalker hqlSqlWalker) {
|
||||||
if ( whereFragment == null ) {
|
if ( whereFragment == null ) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if ( !fromElement.useWhereFragment() && !joinFragment.hasThetaJoins() ) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
whereFragment = whereFragment.trim();
|
whereFragment = whereFragment.trim();
|
||||||
if ( StringHelper.isEmpty( whereFragment ) ) {
|
if ( StringHelper.isEmpty( whereFragment ) ) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
else if ( !fromElement.useWhereFragment() && !joinFragment.hasThetaJoins() ) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Forcefully remove leading ands from where fragments; the grammar will
|
// Forcefully remove leading ands from where fragments; the grammar will
|
||||||
// handle adding them
|
// handle adding them
|
||||||
|
@ -55,12 +66,36 @@ public class SyntheticAndFactory implements HqlSqlTokenTypes {
|
||||||
whereFragment = whereFragment.substring( 4 );
|
whereFragment = whereFragment.substring( 4 );
|
||||||
}
|
}
|
||||||
|
|
||||||
if ( log.isDebugEnabled() ) log.debug( "Using WHERE fragment [" + whereFragment + "]" );
|
if ( log.isDebugEnabled() ) {
|
||||||
|
log.debug( "Using unprocessed WHERE-fragment [" + whereFragment + "]");
|
||||||
|
}
|
||||||
|
|
||||||
SqlFragment fragment = ( SqlFragment ) ASTUtil.create( astFactory, SQL_TOKEN, whereFragment );
|
SqlFragment fragment = ( SqlFragment ) create( SQL_TOKEN, whereFragment );
|
||||||
fragment.setJoinFragment( joinFragment );
|
fragment.setJoinFragment( joinFragment );
|
||||||
fragment.setFromElement( fromElement );
|
fragment.setFromElement( fromElement );
|
||||||
|
|
||||||
|
if ( hqlSqlWalker.isFilter() ) {
|
||||||
|
if ( whereFragment.indexOf( '?' ) >= 0 ) {
|
||||||
|
Type collectionFilterKeyType = hqlSqlWalker.getSessionFactoryHelper()
|
||||||
|
.requireQueryableCollection( hqlSqlWalker.getCollectionFilterRole() )
|
||||||
|
.getKeyType();
|
||||||
|
CollectionFilterKeyParameterSpecification paramSpec = new CollectionFilterKeyParameterSpecification(
|
||||||
|
hqlSqlWalker.getCollectionFilterRole(),
|
||||||
|
collectionFilterKeyType,
|
||||||
|
0
|
||||||
|
);
|
||||||
|
fragment.addEmbeddedParameter( paramSpec );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
JoinProcessor.processDynamicFilterParameters(
|
||||||
|
whereFragment,
|
||||||
|
fragment,
|
||||||
|
hqlSqlWalker
|
||||||
|
);
|
||||||
|
|
||||||
|
log.debug( "Using processed WHERE-fragment [" + fragment.getText() + "]" );
|
||||||
|
|
||||||
// Filter conditions need to be inserted before the HQL where condition and the
|
// Filter conditions need to be inserted before the HQL where condition and the
|
||||||
// theta join node. This is because org.hibernate.loader.Loader binds the filter parameters first,
|
// theta join node. This is because org.hibernate.loader.Loader binds the filter parameters first,
|
||||||
// then it binds all the HQL query parameters, see org.hibernate.loader.Loader.processFilterParameters().
|
// then it binds all the HQL query parameters, see org.hibernate.loader.Loader.processFilterParameters().
|
||||||
|
@ -69,11 +104,11 @@ public class SyntheticAndFactory implements HqlSqlTokenTypes {
|
||||||
// Find or create the WHERE clause
|
// Find or create the WHERE clause
|
||||||
AST where = query.getWhereClause();
|
AST where = query.getWhereClause();
|
||||||
// Create a new FILTERS node as a parent of all filters
|
// Create a new FILTERS node as a parent of all filters
|
||||||
filters = astFactory.create( FILTERS, "{filter conditions}" );
|
filters = create( FILTERS, "{filter conditions}" );
|
||||||
// Put the FILTERS node before the HQL condition and theta joins
|
// Put the FILTERS node before the HQL condition and theta joins
|
||||||
ASTUtil.insertChild( where, filters );
|
ASTUtil.insertChild( where, filters );
|
||||||
}
|
}
|
||||||
|
|
||||||
// add the current fragment to the FILTERS node
|
// add the current fragment to the FILTERS node
|
||||||
filters.addChild( fragment );
|
filters.addChild( fragment );
|
||||||
}
|
}
|
||||||
|
@ -82,7 +117,7 @@ public class SyntheticAndFactory implements HqlSqlTokenTypes {
|
||||||
// Find or create the WHERE clause
|
// Find or create the WHERE clause
|
||||||
AST where = query.getWhereClause();
|
AST where = query.getWhereClause();
|
||||||
// Create a new THETA_JOINS node as a parent of all filters
|
// Create a new THETA_JOINS node as a parent of all filters
|
||||||
thetaJoins = astFactory.create( THETA_JOINS, "{theta joins}" );
|
thetaJoins = create( THETA_JOINS, "{theta joins}" );
|
||||||
// Put the THETA_JOINS node before the HQL condition, after the filters.
|
// Put the THETA_JOINS node before the HQL condition, after the filters.
|
||||||
if (filters==null) {
|
if (filters==null) {
|
||||||
ASTUtil.insertChild( where, thetaJoins );
|
ASTUtil.insertChild( where, thetaJoins );
|
||||||
|
@ -91,14 +126,18 @@ public class SyntheticAndFactory implements HqlSqlTokenTypes {
|
||||||
ASTUtil.insertSibling( thetaJoins, filters );
|
ASTUtil.insertSibling( thetaJoins, filters );
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// add the current fragment to the THETA_JOINS node
|
// add the current fragment to the THETA_JOINS node
|
||||||
thetaJoins.addChild(fragment);
|
thetaJoins.addChild(fragment);
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public void addDiscriminatorWhereFragment(RestrictableStatement statement, Queryable persister, Map enabledFilters, String alias) {
|
public void addDiscriminatorWhereFragment(
|
||||||
|
RestrictableStatement statement,
|
||||||
|
Queryable persister,
|
||||||
|
Map enabledFilters,
|
||||||
|
String alias) {
|
||||||
String whereFragment = persister.filterFragment( alias, enabledFilters ).trim();
|
String whereFragment = persister.filterFragment( alias, enabledFilters ).trim();
|
||||||
if ( "".equals( whereFragment ) ) {
|
if ( "".equals( whereFragment ) ) {
|
||||||
return;
|
return;
|
||||||
|
@ -118,13 +157,19 @@ public class SyntheticAndFactory implements HqlSqlTokenTypes {
|
||||||
// At some point we probably want to apply an additional grammar to
|
// At some point we probably want to apply an additional grammar to
|
||||||
// properly tokenize this where fragment into constituent parts
|
// properly tokenize this where fragment into constituent parts
|
||||||
// focused on the operators embedded within the fragment.
|
// focused on the operators embedded within the fragment.
|
||||||
AST discrimNode = astFactory.create( SQL_TOKEN, whereFragment );
|
SqlFragment discrimNode = ( SqlFragment ) create( SQL_TOKEN, whereFragment );
|
||||||
|
|
||||||
|
JoinProcessor.processDynamicFilterParameters(
|
||||||
|
whereFragment,
|
||||||
|
discrimNode,
|
||||||
|
hqlSqlWalker
|
||||||
|
);
|
||||||
|
|
||||||
if ( statement.getWhereClause().getNumberOfChildren() == 0 ) {
|
if ( statement.getWhereClause().getNumberOfChildren() == 0 ) {
|
||||||
statement.getWhereClause().setFirstChild( discrimNode );
|
statement.getWhereClause().setFirstChild( discrimNode );
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
AST and = astFactory.create( AND, "{and}" );
|
AST and = create( AND, "{and}" );
|
||||||
AST currentFirstChild = statement.getWhereClause().getFirstChild();
|
AST currentFirstChild = statement.getWhereClause().getFirstChild();
|
||||||
and.setFirstChild( discrimNode );
|
and.setFirstChild( discrimNode );
|
||||||
and.addChild( currentFirstChild );
|
and.addChild( currentFirstChild );
|
||||||
|
|
|
@ -483,8 +483,8 @@ public class QueryLoader extends BasicLoader {
|
||||||
final QueryParameters queryParameters,
|
final QueryParameters queryParameters,
|
||||||
final int startIndex,
|
final int startIndex,
|
||||||
final SessionImplementor session) throws SQLException {
|
final SessionImplementor session) throws SQLException {
|
||||||
int position = bindFilterParameterValues( statement, queryParameters, startIndex, session );
|
int position = startIndex;
|
||||||
List parameterSpecs = queryTranslator.getSqlAST().getWalker().getParameters();
|
List parameterSpecs = queryTranslator.getCollectedParameterSpecifications();
|
||||||
Iterator itr = parameterSpecs.iterator();
|
Iterator itr = parameterSpecs.iterator();
|
||||||
while ( itr.hasNext() ) {
|
while ( itr.hasNext() ) {
|
||||||
ParameterSpecification spec = ( ParameterSpecification ) itr.next();
|
ParameterSpecification spec = ( ParameterSpecification ) itr.next();
|
||||||
|
|
|
@ -8,13 +8,12 @@ import org.hibernate.engine.SessionImplementor;
|
||||||
import org.hibernate.type.Type;
|
import org.hibernate.type.Type;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* A specialized ParameterSpecification impl for dealing with a collection-key
|
* A specialized ParameterSpecification impl for dealing with a collection-key as part of a collection filter
|
||||||
* as part of a collection filter compilation.
|
* compilation.
|
||||||
*
|
*
|
||||||
* @author Steve Ebersole
|
* @author Steve Ebersole
|
||||||
*/
|
*/
|
||||||
public class CollectionFilterKeyParameterSpecification implements ParameterSpecification {
|
public class CollectionFilterKeyParameterSpecification implements ParameterSpecification {
|
||||||
|
|
||||||
private final String collectionRole;
|
private final String collectionRole;
|
||||||
private final Type keyType;
|
private final Type keyType;
|
||||||
private final int queryParameterPosition;
|
private final int queryParameterPosition;
|
||||||
|
@ -34,6 +33,9 @@ public class CollectionFilterKeyParameterSpecification implements ParameterSpeci
|
||||||
this.queryParameterPosition = queryParameterPosition;
|
this.queryParameterPosition = queryParameterPosition;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* {@inheritDoc}
|
||||||
|
*/
|
||||||
public int bind(
|
public int bind(
|
||||||
PreparedStatement statement,
|
PreparedStatement statement,
|
||||||
QueryParameters qp,
|
QueryParameters qp,
|
||||||
|
@ -44,14 +46,23 @@ public class CollectionFilterKeyParameterSpecification implements ParameterSpeci
|
||||||
return keyType.getColumnSpan( session.getFactory() );
|
return keyType.getColumnSpan( session.getFactory() );
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* {@inheritDoc}
|
||||||
|
*/
|
||||||
public Type getExpectedType() {
|
public Type getExpectedType() {
|
||||||
return keyType;
|
return keyType;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* {@inheritDoc}
|
||||||
|
*/
|
||||||
public void setExpectedType(Type expectedType) {
|
public void setExpectedType(Type expectedType) {
|
||||||
// todo : throw exception?
|
// todo : throw exception?
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* {@inheritDoc}
|
||||||
|
*/
|
||||||
public String renderDisplayInfo() {
|
public String renderDisplayInfo() {
|
||||||
return "collection-filter-key=" + collectionRole;
|
return "collection-filter-key=" + collectionRole;
|
||||||
}
|
}
|
||||||
|
|
|
@ -2,20 +2,17 @@ package org.hibernate.param;
|
||||||
|
|
||||||
import java.sql.PreparedStatement;
|
import java.sql.PreparedStatement;
|
||||||
import java.sql.SQLException;
|
import java.sql.SQLException;
|
||||||
|
import java.util.Collection;
|
||||||
|
import java.util.Iterator;
|
||||||
|
|
||||||
import org.hibernate.engine.QueryParameters;
|
import org.hibernate.engine.QueryParameters;
|
||||||
import org.hibernate.engine.SessionImplementor;
|
import org.hibernate.engine.SessionImplementor;
|
||||||
import org.hibernate.type.Type;
|
import org.hibernate.type.Type;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* A specialized ParameterSpecification impl for dealing with a dynamic filter
|
* A specialized ParameterSpecification impl for dealing with a dynamic filter parameters.
|
||||||
* parameters.
|
*
|
||||||
* <p/>
|
* @see org.hibernate.Session#enableFilter(String)
|
||||||
* Note: this class is currently not used. The ideal way to deal with dynamic filter
|
|
||||||
* parameters for HQL would be to track them just as we do with other parameters
|
|
||||||
* in the translator. However, the problem with that is that we currently do not
|
|
||||||
* know the filters which actually apply to the query; we know the active/enabled ones,
|
|
||||||
* but not the ones that actually "make it into" the resulting query.
|
|
||||||
*
|
*
|
||||||
* @author Steve Ebersole
|
* @author Steve Ebersole
|
||||||
*/
|
*/
|
||||||
|
@ -23,37 +20,65 @@ public class DynamicFilterParameterSpecification implements ParameterSpecificati
|
||||||
private final String filterName;
|
private final String filterName;
|
||||||
private final String parameterName;
|
private final String parameterName;
|
||||||
private final Type definedParameterType;
|
private final Type definedParameterType;
|
||||||
private final int queryParameterPosition;
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Constructs a parameter specification for a particular filter parameter.
|
||||||
|
*
|
||||||
|
* @param filterName The name of the filter
|
||||||
|
* @param parameterName The name of the parameter
|
||||||
|
* @param definedParameterType The paremeter type specified on the filter metadata
|
||||||
|
*/
|
||||||
public DynamicFilterParameterSpecification(
|
public DynamicFilterParameterSpecification(
|
||||||
String filterName,
|
String filterName,
|
||||||
String parameterName,
|
String parameterName,
|
||||||
Type definedParameterType,
|
Type definedParameterType) {
|
||||||
int queryParameterPosition) {
|
|
||||||
this.filterName = filterName;
|
this.filterName = filterName;
|
||||||
this.parameterName = parameterName;
|
this.parameterName = parameterName;
|
||||||
this.definedParameterType = definedParameterType;
|
this.definedParameterType = definedParameterType;
|
||||||
this.queryParameterPosition = queryParameterPosition;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* {@inheritDoc}
|
||||||
|
*/
|
||||||
public int bind(
|
public int bind(
|
||||||
PreparedStatement statement,
|
PreparedStatement statement,
|
||||||
QueryParameters qp,
|
QueryParameters qp,
|
||||||
SessionImplementor session,
|
SessionImplementor session,
|
||||||
int position) throws SQLException {
|
int start) throws SQLException {
|
||||||
Object value = qp.getFilteredPositionalParameterValues()[queryParameterPosition];
|
final int columnSpan = definedParameterType.getColumnSpan( session.getFactory() );
|
||||||
definedParameterType.nullSafeSet( statement, value, position, session );
|
final Object value = session.getFilterParameterValue( filterName + '.' + parameterName );
|
||||||
return definedParameterType.getColumnSpan( session.getFactory() );
|
if ( Collection.class.isInstance( value ) ) {
|
||||||
|
int positions = 0;
|
||||||
|
Iterator itr = ( ( Collection ) value ).iterator();
|
||||||
|
while ( itr.hasNext() ) {
|
||||||
|
definedParameterType.nullSafeSet( statement, itr.next(), start + positions, session );
|
||||||
|
positions += columnSpan;
|
||||||
|
}
|
||||||
|
return positions;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
definedParameterType.nullSafeSet( statement, value, start, session );
|
||||||
|
return columnSpan;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* {@inheritDoc}
|
||||||
|
*/
|
||||||
public Type getExpectedType() {
|
public Type getExpectedType() {
|
||||||
return definedParameterType;
|
return definedParameterType;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* {@inheritDoc}
|
||||||
|
*/
|
||||||
public void setExpectedType(Type expectedType) {
|
public void setExpectedType(Type expectedType) {
|
||||||
// todo : throw exception?
|
// todo : throw exception? maybe warn if not the same?
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* {@inheritDoc}
|
||||||
|
*/
|
||||||
public String renderDisplayInfo() {
|
public String renderDisplayInfo() {
|
||||||
return "dynamic-filter={filterName=" + filterName + ",paramName=" + parameterName + "}";
|
return "dynamic-filter={filterName=" + filterName + ",paramName=" + parameterName + "}";
|
||||||
}
|
}
|
||||||
|
|
|
@ -9,14 +9,20 @@ import java.sql.PreparedStatement;
|
||||||
import java.sql.SQLException;
|
import java.sql.SQLException;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Relates to an explicit query named-parameter.
|
* Parameter bind specification for an explicit named parameter.
|
||||||
*
|
*
|
||||||
* @author Steve Ebersole
|
* @author Steve Ebersole
|
||||||
*/
|
*/
|
||||||
public class NamedParameterSpecification extends AbstractExplicitParameterSpecification implements ParameterSpecification {
|
public class NamedParameterSpecification extends AbstractExplicitParameterSpecification implements ParameterSpecification {
|
||||||
|
|
||||||
private final String name;
|
private final String name;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Constructs a named parameter bind specification.
|
||||||
|
*
|
||||||
|
* @param sourceLine See {@link #getSourceLine()}
|
||||||
|
* @param sourceColumn See {@link #getSourceColumn()}
|
||||||
|
* @param name The named parameter name.
|
||||||
|
*/
|
||||||
public NamedParameterSpecification(int sourceLine, int sourceColumn, String name) {
|
public NamedParameterSpecification(int sourceLine, int sourceColumn, String name) {
|
||||||
super( sourceLine, sourceColumn );
|
super( sourceLine, sourceColumn );
|
||||||
this.name = name;
|
this.name = name;
|
||||||
|
@ -39,10 +45,18 @@ public class NamedParameterSpecification extends AbstractExplicitParameterSpecif
|
||||||
return typedValue.getType().getColumnSpan( session.getFactory() );
|
return typedValue.getType().getColumnSpan( session.getFactory() );
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* {@inheritDoc}
|
||||||
|
*/
|
||||||
public String renderDisplayInfo() {
|
public String renderDisplayInfo() {
|
||||||
return "name=" + name + ", expectedType=" + getExpectedType();
|
return "name=" + name + ", expectedType=" + getExpectedType();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Getter for property 'name'.
|
||||||
|
*
|
||||||
|
* @return Value for property 'name'.
|
||||||
|
*/
|
||||||
public String getName() {
|
public String getName() {
|
||||||
return name;
|
return name;
|
||||||
}
|
}
|
||||||
|
|
|
@ -9,14 +9,20 @@ import java.sql.PreparedStatement;
|
||||||
import java.sql.SQLException;
|
import java.sql.SQLException;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Relates to an explicit query positional (or ordinal) parameter.
|
* Parameter bind specification for an explicit positional (or ordinal) parameter.
|
||||||
*
|
*
|
||||||
* @author Steve Ebersole
|
* @author Steve Ebersole
|
||||||
*/
|
*/
|
||||||
public class PositionalParameterSpecification extends AbstractExplicitParameterSpecification implements ParameterSpecification {
|
public class PositionalParameterSpecification extends AbstractExplicitParameterSpecification implements ParameterSpecification {
|
||||||
|
|
||||||
private final int hqlPosition;
|
private final int hqlPosition;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Constructs a position/ordinal parameter bind specification.
|
||||||
|
*
|
||||||
|
* @param sourceLine See {@link #getSourceLine()}
|
||||||
|
* @param sourceColumn See {@link #getSourceColumn()}
|
||||||
|
* @param hqlPosition The position in the source query, relative to the other source positional parameters.
|
||||||
|
*/
|
||||||
public PositionalParameterSpecification(int sourceLine, int sourceColumn, int hqlPosition) {
|
public PositionalParameterSpecification(int sourceLine, int sourceColumn, int hqlPosition) {
|
||||||
super( sourceLine, sourceColumn );
|
super( sourceLine, sourceColumn );
|
||||||
this.hqlPosition = hqlPosition;
|
this.hqlPosition = hqlPosition;
|
||||||
|
@ -40,10 +46,18 @@ public class PositionalParameterSpecification extends AbstractExplicitParameterS
|
||||||
return type.getColumnSpan( session.getFactory() );
|
return type.getColumnSpan( session.getFactory() );
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* {@inheritDoc}
|
||||||
|
*/
|
||||||
public String renderDisplayInfo() {
|
public String renderDisplayInfo() {
|
||||||
return "ordinal=" + hqlPosition + ", expectedType=" + getExpectedType();
|
return "ordinal=" + hqlPosition + ", expectedType=" + getExpectedType();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Getter for property 'hqlPosition'.
|
||||||
|
*
|
||||||
|
* @return Value for property 'hqlPosition'.
|
||||||
|
*/
|
||||||
public int getHqlPosition() {
|
public int getHqlPosition() {
|
||||||
return hqlPosition;
|
return hqlPosition;
|
||||||
}
|
}
|
||||||
|
|
|
@ -11,20 +11,24 @@ import java.sql.PreparedStatement;
|
||||||
import java.sql.SQLException;
|
import java.sql.SQLException;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Implementation of VersionTypeSeedParameterSpecification.
|
* Parameter bind specification used for optimisitc lock version seeding (from insert statements).
|
||||||
*
|
*
|
||||||
* @author Steve Ebersole
|
* @author Steve Ebersole
|
||||||
*/
|
*/
|
||||||
public class VersionTypeSeedParameterSpecification implements ParameterSpecification {
|
public class VersionTypeSeedParameterSpecification implements ParameterSpecification {
|
||||||
|
|
||||||
private VersionType type;
|
private VersionType type;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Constructs a version seed parameter bind specification.
|
||||||
|
*
|
||||||
|
* @param type The version type.
|
||||||
|
*/
|
||||||
public VersionTypeSeedParameterSpecification(VersionType type) {
|
public VersionTypeSeedParameterSpecification(VersionType type) {
|
||||||
this.type = type;
|
this.type = type;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @see org.hibernate.param.ParameterSpecification#bind
|
* {@inheritDoc}
|
||||||
*/
|
*/
|
||||||
public int bind(PreparedStatement statement, QueryParameters qp, SessionImplementor session, int position)
|
public int bind(PreparedStatement statement, QueryParameters qp, SessionImplementor session, int position)
|
||||||
throws SQLException {
|
throws SQLException {
|
||||||
|
@ -32,14 +36,23 @@ public class VersionTypeSeedParameterSpecification implements ParameterSpecifica
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* {@inheritDoc}
|
||||||
|
*/
|
||||||
public Type getExpectedType() {
|
public Type getExpectedType() {
|
||||||
return type;
|
return type;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* {@inheritDoc}
|
||||||
|
*/
|
||||||
public void setExpectedType(Type expectedType) {
|
public void setExpectedType(Type expectedType) {
|
||||||
// expected type is intrinsic here...
|
// expected type is intrinsic here...
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* {@inheritDoc}
|
||||||
|
*/
|
||||||
public String renderDisplayInfo() {
|
public String renderDisplayInfo() {
|
||||||
return "version-seed, type=" + type;
|
return "version-seed, type=" + type;
|
||||||
}
|
}
|
||||||
|
|
|
@ -10,26 +10,26 @@ import java.util.List;
|
||||||
import java.util.Set;
|
import java.util.Set;
|
||||||
|
|
||||||
import junit.framework.Test;
|
import junit.framework.Test;
|
||||||
import junit.framework.TestSuite;
|
|
||||||
|
|
||||||
import org.apache.commons.logging.Log;
|
|
||||||
import org.apache.commons.logging.LogFactory;
|
|
||||||
import org.hibernate.EntityMode;
|
import org.hibernate.EntityMode;
|
||||||
import org.hibernate.FetchMode;
|
import org.hibernate.FetchMode;
|
||||||
import org.hibernate.Hibernate;
|
import org.hibernate.Hibernate;
|
||||||
import org.hibernate.Session;
|
import org.hibernate.Session;
|
||||||
import org.hibernate.Transaction;
|
import org.hibernate.Transaction;
|
||||||
import org.hibernate.junit.functional.FunctionalTestCase;
|
import org.hibernate.Criteria;
|
||||||
import org.hibernate.junit.functional.FunctionalTestClassTestSuite;
|
import org.hibernate.impl.SessionFactoryImpl;
|
||||||
|
import org.hibernate.engine.SessionImplementor;
|
||||||
import org.hibernate.cache.CacheKey;
|
import org.hibernate.cache.CacheKey;
|
||||||
import org.hibernate.cache.entry.CollectionCacheEntry;
|
import org.hibernate.cache.entry.CollectionCacheEntry;
|
||||||
import org.hibernate.cfg.Configuration;
|
import org.hibernate.cfg.Configuration;
|
||||||
import org.hibernate.cfg.Environment;
|
import org.hibernate.cfg.Environment;
|
||||||
import org.hibernate.criterion.Expression;
|
import org.hibernate.criterion.Restrictions;
|
||||||
import org.hibernate.engine.SessionFactoryImplementor;
|
import org.hibernate.criterion.DetachedCriteria;
|
||||||
import org.hibernate.impl.SessionFactoryImpl;
|
import org.hibernate.criterion.Property;
|
||||||
|
import org.hibernate.criterion.Subqueries;
|
||||||
|
import org.hibernate.junit.functional.FunctionalTestCase;
|
||||||
|
import org.hibernate.junit.functional.FunctionalTestClassTestSuite;
|
||||||
import org.hibernate.persister.collection.CollectionPersister;
|
import org.hibernate.persister.collection.CollectionPersister;
|
||||||
import org.hibernate.test.TestCase;
|
|
||||||
import org.hibernate.transform.DistinctRootEntityResultTransformer;
|
import org.hibernate.transform.DistinctRootEntityResultTransformer;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -39,8 +39,6 @@ import org.hibernate.transform.DistinctRootEntityResultTransformer;
|
||||||
*/
|
*/
|
||||||
public class DynamicFilterTest extends FunctionalTestCase {
|
public class DynamicFilterTest extends FunctionalTestCase {
|
||||||
|
|
||||||
private Log log = LogFactory.getLog( DynamicFilterTest.class );
|
|
||||||
|
|
||||||
public DynamicFilterTest(String testName) {
|
public DynamicFilterTest(String testName) {
|
||||||
super( testName );
|
super( testName );
|
||||||
}
|
}
|
||||||
|
@ -79,6 +77,7 @@ public class DynamicFilterTest extends FunctionalTestCase {
|
||||||
testData.prepare();
|
testData.prepare();
|
||||||
|
|
||||||
Session session = openSession();
|
Session session = openSession();
|
||||||
|
long ts = ( ( SessionImplementor ) session ).getTimestamp();
|
||||||
|
|
||||||
// Force a collection into the second level cache, with its non-filtered elements
|
// Force a collection into the second level cache, with its non-filtered elements
|
||||||
Salesperson sp = ( Salesperson ) session.load( Salesperson.class, testData.steveId );
|
Salesperson sp = ( Salesperson ) session.load( Salesperson.class, testData.steveId );
|
||||||
|
@ -93,6 +92,7 @@ public class DynamicFilterTest extends FunctionalTestCase {
|
||||||
session.close();
|
session.close();
|
||||||
|
|
||||||
session = openSession();
|
session = openSession();
|
||||||
|
ts = ( ( SessionImplementor ) session ).getTimestamp();
|
||||||
session.enableFilter( "fulfilledOrders" ).setParameter( "asOfDate", testData.lastMonth.getTime() );
|
session.enableFilter( "fulfilledOrders" ).setParameter( "asOfDate", testData.lastMonth.getTime() );
|
||||||
sp = ( Salesperson ) session.createQuery( "from Salesperson as s where s.id = :id" )
|
sp = ( Salesperson ) session.createQuery( "from Salesperson as s where s.id = :id" )
|
||||||
.setLong( "id", testData.steveId.longValue() )
|
.setLong( "id", testData.steveId.longValue() )
|
||||||
|
@ -152,7 +152,6 @@ public class DynamicFilterTest extends FunctionalTestCase {
|
||||||
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||||
// HQL test
|
// HQL test
|
||||||
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||||
log.info( "Starting HQL filter tests" );
|
|
||||||
TestData testData = new TestData();
|
TestData testData = new TestData();
|
||||||
testData.prepare();
|
testData.prepare();
|
||||||
|
|
||||||
|
@ -162,13 +161,11 @@ public class DynamicFilterTest extends FunctionalTestCase {
|
||||||
session.enableFilter( "effectiveDate" )
|
session.enableFilter( "effectiveDate" )
|
||||||
.setParameter( "asOfDate", testData.lastMonth.getTime() );
|
.setParameter( "asOfDate", testData.lastMonth.getTime() );
|
||||||
|
|
||||||
log.info( "HQL against Salesperson..." );
|
|
||||||
List results = session.createQuery( "select s from Salesperson as s left join fetch s.orders" ).list();
|
List results = session.createQuery( "select s from Salesperson as s left join fetch s.orders" ).list();
|
||||||
assertTrue( "Incorrect filtered HQL result count [" + results.size() + "]", results.size() == 1 );
|
assertTrue( "Incorrect filtered HQL result count [" + results.size() + "]", results.size() == 1 );
|
||||||
Salesperson result = ( Salesperson ) results.get( 0 );
|
Salesperson result = ( Salesperson ) results.get( 0 );
|
||||||
assertTrue( "Incorrect collectionfilter count", result.getOrders().size() == 1 );
|
assertTrue( "Incorrect collectionfilter count", result.getOrders().size() == 1 );
|
||||||
|
|
||||||
log.info( "HQL against Product..." );
|
|
||||||
results = session.createQuery( "from Product as p where p.stockNumber = ?" ).setInteger( 0, 124 ).list();
|
results = session.createQuery( "from Product as p where p.stockNumber = ?" ).setInteger( 0, 124 ).list();
|
||||||
assertTrue( results.size() == 1 );
|
assertTrue( results.size() == 1 );
|
||||||
|
|
||||||
|
@ -180,7 +177,6 @@ public class DynamicFilterTest extends FunctionalTestCase {
|
||||||
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||||
// Criteria-query test
|
// Criteria-query test
|
||||||
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||||
log.info( "Starting Criteria-query filter tests" );
|
|
||||||
TestData testData = new TestData();
|
TestData testData = new TestData();
|
||||||
testData.prepare();
|
testData.prepare();
|
||||||
|
|
||||||
|
@ -193,16 +189,14 @@ public class DynamicFilterTest extends FunctionalTestCase {
|
||||||
session.enableFilter( "effectiveDate" )
|
session.enableFilter( "effectiveDate" )
|
||||||
.setParameter( "asOfDate", testData.lastMonth.getTime() );
|
.setParameter( "asOfDate", testData.lastMonth.getTime() );
|
||||||
|
|
||||||
log.info( "Criteria query against Salesperson..." );
|
|
||||||
List salespersons = session.createCriteria( Salesperson.class )
|
List salespersons = session.createCriteria( Salesperson.class )
|
||||||
.setFetchMode( "orders", FetchMode.JOIN )
|
.setFetchMode( "orders", FetchMode.JOIN )
|
||||||
.list();
|
.list();
|
||||||
assertEquals( "Incorrect salesperson count", 1, salespersons.size() );
|
assertEquals( "Incorrect salesperson count", 1, salespersons.size() );
|
||||||
assertEquals( "Incorrect order count", 1, ( ( Salesperson ) salespersons.get( 0 ) ).getOrders().size() );
|
assertEquals( "Incorrect order count", 1, ( ( Salesperson ) salespersons.get( 0 ) ).getOrders().size() );
|
||||||
|
|
||||||
log.info( "Criteria query against Product..." );
|
|
||||||
List products = session.createCriteria( Product.class )
|
List products = session.createCriteria( Product.class )
|
||||||
.add( Expression.eq( "stockNumber", new Integer( 124 ) ) )
|
.add( Restrictions.eq( "stockNumber", new Integer( 124 ) ) )
|
||||||
.list();
|
.list();
|
||||||
assertEquals( "Incorrect product count", 1, products.size() );
|
assertEquals( "Incorrect product count", 1, products.size() );
|
||||||
|
|
||||||
|
@ -210,18 +204,292 @@ public class DynamicFilterTest extends FunctionalTestCase {
|
||||||
testData.release();
|
testData.release();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public void testCriteriaControl() {
|
||||||
|
TestData testData = new TestData();
|
||||||
|
testData.prepare();
|
||||||
|
|
||||||
|
// the subquery...
|
||||||
|
DetachedCriteria subquery = DetachedCriteria.forClass( Salesperson.class )
|
||||||
|
.setProjection( Property.forName( "name" ) );
|
||||||
|
|
||||||
|
Session session = openSession();
|
||||||
|
session.beginTransaction();
|
||||||
|
session.enableFilter( "fulfilledOrders" ).setParameter( "asOfDate", testData.lastMonth.getTime() );
|
||||||
|
session.enableFilter( "regionlist" ).setParameterList( "regions", new String[] { "APAC" } );
|
||||||
|
|
||||||
|
List result = session.createCriteria( Order.class )
|
||||||
|
.add( Subqueries.in( "steve", subquery ) )
|
||||||
|
.list();
|
||||||
|
assertEquals( 1, result.size() );
|
||||||
|
|
||||||
|
session.getTransaction().commit();
|
||||||
|
session.close();
|
||||||
|
|
||||||
|
testData.release();
|
||||||
|
}
|
||||||
|
|
||||||
|
public void testCriteriaSubqueryWithFilters() {
|
||||||
|
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||||
|
// Criteria-subquery test
|
||||||
|
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||||
|
TestData testData = new TestData();
|
||||||
|
testData.prepare();
|
||||||
|
|
||||||
|
Session session = openSession();
|
||||||
|
session.enableFilter("region").setParameter("region", "APAC");
|
||||||
|
|
||||||
|
DetachedCriteria salespersonSubquery = DetachedCriteria.forClass(Salesperson.class)
|
||||||
|
.add(Restrictions.eq("name", "steve"))
|
||||||
|
.setProjection(Property.forName("department"));
|
||||||
|
|
||||||
|
Criteria departmentsQuery = session.createCriteria(Department.class).add(Subqueries.propertyIn("id", salespersonSubquery));
|
||||||
|
List departments = departmentsQuery.list();
|
||||||
|
|
||||||
|
assertEquals("Incorrect department count", 1, departments.size());
|
||||||
|
|
||||||
|
session.enableFilter("region").setParameter("region", "Foobar");
|
||||||
|
departments = departmentsQuery.list();
|
||||||
|
|
||||||
|
assertEquals("Incorrect department count", 0, departments.size());
|
||||||
|
|
||||||
|
session.enableFilter("region").setParameter("region", "APAC");
|
||||||
|
|
||||||
|
DetachedCriteria lineItemSubquery = DetachedCriteria.forClass(LineItem.class)
|
||||||
|
.add(Restrictions.ge("quantity", 1L))
|
||||||
|
.createCriteria("product")
|
||||||
|
.add(Restrictions.eq("name", "Acme Hair Gel"))
|
||||||
|
.setProjection(Property.forName("id"));
|
||||||
|
|
||||||
|
List orders = session.createCriteria(Order.class)
|
||||||
|
.add(Subqueries.exists(lineItemSubquery))
|
||||||
|
.add(Restrictions.eq("buyer", "gavin"))
|
||||||
|
.list();
|
||||||
|
|
||||||
|
assertEquals("Incorrect orders count", 1, orders.size());
|
||||||
|
|
||||||
|
session.enableFilter("region").setParameter("region", "APAC");
|
||||||
|
session.enableFilter("effectiveDate").setParameter("asOfDate", testData.lastMonth.getTime());
|
||||||
|
|
||||||
|
DetachedCriteria productSubquery = DetachedCriteria.forClass(Product.class)
|
||||||
|
.add(Restrictions.eq("name", "Acme Hair Gel"))
|
||||||
|
.setProjection(Property.forName("id"));
|
||||||
|
|
||||||
|
lineItemSubquery = DetachedCriteria.forClass(LineItem.class)
|
||||||
|
.add(Restrictions.ge("quantity", 1L))
|
||||||
|
.createCriteria("product")
|
||||||
|
.add(Subqueries.propertyIn("id", productSubquery))
|
||||||
|
.setProjection(Property.forName("id"));
|
||||||
|
|
||||||
|
orders = session.createCriteria(Order.class)
|
||||||
|
.add(Subqueries.exists(lineItemSubquery))
|
||||||
|
.add(Restrictions.eq("buyer", "gavin"))
|
||||||
|
.list();
|
||||||
|
|
||||||
|
assertEquals("Incorrect orders count", 1, orders.size());
|
||||||
|
|
||||||
|
session.enableFilter("region").setParameter("region", "APAC");
|
||||||
|
session.enableFilter("effectiveDate").setParameter("asOfDate", testData.fourMonthsAgo.getTime());
|
||||||
|
|
||||||
|
orders = session.createCriteria(Order.class)
|
||||||
|
.add(Subqueries.exists(lineItemSubquery))
|
||||||
|
.add(Restrictions.eq("buyer", "gavin"))
|
||||||
|
.list();
|
||||||
|
|
||||||
|
assertEquals("Incorrect orders count", 0, orders.size());
|
||||||
|
|
||||||
|
session.close();
|
||||||
|
testData.release();
|
||||||
|
}
|
||||||
|
|
||||||
|
public void testHQLSubqueryWithFilters() {
|
||||||
|
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||||
|
// HQL subquery with filters test
|
||||||
|
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||||
|
TestData testData = new TestData();
|
||||||
|
testData.prepare();
|
||||||
|
|
||||||
|
Session session = openSession();
|
||||||
|
session.enableFilter("region").setParameter("region", "APAC");
|
||||||
|
|
||||||
|
List departments = session.createQuery("select d from Department as d where d.id in (select s.department from Salesperson s where s.name = ?)").setString(0, "steve").list();
|
||||||
|
|
||||||
|
assertEquals("Incorrect department count", 1, departments.size());
|
||||||
|
|
||||||
|
session.enableFilter("region").setParameter("region", "Foobar");
|
||||||
|
departments = session.createQuery("select d from Department as d where d.id in (select s.department from Salesperson s where s.name = ?)").setString(0, "steve").list();
|
||||||
|
|
||||||
|
assertEquals("Incorrect department count", 0, departments.size());
|
||||||
|
|
||||||
|
session.enableFilter("region").setParameter("region", "APAC");
|
||||||
|
|
||||||
|
List orders = session.createQuery("select o from Order as o where exists (select li.id from LineItem li, Product as p where p.id = li.product and li.quantity >= ? and p.name = ?) and o.buyer = ?")
|
||||||
|
.setLong(0, 1L).setString(1, "Acme Hair Gel").setString(2, "gavin").list();
|
||||||
|
|
||||||
|
assertEquals("Incorrect orders count", 1, orders.size());
|
||||||
|
|
||||||
|
session.enableFilter("region").setParameter("region", "APAC");
|
||||||
|
session.enableFilter("effectiveDate").setParameter("asOfDate", testData.lastMonth.getTime());
|
||||||
|
|
||||||
|
orders = session.createQuery("select o from Order as o where exists (select li.id from LineItem li where li.quantity >= ? and li.product in (select p.id from Product p where p.name = ?)) and o.buyer = ?")
|
||||||
|
.setLong(0, 1L).setString(1, "Acme Hair Gel").setString(2, "gavin").list();
|
||||||
|
|
||||||
|
assertEquals("Incorrect orders count", 1, orders.size());
|
||||||
|
|
||||||
|
session.enableFilter("region").setParameter("region", "APAC");
|
||||||
|
session.enableFilter("effectiveDate").setParameter("asOfDate", testData.fourMonthsAgo.getTime());
|
||||||
|
|
||||||
|
orders = session.createQuery("select o from Order as o where exists (select li.id from LineItem li where li.quantity >= ? and li.product in (select p.id from Product p where p.name = ?)) and o.buyer = ?")
|
||||||
|
.setLong(0, 1L).setString(1, "Acme Hair Gel").setString(2, "gavin").list();
|
||||||
|
|
||||||
|
assertEquals("Incorrect orders count", 0, orders.size());
|
||||||
|
|
||||||
|
session.enableFilter("region").setParameter("region", "APAC");
|
||||||
|
session.enableFilter("effectiveDate").setParameter("asOfDate", testData.lastMonth.getTime());
|
||||||
|
|
||||||
|
orders = session.createQuery("select o from Order as o where exists (select li.id from LineItem li where li.quantity >= :quantity and li.product in (select p.id from Product p where p.name = :name)) and o.buyer = :buyer")
|
||||||
|
.setLong("quantity", 1L).setString("name", "Acme Hair Gel").setString("buyer", "gavin").list();
|
||||||
|
|
||||||
|
assertEquals("Incorrect orders count", 1, orders.size());
|
||||||
|
|
||||||
|
session.enableFilter("region").setParameter("region", "APAC");
|
||||||
|
session.enableFilter("effectiveDate").setParameter("asOfDate", testData.lastMonth.getTime());
|
||||||
|
|
||||||
|
orders = session.createQuery("select o from Order as o where exists (select li.id from LineItem li where li.quantity >= ? and li.product in (select p.id from Product p where p.name = ?)) and o.buyer = :buyer")
|
||||||
|
.setLong(0, 1L).setString(1, "Acme Hair Gel").setString("buyer", "gavin").list();
|
||||||
|
|
||||||
|
assertEquals("Incorrect orders count", 1, orders.size());
|
||||||
|
|
||||||
|
session.close();
|
||||||
|
testData.release();
|
||||||
|
}
|
||||||
|
|
||||||
|
public void testFilterApplicationOnHqlQueryWithImplicitSubqueryContainingPositionalParameter() {
|
||||||
|
TestData testData = new TestData();
|
||||||
|
testData.prepare();
|
||||||
|
|
||||||
|
Session session = openSession();
|
||||||
|
session.beginTransaction();
|
||||||
|
|
||||||
|
final String queryString = "from Order o where ? in ( select sp.name from Salesperson sp )";
|
||||||
|
|
||||||
|
// first a control-group query
|
||||||
|
List result = session.createQuery( queryString ).setParameter( 0, "steve" ).list();
|
||||||
|
assertEquals( 2, result.size() );
|
||||||
|
|
||||||
|
// now lets enable filters on Order...
|
||||||
|
session.enableFilter( "fulfilledOrders" ).setParameter( "asOfDate", testData.lastMonth.getTime() );
|
||||||
|
result = session.createQuery( queryString ).setParameter( 0, "steve" ).list();
|
||||||
|
assertEquals( 1, result.size() );
|
||||||
|
|
||||||
|
// now, lets additionally enable filter on Salesperson. First a valid one...
|
||||||
|
session.enableFilter( "regionlist" ).setParameterList( "regions", new String[] { "APAC" } );
|
||||||
|
result = session.createQuery( queryString ).setParameter( 0, "steve" ).list();
|
||||||
|
assertEquals( 1, result.size() );
|
||||||
|
|
||||||
|
// ... then a silly one...
|
||||||
|
session.enableFilter( "regionlist" ).setParameterList( "regions", new String[] { "gamma quadrant" } );
|
||||||
|
result = session.createQuery( queryString ).setParameter( 0, "steve" ).list();
|
||||||
|
assertEquals( 0, result.size() );
|
||||||
|
|
||||||
|
session.getTransaction().commit();
|
||||||
|
session.close();
|
||||||
|
|
||||||
|
testData.release();
|
||||||
|
}
|
||||||
|
|
||||||
|
public void testFilterApplicationOnHqlQueryWithImplicitSubqueryContainingNamedParameter() {
|
||||||
|
TestData testData = new TestData();
|
||||||
|
testData.prepare();
|
||||||
|
|
||||||
|
Session session = openSession();
|
||||||
|
session.beginTransaction();
|
||||||
|
|
||||||
|
final String queryString = "from Order o where :salesPersonName in ( select sp.name from Salesperson sp )";
|
||||||
|
|
||||||
|
// first a control-group query
|
||||||
|
List result = session.createQuery( queryString ).setParameter( "salesPersonName", "steve" ).list();
|
||||||
|
assertEquals( 2, result.size() );
|
||||||
|
|
||||||
|
// now lets enable filters on Order...
|
||||||
|
session.enableFilter( "fulfilledOrders" ).setParameter( "asOfDate", testData.lastMonth.getTime() );
|
||||||
|
result = session.createQuery( queryString ).setParameter( "salesPersonName", "steve" ).list();
|
||||||
|
assertEquals( 1, result.size() );
|
||||||
|
|
||||||
|
// now, lets additionally enable filter on Salesperson. First a valid one...
|
||||||
|
session.enableFilter( "regionlist" ).setParameterList( "regions", new String[] { "APAC" } );
|
||||||
|
result = session.createQuery( queryString ).setParameter( "salesPersonName", "steve" ).list();
|
||||||
|
assertEquals( 1, result.size() );
|
||||||
|
|
||||||
|
// ... then a silly one...
|
||||||
|
session.enableFilter( "regionlist" ).setParameterList( "regions", new String[] { "gamma quadrant" } );
|
||||||
|
result = session.createQuery( queryString ).setParameter( "salesPersonName", "steve" ).list();
|
||||||
|
assertEquals( 0, result.size() );
|
||||||
|
|
||||||
|
session.getTransaction().commit();
|
||||||
|
session.close();
|
||||||
|
|
||||||
|
testData.release();
|
||||||
|
}
|
||||||
|
|
||||||
|
public void testFiltersOnSimpleHqlDelete() {
|
||||||
|
Session session = openSession();
|
||||||
|
session.beginTransaction();
|
||||||
|
Salesperson sp = new Salesperson();
|
||||||
|
sp.setName( "steve" );
|
||||||
|
sp.setRegion( "NA" );
|
||||||
|
session.persist( sp );
|
||||||
|
Salesperson sp2 = new Salesperson();
|
||||||
|
sp2.setName( "john" );
|
||||||
|
sp2.setRegion( "APAC" );
|
||||||
|
session.persist( sp2 );
|
||||||
|
session.getTransaction().commit();
|
||||||
|
session.close();
|
||||||
|
|
||||||
|
session = openSession();
|
||||||
|
session.beginTransaction();
|
||||||
|
session.enableFilter( "region" ).setParameter( "region", "NA" );
|
||||||
|
int count = session.createQuery( "delete from Salesperson" ).executeUpdate();
|
||||||
|
assertEquals( 1, count );
|
||||||
|
session.delete( sp2 );
|
||||||
|
session.getTransaction().commit();
|
||||||
|
session.close();
|
||||||
|
}
|
||||||
|
|
||||||
|
public void testFiltersOnMultiTableHqlDelete() {
|
||||||
|
Session session = openSession();
|
||||||
|
session.beginTransaction();
|
||||||
|
Salesperson sp = new Salesperson();
|
||||||
|
sp.setName( "steve" );
|
||||||
|
sp.setRegion( "NA" );
|
||||||
|
session.persist( sp );
|
||||||
|
Salesperson sp2 = new Salesperson();
|
||||||
|
sp2.setName( "john" );
|
||||||
|
sp2.setRegion( "APAC" );
|
||||||
|
session.persist( sp2 );
|
||||||
|
session.getTransaction().commit();
|
||||||
|
session.close();
|
||||||
|
|
||||||
|
session = openSession();
|
||||||
|
session.beginTransaction();
|
||||||
|
session.enableFilter( "region" ).setParameter( "region", "NA" );
|
||||||
|
int count = session.createQuery( "delete from Salesperson" ).executeUpdate();
|
||||||
|
assertEquals( 1, count );
|
||||||
|
session.delete( sp2 );
|
||||||
|
session.getTransaction().commit();
|
||||||
|
session.close();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
public void testGetFilters() {
|
public void testGetFilters() {
|
||||||
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||||
// Get() test
|
// Get() test
|
||||||
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||||
log.info( "Starting get() filter tests (eager assoc. fetching)." );
|
|
||||||
TestData testData = new TestData();
|
TestData testData = new TestData();
|
||||||
testData.prepare();
|
testData.prepare();
|
||||||
|
|
||||||
Session session = openSession();
|
Session session = openSession();
|
||||||
session.enableFilter( "region" ).setParameter( "region", "APAC" );
|
session.enableFilter( "region" ).setParameter( "region", "APAC" );
|
||||||
|
|
||||||
log.info( "Performing get()..." );
|
|
||||||
Salesperson salesperson = ( Salesperson ) session.get( Salesperson.class, testData.steveId );
|
Salesperson salesperson = ( Salesperson ) session.get( Salesperson.class, testData.steveId );
|
||||||
assertNotNull( salesperson );
|
assertNotNull( salesperson );
|
||||||
assertEquals( "Incorrect order count", 1, salesperson.getOrders().size() );
|
assertEquals( "Incorrect order count", 1, salesperson.getOrders().size() );
|
||||||
|
@ -234,7 +502,6 @@ public class DynamicFilterTest extends FunctionalTestCase {
|
||||||
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||||
// one-to-many loading tests
|
// one-to-many loading tests
|
||||||
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||||
log.info( "Starting one-to-many collection loader filter tests." );
|
|
||||||
TestData testData = new TestData();
|
TestData testData = new TestData();
|
||||||
testData.prepare();
|
testData.prepare();
|
||||||
|
|
||||||
|
@ -242,7 +509,6 @@ public class DynamicFilterTest extends FunctionalTestCase {
|
||||||
session.enableFilter( "seniorSalespersons" )
|
session.enableFilter( "seniorSalespersons" )
|
||||||
.setParameter( "asOfDate", testData.lastMonth.getTime() );
|
.setParameter( "asOfDate", testData.lastMonth.getTime() );
|
||||||
|
|
||||||
log.info( "Performing load of Department..." );
|
|
||||||
Department department = ( Department ) session.load( Department.class, testData.deptId );
|
Department department = ( Department ) session.load( Department.class, testData.deptId );
|
||||||
Set salespersons = department.getSalespersons();
|
Set salespersons = department.getSalespersons();
|
||||||
assertEquals( "Incorrect salesperson count", 1, salespersons.size() );
|
assertEquals( "Incorrect salesperson count", 1, salespersons.size() );
|
||||||
|
@ -255,7 +521,6 @@ public class DynamicFilterTest extends FunctionalTestCase {
|
||||||
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||||
// one-to-many loading tests
|
// one-to-many loading tests
|
||||||
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||||
log.info( "Starting one-to-many collection loader filter tests." );
|
|
||||||
TestData testData = new TestData();
|
TestData testData = new TestData();
|
||||||
testData.prepare();
|
testData.prepare();
|
||||||
|
|
||||||
|
@ -263,7 +528,6 @@ public class DynamicFilterTest extends FunctionalTestCase {
|
||||||
session.enableFilter( "regionlist" )
|
session.enableFilter( "regionlist" )
|
||||||
.setParameterList( "regions", new String[]{"LA", "APAC"} );
|
.setParameterList( "regions", new String[]{"LA", "APAC"} );
|
||||||
|
|
||||||
log.debug( "Performing query of Salespersons" );
|
|
||||||
List salespersons = session.createQuery( "from Salesperson" ).list();
|
List salespersons = session.createQuery( "from Salesperson" ).list();
|
||||||
assertEquals( "Incorrect salesperson count", 1, salespersons.size() );
|
assertEquals( "Incorrect salesperson count", 1, salespersons.size() );
|
||||||
|
|
||||||
|
@ -280,7 +544,7 @@ public class DynamicFilterTest extends FunctionalTestCase {
|
||||||
|
|
||||||
Product prod = ( Product ) session.createCriteria( Product.class )
|
Product prod = ( Product ) session.createCriteria( Product.class )
|
||||||
.setResultTransformer( new DistinctRootEntityResultTransformer() )
|
.setResultTransformer( new DistinctRootEntityResultTransformer() )
|
||||||
.add( Expression.eq( "id", testData.prod1Id ) )
|
.add( Restrictions.eq( "id", testData.prod1Id ) )
|
||||||
.uniqueResult();
|
.uniqueResult();
|
||||||
|
|
||||||
assertNotNull( prod );
|
assertNotNull( prod );
|
||||||
|
@ -420,7 +684,7 @@ public class DynamicFilterTest extends FunctionalTestCase {
|
||||||
Session session = openSession();
|
Session session = openSession();
|
||||||
|
|
||||||
List result = session.createCriteria( Product.class )
|
List result = session.createCriteria( Product.class )
|
||||||
.add( Expression.eq( "id", testData.prod1Id ) )
|
.add( Restrictions.eq( "id", testData.prod1Id ) )
|
||||||
.list();
|
.list();
|
||||||
|
|
||||||
Product prod = ( Product ) result.get( 0 );
|
Product prod = ( Product ) result.get( 0 );
|
||||||
|
|
|
@ -0,0 +1,40 @@
|
||||||
|
<?xml version="1.0"?>
|
||||||
|
<!--
|
||||||
|
~ Hibernate, Relational Persistence for Idiomatic Java
|
||||||
|
~
|
||||||
|
~ Copyright (c) 2008, 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.
|
||||||
|
~
|
||||||
|
~ 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
|
||||||
|
~ Lesser General Public License, as published by the Free Software Foundation.
|
||||||
|
~
|
||||||
|
~ This program is distributed in the hope that it will be useful,
|
||||||
|
~ but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
|
||||||
|
~ or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License
|
||||||
|
~ for more details.
|
||||||
|
~
|
||||||
|
~ You should have received a copy of the GNU Lesser General Public License
|
||||||
|
~ along with this distribution; if not, write to:
|
||||||
|
~ Free Software Foundation, Inc.
|
||||||
|
~ 51 Franklin Street, Fifth Floor
|
||||||
|
~ Boston, MA 02110-1301 USA
|
||||||
|
~
|
||||||
|
-->
|
||||||
|
|
||||||
|
<!DOCTYPE hibernate-mapping
|
||||||
|
SYSTEM
|
||||||
|
"http://hibernate.sourceforge.net/hibernate-mapping-3.0.dtd" >
|
||||||
|
|
||||||
|
<hibernate-mapping package="org.hibernate.test.filter.hql">
|
||||||
|
<class name="Person" table="FILTER_HQL_PERSON">
|
||||||
|
<id column="ID" name="id" type="long">
|
||||||
|
<generator class="increment"/>
|
||||||
|
</id>
|
||||||
|
<property name="name" type="string"/>
|
||||||
|
<property name="sex" column="SEX_CODE" type="char"/>
|
||||||
|
<filter name="sex"/>
|
||||||
|
</class>
|
||||||
|
</hibernate-mapping>
|
|
@ -0,0 +1,93 @@
|
||||||
|
/*
|
||||||
|
* Hibernate, Relational Persistence for Idiomatic Java
|
||||||
|
*
|
||||||
|
* Copyright (c) 2008, 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.
|
||||||
|
*
|
||||||
|
* 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
|
||||||
|
* Lesser General Public License, as published by the Free Software Foundation.
|
||||||
|
*
|
||||||
|
* This program is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
|
||||||
|
* or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License
|
||||||
|
* for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU Lesser General Public License
|
||||||
|
* along with this distribution; if not, write to:
|
||||||
|
* Free Software Foundation, Inc.
|
||||||
|
* 51 Franklin Street, Fifth Floor
|
||||||
|
* Boston, MA 02110-1301 USA
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
package org.hibernate.test.filter.hql;
|
||||||
|
|
||||||
|
import org.hibernate.junit.functional.FunctionalTestCase;
|
||||||
|
import org.hibernate.Session;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Tests for application of filters
|
||||||
|
*
|
||||||
|
* @author Steve Ebersole
|
||||||
|
*/
|
||||||
|
public class BasicFilteredBulkManipulationTest extends FunctionalTestCase {
|
||||||
|
public BasicFilteredBulkManipulationTest(String string) {
|
||||||
|
super( string );
|
||||||
|
}
|
||||||
|
|
||||||
|
public String[] getMappings() {
|
||||||
|
return new String[]{
|
||||||
|
"filter/hql/filter-defs.hbm.xml",
|
||||||
|
"filter/hql/Basic.hbm.xml"
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
public void testBasicFilteredHqlDelete() {
|
||||||
|
Session s = openSession();
|
||||||
|
s.beginTransaction();
|
||||||
|
s.save( new Person( "Steve", 'M' ) );
|
||||||
|
s.save( new Person( "Emmanuel", 'M' ) );
|
||||||
|
s.save( new Person( "Gail", 'F' ) );
|
||||||
|
s.getTransaction().commit();
|
||||||
|
s.close();
|
||||||
|
|
||||||
|
s = openSession();
|
||||||
|
s.beginTransaction();
|
||||||
|
s.enableFilter( "sex" ).setParameter( "sexCode", new Character( 'M' ) );
|
||||||
|
int count = s.createQuery( "delete Person" ).executeUpdate();
|
||||||
|
assertEquals( 2, count );
|
||||||
|
s.getTransaction().commit();
|
||||||
|
s.close();
|
||||||
|
|
||||||
|
s = openSession();
|
||||||
|
s.beginTransaction();
|
||||||
|
s.createQuery( "delete Person" ).executeUpdate();
|
||||||
|
s.getTransaction().commit();
|
||||||
|
s.close();
|
||||||
|
}
|
||||||
|
|
||||||
|
public void testBasicFilteredHqlUpdate() {
|
||||||
|
Session s = openSession();
|
||||||
|
s.beginTransaction();
|
||||||
|
s.save( new Person( "Shawn", 'M' ) );
|
||||||
|
s.save( new Person( "Sally", 'F' ) );
|
||||||
|
s.getTransaction().commit();
|
||||||
|
s.close();
|
||||||
|
|
||||||
|
s = openSession();
|
||||||
|
s.beginTransaction();
|
||||||
|
s.enableFilter( "sex" ).setParameter( "sexCode", new Character( 'M' ) );
|
||||||
|
int count = s.createQuery( "update Person p set p.name = 'Shawn'" ).executeUpdate();
|
||||||
|
assertEquals( 1, count );
|
||||||
|
s.getTransaction().commit();
|
||||||
|
s.close();
|
||||||
|
|
||||||
|
s = openSession();
|
||||||
|
s.beginTransaction();
|
||||||
|
s.createQuery( "delete Person" ).executeUpdate();
|
||||||
|
s.getTransaction().commit();
|
||||||
|
s.close();
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,51 @@
|
||||||
|
/*
|
||||||
|
* Hibernate, Relational Persistence for Idiomatic Java
|
||||||
|
*
|
||||||
|
* Copyright (c) 2008, 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.
|
||||||
|
*
|
||||||
|
* 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
|
||||||
|
* Lesser General Public License, as published by the Free Software Foundation.
|
||||||
|
*
|
||||||
|
* This program is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
|
||||||
|
* or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License
|
||||||
|
* for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU Lesser General Public License
|
||||||
|
* along with this distribution; if not, write to:
|
||||||
|
* Free Software Foundation, Inc.
|
||||||
|
* 51 Franklin Street, Fifth Floor
|
||||||
|
* Boston, MA 02110-1301 USA
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
package org.hibernate.test.filter.hql;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Leaf subclass
|
||||||
|
*
|
||||||
|
* @author Steve Ebersole
|
||||||
|
*/
|
||||||
|
public class Customer extends User {
|
||||||
|
private String company;
|
||||||
|
|
||||||
|
protected Customer() {
|
||||||
|
super();
|
||||||
|
}
|
||||||
|
|
||||||
|
public Customer(String name, char sex, String username, String company) {
|
||||||
|
super( name, sex, username );
|
||||||
|
this.company = company;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getCompany() {
|
||||||
|
return company;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setCompany(String company) {
|
||||||
|
this.company = company;
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,53 @@
|
||||||
|
/*
|
||||||
|
* Hibernate, Relational Persistence for Idiomatic Java
|
||||||
|
*
|
||||||
|
* Copyright (c) 2008, 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.
|
||||||
|
*
|
||||||
|
* 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
|
||||||
|
* Lesser General Public License, as published by the Free Software Foundation.
|
||||||
|
*
|
||||||
|
* This program is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
|
||||||
|
* or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License
|
||||||
|
* for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU Lesser General Public License
|
||||||
|
* along with this distribution; if not, write to:
|
||||||
|
* Free Software Foundation, Inc.
|
||||||
|
* 51 Franklin Street, Fifth Floor
|
||||||
|
* Boston, MA 02110-1301 USA
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
package org.hibernate.test.filter.hql;
|
||||||
|
|
||||||
|
import java.util.Date;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Leaf subclass
|
||||||
|
*
|
||||||
|
* @author Steve Ebersole
|
||||||
|
*/
|
||||||
|
public class Employee extends User {
|
||||||
|
private Date hireDate;
|
||||||
|
|
||||||
|
protected Employee() {
|
||||||
|
super();
|
||||||
|
}
|
||||||
|
|
||||||
|
public Employee(String name, char sex, String username, Date hireDate) {
|
||||||
|
super( name, sex, username );
|
||||||
|
this.hireDate = hireDate;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Date getHireDate() {
|
||||||
|
return hireDate;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setHireDate(Date hireDate) {
|
||||||
|
this.hireDate = hireDate;
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,52 @@
|
||||||
|
<?xml version="1.0"?>
|
||||||
|
<!--
|
||||||
|
~ Hibernate, Relational Persistence for Idiomatic Java
|
||||||
|
~
|
||||||
|
~ Copyright (c) 2008, 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.
|
||||||
|
~
|
||||||
|
~ 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
|
||||||
|
~ Lesser General Public License, as published by the Free Software Foundation.
|
||||||
|
~
|
||||||
|
~ This program is distributed in the hope that it will be useful,
|
||||||
|
~ but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
|
||||||
|
~ or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License
|
||||||
|
~ for more details.
|
||||||
|
~
|
||||||
|
~ You should have received a copy of the GNU Lesser General Public License
|
||||||
|
~ along with this distribution; if not, write to:
|
||||||
|
~ Free Software Foundation, Inc.
|
||||||
|
~ 51 Franklin Street, Fifth Floor
|
||||||
|
~ Boston, MA 02110-1301 USA
|
||||||
|
~
|
||||||
|
-->
|
||||||
|
|
||||||
|
<!DOCTYPE hibernate-mapping
|
||||||
|
SYSTEM
|
||||||
|
"http://hibernate.sourceforge.net/hibernate-mapping-3.0.dtd" >
|
||||||
|
|
||||||
|
<hibernate-mapping package="org.hibernate.test.filter.hql">
|
||||||
|
<class name="Person" table="FILTER_HQL_JOINED_PERSON">
|
||||||
|
<id column="ID" name="id" type="long">
|
||||||
|
<generator class="increment"/>
|
||||||
|
</id>
|
||||||
|
<property name="name" type="string"/>
|
||||||
|
<property name="sex" column="SEX_CODE" type="char"/>
|
||||||
|
<joined-subclass name="User" table="FILTER_HQL_JOINED_USER">
|
||||||
|
<key column="USER_ID"/>
|
||||||
|
<property name="username" type="string"/>
|
||||||
|
<joined-subclass name="Employee" table="FILTER_HQL_JOINED_EMP">
|
||||||
|
<key column="EMP_ID"/>
|
||||||
|
<property name="hireDate" type="date"/>
|
||||||
|
</joined-subclass>
|
||||||
|
<joined-subclass name="Customer" table="FILTER_HQL_JOINED_CUST">
|
||||||
|
<key column="CUST_ID"/>
|
||||||
|
<property name="company" type="string"/>
|
||||||
|
</joined-subclass>
|
||||||
|
</joined-subclass>
|
||||||
|
<filter name="sex"/>
|
||||||
|
</class>
|
||||||
|
</hibernate-mapping>
|
|
@ -0,0 +1,201 @@
|
||||||
|
/*
|
||||||
|
* Hibernate, Relational Persistence for Idiomatic Java
|
||||||
|
*
|
||||||
|
* Copyright (c) 2008, 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.
|
||||||
|
*
|
||||||
|
* 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
|
||||||
|
* Lesser General Public License, as published by the Free Software Foundation.
|
||||||
|
*
|
||||||
|
* This program is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
|
||||||
|
* or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License
|
||||||
|
* for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU Lesser General Public License
|
||||||
|
* along with this distribution; if not, write to:
|
||||||
|
* Free Software Foundation, Inc.
|
||||||
|
* 51 Franklin Street, Fifth Floor
|
||||||
|
* Boston, MA 02110-1301 USA
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
package org.hibernate.test.filter.hql;
|
||||||
|
|
||||||
|
import java.util.Date;
|
||||||
|
|
||||||
|
import org.hibernate.junit.functional.FunctionalTestCase;
|
||||||
|
import org.hibernate.Session;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* TODO : javadoc
|
||||||
|
*
|
||||||
|
* @author Steve Ebersole
|
||||||
|
*/
|
||||||
|
public class JoinedFilteredBulkManipulationTest extends FunctionalTestCase {
|
||||||
|
public JoinedFilteredBulkManipulationTest(String string) {
|
||||||
|
super( string );
|
||||||
|
}
|
||||||
|
|
||||||
|
public String[] getMappings() {
|
||||||
|
return new String[]{
|
||||||
|
"filter/hql/filter-defs.hbm.xml",
|
||||||
|
"filter/hql/Joined.hbm.xml"
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
public void testFilteredJoinedSubclassHqlDeleteRoot() {
|
||||||
|
Session s = openSession();
|
||||||
|
s.beginTransaction();
|
||||||
|
s.save( new Employee( "John", 'M', "john", new Date() ) );
|
||||||
|
s.save( new Employee( "Jane", 'F', "jane", new Date() ) );
|
||||||
|
s.save( new Customer( "Charlie", 'M', "charlie", "Acme" ) );
|
||||||
|
s.save( new Customer( "Wanda", 'F', "wanda", "ABC" ) );
|
||||||
|
s.getTransaction().commit();
|
||||||
|
s.close();
|
||||||
|
|
||||||
|
s = openSession();
|
||||||
|
s.beginTransaction();
|
||||||
|
s.enableFilter( "sex" ).setParameter( "sexCode", new Character('M' ) );
|
||||||
|
int count = s.createQuery( "delete Person" ).executeUpdate();
|
||||||
|
assertEquals( 2, count );
|
||||||
|
s.getTransaction().commit();
|
||||||
|
s.close();
|
||||||
|
|
||||||
|
s = openSession();
|
||||||
|
s.beginTransaction();
|
||||||
|
s.createQuery( "delete Person" ).executeUpdate();
|
||||||
|
s.getTransaction().commit();
|
||||||
|
s.close();
|
||||||
|
}
|
||||||
|
|
||||||
|
public void testFilteredJoinedSubclassHqlDeleteNonLeaf() {
|
||||||
|
Session s = openSession();
|
||||||
|
s.beginTransaction();
|
||||||
|
s.save( new Employee( "John", 'M', "john", new Date() ) );
|
||||||
|
s.save( new Employee( "Jane", 'F', "jane", new Date() ) );
|
||||||
|
s.save( new Customer( "Charlie", 'M', "charlie", "Acme" ) );
|
||||||
|
s.save( new Customer( "Wanda", 'F', "wanda", "ABC" ) );
|
||||||
|
s.getTransaction().commit();
|
||||||
|
s.close();
|
||||||
|
|
||||||
|
s = openSession();
|
||||||
|
s.beginTransaction();
|
||||||
|
s.enableFilter( "sex" ).setParameter( "sexCode", new Character('M' ) );
|
||||||
|
int count = s.createQuery( "delete User" ).executeUpdate();
|
||||||
|
assertEquals( 2, count );
|
||||||
|
s.getTransaction().commit();
|
||||||
|
s.close();
|
||||||
|
|
||||||
|
s = openSession();
|
||||||
|
s.beginTransaction();
|
||||||
|
s.createQuery( "delete Person" ).executeUpdate();
|
||||||
|
s.getTransaction().commit();
|
||||||
|
s.close();
|
||||||
|
}
|
||||||
|
|
||||||
|
public void testFilteredJoinedSubclassHqlDeleteLeaf() {
|
||||||
|
Session s = openSession();
|
||||||
|
s.beginTransaction();
|
||||||
|
s.save( new Employee( "John", 'M', "john", new Date() ) );
|
||||||
|
s.save( new Employee( "Jane", 'F', "jane", new Date() ) );
|
||||||
|
s.save( new Customer( "Charlie", 'M', "charlie", "Acme" ) );
|
||||||
|
s.save( new Customer( "Wanda", 'F', "wanda", "ABC" ) );
|
||||||
|
s.getTransaction().commit();
|
||||||
|
s.close();
|
||||||
|
|
||||||
|
s = openSession();
|
||||||
|
s.beginTransaction();
|
||||||
|
s.enableFilter( "sex" ).setParameter( "sexCode", new Character('M' ) );
|
||||||
|
int count = s.createQuery( "delete Employee" ).executeUpdate();
|
||||||
|
assertEquals( 1, count );
|
||||||
|
s.getTransaction().commit();
|
||||||
|
s.close();
|
||||||
|
|
||||||
|
s = openSession();
|
||||||
|
s.beginTransaction();
|
||||||
|
s.createQuery( "delete Person" ).executeUpdate();
|
||||||
|
s.getTransaction().commit();
|
||||||
|
s.close();
|
||||||
|
}
|
||||||
|
|
||||||
|
public void testFilteredJoinedSubclassHqlUpdateRoot() {
|
||||||
|
Session s = openSession();
|
||||||
|
s.beginTransaction();
|
||||||
|
s.save( new Employee( "John", 'M', "john", new Date() ) );
|
||||||
|
s.save( new Employee( "Jane", 'F', "jane", new Date() ) );
|
||||||
|
s.save( new Customer( "Charlie", 'M', "charlie", "Acme" ) );
|
||||||
|
s.save( new Customer( "Wanda", 'F', "wanda", "ABC" ) );
|
||||||
|
s.getTransaction().commit();
|
||||||
|
s.close();
|
||||||
|
|
||||||
|
s = openSession();
|
||||||
|
s.beginTransaction();
|
||||||
|
s.enableFilter( "sex" ).setParameter( "sexCode", new Character('M' ) );
|
||||||
|
int count = s.createQuery( "update Person p set p.name = '<male>'" ).executeUpdate();
|
||||||
|
assertEquals( 2, count );
|
||||||
|
s.getTransaction().commit();
|
||||||
|
s.close();
|
||||||
|
|
||||||
|
s = openSession();
|
||||||
|
s.beginTransaction();
|
||||||
|
s.createQuery( "delete Person" ).executeUpdate();
|
||||||
|
s.getTransaction().commit();
|
||||||
|
s.close();
|
||||||
|
}
|
||||||
|
|
||||||
|
public void testFilteredJoinedSubclassHqlUpdateNonLeaf() {
|
||||||
|
Session s = openSession();
|
||||||
|
s.beginTransaction();
|
||||||
|
s.save( new Employee( "John", 'M', "john", new Date() ) );
|
||||||
|
s.save( new Employee( "Jane", 'F', "jane", new Date() ) );
|
||||||
|
s.save( new Customer( "Charlie", 'M', "charlie", "Acme" ) );
|
||||||
|
s.save( new Customer( "Wanda", 'F', "wanda", "ABC" ) );
|
||||||
|
s.getTransaction().commit();
|
||||||
|
s.close();
|
||||||
|
|
||||||
|
s = openSession();
|
||||||
|
s.beginTransaction();
|
||||||
|
s.enableFilter( "sex" ).setParameter( "sexCode", new Character('M' ) );
|
||||||
|
int count = s.createQuery( "update User u set u.username = :un where u.name = :n" )
|
||||||
|
.setString( "un", "charlie" )
|
||||||
|
.setString( "n", "Wanda" )
|
||||||
|
.executeUpdate();
|
||||||
|
assertEquals( 0, count );
|
||||||
|
s.getTransaction().commit();
|
||||||
|
s.close();
|
||||||
|
|
||||||
|
s = openSession();
|
||||||
|
s.beginTransaction();
|
||||||
|
s.createQuery( "delete Person" ).executeUpdate();
|
||||||
|
s.getTransaction().commit();
|
||||||
|
s.close();
|
||||||
|
}
|
||||||
|
|
||||||
|
public void testFilteredJoinedSubclassHqlUpdateLeaf() {
|
||||||
|
Session s = openSession();
|
||||||
|
s.beginTransaction();
|
||||||
|
s.save( new Employee( "John", 'M', "john", new Date() ) );
|
||||||
|
s.save( new Employee( "Jane", 'F', "jane", new Date() ) );
|
||||||
|
s.save( new Customer( "Charlie", 'M', "charlie", "Acme" ) );
|
||||||
|
s.save( new Customer( "Wanda", 'F', "wanda", "ABC" ) );
|
||||||
|
s.getTransaction().commit();
|
||||||
|
s.close();
|
||||||
|
|
||||||
|
s = openSession();
|
||||||
|
s.beginTransaction();
|
||||||
|
s.enableFilter( "sex" ).setParameter( "sexCode", new Character('M' ) );
|
||||||
|
int count = s.createQuery( "update Customer c set c.company = 'XYZ'" ).executeUpdate();
|
||||||
|
assertEquals( 1, count );
|
||||||
|
s.getTransaction().commit();
|
||||||
|
s.close();
|
||||||
|
|
||||||
|
s = openSession();
|
||||||
|
s.beginTransaction();
|
||||||
|
s.createQuery( "delete Person" ).executeUpdate();
|
||||||
|
s.getTransaction().commit();
|
||||||
|
s.close();
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,71 @@
|
||||||
|
/*
|
||||||
|
* Hibernate, Relational Persistence for Idiomatic Java
|
||||||
|
*
|
||||||
|
* Copyright (c) 2008, 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.
|
||||||
|
*
|
||||||
|
* 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
|
||||||
|
* Lesser General Public License, as published by the Free Software Foundation.
|
||||||
|
*
|
||||||
|
* This program is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
|
||||||
|
* or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License
|
||||||
|
* for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU Lesser General Public License
|
||||||
|
* along with this distribution; if not, write to:
|
||||||
|
* Free Software Foundation, Inc.
|
||||||
|
* 51 Franklin Street, Fifth Floor
|
||||||
|
* Boston, MA 02110-1301 USA
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
package org.hibernate.test.filter.hql;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Base of inheritence hierarchy
|
||||||
|
*
|
||||||
|
* @author Steve Ebersole
|
||||||
|
*/
|
||||||
|
public class Person {
|
||||||
|
private Long id;
|
||||||
|
private String name;
|
||||||
|
private char sex;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Used by persistence
|
||||||
|
*/
|
||||||
|
protected Person() {
|
||||||
|
}
|
||||||
|
|
||||||
|
public Person(String name, char sex) {
|
||||||
|
this.name = name;
|
||||||
|
this.sex = sex;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Long getId() {
|
||||||
|
return id;
|
||||||
|
}
|
||||||
|
|
||||||
|
private void setId(Long id) {
|
||||||
|
this.id = id;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getName() {
|
||||||
|
return name;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setName(String name) {
|
||||||
|
this.name = name;
|
||||||
|
}
|
||||||
|
|
||||||
|
public char getSex() {
|
||||||
|
return sex;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setSex(char sex) {
|
||||||
|
this.sex = sex;
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,51 @@
|
||||||
|
/*
|
||||||
|
* Hibernate, Relational Persistence for Idiomatic Java
|
||||||
|
*
|
||||||
|
* Copyright (c) 2008, 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.
|
||||||
|
*
|
||||||
|
* 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
|
||||||
|
* Lesser General Public License, as published by the Free Software Foundation.
|
||||||
|
*
|
||||||
|
* This program is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
|
||||||
|
* or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License
|
||||||
|
* for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU Lesser General Public License
|
||||||
|
* along with this distribution; if not, write to:
|
||||||
|
* Free Software Foundation, Inc.
|
||||||
|
* 51 Franklin Street, Fifth Floor
|
||||||
|
* Boston, MA 02110-1301 USA
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
package org.hibernate.test.filter.hql;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Non-leaf subclass
|
||||||
|
*
|
||||||
|
* @author Steve Ebersole
|
||||||
|
*/
|
||||||
|
public class User extends Person {
|
||||||
|
private String username;
|
||||||
|
|
||||||
|
protected User() {
|
||||||
|
super();
|
||||||
|
}
|
||||||
|
|
||||||
|
public User(String name, char sex, String username) {
|
||||||
|
super( name, sex );
|
||||||
|
this.username = username;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getUsername() {
|
||||||
|
return username;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setUsername(String username) {
|
||||||
|
this.username = username;
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,35 @@
|
||||||
|
<?xml version="1.0"?>
|
||||||
|
<!--
|
||||||
|
~ Hibernate, Relational Persistence for Idiomatic Java
|
||||||
|
~
|
||||||
|
~ Copyright (c) 2008, 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.
|
||||||
|
~
|
||||||
|
~ 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
|
||||||
|
~ Lesser General Public License, as published by the Free Software Foundation.
|
||||||
|
~
|
||||||
|
~ This program is distributed in the hope that it will be useful,
|
||||||
|
~ but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
|
||||||
|
~ or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License
|
||||||
|
~ for more details.
|
||||||
|
~
|
||||||
|
~ You should have received a copy of the GNU Lesser General Public License
|
||||||
|
~ along with this distribution; if not, write to:
|
||||||
|
~ Free Software Foundation, Inc.
|
||||||
|
~ 51 Franklin Street, Fifth Floor
|
||||||
|
~ Boston, MA 02110-1301 USA
|
||||||
|
~
|
||||||
|
-->
|
||||||
|
|
||||||
|
<!DOCTYPE hibernate-mapping
|
||||||
|
SYSTEM
|
||||||
|
"http://hibernate.sourceforge.net/hibernate-mapping-3.0.dtd" >
|
||||||
|
|
||||||
|
<hibernate-mapping package="org.hibernate.test.filter.hql">
|
||||||
|
<filter-def name="sex" condition="SEX_CODE = :sexCode">
|
||||||
|
<filter-param name="sexCode" type="char"/>
|
||||||
|
</filter-def>
|
||||||
|
</hibernate-mapping>
|
Loading…
Reference in New Issue