[hibernate-commits] Hibernate SVN: r10775 - in branches/Branch_3_2/Hibernate3: src/org/hibernate/dialect src/org/hibernate/dialect/function src/org/hibernate/exception src/org/hibernate/sql test/org/hibernate/test test/org/hibernate/test/hql test/org/hibernate/test/legacy

hibernate-commits at lists.jboss.org hibernate-commits at lists.jboss.org
Wed Nov 8 11:57:31 EST 2006


Author: steve.ebersole at jboss.com
Date: 2006-11-08 11:56:52 -0500 (Wed, 08 Nov 2006)
New Revision: 10775

Added:
   branches/Branch_3_2/Hibernate3/src/org/hibernate/dialect/Cache71Dialect.java
   branches/Branch_3_2/Hibernate3/src/org/hibernate/dialect/function/ConditionalParenthesisFunction.java
   branches/Branch_3_2/Hibernate3/src/org/hibernate/dialect/function/ConvertFunction.java
   branches/Branch_3_2/Hibernate3/src/org/hibernate/dialect/function/StandardJDBCEscapeFunction.java
   branches/Branch_3_2/Hibernate3/src/org/hibernate/exception/CacheSQLStateConverter.java
   branches/Branch_3_2/Hibernate3/src/org/hibernate/sql/CacheJoinFragment.java
Modified:
   branches/Branch_3_2/Hibernate3/src/org/hibernate/dialect/Dialect.java
   branches/Branch_3_2/Hibernate3/src/org/hibernate/dialect/function/SQLFunction.java
   branches/Branch_3_2/Hibernate3/src/org/hibernate/dialect/function/StandardSQLFunction.java
   branches/Branch_3_2/Hibernate3/test/org/hibernate/test/TestCase.java
   branches/Branch_3_2/Hibernate3/test/org/hibernate/test/hql/FooBarCopy.hbm.xml
   branches/Branch_3_2/Hibernate3/test/org/hibernate/test/legacy/Baz.hbm.xml
   branches/Branch_3_2/Hibernate3/test/org/hibernate/test/legacy/FooBar.hbm.xml
   branches/Branch_3_2/Hibernate3/test/org/hibernate/test/legacy/Glarch.hbm.xml
Log:
HHH-2205 : dialect for InterSystems' CacheSQL

Added: branches/Branch_3_2/Hibernate3/src/org/hibernate/dialect/Cache71Dialect.java
===================================================================
--- branches/Branch_3_2/Hibernate3/src/org/hibernate/dialect/Cache71Dialect.java	2006-11-08 16:54:55 UTC (rev 10774)
+++ branches/Branch_3_2/Hibernate3/src/org/hibernate/dialect/Cache71Dialect.java	2006-11-08 16:56:52 UTC (rev 10775)
@@ -0,0 +1,844 @@
+//$Id:  $
+package org.hibernate.dialect;
+
+import java.sql.CallableStatement;
+import java.sql.ResultSet;
+import java.sql.SQLException;
+import java.sql.Types;
+
+import org.hibernate.Hibernate;
+import org.hibernate.LockMode;
+import org.hibernate.MappingException;
+import org.hibernate.cfg.Environment;
+import org.hibernate.dialect.function.NoArgSQLFunction;
+import org.hibernate.dialect.function.NvlFunction;
+import org.hibernate.dialect.function.SQLFunctionTemplate;
+import org.hibernate.dialect.function.StandardSQLFunction;
+import org.hibernate.dialect.function.VarArgsSQLFunction;
+import org.hibernate.dialect.function.StandardJDBCEscapeFunction;
+import org.hibernate.dialect.function.ConvertFunction;
+import org.hibernate.dialect.function.ConditionalParenthesisFunction;
+import org.hibernate.dialect.lock.LockingStrategy;
+import org.hibernate.dialect.lock.SelectLockingStrategy;
+import org.hibernate.dialect.lock.UpdateLockingStrategy;
+import org.hibernate.exception.CacheSQLStateConverter;
+import org.hibernate.exception.SQLExceptionConverter;
+import org.hibernate.exception.TemplatedViolatedConstraintNameExtracter;
+import org.hibernate.exception.ViolatedConstraintNameExtracter;
+import org.hibernate.id.IdentityGenerator;
+import org.hibernate.persister.entity.Lockable;
+import org.hibernate.sql.CacheJoinFragment;
+import org.hibernate.sql.JoinFragment;
+import org.hibernate.util.StringHelper;
+
+/**
+ * Cach&eacute; 2007.1 dialect. This class is required in order to use Hibernate with Intersystems Caché SQL.<br>
+ * <br>
+ * Compatible with Caché 2007.1.
+ * Cache JDBC driver version ?.?.
+ * <br>
+ * <head>
+ * <title>Cach&eacute; and Hibernate</title>
+ * </head>
+ * <body>
+ * <h1>Cach&eacute; and Hibernate</h1>
+ * <h2>PREREQUISITES</h2>
+ * These setup instructions assume that both Cach&eacute; and Hibernate are installed and operational.
+ * <br>
+ * <h2>HIBERNATE DIRECTORIES AND FILES</h2>
+ * InterSystems support for Hibernate 2.1.8 and Hibernate 3.0.5
+ * requires different dialect files from those distributed with Hibernate 3.2.
+ * Also Hibernate 2.1.8 has a different directory and Java package structure which is reflected in the InterSystems sources.
+ * JBoss distributes the InterSystems Cache' dialect for Hibernate 3.2.
+ * For earlier versions of Hibernate please contact
+ * <a href="http://www.intersystems.com/support/cache-support.html">InterSystems Worldwide Response Center</A> (WRC)
+ * for the appropriate source files.
+ * <br>
+ * <h2>CACH&Eacute; DOCUMENTATION</h2>
+ * Documentation for Cach&eacute; is available online when Cach&eacute; is running.
+ * It can also be obtained from the
+ * <a href="http://www.intersystems.com/cache/downloads/documentation.html">InterSystems</A> website.
+ * The book, "Object-oriented Application Development Using the Cach&eacute; Post-relational Database:
+ * is also available from Springer-Verlag.
+ * <br>
+ * <h2>HIBERNATE DOCUMENTATION</h2>
+ * Hibernate comes with extensive electronic documentation.
+ * In addition, several books on Hibernate are available from
+ * <a href="http://www.manning.com">Manning Publications Co</a>.
+ * Three available titles are "Hibernate Quickly", "Hibernate in Action", and "Java Persistence with Hibernate".
+ * <br>
+ * <h2>TO SET UP HIBERNATE FOR USE WITH CACH&Eacute;</h2>
+ * The following steps assume that the directory where Cach&eacute; was installed is C:\CacheSys.
+ * This is the default installation directory for  Cach&eacute;.
+ * The default installation directory for Hibernate is assumed to be C:\Hibernate.
+ * <p/>
+ * If either product is installed in a different location, the pathnames that follow should be modified appropriately.
+ * <p/>
+ * Cach&eacute; version 2007.1 and above is recommended for use with
+ * Hibernate.  The next step depends on the location of your
+ * CacheDB.jar depending on your version of Cach&eacute;.
+ * <ol>
+ * <li>Copy C:\CacheSys\dev\java\lib\CacheDB.jar to C:\Hibernate\lib\CacheDB.jar.</li>
+ * <li>Copy C:\CacheSys\dev\java\lib\JDK15\CacheDB.jar to C:\Hibernate\lib\CacheDB.jar.</li>
+ * <p/>
+ * <li>Insert the following files into your Java classpath:
+ * <p/>
+ * <ul>
+ * <li>All jar files in the directory C:\Hibernate\lib</li>
+ * <li>The directory (or directories) where hibernate.properties and/or hibernate.cfg.xml are kept.</li>
+ * </ul>
+ * </li>
+ * <p/>
+ * <li>In the file, hibernate.properties (or hibernate.cfg.xml),
+ * specify the Cach&eacute; dialect and the Cach&eacute; version URL settings.</li>
+ * </ol>
+ * <p/>
+ * For example, in Hibernate 3.2, typical entries in hibernate.properties would have the following
+ * "name=value" pairs:
+ * <p/>
+ * <table cols=3 border cellpadding=5 cellspacing=0>
+ * <tr>
+ * <th>Property Name</th>
+ * <th>Property Value 3.2</th>
+ * <th>Property Value 2.1.8</th>
+ * </tr>
+ * <tr>
+ * <td>hibernate.dialect</td>
+ * <td>org.hibernate.dialect.Cache71Dialect</td>
+ * <td>net.sf.hibernate.dialect.Cache50Dialect</td>
+ * </tr>
+ * <tr>
+ * <td>hibernate.connection.driver_class</td>
+ * <td>com.intersys.jdbc.CacheDriver</td>
+ * <td>com.intersys.jdbc.CacheDriver</td>
+ * </tr>
+ * <tr>
+ * <td>hibernate.connection.username</td>
+ * <td>(see note 1)</td>
+ * <td>(see note 1)</td>
+ * </tr>
+ * <tr>
+ * <td>hibernate.connection.password</td>
+ * <td>(see note 1)</td>
+ * <td>(see note 1)</td>
+ * </tr>
+ * <tr>
+ * <td>hibernate.connection.url</td>
+ * <td>jdbc:Cache://127.0.0.1:1972/USER</td>
+ * <td>jdbc:Cache://127.0.0.1:1972/USER</td>
+ * </tr>
+ * </table>
+ * <p/>
+ * <dl>
+ * <dt><b>Note 1</b></dt>
+ * <dd>Please contact your administrator for the userid and password you should use when attempting access via JDBC.
+ * By default, these are chosen to be "_SYSTEM" and "SYS" respectively as noted in the SQL standard.</dd>
+ * </dl>
+ * <br>
+ * <h2>CACH&Eacute; VERSION URL</h2>
+ * This is the standard URL for the JDBC driver.
+ * For a JDBC driver on the machine hosting Cach&eacute;, use the IP "loopback" address, 127.0.0.1.
+ * For 1972, the default port, specify the super server port of your Cach&eacute; instance.
+ * For USER, substitute the NAMESPACE which contains your Cach&eacute; database data.
+ * <br>
+ * <h2>CACH&Eacute; DIALECTS</h2>
+ * Choices for Dialect are:
+ * <br>
+ * <p/>
+ * <ol>
+ * <li>
+ * org.hibernate.dialect.Cache50Dialect (requires Cach&eacute;
+ * 5.0 or above)
+ * </li>
+ * <p/>
+ * <li>org.hibernate.dialect.Cache51Dialect (requires Cach&eacute; 5.1 or
+ * above)</li>
+ * <p/>
+ * <li>org.hibernate.dialect.Cache51SequenceDialect (requires Cach&eacute; 5.1 or
+ * above)</li>
+ * <p/>
+ * <li>org.hibernate.dialect.Cache71Dialect (requires Cach&eacute;
+ * 2007.1 or above)</li>
+ * <p/>
+ * <li>org.hibernate.dialect.Cache71SequenceDialect (requires Cach&eacute;
+ * 2007.1 or above)</li>
+ * </ol>
+ * <p/>
+ * Setting up for Cach&eacute; 5.0 is similar except that the hibernate
+ * dialect package is "org.hibernate.dialect.Cache50Dialect"
+ * <br>
+ * <h2>SETTING UP CACH&Eacute; DIALECT FROM INTERSYSTEMS SOURCES</h2>
+ * <p/>
+ * InterSystems provides source code for the Hibernate Dialect classes.
+ * Therefore, you must first place the source code in the proper locations
+ * and compile it into Java class files.
+ * Doing this will eliminate possible version mismatches in the compiled Java code.
+ * <p/>
+ * To begin, unzip the InterSystems source into the PARENT directory of the location where you installed Hibernate.
+ * The InterSystems zip file that contains InterSystems Hibernate support for
+ * Hibernate 2.1.8 and Hibernate 3.0.5 already contains hibernate-2.1
+ * and hibernate-3.0 in its directory structure.  This is why you must
+ * unzip to the directory CONTAINING your Hibernate install directory.
+ * <p/>
+ * If you are using Hibernate 3.2, JBoss has already built the right JAR file for you.
+ * If you are NOT using Hibernate 3.2, then you must do the following:
+ * <p/>
+ * <ol>
+ * <li>In your Hibernate install directory, after the unzip we described above,
+ * type the following:
+ * <br>
+ * <pre>
+ *     build
+ * </pre></li>
+ * <li>Copy the JAR file to the proper place.
+ * <p/>
+ * For Hibernate 3.0.5, copy
+ * <pre>
+ * ..\hibernate\hibernate3.jar
+ * </pre>
+ * to the Hibernate install directory.
+ * <p/>
+ * For Hibernate 2.1.8, copy
+ * <pre>
+ *     ..\hibernate\hibernate.2jar
+ * </pre>
+ * to the Hibernate install directory.</li>
+ * <p/>
+ * <li>Test your installation by configuring etc\hibernate.properties for your Cach&eacute; database,
+ * and then running the following:
+ * <pre>
+ *     build eg
+ * </pre>
+ * The build process reports its success or failure.  If you see,
+ * <pre>
+ *     BUILD FAILED
+ * </pre>
+ * please contact the
+ * <a href="http://www.intersystems.com/support/cache-support.html">InterSystems Worldwide Response Center</A>
+ * for assistance.
+ * </li>
+ * </ol>
+ * <br>
+ * <h2>SUPPORT FOR IDENTITY COLUMNS</h2>
+ * Cach&eacute; 5.1 or later supports identity columns.  This includes Cache' 2007.1.  To cause
+ * Hibernate to use identity columns, specify "native" as the
+ * generator.  Also make sure that
+ * hibernate.jdbc.use_get_generated_keys is set to true, which is the
+ * default.  In the Cache' 2007.1 release, with the
+ * Cache71Dialect, you can set hibernate.jdbc.use_get_generated_keys to
+ * false, and still use identity columns.
+ * <br>
+ * <h2>SEQUENCE DIALECTS SUPPORT SEQUENCES</h2>
+ * You do not have to use the sequence dialects with Cach&eacute;.
+ * These are Cache50SequenceDialect, Cache51SequenceDialect and Cache71SequenceDialect.
+ * But if you choose to use them, set them up as follows:
+ * <p/>
+ * To use Hibernate sequence support with Cach&eacute; in a namespace, you must FIRST load the following file into that namespace:
+ * <pre>
+ *     src\org\hibernate\dialect\CacheSequences.xml
+ * </pre>
+ * In your Hibernate mapping you can specify sequence use.
+ * When you are using a Cache' sequence dialect, the type "native" maps to sequence.
+ * <p/>
+ * For example, the following shows the use of a sequence generator in a Hibernate mapping:
+ * <pre>
+ *     &lt;id name="id" column="uid" type="long" unsaved-value="null"&gt;
+ *         &lt;generator class="seqhilo"&gt;
+ *             &lt;param name="sequence"&gt;EVENTS_SEQ&lt;/param&gt;
+ *             &lt;param name="max_lo"&gt;0&lt;/param&gt;
+ *         &lt;/generator&gt;
+ *     &lt;/id&gt;
+ * </pre>
+ * <br>
+ * <p/>
+ * Some versions of Hibernate under some circumstances call
+ * getSelectSequenceNextValString() in the dialect.  If this happens
+ * you will receive the error message: new MappingException( "Dialect
+ * does not support sequences" ).
+ * <h2>BIGINT SUPPORT</h2>
+ * Cach&eacute; 5.1 and above supports BIGINT. 2007.1 supports BIGINT.
+ * <p/>
+ * Cach&eacute; 5.0.x does not have direct BIGINT support.
+ * To imitate BIGINT support in Cache 5.0.x, in the SQL configuration,
+ * remap %INTEGER as follows, to be used by Cach&eacute; 5.0.x  dialects:
+ * <p/>
+ * <pre>
+ *     %Library.Integer(MAXVAL=99999999999999999999,MINVAL=-999999999999999999)
+ * </pre>
+ * <p/>
+ * To change SQL settings:
+ * <p/>
+ * <ol>
+ * <li>In Cach&eacute; 2007.1, use the System Management Portal.</li>
+ * <p/>
+ * <li>In Cach&eacute; 5.0, use the Configuration Manager.</li>
+ * </ol>
+ * <p/>
+ * Set Cach&eacute; SQL to allow:
+ * <p/>
+ * <ol>
+ * <li>delimited identifiers</li>
+ * <li>drop of non-existent tables</li>
+ * <li>drop of non-existent constraints</li>
+ * </ol>
+ * <p/>
+ * <h2>HIBERNATE 2.1.8</h2>
+ * Hibernate 2.1.8 requires different source files from InterSystems reflecting
+ * the different directory and Java package structure of Hibernate 2.1.8.
+ * Please contact
+ * <a href="http://www.intersystems.com/support/cache-support.html">InterSystems Worldwide Response Center</A> (WRC)
+ * for these source files if you need to use Hibernate 2.1.8.
+ * <p/>
+ * To run a Caché application with Hibernate 2.1.8, set the following flag when starting your JVM:
+ * <pre>
+ *      -Dhibernate.jdbc.use_streams_for_binary=false
+ * </pre>
+ * <p/>
+ * In Hibernate 3.0.5, this flag is not necessary;
+ * it is taken care of by the Cach&eacute; dialect itself.
+ * <br>
+ * <h2>HIBERNATE FILES ASSOCIATED WITH CACH&Eacute; DIALECT</h2>
+ * The following files are associated with Cach&eacute; dialect:
+ * <p/>
+ * <ol>
+ * <li>src\org\hibernate\dialect\Cache71Dialect.java</li>
+ * <li>src\org\hibernate\dialect\function\ConditionalParenthesisFunction.java</li>
+ * <li>src\org\hibernate\dialect\function\ConvertFunction.java</li>
+ * <li>src\org\hibernate\exception\CacheSQLStateConverter.java</li>
+ * <li>src\org\hibernate\sql\CacheJoinFragment.java</li>
+ * </ol>
+ * Cache71Dialect ships with Hibernate 3.2.  All other dialects are distributed by InterSystems and subclass Cache71Dialect.
+ * <h2>Limitations</h2>
+ * The following is a list of the currently known limitations of using Cache' with Hibernate. Please check with InterSystems on the latest status as these are server side issues.
+ * <p/>
+ * The following also lists known issues with running the full Hibernate regression tests against InterSystems Cache'.
+ * <p/>
+ * - Delete of self-referential foreign keys.
+ * <p/>
+ * We do not current support deletion of a table row when the table has a foreign key that references itself and the foreign key in the table row references that table row. (self-referential foreign keys)
+ * <p/>
+ * - Support for "SELECT FOR UPDATE."
+ * <p/>
+ * The default locking mode strategy for Cache' is Hibernate's UpdateLockingStrategy, which you use with Hibernate's versioning capability.
+ * <p/>
+ * To use Concurrency modes that requires other locking strategies you can subclass your Cache' dialect and define a locking strategy.
+ * <p/>
+ * Cache' does not currently support "SELECT FOR UPDATE."  While grammatically correct, it does no locking.
+ * <p/>
+ * In versions prior to 2007.1, there are limitations in support for outer joins (see Cache' documentation).
+ * <p/>
+ * For example, Cache' prior to 2007.1 does support "NOT NULL" clauses in the ON conditions.
+ * <p/>
+ * Cache' does not support using longvarbinary or longvarchar in a where clause.
+ * <p/>
+ * In Hibernate regression tests, Baz.hbm.xml, FooBar.hbm.xml, Glarch.hbm.xml and XY.hbm.xml have to be edited to replace "!" by BANG and "^" by CARET.  Our own identifier translation is not enough since Hibernate uses names containing these in its own mapping files and Hibernate (on the client-side) does not know about our server-side mapping.
+ * <p/>
+ * There are some tests that involve batch operations where the test
+ * will succeed if you increase the size of the lock table from
+ * 786432 (the default) to 1786432.  You can use the System Management
+ * Portal in 2007.1 or the configuration manager in 5.0.X to increase the
+ * size of the lock table.  This requirement of increasing the lock
+ * table size is specific to running the Hibernate regression tests.
+ * <p/>
+ * Cache' fails tests that attempt to COUNT stream fields
+ * <p/>
+ * Here is an example of such an error message, SQL ERROR -37: Aggregate function COUNT not supported for Stream fields
+ * <p/>
+ * We fail on tests that use mappings like the following
+ * <p/>
+ * <pre>
+ * 			&lt;property name="yob" formula="year(dob)"/&gt;
+ * </pre>
+ * and the error is:
+ * <p/>
+ * ERROR #359: User defined SQL Function 'SQLUSER.YEAR' does not exist
+ * <p/>
+ * If the mapping is changed to
+ * <p/>
+ * <pre>
+ * 			&lt;property name="yob" formula="{fn year(dob)}"/&gt;
+ * </pre>
+ * then such tests succeed.
+ * <p/>
+ * Cache' 2007.1 supports temp tables.  Prior versions do not.
+ * <p/>
+ * We do not support row valued expression.  So WHERE clauses like "WHERE (a,b,c) = (d,e,f)" give syntax errors.  The Hibernate regression tests use row valued expressions and we fail on these.
+ * <p/>
+ * For example:
+ * <p/>
+ * <pre>
+ * result = s.createQuery("from Transaction txn where txn.value = (1.5, 'AUD')").list();
+ * </pre>
+ * will not generate valid Cache' SQL because of the parenthesis around (1.5, 'AUD')
+ * <p/>
+ * Queries like the following:
+ * <p/>
+ * <pre>
+ * session.createQuery("select extract(second from current_timestamp()), extract(minute from current_timestamp()), extract(hour from current_timestamp()) from Mammal m").list();
+ * </pre>
+ * <p/>
+ * will not work, because we do support "extract" function.
+ * <p/>
+ * We do not support in () (empty parenthesis)
+ * <p/>
+ * We do not guarantee the case of a column returned using a group by clause.
+ * <p/>
+ * For instance in the regression test,
+ * <p/>
+ * <pre>
+ * list = s.find("select new Result( baz.name, max(foo.long), count(foo) ) from Baz baz join baz.fooArray foo group by baz.name");
+ * </pre>
+ * we return baz.name in lower case, and the test that generates this SQL fails.
+ *
+ * @author Jonathan Levinson
+ */
+
+public class Cache71Dialect extends Dialect {
+
+	/**
+	 * Creates new <code>Caché71Dialect</code> instance. Sets up the JDBC /
+	 * Caché type mappings.
+	 */
+	public Cache71Dialect() {
+		super();
+		commonRegistration();
+		register71Functions();
+	}
+
+	protected final void commonRegistration() {
+		// Note: For object <-> SQL datatype mappings see:
+		//	 Configuration Manager | Advanced | SQL | System DDL Datatype Mappings
+		//
+		//	TBD	registerColumnType(Types.BINARY,        "binary($1)");
+		// changed 08-11-2005, jsl
+		registerColumnType( Types.BINARY, "varbinary($1)" );
+		registerColumnType( Types.BIGINT, "BigInt" );
+		registerColumnType( Types.BIT, "bit" );
+		registerColumnType( Types.CHAR, "char(1)" );
+		registerColumnType( Types.DATE, "date" );
+		registerColumnType( Types.DECIMAL, "decimal" );
+		registerColumnType( Types.DOUBLE, "double" );
+		registerColumnType( Types.FLOAT, "float" );
+		registerColumnType( Types.INTEGER, "integer" );
+		registerColumnType( Types.LONGVARBINARY, "longvarbinary" );	// binary %Stream
+		registerColumnType( Types.LONGVARCHAR, "longvarchar" );		// character %Stream
+		registerColumnType( Types.NUMERIC, "numeric($p,$s)" );
+		registerColumnType( Types.REAL, "real" );
+		registerColumnType( Types.SMALLINT, "smallint" );
+		registerColumnType( Types.TIMESTAMP, "timestamp" );
+		registerColumnType( Types.TIME, "time" );
+		registerColumnType( Types.TINYINT, "tinyint" );
+		// TBD should this be varbinary($1)?
+		//		registerColumnType(Types.VARBINARY,     "binary($1)");
+		registerColumnType( Types.VARBINARY, "longvarbinary" );
+		registerColumnType( Types.VARCHAR, "varchar($l)" );
+		registerColumnType( Types.BLOB, "longvarbinary" );
+		registerColumnType( Types.CLOB, "longvarchar" );
+
+		getDefaultProperties().setProperty( Environment.USE_STREAMS_FOR_BINARY, "false" );
+		getDefaultProperties().setProperty( Environment.STATEMENT_BATCH_SIZE, DEFAULT_BATCH_SIZE );
+		//getDefaultProperties().setProperty(Environment.STATEMENT_BATCH_SIZE, NO_BATCH);
+
+		getDefaultProperties().setProperty( Environment.USE_SQL_COMMENTS, "false" );
+
+		registerFunction( "abs", new StandardSQLFunction( "abs" ) );
+		registerFunction( "acos", new StandardJDBCEscapeFunction( "acos", Hibernate.DOUBLE ) );
+		registerFunction( "%alphaup", new StandardSQLFunction( "%alphaup", Hibernate.STRING ) );
+		registerFunction( "ascii", new StandardSQLFunction( "ascii", Hibernate.STRING ) );
+		registerFunction( "asin", new StandardJDBCEscapeFunction( "asin", Hibernate.DOUBLE ) );
+		registerFunction( "atan", new StandardJDBCEscapeFunction( "atan", Hibernate.DOUBLE ) );
+		registerFunction( "bit_length", new SQLFunctionTemplate( Hibernate.INTEGER, "($length(?1)*8)" ) );
+		// hibernate impelemnts cast in Dialect.java
+		registerFunction( "ceiling", new StandardSQLFunction( "ceiling", Hibernate.INTEGER ) );
+		registerFunction( "char", new StandardJDBCEscapeFunction( "char", Hibernate.CHARACTER ) );
+		registerFunction( "character_length", new StandardSQLFunction( "character_length", Hibernate.INTEGER ) );
+		registerFunction( "char_length", new StandardSQLFunction( "char_length", Hibernate.INTEGER ) );
+		registerFunction( "cos", new StandardJDBCEscapeFunction( "cos", Hibernate.DOUBLE ) );
+		registerFunction( "cot", new StandardJDBCEscapeFunction( "cot", Hibernate.DOUBLE ) );
+		registerFunction( "coalesce", new VarArgsSQLFunction( "coalesce(", ",", ")" ) );
+		registerFunction( "concat", new VarArgsSQLFunction( Hibernate.STRING, "", "||", "" ) );
+		registerFunction( "convert", new ConvertFunction() );
+		registerFunction( "curdate", new StandardJDBCEscapeFunction( "curdate", Hibernate.DATE ) );
+		registerFunction( "current_date", new NoArgSQLFunction( "current_date", Hibernate.DATE, false ) );
+		registerFunction( "current_time", new NoArgSQLFunction( "current_time", Hibernate.TIME, false ) );
+		registerFunction(
+				"current_timestamp", new ConditionalParenthesisFunction( "current_timestamp", Hibernate.TIMESTAMP )
+		);
+		registerFunction( "curtime", new StandardJDBCEscapeFunction( "curtime", Hibernate.TIME ) );
+		registerFunction( "database", new StandardJDBCEscapeFunction( "database", Hibernate.STRING ) );
+		registerFunction( "dateadd", new VarArgsSQLFunction( Hibernate.TIMESTAMP, "dateadd(", ",", ")" ) );
+		registerFunction( "datediff", new VarArgsSQLFunction( Hibernate.INTEGER, "datediff(", ",", ")" ) );
+		registerFunction( "datename", new VarArgsSQLFunction( Hibernate.STRING, "datename(", ",", ")" ) );
+		registerFunction( "datepart", new VarArgsSQLFunction( Hibernate.INTEGER, "datepart(", ",", ")" ) );
+		registerFunction( "day", new StandardSQLFunction( "day", Hibernate.INTEGER ) );
+		registerFunction( "dayname", new StandardJDBCEscapeFunction( "dayname", Hibernate.STRING ) );
+		registerFunction( "dayofmonth", new StandardJDBCEscapeFunction( "dayofmonth", Hibernate.INTEGER ) );
+		registerFunction( "dayofweek", new StandardJDBCEscapeFunction( "dayofweek", Hibernate.INTEGER ) );
+		registerFunction( "dayofyear", new StandardJDBCEscapeFunction( "dayofyear", Hibernate.INTEGER ) );
+		// is it necessary to register %exact since it can only appear in a where clause?
+		registerFunction( "%exact", new StandardSQLFunction( "%exact", Hibernate.STRING ) );
+		registerFunction( "exp", new StandardJDBCEscapeFunction( "exp", Hibernate.DOUBLE ) );
+		registerFunction( "%external", new StandardSQLFunction( "%external", Hibernate.STRING ) );
+		registerFunction( "$extract", new VarArgsSQLFunction( Hibernate.INTEGER, "$extract(", ",", ")" ) );
+		registerFunction( "$find", new VarArgsSQLFunction( Hibernate.INTEGER, "$find(", ",", ")" ) );
+		registerFunction( "floor", new StandardSQLFunction( "floor", Hibernate.INTEGER ) );
+		registerFunction( "getdate", new StandardSQLFunction( "getdate", Hibernate.TIMESTAMP ) );
+		registerFunction( "hour", new StandardJDBCEscapeFunction( "hour", Hibernate.INTEGER ) );
+		registerFunction( "ifnull", new VarArgsSQLFunction( "ifnull(", ",", ")" ) );
+		registerFunction( "%internal", new StandardSQLFunction( "%internal" ) );
+		registerFunction( "isnull", new VarArgsSQLFunction( "isnull(", ",", ")" ) );
+		registerFunction( "isnumeric", new StandardSQLFunction( "isnumeric", Hibernate.INTEGER ) );
+		registerFunction( "lcase", new StandardJDBCEscapeFunction( "lcase", Hibernate.STRING ) );
+		registerFunction( "left", new StandardJDBCEscapeFunction( "left", Hibernate.STRING ) );
+		registerFunction( "len", new StandardSQLFunction( "len", Hibernate.INTEGER ) );
+		registerFunction( "length", new StandardSQLFunction( "length", Hibernate.INTEGER ) );
+		registerFunction( "$length", new VarArgsSQLFunction( "$length(", ",", ")" ) );
+		// aggregate functions shouldn't be registered, right?
+		//registerFunction( "list", new StandardSQLFunction("list",Hibernate.STRING) );
+		// stopped on $list
+		registerFunction( "$list", new VarArgsSQLFunction( "$list(", ",", ")" ) );
+		registerFunction( "$listdata", new VarArgsSQLFunction( "$listdata(", ",", ")" ) );
+		registerFunction( "$listfind", new VarArgsSQLFunction( "$listfind(", ",", ")" ) );
+		registerFunction( "$listget", new VarArgsSQLFunction( "$listget(", ",", ")" ) );
+		registerFunction( "$listlength", new StandardSQLFunction( "$listlength", Hibernate.INTEGER ) );
+		registerFunction( "locate", new StandardSQLFunction( "$FIND", Hibernate.INTEGER ) );
+		registerFunction( "log", new StandardJDBCEscapeFunction( "log", Hibernate.DOUBLE ) );
+		registerFunction( "log10", new StandardJDBCEscapeFunction( "log", Hibernate.DOUBLE ) );
+		registerFunction( "lower", new StandardSQLFunction( "lower" ) );
+		registerFunction( "ltrim", new StandardSQLFunction( "ltrim" ) );
+		registerFunction( "minute", new StandardJDBCEscapeFunction( "minute", Hibernate.INTEGER ) );
+		registerFunction( "mod", new StandardJDBCEscapeFunction( "mod", Hibernate.DOUBLE ) );
+		registerFunction( "month", new StandardJDBCEscapeFunction( "month", Hibernate.INTEGER ) );
+		registerFunction( "monthname", new StandardJDBCEscapeFunction( "monthname", Hibernate.STRING ) );
+		registerFunction( "now", new StandardJDBCEscapeFunction( "monthname", Hibernate.TIMESTAMP ) );
+		registerFunction( "nullif", new VarArgsSQLFunction( "nullif(", ",", ")" ) );
+		registerFunction( "nvl", new NvlFunction() );
+		registerFunction( "%odbcin", new StandardSQLFunction( "%odbcin" ) );
+		registerFunction( "%odbcout", new StandardSQLFunction( "%odbcin" ) );
+		registerFunction( "%pattern", new VarArgsSQLFunction( Hibernate.STRING, "", "%pattern", "" ) );
+		registerFunction( "pi", new StandardJDBCEscapeFunction( "pi", Hibernate.DOUBLE ) );
+		registerFunction( "$piece", new VarArgsSQLFunction( Hibernate.STRING, "$piece(", ",", ")" ) );
+		registerFunction( "position", new VarArgsSQLFunction( Hibernate.INTEGER, "position(", " in ", ")" ) );
+		registerFunction( "power", new VarArgsSQLFunction( Hibernate.STRING, "power(", ",", ")" ) );
+		registerFunction( "quarter", new StandardJDBCEscapeFunction( "quarter", Hibernate.INTEGER ) );
+		registerFunction( "repeat", new VarArgsSQLFunction( Hibernate.STRING, "repeat(", ",", ")" ) );
+		registerFunction( "replicate", new VarArgsSQLFunction( Hibernate.STRING, "replicate(", ",", ")" ) );
+		registerFunction( "right", new StandardJDBCEscapeFunction( "right", Hibernate.STRING ) );
+		registerFunction( "round", new VarArgsSQLFunction( Hibernate.FLOAT, "round(", ",", ")" ) );
+		registerFunction( "rtrim", new StandardSQLFunction( "rtrim", Hibernate.STRING ) );
+		registerFunction( "second", new StandardJDBCEscapeFunction( "second", Hibernate.INTEGER ) );
+		registerFunction( "sign", new StandardSQLFunction( "sign", Hibernate.INTEGER ) );
+		registerFunction( "sin", new StandardJDBCEscapeFunction( "sin", Hibernate.DOUBLE ) );
+		registerFunction( "space", new StandardSQLFunction( "space", Hibernate.STRING ) );
+		registerFunction( "%sqlstring", new VarArgsSQLFunction( Hibernate.STRING, "%sqlstring(", ",", ")" ) );
+		registerFunction( "%sqlupper", new VarArgsSQLFunction( Hibernate.STRING, "%sqlupper(", ",", ")" ) );
+		registerFunction( "sqrt", new StandardJDBCEscapeFunction( "SQRT", Hibernate.DOUBLE ) );
+		registerFunction( "%startswith", new VarArgsSQLFunction( Hibernate.STRING, "", "%startswith", "" ) );
+		// below is for Cache' that don't have str in 2007.1 there is str and we register str directly
+		registerFunction( "str", new SQLFunctionTemplate( Hibernate.STRING, "cast(?1 as char varying)" ) );
+		registerFunction( "string", new VarArgsSQLFunction( Hibernate.STRING, "string(", ",", ")" ) );
+		// note that %string is deprecated
+		registerFunction( "%string", new VarArgsSQLFunction( Hibernate.STRING, "%string(", ",", ")" ) );
+		registerFunction( "substr", new VarArgsSQLFunction( Hibernate.STRING, "substr(", ",", ")" ) );
+		registerFunction( "substring", new VarArgsSQLFunction( Hibernate.STRING, "substring(", ",", ")" ) );
+		registerFunction( "sysdate", new NoArgSQLFunction( "sysdate", Hibernate.TIMESTAMP, false ) );
+		registerFunction( "tan", new StandardJDBCEscapeFunction( "tan", Hibernate.DOUBLE ) );
+		registerFunction( "timestampadd", new StandardJDBCEscapeFunction( "timestampadd", Hibernate.DOUBLE ) );
+		registerFunction( "timestampdiff", new StandardJDBCEscapeFunction( "timestampdiff", Hibernate.DOUBLE ) );
+		registerFunction( "tochar", new VarArgsSQLFunction( Hibernate.STRING, "tochar(", ",", ")" ) );
+		registerFunction( "to_char", new VarArgsSQLFunction( Hibernate.STRING, "to_char(", ",", ")" ) );
+		registerFunction( "todate", new VarArgsSQLFunction( Hibernate.STRING, "todate(", ",", ")" ) );
+		registerFunction( "to_date", new VarArgsSQLFunction( Hibernate.STRING, "todate(", ",", ")" ) );
+		registerFunction( "tonumber", new StandardSQLFunction( "tonumber" ) );
+		registerFunction( "to_number", new StandardSQLFunction( "tonumber" ) );
+		// TRIM(end_keyword string-expression-1 FROM string-expression-2)
+		// use Hibernate implementation "From" is one of the parameters they pass in position ?3
+		//registerFunction( "trim", new SQLFunctionTemplate(Hibernate.STRING, "trim(?1 ?2 from ?3)") );
+		registerFunction( "truncate", new StandardJDBCEscapeFunction( "truncate", Hibernate.STRING ) );
+		registerFunction( "ucase", new StandardJDBCEscapeFunction( "ucase", Hibernate.STRING ) );
+		registerFunction( "upper", new StandardSQLFunction( "upper" ) );
+		// %upper is deprecated
+		registerFunction( "%upper", new StandardSQLFunction( "%upper" ) );
+		registerFunction( "user", new StandardJDBCEscapeFunction( "user", Hibernate.STRING ) );
+		registerFunction( "week", new StandardJDBCEscapeFunction( "user", Hibernate.INTEGER ) );
+		registerFunction( "xmlconcat", new VarArgsSQLFunction( Hibernate.STRING, "xmlconcat(", ",", ")" ) );
+		registerFunction( "xmlelement", new VarArgsSQLFunction( Hibernate.STRING, "xmlelement(", ",", ")" ) );
+		// xmlforest requires a new kind of function constructor
+		registerFunction( "year", new StandardJDBCEscapeFunction( "year", Hibernate.INTEGER ) );
+	}
+
+	protected final void register71Functions() {
+		this.registerFunction( "str", new VarArgsSQLFunction( Hibernate.STRING, "str(", ",", ")" ) );
+	}
+
+	// DDL support ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+	public boolean hasAlterTable() {
+		// Does this dialect support the ALTER TABLE syntax?
+		return true;
+	}
+
+	public boolean qualifyIndexName() {
+		// Do we need to qualify index names with the schema name?
+		return false;
+	}
+
+	public boolean supportsUnique() {
+		// Does this dialect support the UNIQUE column syntax?
+		return true;
+	}
+
+	/**
+	 * The syntax used to add a foreign key constraint to a table.
+	 *
+	 * @return String
+	 */
+	public String getAddForeignKeyConstraintString(
+			String constraintName,
+			String[] foreignKey,
+			String referencedTable,
+			String[] primaryKey,
+			boolean referencesPrimaryKey) {
+		// The syntax used to add a foreign key constraint to a table.
+		return new StringBuffer( 300 )
+				.append( " ADD CONSTRAINT " )
+				.append( constraintName )
+				.append( " FOREIGN KEY " )
+				.append( constraintName )
+				.append( " (" )
+				.append( StringHelper.join( ", ", foreignKey ) )	// identifier-commalist
+				.append( ") REFERENCES " )
+				.append( referencedTable )
+				.append( " (" )
+				.append( StringHelper.join( ", ", primaryKey ) ) // identifier-commalist
+				.append( ") " )
+				.toString();
+	}
+
+	public boolean supportsCheck() {
+		// Does this dialect support check constraints?
+		return false;
+	}
+
+	public String getAddColumnString() {
+		// The syntax used to add a column to a table
+		return " add column";
+	}
+
+	public String getCascadeConstraintsString() {
+		// Completely optional cascading drop clause.
+		return "";
+	}
+
+	public boolean dropConstraints() {
+		// Do we need to drop constraints before dropping tables in this dialect?
+		return true;
+	}
+
+	public boolean supportsCascadeDelete() {
+		return true;
+	}
+
+	public boolean hasSelfReferentialForeignKeyBug() {
+		return true;
+	}
+
+	// temporary table support ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+	public boolean supportsTemporaryTables() {
+		return true;
+	}
+
+	public String generateTemporaryTableName(String baseTableName) {
+		String name = super.generateTemporaryTableName( baseTableName );
+		return name.length() > 25 ? name.substring( 1, 25 ) : name;
+	}
+
+	public String getCreateTemporaryTableString() {
+		return "create global temporary table";
+	}
+
+	public boolean performTemporaryTableDDLInIsolation() {
+		return false;
+	}
+
+	public String getCreateTemporaryTablePostfix() {
+		return "";
+	}
+
+	public boolean dropTemporaryTableAfterUse() {
+		return true;
+	}
+
+	// IDENTITY support ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+	public boolean supportsIdentityColumns() {
+		return true;
+	}
+
+	public Class getNativeIdentifierGeneratorClass() {
+		return IdentityGenerator.class;
+	}
+
+	public boolean hasDataTypeInIdentityColumn() {
+		// Whether this dialect has an Identity clause added to the data type or a completely seperate identity
+		// data type
+		return true;
+	}
+
+	public String getIdentityColumnString() throws MappingException {
+		// The keyword used to specify an identity column, if identity column key generation is supported.
+		return "identity";
+	}
+
+	public String getIdentitySelectString() {
+		return "SELECT LAST_IDENTITY() FROM %TSQL_sys.snf";
+	}
+
+	// SEQUENCE support ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+	public boolean supportsSequences() {
+		return true;
+	}
+
+	public String getSequenceNextValString(String sequenceName) {
+		return "select InterSystems.Sequences_GetNext('" + sequenceName + "') from InterSystems.Sequences where ucase(name)=ucase('" + sequenceName + "'))";
+	}
+
+	public String getSelectSequenceNextValString(String sequenceName) {
+		return "(select InterSystems.Sequences_GetNext('" + sequenceName + "') from InterSystems.Sequences where ucase(name)=ucase('" + sequenceName + "')))";
+	}
+
+	public String getCreateSequenceString(String sequenceName) {
+		return "insert into InterSystems.Sequences(Name) values (ucase('" + sequenceName + "'))";
+	}
+
+	public String getDropSequenceString(String sequenceName) {
+		return "delete from InterSystems.Sequences where ucase(name)=ucase('" + sequenceName + "')";
+	}
+
+	public String getQuerySequencesString() {
+		return "select name from InterSystems.Sequences";
+	}
+
+	// lock acquisition support ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+	public boolean supportsForUpdate() {
+		// Does this dialect support the FOR UPDATE syntax?
+		return false;
+	}
+
+	public boolean supportsForUpdateOf() {
+		// Does this dialect support FOR UPDATE OF, allowing particular rows to be locked?
+		return false;
+	}
+
+	public boolean supportsForUpdateNowait() {
+		// Does this dialect support the Oracle-style FOR UPDATE NOWAIT syntax?
+		return false;
+	}
+
+	public boolean supportsOuterJoinForUpdate() {
+		return false;
+	}
+
+	public LockingStrategy getLockingStrategy(Lockable lockable, LockMode lockMode) {
+		// InterSystems Cache' does not current support "SELECT ... FOR UPDATE" syntax...
+		// Set your transaction mode to READ_COMMITTED before using
+		if ( lockMode.greaterThan( LockMode.READ ) ) {
+			return new UpdateLockingStrategy( lockable, lockMode );
+		}
+		else {
+			return new SelectLockingStrategy( lockable, lockMode );
+		}
+	}
+
+	// LIMIT support (ala TOP) ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+	public boolean supportsLimit() {
+		return true;
+	}
+
+	public boolean supportsLimitOffset() {
+		return false;
+	}
+
+	public boolean supportsVariableLimit() {
+		return true;
+	}
+
+	public boolean bindLimitParametersFirst() {
+		// Does the LIMIT clause come at the start of the SELECT statement, rather than at the end?
+		return true;
+	}
+
+	public boolean useMaxForLimit() {
+		// Does the LIMIT clause take a "maximum" row number instead of a total number of returned rows?
+		return true;
+	}
+
+	public String getLimitString(String sql, boolean hasOffset) {
+		if ( hasOffset ) {
+			throw new UnsupportedOperationException( "An offset may not be specified to <TOP n> in Cache SQL" );
+		}
+
+		// This does not support the Cache SQL 'DISTINCT BY (comma-list)' extensions,
+		// but this extension is not supported through Hibernate anyway.
+		int insertionPoint = sql.startsWith( "select distinct" ) ? 15 : 6;
+
+		return new StringBuffer( sql.length() + 8 )
+				.append( sql )
+				.insert( insertionPoint, " TOP ? " )
+				.toString();
+	}
+
+	// callable statement support ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+	public int registerResultSetOutParameter(CallableStatement statement, int col) throws SQLException {
+		return col;
+	}
+
+	public ResultSet getResultSet(CallableStatement ps) throws SQLException {
+		ps.execute();
+		return ( ResultSet ) ps.getObject( 1 );
+	}
+
+	// miscellaneous support ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+	public String getLowercaseFunction() {
+		// The name of the SQL function that transforms a string to lowercase
+		return "lower";
+	}
+
+	public String getNullColumnString() {
+		// The keyword used to specify a nullable column.
+		return " null";
+	}
+
+	public JoinFragment createOuterJoinFragment() {
+		// Create an OuterJoinGenerator for this dialect.
+		return new CacheJoinFragment();
+	}
+
+	public String getNoColumnsInsertString() {
+		// The keyword used to insert a row without specifying
+		// any column values
+		return " default values";
+	}
+
+	public SQLExceptionConverter buildSQLExceptionConverter() {
+		return new CacheSQLStateConverter( EXTRACTER );
+	}
+
+	public static final ViolatedConstraintNameExtracter EXTRACTER = new TemplatedViolatedConstraintNameExtracter() {
+		/**
+		 * Extract the name of the violated constraint from the given SQLException.
+		 *
+		 * @param sqle The exception that was the result of the constraint violation.
+		 * @return The extracted constraint name.
+		 */
+		public String extractConstraintName(SQLException sqle) {
+			return extractUsingTemplate( "constraint (", ") violated", sqle.getMessage() );
+		}
+	};
+}

Modified: branches/Branch_3_2/Hibernate3/src/org/hibernate/dialect/Dialect.java
===================================================================
--- branches/Branch_3_2/Hibernate3/src/org/hibernate/dialect/Dialect.java	2006-11-08 16:54:55 UTC (rev 10774)
+++ branches/Branch_3_2/Hibernate3/src/org/hibernate/dialect/Dialect.java	2006-11-08 16:56:52 UTC (rev 10775)
@@ -57,11 +57,19 @@
 
 	private static final Log log = LogFactory.getLog( Dialect.class );
 
-	static final String DEFAULT_BATCH_SIZE = "15";
-	static final String NO_BATCH = "0";
+	public static final String DEFAULT_BATCH_SIZE = "15";
+	public static final String NO_BATCH = "0";
 
+	/**
+	 * Characters used for quoting SQL identifiers
+	 */
+	public static final String QUOTE = "`\"[";
+	public static final String CLOSED_QUOTE = "`\"]";
+
+
+	// build the map of standard ANSI SQL aggregation functions ~~~~~~~~~~~~~~~
+
 	private static final Map STANDARD_AGGREGATE_FUNCTIONS = new HashMap();
-	
 	static {
 		STANDARD_AGGREGATE_FUNCTIONS.put( "count", new StandardSQLFunction("count") {
 			public Type getReturnType(Type columnType, Mapping mapping) {
@@ -136,7 +144,9 @@
 	private final Map sqlFunctions = new HashMap();
 	private final Set sqlKeywords = new HashSet();
 
-	
+
+	// constructors and factory methods ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
 	protected Dialect() {
 		log.info( "Using dialect: " + this );
 		sqlFunctions.putAll( STANDARD_AGGREGATE_FUNCTIONS );
@@ -186,27 +196,74 @@
 		registerHibernateType( Types.DECIMAL, Hibernate.BIG_DECIMAL.getName() );
 		registerHibernateType( Types.BLOB, Hibernate.BLOB.getName() );
 		registerHibernateType( Types.CLOB, Hibernate.CLOB.getName() );
-		
 	}
 
-	public String toString() {
-		return getClass().getName();
+	/**
+	 * Get an instance of the dialect specified by the current <tt>System</tt> properties.
+	 *
+	 * @return The specified Dialect
+	 * @throws HibernateException If no dialect was specified, or if it could not be instantiated.
+	 */
+	public static Dialect getDialect() throws HibernateException {
+		String dialectName = Environment.getProperties().getProperty( Environment.DIALECT );
+		return instantiateDialect( dialectName );
 	}
 
+
 	/**
-	 * Characters used for quoting SQL identifiers
+	 * Get an instance of the dialect specified by the given properties or by
+	 * the current <tt>System</tt> properties.
+	 *
+	 * @param props The properties to use for finding the dialect class to use.
+	 * @return The specified Dialect
+	 * @throws HibernateException If no dialect was specified, or if it could not be instantiated.
 	 */
-	public static final String QUOTE = "`\"[";
-	public static final String CLOSED_QUOTE = "`\"]";
+	public static Dialect getDialect(Properties props) throws HibernateException {
+		String dialectName = props.getProperty( Environment.DIALECT );
+		if ( dialectName == null ) {
+			return getDialect();
+		}
+		return instantiateDialect( dialectName );
+	}
 
+	private static Dialect instantiateDialect(String dialectName) throws HibernateException {
+		if ( dialectName == null ) {
+			throw new HibernateException( "The dialect was not set. Set the property hibernate.dialect." );
+		}
+		try {
+			return ( Dialect ) ReflectHelper.classForName( dialectName ).newInstance();
+		}
+		catch ( ClassNotFoundException cnfe ) {
+			throw new HibernateException( "Dialect class not found: " + dialectName );
+		}
+		catch ( Exception e ) {
+			throw new HibernateException( "Could not instantiate dialect class", e );
+		}
+	}
 
 	/**
+	 * Retrieve a set of default Hibernate properties for this database.
+	 *
+	 * @return a set of Hibernate properties
+	 */
+	public final Properties getDefaultProperties() {
+		return properties;
+	}
+
+	public String toString() {
+		return getClass().getName();
+	}
+
+
+	// database type mapping support ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+	/**
 	 * Get the name of the database type associated with the given
-	 * <tt>java.sql.Types</tt> typecode.
+	 * {@link java.sql.Types} typecode.
 	 *
-	 * @param code <tt>java.sql.Types</tt> typecode
+	 * @param code The {@link java.sql.Types} typecode
 	 * @return the database type name
-	 * @throws HibernateException
+	 * @throws HibernateException If no mapping was specified for that type.
 	 */
 	public String getTypeName(int code) throws HibernateException {
 		String result = typeNames.get( code );
@@ -216,355 +273,310 @@
 		return result;
 	}
 
-	
-	public String getHibernateTypeName(int code) throws HibernateException {
-		String result = hibernateTypeNames.get( code );
-		if ( result == null ) {
-			throw new HibernateException( 
-					"No Hibernate type mapping for java.sql.Types code: " +
-					code);
-		}
-		return result;
-	}
-
-	public String getHibernateTypeName(int code, int length, int precision, int scale) throws HibernateException {
-		String result = hibernateTypeNames.get( code, length, precision, scale );
-		if ( result == null ) {
-			throw new HibernateException( 
-					"No Hibernate type mapping for java.sql.Types code: " +
-					code +
-					", length: " +
-					length 
-				);
-		}
-		return result;		
-	}
-
 	/**
 	 * Get the name of the database type associated with the given
-	 * <tt>java.sql.Types</tt> typecode.
-	 * @param code      <tt>java.sql.Types</tt> typecode
-	 * @param length    the length or precision of the column
-	 * @param precision the precision of the column
-	 * @param scale the scale of the column
+	 * {@link java.sql.Types} typecode with the given storage specification
+	 * parameters.
 	 *
+	 * @param code The {@link java.sql.Types} typecode
+	 * @param length The datatype length
+	 * @param precision The datatype precision
+	 * @param scale The datatype scale
 	 * @return the database type name
-	 * @throws HibernateException
+	 * @throws HibernateException If no mapping was specified for that type.
 	 */
 	public String getTypeName(int code, int length, int precision, int scale) throws HibernateException {
 		String result = typeNames.get( code, length, precision, scale );
 		if ( result == null ) {
-			throw new HibernateException( 
+			throw new HibernateException(
 					"No type mapping for java.sql.Types code: " +
 					code +
 					", length: " +
-					length 
-				);
+					length
+			);
 		}
 		return result;
 	}
-	
+
+	/**
+	 * Get the name of the database type appropriate for casting operations
+	 * (via the CAST() SQL function) for the given {@link java.sql.Types} typecode.
+	 *
+	 * @param code The {@link java.sql.Types} typecode
+	 * @return The database type name
+	 */
 	public String getCastTypeName(int code) {
-		return getTypeName(
-				code, 
-				Column.DEFAULT_LENGTH, 
-				Column.DEFAULT_PRECISION, 
-				Column.DEFAULT_SCALE 
-			);
+		return getTypeName( code, Column.DEFAULT_LENGTH, Column.DEFAULT_PRECISION, Column.DEFAULT_SCALE );
 	}
 
-	protected void registerFunction(String name, SQLFunction function) {
-		sqlFunctions.put( name, function );
-	}
-
-	protected void registerKeyword(String word) {
-		sqlKeywords.add(word);
-	}
-	
-	public Set getKeywords() {
-		return sqlKeywords;
-	}
-
 	/**
-	 * Subclasses register a typename for the given type code and maximum
+	 * Subclasses register a type name for the given type code and maximum
 	 * column length. <tt>$l</tt> in the type name with be replaced by the
 	 * column length (if appropriate).
 	 *
-	 * @param code     <tt>java.sql.Types</tt> typecode
-	 * @param capacity maximum length of database type
-	 * @param name     the database type name
+	 * @param code The {@link java.sql.Types} typecode
+	 * @param capacity The maximum length of database type
+	 * @param name The database type name
 	 */
 	protected void registerColumnType(int code, int capacity, String name) {
 		typeNames.put( code, capacity, name );
 	}
 
 	/**
-	 * Subclasses register a typename for the given type code. <tt>$l</tt> in
+	 * Subclasses register a type name for the given type code. <tt>$l</tt> in
 	 * the type name with be replaced by the column length (if appropriate).
 	 *
-	 * @param code <tt>java.sql.Types</tt> typecode
-	 * @param name the database type name
+	 * @param code The {@link java.sql.Types} typecode
+	 * @param name The database type name
 	 */
 	protected void registerColumnType(int code, String name) {
 		typeNames.put( code, name );
 	}
-	
-	protected void registerHibernateType(int sqlcode, String name) {
-		hibernateTypeNames.put( sqlcode, name);
-	}
 
-	protected void registerHibernateType(int sqlcode, int capacity, String name) {
-		hibernateTypeNames.put( sqlcode, capacity, name);
-	}
 
-	/**
-	 * Does this dialect support the <tt>ALTER TABLE</tt> syntax?
-	 *
-	 * @return boolean
-	 */
-	public boolean hasAlterTable() {
-		return true;
-	}
+	// hibernate type mapping support ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
 
 	/**
-	 * Do we need to drop constraints before dropping tables in this dialect?
+	 * Get the name of the Hibernate {@link org.hibernate.type.Type} associated with th given
+	 * {@link java.sql.Types} typecode.
 	 *
-	 * @return boolean
+	 * @param code The {@link java.sql.Types} typecode
+	 * @return The Hibernate {@link org.hibernate.type.Type} name.
+	 * @throws HibernateException If no mapping was specified for that type.
 	 */
-	public boolean dropConstraints() {
-		return true;
+	public String getHibernateTypeName(int code) throws HibernateException {
+		String result = hibernateTypeNames.get( code );
+		if ( result == null ) {
+			throw new HibernateException( "No Hibernate type mapping for java.sql.Types code: " + code );
+		}
+		return result;
 	}
 
 	/**
-	 * Do we need to qualify index names with the schema name?
+	 * Get the name of the Hibernate {@link org.hibernate.type.Type} associated
+	 * with the given {@link java.sql.Types} typecode with the given storage
+	 * specification parameters.
 	 *
-	 * @return boolean
+	 * @param code The {@link java.sql.Types} typecode
+	 * @param length The datatype length
+	 * @param precision The datatype precision
+	 * @param scale The datatype scale
+	 * @return The Hibernate {@link org.hibernate.type.Type} name.
+	 * @throws HibernateException If no mapping was specified for that type.
 	 */
-	public boolean qualifyIndexName() {
-		return true;
+	public String getHibernateTypeName(int code, int length, int precision, int scale) throws HibernateException {
+		String result = hibernateTypeNames.get( code, length, precision, scale );
+		if ( result == null ) {
+			throw new HibernateException( 
+					"No Hibernate type mapping for java.sql.Types code: " +
+					code +
+					", length: " +
+					length 
+			);
+		}
+		return result;		
 	}
 
 	/**
-	 * Does the <tt>FOR UPDATE OF</tt> syntax specify particular
-	 * columns?
-	 */
-	public boolean forUpdateOfColumns() {
-		return false;
-	}
-
-	/**
-	 * Retrieves the <tt>FOR UPDATE OF column_list</tt> syntax specific to this
-	 * dialect, where the given aliases represent the aliases of the columns
-	 * which are to be write locked.
+	 * Registers a Hibernate {@link org.hibernate.type.Type} name for the given
+	 * {@link java.sql.Types} type code and maximum column length.
 	 *
-	 * @return The appropriate <tt>FOR UPDATE OF column_list</tt> clause string.
+	 * @param code The {@link java.sql.Types} typecode
+	 * @param capacity The maximum length of database type
+	 * @param name The Hibernate {@link org.hibernate.type.Type} name
 	 */
-	public String getForUpdateString(String aliases) {
-		return getForUpdateString();
+	protected void registerHibernateType(int code, int capacity, String name) {
+		hibernateTypeNames.put( code, capacity, name);
 	}
 
 	/**
-	 * Retrieves the <tt>FOR UPDATE OF column_list NOWAIT</tt> syntax specific
-	 * to this dialect, where the given aliases represent the aliases of the
-	 * columns which are to be write locked.
+	 * Registers a Hibernate {@link org.hibernate.type.Type} name for the given
+	 * {@link java.sql.Types} type code.
 	 *
-	 * @return The appropriate <tt>FOR UPDATE colunm_list</tt> NOWAIT clause string.
+	 * @param code The {@link java.sql.Types} typecode
+	 * @param name The Hibernate {@link org.hibernate.type.Type} name
 	 */
-	public String getForUpdateNowaitString(String aliases) {
-		return getForUpdateString( aliases );
+	protected void registerHibernateType(int code, String name) {
+		hibernateTypeNames.put( code, name);
 	}
 
-	/**
-	 * Retrieves the <tt>FOR UPDATE</tt> syntax specific to this dialect.
-	 *
-	 * @return The appropriate <tt>FOR UPDATE</tt> clause string.
-	 */
-	public String getForUpdateString() {
-		return " for update";
-	}
 
-	/**
-	 * Retrieves the <tt>FOR UPDATE NOWAIT</tt> syntax specific to this dialect.
-	 *
-	 * @return The appropriate <tt>FOR UPDATE NOWAIT</tt> clause string.
-	 */
-	public String getForUpdateNowaitString() {
-		return getForUpdateString();
+	// function support ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+	protected void registerFunction(String name, SQLFunction function) {
+		sqlFunctions.put( name, function );
 	}
 
 	/**
-	 * Does this dialect support the <tt>UNIQUE</tt> column syntax?
+	 * Retrieves a map of the dialect's registered fucntions
+	 * (functionName => {@link org.hibernate.dialect.function.SQLFunction}).
 	 *
-	 * @return boolean
+	 * @return The map of registered functions.
 	 */
-	public boolean supportsUnique() {
-		return true;
+	public final Map getFunctions() {
+		return sqlFunctions;
 	}
-	
 
-    /**
-     * Does this dialect support adding Unique constraints via create and alter table ?
-     * @return boolean
-     */
-	public boolean supportsUniqueConstraintInCreateAlterTable() {
-	    return true;
-	}
 
+	// keyword support ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
 
-	/**
-	 * The syntax used to add a column to a table (optional).
-	 */
-	public String getAddColumnString() {
-		throw new UnsupportedOperationException( "No add column syntax supported by Dialect" );
+	protected void registerKeyword(String word) {
+		sqlKeywords.add(word);
 	}
-
-	public String getDropForeignKeyString() {
-		return " drop constraint ";
+	
+	public Set getKeywords() {
+		return sqlKeywords;
 	}
 
-	public String getTableTypeString() {
-		return "";
-	}
 
+	// native identifier generatiion ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
 	/**
-	 * The syntax used to add a foreign key constraint to a table.
-	 * 
-	 * @param referencesPrimaryKey if false, constraint should be 
-	 * explicit about which column names the constraint refers to
+	 * The class (which implements {@link org.hibernate.id.IdentifierGenerator})
+	 * which acts as this dialects native generation strategy.
+	 * <p/>
+	 * Comes into play whenever the user specifies the native generator.
 	 *
-	 * @return String
+	 * @return The native generator class.
 	 */
-	public String getAddForeignKeyConstraintString(
-			String constraintName,
-			String[] foreignKey,
-			String referencedTable,
-			String[] primaryKey, 
-			boolean referencesPrimaryKey
-	) {
-		StringBuffer res = new StringBuffer( 30 );
-		
-		res.append( " add constraint " )
-		   .append( constraintName )
-		   .append( " foreign key (" )
-		   .append( StringHelper.join( ", ", foreignKey ) )
-		   .append( ") references " )
-		   .append( referencedTable );
-		
-		if(!referencesPrimaryKey) {
-			res.append(" (")
-			   .append( StringHelper.join(", ", primaryKey) )
-			   .append(')');
+	public Class getNativeIdentifierGeneratorClass() {
+		if ( supportsIdentityColumns() ) {
+			return IdentityGenerator.class;
 		}
-
-		return res.toString();
+		else if ( supportsSequences() ) {
+			return SequenceGenerator.class;
+		}
+		else {
+			return TableHiLoGenerator.class;
+		}
 	}
 
-	/**
-	 * The syntax used to add a primary key constraint to a table.
-	 *
-	 * @return String
-	 */
-	public String getAddPrimaryKeyConstraintString(String constraintName) {
-		return " add constraint " + constraintName + " primary key ";
-	}
 
+	// IDENTITY support ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
 	/**
-	 * The keyword used to specify a nullable column.
+	 * Does this dialect support identity column key generation?
 	 *
-	 * @return String
+	 * @return True if IDENTITY columns are supported; false otherwise.
 	 */
-	public String getNullColumnString() {
-		return "";
+	public boolean supportsIdentityColumns() {
+		return false;
 	}
 
 	/**
-	 * Does this dialect support identity column key generation?
+	 * Does the dialect support some form of inserting and selecting
+	 * the generated IDENTITY value all in the same statement.
 	 *
-	 * @return boolean
+	 * @return True if the dialect supports selecting the just
+	 * generated IDENTITY in the insert statement.
 	 */
-	public boolean supportsIdentityColumns() {
+	public boolean supportsInsertSelectIdentity() {
 		return false;
 	}
 
 	/**
-	 * Does this dialect support sequences?
+	 * Whether this dialect have an Identity clause added to the data type or a
+	 * completely seperate identity data type
 	 *
 	 * @return boolean
 	 */
-	public boolean supportsSequences() {
-		return false;
+	public boolean hasDataTypeInIdentityColumn() {
+		return true;
 	}
 
-	public boolean supportsInsertSelectIdentity() {
-		return false;
-	}
-
 	/**
-	 * Append a clause to retrieve the generated identity value for the
-	 * given <tt>INSERT</tt> statement.
+	 * Provided we {@link #supportsInsertSelectIdentity}, then attch the
+	 * "select identity" clause to the  insert statement.
+	 *  <p/>
+	 * Note, if {@link #supportsInsertSelectIdentity} == false then
+	 * the insert-string should be returned without modification.
+	 *
+	 * @param insertString The insert command
+	 * @return The insert command with any necessary identity select
+	 * clause attached.
 	 */
 	public String appendIdentitySelectToInsert(String insertString) {
 		return insertString;
 	}
 
-	protected String getIdentitySelectString() throws MappingException {
-		throw new MappingException( "Dialect does not support identity key generation" );
-	}
-
 	/**
-	 * The syntax that returns the identity value of the last insert, if
-	 * identity column key generation is supported.
+	 * Get the select command to use to retrieve the last generated IDENTITY
+	 * value for a particuar table
 	 *
-	 * @param type TODO
-	 * @throws MappingException if no native key generation
+	 * @param table The table into which the insert was done
+	 * @param column The PK column.
+	 * @param type The {@link java.sql.Types} type code.
+	 * @return The appropriate select command
+	 * @throws MappingException If IDENTITY generation is not supported.
 	 */
-	public String getIdentitySelectString(String table, String column, int type)
-			throws MappingException {
+	public String getIdentitySelectString(String table, String column, int type) throws MappingException {
 		return getIdentitySelectString();
 	}
 
-	protected String getIdentityColumnString() throws MappingException {
+	/**
+	 * Get the select command to use to retrieve the last generated IDENTITY
+	 * value.
+	 *
+	 * @return The appropriate select command
+	 * @throws MappingException If IDENTITY generation is not supported.
+	 */
+	protected String getIdentitySelectString() throws MappingException {
 		throw new MappingException( "Dialect does not support identity key generation" );
 	}
 
 	/**
-	 * The keyword used to specify an identity column, if identity
-	 * column key generation is supported.
+	 * The syntax used during DDL to define a column as being an IDENTITY of
+	 * a particular type.
 	 *
-	 * @param type the SQL column type, as defined by <tt>java.sql.Types</tt>
-	 * @throws MappingException if no native key generation
+	 * @param type The {@link java.sql.Types} type code.
+	 * @return The appropriate DDL fragment.
+	 * @throws MappingException If IDENTITY generation is not supported.
 	 */
 	public String getIdentityColumnString(int type) throws MappingException {
 		return getIdentityColumnString();
 	}
 
 	/**
+	 * The syntax used during DDL to define a column as being an IDENTITY.
+	 *
+	 * @return The appropriate DDL fragment.
+	 * @throws MappingException If IDENTITY generation is not supported.
+	 */
+	protected String getIdentityColumnString() throws MappingException {
+		throw new MappingException( "Dialect does not support identity key generation" );
+	}
+
+	/**
 	 * The keyword used to insert a generated value into an identity column (or null).
 	 * Need if the dialect does not support inserts that specify no column values.
 	 *
-	 * @return String
+	 * @return The appropriate keyword.
 	 */
 	public String getIdentityInsertString() {
 		return null;
 	}
 
+
+	// SEQUENCE support ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
 	/**
-	 * The keyword used to insert a row without specifying any column values.
-	 * This is not possible on some databases.
+	 * Does this dialect support sequences?
+	 *
+	 * @return True if sequences supported; false otherwise.
 	 */
-	public String getNoColumnsInsertString() {
-		return "values ( )";
+	public boolean supportsSequences() {
+		return false;
 	}
 
 	/**
 	 * Generate the appropriate select statement to to retreive the next value
-	 * of a sequence, if sequences are supported.
+	 * of a sequence.
 	 * <p/>
 	 * This should be a "stand alone" select statement.
 	 *
 	 * @param sequenceName the name of the sequence
 	 * @return String The "nextval" select string.
-	 * @throws MappingException if no sequences
+	 * @throws MappingException If sequences are not supported.
 	 */
 	public String getSequenceNextValString(String sequenceName) throws MappingException {
 		throw new MappingException( "Dialect does not support sequences" );
@@ -572,322 +584,467 @@
 
 	/**
 	 * Generate the select expression fragment that will retreive the next
-	 * value of a sequence, if sequences are supported.
+	 * value of a sequence as part of another (typically DML) statement.
 	 * <p/>
 	 * This differs from {@link #getSequenceNextValString(String)} in that this
-	 * should return an expression usable within another select statement.
+	 * should return an expression usable within another statement.
 	 *
 	 * @param sequenceName the name of the sequence
-	 * @return String
-	 * @throws MappingException if no sequences
+	 * @return The "nextval" fragment.
+	 * @throws MappingException If sequences are not supported.
 	 */
 	public String getSelectSequenceNextValString(String sequenceName) throws MappingException {
 		throw new MappingException( "Dialect does not support sequences" );
 	}
 
 	/**
-	 * The syntax used to create a sequence, if sequences are supported.
+	 * The multiline script used to create a sequence.
 	 *
-	 * @param sequenceName the name of the sequence
-	 * @return String
-	 * @throws MappingException if no sequences
+	 * @param sequenceName The name of the sequence
+	 * @return The sequence creation commands
+	 * @throws MappingException If sequences are not supported.
 	 */
-	protected String getCreateSequenceString(String sequenceName) throws MappingException {
-		throw new MappingException( "Dialect does not support sequences" );
+	public String[] getCreateSequenceStrings(String sequenceName) throws MappingException {
+		return new String[] { getCreateSequenceString( sequenceName ) };
 	}
 
 	/**
-	 * The multiline script used to create a sequence, if sequences are supported.
+	 * Typically dialects which support sequences can create a sequence
+	 * with a single command.  This is convenience form of
+	 * {@link #getCreateSequenceStrings} to help facilitate that.
+	 * <p/>
+	 * Dialects which support sequences and can create a sequence in a
+	 * single command need *only* override this method.  Dialects
+	 * which support sequences but require multiple commands to create
+	 * a sequence should instead override {@link #getCreateSequenceStrings}.
 	 *
-	 * @param sequenceName the name of the sequence
-	 * @return String[]
-	 * @throws MappingException if no sequences
+	 * @param sequenceName The name of the sequence
+	 * @return The sequence creation command
+	 * @throws MappingException If sequences are not supported.
 	 */
-	public String[] getCreateSequenceStrings(String sequenceName) throws MappingException {
-		return new String[]{getCreateSequenceString( sequenceName )};
+	protected String getCreateSequenceString(String sequenceName) throws MappingException {
+		throw new MappingException( "Dialect does not support sequences" );
 	}
 
 	/**
-	 * The syntax used to drop a sequence, if sequences are supported.
+	 * The multiline script used to drop a sequence.
 	 *
-	 * @param sequenceName the name of the sequence
-	 * @return String
-	 * @throws MappingException if no sequences
+	 * @param sequenceName The name of the sequence
+	 * @return The sequence drop commands
+	 * @throws MappingException If sequences are not supported.
 	 */
-	protected String getDropSequenceString(String sequenceName) throws MappingException {
-		throw new MappingException( "Dialect does not support sequences" );
+	public String[] getDropSequenceStrings(String sequenceName) throws MappingException {
+		return new String[]{getDropSequenceString( sequenceName )};
 	}
 
 	/**
-	 * The multiline script used to drop a sequence, if sequences are supported.
+	 * Typically dialects which support sequences can drop a sequence
+	 * with a single command.  This is convenience form of
+	 * {@link #getDropSequenceStrings} to help facilitate that.
+	 * <p/>
+	 * Dialects which support sequences and can drop a sequence in a
+	 * single command need *only* override this method.  Dialects
+	 * which support sequences but require multiple commands to drop
+	 * a sequence should instead override {@link #getDropSequenceStrings}.
 	 *
-	 * @param sequenceName the name of the sequence
-	 * @return String[]
-	 * @throws MappingException if no sequences
+	 * @param sequenceName The name of the sequence
+	 * @return The sequence drop commands
+	 * @throws MappingException If sequences are not supported.
 	 */
-	public String[] getDropSequenceStrings(String sequenceName) throws MappingException {
-		return new String[]{getDropSequenceString( sequenceName )};
+	protected String getDropSequenceString(String sequenceName) throws MappingException {
+		throw new MappingException( "Dialect does not support sequences" );
 	}
 
 	/**
-	 * A query used to find all sequences
+	 * 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 null;
 	}
 
+
+	// GUID support ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
 	/**
-	 * Get the <tt>Dialect</tt> specified by the current <tt>System</tt> properties.
+	 * Get the command used to select a GUID from the underlying database.
+	 * <p/>
+	 * Optional operation.
 	 *
-	 * @return Dialect
-	 * @throws HibernateException
+	 * @return The appropriate command.
 	 */
-	public static Dialect getDialect() throws HibernateException {
-		String dialectName = Environment.getProperties().getProperty( Environment.DIALECT );
-		if ( dialectName == null ) throw new HibernateException( "The dialect was not set. Set the property hibernate.dialect." );
-		try {
-			return ( Dialect ) ReflectHelper.classForName( dialectName ).newInstance();
-		}
-		catch ( ClassNotFoundException cnfe ) {
-			throw new HibernateException( "Dialect class not found: " + dialectName );
-		}
-		catch ( Exception e ) {
-			throw new HibernateException( "Could not instantiate dialect class", e );
-		}
+	public String getSelectGUIDString() {
+		throw new UnsupportedOperationException( "dialect does not support GUIDs" );
 	}
 
 
+	// limit/offset support ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
 	/**
-	 * Get the <tt>Dialect</tt> specified by the given properties or system properties.
+	 * Does this dialect support some form of limiting query results
+	 * via a SQL clause?
 	 *
-	 * @param props
-	 * @return Dialect
-	 * @throws HibernateException
+	 * @return True if this dialect supports some form of LIMIT.
 	 */
-	public static Dialect getDialect(Properties props) throws HibernateException {
-		String dialectName = props.getProperty( Environment.DIALECT );
-		if ( dialectName == null ) return getDialect();
-		try {
-			return ( Dialect ) ReflectHelper.classForName( dialectName ).newInstance();
-		}
-		catch ( ClassNotFoundException cnfe ) {
-			throw new HibernateException( "Dialect class not found: " + dialectName );
-		}
-		catch ( Exception e ) {
-			throw new HibernateException( "Could not instantiate dialect class", e );
-		}
+	public boolean supportsLimit() {
+		return false;
 	}
 
 	/**
-	 * Retrieve a set of default Hibernate properties for this database.
+	 * Does this dialect's LIMIT support (if any) additionally
+	 * support specifying an offset?
 	 *
-	 * @return a set of Hibernate properties
+	 * @return True if the dialect supports an offset within the limit support.
 	 */
-	public final Properties getDefaultProperties() {
-		return properties;
+	public boolean supportsLimitOffset() {
+		return supportsLimit();
 	}
 
 	/**
-	 * Completely optional cascading drop clause
+	 * Does this dialect support bind variables (i.e., prepared statememnt
+	 * parameters) for its limit/offset?
 	 *
-	 * @return String
+	 * @return True if bind variables can be used; false otherwise.
 	 */
-	public String getCascadeConstraintsString() {
-		return "";
+	public boolean supportsVariableLimit() {
+		return supportsLimit();
 	}
 
 	/**
-	 * Create an <tt>OuterJoinGenerator</tt> for this dialect.
+	 * ANSI SQL defines the LIMIT clause to be in the form LIMIT offset, limit.
+	 * Does this dialect require us to bind the parameters in reverse order?
 	 *
-	 * @return OuterJoinGenerator
+	 * @return true if the correct order is limit, offset
 	 */
-	public JoinFragment createOuterJoinFragment() {
-		return new ANSIJoinFragment();
+	public boolean bindLimitParametersInReverseOrder() {
+		return false;
 	}
 
 	/**
-	 * Create a <tt>CaseFragment</tt> for this dialect.
+	 * Does the <tt>LIMIT</tt> clause come at the start of the
+	 * <tt>SELECT</tt> statement, rather than at the end?
 	 *
-	 * @return OuterJoinGenerator
+	 * @return true if limit parameters should come before other parameters
 	 */
-	public CaseFragment createCaseFragment() {
-		return new ANSICaseFragment();
+	public boolean bindLimitParametersFirst() {
+		return false;
 	}
 
 	/**
-	 * The name of the SQL function that transforms a string to
-	 * lowercase
+	 * Does the <tt>LIMIT</tt> clause take a "maximum" row number instead
+	 * of a total number of returned rows?
+	 * <p/>
+	 * This is easiest understood via an example.  Consider you have a table
+	 * with 20 rows, but you only want to retrieve rows number 11 through 20.
+	 * Generally, a limit with offset would say that the offset = 11 and the
+	 * limit = 10 (we only want 10 rows at a time); this is specifying the
+	 * total number of returned rows.  Some dialects require that we instead
+	 * specify offset = 11 and limit = 20, where 20 is the "last" row we want
+	 * relative to offset (i.e. total number of rows = 20 - 11 = 9)
+	 * <p/>
+	 * So essentially, is limit relative from offset?  Or is limit absolute?
 	 *
-	 * @return String
+	 * @return True if limit is relative from offset; false otherwise.
 	 */
-	public String getLowercaseFunction() {
-		return "lower";
+	public boolean useMaxForLimit() {
+		return false;
 	}
 
 	/**
-	 * Does this <tt>Dialect</tt> have some kind of <tt>LIMIT</tt> syntax?
+	 * Given a limit and an offset, apply the limit clause to the query.
+	 *
+	 * @param query The query to which to apply the limit.
+	 * @param offset The offset of the limit
+	 * @param limit The limit of the limit ;)
+	 * @return The modified query statement with the limit applied.
 	 */
-	public boolean supportsLimit() {
-		return false;
+	public String getLimitString(String query, int offset, int limit) {
+		return getLimitString( query, offset > 0 );
 	}
 
 	/**
-	 * Does this dialect support an offset?
+	 * Apply s limit clause to the query.
+	 * <p/>
+	 * Typically dialects utilize {@link #supportsVariableLimit() variable}
+	 * limit caluses when they support limits.  Thus, when building the
+	 * select command we do not actually need to know the limit or the offest
+	 * since we will just be using placeholders.
+	 * <p/>
+	 * Here we do still pass along whether or not an offset was specified
+	 * so that dialects not supporting offsets can generate proper exceptions.
+	 * In general, dialects will override one or the other of this method and
+	 * {@link #getLimitString(String, int, int)}.
+	 *
+	 * @param query The query to which to apply the limit.
+	 * @param hasOffset Is the query requesting an offset?
+	 * @return the modified SQL
 	 */
-	public boolean supportsLimitOffset() {
-		return supportsLimit();
+	protected String getLimitString(String query, boolean hasOffset) {
+		throw new UnsupportedOperationException( "paged queries not supported" );
 	}
 
+
+	// lock acquisition support ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
 	/**
-	 * Add a <tt>LIMIT</tt> clause to the given SQL <tt>SELECT</tt>
+	 * Get a strategy instance which knows how to acquire a database-level lock
+	 * of the specified mode for this dialect.
 	 *
-	 * @return the modified SQL
+	 * @param lockable The persister for the entity to be locked.
+	 * @param lockMode The type of lock to be acquired.
+	 * @return The appropriate locking strategy.
+	 * @since 3.2
 	 */
-	public String getLimitString(String querySelect, boolean hasOffset) {
-		throw new UnsupportedOperationException( "paged queries not supported" );
+	public LockingStrategy getLockingStrategy(Lockable lockable, LockMode lockMode) {
+		return new SelectLockingStrategy( lockable, lockMode );
 	}
 
-	public String getLimitString(String querySelect, int offset, int limit) {
-		return getLimitString( querySelect, offset>0 );
+	/**
+	 * Given a lock mode, determine the appropriate for update fragment to use.
+	 *
+	 * @param lockMode The lock mode to apply.
+	 * @return The appropriate for update fragment.
+	 */
+	public String getForUpdateString(LockMode lockMode) {
+		if ( lockMode==LockMode.UPGRADE ) {
+			return getForUpdateString();
+		}
+		else if ( lockMode==LockMode.UPGRADE_NOWAIT ) {
+			return getForUpdateNowaitString();
+		}
+		else if ( lockMode==LockMode.FORCE ) {
+			return getForUpdateNowaitString();
+		}
+		else {
+			return "";
+		}
 	}
 
-	public boolean supportsVariableLimit() {
-		return supportsLimit();
+	/**
+	 * Get the string to append to SELECT statements to acquire locks
+	 * for this dialect.
+	 *
+	 * @return The appropriate <tt>FOR UPDATE</tt> clause string.
+	 */
+	public String getForUpdateString() {
+		return " for update";
 	}
 
 	/**
-	 * Does the <tt>LIMIT</tt> clause specify arguments in the "reverse" order
-	 * limit, offset instead of offset, limit?
+	 * Is <tt>FOR UPDATE OF</tt> syntax supported?
 	 *
-	 * @return true if the correct order is limit, offset
+	 * @return True if the database supports <tt>FOR UPDATE OF</tt> syntax;
+	 * false otherwise.
 	 */
-	public boolean bindLimitParametersInReverseOrder() {
+	public boolean forUpdateOfColumns() {
+		// by default we report no support
 		return false;
 	}
 
 	/**
-	 * Does the <tt>LIMIT</tt> clause come at the start of the
-	 * <tt>SELECT</tt> statement, rather than at the end?
+	 * Does this dialect support <tt>FOR UPDATE</tt> in conjunction with
+	 * outer joined rows?
 	 *
-	 * @return true if limit parameters should come before other parameters
+	 * @return True if outer joined rows can be locked via <tt>FOR UPDATE</tt>.
 	 */
-	public boolean bindLimitParametersFirst() {
-		return false;
+	public boolean supportsOuterJoinForUpdate() {
+		return true;
 	}
 
 	/**
-	 * Does the <tt>LIMIT</tt> clause take a "maximum" row number instead
-	 * of a total number of returned rows?
+	 * Get the <tt>FOR UPDATE OF column_list</tt> fragment appropriate for this
+	 * dialect given the aliases of the columns to be write locked.
+	 *
+	 * @param aliases The columns to be write locked.
+	 * @return The appropriate <tt>FOR UPDATE OF column_list</tt> clause string.
 	 */
-	public boolean useMaxForLimit() {
-		return false;
+	public String getForUpdateString(String aliases) {
+		// by default we simply return the getForUpdateString() result since
+		// the default is to say no support for "FOR UPDATE OF ..."
+		return getForUpdateString();
 	}
 
 	/**
-	 * The opening quote for a quoted identifier
+	 * Retrieves the <tt>FOR UPDATE NOWAIT</tt> syntax specific to this dialect.
+	 *
+	 * @return The appropriate <tt>FOR UPDATE NOWAIT</tt> clause string.
 	 */
-	public char openQuote() {
-		return '"';
+	public String getForUpdateNowaitString() {
+		// by default we report no support for NOWAIT lock semantics
+		return getForUpdateString();
 	}
 
 	/**
-	 * The closing quote for a quoted identifier
+	 * Get the <tt>FOR UPDATE OF column_list NOWAIT</tt> fragment appropriate
+	 * for this dialect given the aliases of the columns to be write locked.
+	 *
+	 * @param aliases The columns to be write locked.
+	 * @return The appropriate <tt>FOR UPDATE colunm_list NOWAIT</tt> clause string.
 	 */
-	public char closeQuote() {
-		return '"';
+	public String getForUpdateNowaitString(String aliases) {
+		return getForUpdateString( aliases );
 	}
 
 	/**
-	 * SQL functions as defined in general. The results of this
-	 * method should be integrated with the specialisation's data.
+	 * Some dialects support an alternative means to <tt>SELECT FOR UPDATE</tt>,
+	 * whereby a "lock hint" is appends to the table name in the from clause.
+	 * <p/>
+	 * contributed by <a href="http://sourceforge.net/users/heschulz">Helge Schulz</a>
+	 *
+	 * @param mode The lock mode to apply
+	 * @param tableName The name of the table to which to apply the lock hint.
+	 * @return The table with any required lock hints.
 	 */
-	public final Map getFunctions() {
-		return sqlFunctions;
+	public String appendLockHint(LockMode mode, String tableName) {
+		return tableName;
 	}
 
-	public boolean supportsIfExistsBeforeTableName() {
+
+	// temporary table support ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+	/**
+	 * Does this dialect support temporary tables?
+	 *
+	 * @return True if temp tables are supported; false otherwise.
+	 */
+	public boolean supportsTemporaryTables() {
 		return false;
 	}
 
-	public boolean supportsIfExistsAfterTableName() {
-		return false;
+	/**
+	 * Generate a temporary table name given the bas table.
+	 *
+	 * @param baseTableName The table name from which to base the temp table name.
+	 * @return The generated temp table name.
+	 */
+	public String generateTemporaryTableName(String baseTableName) {
+		return "HT_" + baseTableName;
 	}
-	
+
 	/**
-	 * Does this dialect support column-level check constraints?
+	 * Command used to create a temporary table.
+	 *
+	 * @return The command used to create a temporary table.
 	 */
-	public boolean supportsColumnCheck() {
-		return true;
+	public String getCreateTemporaryTableString() {
+		return "create table";
 	}
-	
+
 	/**
-	 * Does this dialect support table-level check constraints?
+	 * Get any fragments needing to be postfixed to the command for
+	 * temporary table creation.
+	 *
+	 * @return Any required postfix.
 	 */
-	public boolean supportsTableCheck() {
-		return true;
+	public String getCreateTemporaryTablePostfix() {
+		return "";
 	}
 
 	/**
-	 * Whether this dialect have an Identity clause added to the data type or a
-	 * completely seperate identity data type
+	 * Does the dialect require that temporary table DDL statements
+	 * occur in isolation from other statements?
+	 * todo : perhaps have this return java.lang.Boolean instead where null means to use the value returned by the driver.
+	 * 
+	 * @return
+	 */
+	public boolean performTemporaryTableDDLInIsolation() {
+		return false;
+	}
+
+	/**
+	 * Do we need to drop the temporary table after use?
 	 *
-	 * @return boolean
+	 * @return True if the table should be dropped.
 	 */
-	public boolean hasDataTypeInIdentityColumn() {
+	public boolean dropTemporaryTableAfterUse() {
 		return true;
 	}
 
-	public boolean supportsCascadeDelete() {
-		return true;
+
+	// callable statement support ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+	/**
+	 * Registers an OUT parameter which will be returing a
+	 * {@link java.sql.ResultSet}.  How this is accomplished varies greatly
+	 * from DB to DB, hence its inclusion (along with {@link #getResultSet}) here.
+	 *
+	 * @param statement The callable statement.
+	 * @param position The bind position at which to register the OUT param.
+	 * @return The number of (contiguous) bind positions used.
+	 * @throws SQLException Indicates problems registering the OUT param.
+	 */
+	public int registerResultSetOutParameter(CallableStatement statement, int position) throws SQLException {
+		throw new UnsupportedOperationException(
+				getClass().getName() +
+				" does not support resultsets via stored procedures"
+			);
 	}
 
 	/**
-	 * Method <code>appendLockHint</code> appends according to the given
-	 * lock mode a lock hint behind the given table name, if this dialect
-	 * needs this. MS SQL Server for example doesn't support the
-	 * standard "<code>select ... for update</code>" syntax and use a
-	 * special "<code>select ... from TABLE as ALIAS with (updlock, rowlock)
-	 * where ...</code>" syntax instead.
+	 * Given a callable statement previously processed by {@link #registerResultSetOutParameter},
+	 * extract the {@link java.sql.ResultSet} from the OUT parameter.
 	 *
-	 * @param tableName name of table to append lock hint
-	 * @return String
-	 *         <p/>
-	 *         author <a href="http://sourceforge.net/users/heschulz">Helge Schulz</a>
+	 * @param statement The callable statement.
+	 * @return The extracted result set.
+	 * @throws SQLException Indicates problems extracting the result set.
 	 */
-	public String appendLockHint(LockMode mode, String tableName) {
-		return tableName;
+	public ResultSet getResultSet(CallableStatement statement) throws SQLException {
+		throw new UnsupportedOperationException(
+				getClass().getName() +
+				" does not support resultsets via stored procedures"
+			);
 	}
 
-	public Class getNativeIdentifierGeneratorClass() {
-		if ( supportsIdentityColumns() ) {
-			return IdentityGenerator.class;
-		}
-		else if ( supportsSequences() ) {
-			return SequenceGenerator.class;
-		}
-		else {
-			return TableHiLoGenerator.class;
-		}
+	// current timestamp support ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+	/**
+	 * 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 false;
 	}
 
-	public String getSelectGUIDString() {
-		throw new UnsupportedOperationException( "dialect does not support GUIDs" );
+	/**
+	 * 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() {
+		throw new UnsupportedOperationException( "Database not known to define a current timestamp function" );
 	}
 
-	public boolean supportsOuterJoinForUpdate() {
-		return true;
+	/**
+	 * Retrieve the command used to retrieve the current timestammp from the
+	 * database.
+	 *
+	 * @return The command.
+	 */
+	public String getCurrentTimestampSelectString() {
+		throw new UnsupportedOperationException( "Database not known to define a current timestamp function" );
 	}
 
-	public String getSelectClauseNullString(int sqlType) {
-		return "null";
+	/**
+	 * The name of the database-specific SQL function for retrieving the
+	 * current timestamp.
+	 *
+	 * @return The function name.
+	 */
+	public String getCurrentTimestampSQLFunctionName() {
+		// the standard SQL function name is current_timestamp...
+		return "current_timestamp";
 	}
-	
-	public boolean supportsNotNullUnique() {
-		return true;
-	}
 
+
+	// SQLException support ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
 	/**
 	 * Build an instance of the SQLExceptionConverter preferred by this dialect for
 	 * converting SQLExceptions into Hibernate's JDBCException hierarchy.  The default
@@ -917,167 +1074,357 @@
 		return EXTRACTER;
 	}
 
-	public final String quote(String column) {
-		if ( column.charAt( 0 ) == '`' ) {
-			return openQuote() + column.substring( 1, column.length() - 1 ) + closeQuote();
-		}
-		else {
-			return column;
-		}
+
+	// union subclass support ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+	/**
+	 * Given a {@link java.sql.Types} type code, determine an appropriate
+	 * null value to use in a select clause.
+	 * <p/>
+	 * One thing to consider here is that certain databases might
+	 * require proper casting for the nulls here since the select here
+	 * will be part of a UNION/UNION ALL.
+	 *
+	 * @param sqlType The {@link java.sql.Types} type code.
+	 * @return The appropriate select clause value fragment.
+	 */
+	public String getSelectClauseNullString(int sqlType) {
+		return "null";
 	}
 
-	public boolean hasSelfReferentialForeignKeyBug() {
+	/**
+	 * 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 false;
 	}
-	
 
-	public boolean useInputStreamToInsertBlob() {
-		return true;
+
+	// miscellaneous support ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+
+	/**
+	 * Create a {@link org.hibernate.sql.JoinFragment} strategy responsible
+	 * for handling this dialect's variations in how joins are handled.
+	 *
+	 * @return This dialect's {@link org.hibernate.sql.JoinFragment} strategy.
+	 */
+	public JoinFragment createOuterJoinFragment() {
+		return new ANSIJoinFragment();
 	}
 
-	public int registerResultSetOutParameter(CallableStatement statement, int col) throws SQLException {
-		throw new UnsupportedOperationException(
-				getClass().getName() + 
-				" does not support resultsets via stored procedures"
-			);
+	/**
+	 * Create a {@link org.hibernate.sql.CaseFragment} strategy responsible
+	 * for handling this dialect's variations in how CASE statements are
+	 * handled.
+	 *
+	 * @return This dialect's {@link org.hibernate.sql.CaseFragment} strategy.
+	 */
+	public CaseFragment createCaseFragment() {
+		return new ANSICaseFragment();
 	}
 
-	public ResultSet getResultSet(CallableStatement ps) throws SQLException {
-		throw new UnsupportedOperationException(
-				getClass().getName() + 
-				" does not support resultsets via stored procedures"
-			);
+	/**
+	 * The fragment used to insert a row without specifying any column values.
+	 * This is not possible on some databases.
+	 *
+	 * @return The appropriate empty values clause.
+	 */
+	public String getNoColumnsInsertString() {
+		return "values ( )";
 	}
-	
-	public boolean supportsUnionAll() {
-		return false;
+
+	/**
+	 * The name of the SQL function that transforms a string to
+	 * lowercase
+	 *
+	 * @return The dialect-specific lowercase function.
+	 */
+	public String getLowercaseFunction() {
+		return "lower";
 	}
-	
-	public boolean supportsCommentOn() {
-		return false;
+
+	/**
+	 * Should LOBs (both BLOB and CLOB) be bound using stream operations (i.e.
+	 * {@link java.sql.PreparedStatement#setBinaryStream}).
+	 *
+	 * @return True if BLOBs and CLOBs should be bound using stream operations.
+	 */
+	public boolean useInputStreamToInsertBlob() {
+		return true;
 	}
-	
-	public String getTableComment(String comment) {
-		return "";
-	}
 
-	public String getColumnComment(String comment) {
-		return "";
-	}
-	
+	/**
+	 * Meant as a means for end users to affect the select strings being sent
+	 * to the database and perhaps manipulate them in some fashion.
+	 * <p/>
+	 * The recommend approach is to instead use
+	 * {@link org.hibernate.Interceptor#onPrepareStatement(String)}.
+	 *
+	 * @param select The select command
+	 * @return The mutated select command, or the same as was passed in.
+	 */
 	public String transformSelectString(String select) {
 		return select;
 	}
 
-	public boolean supportsTemporaryTables() {
-		return false;
+	/**
+	 * What is the maximum length Hibernate can use for generated aliases?
+	 *
+	 * @return The maximum length.
+	 */
+	public int getMaxAliasLength() {
+		return 10;
 	}
 
-	public String generateTemporaryTableName(String baseTableName) {
-		return "HT_" + baseTableName;
+	/**
+	 * The SQL literal value to which this database maps boolean values.
+	 *
+	 * @param bool The boolean value
+	 * @return The appropriate SQL literal.
+	 */
+	public String toBooleanValueString(boolean bool) {
+		return bool ? "1" : "0";
 	}
 
-	public String getCreateTemporaryTableString() {
-		return "create table";
+	/**
+	 * Does this dialect support parameters within the select clause of
+	 * INSERT ... SELECT ... statements?
+	 *
+	 * @return True if this is supported; false otherwise.
+	 */
+	public boolean supportsParametersInInsertSelect() {
+		return true;
 	}
 
-	public boolean performTemporaryTableDDLInIsolation() {
+	/**
+	 * Is this dialect known to support what ANSI-SQL terms "row value
+	 * constructor" syntax; sometimes called tuple syntax.
+	 * <p/>
+	 * Basically, does it support syntax like
+	 * "... where (FIRST_NAME, LAST_NAME) = ('Steve', 'Ebersole') ...".
+	 *
+	 * @return True if this SQL dialect is known to support "row value
+	 * constructor" syntax; false otherwise.
+	 * @since 3.2
+	 */
+	public boolean supportsRowValueConstructorSyntax() {
+		// return false here, as most databases do not properly support this construct...
 		return false;
 	}
 
-	public String getCreateTemporaryTablePostfix() {
-		return "";
+
+	// identifier quoting support ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+	/**
+	 * The character specific to this dialect used to begin a quoted identifier.
+	 *
+	 * @return The dialect's specific open quote character.
+	 */
+	public char openQuote() {
+		return '"';
 	}
 
-	public boolean dropTemporaryTableAfterUse() {
-		return true;
+	/**
+	 * The character specific to this dialect used to close a quoted identifier.
+	 *
+	 * @return The dialect's specific close quote character.
+	 */
+	public char closeQuote() {
+		return '"';
 	}
 
-	public String getForUpdateString(LockMode lockMode) {
-		if ( lockMode==LockMode.UPGRADE ) {
-			return getForUpdateString();
+	/**
+	 * Apply dialect-specific quoting.
+	 * <p/>
+	 * By default, the incoming value is checked to see if its first character
+	 * is the back-tick (`).  If so, the dialect specific quoting is applied.
+	 *
+	 * @param column The value to be quoted.
+	 * @return The quoted (or unmodified, if not starting with back-tick) value.
+	 * @see #openQuote()
+	 * @see #closeQuote()
+	 */
+	public final String quote(String column) {
+		if ( column.charAt( 0 ) == '`' ) {
+			return openQuote() + column.substring( 1, column.length() - 1 ) + closeQuote();
 		}
-		else if ( lockMode==LockMode.UPGRADE_NOWAIT ) {
-			return getForUpdateNowaitString();
-		}
-		else if ( lockMode==LockMode.FORCE ) {
-			return getForUpdateNowaitString();
-		}
 		else {
-			return "";
+			return column;
 		}
 	}
-	
-	public int getMaxAliasLength() {
-		return 10;
+
+
+	// DDL support ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+	/**
+	 * Does this dialect support the <tt>ALTER TABLE</tt> syntax?
+	 *
+	 * @return True if we support altering of tables; false otherwise.
+	 */
+	public boolean hasAlterTable() {
+		return true;
 	}
 
-	public boolean supportsCurrentTimestampSelection() {
-		return false;
+	/**
+	 * Do we need to drop constraints before dropping tables in this dialect?
+	 *
+	 * @return True if constraints must be dropped prior to dropping
+	 * the table; false otherwise.
+	 */
+	public boolean dropConstraints() {
+		return true;
 	}
 
-	public String getCurrentTimestampSelectString() {
-		throw new UnsupportedOperationException( "Database not known to define a current timestamp function" );
+	/**
+	 * Do we need to qualify index names with the schema name?
+	 *
+	 * @return boolean
+	 */
+	public boolean qualifyIndexName() {
+		return true;
 	}
 
-	public boolean isCurrentTimestampSelectStringCallable() {
-		throw new UnsupportedOperationException( "Database not known to define a current timestamp function" );
+	/**
+	 * Does this dialect support the <tt>UNIQUE</tt> column syntax?
+	 *
+	 * @return boolean
+	 */
+	public boolean supportsUnique() {
+		return true;
 	}
 	
+    /**
+     * Does this dialect support adding Unique constraints via create and alter table ?
+     * @return boolean
+     */
+	public boolean supportsUniqueConstraintInCreateAlterTable() {
+	    return true;
+	}
+
 	/**
-	 * The SQL value that the JDBC driver maps boolean values to
+	 * The syntax used to add a column to a table (optional).
 	 */
-	public String toBooleanValueString(boolean bool) {
-		return bool ? "1" : "0";
+	public String getAddColumnString() {
+		throw new UnsupportedOperationException( "No add column syntax supported by Dialect" );
 	}
 
+	public String getDropForeignKeyString() {
+		return " drop constraint ";
+	}
+
+	public String getTableTypeString() {
+		// grrr... for differentiation of mysql storage engines
+		return "";
+	}
+
 	/**
-	 * Does this dialect support parameters within the select clause of
-	 * INSERT ... SELECT ... statements?
+	 * The syntax used to add a foreign key constraint to a table.
+	 * 
+	 * @param referencesPrimaryKey if false, constraint should be 
+	 * explicit about which column names the constraint refers to
 	 *
-	 * @return True if this is supported; false otherwise.
+	 * @return String
 	 */
-	public boolean supportsParametersInInsertSelect() {
-		return true;
+	public String getAddForeignKeyConstraintString(
+			String constraintName,
+			String[] foreignKey,
+			String referencedTable,
+			String[] primaryKey, 
+			boolean referencesPrimaryKey
+	) {
+		StringBuffer res = new StringBuffer( 30 );
+		
+		res.append( " add constraint " )
+		   .append( constraintName )
+		   .append( " foreign key (" )
+		   .append( StringHelper.join( ", ", foreignKey ) )
+		   .append( ") references " )
+		   .append( referencedTable );
+		
+		if(!referencesPrimaryKey) {
+			res.append(" (")
+			   .append( StringHelper.join(", ", primaryKey) )
+			   .append(')');
+		}
+
+		return res.toString();
 	}
 
 	/**
-	 * The name of the database-specific SQL function for retrieving the
-	 * current timestamp.
+	 * The syntax used to add a primary key constraint to a table.
 	 *
-	 * @return The function name.
+	 * @return String
 	 */
-	public String getCurrentTimestampSQLFunctionName() {
-		// the standard SQL function name is current_timestamp...
-		return "current_timestamp";
+	public String getAddPrimaryKeyConstraintString(String constraintName) {
+		return " add constraint " + constraintName + " primary key ";
 	}
 
+	public boolean hasSelfReferentialForeignKeyBug() {
+		return false;
+	}
+
 	/**
-	 * Get a strategy instance which knows how to acquire a database-level lock
-	 * of the specified mode for this dialect.
+	 * The keyword used to specify a nullable column.
 	 *
-	 * @param lockable The persister for the entity to be locked.
-	 * @param lockMode The type of lock to be acquired.
-	 * @return The appropriate locking strategy.
-	 * @since 3.2
+	 * @return String
 	 */
-	public LockingStrategy getLockingStrategy(Lockable lockable, LockMode lockMode) {
-		return new SelectLockingStrategy( lockable, lockMode );
+	public String getNullColumnString() {
+		return "";
 	}
 
+	public boolean supportsCommentOn() {
+		return false;
+	}
+
+	public String getTableComment(String comment) {
+		return "";
+	}
+
+	public String getColumnComment(String comment) {
+		return "";
+	}
+
+	public boolean supportsIfExistsBeforeTableName() {
+		return false;
+	}
+
+	public boolean supportsIfExistsAfterTableName() {
+		return false;
+	}
+
 	/**
-	 * Is this dialect known to support what ANSI-SQL terms "row value
-	 * constructor" syntax; sometimes called tuple syntax.
-	 * <p/>
-	 * Basically, does it support syntax like
-	 * "... where (FIRST_NAME, LAST_NAME) = ('Steve', 'Ebersole') ...".
+	 * Does this dialect support column-level check constraints?
+	 */
+	public boolean supportsColumnCheck() {
+		return true;
+	}
+
+	/**
+	 * Does this dialect support table-level check constraints?
+	 */
+	public boolean supportsTableCheck() {
+		return true;
+	}
+
+	public boolean supportsCascadeDelete() {
+		return true;
+	}
+
+	public boolean supportsNotNullUnique() {
+		return true;
+	}
+
+	/**
+	 * Completely optional cascading drop clause
 	 *
-	 * @return True if this SQL dialect is known to support "row value
-	 * constructor" syntax; false otherwise.
-	 * @since 3.2
+	 * @return String
 	 */
-	public boolean supportsRowValueConstructorSyntax() {
-		// return false here, as most databases do not properly support this construct...
-		return false;
+	public String getCascadeConstraintsString() {
+		return "";
 	}
+
 }

Added: branches/Branch_3_2/Hibernate3/src/org/hibernate/dialect/function/ConditionalParenthesisFunction.java
===================================================================
--- branches/Branch_3_2/Hibernate3/src/org/hibernate/dialect/function/ConditionalParenthesisFunction.java	2006-11-08 16:54:55 UTC (rev 10774)
+++ branches/Branch_3_2/Hibernate3/src/org/hibernate/dialect/function/ConditionalParenthesisFunction.java	2006-11-08 16:56:52 UTC (rev 10775)
@@ -0,0 +1,45 @@
+//$Id: ConditionalParenthesisFunction.java,v 1.4 2005/04/26 18:08:01 oneovthafew Exp $
+package org.hibernate.dialect.function;
+
+import java.util.List;
+
+import org.hibernate.engine.SessionFactoryImplementor;
+import org.hibernate.type.Type;
+
+/**
+ * Essentially the same as {@link org.hibernate.dialect.function.StandardSQLFunction},
+ * except that here the parentheses are not included when no arguments are given.
+ *
+ * @author Jonathan Levinson
+ */
+public class ConditionalParenthesisFunction extends StandardSQLFunction {
+
+	public ConditionalParenthesisFunction(String name) {
+		super( name );
+	}
+
+	public ConditionalParenthesisFunction(String name, Type type) {
+		super( name, type );
+	}
+
+	public boolean hasParenthesesIfNoArguments() {
+		return false;
+	}
+
+	public String render(List args, SessionFactoryImplementor factory) {
+		final boolean hasArgs = !args.isEmpty();
+		StringBuffer buf = new StringBuffer();
+		buf.append( getName() );
+		if ( hasArgs ) {
+			buf.append( "(" );
+			for ( int i = 0; i < args.size(); i++ ) {
+				buf.append( args.get( i ) );
+				if ( i < args.size() - 1 ) {
+					buf.append( ", " );
+				}
+			}
+			buf.append( ")" );
+		}
+		return buf.toString();
+	}
+}

Added: branches/Branch_3_2/Hibernate3/src/org/hibernate/dialect/function/ConvertFunction.java
===================================================================
--- branches/Branch_3_2/Hibernate3/src/org/hibernate/dialect/function/ConvertFunction.java	2006-11-08 16:54:55 UTC (rev 10774)
+++ branches/Branch_3_2/Hibernate3/src/org/hibernate/dialect/function/ConvertFunction.java	2006-11-08 16:56:52 UTC (rev 10775)
@@ -0,0 +1,45 @@
+//$Id: CastFunction.java 7368 2005-07-04 02:54:27Z oneovthafew $
+package org.hibernate.dialect.function;
+
+import java.util.List;
+
+import org.hibernate.QueryException;
+import org.hibernate.Hibernate;
+import org.hibernate.engine.Mapping;
+import org.hibernate.engine.SessionFactoryImplementor;
+import org.hibernate.type.Type;
+
+/**
+ * A Cach&eacute; defintion of a convert function.
+ *
+ * @author Jonathan Levinson
+ */
+public class ConvertFunction implements SQLFunction {
+
+	public Type getReturnType(Type columnType, Mapping mapping) throws QueryException {
+		return Hibernate.STRING;
+	}
+
+	public boolean hasArguments() {
+		return true;
+	}
+
+	public boolean hasParenthesesIfNoArguments() {
+		return true;
+	}
+
+	public String render(List args, SessionFactoryImplementor factory) throws QueryException {
+		if ( args.size() != 2 && args.size() != 3 ) {
+			throw new QueryException( "convert() requires two or three arguments" );
+		}
+		String type = ( String ) args.get( 1 );
+
+		if ( args.size() == 2 ) {
+			return "{fn convert(" + args.get( 0 ) + " , " + type + ")}";
+		}
+		else {
+			return "convert(" + args.get( 0 ) + " , " + type + "," + args.get( 2 ) + ")";
+		}
+	}
+
+}

Modified: branches/Branch_3_2/Hibernate3/src/org/hibernate/dialect/function/SQLFunction.java
===================================================================
--- branches/Branch_3_2/Hibernate3/src/org/hibernate/dialect/function/SQLFunction.java	2006-11-08 16:54:55 UTC (rev 10774)
+++ branches/Branch_3_2/Hibernate3/src/org/hibernate/dialect/function/SQLFunction.java	2006-11-08 16:56:52 UTC (rev 10775)
@@ -20,20 +20,39 @@
  */
 public interface SQLFunction {
 	/**
-	 * The function return type
+	 * The return type of the function.  May be either a concrete type which
+	 * is preset, or variable depending upon the type of the first function
+	 * argument.
+	 *
 	 * @param columnType the type of the first argument
+	 * @param mapping The mapping source.
+	 * @return The type to be expected as a return.
+	 * @throws org.hibernate.QueryException Indicates an issue resolving the return type.
 	 */
 	public Type getReturnType(Type columnType, Mapping mapping) throws QueryException;
+
 	/**
 	 * Does this function have any arguments?
+	 *
+	 * @return True if the function expects to have parameters; false otherwise.
 	 */
 	public boolean hasArguments();
+
 	/**
 	 * If there are no arguments, are parens required?
+	 *
+	 * @return True if a no-arg call of this function requires parentheses.
 	 */
 	public boolean hasParenthesesIfNoArguments();
+
 	/**
-	 * Render the function call as SQL
+	 * Render the function call as SQL fragment.
+	 * 
+	 * @param args The function arguments
+	 * @param factory The SessionFactory
+	 * @return The rendered function call
+	 * @throws org.hibernate.QueryException Indicates a problem rendering the
+	 * function call.
 	 */
 	public String render(List args, SessionFactoryImplementor factory) throws QueryException;
 }

Added: branches/Branch_3_2/Hibernate3/src/org/hibernate/dialect/function/StandardJDBCEscapeFunction.java
===================================================================
--- branches/Branch_3_2/Hibernate3/src/org/hibernate/dialect/function/StandardJDBCEscapeFunction.java	2006-11-08 16:54:55 UTC (rev 10774)
+++ branches/Branch_3_2/Hibernate3/src/org/hibernate/dialect/function/StandardJDBCEscapeFunction.java	2006-11-08 16:56:52 UTC (rev 10775)
@@ -0,0 +1,31 @@
+package org.hibernate.dialect.function;
+
+import java.util.List;
+
+import org.hibernate.type.Type;
+import org.hibernate.engine.SessionFactoryImplementor;
+
+/**
+ * Analogous to {@link org.hibernate.dialect.function.StandardSQLFunction}
+ * except that standard JDBC escape sequences (i.e. {fn blah}) are used when
+ * rendering the SQL.
+ *
+ * @author Steve Ebersole
+ */
+public class StandardJDBCEscapeFunction extends StandardSQLFunction {
+	public StandardJDBCEscapeFunction(String name) {
+		super( name );
+	}
+
+	public StandardJDBCEscapeFunction(String name, Type typeValue) {
+		super( name, typeValue );
+	}
+
+	public String render(List args, SessionFactoryImplementor factory) {
+		return "{fn " + super.render( args, factory ) + "}";
+	}
+
+	public String toString() {
+		return "{fn " + getName() + "...}";
+	}
+}

Modified: branches/Branch_3_2/Hibernate3/src/org/hibernate/dialect/function/StandardSQLFunction.java
===================================================================
--- branches/Branch_3_2/Hibernate3/src/org/hibernate/dialect/function/StandardSQLFunction.java	2006-11-08 16:54:55 UTC (rev 10774)
+++ branches/Branch_3_2/Hibernate3/src/org/hibernate/dialect/function/StandardSQLFunction.java	2006-11-08 16:56:52 UTC (rev 10775)
@@ -16,41 +16,91 @@
  * @author David Channon
  */
 public class StandardSQLFunction implements SQLFunction {
-	private Type returnType = null;
-	private String name;
-	
+	private final String name;
+	private final Type type;
+
+	/**
+	 * Construct a standard SQL function definition with a variable return type;
+	 * the actual return type will depend on the types to which the function
+	 * is applied.
+	 * <p/>
+	 * Using this form, the return type is considered non-static and assumed
+	 * to be the type of the first argument.
+	 *
+	 * @param name The name of the function.
+	 */
 	public StandardSQLFunction(String name) {
-		this.name = name;
+		this( name, null );
 	}
-	
-	public StandardSQLFunction(String name, Type typeValue) {
-		returnType = typeValue;
+
+	/**
+	 * Construct a standard SQL function definition with a static return type.
+	 *
+	 * @param name The name of the function.
+	 * @param type The static return type.
+	 */
+	public StandardSQLFunction(String name, Type type) {
 		this.name = name;
+		this.type = type;
 	}
-	
+
+	/**
+	 * Function name accessor
+	 *
+	 * @return The function name.
+	 */
+	public String getName() {
+		return name;
+	}
+
+	/**
+	 * Function static return type accessor.
+	 *
+	 * @return The static function return type; or null if return type is
+	 * not static.
+	 */
+	public Type getType() {
+		return type;
+	}
+
+	/**
+	 * {@inheritDoc}
+	 */
 	public Type getReturnType(Type columnType, Mapping mapping) {
-		return returnType == null ? columnType : returnType;
+		// return the concrete type, or the underlying type if a concrete type
+		// was not specified
+		return type == null ? columnType : type;
 	}
-	
+
+	/**
+	 * {@inheritDoc}
+	 */
 	public boolean hasArguments() {
 		return true;
 	}
-	
+
+	/**
+	 * {@inheritDoc}
+	 */
 	public boolean hasParenthesesIfNoArguments() {
 		return true;
 	}
-	
+
+	/**
+	 * {@inheritDoc}
+	 */
 	public String render(List args, SessionFactoryImplementor factory) {
 		StringBuffer buf = new StringBuffer();
-		buf.append(name)
-			.append('(');
-		for ( int i=0; i<args.size(); i++ ) {
-			buf.append( args.get(i) );
-			if ( i<args.size()-1 ) buf.append(", ");
+		buf.append( name ).append( '(' );
+		for ( int i = 0; i < args.size(); i++ ) {
+			buf.append( args.get( i ) );
+			if ( i < args.size() - 1 ) {
+				buf.append( ", " );
+			}
 		}
-		return buf.append(')').toString();
+		return buf.append( ')' ).toString();
 	}
-	
+
 	public String toString() {
 		return name;
 	}

Added: branches/Branch_3_2/Hibernate3/src/org/hibernate/exception/CacheSQLStateConverter.java
===================================================================
--- branches/Branch_3_2/Hibernate3/src/org/hibernate/exception/CacheSQLStateConverter.java	2006-11-08 16:54:55 UTC (rev 10774)
+++ branches/Branch_3_2/Hibernate3/src/org/hibernate/exception/CacheSQLStateConverter.java	2006-11-08 16:56:52 UTC (rev 10775)
@@ -0,0 +1,93 @@
+// $Id: $
+package org.hibernate.exception;
+
+import org.hibernate.JDBCException;
+
+import java.sql.SQLException;
+import java.util.HashSet;
+import java.util.Set;
+
+/**
+ * A SQLExceptionConverter implementation specific to Cach&eacute; SQL,
+ * accounting for its custom integrity constraint violation error codes.
+ *
+ * @author Jonathan Levinson
+ */
+public class CacheSQLStateConverter implements SQLExceptionConverter {
+
+	private ViolatedConstraintNameExtracter extracter;
+
+	private static final Set SQL_GRAMMAR_CATEGORIES = new HashSet();
+	private static final Set DATA_CATEGORIES = new HashSet();
+	private static final Set INTEGRITY_VIOLATION_CATEGORIES = new HashSet();
+	private static final Set CONNECTION_CATEGORIES = new HashSet();
+
+	static {
+		SQL_GRAMMAR_CATEGORIES.add( "07" );
+		SQL_GRAMMAR_CATEGORIES.add( "37" );
+		SQL_GRAMMAR_CATEGORIES.add( "42" );
+		SQL_GRAMMAR_CATEGORIES.add( "65" );
+		SQL_GRAMMAR_CATEGORIES.add( "S0" );
+		SQL_GRAMMAR_CATEGORIES.add( "20" );
+
+		DATA_CATEGORIES.add( "22" );
+		DATA_CATEGORIES.add( "21" );
+		DATA_CATEGORIES.add( "02" );
+
+		INTEGRITY_VIOLATION_CATEGORIES.add( new Integer( 119 ) );
+		INTEGRITY_VIOLATION_CATEGORIES.add( new Integer( 120 ) );
+		INTEGRITY_VIOLATION_CATEGORIES.add( new Integer( 121 ) );
+		INTEGRITY_VIOLATION_CATEGORIES.add( new Integer( 122 ) );
+		INTEGRITY_VIOLATION_CATEGORIES.add( new Integer( 123 ) );
+		INTEGRITY_VIOLATION_CATEGORIES.add( new Integer( 124 ) );
+		INTEGRITY_VIOLATION_CATEGORIES.add( new Integer( 125 ) );
+		INTEGRITY_VIOLATION_CATEGORIES.add( new Integer( 127 ) );
+
+		CONNECTION_CATEGORIES.add( "08" );
+	}
+
+	public CacheSQLStateConverter(ViolatedConstraintNameExtracter extracter) {
+		this.extracter = extracter;
+	}
+
+	/**
+	 * Convert the given SQLException into Hibernate's JDBCException hierarchy.
+	 *
+	 * @param sqlException The SQLException to be converted.
+	 * @param message	  An optional error message.
+	 * @param sql		  Optionally, the sql being performed when the exception occurred.
+	 * @return The resulting JDBCException.
+	 */
+	public JDBCException convert(SQLException sqlException, String message, String sql) {
+		String sqlStateClassCode = JDBCExceptionHelper.extractSqlStateClassCode( sqlException );
+		Integer errorCode = new Integer( JDBCExceptionHelper.extractErrorCode( sqlException ) );
+		if ( sqlStateClassCode != null ) {
+			if ( SQL_GRAMMAR_CATEGORIES.contains( sqlStateClassCode ) ) {
+				return new SQLGrammarException( message, sqlException, sql );
+			}
+			else if ( INTEGRITY_VIOLATION_CATEGORIES.contains( errorCode ) ) {
+				String constraintName = extracter.extractConstraintName( sqlException );
+				return new ConstraintViolationException( message, sqlException, sql, constraintName );
+			}
+			else if ( CONNECTION_CATEGORIES.contains( sqlStateClassCode ) ) {
+				return new JDBCConnectionException( message, sqlException, sql );
+			}
+			else if ( DATA_CATEGORIES.contains( sqlStateClassCode ) ) {
+				return new DataException( message, sqlException, sql );
+			}
+		}
+		return handledNonSpecificException( sqlException, message, sql );
+	}
+
+	/**
+	 * Handle an exception not converted to a specific type based on the SQLState.
+	 *
+	 * @param sqlException The exception to be handled.
+	 * @param message	  An optional message
+	 * @param sql		  Optionally, the sql being performed when the exception occurred.
+	 * @return The converted exception; should <b>never</b> be null.
+	 */
+	protected JDBCException handledNonSpecificException(SQLException sqlException, String message, String sql) {
+		return new GenericJDBCException( message, sqlException, sql );
+	}
+}

Added: branches/Branch_3_2/Hibernate3/src/org/hibernate/sql/CacheJoinFragment.java
===================================================================
--- branches/Branch_3_2/Hibernate3/src/org/hibernate/sql/CacheJoinFragment.java	2006-11-08 16:54:55 UTC (rev 10774)
+++ branches/Branch_3_2/Hibernate3/src/org/hibernate/sql/CacheJoinFragment.java	2006-11-08 16:56:52 UTC (rev 10775)
@@ -0,0 +1,22 @@
+//$Id: $
+package org.hibernate.sql;
+
+import org.hibernate.AssertionFailure;
+
+/**
+ * A Cach&eacute; dialect join.  Differs from ANSI only in that full outer join
+ * is not supported.
+ *
+ * @author Jeff Miller
+ * @author Jonathan Levinson
+ */
+public class CacheJoinFragment extends ANSIJoinFragment {
+
+	public void addJoin(String tableName, String alias, String[] fkColumns, String[] pkColumns, int joinType, String on) {
+		if ( joinType == FULL_JOIN ) {
+			throw new AssertionFailure( "Cache does not support full outer joins" );
+		}
+		super.addJoin( tableName, alias, fkColumns, pkColumns, joinType, on );
+	}
+
+}

Modified: branches/Branch_3_2/Hibernate3/test/org/hibernate/test/TestCase.java
===================================================================
--- branches/Branch_3_2/Hibernate3/test/org/hibernate/test/TestCase.java	2006-11-08 16:54:55 UTC (rev 10774)
+++ branches/Branch_3_2/Hibernate3/test/org/hibernate/test/TestCase.java	2006-11-08 16:56:52 UTC (rev 10775)
@@ -29,6 +29,7 @@
 import org.hibernate.dialect.SybaseDialect;
 import org.hibernate.dialect.TimesTenDialect;
 import org.hibernate.dialect.DerbyDialect;
+import org.hibernate.dialect.Cache71Dialect;
 import org.hibernate.engine.SessionFactoryImplementor;
 import org.hibernate.mapping.Collection;
 import org.hibernate.mapping.PersistentClass;
@@ -386,11 +387,14 @@
 
 	/**
 	 * Intended to indicate that this test class as a whole is intended for
-	 * a dialect or series of dialects.  Skips here (appliesTo = false), therefore
+	 * a dialect or series of dialects.  Skips here (appliesTo = false) therefore
 	 * simply indicate that the given tests target a particular feature of the
-	 * current database...
+	 * checked database and none of the tests on this class should be run for the
+	 * checked dialect.
 	 *
-	 * @param dialect
+	 * @param dialect The dialect to be checked.
+	 * @return True if all the tests on this class apply to the given dialect (and
+	 * therefore should be run); false otherwise.
 	 */
 	public boolean appliesTo(Dialect dialect) {
 		return true;
@@ -490,7 +494,8 @@
 						SQLServerDialect.class,
 						SybaseDialect.class,
 						PostgreSQLDialect.class,
-						TimesTenDialect.class
+						TimesTenDialect.class,
+						Cache71Dialect.class
 				}
 		);
 
@@ -508,7 +513,7 @@
 	protected boolean dialectIsCaseSensitive(String testDescription) {
 		//	MySQL and SQLServer is case insensitive on strings (at least in default installation)
 		boolean canDoIt = dialectIsNot(
-				new Class[] { MySQLDialect.class, SQLServerDialect.class }
+				new Class[] { MySQLDialect.class, SQLServerDialect.class, Cache71Dialect.class }
 		);
 
 		if ( !canDoIt ) {
@@ -518,12 +523,13 @@
 	}
 
 	protected boolean supportsRowValueConstructorSyntaxInInList() {
-		boolean supported = ! (
-				getDialect() instanceof HSQLDialect ||
+		// this is a bit more lenient than Dialect.supportsRowValueConstructorSyntax() check
+		boolean supported = ! (getDialect() instanceof HSQLDialect ||
 				getDialect() instanceof PostgreSQLDialect ||
 				getDialect() instanceof MySQLDialect ||
 				getDialect() instanceof DB2Dialect ||
-		        getDialect() instanceof SybaseDialect
+		        getDialect() instanceof SybaseDialect ||
+				getDialect() instanceof Cache71Dialect
 		);
 
 		if ( !supported ) {
@@ -533,7 +539,7 @@
 	}
 
 	protected boolean supportsResultSetPositionQueryMethodsOnForwardOnlyCursor() {
-		if ( getDialect() instanceof SQLServerDialect ) {
+		if ( getDialect() instanceof SQLServerDialect || getDialect() instanceof Cache71Dialect ) {
 			reportSkip( "Driver does not support 'position query' methods on forward-only cursors", "query support" );
 			return false;
 		}

Modified: branches/Branch_3_2/Hibernate3/test/org/hibernate/test/hql/FooBarCopy.hbm.xml
===================================================================
--- branches/Branch_3_2/Hibernate3/test/org/hibernate/test/hql/FooBarCopy.hbm.xml	2006-11-08 16:54:55 UTC (rev 10774)
+++ branches/Branch_3_2/Hibernate3/test/org/hibernate/test/hql/FooBarCopy.hbm.xml	2006-11-08 16:56:52 UTC (rev 10775)
@@ -23,7 +23,7 @@
 			</generator>
 		</id>
 
-		<discriminator column="`^foo_subclass$1234`" type="character" force="true"/>
+		<discriminator column="`foo_subclass_1234`" type="character" force="true"/>
 		<version name="version"/>
 
 		<many-to-one name="foo" class="Foo">
@@ -34,7 +34,7 @@
 			<column name="long_" index="fbmtoidx" unique-key="abc" not-null="true"/>
 		</property>
 		<property name="integer">
-				<column name="`@@##integer_*`" unique-key="abc" not-null="true"/>
+				<column name="`integer__`" unique-key="abc" not-null="true"/>
 		</property>
 		<property name="float">
 				<column name="float_" unique-key="abc" not-null="true" check="float_ > 0.0"/>
@@ -47,7 +47,7 @@
 			<index column="i"/>
 			<element column="byte_" type="byte"/>
 		</primitive-array>
-	
+
 		<property name="date" type="date" column="date_"/>
 		<property name="timestamp" type="timestamp" column="timestamp_"/>
 		<property name="boolean" column="boolean_"/>
@@ -65,7 +65,7 @@
 		<property name="blob" type="org.hibernate.test.legacy.Foo$Struct" column="blobb_"/>
 		<property name="nullBlob" type="serializable"/>
 		<property name="binary" column="bin_"/>
-		<property name="theLocale" access="field" column="`localeayzabc123!@#$`"/>
+		<property name="theLocale" access="field" column="`localeayzabc123`"/>
 		
 		<property name="formula" formula="int_/2"/>
 		

Modified: branches/Branch_3_2/Hibernate3/test/org/hibernate/test/legacy/Baz.hbm.xml
===================================================================
--- branches/Branch_3_2/Hibernate3/test/org/hibernate/test/legacy/Baz.hbm.xml	2006-11-08 16:54:55 UTC (rev 10774)
+++ branches/Branch_3_2/Hibernate3/test/org/hibernate/test/legacy/Baz.hbm.xml	2006-11-08 16:56:52 UTC (rev 10775)
@@ -60,11 +60,11 @@
 			<index column="j"/>
 			<element column="the_time" type="time"/>
 		</array>
-		<bag name="bag" order-by="`name!`" table="`^%$^bxaxg`">
+		<bag name="bag" order-by="`name_`" table="`bxaxg`">
 			<key>
-				<column name="`baz_id$`" length="16"/>
+				<column name="`baz_id_`" length="16"/>
 			</key>
-			<element column="`name!`" type="string"/>
+			<element column="`name_`" type="string"/>
 		</bag>
 		<map name="fooToGlarch" lazy="false">
 			<key>

Modified: branches/Branch_3_2/Hibernate3/test/org/hibernate/test/legacy/FooBar.hbm.xml
===================================================================
--- branches/Branch_3_2/Hibernate3/test/org/hibernate/test/legacy/FooBar.hbm.xml	2006-11-08 16:54:55 UTC (rev 10774)
+++ branches/Branch_3_2/Hibernate3/test/org/hibernate/test/legacy/FooBar.hbm.xml	2006-11-08 16:56:52 UTC (rev 10775)
@@ -25,7 +25,7 @@
 				<param name="seperator">:</param>
 			</generator>
 		</id>
-		<discriminator column="`^foo_subclass$1234`" type="character" force="true"/>
+		<discriminator column="`foo_subclass_1234`" type="character" force="true"/>
 		<version name="version"/>
 		<!--<version name="versionCalendar" type="calendar"/>-->
 		<!--<timestamp name="versionTimestamp"/>-->
@@ -36,7 +36,7 @@
 			<column name="long_" index="fbmtoidx" unique-key="abc" not-null="true"/>
 		</property>
 		<property name="integer">
-				<column name="`@@##integer_*`" unique-key="abc" not-null="true"/>
+				<column name="`integer__`" unique-key="abc" not-null="true"/>
 		</property>
 		<property name="float">
 				<column name="float_" unique-key="abc" not-null="true" check="float_ > 0.0"/>
@@ -49,7 +49,7 @@
 			<index column="i"/>
 			<element column="byte_" type="byte"/>
 		</primitive-array>
-	
+
 		<property name="date" type="date" column="date_"/>
 		<property name="timestamp" type="timestamp" column="timestamp_"/>
 		<property name="boolean" column="boolean_"/>
@@ -67,7 +67,7 @@
 		<property name="blob" type="org.hibernate.test.legacy.Foo$Struct" column="blobb_"/>
 		<property name="nullBlob" type="serializable"/>
 		<property name="binary" column="bin_"/>
-		<property name="theLocale" access="field" column="`localeayzabc123!@#$`"/>
+		<property name="theLocale" access="field" column="`localeayzabc123`"/>
 		
 		<property name="formula" formula="int_/2"/>
 		

Modified: branches/Branch_3_2/Hibernate3/test/org/hibernate/test/legacy/Glarch.hbm.xml
===================================================================
--- branches/Branch_3_2/Hibernate3/test/org/hibernate/test/legacy/Glarch.hbm.xml	2006-11-08 16:54:55 UTC (rev 10774)
+++ branches/Branch_3_2/Hibernate3/test/org/hibernate/test/legacy/Glarch.hbm.xml	2006-11-08 16:56:52 UTC (rev 10775)
@@ -25,7 +25,7 @@
         <property name="x"/>
         <list name="strings">
             <key column="glarch_key"/>
-            <index column="`!@#i`"/>
+            <index column="`indx_`"/>
             <element type="string" column="`tha_stryng`"/>
         </list>
         <list name="fooComponents" lazy="true" cascade="all">




More information about the hibernate-commits mailing list