diff --git a/core/src/main/java/org/hibernate/dialect/Ingres10Dialect.java b/core/src/main/java/org/hibernate/dialect/Ingres10Dialect.java
new file mode 100644
index 0000000000..748bd2897f
--- /dev/null
+++ b/core/src/main/java/org/hibernate/dialect/Ingres10Dialect.java
@@ -0,0 +1,22 @@
+package org.hibernate.dialect;
+
+import java.sql.Types;
+
+import org.hibernate.Hibernate;
+import org.hibernate.cfg.Environment;
+import org.hibernate.dialect.function.NoArgSQLFunction;
+
+/**
+ * A SQL dialect for Ingres 10 and later versions.
+ *
+ * Changes:
+ *
+ *
+ * @author Raymond Fan
+ */
+public class Ingres10Dialect extends Ingres9Dialect {
+ public Ingres10Dialect() {
+ super();
+ }
+}
diff --git a/core/src/main/java/org/hibernate/dialect/Ingres9Dialect.java b/core/src/main/java/org/hibernate/dialect/Ingres9Dialect.java
new file mode 100644
index 0000000000..5f5e250f7a
--- /dev/null
+++ b/core/src/main/java/org/hibernate/dialect/Ingres9Dialect.java
@@ -0,0 +1,215 @@
+package org.hibernate.dialect;
+
+import java.sql.Types;
+
+import org.hibernate.Hibernate;
+import org.hibernate.dialect.function.NoArgSQLFunction;
+
+/**
+ * A SQL dialect for Ingres 9.3 and later versions.
+ *
+ * Changes:
+ *
+ * - Support for the SQL functions current_time, current_timestamp and current_date added
+ * - Type mapping of
Types.TIMESTAMP
changed from "timestamp with time zone" to "timestamp(9) with time zone"
+ * - Improved handling of "SELECT...FOR UPDATE" statements
+ * - Added support for pooled sequences
+ * - Added support for SELECT queries with limit and offset
+ * - Added getIdentitySelectString
+ *
+ *
+ * @author Enrico Schenk, Raymond Fan
+ */
+public class Ingres9Dialect extends IngresDialect {
+ public Ingres9Dialect() {
+ super();
+ registerDateTimeFunctions();
+ registerDateTimeColumnTypes();
+ }
+
+ /**
+ * Register functions current_time, current_timestamp, current_date
+ */
+ protected void registerDateTimeFunctions() {
+ registerFunction("current_time", new NoArgSQLFunction("current_time", Hibernate.TIME, false));
+ registerFunction("current_timestamp", new NoArgSQLFunction("current_timestamp", Hibernate.TIMESTAMP, false));
+ registerFunction("current_date", new NoArgSQLFunction("current_date", Hibernate.DATE, false));
+ }
+
+ /**
+ * Register column types date, time, timestamp
+ */
+ protected void registerDateTimeColumnTypes() {
+ registerColumnType(Types.DATE, "ansidate");
+ //registerColumnType(Types.TIME, "time with time zone");
+ registerColumnType(Types.TIMESTAMP, "timestamp(9) with time zone");
+ }
+
+ // lock acquisition support ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+ /**
+ * Does this dialect support FOR UPDATE in conjunction with outer
+ * joined rows?
+ *
+ * @return True if outer joined rows can be locked via FOR UPDATE.
+ */
+ public boolean supportsOuterJoinForUpdate() {
+ return false;
+ }
+
+ /**
+ * Is FOR UPDATE OF syntax supported?
+ *
+ * @return True if the database supports FOR UPDATE OF syntax;
+ * false otherwise.
+ */
+ public boolean forUpdateOfColumns() {
+ return true;
+ }
+
+ // SEQUENCE support ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+ /**
+ * Get the select command used to retrieve the last generated sequence
+ * value.
+ *
+ * @return Statement to retrieve last generated sequence value
+ */
+ public String getIdentitySelectString() {
+ return "select last_identity()";
+ }
+
+ /**
+ * Get the select command used retrieve the names of all sequences.
+ *
+ * @return The select command; or null if sequences are not supported.
+ * @see org.hibernate.tool.hbm2ddl.SchemaUpdate
+ */
+ public String getQuerySequencesString() {
+ return "select seq_name from iisequences";
+ }
+
+ /**
+ * Does this dialect support "pooled" sequences. Not aware of a better name
+ * for this. Essentially can we specify the initial and increment values?
+ *
+ * @return True if such "pooled" sequences are supported; false otherwise.
+ * @see #getCreateSequenceStrings(String, int, int)
+ * @see #getCreateSequenceString(String, int, int)
+ */
+ public boolean supportsPooledSequences() {
+ return true;
+ }
+
+ // current timestamp support ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+ /**
+ * Should the value returned by {@link #getCurrentTimestampSelectString} be
+ * treated as callable. Typically this indicates that JDBC escape sytnax is
+ * being used...
+ *
+ * @return True if the {@link #getCurrentTimestampSelectString} return is
+ * callable; false otherwise.
+ */
+ public boolean isCurrentTimestampSelectStringCallable() {
+ return false;
+ }
+
+ /**
+ * Does this dialect support a way to retrieve the database's current
+ * timestamp value?
+ *
+ * @return True if the current timestamp can be retrieved; false otherwise.
+ */
+ public boolean supportsCurrentTimestampSelection() {
+ return true;
+ }
+
+ /**
+ * Retrieve the command used to retrieve the current timestamp from the
+ * database.
+ *
+ * @return The command.
+ */
+ public String getCurrentTimestampSelectString() {
+ return "select current_timestamp";
+ }
+
+ /**
+ * Expression for current_timestamp
+ */
+ public String getCurrentTimestampSQLFunctionName() {
+ return "current_timestamp";
+ }
+
+ // union subclass support ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+ /**
+ * Does this dialect support UNION ALL, which is generally a faster variant
+ * of UNION?
+ *
+ * @return True if UNION ALL is supported; false otherwise.
+ */
+ public boolean supportsUnionAll() {
+ return true;
+ }
+
+ // Informational metadata ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+ /**
+ * For the underlying database, is READ_COMMITTED isolation implemented by
+ * forcing readers to wait for write locks to be released?
+ *
+ * @return true
+ */
+ public boolean doesReadCommittedCauseWritersToBlockReaders() {
+ return true;
+ }
+
+ /**
+ * For the underlying database, is REPEATABLE_READ isolation implemented by
+ * forcing writers to wait for read locks to be released?
+ *
+ * @return true
+ */
+ public boolean doesRepeatableReadCauseReadersToBlockWriters() {
+ return true;
+ }
+
+ // limit/offset support ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+ /**
+ * Does this dialect's LIMIT support (if any) additionally support
+ * specifying an offset?
+ *
+ * @return true
+ */
+ public boolean supportsLimitOffset() {
+ return true;
+ }
+
+ /**
+ * Does this dialect support bind variables (i.e., prepared statement
+ * parameters) for its limit/offset?
+ *
+ * @return false
+ */
+ public boolean supportsVariableLimit() {
+ return false;
+ }
+
+ /**
+ * Add a LIMIT clause to the given SQL SELECT
+ *
+ * @return the modified SQL
+ */
+ public String getLimitString(String querySelect, int offset, int limit) {
+ StringBuffer sb = new StringBuffer(querySelect.length() + 16);
+ sb.append(querySelect.trim()).insert(6, " first " + limit);
+ if (offset > 0) {
+ sb.append(" offset " + offset);
+ }
+ return sb.toString();
+ }
+
+}
diff --git a/core/src/main/java/org/hibernate/dialect/IngresDialect.java b/core/src/main/java/org/hibernate/dialect/IngresDialect.java
index 3ace608f34..1e19672a89 100644
--- a/core/src/main/java/org/hibernate/dialect/IngresDialect.java
+++ b/core/src/main/java/org/hibernate/dialect/IngresDialect.java
@@ -27,6 +27,7 @@ package org.hibernate.dialect;
import java.sql.Types;
import org.hibernate.Hibernate;
+import org.hibernate.cfg.Environment;
import org.hibernate.dialect.function.SQLFunctionTemplate;
import org.hibernate.dialect.function.NoArgSQLFunction;
import org.hibernate.dialect.function.StandardSQLFunction;
@@ -36,9 +37,12 @@ import org.hibernate.dialect.function.VarArgsSQLFunction;
* An SQL dialect for Ingres 9.2.
*
* Known limitations:
- * - only supports simple constants or columns on the left side of an IN, making (1,2,3) in (...) or (<subselect>) in (...) non-supported
- * - supports only 39 digits in decimal
- *
+ *
+ * - Only supports simple constants or columns on the left side of an IN, making (1,2,3) in (...) or (<subselect>) in (...) non-supported.
+ *
- Supports only 39 digits in decimal.
+ *
- Explicitly set USE_GET_GENERATED_KEYS property to false.
+ *
+ *
* @author Ian Booth, Bruce Lunsford, Max Rydahl Andersen
*/
public class IngresDialect extends Dialect {
@@ -135,6 +139,17 @@ public class IngresDialect extends Dialect {
registerFunction( "uuid_from_char", new StandardSQLFunction( "uuid_from_char", Hibernate.BYTE ) );
registerFunction( "uuid_to_char", new StandardSQLFunction( "uuid_to_char", Hibernate.STRING ) );
registerFunction( "year", new StandardSQLFunction( "year", Hibernate.INTEGER ) );
+ // Ingres driver supports getGeneratedKeys but only in the following
+ // form:
+ // The Ingres DBMS returns only a single table key or a single object
+ // key per insert statement. Ingres does not return table and object
+ // keys for INSERT AS SELECT statements. Depending on the keys that are
+ // produced by the statement executed, auto-generated key parameters in
+ // execute(), executeUpdate(), and prepareStatement() methods are
+ // ignored and getGeneratedKeys() returns a result-set containing no
+ // rows, a single row with one column, or a single row with two columns.
+ // Ingres JDBC Driver returns table and object keys as BINARY values.
+ getDefaultProperties().setProperty(Environment.USE_GET_GENERATED_KEYS, "false");
}
/**
diff --git a/core/src/main/java/org/hibernate/dialect/resolver/StandardDialectResolver.java b/core/src/main/java/org/hibernate/dialect/resolver/StandardDialectResolver.java
index e809e3b28c..409a6ca669 100644
--- a/core/src/main/java/org/hibernate/dialect/resolver/StandardDialectResolver.java
+++ b/core/src/main/java/org/hibernate/dialect/resolver/StandardDialectResolver.java
@@ -35,6 +35,8 @@ import org.hibernate.dialect.H2Dialect;
import org.hibernate.dialect.MySQLDialect;
import org.hibernate.dialect.PostgreSQLDialect;
import org.hibernate.dialect.DerbyDialect;
+import org.hibernate.dialect.Ingres10Dialect;
+import org.hibernate.dialect.Ingres9Dialect;
import org.hibernate.dialect.IngresDialect;
import org.hibernate.dialect.SQLServerDialect;
import org.hibernate.dialect.InformixDialect;
@@ -78,6 +80,19 @@ public class StandardDialectResolver extends AbstractDialectResolver{
}
if ( "ingres".equalsIgnoreCase( databaseName ) ) {
+ switch( databaseMajorVersion ) {
+ case 9:
+ int databaseMinorVersion = metaData.getDatabaseMinorVersion();
+ if (databaseMinorVersion > 2) {
+ return new Ingres9Dialect();
+ }
+ return new IngresDialect();
+ case 10:
+ log.warn( "Ingres " + databaseMajorVersion + " is not yet fully supported; using Ingres 9.3 dialect" );
+ return new Ingres10Dialect();
+ default:
+ log.warn( "Unknown Ingres major version [" + databaseMajorVersion + "] using Ingres 9.2 dialect" );
+ }
return new IngresDialect();
}