HHH-1123 Cannot put more than 1000 elements in a InExpression

This commit is contained in:
brmeyer 2012-09-04 18:41:51 -04:00 committed by Steve Ebersole
parent 6ac746fffc
commit 970bd8679e
11 changed files with 141 additions and 23 deletions

View File

@ -2365,4 +2365,24 @@ public abstract class Dialect implements ConversionContext {
// oddly most database in fact seem to, so true is the default.
return true;
}
/**
* Does this databases restrict the number of parameters in a query list?
*
* @return boolean
* True if limited, false if not.
*/
public boolean limitsParamListSize() {
return false;
}
/**
* If limitsListSize() is true, define the size threshold.
*
* @return int
* The list size threshold
*/
public int getParamListSizeLimit() {
return 0;
}
}

View File

@ -58,6 +58,8 @@ import org.hibernate.type.descriptor.sql.SqlTypeDescriptor;
* @author Steve Ebersole
*/
public class Oracle8iDialect extends Dialect {
private static final int PARAM_LIST_SIZE_LIMIT = 1000;
public Oracle8iDialect() {
super();
@ -551,15 +553,30 @@ public class Oracle8iDialect extends Dialect {
return false;
}
// Overridden informational metadata ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
@Override
public boolean supportsEmptyInList() {
return false;
}
@Override
public boolean supportsExistsInSelect() {
return false;
}
/* (non-Javadoc)
* @see org.hibernate.dialect.Dialect#limitsParamListSize()
*/
@Override
public boolean limitsParamListSize() {
return true;
}
/* (non-Javadoc)
* @see org.hibernate.dialect.Dialect#getParamListSizeLimit()
*/
@Override
public int getParamListSizeLimit() {
return PARAM_LIST_SIZE_LIMIT;
}
}

View File

@ -52,6 +52,8 @@ import org.hibernate.type.StandardBasicTypes;
*/
@Deprecated
public class Oracle9Dialect extends Dialect {
private static final int PARAM_LIST_SIZE_LIMIT = 1000;
private static final CoreMessageLogger LOG = Logger.getMessageLogger(CoreMessageLogger.class, Oracle9Dialect.class.getName());
@ -360,9 +362,6 @@ public class Oracle9Dialect extends Dialect {
return false;
}
// Overridden informational metadata ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
public boolean supportsEmptyInList() {
return false;
}
@ -370,4 +369,20 @@ public class Oracle9Dialect extends Dialect {
public boolean supportsExistsInSelect() {
return false;
}
/* (non-Javadoc)
* @see org.hibernate.dialect.Dialect#limitsParamListSize()
*/
@Override
public boolean limitsParamListSize() {
return true;
}
/* (non-Javadoc)
* @see org.hibernate.dialect.Dialect#getParamListSizeLimit()
*/
@Override
public int getParamListSizeLimit() {
return PARAM_LIST_SIZE_LIMIT;
}
}

View File

@ -39,6 +39,8 @@ import org.hibernate.type.descriptor.sql.SqlTypeDescriptor;
* @author Gavin King
*/
public class SQLServerDialect extends AbstractTransactSQLDialect {
private static final int PARAM_LIST_SIZE_LIMIT = 2100;
public SQLServerDialect() {
registerColumnType( Types.VARBINARY, "image" );
@ -188,5 +190,21 @@ public class SQLServerDialect extends AbstractTransactSQLDialect {
protected SqlTypeDescriptor getSqlTypeDescriptorOverride( int sqlCode ) {
return sqlCode == Types.TINYINT ? SmallIntTypeDescriptor.INSTANCE : super.getSqlTypeDescriptorOverride(sqlCode);
}
/* (non-Javadoc)
* @see org.hibernate.dialect.Dialect#limitsParamListSize()
*/
@Override
public boolean limitsParamListSize() {
return true;
}
/* (non-Javadoc)
* @see org.hibernate.dialect.Dialect#getParamListSizeLimit()
*/
@Override
public int getParamListSizeLimit() {
return PARAM_LIST_SIZE_LIMIT;
}
}

View File

@ -29,7 +29,7 @@ import org.hibernate.sql.Sybase11JoinFragment;
* A SQL dialect suitable for use with Sybase 11.9.2 (specifically: avoids ANSI JOIN syntax)
* @author Colm O' Flaherty
*/
public class Sybase11Dialect extends AbstractTransactSQLDialect {
public class Sybase11Dialect extends SybaseDialect {
public Sybase11Dialect() {
super();
}

View File

@ -40,7 +40,7 @@ import org.hibernate.type.descriptor.sql.TinyIntTypeDescriptor;
*
* @author Gavin King
*/
public class SybaseASE15Dialect extends AbstractTransactSQLDialect {
public class SybaseASE15Dialect extends SybaseDialect {
public SybaseASE15Dialect() {
super();

View File

@ -30,7 +30,7 @@ package org.hibernate.dialect;
* (Tested on ASA 8.x)
* @author ?
*/
public class SybaseAnywhereDialect extends AbstractTransactSQLDialect {
public class SybaseAnywhereDialect extends SybaseDialect {
/**
* Sybase Anywhere syntax would require a "DEFAULT" for each column specified,
* but I suppose Hibernate use this syntax only with tables with just 1 column

View File

@ -25,16 +25,27 @@ package org.hibernate.dialect;
/**
* This dialect is being deprecated; it had been used both as the base class
* for TransactSQL-based dialects as well as the physical dialect for handling
* Sybase. Those functions have now been split.
* {@link AbstractTransactSQLDialect} should be used as the base class for
* TransactSQL-based dialects.
* All Sybase dialects share an IN list size limit.
*
* @deprecated use {@link AbstractTransactSQLDialect}, {@link SybaseASE15Dialect} or {@link SQLServerDialect}
* instead depending on need.
*
* @author Gail Badner
* @author Brett Meyer
*/
public class SybaseDialect extends AbstractTransactSQLDialect {
private static final int PARAM_LIST_SIZE_LIMIT = 250000;
/* (non-Javadoc)
* @see org.hibernate.dialect.Dialect#limitsParamListSize()
*/
@Override
public boolean limitsParamListSize() {
return true;
}
/* (non-Javadoc)
* @see org.hibernate.dialect.Dialect#getParamListSizeLimit()
*/
@Override
public int getParamListSizeLimit() {
return PARAM_LIST_SIZE_LIMIT;
}
}

View File

@ -37,6 +37,8 @@ import org.hibernate.type.StandardBasicTypes;
* @author Jay Nance
*/
public class TeradataDialect extends Dialect {
private static final int PARAM_LIST_SIZE_LIMIT = 1024;
/**
* Constructor
@ -256,4 +258,20 @@ public class TeradataDialect extends Dialect {
public boolean supportsBindAsCallableArgument() {
return false;
}
/* (non-Javadoc)
* @see org.hibernate.dialect.Dialect#limitsParamListSize()
*/
@Override
public boolean limitsParamListSize() {
return true;
}
/* (non-Javadoc)
* @see org.hibernate.dialect.Dialect#getParamListSizeLimit()
*/
@Override
public int getParamListSizeLimit() {
return PARAM_LIST_SIZE_LIMIT;
}
}

View File

@ -49,6 +49,7 @@ import org.hibernate.PropertyNotFoundException;
import org.hibernate.Query;
import org.hibernate.QueryException;
import org.hibernate.Session;
import org.hibernate.dialect.Dialect;
import org.hibernate.engine.query.spi.ParameterMetadata;
import org.hibernate.engine.spi.QueryParameters;
import org.hibernate.engine.spi.RowSelection;
@ -65,6 +66,7 @@ import org.hibernate.transform.ResultTransformer;
import org.hibernate.type.SerializableType;
import org.hibernate.type.StandardBasicTypes;
import org.hibernate.type.Type;
import org.jboss.logging.Logger;
/**
* Abstract implementation of the Query interface.
@ -73,6 +75,7 @@ import org.hibernate.type.Type;
* @author Max Andersen
*/
public abstract class AbstractQueryImpl implements Query {
private static final Logger log = Logger.getLogger( AbstractQueryImpl.class );
private static final Object UNSET_PARAMETER = new MarkerObject("<unset parameter>");
private static final Object UNSET_TYPE = new MarkerObject("<unset type>");
@ -798,6 +801,22 @@ public abstract class AbstractQueryImpl implements Query {
*/
private String expandParameterList(String query, String name, TypedValue typedList, Map namedParamsCopy) {
Collection vals = (Collection) typedList.getValue();
// HHH-1123
// Some DBs limit the size of param lists. For now, warn...
//
// TODO: HHH-1123 was rejected, but this issue may still deserve some
// research.
Dialect dialect = session.getFactory().getDialect();
if (dialect.limitsParamListSize()
&& vals.size() >= dialect.getParamListSizeLimit()) {
log.warn(dialect.getClass().getName()
+ " limits the size of parameter lists to "
+ dialect.getParamListSizeLimit()
+ " entries. The given list size of "
+ vals.size() + " may cause failures.");
}
Type type = typedList.getType();
boolean isJpaPositionalParam = parameterMetadata.getNamedParameterDescriptor( name ).isJpaStyle();

View File

@ -22,11 +22,11 @@
* Boston, MA 02110-1301 USA
*/
package org.hibernate.test.criteria;
import static org.junit.Assert.assertEquals;
import java.util.ArrayList;
import java.util.List;
import org.junit.Test;
import org.hibernate.Criteria;
import org.hibernate.Query;
import org.hibernate.Session;
@ -34,13 +34,13 @@ import org.hibernate.Transaction;
import org.hibernate.criterion.Restrictions;
import org.hibernate.dialect.Oracle8iDialect;
import org.hibernate.dialect.SQLServerDialect;
import org.hibernate.dialect.SybaseDialect;
import org.hibernate.dialect.TeradataDialect;
import org.hibernate.test.hql.StateProvince;
import org.hibernate.testing.SkipForDialect;
import org.hibernate.testing.TestForIssue;
import org.hibernate.testing.junit4.BaseCoreFunctionalTestCase;
import static org.junit.Assert.assertEquals;
import org.junit.Test;
/**
* HHH-2166 Long "in" lists in queries results in a Java stack overflow
@ -60,7 +60,7 @@ public class LongInElementsTest extends BaseCoreFunctionalTestCase {
@Test
@TestForIssue( jiraKey = "HHH-2166" )
@SkipForDialect(
value = { SQLServerDialect.class, Oracle8iDialect.class, TeradataDialect.class },
value = { SQLServerDialect.class, Oracle8iDialect.class, TeradataDialect.class, SybaseDialect.class },
comment = "this test fails on oracle and ms sql server, for more info, see HHH-1123"
)
public void testLongInElementsByHQL() {
@ -90,7 +90,7 @@ public class LongInElementsTest extends BaseCoreFunctionalTestCase {
@Test
@TestForIssue( jiraKey = "HHH-2166" )
@SkipForDialect(
value = { SQLServerDialect.class, Oracle8iDialect.class, TeradataDialect.class },
value = { SQLServerDialect.class, Oracle8iDialect.class, TeradataDialect.class, SybaseDialect.class },
comment = "this test fails on oracle and ms sql server, for more info, see HHH-1123"
)
public void testLongInElementsByCriteria() {