HHH-8007 - Fix and test
This commit is contained in:
parent
68b45f48bb
commit
52f2edfa45
|
@ -121,10 +121,12 @@ public class SQLServer2005LimitHandler extends AbstractLimitHandler {
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Adds missing aliases in provided SELECT clause and returns coma-separated list of them.
|
* Adds missing aliases in provided SELECT clause and returns coma-separated list of them.
|
||||||
|
* If query takes advantage of expressions like {@literal *} or {@literal {table}.*} inside SELECT clause,
|
||||||
|
* method returns {@literal *}.
|
||||||
*
|
*
|
||||||
* @param sb SQL query.
|
* @param sb SQL query.
|
||||||
*
|
*
|
||||||
* @return List of aliases separated with comas.
|
* @return List of aliases separated with comas or {@literal *}.
|
||||||
*/
|
*/
|
||||||
protected String fillAliasInSelectClause(StringBuilder sb) {
|
protected String fillAliasInSelectClause(StringBuilder sb) {
|
||||||
final List<String> aliases = new LinkedList<String>();
|
final List<String> aliases = new LinkedList<String>();
|
||||||
|
@ -133,6 +135,7 @@ public class SQLServer2005LimitHandler extends AbstractLimitHandler {
|
||||||
int nextComa = startPos;
|
int nextComa = startPos;
|
||||||
int prevComa = startPos;
|
int prevComa = startPos;
|
||||||
int unique = 0;
|
int unique = 0;
|
||||||
|
boolean selectsMultipleColumns = false;
|
||||||
|
|
||||||
while ( nextComa != -1 ) {
|
while ( nextComa != -1 ) {
|
||||||
prevComa = nextComa;
|
prevComa = nextComa;
|
||||||
|
@ -142,30 +145,51 @@ public class SQLServer2005LimitHandler extends AbstractLimitHandler {
|
||||||
}
|
}
|
||||||
if ( nextComa != -1 ) {
|
if ( nextComa != -1 ) {
|
||||||
String expression = sb.substring( prevComa, nextComa );
|
String expression = sb.substring( prevComa, nextComa );
|
||||||
String alias = getAlias( expression );
|
if ( selectsMultipleColumns( expression ) ) {
|
||||||
if ( alias == null ) {
|
selectsMultipleColumns = true;
|
||||||
// Inserting alias. It is unlikely that we would have to add alias, but just in case.
|
}
|
||||||
alias = StringHelper.generateAlias( "page", unique );
|
else {
|
||||||
sb.insert( nextComa, " as " + alias );
|
String alias = getAlias( expression );
|
||||||
++unique;
|
if ( alias == null ) {
|
||||||
nextComa += ( " as " + alias ).length();
|
// Inserting alias. It is unlikely that we would have to add alias, but just in case.
|
||||||
|
alias = StringHelper.generateAlias( "page", unique );
|
||||||
|
sb.insert( nextComa, " as " + alias );
|
||||||
|
++unique;
|
||||||
|
nextComa += ( " as " + alias ).length();
|
||||||
|
}
|
||||||
|
aliases.add( alias );
|
||||||
}
|
}
|
||||||
aliases.add( alias );
|
|
||||||
++nextComa;
|
++nextComa;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
// Processing last column.
|
// Processing last column.
|
||||||
endPos = shallowIndexOfWord( sb, FROM, startPos ); // Refreshing end position, because we might have inserted new alias.
|
endPos = shallowIndexOfWord( sb, FROM, startPos ); // Refreshing end position, because we might have inserted new alias.
|
||||||
String expression = sb.substring( prevComa, endPos );
|
String expression = sb.substring( prevComa, endPos );
|
||||||
String alias = getAlias( expression );
|
if ( selectsMultipleColumns( expression ) ) {
|
||||||
if ( alias == null ) {
|
selectsMultipleColumns = true;
|
||||||
// Inserting alias. It is unlikely that we would have to add alias, but just in case.
|
}
|
||||||
alias = StringHelper.generateAlias( "page", unique );
|
else {
|
||||||
sb.insert( endPos - 1, " as " + alias );
|
String alias = getAlias( expression );
|
||||||
|
if ( alias == null ) {
|
||||||
|
// Inserting alias. It is unlikely that we would have to add alias, but just in case.
|
||||||
|
alias = StringHelper.generateAlias( "page", unique );
|
||||||
|
sb.insert( endPos - 1, " as " + alias );
|
||||||
|
}
|
||||||
|
aliases.add( alias );
|
||||||
}
|
}
|
||||||
aliases.add( alias );
|
|
||||||
|
|
||||||
return StringHelper.join( ", ", aliases.iterator() );
|
// In case of '*' or '{table}.*' expressions adding an alias breaks SQL syntax, returning '*'.
|
||||||
|
return selectsMultipleColumns ? "*" : StringHelper.join( ", ", aliases.iterator() );
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param expression Select expression.
|
||||||
|
*
|
||||||
|
* @return {@code true} when expression selects multiple columns, {@code false} otherwise.
|
||||||
|
*/
|
||||||
|
private boolean selectsMultipleColumns(String expression) {
|
||||||
|
final String lastExpr = expression.trim().replaceFirst( "(?i)(.)*\\s", "" );
|
||||||
|
return "*".equals( lastExpr ) || lastExpr.endsWith( ".*" );
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
|
@ -168,6 +168,32 @@ public class SQLServer2005DialectTestCase extends BaseUnitTestCase {
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
@TestForIssue(jiraKey = "HHH-8007")
|
||||||
|
public void testGetLimitStringSelectingMultipleColumnsFromSeveralTables() {
|
||||||
|
final String query = "select t1.*, t2.* from tab1 t1, tab2 t2 where t1.ref = t2.ref order by t1.id desc";
|
||||||
|
|
||||||
|
assertEquals(
|
||||||
|
"WITH query AS (SELECT inner_query.*, ROW_NUMBER() OVER (ORDER BY CURRENT_TIMESTAMP) as __hibernate_row_nr__ FROM ( " +
|
||||||
|
"select TOP(?) t1.*, t2.* from tab1 t1, tab2 t2 where t1.ref = t2.ref order by t1.id desc ) inner_query ) " +
|
||||||
|
"SELECT * FROM query WHERE __hibernate_row_nr__ >= ? AND __hibernate_row_nr__ < ?",
|
||||||
|
dialect.buildLimitHandler( query, toRowSelection( 1, 3 ) ).getProcessedSql()
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
@TestForIssue(jiraKey = "HHH-8007")
|
||||||
|
public void testGetLimitStringSelectingAllColumns() {
|
||||||
|
final String query = "select * from tab1 t1, tab2 t2 where t1.ref = t2.ref order by t1.id desc";
|
||||||
|
|
||||||
|
assertEquals(
|
||||||
|
"WITH query AS (SELECT inner_query.*, ROW_NUMBER() OVER (ORDER BY CURRENT_TIMESTAMP) as __hibernate_row_nr__ FROM ( " +
|
||||||
|
"select TOP(?) * from tab1 t1, tab2 t2 where t1.ref = t2.ref order by t1.id desc ) inner_query ) " +
|
||||||
|
"SELECT * FROM query WHERE __hibernate_row_nr__ >= ? AND __hibernate_row_nr__ < ?",
|
||||||
|
dialect.buildLimitHandler( query, toRowSelection( 1, 3 ) ).getProcessedSql()
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
private RowSelection toRowSelection(int firstRow, int maxRows) {
|
private RowSelection toRowSelection(int firstRow, int maxRows) {
|
||||||
RowSelection selection = new RowSelection();
|
RowSelection selection = new RowSelection();
|
||||||
selection.setFirstRow( firstRow );
|
selection.setFirstRow( firstRow );
|
||||||
|
|
Loading…
Reference in New Issue