Author: steve.ebersole(a)jboss.com
Date: 2008-10-01 15:32:11 -0400 (Wed, 01 Oct 2008)
New Revision: 15240
Added:
core/branches/Branch_3_2/src/org/hibernate/hql/ast/tree/ParameterContainer.java
core/branches/Branch_3_2/test/org/hibernate/test/filter/hql/
core/branches/Branch_3_2/test/org/hibernate/test/filter/hql/Basic.hbm.xml
core/branches/Branch_3_2/test/org/hibernate/test/filter/hql/BasicFilteredBulkManipulationTest.java
core/branches/Branch_3_2/test/org/hibernate/test/filter/hql/Customer.java
core/branches/Branch_3_2/test/org/hibernate/test/filter/hql/Employee.java
core/branches/Branch_3_2/test/org/hibernate/test/filter/hql/Joined.hbm.xml
core/branches/Branch_3_2/test/org/hibernate/test/filter/hql/JoinedFilteredBulkManipulationTest.java
core/branches/Branch_3_2/test/org/hibernate/test/filter/hql/Person.java
core/branches/Branch_3_2/test/org/hibernate/test/filter/hql/User.java
core/branches/Branch_3_2/test/org/hibernate/test/filter/hql/filter-defs.hbm.xml
Modified:
core/branches/Branch_3_2/src/org/hibernate/criterion/SubqueryExpression.java
core/branches/Branch_3_2/src/org/hibernate/engine/QueryParameters.java
core/branches/Branch_3_2/src/org/hibernate/hql/ast/HqlSqlWalker.java
core/branches/Branch_3_2/src/org/hibernate/hql/ast/QueryTranslatorImpl.java
core/branches/Branch_3_2/src/org/hibernate/hql/ast/SqlGenerator.java
core/branches/Branch_3_2/src/org/hibernate/hql/ast/exec/AbstractStatementExecutor.java
core/branches/Branch_3_2/src/org/hibernate/hql/ast/exec/BasicExecutor.java
core/branches/Branch_3_2/src/org/hibernate/hql/ast/exec/MultiTableDeleteExecutor.java
core/branches/Branch_3_2/src/org/hibernate/hql/ast/exec/MultiTableUpdateExecutor.java
core/branches/Branch_3_2/src/org/hibernate/hql/ast/tree/FromElement.java
core/branches/Branch_3_2/src/org/hibernate/hql/ast/tree/SqlFragment.java
core/branches/Branch_3_2/src/org/hibernate/hql/ast/util/JoinProcessor.java
core/branches/Branch_3_2/src/org/hibernate/hql/ast/util/SyntheticAndFactory.java
core/branches/Branch_3_2/src/org/hibernate/loader/hql/QueryLoader.java
core/branches/Branch_3_2/src/org/hibernate/param/CollectionFilterKeyParameterSpecification.java
core/branches/Branch_3_2/src/org/hibernate/param/DynamicFilterParameterSpecification.java
core/branches/Branch_3_2/src/org/hibernate/param/NamedParameterSpecification.java
core/branches/Branch_3_2/src/org/hibernate/param/PositionalParameterSpecification.java
core/branches/Branch_3_2/src/org/hibernate/param/VersionTypeSeedParameterSpecification.java
core/branches/Branch_3_2/test/org/hibernate/test/filter/DynamicFilterTest.java
Log:
HHH-530 : filters + subqueries;
HHH-3506 : filters + HQL update/delete
Modified: core/branches/Branch_3_2/src/org/hibernate/criterion/SubqueryExpression.java
===================================================================
---
core/branches/Branch_3_2/src/org/hibernate/criterion/SubqueryExpression.java 2008-10-01
19:03:53 UTC (rev 15239)
+++
core/branches/Branch_3_2/src/org/hibernate/criterion/SubqueryExpression.java 2008-10-01
19:32:11 UTC (rev 15240)
@@ -1,14 +1,13 @@
//$Id$
package org.hibernate.criterion;
-import java.util.HashMap;
-
import org.hibernate.Criteria;
import org.hibernate.EntityMode;
import org.hibernate.HibernateException;
import org.hibernate.engine.QueryParameters;
import org.hibernate.engine.SessionFactoryImplementor;
import org.hibernate.engine.TypedValue;
+import org.hibernate.engine.SessionImplementor;
import org.hibernate.impl.CriteriaImpl;
import org.hibernate.loader.criteria.CriteriaJoinWalker;
import org.hibernate.loader.criteria.CriteriaQueryTranslator;
@@ -19,7 +18,7 @@
* @author Gavin King
*/
public abstract class SubqueryExpression implements Criterion {
-
+
private CriteriaImpl criteriaImpl;
private String quantifier;
private String op;
@@ -30,49 +29,67 @@
protected Type[] getTypes() {
return types;
}
-
+
protected SubqueryExpression(String op, String quantifier, DetachedCriteria dc) {
this.criteriaImpl = dc.getCriteriaImpl();
this.quantifier = quantifier;
this.op = op;
}
-
+
protected abstract String toLeftSqlString(Criteria criteria, CriteriaQuery outerQuery);
- public String toSqlString(Criteria criteria, CriteriaQuery criteriaQuery)
- throws HibernateException {
-
+ public String toSqlString(Criteria criteria, CriteriaQuery criteriaQuery) throws
HibernateException {
final SessionFactoryImplementor factory = criteriaQuery.getFactory();
- final OuterJoinLoadable persister = (OuterJoinLoadable) factory.getEntityPersister(
criteriaImpl.getEntityOrClassName() );
+ final OuterJoinLoadable persister =
+ ( OuterJoinLoadable ) factory.getEntityPersister( criteriaImpl.getEntityOrClassName()
);
createAndSetInnerQuery( criteriaQuery, factory );
-
+ criteriaImpl.setSession( deriveRootSession( criteria ) );
+
CriteriaJoinWalker walker = new CriteriaJoinWalker(
persister,
innerQuery,
factory,
criteriaImpl,
criteriaImpl.getEntityOrClassName(),
- new HashMap(),
- innerQuery.getRootSQLALias());
+ criteriaImpl.getSession().getEnabledFilters(),
+ innerQuery.getRootSQLALias()
+ );
String sql = walker.getSQLString();
- final StringBuffer buf = new StringBuffer()
- .append( toLeftSqlString(criteria, criteriaQuery) );
- if (op!=null) buf.append(' ').append(op).append(' ');
- if (quantifier!=null) buf.append(quantifier).append(' ');
- return buf.append('(').append(sql).append(')')
- .toString();
+ final StringBuffer buf = new StringBuffer( toLeftSqlString(criteria, criteriaQuery) );
+ if ( op != null ) {
+ buf.append( ' ' ).append( op ).append( ' ' );
+ }
+ if ( quantifier != null ) {
+ 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 {
//the following two lines were added to ensure that this.params is not null, which
//can happen with two-deep nested subqueries
SessionFactoryImplementor factory = criteriaQuery.getFactory();
createAndSetInnerQuery(criteriaQuery, factory);
-
+
Type[] ppTypes = params.getPositionalParameterTypes();
Object[] ppValues = params.getPositionalParameterValues();
TypedValue[] tv = new TypedValue[ppTypes.length];
@@ -83,12 +100,12 @@
}
/**
- * Creates the inner query used to extract some useful information about
- * types, since it is needed in both methods.
- * @param criteriaQuery
- * @param factory
+ * Creates the inner query used to extract some useful information about types, since it
is needed in both methods.
+ *
+ * @param criteriaQuery The criteria query
+ * @param factory The session factory.
*/
- private void createAndSetInnerQuery(CriteriaQuery criteriaQuery, final
SessionFactoryImplementor factory) {
+ private void createAndSetInnerQuery(CriteriaQuery criteriaQuery,
SessionFactoryImplementor factory) {
if ( innerQuery == null ) {
//with two-deep subqueries, the same alias would get generated for
//both using the old method (criteriaQuery.generateSQLAlias()), so
Modified: core/branches/Branch_3_2/src/org/hibernate/engine/QueryParameters.java
===================================================================
--- core/branches/Branch_3_2/src/org/hibernate/engine/QueryParameters.java 2008-10-01
19:03:53 UTC (rev 15239)
+++ core/branches/Branch_3_2/src/org/hibernate/engine/QueryParameters.java 2008-10-01
19:32:11 UTC (rev 15240)
@@ -3,7 +3,6 @@
import java.io.Serializable;
import java.util.ArrayList;
-import java.util.Arrays;
import java.util.Collection;
import java.util.Iterator;
import java.util.List;
@@ -16,6 +15,7 @@
import org.hibernate.HibernateException;
import org.hibernate.QueryException;
import org.hibernate.ScrollMode;
+import org.hibernate.impl.FilterImpl;
import org.hibernate.dialect.Dialect;
import org.hibernate.hql.classic.ParserHelper;
import org.hibernate.pretty.Printer;
@@ -46,29 +46,28 @@
private boolean callable = false;
private boolean autodiscovertypes = false;
private boolean isNaturalKeyLookup;
-
+
private final ResultTransformer resultTransformer; // why is all others non final ?
-
+
private String processedSQL;
private Type[] processedPositionalParameterTypes;
private Object[] processedPositionalParameterValues;
-
+
public QueryParameters() {
this( ArrayHelper.EMPTY_TYPE_ARRAY, ArrayHelper.EMPTY_OBJECT_ARRAY );
}
public QueryParameters(Type type, Object value) {
- this( new Type[] {type}, new Object[] {value} );
+ this( new Type[] { type }, new Object[] { value } );
}
public QueryParameters(
- final Type[] positionalParameterTypes,
- final Object[] postionalParameterValues,
- final Object optionalObject,
- final String optionalEntityName,
- final Serializable optionalObjectId
- ) {
- this(positionalParameterTypes, postionalParameterValues);
+ final Type[] positionalParameterTypes,
+ final Object[] postionalParameterValues,
+ final Object optionalObject,
+ final String optionalEntityName,
+ final Serializable optionalObjectId) {
+ this( positionalParameterTypes, postionalParameterValues );
this.optionalObject = optionalObject;
this.optionalId = optionalObjectId;
this.optionalEntityName = optionalEntityName;
@@ -76,42 +75,24 @@
}
public QueryParameters(
- final Type[] positionalParameterTypes,
- final Object[] postionalParameterValues
- ) {
- this(
- positionalParameterTypes,
- postionalParameterValues,
- null,
- null,
- false,
- null,
- null,
- false,
- null
- );
+ final Type[] positionalParameterTypes,
+ final Object[] postionalParameterValues) {
+ this( positionalParameterTypes, postionalParameterValues, null, null, false, null,
null, false, null );
}
public QueryParameters(
- final Type[] positionalParameterTypes,
- final Object[] postionalParameterValues,
- final Serializable[] collectionKeys
- ) {
- this(
- positionalParameterTypes,
- postionalParameterValues,
- null,
- collectionKeys
- );
+ final Type[] positionalParameterTypes,
+ final Object[] postionalParameterValues,
+ final Serializable[] collectionKeys) {
+ this( positionalParameterTypes, postionalParameterValues, null, collectionKeys );
}
public QueryParameters(
final Type[] positionalParameterTypes,
final Object[] postionalParameterValues,
final Map namedParameters,
- final Serializable[] collectionKeys
- ) {
- this(
+ final Serializable[] collectionKeys) {
+ this(
positionalParameterTypes,
postionalParameterValues,
namedParameters,
@@ -119,37 +100,36 @@
null,
false,
false,
- null,
null,
+ null,
collectionKeys,
null
- );
- }
+ );
+ }
public QueryParameters(
- final Type[] positionalParameterTypes,
- final Object[] positionalParameterValues,
- final Map lockModes,
- final RowSelection rowSelection,
- final boolean cacheable,
- final String cacheRegion,
- //final boolean forceCacheRefresh,
- final String comment,
- final boolean isLookupByNaturalKey,
- final ResultTransformer transformer
- ) {
+ final Type[] positionalParameterTypes,
+ final Object[] positionalParameterValues,
+ final Map lockModes,
+ final RowSelection rowSelection,
+ final boolean cacheable,
+ final String cacheRegion,
+ //final boolean forceCacheRefresh,
+ final String comment,
+ final boolean isLookupByNaturalKey,
+ final ResultTransformer transformer) {
this(
- positionalParameterTypes,
- positionalParameterValues,
- null,
- lockModes,
- rowSelection,
- false,
- cacheable,
- cacheRegion,
- comment,
- null,
- transformer
+ positionalParameterTypes,
+ positionalParameterValues,
+ null,
+ lockModes,
+ rowSelection,
+ false,
+ cacheable,
+ cacheRegion,
+ comment,
+ null,
+ transformer
);
isNaturalKeyLookup = isLookupByNaturalKey;
}
@@ -166,8 +146,7 @@
//final boolean forceCacheRefresh,
final String comment,
final Serializable[] collectionKeys,
- ResultTransformer transformer
- ) {
+ ResultTransformer transformer) {
this.positionalParameterTypes = positionalParameterTypes;
this.positionalParameterValues = positionalParameterValues;
this.namedParameters = namedParameters;
@@ -181,36 +160,35 @@
this.readOnly = readOnly;
this.resultTransformer = transformer;
}
-
+
public QueryParameters(
- final Type[] positionalParameterTypes,
- final Object[] positionalParameterValues,
- final Map namedParameters,
- final Map lockModes,
- final RowSelection rowSelection,
- final boolean readOnly,
- final boolean cacheable,
- final String cacheRegion,
- //final boolean forceCacheRefresh,
- final String comment,
- final Serializable[] collectionKeys,
- final Object optionalObject,
- final String optionalEntityName,
- final Serializable optionalId,
- final ResultTransformer transformer
- ) {
+ final Type[] positionalParameterTypes,
+ final Object[] positionalParameterValues,
+ final Map namedParameters,
+ final Map lockModes,
+ final RowSelection rowSelection,
+ final boolean readOnly,
+ final boolean cacheable,
+ final String cacheRegion,
+ //final boolean forceCacheRefresh,
+ final String comment,
+ final Serializable[] collectionKeys,
+ final Object optionalObject,
+ final String optionalEntityName,
+ final Serializable optionalId,
+ final ResultTransformer transformer) {
this(
- positionalParameterTypes,
- positionalParameterValues,
- namedParameters,
- lockModes,
- rowSelection,
- readOnly,
- cacheable,
- cacheRegion,
- comment,
- collectionKeys,
- transformer
+ positionalParameterTypes,
+ positionalParameterValues,
+ namedParameters,
+ lockModes,
+ rowSelection,
+ readOnly,
+ cacheable,
+ cacheRegion,
+ comment,
+ collectionKeys,
+ transformer
);
this.optionalEntityName = optionalEntityName;
this.optionalId = optionalId;
@@ -218,7 +196,7 @@
}
public boolean hasRowSelection() {
- return rowSelection!=null;
+ return rowSelection != null;
}
public Map getNamedParameters() {
@@ -236,7 +214,7 @@
public RowSelection getRowSelection() {
return rowSelection;
}
-
+
public ResultTransformer getResultTransformer() {
return resultTransformer;
}
@@ -266,15 +244,15 @@
}
public void traceParameters(SessionFactoryImplementor factory) throws HibernateException
{
- Printer print = new Printer(factory);
- if (positionalParameterValues.length!=0) {
+ Printer print = new Printer( factory );
+ if ( positionalParameterValues.length != 0 ) {
log.trace(
- "parameters: " +
- print.toString(positionalParameterTypes, positionalParameterValues)
- );
+ "parameters: " +
+ print.toString( positionalParameterTypes, positionalParameterValues )
+ );
}
- if (namedParameters!=null) {
- log.trace( "named parameters: " + print.toString(namedParameters) );
+ if ( namedParameters != null ) {
+ log.trace( "named parameters: " + print.toString( namedParameters ) );
}
}
@@ -295,13 +273,13 @@
}
public void validateParameters() throws QueryException {
- int types = positionalParameterTypes==null ? 0 : positionalParameterTypes.length;
- int values = positionalParameterValues==null ? 0 : positionalParameterValues.length;
- if (types!=values) {
+ int types = positionalParameterTypes == null ? 0 : positionalParameterTypes.length;
+ int values = positionalParameterValues == null ? 0 : positionalParameterValues.length;
+ if ( types != values ) {
throw new QueryException(
- "Number of positional parameter types:" + types +
- " does not match number of positional parameters: " + values
- );
+ "Number of positional parameter types:" + types +
+ " does not match number of positional parameters: " + values
+ );
}
}
@@ -362,44 +340,49 @@
}
public void setCallable(boolean callable) {
- this.callable = callable;
+ this.callable = callable;
}
public boolean isCallable() {
return callable;
}
-
+
public boolean hasAutoDiscoverScalarTypes() {
return autodiscovertypes;
}
public void processFilters(String sql, SessionImplementor session) {
-
- if ( session.getEnabledFilters().size()==0 ||
sql.indexOf(ParserHelper.HQL_VARIABLE_PREFIX)<0 ) {
+ processFilters( sql, session.getEnabledFilters(), session.getFactory() );
+ }
+
+ public void processFilters(String sql, Map filters, SessionFactoryImplementor factory)
{
+ if ( filters.size() == 0 || sql.indexOf( ParserHelper.HQL_VARIABLE_PREFIX ) < 0 ) {
// HELLA IMPORTANT OPTIMIZATION!!!
processedPositionalParameterValues = getPositionalParameterValues();
processedPositionalParameterTypes = getPositionalParameterTypes();
processedSQL = sql;
}
else {
-
- Dialect dialect = session.getFactory().getDialect();
+ final Dialect dialect = factory.getDialect();
String symbols = new StringBuffer().append( ParserHelper.HQL_SEPARATORS )
.append( dialect.openQuote() )
.append( dialect.closeQuote() )
.toString();
StringTokenizer tokens = new StringTokenizer( sql, symbols, true );
StringBuffer result = new StringBuffer();
-
+
List parameters = new ArrayList();
List parameterTypes = new ArrayList();
-
+
+ int positionalIndex = 0;
while ( tokens.hasMoreTokens() ) {
final String token = tokens.nextToken();
if ( token.startsWith( ParserHelper.HQL_VARIABLE_PREFIX ) ) {
- String filterParameterName = token.substring( 1 );
- Object value = session.getFilterParameterValue( filterParameterName );
- Type type = session.getFilterParameterType( filterParameterName );
+ final String filterParameterName = token.substring( 1 );
+ final String[] parts = parseFilterParameterName( 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() )
) {
Iterator itr = ( ( Collection ) value ).iterator();
while ( itr.hasNext() ) {
@@ -419,15 +402,17 @@
}
}
else {
+ if ( "?".equals( token ) && positionalIndex <
getPositionalParameterValues().length ) {
+ parameters.add( getPositionalParameterValues()[positionalIndex] );
+ parameterTypes.add( getPositionalParameterTypes()[positionalIndex] );
+ positionalIndex++;
+ }
result.append( token );
}
}
- parameters.addAll( Arrays.asList( getPositionalParameterValues() ) );
- parameterTypes.addAll( Arrays.asList( getPositionalParameterTypes() ) );
processedPositionalParameterValues = parameters.toArray();
- processedPositionalParameterTypes = ( Type[] ) parameterTypes.toArray( new Type[0] );
+ processedPositionalParameterTypes = ( Type[] ) parameterTypes.toArray( new
Type[parameterTypes.size()] );
processedSQL = result.toString();
-
}
}
@@ -458,16 +443,16 @@
public QueryParameters createCopyUsing(RowSelection selection) {
QueryParameters copy = new QueryParameters(
this.positionalParameterTypes,
- this.positionalParameterValues,
- this.namedParameters,
- this.lockModes,
- selection,
- this.readOnly,
- this.cacheable,
- this.cacheRegion,
- this.comment,
- this.collectionKeys,
- this.optionalObject,
+ this.positionalParameterValues,
+ this.namedParameters,
+ this.lockModes,
+ selection,
+ this.readOnly,
+ this.cacheable,
+ this.cacheRegion,
+ this.comment,
+ this.collectionKeys,
+ this.optionalObject,
this.optionalEntityName,
this.optionalId,
this.resultTransformer
@@ -478,5 +463,13 @@
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 };
+ }
}
Modified: core/branches/Branch_3_2/src/org/hibernate/hql/ast/HqlSqlWalker.java
===================================================================
--- core/branches/Branch_3_2/src/org/hibernate/hql/ast/HqlSqlWalker.java 2008-10-01
19:03:53 UTC (rev 15239)
+++ core/branches/Branch_3_2/src/org/hibernate/hql/ast/HqlSqlWalker.java 2008-10-01
19:32:11 UTC (rev 15240)
@@ -209,6 +209,10 @@
return collectionFilterRole != null;
}
+ public String getCollectionFilterRole() {
+ return collectionFilterRole;
+ }
+
public SessionFactoryHelper getSessionFactoryHelper() {
return sessionFactoryHelper;
}
@@ -531,8 +535,8 @@
// After that, process the JOINs.
// Invoke a delegate to do the work, as this is farily complex.
- JoinProcessor joinProcessor = new JoinProcessor( astFactory, queryTranslatorImpl );
- joinProcessor.processJoins( qn, isSubQuery() );
+ JoinProcessor joinProcessor = new JoinProcessor( this );
+ joinProcessor.processJoins( qn );
// Attach any mapping-defined "ORDER BY" fragments
Iterator itr = qn.getFromClause().getProjectionList().iterator();
@@ -570,13 +574,21 @@
// Make #@%$^#^&# sure no alias is applied to the table name
fromElement.setText( persister.getTableName() );
- // append any filter fragments; the EMPTY_MAP is used under the assumption that
- // currently enabled filters should not affect this process
- if ( persister.getDiscriminatorType() != null ) {
- new SyntheticAndFactory( getASTFactory() ).addDiscriminatorWhereFragment(
+// // append any filter fragments; the EMPTY_MAP is used under the assumption that
+// // currently enabled filters should not affect this process
+// if ( persister.getDiscriminatorType() != null ) {
+// 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,
persister,
- java.util.Collections.EMPTY_MAP,
+ queryTranslatorImpl.getEnabledFilters(),
fromElement.getTableAlias()
);
}
Modified: core/branches/Branch_3_2/src/org/hibernate/hql/ast/QueryTranslatorImpl.java
===================================================================
--- core/branches/Branch_3_2/src/org/hibernate/hql/ast/QueryTranslatorImpl.java 2008-10-01
19:03:53 UTC (rev 15239)
+++ core/branches/Branch_3_2/src/org/hibernate/hql/ast/QueryTranslatorImpl.java 2008-10-01
19:32:11 UTC (rev 15240)
@@ -74,7 +74,9 @@
private String sql;
private ParameterTranslations paramTranslations;
+ private List collectedParameterSpecifications;
+
/**
* Creates a new AST-based query translator.
*
@@ -217,6 +219,7 @@
log.debug( "SQL: " + sql );
}
gen.getParseErrorHandler().throwQueryException();
+ collectedParameterSpecifications = gen.getCollectedParameters();
}
}
@@ -540,10 +543,15 @@
public ParameterTranslations getParameterTranslations() {
if ( paramTranslations == null ) {
paramTranslations = new ParameterTranslationsImpl( getWalker().getParameters() );
+// paramTranslations = new ParameterTranslationsImpl( collectedParameterSpecifications
);
}
return paramTranslations;
}
+ public List getCollectedParameterSpecifications() {
+ return collectedParameterSpecifications;
+ }
+
public static class JavaConstantConverter implements NodeTraverser.VisitationStrategy {
private AST dotRoot;
public void visit(AST node) {
Modified: core/branches/Branch_3_2/src/org/hibernate/hql/ast/SqlGenerator.java
===================================================================
--- core/branches/Branch_3_2/src/org/hibernate/hql/ast/SqlGenerator.java 2008-10-01
19:03:53 UTC (rev 15239)
+++ core/branches/Branch_3_2/src/org/hibernate/hql/ast/SqlGenerator.java 2008-10-01
19:32:11 UTC (rev 15240)
@@ -4,16 +4,20 @@
import java.util.ArrayList;
import java.util.LinkedList;
import java.util.List;
+import java.util.Arrays;
import antlr.RecognitionException;
import antlr.collections.AST;
import org.hibernate.QueryException;
+import org.hibernate.param.ParameterSpecification;
import org.hibernate.dialect.function.SQLFunction;
import org.hibernate.engine.SessionFactoryImplementor;
import org.hibernate.hql.antlr.SqlGeneratorBase;
import org.hibernate.hql.ast.tree.MethodNode;
import org.hibernate.hql.ast.tree.FromElement;
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
@@ -41,6 +45,12 @@
private LinkedList outputStack = new LinkedList();
+ private List collectedParameters = new ArrayList();
+
+ public List getCollectedParameters() {
+ return collectedParameters;
+ }
+
protected void out(String s) {
writer.clause( s );
}
@@ -52,6 +62,18 @@
else {
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) {
Modified:
core/branches/Branch_3_2/src/org/hibernate/hql/ast/exec/AbstractStatementExecutor.java
===================================================================
---
core/branches/Branch_3_2/src/org/hibernate/hql/ast/exec/AbstractStatementExecutor.java 2008-10-01
19:03:53 UTC (rev 15239)
+++
core/branches/Branch_3_2/src/org/hibernate/hql/ast/exec/AbstractStatementExecutor.java 2008-10-01
19:32:11 UTC (rev 15240)
@@ -4,6 +4,8 @@
import java.sql.PreparedStatement;
import java.sql.Connection;
import java.sql.Statement;
+import java.util.Collections;
+import java.util.List;
import org.hibernate.HibernateException;
import org.hibernate.action.BulkOperationCleanupAction;
@@ -34,6 +36,7 @@
private final Log log;
private final HqlSqlWalker walker;
+ private List idSelectParameterSpecifications = Collections.EMPTY_LIST;
public AbstractStatementExecutor(HqlSqlWalker walker, Log log) {
this.walker = walker;
@@ -48,6 +51,10 @@
return walker.getSessionFactoryHelper().getFactory();
}
+ protected List getIdSelectParameterSpecifications() {
+ return idSelectParameterSpecifications;
+ }
+
protected abstract Queryable[] getAffectedQueryables();
protected String generateIdInsertSelect(Queryable persister, String tableAlias, AST
whereClause) {
@@ -80,6 +87,7 @@
SqlGenerator sqlGenerator = new SqlGenerator( getFactory() );
sqlGenerator.whereClause( whereClause );
userWhereClause = sqlGenerator.getSQL().substring( 7 ); // strip the " where
"
+ idSelectParameterSpecifications = sqlGenerator.getCollectedParameters();
}
catch ( RecognitionException e ) {
throw new HibernateException( "Unable to generate id select for DML
operation", e );
Modified: core/branches/Branch_3_2/src/org/hibernate/hql/ast/exec/BasicExecutor.java
===================================================================
--- core/branches/Branch_3_2/src/org/hibernate/hql/ast/exec/BasicExecutor.java 2008-10-01
19:03:53 UTC (rev 15239)
+++ core/branches/Branch_3_2/src/org/hibernate/hql/ast/exec/BasicExecutor.java 2008-10-01
19:32:11 UTC (rev 15240)
@@ -4,6 +4,7 @@
import java.sql.PreparedStatement;
import java.sql.SQLException;
import java.util.Iterator;
+import java.util.List;
import org.hibernate.HibernateException;
import org.hibernate.engine.QueryParameters;
@@ -31,6 +32,7 @@
private final Queryable persister;
private final String sql;
+ private final List parameterSpecifications;
public BasicExecutor(HqlSqlWalker walker, Queryable persister) {
super( walker, log );
@@ -40,6 +42,7 @@
gen.statement( walker.getAST() );
sql = gen.getSQL();
gen.getParseErrorHandler().throwQueryException();
+ parameterSpecifications = gen.getCollectedParameters();
}
catch ( RecognitionException e ) {
throw QuerySyntaxException.convert( e );
@@ -60,10 +63,10 @@
try {
try {
st = session.getBatcher().prepareStatement( sql );
- Iterator paramSpecifications = getWalker().getParameters().iterator();
+ Iterator parameterSpecifications = this.parameterSpecifications.iterator();
int pos = 1;
- while ( paramSpecifications.hasNext() ) {
- final ParameterSpecification paramSpec = ( ParameterSpecification )
paramSpecifications.next();
+ while ( parameterSpecifications.hasNext() ) {
+ final ParameterSpecification paramSpec = ( ParameterSpecification )
parameterSpecifications.next();
pos += paramSpec.bind( st, parameters, session, pos );
}
if ( selection != null ) {
Modified:
core/branches/Branch_3_2/src/org/hibernate/hql/ast/exec/MultiTableDeleteExecutor.java
===================================================================
---
core/branches/Branch_3_2/src/org/hibernate/hql/ast/exec/MultiTableDeleteExecutor.java 2008-10-01
19:03:53 UTC (rev 15239)
+++
core/branches/Branch_3_2/src/org/hibernate/hql/ast/exec/MultiTableDeleteExecutor.java 2008-10-01
19:32:11 UTC (rev 15240)
@@ -84,7 +84,7 @@
try {
try {
ps = session.getBatcher().prepareStatement( idInsertSelect );
- Iterator paramSpecifications = getWalker().getParameters().iterator();
+ Iterator paramSpecifications = getIdSelectParameterSpecifications().iterator();
int pos = 1;
while ( paramSpecifications.hasNext() ) {
final ParameterSpecification paramSpec = ( ParameterSpecification )
paramSpecifications.next();
Modified:
core/branches/Branch_3_2/src/org/hibernate/hql/ast/exec/MultiTableUpdateExecutor.java
===================================================================
---
core/branches/Branch_3_2/src/org/hibernate/hql/ast/exec/MultiTableUpdateExecutor.java 2008-10-01
19:03:53 UTC (rev 15239)
+++
core/branches/Branch_3_2/src/org/hibernate/hql/ast/exec/MultiTableUpdateExecutor.java 2008-10-01
19:32:11 UTC (rev 15240)
@@ -109,7 +109,7 @@
try {
ps = session.getBatcher().prepareStatement( idInsertSelect );
int parameterStart = getWalker().getNumberOfParametersInSetClause();
- List allParams = getWalker().getParameters();
+ List allParams = getIdSelectParameterSpecifications();
Iterator whereParams = allParams.subList( parameterStart, allParams.size()
).iterator();
int sum = 1; // jdbc params are 1-based
while ( whereParams.hasNext() ) {
Modified: core/branches/Branch_3_2/src/org/hibernate/hql/ast/tree/FromElement.java
===================================================================
--- core/branches/Branch_3_2/src/org/hibernate/hql/ast/tree/FromElement.java 2008-10-01
19:03:53 UTC (rev 15239)
+++ core/branches/Branch_3_2/src/org/hibernate/hql/ast/tree/FromElement.java 2008-10-01
19:32:11 UTC (rev 15240)
@@ -3,8 +3,10 @@
import java.util.LinkedList;
import java.util.List;
+import java.util.ArrayList;
import org.hibernate.QueryException;
+import org.hibernate.param.ParameterSpecification;
import org.hibernate.engine.JoinSequence;
import org.hibernate.hql.QueryTranslator;
import org.hibernate.hql.CollectionProperties;
@@ -36,7 +38,7 @@
* Date: Dec 6, 2003<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 String className;
@@ -548,4 +550,23 @@
public boolean isDereferencedBySubclassProperty() {
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() ] );
+ }
}
Added: core/branches/Branch_3_2/src/org/hibernate/hql/ast/tree/ParameterContainer.java
===================================================================
--- core/branches/Branch_3_2/src/org/hibernate/hql/ast/tree/ParameterContainer.java
(rev 0)
+++
core/branches/Branch_3_2/src/org/hibernate/hql/ast/tree/ParameterContainer.java 2008-10-01
19:32:11 UTC (rev 15240)
@@ -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();
+}
Modified: core/branches/Branch_3_2/src/org/hibernate/hql/ast/tree/SqlFragment.java
===================================================================
--- core/branches/Branch_3_2/src/org/hibernate/hql/ast/tree/SqlFragment.java 2008-10-01
19:03:53 UTC (rev 15239)
+++ core/branches/Branch_3_2/src/org/hibernate/hql/ast/tree/SqlFragment.java 2008-10-01
19:32:11 UTC (rev 15240)
@@ -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;
+import java.util.List;
+import java.util.ArrayList;
+
import org.hibernate.sql.JoinFragment;
+import org.hibernate.param.ParameterSpecification;
/**
* 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 FromElement fromElement;
@@ -27,4 +54,23 @@
public FromElement getFromElement() {
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() ] );
+ }
}
Modified: core/branches/Branch_3_2/src/org/hibernate/hql/ast/util/JoinProcessor.java
===================================================================
--- core/branches/Branch_3_2/src/org/hibernate/hql/ast/util/JoinProcessor.java 2008-10-01
19:03:53 UTC (rev 15239)
+++ core/branches/Branch_3_2/src/org/hibernate/hql/ast/util/JoinProcessor.java 2008-10-01
19:32:11 UTC (rev 15240)
@@ -4,22 +4,29 @@
import java.util.ArrayList;
import java.util.Iterator;
import java.util.ListIterator;
-import java.util.Collections;
import java.util.List;
+import java.util.StringTokenizer;
+import java.util.Collection;
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.QueryParameters;
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.FromElement;
import org.hibernate.hql.ast.tree.QueryNode;
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.util.StringHelper;
+import org.hibernate.util.ArrayHelper;
-import antlr.ASTFactory;
-
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
@@ -34,18 +41,17 @@
private static final Log log = LogFactory.getLog( JoinProcessor.class );
- private QueryTranslatorImpl queryTranslatorImpl;
- private SyntheticAndFactory andFactory;
+ private final HqlSqlWalker walker;
+ private final SyntheticAndFactory syntheticAndFactory;
/**
* Constructs a new JoinProcessor.
*
- * @param astFactory The factory for AST node creation.
- * @param queryTranslatorImpl The query translator.
+ * @param walker The walker to which we are bound, giving us access to needed
resources.
*/
- public JoinProcessor(ASTFactory astFactory, QueryTranslatorImpl queryTranslatorImpl) {
- this.andFactory = new SyntheticAndFactory( astFactory );
- this.queryTranslatorImpl = queryTranslatorImpl;
+ public JoinProcessor(HqlSqlWalker walker) {
+ this.walker = walker;
+ this.syntheticAndFactory = new SyntheticAndFactory( walker );
}
/**
@@ -69,7 +75,7 @@
}
}
- public void processJoins(QueryNode query, boolean inSubquery) {
+ public void processJoins(QueryNode query) {
final FromClause fromClause = query.getFromClause();
final List fromElements;
@@ -108,22 +114,21 @@
log.trace( "forcing inclusion of extra joins [alias=" + alias + ",
containsTableAlias=" + containsTableAlias + "]" );
return true;
}
- boolean shallowQuery = queryTranslatorImpl.isShallowQuery();
+ boolean shallowQuery = walker.isShallowQuery();
boolean includeSubclasses = fromElement.isIncludeSubclasses();
boolean subQuery = fromClause.isSubQuery();
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) {
- // Generate FROM and WHERE fragments for the from element.
+ private void addJoinNodes(QueryNode query, JoinSequence join, FromElement fromElement)
{
JoinFragment joinFragment = join.toJoinFragment(
- inSubquery ? Collections.EMPTY_MAP : queryTranslatorImpl.getEnabledFilters(),
+ walker.getEnabledFilters(),
fromElement.useFromFragment() ||
fromElement.isDereferencedBySuperclassOrSubclassProperty(),
fromElement.getWithClauseFragment(),
fromElement.getWithClauseJoinAlias()
@@ -143,13 +148,24 @@
// If there is a FROM fragment and the FROM element is an explicit, then add the from
part.
if ( fromElement.useFromFragment() /*&& StringHelper.isNotEmpty( frag )*/ ) {
- String fromFragment = processFromFragment( frag, join );
+ String fromFragment = processFromFragment( frag, join ).trim();
if ( log.isDebugEnabled() ) {
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) {
@@ -161,4 +177,56 @@
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;
+ }
+
}
Modified:
core/branches/Branch_3_2/src/org/hibernate/hql/ast/util/SyntheticAndFactory.java
===================================================================
---
core/branches/Branch_3_2/src/org/hibernate/hql/ast/util/SyntheticAndFactory.java 2008-10-01
19:03:53 UTC (rev 15239)
+++
core/branches/Branch_3_2/src/org/hibernate/hql/ast/util/SyntheticAndFactory.java 2008-10-01
19:32:11 UTC (rev 15240)
@@ -2,18 +2,20 @@
package org.hibernate.hql.ast.util;
import java.util.Map;
-import java.util.StringTokenizer;
import org.hibernate.hql.antlr.HqlSqlTokenTypes;
import org.hibernate.hql.ast.tree.FromElement;
import org.hibernate.hql.ast.tree.QueryNode;
import org.hibernate.hql.ast.tree.RestrictableStatement;
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.sql.JoinFragment;
import org.hibernate.util.StringHelper;
+import org.hibernate.type.Type;
+import org.hibernate.param.CollectionFilterKeyParameterSpecification;
-import antlr.ASTFactory;
import antlr.collections.AST;
import org.apache.commons.logging.Log;
@@ -27,27 +29,36 @@
public class SyntheticAndFactory implements HqlSqlTokenTypes {
private static final Log log = LogFactory.getLog( SyntheticAndFactory.class );
- private ASTFactory astFactory;
+ private HqlSqlWalker hqlSqlWalker;
private AST thetaJoins;
private AST filters;
- public SyntheticAndFactory(ASTFactory astFactory) {
- this.astFactory = astFactory;
+ public SyntheticAndFactory(HqlSqlWalker hqlSqlWalker) {
+ 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 ) {
return;
}
+ if ( !fromElement.useWhereFragment() && !joinFragment.hasThetaJoins() ) {
+ return;
+ }
+
whereFragment = whereFragment.trim();
if ( StringHelper.isEmpty( whereFragment ) ) {
return;
}
- else if ( !fromElement.useWhereFragment() && !joinFragment.hasThetaJoins() ) {
- return;
- }
// Forcefully remove leading ands from where fragments; the grammar will
// handle adding them
@@ -55,12 +66,36 @@
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.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
// 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().
@@ -69,11 +104,11 @@
// Find or create the WHERE clause
AST where = query.getWhereClause();
// 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
ASTUtil.insertChild( where, filters );
}
-
+
// add the current fragment to the FILTERS node
filters.addChild( fragment );
}
@@ -82,7 +117,7 @@
// Find or create the WHERE clause
AST where = query.getWhereClause();
// 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.
if (filters==null) {
ASTUtil.insertChild( where, thetaJoins );
@@ -91,14 +126,18 @@
ASTUtil.insertSibling( thetaJoins, filters );
}
}
-
+
// add the current fragment to the THETA_JOINS node
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();
if ( "".equals( whereFragment ) ) {
return;
@@ -118,13 +157,19 @@
// At some point we probably want to apply an additional grammar to
// properly tokenize this where fragment into constituent parts
// 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 ) {
statement.getWhereClause().setFirstChild( discrimNode );
}
else {
- AST and = astFactory.create( AND, "{and}" );
+ AST and = create( AND, "{and}" );
AST currentFirstChild = statement.getWhereClause().getFirstChild();
and.setFirstChild( discrimNode );
and.addChild( currentFirstChild );
Modified: core/branches/Branch_3_2/src/org/hibernate/loader/hql/QueryLoader.java
===================================================================
--- core/branches/Branch_3_2/src/org/hibernate/loader/hql/QueryLoader.java 2008-10-01
19:03:53 UTC (rev 15239)
+++ core/branches/Branch_3_2/src/org/hibernate/loader/hql/QueryLoader.java 2008-10-01
19:32:11 UTC (rev 15240)
@@ -483,8 +483,8 @@
final QueryParameters queryParameters,
final int startIndex,
final SessionImplementor session) throws SQLException {
- int position = bindFilterParameterValues( statement, queryParameters, startIndex,
session );
- List parameterSpecs = queryTranslator.getSqlAST().getWalker().getParameters();
+ int position = startIndex;
+ List parameterSpecs = queryTranslator.getCollectedParameterSpecifications();
Iterator itr = parameterSpecs.iterator();
while ( itr.hasNext() ) {
ParameterSpecification spec = ( ParameterSpecification ) itr.next();
Modified:
core/branches/Branch_3_2/src/org/hibernate/param/CollectionFilterKeyParameterSpecification.java
===================================================================
---
core/branches/Branch_3_2/src/org/hibernate/param/CollectionFilterKeyParameterSpecification.java 2008-10-01
19:03:53 UTC (rev 15239)
+++
core/branches/Branch_3_2/src/org/hibernate/param/CollectionFilterKeyParameterSpecification.java 2008-10-01
19:32:11 UTC (rev 15240)
@@ -8,13 +8,12 @@
import org.hibernate.type.Type;
/**
- * A specialized ParameterSpecification impl for dealing with a collection-key
- * as part of a collection filter compilation.
+ * A specialized ParameterSpecification impl for dealing with a collection-key as part of
a collection filter
+ * compilation.
*
* @author Steve Ebersole
*/
public class CollectionFilterKeyParameterSpecification implements ParameterSpecification
{
-
private final String collectionRole;
private final Type keyType;
private final int queryParameterPosition;
@@ -34,6 +33,9 @@
this.queryParameterPosition = queryParameterPosition;
}
+ /**
+ * {@inheritDoc}
+ */
public int bind(
PreparedStatement statement,
QueryParameters qp,
@@ -44,14 +46,23 @@
return keyType.getColumnSpan( session.getFactory() );
}
+ /**
+ * {@inheritDoc}
+ */
public Type getExpectedType() {
return keyType;
}
+ /**
+ * {@inheritDoc}
+ */
public void setExpectedType(Type expectedType) {
// todo : throw exception?
}
+ /**
+ * {@inheritDoc}
+ */
public String renderDisplayInfo() {
return "collection-filter-key=" + collectionRole;
}
Modified:
core/branches/Branch_3_2/src/org/hibernate/param/DynamicFilterParameterSpecification.java
===================================================================
---
core/branches/Branch_3_2/src/org/hibernate/param/DynamicFilterParameterSpecification.java 2008-10-01
19:03:53 UTC (rev 15239)
+++
core/branches/Branch_3_2/src/org/hibernate/param/DynamicFilterParameterSpecification.java 2008-10-01
19:32:11 UTC (rev 15240)
@@ -2,20 +2,17 @@
import java.sql.PreparedStatement;
import java.sql.SQLException;
+import java.util.Collection;
+import java.util.Iterator;
import org.hibernate.engine.QueryParameters;
import org.hibernate.engine.SessionImplementor;
import org.hibernate.type.Type;
/**
- * A specialized ParameterSpecification impl for dealing with a dynamic filter
- * parameters.
- * <p/>
- * 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.
+ * A specialized ParameterSpecification impl for dealing with a dynamic filter
parameters.
+ *
+ * @see org.hibernate.Session#enableFilter(String)
*
* @author Steve Ebersole
*/
@@ -23,37 +20,65 @@
private final String filterName;
private final String parameterName;
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(
String filterName,
String parameterName,
- Type definedParameterType,
- int queryParameterPosition) {
+ Type definedParameterType) {
this.filterName = filterName;
this.parameterName = parameterName;
this.definedParameterType = definedParameterType;
- this.queryParameterPosition = queryParameterPosition;
}
+ /**
+ * {@inheritDoc}
+ */
public int bind(
PreparedStatement statement,
QueryParameters qp,
SessionImplementor session,
- int position) throws SQLException {
- Object value = qp.getFilteredPositionalParameterValues()[queryParameterPosition];
- definedParameterType.nullSafeSet( statement, value, position, session );
- return definedParameterType.getColumnSpan( session.getFactory() );
+ int start) throws SQLException {
+ final int columnSpan = definedParameterType.getColumnSpan( session.getFactory() );
+ final Object value = session.getFilterParameterValue( filterName + '.' +
parameterName );
+ 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() {
return definedParameterType;
}
+ /**
+ * {@inheritDoc}
+ */
public void setExpectedType(Type expectedType) {
- // todo : throw exception?
+ // todo : throw exception? maybe warn if not the same?
}
+ /**
+ * {@inheritDoc}
+ */
public String renderDisplayInfo() {
return "dynamic-filter={filterName=" + filterName + ",paramName=" +
parameterName + "}";
}
Modified:
core/branches/Branch_3_2/src/org/hibernate/param/NamedParameterSpecification.java
===================================================================
---
core/branches/Branch_3_2/src/org/hibernate/param/NamedParameterSpecification.java 2008-10-01
19:03:53 UTC (rev 15239)
+++
core/branches/Branch_3_2/src/org/hibernate/param/NamedParameterSpecification.java 2008-10-01
19:32:11 UTC (rev 15240)
@@ -9,14 +9,20 @@
import java.sql.SQLException;
/**
- * Relates to an explicit query named-parameter.
+ * Parameter bind specification for an explicit named parameter.
*
* @author Steve Ebersole
*/
public class NamedParameterSpecification extends AbstractExplicitParameterSpecification
implements ParameterSpecification {
-
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) {
super( sourceLine, sourceColumn );
this.name = name;
@@ -39,10 +45,18 @@
return typedValue.getType().getColumnSpan( session.getFactory() );
}
+ /**
+ * {@inheritDoc}
+ */
public String renderDisplayInfo() {
return "name=" + name + ", expectedType=" + getExpectedType();
}
+ /**
+ * Getter for property 'name'.
+ *
+ * @return Value for property 'name'.
+ */
public String getName() {
return name;
}
Modified:
core/branches/Branch_3_2/src/org/hibernate/param/PositionalParameterSpecification.java
===================================================================
---
core/branches/Branch_3_2/src/org/hibernate/param/PositionalParameterSpecification.java 2008-10-01
19:03:53 UTC (rev 15239)
+++
core/branches/Branch_3_2/src/org/hibernate/param/PositionalParameterSpecification.java 2008-10-01
19:32:11 UTC (rev 15240)
@@ -9,14 +9,20 @@
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
*/
public class PositionalParameterSpecification extends
AbstractExplicitParameterSpecification implements ParameterSpecification {
-
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) {
super( sourceLine, sourceColumn );
this.hqlPosition = hqlPosition;
@@ -40,10 +46,18 @@
return type.getColumnSpan( session.getFactory() );
}
+ /**
+ * {@inheritDoc}
+ */
public String renderDisplayInfo() {
return "ordinal=" + hqlPosition + ", expectedType=" +
getExpectedType();
}
+ /**
+ * Getter for property 'hqlPosition'.
+ *
+ * @return Value for property 'hqlPosition'.
+ */
public int getHqlPosition() {
return hqlPosition;
}
Modified:
core/branches/Branch_3_2/src/org/hibernate/param/VersionTypeSeedParameterSpecification.java
===================================================================
---
core/branches/Branch_3_2/src/org/hibernate/param/VersionTypeSeedParameterSpecification.java 2008-10-01
19:03:53 UTC (rev 15239)
+++
core/branches/Branch_3_2/src/org/hibernate/param/VersionTypeSeedParameterSpecification.java 2008-10-01
19:32:11 UTC (rev 15240)
@@ -11,20 +11,24 @@
import java.sql.SQLException;
/**
- * Implementation of VersionTypeSeedParameterSpecification.
+ * Parameter bind specification used for optimisitc lock version seeding (from insert
statements).
*
* @author Steve Ebersole
*/
public class VersionTypeSeedParameterSpecification implements ParameterSpecification {
-
private VersionType type;
+ /**
+ * Constructs a version seed parameter bind specification.
+ *
+ * @param type The version type.
+ */
public VersionTypeSeedParameterSpecification(VersionType type) {
this.type = type;
}
/**
- * @see org.hibernate.param.ParameterSpecification#bind
+ * {@inheritDoc}
*/
public int bind(PreparedStatement statement, QueryParameters qp, SessionImplementor
session, int position)
throws SQLException {
@@ -32,14 +36,23 @@
return 1;
}
+ /**
+ * {@inheritDoc}
+ */
public Type getExpectedType() {
return type;
}
+ /**
+ * {@inheritDoc}
+ */
public void setExpectedType(Type expectedType) {
// expected type is intrinsic here...
}
+ /**
+ * {@inheritDoc}
+ */
public String renderDisplayInfo() {
return "version-seed, type=" + type;
}
Modified: core/branches/Branch_3_2/test/org/hibernate/test/filter/DynamicFilterTest.java
===================================================================
---
core/branches/Branch_3_2/test/org/hibernate/test/filter/DynamicFilterTest.java 2008-10-01
19:03:53 UTC (rev 15239)
+++
core/branches/Branch_3_2/test/org/hibernate/test/filter/DynamicFilterTest.java 2008-10-01
19:32:11 UTC (rev 15240)
@@ -10,26 +10,26 @@
import java.util.Set;
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.FetchMode;
import org.hibernate.Hibernate;
import org.hibernate.Session;
import org.hibernate.Transaction;
-import org.hibernate.junit.functional.FunctionalTestCase;
-import org.hibernate.junit.functional.FunctionalTestClassTestSuite;
+import org.hibernate.Criteria;
+import org.hibernate.impl.SessionFactoryImpl;
+import org.hibernate.engine.SessionImplementor;
import org.hibernate.cache.CacheKey;
import org.hibernate.cache.entry.CollectionCacheEntry;
import org.hibernate.cfg.Configuration;
import org.hibernate.cfg.Environment;
-import org.hibernate.criterion.Expression;
-import org.hibernate.engine.SessionFactoryImplementor;
-import org.hibernate.impl.SessionFactoryImpl;
+import org.hibernate.criterion.Restrictions;
+import org.hibernate.criterion.DetachedCriteria;
+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.test.TestCase;
import org.hibernate.transform.DistinctRootEntityResultTransformer;
/**
@@ -39,8 +39,6 @@
*/
public class DynamicFilterTest extends FunctionalTestCase {
- private Log log = LogFactory.getLog( DynamicFilterTest.class );
-
public DynamicFilterTest(String testName) {
super( testName );
}
@@ -79,6 +77,7 @@
testData.prepare();
Session session = openSession();
+ long ts = ( ( SessionImplementor ) session ).getTimestamp();
// Force a collection into the second level cache, with its non-filtered elements
Salesperson sp = ( Salesperson ) session.load( Salesperson.class, testData.steveId );
@@ -93,6 +92,7 @@
session.close();
session = openSession();
+ ts = ( ( SessionImplementor ) session ).getTimestamp();
session.enableFilter( "fulfilledOrders" ).setParameter( "asOfDate",
testData.lastMonth.getTime() );
sp = ( Salesperson ) session.createQuery( "from Salesperson as s where s.id =
:id" )
.setLong( "id", testData.steveId.longValue() )
@@ -152,7 +152,6 @@
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
// HQL test
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
- log.info( "Starting HQL filter tests" );
TestData testData = new TestData();
testData.prepare();
@@ -162,13 +161,11 @@
session.enableFilter( "effectiveDate" )
.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();
assertTrue( "Incorrect filtered HQL result count [" + results.size() +
"]", results.size() == 1 );
Salesperson result = ( Salesperson ) results.get( 0 );
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();
assertTrue( results.size() == 1 );
@@ -180,7 +177,6 @@
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
// Criteria-query test
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
- log.info( "Starting Criteria-query filter tests" );
TestData testData = new TestData();
testData.prepare();
@@ -193,16 +189,14 @@
session.enableFilter( "effectiveDate" )
.setParameter( "asOfDate", testData.lastMonth.getTime() );
- log.info( "Criteria query against Salesperson..." );
List salespersons = session.createCriteria( Salesperson.class )
.setFetchMode( "orders", FetchMode.JOIN )
.list();
assertEquals( "Incorrect salesperson count", 1, salespersons.size() );
assertEquals( "Incorrect order count", 1, ( ( Salesperson ) salespersons.get(
0 ) ).getOrders().size() );
- log.info( "Criteria query against Product..." );
List products = session.createCriteria( Product.class )
- .add( Expression.eq( "stockNumber", new Integer( 124 ) ) )
+ .add( Restrictions.eq( "stockNumber", new Integer( 124 ) ) )
.list();
assertEquals( "Incorrect product count", 1, products.size() );
@@ -210,18 +204,292 @@
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() {
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
// Get() test
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
- log.info( "Starting get() filter tests (eager assoc. fetching)." );
TestData testData = new TestData();
testData.prepare();
Session session = openSession();
session.enableFilter( "region" ).setParameter( "region",
"APAC" );
- log.info( "Performing get()..." );
Salesperson salesperson = ( Salesperson ) session.get( Salesperson.class,
testData.steveId );
assertNotNull( salesperson );
assertEquals( "Incorrect order count", 1, salesperson.getOrders().size() );
@@ -234,7 +502,6 @@
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
// one-to-many loading tests
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
- log.info( "Starting one-to-many collection loader filter tests." );
TestData testData = new TestData();
testData.prepare();
@@ -242,7 +509,6 @@
session.enableFilter( "seniorSalespersons" )
.setParameter( "asOfDate", testData.lastMonth.getTime() );
- log.info( "Performing load of Department..." );
Department department = ( Department ) session.load( Department.class, testData.deptId
);
Set salespersons = department.getSalespersons();
assertEquals( "Incorrect salesperson count", 1, salespersons.size() );
@@ -255,7 +521,6 @@
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
// one-to-many loading tests
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
- log.info( "Starting one-to-many collection loader filter tests." );
TestData testData = new TestData();
testData.prepare();
@@ -263,7 +528,6 @@
session.enableFilter( "regionlist" )
.setParameterList( "regions", new String[]{"LA",
"APAC"} );
- log.debug( "Performing query of Salespersons" );
List salespersons = session.createQuery( "from Salesperson" ).list();
assertEquals( "Incorrect salesperson count", 1, salespersons.size() );
@@ -280,7 +544,7 @@
Product prod = ( Product ) session.createCriteria( Product.class )
.setResultTransformer( new DistinctRootEntityResultTransformer() )
- .add( Expression.eq( "id", testData.prod1Id ) )
+ .add( Restrictions.eq( "id", testData.prod1Id ) )
.uniqueResult();
assertNotNull( prod );
@@ -420,7 +684,7 @@
Session session = openSession();
List result = session.createCriteria( Product.class )
- .add( Expression.eq( "id", testData.prod1Id ) )
+ .add( Restrictions.eq( "id", testData.prod1Id ) )
.list();
Product prod = ( Product ) result.get( 0 );
Added: core/branches/Branch_3_2/test/org/hibernate/test/filter/hql/Basic.hbm.xml
===================================================================
--- core/branches/Branch_3_2/test/org/hibernate/test/filter/hql/Basic.hbm.xml
(rev 0)
+++ core/branches/Branch_3_2/test/org/hibernate/test/filter/hql/Basic.hbm.xml 2008-10-01
19:32:11 UTC (rev 15240)
@@ -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>
Added:
core/branches/Branch_3_2/test/org/hibernate/test/filter/hql/BasicFilteredBulkManipulationTest.java
===================================================================
---
core/branches/Branch_3_2/test/org/hibernate/test/filter/hql/BasicFilteredBulkManipulationTest.java
(rev 0)
+++
core/branches/Branch_3_2/test/org/hibernate/test/filter/hql/BasicFilteredBulkManipulationTest.java 2008-10-01
19:32:11 UTC (rev 15240)
@@ -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();
+ }
+}
Added: core/branches/Branch_3_2/test/org/hibernate/test/filter/hql/Customer.java
===================================================================
--- core/branches/Branch_3_2/test/org/hibernate/test/filter/hql/Customer.java
(rev 0)
+++ core/branches/Branch_3_2/test/org/hibernate/test/filter/hql/Customer.java 2008-10-01
19:32:11 UTC (rev 15240)
@@ -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;
+ }
+}
Added: core/branches/Branch_3_2/test/org/hibernate/test/filter/hql/Employee.java
===================================================================
--- core/branches/Branch_3_2/test/org/hibernate/test/filter/hql/Employee.java
(rev 0)
+++ core/branches/Branch_3_2/test/org/hibernate/test/filter/hql/Employee.java 2008-10-01
19:32:11 UTC (rev 15240)
@@ -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;
+ }
+}
Added: core/branches/Branch_3_2/test/org/hibernate/test/filter/hql/Joined.hbm.xml
===================================================================
--- core/branches/Branch_3_2/test/org/hibernate/test/filter/hql/Joined.hbm.xml
(rev 0)
+++ core/branches/Branch_3_2/test/org/hibernate/test/filter/hql/Joined.hbm.xml 2008-10-01
19:32:11 UTC (rev 15240)
@@ -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>
Added:
core/branches/Branch_3_2/test/org/hibernate/test/filter/hql/JoinedFilteredBulkManipulationTest.java
===================================================================
---
core/branches/Branch_3_2/test/org/hibernate/test/filter/hql/JoinedFilteredBulkManipulationTest.java
(rev 0)
+++
core/branches/Branch_3_2/test/org/hibernate/test/filter/hql/JoinedFilteredBulkManipulationTest.java 2008-10-01
19:32:11 UTC (rev 15240)
@@ -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();
+ }
+}
Added: core/branches/Branch_3_2/test/org/hibernate/test/filter/hql/Person.java
===================================================================
--- core/branches/Branch_3_2/test/org/hibernate/test/filter/hql/Person.java
(rev 0)
+++ core/branches/Branch_3_2/test/org/hibernate/test/filter/hql/Person.java 2008-10-01
19:32:11 UTC (rev 15240)
@@ -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;
+ }
+}
Added: core/branches/Branch_3_2/test/org/hibernate/test/filter/hql/User.java
===================================================================
--- core/branches/Branch_3_2/test/org/hibernate/test/filter/hql/User.java
(rev 0)
+++ core/branches/Branch_3_2/test/org/hibernate/test/filter/hql/User.java 2008-10-01
19:32:11 UTC (rev 15240)
@@ -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;
+ }
+}
Added: core/branches/Branch_3_2/test/org/hibernate/test/filter/hql/filter-defs.hbm.xml
===================================================================
--- core/branches/Branch_3_2/test/org/hibernate/test/filter/hql/filter-defs.hbm.xml
(rev 0)
+++
core/branches/Branch_3_2/test/org/hibernate/test/filter/hql/filter-defs.hbm.xml 2008-10-01
19:32:11 UTC (rev 15240)
@@ -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>