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. // oddly most database in fact seem to, so true is the default.
return true; 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

@ -59,6 +59,8 @@ import org.hibernate.type.descriptor.sql.SqlTypeDescriptor;
*/ */
public class Oracle8iDialect extends Dialect { public class Oracle8iDialect extends Dialect {
private static final int PARAM_LIST_SIZE_LIMIT = 1000;
public Oracle8iDialect() { public Oracle8iDialect() {
super(); super();
registerCharacterTypeMappings(); registerCharacterTypeMappings();
@ -551,15 +553,30 @@ public class Oracle8iDialect extends Dialect {
return false; return false;
} }
// Overridden informational metadata ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
@Override @Override
public boolean supportsEmptyInList() { public boolean supportsEmptyInList() {
return false; return false;
} }
@Override @Override
public boolean supportsExistsInSelect() { public boolean supportsExistsInSelect() {
return false; 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

@ -53,6 +53,8 @@ import org.hibernate.type.StandardBasicTypes;
@Deprecated @Deprecated
public class Oracle9Dialect extends Dialect { 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()); private static final CoreMessageLogger LOG = Logger.getMessageLogger(CoreMessageLogger.class, Oracle9Dialect.class.getName());
public Oracle9Dialect() { public Oracle9Dialect() {
@ -360,9 +362,6 @@ public class Oracle9Dialect extends Dialect {
return false; return false;
} }
// Overridden informational metadata ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
public boolean supportsEmptyInList() { public boolean supportsEmptyInList() {
return false; return false;
} }
@ -370,4 +369,20 @@ public class Oracle9Dialect extends Dialect {
public boolean supportsExistsInSelect() { public boolean supportsExistsInSelect() {
return false; 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

@ -40,6 +40,8 @@ import org.hibernate.type.descriptor.sql.SqlTypeDescriptor;
*/ */
public class SQLServerDialect extends AbstractTransactSQLDialect { public class SQLServerDialect extends AbstractTransactSQLDialect {
private static final int PARAM_LIST_SIZE_LIMIT = 2100;
public SQLServerDialect() { public SQLServerDialect() {
registerColumnType( Types.VARBINARY, "image" ); registerColumnType( Types.VARBINARY, "image" );
registerColumnType( Types.VARBINARY, 8000, "varbinary($l)" ); registerColumnType( Types.VARBINARY, 8000, "varbinary($l)" );
@ -188,5 +190,21 @@ public class SQLServerDialect extends AbstractTransactSQLDialect {
protected SqlTypeDescriptor getSqlTypeDescriptorOverride( int sqlCode ) { protected SqlTypeDescriptor getSqlTypeDescriptorOverride( int sqlCode ) {
return sqlCode == Types.TINYINT ? SmallIntTypeDescriptor.INSTANCE : super.getSqlTypeDescriptorOverride(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) * A SQL dialect suitable for use with Sybase 11.9.2 (specifically: avoids ANSI JOIN syntax)
* @author Colm O' Flaherty * @author Colm O' Flaherty
*/ */
public class Sybase11Dialect extends AbstractTransactSQLDialect { public class Sybase11Dialect extends SybaseDialect {
public Sybase11Dialect() { public Sybase11Dialect() {
super(); super();
} }

View File

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

View File

@ -30,7 +30,7 @@ package org.hibernate.dialect;
* (Tested on ASA 8.x) * (Tested on ASA 8.x)
* @author ? * @author ?
*/ */
public class SybaseAnywhereDialect extends AbstractTransactSQLDialect { public class SybaseAnywhereDialect extends SybaseDialect {
/** /**
* Sybase Anywhere syntax would require a "DEFAULT" for each column specified, * 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 * 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 * All Sybase dialects share an IN list size limit.
* 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.
* *
* @deprecated use {@link AbstractTransactSQLDialect}, {@link SybaseASE15Dialect} or {@link SQLServerDialect} * @author Brett Meyer
* instead depending on need.
*
* @author Gail Badner
*/ */
public class SybaseDialect extends AbstractTransactSQLDialect { 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

@ -38,6 +38,8 @@ import org.hibernate.type.StandardBasicTypes;
*/ */
public class TeradataDialect extends Dialect { public class TeradataDialect extends Dialect {
private static final int PARAM_LIST_SIZE_LIMIT = 1024;
/** /**
* Constructor * Constructor
*/ */
@ -256,4 +258,20 @@ public class TeradataDialect extends Dialect {
public boolean supportsBindAsCallableArgument() { public boolean supportsBindAsCallableArgument() {
return false; 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.Query;
import org.hibernate.QueryException; import org.hibernate.QueryException;
import org.hibernate.Session; import org.hibernate.Session;
import org.hibernate.dialect.Dialect;
import org.hibernate.engine.query.spi.ParameterMetadata; import org.hibernate.engine.query.spi.ParameterMetadata;
import org.hibernate.engine.spi.QueryParameters; import org.hibernate.engine.spi.QueryParameters;
import org.hibernate.engine.spi.RowSelection; import org.hibernate.engine.spi.RowSelection;
@ -65,6 +66,7 @@ import org.hibernate.transform.ResultTransformer;
import org.hibernate.type.SerializableType; import org.hibernate.type.SerializableType;
import org.hibernate.type.StandardBasicTypes; import org.hibernate.type.StandardBasicTypes;
import org.hibernate.type.Type; import org.hibernate.type.Type;
import org.jboss.logging.Logger;
/** /**
* Abstract implementation of the Query interface. * Abstract implementation of the Query interface.
@ -73,6 +75,7 @@ import org.hibernate.type.Type;
* @author Max Andersen * @author Max Andersen
*/ */
public abstract class AbstractQueryImpl implements Query { 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_PARAMETER = new MarkerObject("<unset parameter>");
private static final Object UNSET_TYPE = new MarkerObject("<unset type>"); 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) { private String expandParameterList(String query, String name, TypedValue typedList, Map namedParamsCopy) {
Collection vals = (Collection) typedList.getValue(); 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(); Type type = typedList.getType();
boolean isJpaPositionalParam = parameterMetadata.getNamedParameterDescriptor( name ).isJpaStyle(); boolean isJpaPositionalParam = parameterMetadata.getNamedParameterDescriptor( name ).isJpaStyle();

View File

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