From 2ec009440e5a9b8d940e6b242851765facf9e1d6 Mon Sep 17 00:00:00 2001 From: Yoryos Valotasios Date: Wed, 10 Nov 2010 22:03:47 +0200 Subject: [PATCH 01/15] SQLServerDialect fallback to the pre HHH-2655 one --- .../hibernate/dialect/SQLServerDialect.java | 124 ++---------------- 1 file changed, 13 insertions(+), 111 deletions(-) diff --git a/hibernate-core/src/main/java/org/hibernate/dialect/SQLServerDialect.java b/hibernate-core/src/main/java/org/hibernate/dialect/SQLServerDialect.java index 1a517a6dd7..d456c2d688 100644 --- a/hibernate-core/src/main/java/org/hibernate/dialect/SQLServerDialect.java +++ b/hibernate-core/src/main/java/org/hibernate/dialect/SQLServerDialect.java @@ -26,9 +26,9 @@ package org.hibernate.dialect; import java.sql.Types; import org.hibernate.LockMode; -import org.hibernate.dialect.function.AnsiTrimEmulationFunction; import org.hibernate.dialect.function.SQLFunctionTemplate; import org.hibernate.dialect.function.StandardSQLFunction; +import org.hibernate.dialect.function.AnsiTrimEmulationFunction; import org.hibernate.type.StandardBasicTypes; /** @@ -37,11 +37,7 @@ import org.hibernate.type.StandardBasicTypes; * @author Gavin King */ public class SQLServerDialect extends AbstractTransactSQLDialect { - private static final String SELECT = "select"; - private static final String FROM = "from"; - private static final String DISTINCT = "distinct"; - - + public SQLServerDialect() { registerColumnType( Types.VARBINARY, "image" ); registerColumnType( Types.VARBINARY, 8000, "varbinary($l)" ); @@ -72,103 +68,14 @@ public class SQLServerDialect extends AbstractTransactSQLDialect { return selectIndex + ( selectDistinctIndex == selectIndex ? 15 : 6 ); } - /** - * 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 ROW_NUMBER() OVER (ORDER BY orderby) as __hibernate_row_nr__, original_query_without_orderby)
-	 * SELECT * FROM query WHERE __hibernate_row_nr__ BEETWIN offset AND offset + last
-	 * 
- * - * - * @param querySqlString The SQL statement to base the limit query off of. - * @param offset Offset of the first row to be returned by the query (zero-based) - * @param limit Maximum number of rows to be returned by the query - * - * @return A new SQL statement with the LIMIT clause applied. - */ - @Override - public String getLimitString(String querySqlString, int offset, int limit) { - if ( offset == 0 ) { - return new StringBuffer( querySqlString.length() + 8 ).append( querySqlString ) - .insert( getAfterSelectInsertPoint( querySqlString ), " top " + limit ) - .toString(); + public String getLimitString(String querySelect, int offset, int limit) { + if ( offset > 0 ) { + throw new UnsupportedOperationException( "query result offset is not supported" ); } - - StringBuilder sb = new StringBuilder( querySqlString.trim().toLowerCase() ); - - int orderByIndex = sb.indexOf( "order by" ); - CharSequence orderby = orderByIndex > 0 ? sb.subSequence( orderByIndex, sb.length() ) : "ORDER BY CURRENT_TIMESTAMP"; - - // Delete the order by clause at the end of the query - if ( orderByIndex > 0 ) { - sb.delete( orderByIndex, orderByIndex + orderby.length() ); - } - - // HHH-5715 bug fix - replaceDistinctWithGroupBy( sb ); - - insertRowNumberFunction( sb, orderby ); - - //Wrap the query within a with statement: - sb.insert( 0, "WITH query AS (").append(") SELECT * FROM query " ); - sb.append( "WHERE __hibernate_row_nr__ BETWEEN " ).append(offset + 1).append( " AND " ).append( limit ); - - return sb.toString(); - } - - /** - * Utility method that checks if the given sql query is a select distinct one and if so replaces the distinct - * select with an equivelant simple select with a group by clause. See {@link SQLServerDialectTestCase#testReplaceDistinctWithGroupBy()} - * - * @param an sql query - */ - protected static void replaceDistinctWithGroupBy(StringBuilder sql) { - int distinctIndex = sql.indexOf( DISTINCT ); - if (distinctIndex > 0) { - sql.delete(distinctIndex, distinctIndex + DISTINCT.length() + 1); - sql.append(" group by").append(getSelectFieldsWithoutAliases(sql)); - } - } - - /** - * This utility method searches the given sql query for the fields of the select statement and - * returns them without the aliases. See {@link SQLServerDialectTestCase#testGetSelectFieldsWithoutAliases()} - * - * @param an sql query - * @return the fields of the select statement without their alias - */ - protected static CharSequence getSelectFieldsWithoutAliases(StringBuilder sql) { - String select = sql.substring( sql.indexOf(SELECT) + SELECT.length(), sql.indexOf(FROM)); - - // Strip the as clauses - return stripAliases( select ); - } - - /** - * Utility method that strips the aliases. See {@link SQLServerDialectTestCase#testStripAliases()} - * - * @param a string to replace the as statements - * @return a string without the as statements - */ - protected static String stripAliases(String str) { - return str.replaceAll( "\\sas[^,]+(,?)", "$1" ); - } - - /** - * Right after the select statement of a given query we must place the row_number function - * - * @param sql the initial sql query without the order by clause - * @param orderby the order by clause of the query - */ - protected static void insertRowNumberFunction(StringBuilder sql, CharSequence orderby) { - // Find the end of the select statement - int selectEndIndex = sql.indexOf( SELECT ) + SELECT.length(); - - // Isert after the select statement the row_number() function: - sql.insert( selectEndIndex, " ROW_NUMBER() OVER (" + orderby + ") as __hibernate_row_nr__," ); + return new StringBuffer( querySelect.length() + 8 ) + .append( querySelect ) + .insert( getAfterSelectInsertPoint( querySelect ), " top " + limit ) + .toString(); } /** @@ -187,11 +94,6 @@ public class SQLServerDialect extends AbstractTransactSQLDialect { } public boolean supportsLimitOffset() { - return true; - } - - @Override - public boolean bindLimitParametersFirst() { return false; } @@ -209,9 +111,9 @@ public class SQLServerDialect extends AbstractTransactSQLDialect { public String appendLockHint(LockMode mode, String tableName) { if ( ( mode == LockMode.UPGRADE ) || - ( mode == LockMode.UPGRADE_NOWAIT ) || - ( mode == LockMode.PESSIMISTIC_WRITE ) || - ( mode == LockMode.WRITE ) ) { + ( mode == LockMode.UPGRADE_NOWAIT ) || + ( mode == LockMode.PESSIMISTIC_WRITE ) || + ( mode == LockMode.WRITE ) ) { return tableName + " with (updlock, rowlock)"; } else if ( mode == LockMode.PESSIMISTIC_READ ) { @@ -224,7 +126,6 @@ public class SQLServerDialect extends AbstractTransactSQLDialect { // The current_timestamp is more accurate, but only known to be supported // in SQL Server 7.0 and later (i.e., Sybase not known to support it at all) - public String getCurrentTimestampSelectString() { return "select current_timestamp"; } @@ -260,3 +161,4 @@ public class SQLServerDialect extends AbstractTransactSQLDialect { } } + From e3ad6c881e37f2e65242425e8149ecc21bdae66b Mon Sep 17 00:00:00 2001 From: Yoryos Valotasios Date: Wed, 10 Nov 2010 22:05:23 +0200 Subject: [PATCH 02/15] SQLServer2005Dialect: supports sql server 2005 but not 2000 --- .../dialect/SQLServer2005Dialect.java | 173 ++++++++++++++++++ 1 file changed, 173 insertions(+) create mode 100644 hibernate-core/src/main/java/org/hibernate/dialect/SQLServer2005Dialect.java diff --git a/hibernate-core/src/main/java/org/hibernate/dialect/SQLServer2005Dialect.java b/hibernate-core/src/main/java/org/hibernate/dialect/SQLServer2005Dialect.java new file mode 100644 index 0000000000..c959530f74 --- /dev/null +++ b/hibernate-core/src/main/java/org/hibernate/dialect/SQLServer2005Dialect.java @@ -0,0 +1,173 @@ +/* + * Hibernate, Relational Persistence for Idiomatic Java + * + * Copyright (c) 2010, Red Hat Inc. or third-party contributors as + * indicated by the @author tags or express copyright attribution + * statements applied by the authors. All third-party contributions are + * distributed under license by Red Hat Inc. + * + * This copyrighted material is made available to anyone wishing to use, modify, + * copy, or redistribute it subject to the terms and conditions of the GNU + * Lesser General Public License, as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License + * for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this distribution; if not, write to: + * Free Software Foundation, Inc. + * 51 Franklin Street, Fifth Floor + * Boston, MA 02110-1301 USA + */ +package org.hibernate.dialect; + +import org.hibernate.dialect.function.NoArgSQLFunction; +import org.hibernate.type.StandardBasicTypes; + +/** + * A dialect for Microsoft SQL 2005 + * + * @author Yoryos Valotasios + */ +public class SQLServer2005Dialect extends SQLServerDialect { + private static final String SELECT = "select"; + private static final String FROM = "from"; + private static final String DISTINCT = "distinct"; + + public SQLServer2005Dialect() { + registerFunction("row_number", new NoArgSQLFunction("row_number", StandardBasicTypes.INTEGER, true)); + } + + /** + * 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 ROW_NUMBER() OVER (ORDER BY orderby) as __hibernate_row_nr__, 
+	 *   original_query_without_orderby
+	 * )
+	 * SELECT * FROM query WHERE __hibernate_row_nr__ BEETWIN offset AND offset + last
+	 * 
+ * + * + * @param querySqlString + * The SQL statement to base the limit query off of. + * @param offset + * Offset of the first row to be returned by the query (zero-based) + * @param limit + * Maximum number of rows to be returned by the query + * + * @return A new SQL statement with the LIMIT clause applied. + */ + @Override + public String getLimitString(String querySqlString, int offset, int limit) { + StringBuilder sb = new StringBuilder(querySqlString.trim().toLowerCase()); + + int orderByIndex = sb.indexOf("order by"); + CharSequence orderby = orderByIndex > 0 ? sb.subSequence(orderByIndex, sb.length()) + : "ORDER BY CURRENT_TIMESTAMP"; + + // Delete the order by clause at the end of the query + if (orderByIndex > 0) { + sb.delete(orderByIndex, orderByIndex + orderby.length()); + } + + // HHH-5715 bug fix + replaceDistinctWithGroupBy(sb); + + insertRowNumberFunction(sb, orderby); + + // Wrap the query within a with statement: + sb.insert(0, "WITH query AS (").append(") SELECT * FROM query "); + sb.append("WHERE __hibernate_row_nr__ BETWEEN ").append(offset + 1).append(" AND ").append(limit); + + return sb.toString(); + } + + /** + * Utility method that checks if the given sql query is a select distinct one and if so replaces the distinct select + * with an equivelant simple select with a group by clause. See + * {@link SQLServer2005DialectTestCase#testReplaceDistinctWithGroupBy()} + * + * @param an + * sql query + */ + protected static void replaceDistinctWithGroupBy(StringBuilder sql) { + int distinctIndex = sql.indexOf(DISTINCT); + if (distinctIndex > 0) { + sql.delete(distinctIndex, distinctIndex + DISTINCT.length() + 1); + sql.append(" group by").append(getSelectFieldsWithoutAliases(sql)); + } + } + + /** + * This utility method searches the given sql query for the fields of the select statement and returns them without + * the aliases. See {@link SQLServer2005DialectTestCase#testGetSelectFieldsWithoutAliases()} + * + * @param an + * sql query + * @return the fields of the select statement without their alias + */ + protected static CharSequence getSelectFieldsWithoutAliases(StringBuilder sql) { + String select = sql.substring(sql.indexOf(SELECT) + SELECT.length(), sql.indexOf(FROM)); + + // Strip the as clauses + return stripAliases(select); + } + + /** + * Utility method that strips the aliases. See {@link SQLServer2005DialectTestCase#testStripAliases()} + * + * @param a + * string to replace the as statements + * @return a string without the as statements + */ + protected static String stripAliases(String str) { + return str.replaceAll("\\sas[^,]+(,?)", "$1"); + } + + /** + * Right after the select statement of a given query we must place the row_number function + * + * @param sql + * the initial sql query without the order by clause + * @param orderby + * the order by clause of the query + */ + protected static void insertRowNumberFunction(StringBuilder sql, CharSequence orderby) { + // Find the end of the select statement + int selectEndIndex = sql.indexOf(SELECT) + SELECT.length(); + + // Isert after the select statement the row_number() function: + sql.insert(selectEndIndex, " ROW_NUMBER() OVER (" + orderby + ") as __hibernate_row_nr__,"); + } + + @Override + public boolean supportsLimit() { + return true; + } + + @Override + public boolean useMaxForLimit() { + return true; + } + + @Override + public boolean supportsLimitOffset() { + return true; + } + + @Override + public boolean bindLimitParametersFirst() { + return false; + } + + public boolean supportsVariableLimit() { + return false; + } + +} From ae271db9baf3b44d2921d271418f98be6549f56b Mon Sep 17 00:00:00 2001 From: Yoryos Valotasios Date: Wed, 10 Nov 2010 22:06:42 +0200 Subject: [PATCH 03/15] renamed the old SQLServerDialect unit tests to SQLServer2005DialectTestCase --- ...TestCase.java => SQLServer2005DialectTestCase.java} | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) rename hibernate-core/src/test/java/org/hibernate/dialect/{SQLServerDialectTestCase.java => SQLServer2005DialectTestCase.java} (77%) diff --git a/hibernate-core/src/test/java/org/hibernate/dialect/SQLServerDialectTestCase.java b/hibernate-core/src/test/java/org/hibernate/dialect/SQLServer2005DialectTestCase.java similarity index 77% rename from hibernate-core/src/test/java/org/hibernate/dialect/SQLServerDialectTestCase.java rename to hibernate-core/src/test/java/org/hibernate/dialect/SQLServer2005DialectTestCase.java index a14857ec1a..da0ac56af1 100644 --- a/hibernate-core/src/test/java/org/hibernate/dialect/SQLServerDialectTestCase.java +++ b/hibernate-core/src/test/java/org/hibernate/dialect/SQLServer2005DialectTestCase.java @@ -8,17 +8,17 @@ import junit.framework.TestCase; * @author Valotasion Yoryos * */ -public class SQLServerDialectTestCase extends TestCase { +public class SQLServer2005DialectTestCase extends TestCase { public void testStripAliases() { String input = "some_field1 as f1, some_fild2 as f2, _field3 as f3 "; - assertEquals( "some_field1, some_fild2, _field3", SQLServerDialect.stripAliases(input) ); + assertEquals( "some_field1, some_fild2, _field3", SQLServer2005Dialect.stripAliases(input) ); } public void testGetSelectFieldsWithoutAliases() { StringBuilder input = new StringBuilder( "select some_field1 as f12, some_fild2 as f879, _field3 as _f24674_3 from...." ); - String output = SQLServerDialect.getSelectFieldsWithoutAliases( input ).toString(); + String output = SQLServer2005Dialect.getSelectFieldsWithoutAliases( input ).toString(); assertEquals( " some_field1, some_fild2, _field3", output ); } @@ -26,7 +26,7 @@ public class SQLServerDialectTestCase extends TestCase { public void testReplaceDistinctWithGroupBy() { StringBuilder input = new StringBuilder( "select distinct f1, f2 as ff, f3 from table where f1 = 5" ); - SQLServerDialect.replaceDistinctWithGroupBy( input ); + SQLServer2005Dialect.replaceDistinctWithGroupBy( input ); assertEquals( "select f1, f2 as ff, f3 from table where f1 = 5 group by f1, f2, f3 ", input.toString() ); } @@ -35,7 +35,7 @@ public class SQLServerDialectTestCase extends TestCase { public void testGetLimitString() { String input = "select distinct f1 as f53245 from table849752 order by f234, f67 desc"; - SQLServerDialect sqlDialect = new SQLServerDialect(); + Dialect sqlDialect = new SQLServer2005Dialect(); assertEquals( "with query as (select row_number() over (order by f234, f67 desc) as __hibernate_row_nr__, f1 as f53245 from table849752 group by f1) select * from query where __hibernate_row_nr__ between 11 and 15", sqlDialect.getLimitString(input, 10, 15).toLowerCase() ); } From 9e2902807c8bd3dd4bab8963ad26dc18f9a0994d Mon Sep 17 00:00:00 2001 From: Yoryos Valotasios Date: Sun, 14 Nov 2010 23:31:20 +0200 Subject: [PATCH 04/15] Make use of generics for the Dialect and TypeNames class --- .../java/org/hibernate/dialect/Dialect.java | 6 +++--- .../java/org/hibernate/dialect/TypeNames.java | 17 +++++++---------- 2 files changed, 10 insertions(+), 13 deletions(-) diff --git a/hibernate-core/src/main/java/org/hibernate/dialect/Dialect.java b/hibernate-core/src/main/java/org/hibernate/dialect/Dialect.java index fdf7a3ad3d..70bf56e328 100644 --- a/hibernate-core/src/main/java/org/hibernate/dialect/Dialect.java +++ b/hibernate-core/src/main/java/org/hibernate/dialect/Dialect.java @@ -99,7 +99,7 @@ public abstract class Dialect { private final Properties properties = new Properties(); private final Map sqlFunctions = new HashMap(); - private final Set sqlKeywords = new HashSet(); + private final Set sqlKeywords = new HashSet(); // constructors and factory methods ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ @@ -373,7 +373,7 @@ public abstract class Dialect { * * @return The map of registered functions. */ - public final Map getFunctions() { + public final Map getFunctions() { return sqlFunctions; } @@ -384,7 +384,7 @@ public abstract class Dialect { sqlKeywords.add(word); } - public Set getKeywords() { + public Set getKeywords() { return sqlKeywords; } diff --git a/hibernate-core/src/main/java/org/hibernate/dialect/TypeNames.java b/hibernate-core/src/main/java/org/hibernate/dialect/TypeNames.java index fcf5454b6a..f5d06fa3d8 100644 --- a/hibernate-core/src/main/java/org/hibernate/dialect/TypeNames.java +++ b/hibernate-core/src/main/java/org/hibernate/dialect/TypeNames.java @@ -26,7 +26,6 @@ package org.hibernate.dialect; import java.util.Map; import java.util.HashMap; import java.util.TreeMap; -import java.util.Iterator; import org.hibernate.MappingException; import org.hibernate.util.StringHelper; @@ -65,8 +64,8 @@ import org.hibernate.util.StringHelper; */ public class TypeNames { - private HashMap weighted = new HashMap(); - private HashMap defaults = new HashMap(); + private Map> weighted = new HashMap>(); + private Map defaults = new HashMap(); /** * get default type name for specified type @@ -74,7 +73,7 @@ public class TypeNames { * @return the default type name associated with specified key */ public String get(int typecode) throws MappingException { - String result = (String) defaults.get( new Integer(typecode) ); + String result = defaults.get( new Integer(typecode) ); if (result==null) throw new MappingException("No Dialect mapping for JDBC type: " + typecode); return result; } @@ -89,12 +88,10 @@ public class TypeNames { * if available and the default type name otherwise */ public String get(int typecode, int size, int precision, int scale) throws MappingException { - Map map = (Map) weighted.get( new Integer(typecode) ); + Map map = weighted.get( new Integer(typecode) ); if ( map!=null && map.size()>0 ) { // iterate entries ordered by capacity to find first fit - Iterator entries = map.entrySet().iterator(); - while ( entries.hasNext() ) { - Map.Entry entry = (Map.Entry)entries.next(); + for (Map.Entry entry: map.entrySet()) { if ( size <= ( (Integer) entry.getKey() ).intValue() ) { return replace( (String) entry.getValue(), size, precision, scale ); } @@ -114,9 +111,9 @@ public class TypeNames { * @param typecode the type key */ public void put(int typecode, int capacity, String value) { - TreeMap map = (TreeMap)weighted.get( new Integer(typecode) ); + Map map = weighted.get( new Integer(typecode) ); if (map == null) {// add new ordered map - map = new TreeMap(); + map = new TreeMap(); weighted.put( new Integer(typecode), map ); } map.put(new Integer(capacity), value); From c9833f3eaa04890652091f8709f10130866e0518 Mon Sep 17 00:00:00 2001 From: Yoryos Valotasios Date: Sun, 14 Nov 2010 23:51:15 +0200 Subject: [PATCH 05/15] HHH-3965 fix, make use of varbinary(max) and varchar(max) --- .../hibernate/dialect/SQLServer2005Dialect.java | 16 ++++++++++++++++ 1 file changed, 16 insertions(+) diff --git a/hibernate-core/src/main/java/org/hibernate/dialect/SQLServer2005Dialect.java b/hibernate-core/src/main/java/org/hibernate/dialect/SQLServer2005Dialect.java index c959530f74..3706e307fc 100644 --- a/hibernate-core/src/main/java/org/hibernate/dialect/SQLServer2005Dialect.java +++ b/hibernate-core/src/main/java/org/hibernate/dialect/SQLServer2005Dialect.java @@ -23,6 +23,8 @@ */ package org.hibernate.dialect; +import java.sql.Types; + import org.hibernate.dialect.function.NoArgSQLFunction; import org.hibernate.type.StandardBasicTypes; @@ -35,8 +37,22 @@ public class SQLServer2005Dialect extends SQLServerDialect { private static final String SELECT = "select"; private static final String FROM = "from"; private static final String DISTINCT = "distinct"; + private static final int MAX_LENGTH = 8000; public SQLServer2005Dialect() { + // HHH-3965 fix + // As per http://www.sql-server-helper.com/faq/sql-server-2005-varchar-max-p01.aspx + // use varchar(max) and varbinary(max) instead of TEXT and IMAGE types + registerColumnType( Types.VARBINARY, "varbinary(MAX)" ); + registerColumnType( Types.VARBINARY, MAX_LENGTH, "varbinary($l)" ); + + registerColumnType( Types.LONGVARBINARY, "varbinary(MAX)" ); + registerColumnType( Types.LONGVARCHAR, "varchar(MAX)" ); + + registerColumnType( Types.VARCHAR, "varchar(MAX)" ); + registerColumnType( Types.VARCHAR, MAX_LENGTH, "varchar($l)" ); + + registerFunction("row_number", new NoArgSQLFunction("row_number", StandardBasicTypes.INTEGER, true)); } From 2964b975ef05173949f2700a33c3297923832ccd Mon Sep 17 00:00:00 2001 From: Yoryos Valotasios Date: Sun, 14 Nov 2010 23:55:06 +0200 Subject: [PATCH 06/15] HHH-3965: registered some more columntypes as varchar(max) and varbinary(max) --- .../java/org/hibernate/dialect/SQLServer2005Dialect.java | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/hibernate-core/src/main/java/org/hibernate/dialect/SQLServer2005Dialect.java b/hibernate-core/src/main/java/org/hibernate/dialect/SQLServer2005Dialect.java index 3706e307fc..2844a8f171 100644 --- a/hibernate-core/src/main/java/org/hibernate/dialect/SQLServer2005Dialect.java +++ b/hibernate-core/src/main/java/org/hibernate/dialect/SQLServer2005Dialect.java @@ -43,12 +43,13 @@ public class SQLServer2005Dialect extends SQLServerDialect { // HHH-3965 fix // As per http://www.sql-server-helper.com/faq/sql-server-2005-varchar-max-p01.aspx // use varchar(max) and varbinary(max) instead of TEXT and IMAGE types + registerColumnType( Types.BLOB, "varbinary(MAX)" ); registerColumnType( Types.VARBINARY, "varbinary(MAX)" ); registerColumnType( Types.VARBINARY, MAX_LENGTH, "varbinary($l)" ); - registerColumnType( Types.LONGVARBINARY, "varbinary(MAX)" ); - registerColumnType( Types.LONGVARCHAR, "varchar(MAX)" ); + registerColumnType( Types.CLOB, "varchar(MAX)" ); + registerColumnType( Types.LONGVARCHAR, "varchar(MAX)" ); registerColumnType( Types.VARCHAR, "varchar(MAX)" ); registerColumnType( Types.VARCHAR, MAX_LENGTH, "varchar($l)" ); From ceba976e5740cfe7dfb0bfc3d31409d732efc210 Mon Sep 17 00:00:00 2001 From: Yoryos Valotasios Date: Sun, 14 Nov 2010 23:56:33 +0200 Subject: [PATCH 07/15] SQLServer2008Dialect should extend SQLServer2005Dialect --- .../main/java/org/hibernate/dialect/SQLServer2008Dialect.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/hibernate-core/src/main/java/org/hibernate/dialect/SQLServer2008Dialect.java b/hibernate-core/src/main/java/org/hibernate/dialect/SQLServer2008Dialect.java index fcf26c89fb..022c44826a 100644 --- a/hibernate-core/src/main/java/org/hibernate/dialect/SQLServer2008Dialect.java +++ b/hibernate-core/src/main/java/org/hibernate/dialect/SQLServer2008Dialect.java @@ -33,7 +33,7 @@ import org.hibernate.type.StandardBasicTypes; * * @author Gavin King */ -public class SQLServer2008Dialect extends SQLServerDialect { +public class SQLServer2008Dialect extends SQLServer2005Dialect { public SQLServer2008Dialect() { registerColumnType( Types.DATE, "date" ); registerColumnType( Types.TIME, "time" ); From 571318e6e462c186533e65d6d43d55e9e8c530f8 Mon Sep 17 00:00:00 2001 From: Yoryos Valotasios Date: Mon, 15 Nov 2010 00:12:10 +0200 Subject: [PATCH 08/15] Added comments. The dialect should also fix HHH-3936 --- .../main/java/org/hibernate/dialect/SQLServer2005Dialect.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/hibernate-core/src/main/java/org/hibernate/dialect/SQLServer2005Dialect.java b/hibernate-core/src/main/java/org/hibernate/dialect/SQLServer2005Dialect.java index 2844a8f171..bba9f034cb 100644 --- a/hibernate-core/src/main/java/org/hibernate/dialect/SQLServer2005Dialect.java +++ b/hibernate-core/src/main/java/org/hibernate/dialect/SQLServer2005Dialect.java @@ -29,7 +29,7 @@ import org.hibernate.dialect.function.NoArgSQLFunction; import org.hibernate.type.StandardBasicTypes; /** - * A dialect for Microsoft SQL 2005 + * A dialect for Microsoft SQL 2005. (HHH-3936 fix) * * @author Yoryos Valotasios */ From 71cef3831d49cbab8be646363de51ae140573edd Mon Sep 17 00:00:00 2001 From: Yoryos Valotasios Date: Mon, 15 Nov 2010 00:33:09 +0200 Subject: [PATCH 09/15] SQLServer2005Dialect: Added @Override to the supportsVariableLimit method --- .../main/java/org/hibernate/dialect/SQLServer2005Dialect.java | 1 + 1 file changed, 1 insertion(+) diff --git a/hibernate-core/src/main/java/org/hibernate/dialect/SQLServer2005Dialect.java b/hibernate-core/src/main/java/org/hibernate/dialect/SQLServer2005Dialect.java index bba9f034cb..8d8c27f859 100644 --- a/hibernate-core/src/main/java/org/hibernate/dialect/SQLServer2005Dialect.java +++ b/hibernate-core/src/main/java/org/hibernate/dialect/SQLServer2005Dialect.java @@ -183,6 +183,7 @@ public class SQLServer2005Dialect extends SQLServerDialect { return false; } + @Override public boolean supportsVariableLimit() { return false; } From 11a98623e58b000165ff7d42cf04599ffa8e992d Mon Sep 17 00:00:00 2001 From: Yoryos Valotasios Date: Mon, 15 Nov 2010 00:58:57 +0200 Subject: [PATCH 10/15] Dialect: Improved exception messages by adding the dialect class name --- .../java/org/hibernate/dialect/Dialect.java | 22 +++++++++---------- 1 file changed, 11 insertions(+), 11 deletions(-) diff --git a/hibernate-core/src/main/java/org/hibernate/dialect/Dialect.java b/hibernate-core/src/main/java/org/hibernate/dialect/Dialect.java index 70bf56e328..70658c749e 100644 --- a/hibernate-core/src/main/java/org/hibernate/dialect/Dialect.java +++ b/hibernate-core/src/main/java/org/hibernate/dialect/Dialect.java @@ -197,7 +197,7 @@ public abstract class Dialect { throw new HibernateException( "Dialect class not found: " + dialectName ); } catch ( Exception e ) { - throw new HibernateException( "Could not instantiate dialect class", e ); + throw new HibernateException( "Could not instantiate given dialect class: " + dialectName, e ); } } @@ -481,7 +481,7 @@ public abstract class Dialect { * @throws MappingException If IDENTITY generation is not supported. */ protected String getIdentitySelectString() throws MappingException { - throw new MappingException( "Dialect does not support identity key generation" ); + throw new MappingException( getClass().getName() + " does not support identity key generation" ); } /** @@ -503,7 +503,7 @@ public abstract class Dialect { * @throws MappingException If IDENTITY generation is not supported. */ protected String getIdentityColumnString() throws MappingException { - throw new MappingException( "Dialect does not support identity key generation" ); + throw new MappingException( getClass().getName() + " does not support identity key generation" ); } /** @@ -551,7 +551,7 @@ public abstract class Dialect { * @throws MappingException If sequences are not supported. */ public String getSequenceNextValString(String sequenceName) throws MappingException { - throw new MappingException( "Dialect does not support sequences" ); + throw new MappingException( getClass().getName() + " does not support sequences" ); } /** @@ -566,7 +566,7 @@ public abstract class Dialect { * @throws MappingException If sequences are not supported. */ public String getSelectSequenceNextValString(String sequenceName) throws MappingException { - throw new MappingException( "Dialect does not support sequences" ); + throw new MappingException( getClass().getName() + " does not support sequences" ); } /** @@ -609,7 +609,7 @@ public abstract class Dialect { * @throws MappingException If sequences are not supported. */ protected String getCreateSequenceString(String sequenceName) throws MappingException { - throw new MappingException( "Dialect does not support sequences" ); + throw new MappingException( getClass().getName() + " does not support sequences" ); } /** @@ -633,7 +633,7 @@ public abstract class Dialect { if ( supportsPooledSequences() ) { return getCreateSequenceString( sequenceName ) + " start with " + initialValue + " increment by " + incrementSize; } - throw new MappingException( "Dialect does not support pooled sequences" ); + throw new MappingException( getClass().getName() + " does not support pooled sequences" ); } /** @@ -662,7 +662,7 @@ public abstract class Dialect { * @throws MappingException If sequences are not supported. */ protected String getDropSequenceString(String sequenceName) throws MappingException { - throw new MappingException( "Dialect does not support sequences" ); + throw new MappingException( getClass().getName() + " does not support sequences" ); } /** @@ -686,7 +686,7 @@ public abstract class Dialect { * @return The appropriate command. */ public String getSelectGUIDString() { - throw new UnsupportedOperationException( "dialect does not support GUIDs" ); + throw new UnsupportedOperationException( getClass().getName() + " does not support GUIDs" ); } @@ -802,7 +802,7 @@ public abstract class Dialect { * @return the modified SQL */ protected String getLimitString(String query, boolean hasOffset) { - throw new UnsupportedOperationException( "paged queries not supported" ); + throw new UnsupportedOperationException( "Paged queries not supported by " + getClass().getName()); } /** @@ -1502,7 +1502,7 @@ public abstract class Dialect { * @return The "add column" fragment. */ public String getAddColumnString() { - throw new UnsupportedOperationException( "No add column syntax supported by Dialect" ); + throw new UnsupportedOperationException( "No add column syntax supported by " + getClass().getName() ); } public String getDropForeignKeyString() { From b47dc5aedab3267b296aee5b34ff28b4e0186d57 Mon Sep 17 00:00:00 2001 From: Yoryos Valotasios Date: Tue, 23 Nov 2010 00:19:22 +0200 Subject: [PATCH 11/15] SQLServer2005Dialect: modifications in order to support variable limit --- .../dialect/SQLServer2005Dialect.java | 19 +++++++++++++++---- 1 file changed, 15 insertions(+), 4 deletions(-) diff --git a/hibernate-core/src/main/java/org/hibernate/dialect/SQLServer2005Dialect.java b/hibernate-core/src/main/java/org/hibernate/dialect/SQLServer2005Dialect.java index 8d8c27f859..f0fefab7b1 100644 --- a/hibernate-core/src/main/java/org/hibernate/dialect/SQLServer2005Dialect.java +++ b/hibernate-core/src/main/java/org/hibernate/dialect/SQLServer2005Dialect.java @@ -56,6 +56,17 @@ public class SQLServer2005Dialect extends SQLServerDialect { registerFunction("row_number", new NoArgSQLFunction("row_number", StandardBasicTypes.INTEGER, true)); } + + @Override + public int convertToFirstRowValue(int zeroBasedFirstResult) { + return zeroBasedFirstResult + 1; + } + + @Override + public String getLimitString(String query, int offset, int limit) { + if (offset > 1 || limit > 1) return getLimitString(query, true); + return query; + } /** * Add a LIMIT clause to the given SQL SELECT (HHH-2655: ROW_NUMBER for Paging) @@ -81,7 +92,7 @@ public class SQLServer2005Dialect extends SQLServerDialect { * @return A new SQL statement with the LIMIT clause applied. */ @Override - public String getLimitString(String querySqlString, int offset, int limit) { + public String getLimitString(String querySqlString, boolean hasOffset) { StringBuilder sb = new StringBuilder(querySqlString.trim().toLowerCase()); int orderByIndex = sb.indexOf("order by"); @@ -100,7 +111,8 @@ public class SQLServer2005Dialect extends SQLServerDialect { // Wrap the query within a with statement: sb.insert(0, "WITH query AS (").append(") SELECT * FROM query "); - sb.append("WHERE __hibernate_row_nr__ BETWEEN ").append(offset + 1).append(" AND ").append(limit); + //sb.append("WHERE __hibernate_row_nr__ BETWEEN ").append(offset + 1).append(" AND ").append(limit); + sb.append("WHERE __hibernate_row_nr__ BETWEEN ? AND ?"); return sb.toString(); } @@ -185,7 +197,6 @@ public class SQLServer2005Dialect extends SQLServerDialect { @Override public boolean supportsVariableLimit() { - return false; + return true; } - } From 48239bbbcc2d1a070b4f9bbb7c33a98815e28604 Mon Sep 17 00:00:00 2001 From: Yoryos Valotasios Date: Tue, 23 Nov 2010 00:22:39 +0200 Subject: [PATCH 12/15] Added some comments --- .../main/java/org/hibernate/dialect/SQLServer2005Dialect.java | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/hibernate-core/src/main/java/org/hibernate/dialect/SQLServer2005Dialect.java b/hibernate-core/src/main/java/org/hibernate/dialect/SQLServer2005Dialect.java index f0fefab7b1..1a538eb4ad 100644 --- a/hibernate-core/src/main/java/org/hibernate/dialect/SQLServer2005Dialect.java +++ b/hibernate-core/src/main/java/org/hibernate/dialect/SQLServer2005Dialect.java @@ -59,11 +59,13 @@ public class SQLServer2005Dialect extends SQLServerDialect { @Override public int convertToFirstRowValue(int zeroBasedFirstResult) { - return zeroBasedFirstResult + 1; + // Our dialect isn't zero based. The first row should get the number 1 + return zeroBasedFirstResult + 1; } @Override public String getLimitString(String query, int offset, int limit) { + // We transform the query to one with an offset and limit if we have an offset and limit to bind if (offset > 1 || limit > 1) return getLimitString(query, true); return query; } From f6a349bcb834fbabdcd11ccf29cabbaa886de9b3 Mon Sep 17 00:00:00 2001 From: Yoryos Valotasios Date: Tue, 23 Nov 2010 00:25:14 +0200 Subject: [PATCH 13/15] SQLServer2005Dialect: Moved the small methods on top of the class --- .../dialect/SQLServer2005Dialect.java | 50 +++++++++---------- 1 file changed, 25 insertions(+), 25 deletions(-) diff --git a/hibernate-core/src/main/java/org/hibernate/dialect/SQLServer2005Dialect.java b/hibernate-core/src/main/java/org/hibernate/dialect/SQLServer2005Dialect.java index 1a538eb4ad..fbd3792aa4 100644 --- a/hibernate-core/src/main/java/org/hibernate/dialect/SQLServer2005Dialect.java +++ b/hibernate-core/src/main/java/org/hibernate/dialect/SQLServer2005Dialect.java @@ -57,6 +57,31 @@ public class SQLServer2005Dialect extends SQLServerDialect { registerFunction("row_number", new NoArgSQLFunction("row_number", StandardBasicTypes.INTEGER, true)); } + @Override + public boolean supportsLimit() { + return true; + } + + @Override + public boolean useMaxForLimit() { + return true; + } + + @Override + public boolean supportsLimitOffset() { + return true; + } + + @Override + public boolean bindLimitParametersFirst() { + return false; + } + + @Override + public boolean supportsVariableLimit() { + return true; + } + @Override public int convertToFirstRowValue(int zeroBasedFirstResult) { // Our dialect isn't zero based. The first row should get the number 1 @@ -176,29 +201,4 @@ public class SQLServer2005Dialect extends SQLServerDialect { // Isert after the select statement the row_number() function: sql.insert(selectEndIndex, " ROW_NUMBER() OVER (" + orderby + ") as __hibernate_row_nr__,"); } - - @Override - public boolean supportsLimit() { - return true; - } - - @Override - public boolean useMaxForLimit() { - return true; - } - - @Override - public boolean supportsLimitOffset() { - return true; - } - - @Override - public boolean bindLimitParametersFirst() { - return false; - } - - @Override - public boolean supportsVariableLimit() { - return true; - } } From 2ae06c94697785d4f3405dd864e4d74122051168 Mon Sep 17 00:00:00 2001 From: Yoryos Valotasios Date: Tue, 23 Nov 2010 00:44:02 +0200 Subject: [PATCH 14/15] SQLServer2005Dialect: removed useless commented code --- .../main/java/org/hibernate/dialect/SQLServer2005Dialect.java | 1 - 1 file changed, 1 deletion(-) diff --git a/hibernate-core/src/main/java/org/hibernate/dialect/SQLServer2005Dialect.java b/hibernate-core/src/main/java/org/hibernate/dialect/SQLServer2005Dialect.java index fbd3792aa4..a84616824c 100644 --- a/hibernate-core/src/main/java/org/hibernate/dialect/SQLServer2005Dialect.java +++ b/hibernate-core/src/main/java/org/hibernate/dialect/SQLServer2005Dialect.java @@ -138,7 +138,6 @@ public class SQLServer2005Dialect extends SQLServerDialect { // Wrap the query within a with statement: sb.insert(0, "WITH query AS (").append(") SELECT * FROM query "); - //sb.append("WHERE __hibernate_row_nr__ BETWEEN ").append(offset + 1).append(" AND ").append(limit); sb.append("WHERE __hibernate_row_nr__ BETWEEN ? AND ?"); return sb.toString(); From 38cd2fe25c0dfc58c47cc00f4494c8c14ab86755 Mon Sep 17 00:00:00 2001 From: Yoryos Valotasios Date: Tue, 23 Nov 2010 00:46:48 +0200 Subject: [PATCH 15/15] SQLServer2005Dialect: Made some comments more specific --- .../main/java/org/hibernate/dialect/SQLServer2005Dialect.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/hibernate-core/src/main/java/org/hibernate/dialect/SQLServer2005Dialect.java b/hibernate-core/src/main/java/org/hibernate/dialect/SQLServer2005Dialect.java index a84616824c..dda5008696 100644 --- a/hibernate-core/src/main/java/org/hibernate/dialect/SQLServer2005Dialect.java +++ b/hibernate-core/src/main/java/org/hibernate/dialect/SQLServer2005Dialect.java @@ -84,7 +84,7 @@ public class SQLServer2005Dialect extends SQLServerDialect { @Override public int convertToFirstRowValue(int zeroBasedFirstResult) { - // Our dialect isn't zero based. The first row should get the number 1 + // Our dialect paginated results aren't zero based. The first row should get the number 1 and so on return zeroBasedFirstResult + 1; }