HHH-4931 improve Ingres dialect supports

git-svn-id: https://svn.jboss.org/repos/hibernate/core/trunk@18948 1b8cb986-b30d-0410-93ca-fae66ebed9b2
This commit is contained in:
Strong Liu 2010-03-09 21:02:15 +00:00
parent 5aa0138ec2
commit e699570e60
4 changed files with 270 additions and 3 deletions

View File

@ -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:
* <ul>
* </ul>
*
* @author Raymond Fan
*/
public class Ingres10Dialect extends Ingres9Dialect {
public Ingres10Dialect() {
super();
}
}

View File

@ -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.
* <p />
* Changes:
* <ul>
* <li>Support for the SQL functions current_time, current_timestamp and current_date added</li>
* <li>Type mapping of <code>Types.TIMESTAMP</code> changed from "timestamp with time zone" to "timestamp(9) with time zone"</li>
* <li>Improved handling of "SELECT...FOR UPDATE" statements</li>
* <li>Added support for pooled sequences</li>
* <li>Added support for SELECT queries with limit and offset</li>
* <li>Added getIdentitySelectString</li>
* </ul>
*
* @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 <tt>FOR UPDATE</tt> in conjunction with outer
* joined rows?
*
* @return True if outer joined rows can be locked via <tt>FOR UPDATE</tt>.
*/
public boolean supportsOuterJoinForUpdate() {
return false;
}
/**
* Is <tt>FOR UPDATE OF</tt> syntax supported?
*
* @return True if the database supports <tt>FOR UPDATE OF</tt> 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 <tt>LIMIT</tt> clause to the given SQL <tt>SELECT</tt>
*
* @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();
}
}

View File

@ -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.
* <p/>
* Known limitations:
* - only supports simple constants or columns on the left side of an IN, making (1,2,3) in (...) or (&lt;subselect&gt;) in (...) non-supported
* - supports only 39 digits in decimal
*
* <ul>
* <li> Only supports simple constants or columns on the left side of an IN, making (1,2,3) in (...) or (&lt;subselect&gt;) in (...) non-supported.
* <li> Supports only 39 digits in decimal.
* <li> Explicitly set USE_GET_GENERATED_KEYS property to false.
* </ul>
*
* @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");
}
/**

View File

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