Top Description Inners Fields Constructors Methods
org.hibernate.dialect.pagination

public Class SQLServer2005LimitHandler

extends AbstractLimitHandler
Class Inheritance
Known Direct Subclasses
org.hibernate.dialect.pagination.SQLServer2012LimitHandler
Imports
java.sql.PreparedStatement, .SQLException, java.util.ArrayList, .LinkedList, .List, .Locale, java.util.regex.Matcher, .Pattern, org.hibernate.engine.spi.RowSelection, org.hibernate.internal.util.StringHelper

LIMIT clause handler compatible with SQL Server 2005 and later.
Authors
Lukasz Antoniak (lukasz dot antoniak at gmail dot com), Chris Cranford

Nested and Inner Type Summary

Modifier and TypeClass and Description
pack-priv static class

Field Summary

Modifier and TypeField and Description
private static final Pattern
private static final Pattern
private static final String
private static final Pattern
private static final String
private static final Pattern
private boolean
private static final String
private static final Pattern
private static final String
private static final String
private static final Pattern
private static final String
private static final Pattern
private static final String
private static final String
private boolean
private static final Pattern
private static final Pattern
private static final Pattern
private static final Pattern
private static final Pattern
private static final Pattern

Constructor Summary

AccessConstructor and Description
public
SQLServer2005LimitHandler()

Constructs a SQLServer2005LimitHandler

Method Summary

Modifier and TypeMethod and Description
protected void
addTopExpression(StringBuilder
SQL query.
sql
,
int
the offset where top expression pattern matching should begin.
offset
)

Adds TOP expression.

private int

Returns:

the position immediately after the CTE inner query plus 1.
advanceOverCTEInnerQuery
(StringBuilder
The sql buffer.
sql
,
int
The offset where to begin advancing the position from.
offset
)

Advances over the CTE inner query that is contained inside matching '(' and ')'.

public int
bindLimitParametersAtEndOfQuery(RowSelection
the selection criteria for rows.
selection
,
PreparedStatement
Statement to which to bind limit parameter values.
statement
,
int
Index from which to start binding.
index
)

Overrides org.hibernate.dialect.pagination.AbstractLimitHandler.bindLimitParametersAtEndOfQuery.

Implements org.hibernate.dialect.pagination.LimitHandler.bindLimitParametersAtEndOfQuery.

Bind parameter values needed by the LIMIT clause after original SELECT statement.
public int
bindLimitParametersAtStartOfQuery(RowSelection
the selection criteria for rows.
selection
,
PreparedStatement
Statement to which to bind limit parameter values.
statement
,
int
Index from which to start binding.
index
)

Overrides org.hibernate.dialect.pagination.AbstractLimitHandler.bindLimitParametersAtStartOfQuery.

Implements org.hibernate.dialect.pagination.LimitHandler.bindLimitParametersAtStartOfQuery.

Bind parameter values needed by the LIMIT clause before original SELECT statement.
private static Pattern

Returns:

Compiled Pattern.
buildShallowIndexPattern
(String
String search pattern.
pattern
,
boolean
whether to apply a word boundary restriction.
wordBoundary
)

Builds a pattern that can be used to find matches of case-insensitive matches based on the search pattern that is not enclosed in parenthesis.

public int
convertToFirstRowValue(int
The user-supplied, zero-based first row offset.
zeroBasedFirstResult
)

Overrides org.hibernate.dialect.pagination.AbstractLimitHandler.convertToFirstRowValue.

Hibernate APIs explicitly state that setFirstResult() should be a zero-based offset.
protected void
encloseWithOuterQuery(StringBuilder
SQL query.
sql
,
int
SQL query offset.
offset
)

Encloses original SQL statement with outer query that provides __row__ column.

protected String

Returns:

List of aliases separated with comas or *.
fillAliasInSelectClause
(StringBuilder
SQL query.
sb
,
int
the starting offset.
offset
)

Adds missing aliases in provided SELECT clause and returns coma-separated list of them.

private static List<SQLServer2005LimitHandler.IgnoreRange>

Returns:

list of IgnoreRange objects, never null.
generateIgnoreRanges
(String
The SQL buffer.
sql
)

Generates a list of IgnoreRange objects that represent nested sections of the provided SQL buffer that should be ignored when performing regular expression matches.

private String

Returns:

Column alias.
getAlias
(String
Single column select expression.
expression
)

Returns alias of provided single column selection or null if not found.

private int

Returns:

the start position where the column list begins.
getSelectColumnsStartPosition
(StringBuilder
the string builder sql.
sb
,
int
the starting offset.
offset
)

Get the start position for where the column list begins.

private int

Returns:

the position where select is found.
getSelectStartPosition
(StringBuilder
the string builder sql.
sb
,
int
the starting offset in buffer.
offset
)

Get the select start position.

private int

Returns:

the index where to begin parsing.
getStatementIndex
(StringBuilder
The sql buffer.
sql
)

Get the starting point for the limit handler to begin injecting and transforming the SQL.

private static boolean

Returns:

true if the position is to ignored/skipped, false otherwise.
isPositionIgnorable
(List<SQLServer2005LimitHandler.IgnoreRange>
list of IgnoreRange objects deduced from the SQL buffer.
ignoreRangeList
,
int
the position to determine whether is ignorable.
position
)

Returns whether the specified position is within the ranges of the ignoreRangeList.

private int

Returns:

the offset where the CTE SELECT clause begins.
locateQueryInCTEStatement
(StringBuilder
The sql buffer.
sql
,
int
The offset to begin pattern matching.
offset
)

Steps through the SQL buffer from the specified offset and performs a series of pattern matches.

public String

Returns:

A new SQL statement with the LIMIT clause applied.
processSql
(String
the SQL query to process.
sql
,
RowSelection
the selection criteria for rows.
selection
)

Overrides org.hibernate.dialect.pagination.AbstractLimitHandler.processSql.

Implements org.hibernate.dialect.pagination.LimitHandler.processSql.

Add a LIMIT clause to the given SQL SELECT (HHH-2655: ROW_NUMBER for Paging) The LIMIT SQL will look like:
WITH query AS (
  SELECT inner_query.*
       , ROW_NUMBER() OVER (ORDER BY CURRENT_TIMESTAMP) as __row__
    FROM ( original_query_with_top_if_order_by_present_and_all_aliased_columns ) inner_query
)
SELECT alias_list FROM query WHERE __row__ >= offset AND __row__ < offset + last
private boolean

Returns:

true when expression selects multiple columns, false otherwise.
selectsMultipleColumns
(String
Select expression.
expression
)

private static int

Returns:

Position of the first match, or -1 if not found.
shallowIndexOfPattern
(final StringBuilder
String to search.
sb
,
final Pattern
Compiled search pattern.
pattern
,
int
The index from which to start the search.
fromIndex
)

Returns index of the first case-insensitive match of search pattern that is not enclosed in parenthesis.

public boolean
supportsLimit()

Overrides org.hibernate.dialect.pagination.AbstractLimitHandler.supportsLimit.

Implements org.hibernate.dialect.pagination.LimitHandler.supportsLimit.

Does this handler support some form of limiting query results via a SQL clause?
public boolean
supportsLimitOffset()

Overrides org.hibernate.dialect.pagination.AbstractLimitHandler.supportsLimitOffset.

Implements org.hibernate.dialect.pagination.LimitHandler.supportsLimitOffset.

Does this handler's LIMIT support (if any) additionally support specifying an offset?
public boolean
supportsVariableLimit()

Overrides org.hibernate.dialect.pagination.AbstractLimitHandler.supportsVariableLimit.

Does this handler support bind variables (i.e., prepared statement parameters) for its limit/offset?
public boolean
useMaxForLimit()

Overrides org.hibernate.dialect.pagination.AbstractLimitHandler.useMaxForLimit.

Does the LIMIT clause take a "maximum" row number instead of a total number of returned rows?
Inherited from org.hibernate.dialect.pagination.AbstractLimitHandler:
bindLimitParametersbindLimitParametersFirstbindLimitParametersInReverseOrderforceLimitUsagegetMaxOrLimitsetMaxRows

Field Detail

ALIAS_PATTERNback to summary
private static final Pattern ALIAS_PATTERN
COMMA_PATTERNback to summary
private static final Pattern COMMA_PATTERN
DISTINCTback to summary
private static final String DISTINCT
DISTINCT_PATTERNback to summary
private static final Pattern DISTINCT_PATTERN
FROMback to summary
private static final String FROM
FROM_PATTERNback to summary
private static final Pattern FROM_PATTERN
isCTEback to summary
private boolean isCTE
ORDER_BYback to summary
private static final String ORDER_BY
ORDER_BY_PATTERNback to summary
private static final Pattern ORDER_BY_PATTERN
SELECTback to summary
private static final String SELECT
SELECT_DISTINCTback to summary
private static final String SELECT_DISTINCT
SELECT_DISTINCT_PATTERNback to summary
private static final Pattern SELECT_DISTINCT_PATTERN
SELECT_DISTINCT_SPACEback to summary
private static final String SELECT_DISTINCT_SPACE
SELECT_PATTERNback to summary
private static final Pattern SELECT_PATTERN
SELECT_SPACEback to summary
private static final String SELECT_SPACE
SPACE_NEWLINE_LINEFEEDback to summary
private static final String SPACE_NEWLINE_LINEFEED
topAddedback to summary
private boolean topAdded
WITH_ASback to summary
private static final Pattern WITH_AS
WITH_COLUMN_NAMES_ENDback to summary
private static final Pattern WITH_COLUMN_NAMES_END
WITH_COLUMN_NAMES_STARTback to summary
private static final Pattern WITH_COLUMN_NAMES_START
WITH_COMMAback to summary
private static final Pattern WITH_COMMA
WITH_CTEback to summary
private static final Pattern WITH_CTE
WITH_EXPRESSION_NAMEback to summary
private static final Pattern WITH_EXPRESSION_NAME

Constructor Detail

SQLServer2005LimitHandlerback to summary
public SQLServer2005LimitHandler()

Constructs a SQLServer2005LimitHandler

Method Detail

addTopExpressionback to summary
protected void addTopExpression(StringBuilder sql, int offset)

Adds TOP expression. Parameter value is bind in bindLimitParametersAtStartOfQuery(RowSelection, PreparedStatement, int) method.

Parameters
sql:StringBuilder

SQL query.

offset:int

the offset where top expression pattern matching should begin.

advanceOverCTEInnerQueryback to summary
private int advanceOverCTEInnerQuery(StringBuilder sql, int offset)

Advances over the CTE inner query that is contained inside matching '(' and ')'.

Parameters
sql:StringBuilder

The sql buffer.

offset:int

The offset where to begin advancing the position from.

Returns:int

the position immediately after the CTE inner query plus 1.

Exceptions
IllegalArgumentException:
if the matching parenthesis aren't detected at the end of the parse.
bindLimitParametersAtEndOfQueryback to summary
public int bindLimitParametersAtEndOfQuery(RowSelection selection, PreparedStatement statement, int index) throws SQLException

Overrides org.hibernate.dialect.pagination.AbstractLimitHandler.bindLimitParametersAtEndOfQuery.

Implements org.hibernate.dialect.pagination.LimitHandler.bindLimitParametersAtEndOfQuery.

Doc from org.hibernate.dialect.pagination.LimitHandler.bindLimitParametersAtEndOfQuery.

Bind parameter values needed by the LIMIT clause after original SELECT statement.

Parameters
selection:RowSelection

the selection criteria for rows.

statement:PreparedStatement

Statement to which to bind limit parameter values.

index:int

Index from which to start binding.

Returns:int

The number of parameter values bound.

Annotations
@Override
Exceptions
SQLException:
Indicates problems binding parameter values.
bindLimitParametersAtStartOfQueryback to summary
public int bindLimitParametersAtStartOfQuery(RowSelection selection, PreparedStatement statement, int index) throws SQLException

Overrides org.hibernate.dialect.pagination.AbstractLimitHandler.bindLimitParametersAtStartOfQuery.

Implements org.hibernate.dialect.pagination.LimitHandler.bindLimitParametersAtStartOfQuery.

Doc from org.hibernate.dialect.pagination.LimitHandler.bindLimitParametersAtStartOfQuery.

Bind parameter values needed by the LIMIT clause before original SELECT statement.

Parameters
selection:RowSelection

the selection criteria for rows.

statement:PreparedStatement

Statement to which to bind limit parameter values.

index:int

Index from which to start binding.

Returns:int

The number of parameter values bound.

Annotations
@Override
Exceptions
SQLException:
Indicates problems binding parameter values.
buildShallowIndexPatternback to summary
private static Pattern buildShallowIndexPattern(String pattern, boolean wordBoundary)

Builds a pattern that can be used to find matches of case-insensitive matches based on the search pattern that is not enclosed in parenthesis.

Parameters
pattern:String

String search pattern.

wordBoundary:boolean

whether to apply a word boundary restriction.

Returns:Pattern

Compiled Pattern.

convertToFirstRowValueback to summary
public int convertToFirstRowValue(int zeroBasedFirstResult)

Overrides org.hibernate.dialect.pagination.AbstractLimitHandler.convertToFirstRowValue.

Doc from org.hibernate.dialect.pagination.AbstractLimitHandler.convertToFirstRowValue.

Hibernate APIs explicitly state that setFirstResult() should be a zero-based offset. Here we allow the Dialect a chance to convert that value based on what the underlying db or driver will expect.

Note

what gets passed into AbstractLimitHandler#processSql(String, org.hibernate.engine.spi.RowSelection) is the zero-based offset. Dialects which do not supportsVariableLimit should take care to perform any needed first-row-conversion calls prior to injecting the limit values into the SQL string.

Parameters
zeroBasedFirstResult:int

The user-supplied, zero-based first row offset.

Returns:int

The corresponding db/dialect specific offset.

Annotations
@Override
encloseWithOuterQueryback to summary
protected void encloseWithOuterQuery(StringBuilder sql, int offset)

Encloses original SQL statement with outer query that provides __row__ column.

Parameters
sql:StringBuilder

SQL query.

offset:int

SQL query offset.

fillAliasInSelectClauseback to summary
protected String fillAliasInSelectClause(StringBuilder sb, int offset)

Adds missing aliases in provided SELECT clause and returns coma-separated list of them. If query takes advantage of expressions like * or {table}.* inside SELECT clause, method returns *.

Parameters
sb:StringBuilder

SQL query.

offset:int

the starting offset.

Returns:String

List of aliases separated with comas or *.

generateIgnoreRangesback to summary
private static List<SQLServer2005LimitHandler.IgnoreRange> generateIgnoreRanges(String sql)

Generates a list of IgnoreRange objects that represent nested sections of the provided SQL buffer that should be ignored when performing regular expression matches.

Parameters
sql:String

The SQL buffer.

Returns:List<SQLServer2005LimitHandler.IgnoreRange>

list of IgnoreRange objects, never null.

getAliasback to summary
private String getAlias(String expression)

Returns alias of provided single column selection or null if not found. Alias should be preceded with AS keyword.

Parameters
expression:String

Single column select expression.

Returns:String

Column alias.

getSelectColumnsStartPositionback to summary
private int getSelectColumnsStartPosition(StringBuilder sb, int offset)

Get the start position for where the column list begins.

Parameters
sb:StringBuilder

the string builder sql.

offset:int

the starting offset.

Returns:int

the start position where the column list begins.

getSelectStartPositionback to summary
private int getSelectStartPosition(StringBuilder sb, int offset)

Get the select start position.

Parameters
sb:StringBuilder

the string builder sql.

offset:int

the starting offset in buffer.

Returns:int

the position where select is found.

getStatementIndexback to summary
private int getStatementIndex(StringBuilder sql)

Get the starting point for the limit handler to begin injecting and transforming the SQL. For non-CTE queries, this is offset 0. For CTE queries, this will be where the CTE's SELECT clause begins (skipping all query definitions, column definitions and expressions). This method also sets isCTE if the query is parsed as a CTE query.

Parameters
sql:StringBuilder

The sql buffer.

Returns:int

the index where to begin parsing.

isPositionIgnorableback to summary
private static boolean isPositionIgnorable(List<SQLServer2005LimitHandler.IgnoreRange> ignoreRangeList, int position)

Returns whether the specified position is within the ranges of the ignoreRangeList.

Parameters
ignoreRangeList:List<SQLServer2005LimitHandler.IgnoreRange>

list of IgnoreRange objects deduced from the SQL buffer.

position:int

the position to determine whether is ignorable.

Returns:boolean

true if the position is to ignored/skipped, false otherwise.

locateQueryInCTEStatementback to summary
private int locateQueryInCTEStatement(StringBuilder sql, int offset)

Steps through the SQL buffer from the specified offset and performs a series of pattern matches. The method locates where the CTE SELECT clause begins and returns that offset from the SQL buffer.

Parameters
sql:StringBuilder

The sql buffer.

offset:int

The offset to begin pattern matching.

Returns:int

the offset where the CTE SELECT clause begins.

Exceptions
IllegalArgumentException:
if the parse of the CTE query fails.
processSqlback to summary
public String processSql(String sql, RowSelection selection)

Overrides org.hibernate.dialect.pagination.AbstractLimitHandler.processSql.

Implements org.hibernate.dialect.pagination.LimitHandler.processSql.

Add a LIMIT clause to the given SQL SELECT (HHH-2655: ROW_NUMBER for Paging) The LIMIT SQL will look like:

WITH query AS (
  SELECT inner_query.*
       , ROW_NUMBER() OVER (ORDER BY CURRENT_TIMESTAMP) as __row__
    FROM ( original_query_with_top_if_order_by_present_and_all_aliased_columns ) inner_query
)
SELECT alias_list FROM query WHERE __row__ >= offset AND __row__ < offset + last
When offset equals 0, only TOP(?) expression is added to the original query.
Parameters
sql:String

Doc from org.hibernate.dialect.pagination.LimitHandler.processSql.

the SQL query to process.

selection:RowSelection

Doc from org.hibernate.dialect.pagination.LimitHandler.processSql.

the selection criteria for rows.

Returns:String

A new SQL statement with the LIMIT clause applied.

Annotations
@Override
selectsMultipleColumnsback to summary
private boolean selectsMultipleColumns(String expression)
Parameters
expression:String

Select expression.

Returns:boolean

true when expression selects multiple columns, false otherwise.

shallowIndexOfPatternback to summary
private static int shallowIndexOfPattern(final StringBuilder sb, final Pattern pattern, int fromIndex)

Returns index of the first case-insensitive match of search pattern that is not enclosed in parenthesis.

Parameters
sb:StringBuilder

String to search.

pattern:Pattern

Compiled search pattern.

fromIndex:int

The index from which to start the search.

Returns:int

Position of the first match, or -1 if not found.

supportsLimitback to summary
public boolean supportsLimit()

Overrides org.hibernate.dialect.pagination.AbstractLimitHandler.supportsLimit.

Implements org.hibernate.dialect.pagination.LimitHandler.supportsLimit.

Doc from org.hibernate.dialect.pagination.LimitHandler.supportsLimit.

Does this handler support some form of limiting query results via a SQL clause?

Returns:boolean

True if this handler supports some form of LIMIT.

Annotations
@Override
supportsLimitOffsetback to summary
public boolean supportsLimitOffset()

Overrides org.hibernate.dialect.pagination.AbstractLimitHandler.supportsLimitOffset.

Implements org.hibernate.dialect.pagination.LimitHandler.supportsLimitOffset.

Doc from org.hibernate.dialect.pagination.LimitHandler.supportsLimitOffset.

Does this handler's LIMIT support (if any) additionally support specifying an offset?

Returns:boolean

True if the handler supports an offset within the limit support.

Annotations
@Override
supportsVariableLimitback to summary
public boolean supportsVariableLimit()

Overrides org.hibernate.dialect.pagination.AbstractLimitHandler.supportsVariableLimit.

Doc from org.hibernate.dialect.pagination.AbstractLimitHandler.supportsVariableLimit.

Does this handler support bind variables (i.e., prepared statement parameters) for its limit/offset?

Returns:boolean

True if bind variables can be used; false otherwise.

Annotations
@Override
useMaxForLimitback to summary
public boolean useMaxForLimit()

Overrides org.hibernate.dialect.pagination.AbstractLimitHandler.useMaxForLimit.

Doc from org.hibernate.dialect.pagination.AbstractLimitHandler.useMaxForLimit.

Does the LIMIT clause take a "maximum" row number instead of a total number of returned rows?

This is easiest understood via an example. Consider you have a table with 20 rows, but you only want to retrieve rows number 11 through 20. Generally, a limit with offset would say that the offset = 11 and the limit = 10 (we only want 10 rows at a time); this is specifying the total number of returned rows. Some dialects require that we instead specify offset = 11 and limit = 20, where 20 is the "last" row we want relative to offset (i.e. total number of rows = 20 - 11 = 9)

So essentially, is limit relative from offset? Or is limit absolute?

Returns:boolean

True if limit is relative from offset; false otherwise.

Annotations
@Override
org.hibernate.dialect.pagination back to summary

pack-priv Class SQLServer2005LimitHandler.IgnoreRange

extends Object
Class Inheritance
  • java.lang.Object
  • org.hibernate.dialect.pagination.SQLServer2005LimitHandler.IgnoreRange

Field Summary

Modifier and TypeField and Description
private int
private int

Constructor Summary

AccessConstructor and Description
pack-priv
IgnoreRange(int start, int end)

Method Summary

Modifier and TypeMethod and Description
pack-priv boolean
isWithinRange(int position)

Inherited from java.lang.Object:
cloneequalsfinalizegetClasshashCodenotifynotifyAlltoStringwaitwaitwait

Field Detail

endback to summary
private int end
startback to summary
private int start

Constructor Detail

IgnoreRangeback to summary
pack-priv IgnoreRange(int start, int end)

Method Detail

isWithinRangeback to summary
pack-priv boolean isWithinRange(int position)