HHH-8007 - Fix and test

This commit is contained in:
Lukasz Antoniak 2013-02-15 14:51:07 +01:00 committed by Brett Meyer
parent 68b45f48bb
commit 52f2edfa45
2 changed files with 66 additions and 16 deletions

View File

@ -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,6 +145,10 @@ public class SQLServer2005LimitHandler extends AbstractLimitHandler {
} }
if ( nextComa != -1 ) { if ( nextComa != -1 ) {
String expression = sb.substring( prevComa, nextComa ); String expression = sb.substring( prevComa, nextComa );
if ( selectsMultipleColumns( expression ) ) {
selectsMultipleColumns = true;
}
else {
String alias = getAlias( expression ); String alias = getAlias( expression );
if ( alias == null ) { if ( alias == null ) {
// Inserting alias. It is unlikely that we would have to add alias, but just in case. // Inserting alias. It is unlikely that we would have to add alias, but just in case.
@ -151,12 +158,17 @@ public class SQLServer2005LimitHandler extends AbstractLimitHandler {
nextComa += ( " as " + alias ).length(); 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 );
if ( selectsMultipleColumns( expression ) ) {
selectsMultipleColumns = true;
}
else {
String alias = getAlias( expression ); String alias = getAlias( expression );
if ( alias == null ) { if ( alias == null ) {
// Inserting alias. It is unlikely that we would have to add alias, but just in case. // Inserting alias. It is unlikely that we would have to add alias, but just in case.
@ -164,8 +176,20 @@ public class SQLServer2005LimitHandler extends AbstractLimitHandler {
sb.insert( endPos - 1, " as " + alias ); 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( ".*" );
} }
/** /**

View File

@ -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 );