Get rid of RowSelection, QueryParameters and related deprecated functionality

This commit is contained in:
Christian Beikov 2021-09-30 19:57:01 +02:00
parent 1246a22c83
commit f416b728a9
27 changed files with 8 additions and 1885 deletions

View File

@ -8,7 +8,6 @@ package org.hibernate.community.dialect.pagination;
import org.hibernate.dialect.pagination.AbstractLimitHandler;
import org.hibernate.dialect.pagination.LimitHandler;
import org.hibernate.engine.spi.RowSelection;
import org.hibernate.query.Limit;
/**
@ -25,40 +24,6 @@ public class SkipFirstLimitHandler extends AbstractLimitHandler {
this.variableLimit = variableLimit;
}
@Override
public String processSql(String sql, RowSelection selection) {
boolean hasFirstRow = hasFirstRow( selection );
boolean hasMaxRows = hasMaxRows( selection );
if ( !hasFirstRow && !hasMaxRows ) {
return sql;
}
StringBuilder skipFirst = new StringBuilder();
if ( supportsVariableLimit() ) {
if ( hasFirstRow ) {
skipFirst.append( " skip ?" );
}
if ( hasMaxRows ) {
skipFirst.append( " first ?" );
}
}
else {
if ( hasFirstRow ) {
skipFirst.append( " skip " )
.append( selection.getFirstRow() );
}
if ( hasMaxRows ) {
skipFirst.append( " first " )
.append( getMaxOrLimit( selection ) );
}
}
return insertAfterSelect( sql, skipFirst.toString() );
}
@Override
public String processSql(String sql, Limit limit) {

View File

@ -11,7 +11,6 @@ import java.sql.SQLException;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import org.hibernate.engine.spi.RowSelection;
import org.hibernate.query.Limit;
import static java.util.regex.Pattern.CASE_INSENSITIVE;
@ -121,7 +120,7 @@ public abstract class AbstractLimitHandler implements LimitHandler {
* specified in the offset clause?
* <p/>
* NOTE: what gets passed into
* {@link AbstractLimitHandler#processSql(String, RowSelection)}
* {@link AbstractLimitHandler#processSql(String, Limit)}
* is the zero-based offset. Handlers which do not {@link #supportsVariableLimit}
* should take care to perform any needed first-row-conversion calls prior
* to injecting the limit values into the SQL string.
@ -134,142 +133,6 @@ public abstract class AbstractLimitHandler implements LimitHandler {
return zeroBasedFirstResult;
}
@Override
public String processSql(String sql, RowSelection selection) {
throw new UnsupportedOperationException( "Paged queries not supported by " + getClass().getName() );
}
@Override
public int bindLimitParametersAtStartOfQuery(RowSelection selection, PreparedStatement statement, int index)
throws SQLException {
return bindLimitParametersFirst()
? bindLimitParameters( selection, statement, index )
: 0;
}
@Override
public int bindLimitParametersAtEndOfQuery(RowSelection selection, PreparedStatement statement, int index)
throws SQLException {
return !bindLimitParametersFirst()
? bindLimitParameters( selection, statement, index )
: 0;
}
@Override
public void setMaxRows(RowSelection selection, PreparedStatement statement) throws SQLException {
}
/**
* Default implementation of binding parameter values needed by the LIMIT clause.
*
* @param selection the selection criteria for rows.
* @param statement Statement to which to bind limit parameter values.
* @param index Index from which to start binding.
* @return The number of parameter values bound.
* @throws SQLException Indicates problems binding parameter values.
*/
protected final int bindLimitParameters(RowSelection selection, PreparedStatement statement, int index)
throws SQLException {
if ( !supportsVariableLimit() ) {
//never any parameters to bind
return 0;
}
final boolean hasMaxRows = hasMaxRows( selection );
final boolean hasFirstRow = hasFirstRow( selection );
final boolean bindLimit
= hasMaxRows && supportsLimit()
|| forceLimitUsage();
final boolean bindOffset
= hasFirstRow && supportsOffset()
|| hasFirstRow && hasMaxRows && supportsLimitOffset();
if ( !bindLimit && !bindOffset ) {
//no parameters to bind this time
return 0;
}
final boolean reverse = bindLimitParametersInReverseOrder();
if ( bindOffset ) {
statement.setInt(
index + ( reverse || !bindLimit ? 1 : 0 ),
getFirstRow( selection )
);
}
if ( bindLimit ) {
statement.setInt(
index + ( reverse || !bindOffset ? 0 : 1 ),
getMaxOrLimit( selection )
);
}
return bindOffset && bindLimit ? 2 : 1;
}
/**
* Is a max row limit indicated?
*
* @param selection The row selection options
*
* @return Whether a max row limit was indicated
*/
public static boolean hasMaxRows(RowSelection selection) {
return selection != null
&& selection.getMaxRows() != null
&& selection.getMaxRows() > 0;
}
/**
* Is a first row limit indicated?
*
* @param selection The row selection options
*
* @return Whether a first row limit was indicated
*/
public static boolean hasFirstRow(RowSelection selection) {
return selection != null
&& selection.getFirstRow() != null
&& selection.getFirstRow() > 0;
}
/**
* Some dialect-specific LIMIT clauses require the maximum last row number
* (aka, first_row_number + total_row_count), while others require the maximum
* returned row count (the total maximum number of rows to return).
*
* @param selection the selection criteria for rows.
*
* @return The appropriate value to bind into the limit clause.
*/
protected final int getMaxOrLimit(RowSelection selection) {
if ( selection == null || selection.getMaxRows() == null ) {
return Integer.MAX_VALUE;
}
final int firstRow = getFirstRow( selection );
final int maxRows = selection.getMaxRows();
final int maxOrLimit = useMaxForLimit()
? maxRows + firstRow //TODO: maxRows + firstRow - 1, surely?
: maxRows;
// Use Integer.MAX_VALUE on overflow
return maxOrLimit < 0 ? Integer.MAX_VALUE : maxOrLimit;
}
/**
* Retrieve the indicated first row for pagination
*
* @param selection The row selection options
*
* @return The first row
*/
protected final int getFirstRow(RowSelection selection) {
if ( selection == null || selection.getFirstRow() == null ) {
return 0;
}
return convertToFirstRowValue( selection.getFirstRow() );
}
@Override
public String processSql(String sql, Limit limit) {

View File

@ -6,7 +6,6 @@
*/
package org.hibernate.dialect.pagination;
import org.hibernate.engine.spi.RowSelection;
import org.hibernate.query.Limit;
import static java.lang.String.valueOf;
@ -33,19 +32,6 @@ public abstract class AbstractNoOffsetLimitHandler extends AbstractLimitHandler
protected abstract String insert(String limitClause, String sql);
@Override
public String processSql(String sql, RowSelection selection) {
if ( !hasMaxRows( selection ) ) {
return sql;
}
String limitClause = limitClause();
if ( !supportsVariableLimit() ) {
String limitLiteral = valueOf( getMaxOrLimit(selection) );
limitClause = limitClause.replace( "?", limitLiteral );
}
return insert( limitClause, sql );
}
@Override
public String processSql(String sql, Limit limit) {
if ( !hasMaxRows( limit ) ) {

View File

@ -6,7 +6,6 @@
*/
package org.hibernate.dialect.pagination;
import org.hibernate.engine.spi.RowSelection;
import org.hibernate.query.Limit;
/**
@ -19,14 +18,6 @@ public abstract class AbstractSimpleLimitHandler extends AbstractLimitHandler {
protected abstract String limitClause(boolean hasFirstRow);
@Override
public String processSql(String sql, RowSelection selection) {
if ( !hasMaxRows( selection ) ) {
return sql;
}
return insert( limitClause( hasFirstRow( selection ) ), sql );
}
@Override
public String processSql(String sql, Limit limit) {
if ( !hasMaxRows( limit ) ) {

View File

@ -6,7 +6,6 @@
*/
package org.hibernate.dialect.pagination;
import org.hibernate.engine.spi.RowSelection;
import org.hibernate.query.Limit;
/**
@ -18,27 +17,6 @@ public class LegacyDB2LimitHandler extends AbstractLimitHandler {
public static final LegacyDB2LimitHandler INSTANCE = new LegacyDB2LimitHandler();
@Override
public String processSql(String sql, RowSelection selection) {
if ( hasFirstRow( selection ) ) {
//nest the main query in an outer select
return "select * from (select row_.*,rownumber() over(order by order of row_) as rownumber_ from ("
+ sql + fetchFirstRows( selection )
+ ") as row_) as query_ where rownumber_>"
+ selection.getFirstRow()
+ " order by rownumber_";
}
else {
//on DB2, offset/fetch comes after all the
//various "for update"ish clauses
return insertAtEnd( fetchFirstRows( selection ), sql );
}
}
private String fetchFirstRows(RowSelection limit) {
return " fetch first " + getMaxOrLimit( limit ) + " rows only";
}
@Override
public String processSql(String sql, Limit limit) {
if ( hasFirstRow( limit ) ) {

View File

@ -7,7 +7,6 @@
package org.hibernate.dialect.pagination;
import org.hibernate.dialect.Dialect;
import org.hibernate.engine.spi.RowSelection;
import org.hibernate.query.Limit;
/**
@ -67,22 +66,6 @@ public class LegacyLimitHandler extends AbstractLimitHandler {
return dialect.convertToFirstRowValue( zeroBasedFirstResult );
}
@Override
public String processSql(String sql, RowSelection selection) {
final boolean useLimitOffset
= supportsOffset()
&& hasFirstRow( selection )
|| supportsLimit()
&& supportsLimitOffset()
&& hasFirstRow( selection )
&& hasMaxRows( selection );
return dialect.getLimitString(
sql,
useLimitOffset ? getFirstRow( selection ) : 0,
getMaxOrLimit( selection )
);
}
@Override
public String processSql(String sql, Limit limit) {
final boolean useLimitOffset

View File

@ -6,7 +6,6 @@
*/
package org.hibernate.dialect.pagination;
import org.hibernate.engine.spi.RowSelection;
import org.hibernate.query.Limit;
import java.util.regex.Matcher;
@ -22,41 +21,6 @@ public class LegacyOracleLimitHandler extends AbstractLimitHandler {
this.version = version;
}
@Override
public String processSql(String sql, RowSelection selection) {
final boolean hasOffset = hasFirstRow( selection );
sql = sql.trim();
String forUpdateClause = null;
Matcher forUpdateMatcher = getForUpdatePattern().matcher( sql );
if ( forUpdateMatcher.find() ) {
int forUpdateIndex = forUpdateMatcher.start();
// save 'for update ...' and then remove it
forUpdateClause = sql.substring( forUpdateIndex );
sql = sql.substring( 0, forUpdateIndex );
}
final StringBuilder pagingSelect = new StringBuilder( sql.length() + 100 );
if ( hasOffset ) {
pagingSelect.append( "select * from (select row_.*,rownum rownum_ from (" ).append( sql );
if ( version < 900 ) {
pagingSelect.append( ") row_) where rownum_<=? and rownum_>?" );
}
else {
pagingSelect.append( ") row_ where rownum<=?) where rownum_>?" );
}
}
else {
pagingSelect.append( "select * from (" ).append( sql ).append( ") where rownum<=?" );
}
if ( forUpdateClause != null ) {
pagingSelect.append( forUpdateClause );
}
return pagingSelect.toString();
}
@Override
public String processSql(String sql, Limit limit) {
final boolean hasOffset = hasFirstRow( limit );

View File

@ -9,8 +9,6 @@ package org.hibernate.dialect.pagination;
import java.sql.PreparedStatement;
import java.sql.SQLException;
import org.hibernate.engine.spi.QueryParameters;
import org.hibernate.engine.spi.RowSelection;
import org.hibernate.query.Limit;
import org.hibernate.query.spi.QueryOptions;
@ -43,139 +41,16 @@ public interface LimitHandler {
*/
boolean supportsLimitOffset();
default String processSql(String sql, Limit limit) {
return processSql(
sql,
limit == null ? null : new RowSelection(
limit.getFirstRow(),
limit.getMaxRows(),
null,
null
)
);
}
String processSql(String sql, Limit limit);
default String processSql(String sql, Limit limit, QueryOptions queryOptions) {
return processSql(
sql,
limit == null ? null : new RowSelection(
limit.getFirstRow(),
limit.getMaxRows(),
null,
null
)
);
return processSql( sql, limit );
}
default int bindLimitParametersAtStartOfQuery(Limit limit, PreparedStatement statement, int index)
throws SQLException {
return bindLimitParametersAtStartOfQuery(
limit == null ? null : new RowSelection(
limit.getFirstRow(),
limit.getMaxRows(),
null,
null
),
statement,
index
);
}
int bindLimitParametersAtStartOfQuery(Limit limit, PreparedStatement statement, int index) throws SQLException;
default int bindLimitParametersAtEndOfQuery(Limit limit, PreparedStatement statement, int index)
throws SQLException {
return bindLimitParametersAtEndOfQuery(
limit == null ? null : new RowSelection(
limit.getFirstRow(),
limit.getMaxRows(),
null,
null
),
statement,
index
);
}
int bindLimitParametersAtEndOfQuery(Limit limit, PreparedStatement statement, int index) throws SQLException;
default void setMaxRows(Limit limit, PreparedStatement statement) throws SQLException {
setMaxRows(
limit == null ? null : new RowSelection(
limit.getFirstRow(),
limit.getMaxRows(),
null,
null
),
statement
);
}
void setMaxRows(Limit limit, PreparedStatement statement) throws SQLException;
/**
* Return processed SQL query.
*
* @param sql the SQL query to process.
* @param selection the selection criteria for rows.
*
* @return Query statement with LIMIT clause applied.
* @deprecated todo (6.0): remove in favor of Limit version?
*/
@Deprecated
String processSql(String sql, RowSelection selection);
/**
* Return processed SQL query.
*
* @param sql the SQL query to process.
* @param queryParameters the queryParameters.
*
* @return Query statement with LIMIT clause applied.
* @deprecated Use {@link #processSql(String, Limit, QueryOptions)}
* todo (6.0): remove in favor of Limit version?
*/
@Deprecated
default String processSql(String sql, QueryParameters queryParameters ){
return processSql( sql, queryParameters.getRowSelection() );
}
/**
* Bind parameter values needed by the limit and offset clauses
* right at the start of the original query statement, before all
* the other query parameters.
*
* @param selection the selection criteria for rows.
* @param statement Statement to which to bind limit parameter values.
* @param index Index from which to start binding.
* @return The number of parameter values bound.
* @throws SQLException Indicates problems binding parameter values.
* @deprecated todo (6.0): remove in favor of Limit version?
*/
@Deprecated
int bindLimitParametersAtStartOfQuery(RowSelection selection, PreparedStatement statement, int index)
throws SQLException;
/**
* Bind parameter values needed by the limit and offset clauses
* right at the end of the original query statement, after all
* the other query parameters.
*
* @param selection the selection criteria for rows.
* @param statement Statement to which to bind limit parameter values.
* @param index Index from which to start binding.
* @return The number of parameter values bound.
* @throws SQLException Indicates problems binding parameter values.
* @deprecated todo (6.0): remove in favor of Limit version?
*/
@Deprecated
int bindLimitParametersAtEndOfQuery(RowSelection selection, PreparedStatement statement, int index)
throws SQLException;
/**
* Use JDBC APIs to limit the number of rows returned by the SQL query.
* Handlers that do not support a SQL limit clause should implement this
* method.
*
* @param selection the selection criteria for rows.
* @param statement Statement which number of returned rows shall be limited.
* @throws SQLException Indicates problems while limiting maximum rows returned.
* @deprecated todo (6.0): remove in favor of Limit version?
*/
@Deprecated
void setMaxRows(RowSelection selection, PreparedStatement statement) throws SQLException;
}

View File

@ -8,12 +8,9 @@ package org.hibernate.dialect.pagination;
import java.sql.PreparedStatement;
import java.sql.SQLException;
import java.util.regex.Pattern;
import org.hibernate.engine.spi.RowSelection;
import org.hibernate.query.Limit;
import static java.util.regex.Pattern.CASE_INSENSITIVE;
import static java.util.regex.Pattern.compile;
/**
@ -25,37 +22,6 @@ public class NoopLimitHandler extends AbstractLimitHandler {
public static final NoopLimitHandler INSTANCE = new NoopLimitHandler();
@Override
public String processSql(String sql, RowSelection selection) {
return sql;
}
@Override
public int bindLimitParametersAtStartOfQuery(RowSelection selection, PreparedStatement statement, int index) {
return 0;
}
@Override
public int bindLimitParametersAtEndOfQuery(RowSelection selection, PreparedStatement statement, int index) {
return 0;
}
@Override
public void setMaxRows(RowSelection selection, PreparedStatement statement) throws SQLException {
if ( selection != null && selection.getMaxRows() != null && selection.getMaxRows() > 0 ) {
final int maxRows = selection.getMaxRows() + convertToFirstRowValue(
selection.getFirstRow() == null ? 0 : selection.getFirstRow()
);
// Use Integer.MAX_VALUE on overflow
if ( maxRows < 0 ) {
statement.setMaxRows( Integer.MAX_VALUE );
}
else {
statement.setMaxRows( maxRows );
}
}
}
@Override
public String processSql(String sql, Limit limit) {
return sql;

View File

@ -6,7 +6,6 @@
*/
package org.hibernate.dialect.pagination;
import org.hibernate.engine.spi.RowSelection;
import org.hibernate.query.Limit;
/**
@ -26,52 +25,6 @@ public class OffsetFetchLimitHandler extends AbstractLimitHandler {
this.variableLimit = variableLimit;
}
@Override
public String processSql(String sql, RowSelection selection) {
boolean hasFirstRow = hasFirstRow(selection);
boolean hasMaxRows = hasMaxRows(selection);
if ( !hasFirstRow && !hasMaxRows ) {
return sql;
}
StringBuilder offsetFetch = new StringBuilder();
begin(sql, offsetFetch, hasFirstRow, hasMaxRows);
if ( hasFirstRow ) {
offsetFetch.append( " offset " );
if ( supportsVariableLimit() ) {
offsetFetch.append( "?" );
}
else {
offsetFetch.append( selection.getFirstRow() );
}
if ( renderOffsetRowsKeyword() ) {
offsetFetch.append( " rows" );
}
}
if ( hasMaxRows ) {
if ( hasFirstRow ) {
offsetFetch.append( " fetch next " );
}
else {
offsetFetch.append( " fetch first " );
}
if ( supportsVariableLimit() ) {
offsetFetch.append( "?" );
}
else {
offsetFetch.append( getMaxOrLimit( selection ) );
}
offsetFetch.append( " rows only" );
}
return insert( offsetFetch.toString(), sql );
}
@Override
public String processSql(String sql, Limit limit) {

View File

@ -10,8 +10,6 @@ import java.util.Locale;
import org.hibernate.LockMode;
import org.hibernate.LockOptions;
import org.hibernate.engine.spi.QueryParameters;
import org.hibernate.engine.spi.RowSelection;
import org.hibernate.query.Limit;
import org.hibernate.query.spi.QueryOptions;
@ -33,18 +31,6 @@ public class Oracle12LimitHandler extends AbstractLimitHandler {
Oracle12LimitHandler() {
}
@Override
public String processSql(String sql, RowSelection selection) {
final boolean hasFirstRow = hasFirstRow( selection );
final boolean hasMaxRows = hasMaxRows( selection );
if ( !hasMaxRows ) {
return sql;
}
return processSql( sql, getForUpdateIndex( sql ), hasFirstRow );
}
@Override
public String processSql(String sql, Limit limit, QueryOptions queryOptions) {
final boolean hasMaxRows = hasMaxRows( limit );
@ -58,24 +44,6 @@ public class Oracle12LimitHandler extends AbstractLimitHandler {
);
}
@Override
public String processSql(String sql, QueryParameters queryParameters) {
final RowSelection selection = queryParameters.getRowSelection();
final boolean hasMaxRows = hasMaxRows( selection );
if ( !hasMaxRows ) {
return sql;
}
sql = sql.trim();
return processSql(
sql,
hasFirstRow( selection ),
queryParameters.getLockOptions()
);
}
protected String processSql(String sql, boolean hasFirstRow, LockOptions lockOptions) {
if ( lockOptions != null ) {
final LockMode lockMode = lockOptions.getLockMode();

View File

@ -13,7 +13,6 @@ import java.util.List;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import org.hibernate.engine.spi.RowSelection;
import org.hibernate.internal.util.StringHelper;
import org.hibernate.query.Limit;
@ -55,84 +54,6 @@ public class SQLServer2005LimitHandler extends AbstractLimitHandler {
return zeroBasedFirstResult + 1;
}
/**
* When the offset of the given {@link RowSelection} is {@literal 0},
* add a {@code top(?)} clause to the given SQL query. When the offset
* is non-zero, wrap the given query in an outer query that limits the
* results using the {@code row_number()} window function.
*
* <pre>
* with query_ as (
* select row_.*, row_number()
* over (order by current_timestamp) AS rownumber_
* from ( [original-query] ) row_
* )
* select [alias-list] from query_
* where rownumber_ >= ? and rownumber_ < ?
* </pre>
*
* Where {@code [original-query]} is the original SQL query, with a
* {@code top()} clause added iff the query has an {@code order by}
* clause, and with generated aliases added to any elements of the
* projection list that don't already have aliases, and
* {@code [alias-list]} is a list of aliases in the projection list.
*
* @return A new SQL statement
*/
@Override
public String processSql(String sql, RowSelection selection) {
sql = sql.trim();
if ( sql.endsWith(";") ) {
sql = sql.substring( 0, sql.length()-1 );
}
final int selectOffset = Keyword.SELECT.rootOffset( sql );
final int afterSelectOffset = Keyword.SELECT.endOffset( sql, selectOffset );
final int fromOffset = Keyword.FROM.rootOffset( sql ); //TODO: what if there is no 'from' clause?!
boolean hasCommonTables = Keyword.WITH.occursAt( sql, 0 );
boolean hasOrderBy = Keyword.ORDER_BY.rootOffset( sql ) > 0;
boolean hasFirstRow = hasFirstRow( selection );
final StringBuilder result = new StringBuilder( sql );
if ( !hasFirstRow || hasOrderBy ) {
result.insert( afterSelectOffset, " top(?)" );
topAdded = true;
}
if ( hasFirstRow ) {
// enclose original SQL statement with outer query
// that provides the rownumber_ column
String aliases = selectAliases( sql, afterSelectOffset, fromOffset, result ); //warning: changes result by side-effect
result.insert( selectOffset, ( hasCommonTables ? "," : "with" )
+ " query_ as (select row_.*,row_number() over (order by current_timestamp) as rownumber_ from (" )
.append( ") row_) select " ).append( aliases )
.append( " from query_ where rownumber_>=? and rownumber_<?" );
}
return result.toString();
}
@Override
public int bindLimitParametersAtStartOfQuery(RowSelection selection, PreparedStatement statement, int index) throws SQLException {
if ( topAdded ) {
// bind parameter to top(?)
statement.setInt( index, getMaxOrLimit( selection ) - 1 );
return 1;
}
return 0;
}
@Override
public int bindLimitParametersAtEndOfQuery(RowSelection selection, PreparedStatement statement, int index) throws SQLException {
return hasFirstRow( selection )
? super.bindLimitParametersAtEndOfQuery( selection, statement, index )
: 0;
}
/**
* When the offset of the given {@link RowSelection} is {@literal 0},
* add a {@code top(?)} clause to the given SQL query. When the offset

View File

@ -1,149 +0,0 @@
/*
* Hibernate, Relational Persistence for Idiomatic Java
*
* License: GNU Lesser General Public License (LGPL), version 2.1 or later.
* See the lgpl.txt file in the root directory or <http://www.gnu.org/licenses/lgpl-2.1.html>.
*/
package org.hibernate.engine.internal;
import java.sql.PreparedStatement;
import java.sql.SQLException;
import java.util.Iterator;
import java.util.Map;
import org.hibernate.HibernateException;
import org.hibernate.engine.spi.QueryParameters;
import org.hibernate.engine.spi.SessionImplementor;
import org.hibernate.engine.spi.TypedValue;
import org.hibernate.internal.CoreMessageLogger;
import org.hibernate.type.Type;
import org.jboss.logging.Logger;
/**
* Centralizes the commonality regarding binding of parameter values into PreparedStatements as this logic is
* used in many places.
* <p/>
* Ideally would like to move to the parameter handling as it is done in the hql.ast package.
*
* @author Steve Ebersole
*/
public class ParameterBinder {
private static final CoreMessageLogger LOG = Logger.getMessageLogger(
CoreMessageLogger.class,
ParameterBinder.class.getName()
);
/**
* Helper contract for dealing with named parameters and resolving their locations
*/
public static interface NamedParameterSource {
/**
* Retrieve the locations for the given parameter name
*
* @param name The parameter name
*
* @return The locations
*/
public int[] getNamedParameterLocations(String name);
}
private ParameterBinder() {
}
/**
* Perform parameter binding
*
* @param st The statement to bind parameters to
* @param queryParameters The parameters
* @param start The initial bind position
* @param source The named parameter source, for resolving the locations of named parameters
* @param session The session
*
* @return The next bind position after the last position we bound here.
*
* @throws SQLException Indicates a problem calling JDBC bind methods
* @throws HibernateException Indicates a problem access bind values.
*/
public static int bindQueryParameters(
final PreparedStatement st,
final QueryParameters queryParameters,
final int start,
final NamedParameterSource source,
SessionImplementor session) throws SQLException, HibernateException {
int col = start;
col += bindPositionalParameters( st, queryParameters, col, session );
col += bindNamedParameters( st, queryParameters, col, source, session );
return col;
}
private static int bindPositionalParameters(
final PreparedStatement st,
final QueryParameters queryParameters,
final int start,
final SessionImplementor session) throws SQLException, HibernateException {
return bindPositionalParameters(
st,
queryParameters.getPositionalParameterValues(),
queryParameters.getPositionalParameterTypes(),
start,
session
);
}
private static int bindPositionalParameters(
final PreparedStatement st,
final Object[] values,
final Type[] types,
final int start,
final SessionImplementor session) throws SQLException, HibernateException {
int span = 0;
for ( int i = 0; i < values.length; i++ ) {
types[i].nullSafeSet( st, values[i], start + span, session );
span += types[i].getColumnSpan( session.getFactory() );
}
return span;
}
private static int bindNamedParameters(
final PreparedStatement ps,
final QueryParameters queryParameters,
final int start,
final NamedParameterSource source,
final SessionImplementor session) throws SQLException, HibernateException {
return bindNamedParameters( ps, queryParameters.getNamedParameters(), start, source, session );
}
private static int bindNamedParameters(
final PreparedStatement ps,
final Map namedParams,
final int start,
final NamedParameterSource source,
final SessionImplementor session) throws SQLException, HibernateException {
if ( namedParams != null ) {
// assumes that types are all of span 1
final Iterator iter = namedParams.entrySet().iterator();
int result = 0;
while ( iter.hasNext() ) {
final Map.Entry e = (Map.Entry) iter.next();
final String name = (String) e.getKey();
final TypedValue typedVal = (TypedValue) e.getValue();
final int[] locations = source.getNamedParameterLocations( name );
for ( int location : locations ) {
if ( LOG.isDebugEnabled() ) {
LOG.debugf(
"bindNamedParameters() %s -> %s [%s]",
typedVal.getValue(),
name,
location + start
);
}
typedVal.getType().nullSafeSet( ps, typedVal.getValue(), location + start, session );
}
result += locations.length;
}
return result;
}
return 0;
}
}

View File

@ -1,597 +0,0 @@
/*
* Hibernate, Relational Persistence for Idiomatic Java
*
* License: GNU Lesser General Public License (LGPL), version 2.1 or later
* See the lgpl.txt file in the root directory or http://www.gnu.org/licenses/lgpl-2.1.html
*/
package org.hibernate.engine.spi;
import java.io.Serializable;
import java.util.List;
import java.util.Map;
import org.hibernate.HibernateException;
import org.hibernate.LockOptions;
import org.hibernate.NotYetImplementedFor6Exception;
import org.hibernate.QueryException;
import org.hibernate.ScrollMode;
import org.hibernate.internal.CoreLogging;
import org.hibernate.internal.util.EntityPrinter;
import org.hibernate.internal.util.collections.ArrayHelper;
import org.hibernate.query.spi.QueryOptions;
import org.hibernate.query.spi.QueryParameterBindings;
import org.hibernate.transform.ResultTransformer;
import org.hibernate.type.ComponentType;
import org.hibernate.type.Type;
import org.jboss.logging.Logger;
/**
* @author Gavin King
*/
public final class QueryParameters {
private static final Logger LOG = CoreLogging.logger( QueryParameters.class );
public static final String HQL_VARIABLE_PREFIX = ":";
private Type[] positionalParameterTypes;
private Object[] positionalParameterValues;
private Map<String, TypedValue> namedParameters;
private LockOptions lockOptions;
private RowSelection rowSelection;
private boolean cacheable;
private String cacheRegion;
private String comment;
private List<String> queryHints;
private ScrollMode scrollMode;
private Serializable[] collectionKeys;
private Object optionalObject;
private String optionalEntityName;
private Serializable optionalId;
private boolean isReadOnlyInitialized;
private boolean readOnly;
private boolean callable;
private boolean autodiscovertypes;
private boolean isNaturalKeyLookup;
private boolean passDistinctThrough = true;
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 } );
}
public QueryParameters(
final Type[] positionalParameterTypes,
final Object[] positionalParameterValues,
final Object optionalObject,
final String optionalEntityName,
final Serializable optionalObjectId) {
this( positionalParameterTypes, positionalParameterValues );
this.optionalObject = optionalObject;
this.optionalId = optionalObjectId;
this.optionalEntityName = optionalEntityName;
}
public QueryParameters(
final Type[] positionalParameterTypes,
final Object[] positionalParameterValues) {
this( positionalParameterTypes, positionalParameterValues, null, null, false, false, false, null, null, null, false, null );
}
public QueryParameters(
final Type[] positionalParameterTypes,
final Object[] positionalParameterValues,
final Object[] collectionKeys) {
this( positionalParameterTypes, positionalParameterValues, null, (Serializable[]) collectionKeys );
}
public QueryParameters(
final Type[] positionalParameterTypes,
final Object[] positionalParameterValues,
final Serializable[] collectionKeys) {
this( positionalParameterTypes, positionalParameterValues, null, collectionKeys );
}
public QueryParameters(
final Type[] positionalParameterTypes,
final Object[] positionalParameterValues,
final Map<String, TypedValue> namedParameters,
final Serializable[] collectionKeys) {
this(
positionalParameterTypes,
positionalParameterValues,
namedParameters,
null,
null,
false,
false,
false,
null,
null,
null,
collectionKeys,
null
);
}
public QueryParameters(
final Type[] positionalParameterTypes,
final Object[] positionalParameterValues,
final LockOptions lockOptions,
final RowSelection rowSelection,
final boolean isReadOnlyInitialized,
final boolean readOnly,
final boolean cacheable,
final String cacheRegion,
//final boolean forceCacheRefresh,
final String comment,
final List<String> queryHints,
final boolean isLookupByNaturalKey,
final ResultTransformer transformer) {
this(
positionalParameterTypes,
positionalParameterValues,
null,
lockOptions,
rowSelection,
isReadOnlyInitialized,
readOnly,
cacheable,
cacheRegion,
comment,
queryHints,
null,
transformer
);
isNaturalKeyLookup = isLookupByNaturalKey;
}
public QueryParameters(
final Type[] positionalParameterTypes,
final Object[] positionalParameterValues,
final Map<String, TypedValue> namedParameters,
final LockOptions lockOptions,
final RowSelection rowSelection,
final boolean isReadOnlyInitialized,
final boolean readOnly,
final boolean cacheable,
final String cacheRegion,
//final boolean forceCacheRefresh,
final String comment,
final List<String> queryHints,
final Serializable[] collectionKeys,
ResultTransformer transformer) {
this.positionalParameterTypes = positionalParameterTypes;
this.positionalParameterValues = positionalParameterValues;
this.namedParameters = namedParameters;
this.lockOptions = lockOptions;
this.rowSelection = rowSelection;
this.cacheable = cacheable;
this.cacheRegion = cacheRegion;
//this.forceCacheRefresh = forceCacheRefresh;
this.comment = comment;
this.queryHints = queryHints;
this.collectionKeys = collectionKeys;
this.isReadOnlyInitialized = isReadOnlyInitialized;
this.readOnly = readOnly;
this.resultTransformer = transformer;
}
public QueryParameters(
final Type[] positionalParameterTypes,
final Object[] positionalParameterValues,
final Map<String, TypedValue> namedParameters,
final LockOptions lockOptions,
final RowSelection rowSelection,
final boolean isReadOnlyInitialized,
final boolean readOnly,
final boolean cacheable,
final String cacheRegion,
//final boolean forceCacheRefresh,
final String comment,
final List<String> queryHints,
final Serializable[] collectionKeys,
final Object optionalObject,
final String optionalEntityName,
final Serializable optionalId,
final ResultTransformer transformer) {
this(
positionalParameterTypes,
positionalParameterValues,
namedParameters,
lockOptions,
rowSelection,
isReadOnlyInitialized,
readOnly,
cacheable,
cacheRegion,
comment,
queryHints,
collectionKeys,
transformer
);
this.optionalEntityName = optionalEntityName;
this.optionalId = optionalId;
this.optionalObject = optionalObject;
}
public QueryParameters(
QueryParameterBindings queryParameterBindings,
LockOptions lockOptions,
QueryOptions queryOptions,
final Serializable[] collectionKeys,
final Object optionalObject,
final String optionalEntityName,
final Serializable optionalId,
ResultTransformer resultTransformer) {
this(
null,
null,
null,
lockOptions,
new RowSelection(
queryOptions.getFirstRow(),
queryOptions.getMaxRows(),
queryOptions.getTimeout(),
queryOptions.getFetchSize()
),
queryOptions.isReadOnly() != null,
queryOptions.isReadOnly(),
queryOptions.isResultCachingEnabled(),
queryOptions.getResultCacheRegionName(),
queryOptions.getComment(),
queryOptions.getDatabaseHints(),
collectionKeys,
optionalObject,
optionalEntityName,
optionalId,
resultTransformer
);
}
@SuppressWarnings( {"UnusedDeclaration"})
public boolean hasRowSelection() {
return rowSelection != null;
}
public Map<String, TypedValue> getNamedParameters() {
return namedParameters;
}
public Type[] getPositionalParameterTypes() {
return positionalParameterTypes;
}
public Object[] getPositionalParameterValues() {
return positionalParameterValues;
}
public RowSelection getRowSelection() {
return rowSelection;
}
public ResultTransformer getResultTransformer() {
return resultTransformer;
}
@SuppressWarnings( {"UnusedDeclaration"})
public void setNamedParameters(Map<String, TypedValue> map) {
namedParameters = map;
}
public void setPositionalParameterTypes(Type[] types) {
positionalParameterTypes = types;
}
public void setPositionalParameterValues(Object[] objects) {
positionalParameterValues = objects;
}
@SuppressWarnings( {"UnusedDeclaration"})
public void setRowSelection(RowSelection selection) {
rowSelection = selection;
}
public LockOptions getLockOptions() {
return lockOptions;
}
public void setLockOptions(LockOptions lockOptions) {
this.lockOptions = lockOptions;
}
public void traceParameters(SessionFactoryImplementor factory) throws HibernateException {
EntityPrinter print = new EntityPrinter( factory );
if ( positionalParameterValues.length != 0 ) {
LOG.tracev( "Parameters: {0}", print.toString( positionalParameterTypes, positionalParameterValues ) );
}
if ( namedParameters != null ) {
LOG.tracev( "Named parameters: {0}", print.toString( namedParameters ) );
}
}
public boolean isCacheable() {
return cacheable;
}
public void setCacheable(boolean b) {
cacheable = b;
}
public String getCacheRegion() {
return cacheRegion;
}
public void setCacheRegion(String cacheRegion) {
this.cacheRegion = cacheRegion;
}
public void validateParameters() throws QueryException {
final int types = positionalParameterTypes == null ? 0 : positionalParameterTypes.length;
final 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 + "]"
);
}
}
public String getComment() {
return comment;
}
public void setComment(String comment) {
this.comment = comment;
}
public List<String> getQueryHints() {
return queryHints;
}
public void setQueryHints(List<String> queryHints) {
this.queryHints = queryHints;
}
public ScrollMode getScrollMode() {
return scrollMode;
}
public void setScrollMode(ScrollMode scrollMode) {
this.scrollMode = scrollMode;
}
public Serializable[] getCollectionKeys() {
return collectionKeys;
}
@SuppressWarnings( {"UnusedDeclaration"})
public void setCollectionKeys(Serializable[] collectionKeys) {
this.collectionKeys = collectionKeys;
}
public String getOptionalEntityName() {
return optionalEntityName;
}
public void setOptionalEntityName(String optionalEntityName) {
this.optionalEntityName = optionalEntityName;
}
public Serializable getOptionalId() {
return optionalId;
}
public void setOptionalId(Serializable optionalId) {
this.optionalId = optionalId;
}
public Object getOptionalObject() {
return optionalObject;
}
public void setOptionalObject(Object optionalObject) {
this.optionalObject = optionalObject;
}
/**
* Has the read-only/modifiable mode been explicitly set?
* @see QueryParameters#setReadOnly(boolean)
* @see QueryParameters#isReadOnly(SharedSessionContractImplementor)
*
* @return true, the read-only/modifiable mode was explicitly set
* false, the read-only/modifiable mode was not explicitly set
*/
public boolean isReadOnlyInitialized() {
return isReadOnlyInitialized;
}
/**
* Should entities and proxies loaded by the Query be put in read-only mode? The
* read-only/modifiable setting must be initialized via QueryParameters#setReadOnly(boolean)
* before calling this method.
*
* @see QueryParameters#isReadOnlyInitialized()
* @see QueryParameters#isReadOnly(SharedSessionContractImplementor)
* @see QueryParameters#setReadOnly(boolean)
*
* The read-only/modifiable setting has no impact on entities/proxies returned by the
* query that existed in the session before the query was executed.
*
* @return true, entities and proxies loaded by the Query will be put in read-only mode
* false, entities and proxies loaded by the Query will be put in modifiable mode
* @throws IllegalStateException if the read-only/modifiable setting has not been
* initialized (i.e., isReadOnlyInitialized() == false).
*/
public boolean isReadOnly() {
if ( !isReadOnlyInitialized() ) {
throw new IllegalStateException( "cannot call isReadOnly() when isReadOnlyInitialized() returns false" );
}
return readOnly;
}
/**
* Should entities and proxies loaded by the Query be put in read-only mode? If the
* read-only/modifiable setting was not initialized (i.e., QueryParameters#isReadOnlyInitialized() == false),
* then the default read-only/modifiable setting for the persistence context is returned instead.
* <p/>
* The read-only/modifiable setting has no impact on entities/proxies returned by the
* query that existed in the session before the query was executed.
*
* @param session The originating session
*
* @return {@code true} indicates that entities and proxies loaded by the query will be put in read-only mode;
* {@code false} indicates that entities and proxies loaded by the query will be put in modifiable mode
*
* @see QueryParameters#isReadOnlyInitialized()
* @see QueryParameters#setReadOnly(boolean)
* @see PersistenceContext#isDefaultReadOnly()
*
* The read-only/modifiable setting has no impact on entities/proxies returned by the
* query that existed in the session before the query was executed.
*
*/
public boolean isReadOnly(SharedSessionContractImplementor session) {
return isReadOnlyInitialized
? isReadOnly()
: session.getPersistenceContextInternal().isDefaultReadOnly();
}
/**
* Set the read-only/modifiable mode for entities and proxies loaded by the query.
* <p/>
* The read-only/modifiable setting has no impact on entities/proxies returned by the
* query that existed in the session before the query was executed.
*
* @param readOnly if {@code true}, entities and proxies loaded by the query will be put in read-only mode; if
* {@code false}, entities and proxies loaded by the query will be put in modifiable mode
*
* @see QueryParameters#isReadOnlyInitialized()
* @see QueryParameters#isReadOnly(SharedSessionContractImplementor)
* @see QueryParameters#setReadOnly(boolean)
* @see PersistenceContext#isDefaultReadOnly()
*/
public void setReadOnly(boolean readOnly) {
this.readOnly = readOnly;
this.isReadOnlyInitialized = true;
}
public void setCallable(boolean callable) {
this.callable = callable;
}
public boolean isCallable() {
return callable;
}
public boolean hasAutoDiscoverScalarTypes() {
return autodiscovertypes;
}
/**
* Check if this query should pass the {@code distinct} to the database.
* @return the query passes {@code distinct} to the database
*/
public boolean isPassDistinctThrough() {
return passDistinctThrough;
}
/**
* Set if this query should pass the {@code distinct} to the database.
* @param passDistinctThrough the query passes {@code distinct} to the database
*/
public void setPassDistinctThrough(boolean passDistinctThrough) {
this.passDistinctThrough = passDistinctThrough;
}
private int getNumberOfParametersCoveredBy(Type[] subtypes) {
int numberOfParameters = 0;
for ( Type type : subtypes ) {
if ( type.isComponentType() ) {
numberOfParameters = numberOfParameters + getNumberOfParametersCoveredBy( ((ComponentType) type).getSubtypes() );
}
else {
numberOfParameters++;
}
}
return numberOfParameters;
}
public String getFilteredSQL() {
return processedSQL;
}
public Object[] getFilteredPositionalParameterValues() {
return processedPositionalParameterValues;
}
public Type[] getFilteredPositionalParameterTypes() {
return processedPositionalParameterTypes;
}
public boolean isNaturalKeyLookup() {
return isNaturalKeyLookup;
}
@SuppressWarnings( {"UnusedDeclaration"})
public void setNaturalKeyLookup(boolean isNaturalKeyLookup) {
this.isNaturalKeyLookup = isNaturalKeyLookup;
}
public void setAutoDiscoverScalarTypes(boolean autodiscovertypes) {
this.autodiscovertypes = autodiscovertypes;
}
public QueryParameters createCopyUsing(RowSelection selection) {
QueryParameters copy = new QueryParameters(
this.positionalParameterTypes,
this.positionalParameterValues,
this.namedParameters,
this.lockOptions,
selection,
this.isReadOnlyInitialized,
this.readOnly,
this.cacheable,
this.cacheRegion,
this.comment,
this.queryHints,
this.collectionKeys,
this.optionalObject,
this.optionalEntityName,
this.optionalId,
this.resultTransformer
);
copy.processedSQL = this.processedSQL;
copy.processedPositionalParameterTypes = this.processedPositionalParameterTypes;
copy.processedPositionalParameterValues = this.processedPositionalParameterValues;
copy.passDistinctThrough = this.passDistinctThrough;
return copy;
}
public void bindDynamicParameter(Type paramType, Object paramValue) {
if(processedPositionalParameterTypes != null) {
int length = processedPositionalParameterTypes.length;
Type[] types = new Type[length + 1];
Object[] values = new Object[length + 1];
for ( int i = 0; i < length; i++ ) {
types[i] = processedPositionalParameterTypes[i];
values[i] = processedPositionalParameterValues[i];
}
types[length] = paramType;
values[length] = paramValue;
processedPositionalParameterTypes = types;
processedPositionalParameterValues = values;
}
}
}

View File

@ -1,96 +0,0 @@
/*
* Hibernate, Relational Persistence for Idiomatic Java
*
* License: GNU Lesser General Public License (LGPL), version 2.1 or later.
* See the lgpl.txt file in the root directory or <http://www.gnu.org/licenses/lgpl-2.1.html>.
*/
package org.hibernate.engine.spi;
import org.hibernate.query.spi.QueryOptions;
/**
* Encapsulates details related to the creation and execution of
* a JDBC statement
*
* Differs from {@link QueryOptions} in that this contract describes options
*
* Represents a selection criteria for rows in a JDBC {@link java.sql.ResultSet}
*
*
*
* @author Gavin King
* @deprecated todo (6.0): remove in favor of Limit within QueryOptions?
*/
@Deprecated
public final class RowSelection {
private Integer firstRow;
private Integer maxRows;
private Integer timeout;
private Integer fetchSize;
public RowSelection() {
}
public RowSelection(Integer firstRow, Integer maxRows, Integer timeout, Integer fetchSize) {
this.firstRow = firstRow;
this.maxRows = maxRows;
this.timeout = timeout;
this.fetchSize = fetchSize;
}
public void setFirstRow(Integer firstRow) {
if ( firstRow != null && firstRow < 0 ) {
throw new IllegalArgumentException( "first-row value cannot be negative : " + firstRow );
}
this.firstRow = firstRow;
}
public void setFirstRow(int firstRow) {
this.firstRow = firstRow;
}
public Integer getFirstRow() {
return firstRow;
}
public void setMaxRows(Integer maxRows) {
this.maxRows = maxRows;
}
public void setMaxRows(int maxRows) {
this.maxRows = maxRows;
}
public Integer getMaxRows() {
return maxRows;
}
public void setTimeout(Integer timeout) {
this.timeout = timeout;
}
public void setTimeout(int timeout) {
this.timeout = timeout;
}
public Integer getTimeout() {
return timeout;
}
public Integer getFetchSize() {
return fetchSize;
}
public void setFetchSize(Integer fetchSize) {
this.fetchSize = fetchSize;
}
public void setFetchSize(int fetchSize) {
this.fetchSize = fetchSize;
}
public boolean definesLimits() {
return maxRows != null || (firstRow != null && firstRow <= 0);
}
}

View File

@ -1,50 +0,0 @@
/*
* Hibernate, Relational Persistence for Idiomatic Java
*
* License: GNU Lesser General Public License (LGPL), version 2.1 or later.
* See the lgpl.txt file in the root directory or <http://www.gnu.org/licenses/lgpl-2.1.html>.
*/
package org.hibernate.param;
import org.hibernate.type.Type;
/**
* Convenience base class for explicitly defined query parameters.
*
* @author Steve Ebersole
*/
public abstract class AbstractExplicitParameterSpecification implements ExplicitParameterSpecification {
private final int sourceLine;
private final int sourceColumn;
private Type expectedType;
/**
* Constructs an AbstractExplicitParameterSpecification.
*
* @param sourceLine See {@link #getSourceLine()}
* @param sourceColumn See {@link #getSourceColumn()}
*/
protected AbstractExplicitParameterSpecification(int sourceLine, int sourceColumn) {
this.sourceLine = sourceLine;
this.sourceColumn = sourceColumn;
}
@Override
public int getSourceLine() {
return sourceLine;
}
@Override
public int getSourceColumn() {
return sourceColumn;
}
@Override
public Type getExpectedType() {
return expectedType;
}
@Override
public void setExpectedType(Type expectedType) {
this.expectedType = expectedType;
}
}

View File

@ -1,64 +0,0 @@
/*
* Hibernate, Relational Persistence for Idiomatic Java
*
* License: GNU Lesser General Public License (LGPL), version 2.1 or later.
* See the lgpl.txt file in the root directory or <http://www.gnu.org/licenses/lgpl-2.1.html>.
*/
package org.hibernate.param;
import java.sql.PreparedStatement;
import java.sql.SQLException;
import org.hibernate.engine.spi.QueryParameters;
import org.hibernate.engine.spi.SharedSessionContractImplementor;
import org.hibernate.type.Type;
/**
* 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 {
public static final String PARAM_KEY = "{collection_key}";
private final String collectionRole;
private final Type keyType;
/**
* Creates a specialized collection-filter collection-key parameter spec.
*
* @param collectionRole The collection role being filtered.
* @param keyType The mapped collection-key type.
*/
public CollectionFilterKeyParameterSpecification(String collectionRole, Type keyType) {
this.collectionRole = collectionRole;
this.keyType = keyType;
}
@Override
public int bind(
PreparedStatement statement,
QueryParameters qp,
SharedSessionContractImplementor session,
int position) throws SQLException {
final Object value = qp.getNamedParameters().get( PARAM_KEY ).getValue();
keyType.nullSafeSet( statement, value, position, session );
return keyType.getColumnSpan( session.getFactory() );
}
@Override
public Type getExpectedType() {
return keyType;
}
@Override
public void setExpectedType(Type expectedType) {
// todo : throw exception?
}
@Override
public String renderDisplayInfo() {
return "collection-filter-key=" + collectionRole;
}
}

View File

@ -1,88 +0,0 @@
/*
* Hibernate, Relational Persistence for Idiomatic Java
*
* License: GNU Lesser General Public License (LGPL), version 2.1 or later.
* See the lgpl.txt file in the root directory or <http://www.gnu.org/licenses/lgpl-2.1.html>.
*/
package org.hibernate.param;
import java.sql.PreparedStatement;
import java.sql.SQLException;
import java.util.Collection;
import java.util.Iterator;
import org.hibernate.engine.spi.QueryParameters;
import org.hibernate.engine.spi.SharedSessionContractImplementor;
import org.hibernate.type.Type;
/**
* A specialized ParameterSpecification impl for dealing with a dynamic filter parameters.
*
* @see org.hibernate.Session#enableFilter(String)
*
* @author Steve Ebersole
*/
public class DynamicFilterParameterSpecification implements ParameterSpecification {
private final String filterName;
private final String parameterName;
private final Type definedParameterType;
/**
* 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 parameter type specified on the filter metadata
*/
public DynamicFilterParameterSpecification(
String filterName,
String parameterName,
Type definedParameterType) {
this.filterName = filterName;
this.parameterName = parameterName;
this.definedParameterType = definedParameterType;
}
@Override
public int bind(
PreparedStatement statement,
QueryParameters qp,
SharedSessionContractImplementor session,
int start) throws SQLException {
final int columnSpan = definedParameterType.getColumnSpan( session.getFactory() );
final String fullParamName = filterName + '.' + parameterName;
final Object value = session.getLoadQueryInfluencers().getFilterParameterValue(fullParamName);
final Type type = session.getLoadQueryInfluencers().getFilterParameterType(fullParamName);
if ( Collection.class.isInstance( value ) ) {
int positions = 0;
Iterator itr = ( ( Collection ) value ).iterator();
while ( itr.hasNext() ) {
Object next = itr.next();
qp.bindDynamicParameter( type, next );
definedParameterType.nullSafeSet( statement, next, start + positions, session );
positions += columnSpan;
}
return positions;
}
else {
qp.bindDynamicParameter(type, value);
definedParameterType.nullSafeSet( statement, value, start, session );
return columnSpan;
}
}
@Override
public Type getExpectedType() {
return definedParameterType;
}
@Override
public void setExpectedType(Type expectedType) {
// todo : throw exception? maybe warn if not the same?
}
@Override
public String renderDisplayInfo() {
return "dynamic-filter={filterName=" + filterName + ",paramName=" + parameterName + "}";
}
}

View File

@ -1,30 +0,0 @@
/*
* Hibernate, Relational Persistence for Idiomatic Java
*
* License: GNU Lesser General Public License (LGPL), version 2.1 or later.
* See the lgpl.txt file in the root directory or <http://www.gnu.org/licenses/lgpl-2.1.html>.
*/
package org.hibernate.param;
/**
* An additional contract for parameters which originate from parameters explicitly encountered in the source statement
* (HQL or native-SQL).
*
* @author Steve Ebersole
*/
public interface ExplicitParameterSpecification extends ParameterSpecification {
/**
* Retrieves the line number on which this parameter occurs in the source query.
*
* @return The line number.
*/
int getSourceLine();
/**
* Retrieves the column number (within the {@link #getSourceLine()}) where this parameter occurs.
*
* @return The column number.
*/
int getSourceColumn();
}

View File

@ -1,70 +0,0 @@
/*
* Hibernate, Relational Persistence for Idiomatic Java
*
* License: GNU Lesser General Public License (LGPL), version 2.1 or later.
* See the lgpl.txt file in the root directory or <http://www.gnu.org/licenses/lgpl-2.1.html>.
*/
package org.hibernate.param;
import java.sql.PreparedStatement;
import java.sql.SQLException;
import org.hibernate.engine.spi.QueryParameters;
import org.hibernate.engine.spi.SharedSessionContractImplementor;
import org.hibernate.engine.spi.TypedValue;
/**
* Parameter bind specification for an explicit named parameter.
*
* @author Steve Ebersole
*/
public class NamedParameterSpecification extends AbstractExplicitParameterSpecification {
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;
}
/**
* Bind the appropriate value into the given statement at the specified position.
*
* @param statement The statement into which the value should be bound.
* @param qp The defined values for the current query execution.
* @param session The session against which the current execution is occuring.
* @param position The position from which to start binding value(s).
*
* @return The number of sql bind positions "eaten" by this bind operation.
*/
@Override
public int bind(
PreparedStatement statement,
QueryParameters qp,
SharedSessionContractImplementor session,
int position) throws SQLException {
TypedValue typedValue = qp.getNamedParameters().get( name );
typedValue.getType().nullSafeSet( statement, typedValue.getValue(), position, session );
return typedValue.getType().getColumnSpan( session.getFactory() );
}
@Override
public String renderDisplayInfo() {
return "name=" + name + ", expectedType=" + getExpectedType();
}
/**
* Getter for property 'name'.
*
* @return Value for property 'name'.
*/
public String getName() {
return name;
}
}

View File

@ -1,32 +0,0 @@
/*
* Hibernate, Relational Persistence for Idiomatic Java
*
* License: GNU Lesser General Public License (LGPL), version 2.1 or later.
* See the lgpl.txt file in the root directory or <http://www.gnu.org/licenses/lgpl-2.1.html>.
*/
package org.hibernate.param;
import java.sql.PreparedStatement;
import java.sql.SQLException;
import org.hibernate.engine.spi.QueryParameters;
import org.hibernate.engine.spi.SharedSessionContractImplementor;
/**
* @author Steve Ebersole
*/
public interface ParameterBinder {
/**
* Bind the appropriate value into the given statement at the specified position.
*
* @param statement The statement into which the value should be bound.
* @param qp The defined values for the current query execution.
* @param session The session against which the current execution is occuring.
* @param position The position from which to start binding value(s).
*
* @return The number of sql bind positions "eaten" by this bind operation.
* @throws SQLException Indicates problems performing the JDBC bind operation.
*/
int bind(PreparedStatement statement, QueryParameters qp, SharedSessionContractImplementor session, int position) throws SQLException;
}

View File

@ -1,41 +0,0 @@
/*
* Hibernate, Relational Persistence for Idiomatic Java
*
* License: GNU Lesser General Public License (LGPL), version 2.1 or later.
* See the lgpl.txt file in the root directory or <http://www.gnu.org/licenses/lgpl-2.1.html>.
*/
package org.hibernate.param;
import java.sql.PreparedStatement;
import org.hibernate.type.Type;
/**
* Maintains information relating to parameters which need to get bound into a
* JDBC {@link PreparedStatement}.
*
* @author Steve Ebersole
*/
public interface ParameterSpecification extends ParameterBinder {
/**
* Get the type which we are expecting for a bind into this parameter based
* on translated contextual information.
*
* @return The expected type.
*/
Type getExpectedType();
/**
* Injects the expected type. Called during translation.
*
* @param expectedType The type to expect.
*/
void setExpectedType(Type expectedType);
/**
* Render this parameter into displayable info (for logging, etc).
*
* @return The displayable info.
*/
String renderDisplayInfo();
}

View File

@ -1,67 +0,0 @@
/*
* Hibernate, Relational Persistence for Idiomatic Java
*
* License: GNU Lesser General Public License (LGPL), version 2.1 or later.
* See the lgpl.txt file in the root directory or <http://www.gnu.org/licenses/lgpl-2.1.html>.
*/
package org.hibernate.param;
import java.sql.PreparedStatement;
import java.sql.SQLException;
import org.hibernate.engine.spi.QueryParameters;
import org.hibernate.engine.spi.SharedSessionContractImplementor;
import org.hibernate.engine.spi.TypedValue;
/**
* Parameter bind specification for an explicit positional (or ordinal) parameter.
*
* @author Steve Ebersole
*/
public class PositionalParameterSpecification extends AbstractExplicitParameterSpecification {
private final int label;
private final int bindingPosition;
/**
* Constructs a position/ordinal parameter bind specification.
*
* @param sourceLine See {@link #getSourceLine()}
* @param sourceColumn See {@link #getSourceColumn()}
* @param label The position in the source query, relative to the other source positional parameters.
*/
public PositionalParameterSpecification(
int sourceLine,
int sourceColumn,
int label,
int bindingPosition) {
super( sourceLine, sourceColumn );
this.label = label;
this.bindingPosition = bindingPosition;
}
/**
* Bind the appropriate value into the given statement at the specified position.
*
* @param statement The statement into which the value should be bound.
* @param qp The defined values for the current query execution.
* @param session The session against which the current execution is occurring.
* @param position The position from which to start binding value(s).
*
* @return The number of sql bind positions "eaten" by this bind operation.
*/
@Override
public int bind(PreparedStatement statement, QueryParameters qp, SharedSessionContractImplementor session, int position) throws SQLException {
final TypedValue typedValue = qp.getNamedParameters().get( Integer.toString( label ) );
typedValue.getType().nullSafeSet( statement, typedValue.getValue(), position, session );
return typedValue.getType().getColumnSpan( session.getFactory() );
}
@Override
public String renderDisplayInfo() {
return "label=" + label + ", expectedType=" + getExpectedType();
}
public int getLabel() {
return label;
}
}

View File

@ -79,7 +79,7 @@ import org.hibernate.metamodel.model.domain.BasicDomainType;
import org.hibernate.metamodel.model.domain.EntityDomainType;
import org.hibernate.metamodel.model.domain.PluralPersistentAttribute;
import org.hibernate.metamodel.model.domain.internal.CompositeSqmPathSource;
import org.hibernate.param.VersionTypeSeedParameterSpecification;
import org.hibernate.sql.exec.internal.VersionTypeSeedParameterSpecification;
import org.hibernate.persister.collection.CollectionPersister;
import org.hibernate.persister.entity.EntityPersister;
import org.hibernate.persister.entity.Joinable;

View File

@ -4,18 +4,14 @@
* License: GNU Lesser General Public License (LGPL), version 2.1 or later.
* See the lgpl.txt file in the root directory or <http://www.gnu.org/licenses/lgpl-2.1.html>.
*/
package org.hibernate.param;
package org.hibernate.sql.exec.internal;
import java.sql.PreparedStatement;
import java.sql.SQLException;
import org.hibernate.engine.spi.QueryParameters;
import org.hibernate.engine.spi.SharedSessionContractImplementor;
import org.hibernate.metamodel.mapping.JdbcMapping;
import org.hibernate.sql.exec.internal.JdbcParameterImpl;
import org.hibernate.sql.exec.spi.ExecutionContext;
import org.hibernate.sql.exec.spi.JdbcParameterBindings;
import org.hibernate.type.Type;
import org.hibernate.type.VersionType;
/**

View File

@ -11,7 +11,6 @@ import java.util.Locale;
import org.hibernate.LockMode;
import org.hibernate.LockOptions;
import org.hibernate.dialect.SQLServer2005Dialect;
import org.hibernate.engine.spi.RowSelection;
import org.hibernate.query.Limit;
import org.hibernate.testing.TestForIssue;

View File

@ -9,7 +9,6 @@ package org.hibernate.orm.test.dialect;
import java.util.Locale;
import org.hibernate.dialect.SQLServer2012Dialect;
import org.hibernate.engine.spi.RowSelection;
import org.hibernate.query.Limit;
import org.junit.After;