using System; using System.Data; using System.Collections.Generic; using Migrator.Framework; namespace Migrator.Providers { /// <summary> /// Defines the implementations specific details for a particular database. /// </summary> public abstract class Dialect { private readonly Dictionary<ColumnProperty, string> propertyMap = new Dictionary<ColumnProperty, string>(); private readonly TypeNames typeNames = new TypeNames(); protected Dialect() { RegisterProperty(ColumnProperty.Null, "NULL"); RegisterProperty(ColumnProperty.NotNull, "NOT NULL"); RegisterProperty(ColumnProperty.Unique, "UNIQUE"); RegisterProperty(ColumnProperty.PrimaryKey, "PRIMARY KEY"); } public abstract Type TransformationProvider { get; } public ITransformationProvider NewProviderForDialect(string connectionString) { return (ITransformationProvider)Activator.CreateInstance(TransformationProvider, this, connectionString); } /// <summary> /// Subclasses register a typename for the given type code and maximum /// column length. <c>$l</c> in the type name will be replaced by the column /// length (if appropriate) /// </summary> /// <param name="code">The typecode</param> /// <param name="capacity">Maximum length of database type</param> /// <param name="name">The database type name</param> protected void RegisterColumnType(DbType code, int capacity, string name) { typeNames.Put(code, capacity, name); } /// <summary> /// Suclasses register a typename for the given type code. <c>$l</c> in the /// typename will be replaced by the column length (if appropriate). /// </summary> /// <param name="code">The typecode</param> /// <param name="name">The database type name</param> protected void RegisterColumnType(DbType code, string name) { typeNames.Put(code, name); } public ColumnPropertiesMapper GetColumnMapper(Column column) { string type = column.Size > 0 ? GetTypeName(column.Type, column.Size) : GetTypeName(column.Type); if (!IdentityNeedsType && column.IsIdentity) type = String.Empty; return new ColumnPropertiesMapper(this, type); } /// <summary> /// Get the name of the database type associated with the given /// </summary> /// <param name="type">The DbType</param> /// <returns>The database type name used by ddl.</returns> public virtual string GetTypeName(DbType type) { string result = typeNames.Get(type); if (result == null) { throw new Exception(string.Format("No default type mapping for DbType {0}", type)); } return result; } /// <summary> /// Get the name of the database type associated with the given /// </summary> /// <param name="type">The DbType</param> /// <returns>The database type name used by ddl.</returns> /// <param name="length"></param> public virtual string GetTypeName(DbType type, int length) { return GetTypeName(type, length, 0, 0); } /// <summary> /// Get the name of the database type associated with the given /// </summary> /// <param name="type">The DbType</param> /// <returns>The database type name used by ddl.</returns> /// <param name="length"></param> /// <param name="precision"></param> /// <param name="scale"></param> public virtual string GetTypeName(DbType type, int length, int precision, int scale) { string resultWithLength = typeNames.Get(type, length, precision, scale); if (resultWithLength != null) return resultWithLength; return GetTypeName(type); } public void RegisterProperty(ColumnProperty property, string sql) { if (!propertyMap.ContainsKey(property)) { propertyMap.Add(property, sql); } propertyMap[property] = sql; } public string SqlForProperty(ColumnProperty property) { if (propertyMap.ContainsKey(property)) { return propertyMap[property]; } return String.Empty; } public virtual bool ColumnNameNeedsQuote { get { return false; } } public virtual bool TableNameNeedsQuote { get { return false; } } public virtual bool ConstraintNameNeedsQuote { get { return false; } } public virtual bool IdentityNeedsType { get { return true; } } public virtual bool NeedsNotNullForIdentity { get { return true; } } public virtual bool SupportsIndex { get { return true; } } public virtual string Quote(string value) { return String.Format(QuoteTemplate, value); } public virtual string QuoteTemplate { get { return "\"{0}\""; } } public virtual string Default(object defaultValue) { if (defaultValue is String && defaultValue.ToString() == String.Empty) { defaultValue = "''"; } return String.Format("DEFAULT {0}", defaultValue); } public ColumnPropertiesMapper GetAndMapColumnProperties(Column column) { ColumnPropertiesMapper mapper = GetColumnMapper(column); mapper.MapColumnProperties(column); if (column.DefaultValue != null) { if (column.DefaultValue is String && column.DefaultValue.ToString() == string.Empty) { column.DefaultValue = @"''"; } mapper.Default = column.DefaultValue; } return mapper; } } }