|
From: <jul...@us...> - 2011-04-10 16:12:32
|
Revision: 5649
http://nhibernate.svn.sourceforge.net/nhibernate/?rev=5649&view=rev
Author: julian-maughan
Date: 2011-04-10 16:12:26 +0000 (Sun, 10 Apr 2011)
Log Message:
-----------
Added Sybase ASE 15 support (NH-2526). Predominantly a port from Hibernate, with some refinements.
Modified Paths:
--------------
trunk/nhibernate/src/NHibernate/NHibernate.csproj
Added Paths:
-----------
trunk/nhibernate/src/NHibernate/Dialect/SybaseASE15Dialect.cs
trunk/nhibernate/src/NHibernate/Driver/SybaseAseClientDriver.cs
trunk/nhibernate/src/NHibernate.Config.Templates/SybaseASE.cfg.xml
Added: trunk/nhibernate/src/NHibernate/Dialect/SybaseASE15Dialect.cs
===================================================================
--- trunk/nhibernate/src/NHibernate/Dialect/SybaseASE15Dialect.cs (rev 0)
+++ trunk/nhibernate/src/NHibernate/Dialect/SybaseASE15Dialect.cs 2011-04-10 16:12:26 UTC (rev 5649)
@@ -0,0 +1,331 @@
+using System;
+using System.Collections.Generic;
+using System.Data;
+using System.Data.Common;
+using System.Text;
+using Environment = NHibernate.Cfg.Environment;
+using NHibernate.Dialect.Function;
+using NHibernate.SqlCommand;
+
+namespace NHibernate.Dialect
+{
+ /// <summary>
+ /// An SQL dialect targeting Sybase Adaptive Server Enterprise (ASE) 15 and higher.
+ /// </summary>
+ /// <remarks>
+ /// The dialect defaults the following configuration properties:
+ /// <list type="table">
+ /// <listheader>
+ /// <term>Property</term>
+ /// <description>Default Value</description>
+ /// </listheader>
+ /// <item>
+ /// <term>connection.driver_class</term>
+ /// <description><see cref="NHibernate.Driver.SybaseAseClientDriver" /></description>
+ /// </item>
+ /// </list>
+ /// </remarks>
+ public class SybaseASE15Dialect : Dialect
+ {
+ public SybaseASE15Dialect()
+ {
+ DefaultProperties[Environment.ConnectionDriver] = "NHibernate.Driver.SybaseAseClientDriver";
+
+ RegisterColumnType(DbType.Boolean, "tinyint"); // Sybase BIT type does not support null values
+ RegisterColumnType(DbType.Int16, "smallint");
+ RegisterColumnType(DbType.Int16, 255, "tinyint");
+ RegisterColumnType(DbType.Int32, "int");
+ RegisterColumnType(DbType.Int64, "bigint");
+ RegisterColumnType(DbType.Decimal, "numeric(18,0)");
+ RegisterColumnType(DbType.Single, "real");
+ RegisterColumnType(DbType.Double, "float");
+ RegisterColumnType(DbType.AnsiStringFixedLength, "char(1)");
+ RegisterColumnType(DbType.AnsiStringFixedLength, 255, "char($l)");
+ RegisterColumnType(DbType.StringFixedLength, "nchar(1)");
+ RegisterColumnType(DbType.StringFixedLength, 255, "nchar($l)");
+ RegisterColumnType(DbType.AnsiString, "varchar(255)");
+ RegisterColumnType(DbType.AnsiString, 16384, "varchar($l)");
+ RegisterColumnType(DbType.String, "nvarchar(255)");
+ RegisterColumnType(DbType.String, 16384, "nvarchar($l)");
+ RegisterColumnType(DbType.String, int.MaxValue, "text");
+ RegisterColumnType(DbType.DateTime, "datetime");
+ RegisterColumnType(DbType.Time, "time");
+ RegisterColumnType(DbType.Date, "date");
+ RegisterColumnType(DbType.Binary, 8000, "varbinary($l)");
+ RegisterColumnType(DbType.Binary, "varbinary");
+
+ RegisterFunction("abs", new StandardSQLFunction("abs"));
+ RegisterFunction("acos", new StandardSQLFunction("acos", NHibernateUtil.Double));
+ RegisterFunction("ascii", new StandardSQLFunction("ascii", NHibernateUtil.Int32));
+ RegisterFunction("asin", new StandardSQLFunction("asin", NHibernateUtil.Double));
+ RegisterFunction("atan", new StandardSQLFunction("atan", NHibernateUtil.Double));
+ RegisterFunction("bit_length", new SQLFunctionTemplate(NHibernateUtil.Int32, "datalength(?1) * 8"));
+ RegisterFunction("ceiling", new StandardSQLFunction("ceiling"));
+ RegisterFunction("char", new StandardSQLFunction("char", NHibernateUtil.String));
+ RegisterFunction("concat", new VarArgsSQLFunction(NHibernateUtil.String, "(","+",")"));
+ RegisterFunction("cos", new StandardSQLFunction("cos", NHibernateUtil.Double));
+ RegisterFunction("cot", new StandardSQLFunction("cot", NHibernateUtil.Double));
+ RegisterFunction("current_date", new NoArgSQLFunction("getdate", NHibernateUtil.Date));
+ RegisterFunction("current_time", new NoArgSQLFunction("getdate", NHibernateUtil.Time));
+ RegisterFunction("current_timestamp", new NoArgSQLFunction("getdate", NHibernateUtil.Timestamp));
+ RegisterFunction("datename", new StandardSQLFunction("datename", NHibernateUtil.String));
+ RegisterFunction("day", new StandardSQLFunction("day", NHibernateUtil.Int32));
+ RegisterFunction("degrees", new StandardSQLFunction("degrees", NHibernateUtil.Double));
+ RegisterFunction("exp", new StandardSQLFunction("exp", NHibernateUtil.Double));
+ RegisterFunction("extract", new SQLFunctionTemplate(NHibernateUtil.Int32, "datepart(?1, ?3)"));
+ RegisterFunction("floor", new StandardSQLFunction("floor"));
+ RegisterFunction("getdate", new NoArgSQLFunction("getdate", NHibernateUtil.Timestamp));
+ RegisterFunction("getutcdate", new NoArgSQLFunction("getutcdate", NHibernateUtil.Timestamp));
+ RegisterFunction("hour", new SQLFunctionTemplate(NHibernateUtil.Int32, "datepart(hour, ?1)"));
+ RegisterFunction("isnull", new StandardSQLFunction("isnull"));
+ RegisterFunction("len", new StandardSQLFunction("len", NHibernateUtil.Int64));
+ RegisterFunction("length", new StandardSQLFunction("len", NHibernateUtil.Int32));
+ RegisterFunction("locate", new CharIndexFunction());
+ RegisterFunction("log", new StandardSQLFunction("log", NHibernateUtil.Double));
+ RegisterFunction("log10", new StandardSQLFunction("log10", NHibernateUtil.Double));
+ RegisterFunction("lower", new StandardSQLFunction("lower"));
+ RegisterFunction("ltrim", new StandardSQLFunction("ltrim"));
+ RegisterFunction("minute", new SQLFunctionTemplate(NHibernateUtil.Int32, "datepart(minute, ?1)"));
+ RegisterFunction("mod", new SQLFunctionTemplate(NHibernateUtil.Int32, "?1 % ?2"));
+ RegisterFunction("month", new StandardSQLFunction("month", NHibernateUtil.Int32));
+ RegisterFunction("pi", new NoArgSQLFunction("pi", NHibernateUtil.Double));
+ RegisterFunction("radians", new StandardSQLFunction("radians", NHibernateUtil.Double));
+ RegisterFunction("rand", new StandardSQLFunction("rand", NHibernateUtil.Double));
+ RegisterFunction("reverse", new StandardSQLFunction("reverse"));
+ RegisterFunction("round", new StandardSQLFunction("round"));
+ RegisterFunction("rtrim", new StandardSQLFunction("rtrim"));
+ RegisterFunction("second", new SQLFunctionTemplate(NHibernateUtil.Int32, "datepart(second, ?1)"));
+ RegisterFunction("sign", new StandardSQLFunction("sign", NHibernateUtil.Int32));
+ RegisterFunction("sin", new StandardSQLFunction("sin", NHibernateUtil.Double));
+ RegisterFunction("space", new StandardSQLFunction("space", NHibernateUtil.String));
+ RegisterFunction("sqrt", new StandardSQLFunction("sqrt", NHibernateUtil.Double));
+ RegisterFunction("square", new StandardSQLFunction("square"));
+ RegisterFunction("str", new StandardSQLFunction("str", NHibernateUtil.String));
+ RegisterFunction("tan", new StandardSQLFunction("tan", NHibernateUtil.Double));
+ // TODO RegisterFunction("trim", new SQLFunctionTemplate(NHibernateUtil.String, "ltrim(rtrim(?1))"));
+ RegisterFunction("upper", new StandardSQLFunction("upper"));
+ RegisterFunction("user", new NoArgSQLFunction("user", NHibernateUtil.String));
+ RegisterFunction("year", new StandardSQLFunction("year", NHibernateUtil.Int32));
+ }
+
+ public override string AddColumnString
+ {
+ get { return "add"; }
+ }
+
+ public override string NullColumnString
+ {
+ get { return " null"; }
+ }
+
+ public override bool QualifyIndexName
+ {
+ get { return false; }
+ }
+
+ public override bool SupportsIdentityColumns
+ {
+ get { return true; }
+ }
+
+ public override string IdentitySelectString
+ {
+ get { return "select @@identity"; }
+ }
+
+ public override string IdentityColumnString
+ {
+ get { return "identity not null"; } // starts with 1, implicitly
+ }
+
+ public override bool SupportsInsertSelectIdentity
+ {
+ get { return true; }
+ }
+
+ public override bool SupportsCurrentTimestampSelection
+ {
+ get { return true; }
+ }
+
+ public override bool IsCurrentTimestampSelectStringCallable
+ {
+ get { return false; }
+ }
+
+ public override string CurrentTimestampSelectString
+ {
+ get { return "select getdate()"; }
+ }
+
+ /// <summary>
+ /// Sybase ASE 15 temporary tables are not supported
+ /// </summary>
+ /// <remarks>
+ /// By default, temporary tables in Sybase ASE 15 can only be created outside a transaction.
+ /// This is not supported by NHibernate. Temporary tables (and other DDL) statements can only
+ /// be run in a transaction if the 'ddl in tran' database option on tempdb is set to 'true'.
+ /// However, Sybase does not recommend this setting due to the performance impact arising from
+ /// locking and contention on tempdb system tables.
+ /// </remarks>
+ public override bool SupportsTemporaryTables
+ {
+ get { return false; }
+ }
+
+ public override string SelectGUIDString
+ {
+ get { return "select newid()"; }
+ }
+
+ public override bool SupportsEmptyInList
+ {
+ get { return false; }
+ }
+
+ public override bool SupportsUnionAll
+ {
+ get { return true; }
+ }
+
+ public override bool SupportsExistsInSelect
+ {
+ get { return false; }
+ }
+
+ public override bool DoesReadCommittedCauseWritersToBlockReaders
+ {
+ get { return true; }
+ }
+
+ public override bool DoesRepeatableReadCauseReadersToBlockWriters
+ {
+ get { return true; }
+ }
+
+ public override bool SupportsCascadeDelete
+ {
+ get { return false; }
+ }
+
+ public override int MaxAliasLength
+ {
+ get { return 30; }
+ }
+
+ /// <summary>
+ /// This is false only by default. The database can be configured to be
+ /// case-insensitive.
+ /// </summary>
+ public override bool AreStringComparisonsCaseInsensitive
+ {
+ get { return false; }
+ }
+
+ public override string CurrentTimestampSQLFunctionName
+ {
+ get { return "getdate()"; }
+ }
+
+ public override bool SupportsExpectedLobUsagePattern
+ {
+ get { return false; }
+ }
+
+ public override char OpenQuote
+ {
+ get { return '['; }
+ }
+
+ public override char CloseQuote
+ {
+ get { return ']'; }
+ }
+
+ public override string ForUpdateString
+ {
+ get { return String.Empty; }
+ }
+
+ public override string GenerateTemporaryTableName(string baseTableName)
+ {
+ return "#" + baseTableName;
+ }
+
+ public override bool DropTemporaryTableAfterUse()
+ {
+ return true;
+ }
+
+ public override SqlString AppendIdentitySelectToInsert(SqlString insertString)
+ {
+ return insertString.Append("\nselect @@identity");
+ }
+
+ public override string AppendLockHint(LockMode lockMode, string tableName)
+ {
+ if (lockMode.GreaterThan(LockMode.Read))
+ return tableName + " holdlock";
+
+ return tableName;
+ }
+
+ public override SqlString ApplyLocksToSql(SqlString sql, IDictionary<string, LockMode> aliasedLockModes, IDictionary<string, string[]> keyColumnNames)
+ {
+ // TODO: merge additional lockoptions support in Dialect.applyLocksToSql
+
+ var buffer = new StringBuilder(sql.ToString());
+ int correction = 0;
+
+ foreach (KeyValuePair<string, LockMode> entry in aliasedLockModes)
+ {
+ LockMode mode = entry.Value;
+
+ if (mode.GreaterThan(LockMode.Read))
+ {
+ string alias = entry.Key;
+ int start = -1;
+ int end = -1;
+
+ if (sql.EndsWith(" " + alias))
+ {
+ start = (sql.Length - alias.Length) + correction;
+ end = start + alias.Length;
+ }
+ else
+ {
+ int position = sql.IndexOfCaseInsensitive(" " + alias + " ");
+
+ if (position <= -1)
+ position = sql.IndexOfCaseInsensitive(" " + alias + ",");
+
+ if (position > -1)
+ {
+ start = position + correction + 1;
+ end = start + alias.Length;
+ }
+ }
+
+ if (start > -1)
+ {
+ string lockHint = AppendLockHint(mode, alias);
+ buffer.Remove(start, end - start + 1);
+ buffer.Insert(start, lockHint);
+ correction += (lockHint.Length - alias.Length);
+ }
+ }
+ }
+ return new SqlString(buffer.ToString());
+ }
+
+ public override int RegisterResultSetOutParameter(DbCommand statement, int position)
+ {
+ return position;
+ }
+
+ public override DbDataReader GetResultSet(DbCommand statement)
+ {
+ return statement.ExecuteReader();
+ }
+ }
+}
\ No newline at end of file
Added: trunk/nhibernate/src/NHibernate/Driver/SybaseAseClientDriver.cs
===================================================================
--- trunk/nhibernate/src/NHibernate/Driver/SybaseAseClientDriver.cs (rev 0)
+++ trunk/nhibernate/src/NHibernate/Driver/SybaseAseClientDriver.cs 2011-04-10 16:12:26 UTC (rev 5649)
@@ -0,0 +1,36 @@
+using System;
+
+namespace NHibernate.Driver
+{
+ /// <summary>
+ /// This provides a driver for Sybase ASE 15 using the ADO.NET driver.
+ /// </summary>
+ /// <remarks>
+ /// You will need the following libraries available to your application:
+ /// <ul>
+ /// <li>Sybase.AdoNet2.AseClient.dll</li>
+ /// <li>sybdrvado20.dll</li>
+ /// </ul>
+ /// </remarks>
+ public class SybaseAseClientDriver : ReflectionBasedDriver
+ {
+ public SybaseAseClientDriver() : base("Sybase.AdoNet2.AseClient", "Sybase.Data.AseClient.AseConnection", "Sybase.Data.AseClient.AseCommand")
+ {
+ }
+
+ public override string NamedPrefix
+ {
+ get { return "@"; }
+ }
+
+ public override bool UseNamedPrefixInParameter
+ {
+ get { return true; }
+ }
+
+ public override bool UseNamedPrefixInSql
+ {
+ get { return true; }
+ }
+ }
+}
Modified: trunk/nhibernate/src/NHibernate/NHibernate.csproj
===================================================================
--- trunk/nhibernate/src/NHibernate/NHibernate.csproj 2011-04-09 16:01:06 UTC (rev 5648)
+++ trunk/nhibernate/src/NHibernate/NHibernate.csproj 2011-04-10 16:12:26 UTC (rev 5649)
@@ -140,6 +140,7 @@
<Compile Include="Dialect\PostgreSQLDialect.cs" />
<Compile Include="Dialect\Schema\PostgreSQLMetadata.cs" />
<Compile Include="Dialect\SQLiteDialect.cs" />
+ <Compile Include="Dialect\SybaseASE15Dialect.cs" />
<Compile Include="Dialect\SybaseSQLAnywhere10Dialect.cs" />
<Compile Include="Dialect\SybaseSQLAnywhere11Dialect.cs" />
<Compile Include="Dialect\TypeNames.cs" />
@@ -159,6 +160,7 @@
<Compile Include="Driver\SqlClientDriver.cs" />
<Compile Include="Driver\BasicResultSetsCommand.cs" />
<Compile Include="Driver\SQLiteDriver.cs" />
+ <Compile Include="Driver\SybaseAseClientDriver.cs" />
<Compile Include="Engine\Cascade.cs" />
<Compile Include="Engine\IBatcher.cs" />
<Compile Include="Engine\IMapping.cs" />
Added: trunk/nhibernate/src/NHibernate.Config.Templates/SybaseASE.cfg.xml
===================================================================
--- trunk/nhibernate/src/NHibernate.Config.Templates/SybaseASE.cfg.xml (rev 0)
+++ trunk/nhibernate/src/NHibernate.Config.Templates/SybaseASE.cfg.xml 2011-04-10 16:12:26 UTC (rev 5649)
@@ -0,0 +1,16 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+This template was written to work with NHibernate.Test.
+Copy the template to your NHibernate.Test project folder and rename it hibernate.cfg.xml. Change it
+for your own use before compiling tests in Visual Studio.
+-->
+<hibernate-configuration xmlns="urn:nhibernate-configuration-2.2">
+ <session-factory name="NHibernate.Test">
+ <property name="connection.driver_class">NHibernate.Driver.SybaseAseClientDriver</property>
+ <property name="connection.connection_string">
+ Data Source=10.0.0.1;Port=5000;Database=nhibernate;User ID=nhibernate;Password=password
+ </property>
+ <property name="dialect">NHibernate.Dialect.SybaseASE15Dialect</property>
+ <property name="query.substitutions">true=1;false=0</property>
+ </session-factory>
+</hibernate-configuration>
\ No newline at end of file
This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site.
|