Fixes ugly classes not structured correctly and removes dead code, simplifies how db types are initialized and removes hacks. Fixes datetimeoffset definition.

This commit is contained in:
Shannon
2021-07-27 10:41:46 -06:00
parent 499a0608ec
commit 29ebb42a01
5 changed files with 87 additions and 74 deletions

View File

@@ -1,4 +1,4 @@
using System;
using System;
using System.Collections.Generic;
using System.Data;
@@ -6,24 +6,13 @@ namespace Umbraco.Cms.Infrastructure.Persistence.SqlSyntax
{
public class DbTypes
{
public DbType DbType;
public string TextDefinition;
public bool ShouldQuoteValue;
public Dictionary<Type, string> ColumnTypeMap = new Dictionary<Type, string>();
public Dictionary<Type, DbType> ColumnDbTypeMap = new Dictionary<Type, DbType>();
public void Set<T>(DbType dbType, string fieldDefinition)
public DbTypes(IReadOnlyDictionary<Type, string> columnTypeMap, IReadOnlyDictionary<Type, DbType> columnDbTypeMap)
{
DbType = dbType;
TextDefinition = fieldDefinition;
ShouldQuoteValue = fieldDefinition != "INTEGER"
&& fieldDefinition != "BIGINT"
&& fieldDefinition != "DOUBLE"
&& fieldDefinition != "DECIMAL"
&& fieldDefinition != "BOOL";
ColumnTypeMap[typeof(T)] = fieldDefinition;
ColumnDbTypeMap[typeof(T)] = dbType;
ColumnTypeMap = columnTypeMap;
ColumnDbTypeMap = columnDbTypeMap;
}
public IReadOnlyDictionary<Type, string> ColumnTypeMap { get; }
public IReadOnlyDictionary<Type, DbType> ColumnDbTypeMap { get; }
}
}

View File

@@ -0,0 +1,20 @@
using System;
using System.Collections.Generic;
using System.Data;
namespace Umbraco.Cms.Infrastructure.Persistence.SqlSyntax
{
internal class DbTypesFactory
{
private readonly Dictionary<Type, string> _columnTypeMap = new Dictionary<Type, string>();
private readonly Dictionary<Type, DbType> _columnDbTypeMap = new Dictionary<Type, DbType>();
public void Set<T>(DbType dbType, string fieldDefinition)
{
_columnTypeMap[typeof(T)] = fieldDefinition;
_columnDbTypeMap[typeof(T)] = dbType;
}
public DbTypes Create() => new DbTypes(_columnTypeMap, _columnDbTypeMap);
}
}

View File

@@ -22,8 +22,6 @@ namespace Umbraco.Cms.Infrastructure.Persistence.SqlSyntax
DecimalColumnDefinition = "DECIMAL(38,6)";
TimeColumnDefinition = "TIME"; //SQLSERVER 2008+
BlobColumnDefinition = "VARBINARY(MAX)";
InitColumnTypeMap();
}
public override string RenameTable => "sp_rename '{0}', '{1}'";
@@ -78,7 +76,7 @@ namespace Umbraco.Cms.Infrastructure.Persistence.SqlSyntax
/// <returns></returns>
public virtual SqlDbType GetSqlDbType(Type clrType)
{
var dbType = DbTypeMap.ColumnDbTypeMap.First(x => x.Key == clrType).Value;
var dbType = DbTypeMap.ColumnDbTypeMap[clrType];
return GetSqlDbType(dbType);
}

View File

@@ -24,6 +24,8 @@ namespace Umbraco.Cms.Infrastructure.Persistence.SqlSyntax
public abstract class SqlSyntaxProviderBase<TSyntax> : ISqlSyntaxProvider
where TSyntax : ISqlSyntaxProvider
{
private readonly Lazy<DbTypes> _dbTypes;
protected SqlSyntaxProviderBase()
{
ClauseOrder = new List<Func<ColumnDefinition, string>>
@@ -42,14 +44,14 @@ namespace Umbraco.Cms.Infrastructure.Persistence.SqlSyntax
StringColumnDefinition = string.Format(StringLengthColumnDefinitionFormat, DefaultStringLength);
DecimalColumnDefinition = string.Format(DecimalColumnDefinitionFormat, DefaultDecimalPrecision, DefaultDecimalScale);
InitColumnTypeMap();
// ReSharper disable VirtualMemberCallInConstructor
// ok to call virtual GetQuotedXxxName here - they don't depend on any state
var col = Regex.Escape(GetQuotedColumnName("column")).Replace("column", @"\w+");
var fld = Regex.Escape(GetQuotedTableName("table") + ".").Replace("table", @"\w+") + col;
// ReSharper restore VirtualMemberCallInConstructor
AliasRegex = new Regex("(" + fld + @")\s+AS\s+(" + col + ")", RegexOptions.Multiline | RegexOptions.Singleline | RegexOptions.IgnoreCase | RegexOptions.Compiled);
_dbTypes = new Lazy<DbTypes>(InitColumnTypeMap);
}
public Regex AliasRegex { get; }
@@ -70,64 +72,68 @@ namespace Umbraco.Cms.Infrastructure.Persistence.SqlSyntax
public string StringLengthColumnDefinitionFormat { get; }
public string AutoIncrementDefinition { get; protected set; } = "AUTOINCREMENT";
public string IntColumnDefinition { get; } = "INTEGER";
public string LongColumnDefinition { get; } = "BIGINT";
public string IntColumnDefinition { get; protected set; } = "INTEGER";
public string LongColumnDefinition { get; protected set; } = "BIGINT";
public string GuidColumnDefinition { get; protected set; } = "GUID";
public string BoolColumnDefinition { get; protected set; } = "BOOL";
public string RealColumnDefinition { get; protected set; } = "DOUBLE";
public string DecimalColumnDefinition { get; protected set; }
public string BlobColumnDefinition { get; protected set; } = "BLOB";
public string DateTimeColumnDefinition { get; } = "DATETIME";
public string DateTimeColumnDefinition { get; protected set; } = "DATETIME";
public string DateTimeOffsetColumnDefinition { get; protected set; } = "DATETIMEOFFSET(7)";
public string TimeColumnDefinition { get; protected set; } = "DATETIME";
protected IList<Func<ColumnDefinition, string>> ClauseOrder { get; }
protected DbTypes DbTypeMap { get; } = new DbTypes();
protected DbTypes DbTypeMap => _dbTypes.Value;
protected void InitColumnTypeMap()
private DbTypes InitColumnTypeMap()
{
DbTypeMap.Set<string>(DbType.String, StringColumnDefinition);
DbTypeMap.Set<char>(DbType.StringFixedLength, StringColumnDefinition);
DbTypeMap.Set<char?>(DbType.StringFixedLength, StringColumnDefinition);
DbTypeMap.Set<char[]>(DbType.String, StringColumnDefinition);
DbTypeMap.Set<bool>(DbType.Boolean, BoolColumnDefinition);
DbTypeMap.Set<bool?>(DbType.Boolean, BoolColumnDefinition);
DbTypeMap.Set<Guid>(DbType.Guid, GuidColumnDefinition);
DbTypeMap.Set<Guid?>(DbType.Guid, GuidColumnDefinition);
DbTypeMap.Set<DateTime>(DbType.DateTime, DateTimeColumnDefinition);
DbTypeMap.Set<DateTime?>(DbType.DateTime, DateTimeColumnDefinition);
DbTypeMap.Set<TimeSpan>(DbType.Time, TimeColumnDefinition);
DbTypeMap.Set<TimeSpan?>(DbType.Time, TimeColumnDefinition);
DbTypeMap.Set<DateTimeOffset>(DbType.DateTimeOffset, TimeColumnDefinition);
DbTypeMap.Set<DateTimeOffset?>(DbType.DateTimeOffset, TimeColumnDefinition);
var dbTypeMap = new DbTypesFactory();
dbTypeMap.Set<string>(DbType.String, StringColumnDefinition);
dbTypeMap.Set<char>(DbType.StringFixedLength, StringColumnDefinition);
dbTypeMap.Set<char?>(DbType.StringFixedLength, StringColumnDefinition);
dbTypeMap.Set<char[]>(DbType.String, StringColumnDefinition);
dbTypeMap.Set<bool>(DbType.Boolean, BoolColumnDefinition);
dbTypeMap.Set<bool?>(DbType.Boolean, BoolColumnDefinition);
dbTypeMap.Set<Guid>(DbType.Guid, GuidColumnDefinition);
dbTypeMap.Set<Guid?>(DbType.Guid, GuidColumnDefinition);
dbTypeMap.Set<DateTime>(DbType.DateTime, DateTimeColumnDefinition);
dbTypeMap.Set<DateTime?>(DbType.DateTime, DateTimeColumnDefinition);
dbTypeMap.Set<TimeSpan>(DbType.Time, TimeColumnDefinition);
dbTypeMap.Set<TimeSpan?>(DbType.Time, TimeColumnDefinition);
dbTypeMap.Set<DateTimeOffset>(DbType.DateTimeOffset, DateTimeOffsetColumnDefinition);
dbTypeMap.Set<DateTimeOffset?>(DbType.DateTimeOffset, DateTimeOffsetColumnDefinition);
DbTypeMap.Set<byte>(DbType.Byte, IntColumnDefinition);
DbTypeMap.Set<byte?>(DbType.Byte, IntColumnDefinition);
DbTypeMap.Set<sbyte>(DbType.SByte, IntColumnDefinition);
DbTypeMap.Set<sbyte?>(DbType.SByte, IntColumnDefinition);
DbTypeMap.Set<short>(DbType.Int16, IntColumnDefinition);
DbTypeMap.Set<short?>(DbType.Int16, IntColumnDefinition);
DbTypeMap.Set<ushort>(DbType.UInt16, IntColumnDefinition);
DbTypeMap.Set<ushort?>(DbType.UInt16, IntColumnDefinition);
DbTypeMap.Set<int>(DbType.Int32, IntColumnDefinition);
DbTypeMap.Set<int?>(DbType.Int32, IntColumnDefinition);
DbTypeMap.Set<uint>(DbType.UInt32, IntColumnDefinition);
DbTypeMap.Set<uint?>(DbType.UInt32, IntColumnDefinition);
dbTypeMap.Set<byte>(DbType.Byte, IntColumnDefinition);
dbTypeMap.Set<byte?>(DbType.Byte, IntColumnDefinition);
dbTypeMap.Set<sbyte>(DbType.SByte, IntColumnDefinition);
dbTypeMap.Set<sbyte?>(DbType.SByte, IntColumnDefinition);
dbTypeMap.Set<short>(DbType.Int16, IntColumnDefinition);
dbTypeMap.Set<short?>(DbType.Int16, IntColumnDefinition);
dbTypeMap.Set<ushort>(DbType.UInt16, IntColumnDefinition);
dbTypeMap.Set<ushort?>(DbType.UInt16, IntColumnDefinition);
dbTypeMap.Set<int>(DbType.Int32, IntColumnDefinition);
dbTypeMap.Set<int?>(DbType.Int32, IntColumnDefinition);
dbTypeMap.Set<uint>(DbType.UInt32, IntColumnDefinition);
dbTypeMap.Set<uint?>(DbType.UInt32, IntColumnDefinition);
DbTypeMap.Set<long>(DbType.Int64, LongColumnDefinition);
DbTypeMap.Set<long?>(DbType.Int64, LongColumnDefinition);
DbTypeMap.Set<ulong>(DbType.UInt64, LongColumnDefinition);
DbTypeMap.Set<ulong?>(DbType.UInt64, LongColumnDefinition);
dbTypeMap.Set<long>(DbType.Int64, LongColumnDefinition);
dbTypeMap.Set<long?>(DbType.Int64, LongColumnDefinition);
dbTypeMap.Set<ulong>(DbType.UInt64, LongColumnDefinition);
dbTypeMap.Set<ulong?>(DbType.UInt64, LongColumnDefinition);
DbTypeMap.Set<float>(DbType.Single, RealColumnDefinition);
DbTypeMap.Set<float?>(DbType.Single, RealColumnDefinition);
DbTypeMap.Set<double>(DbType.Double, RealColumnDefinition);
DbTypeMap.Set<double?>(DbType.Double, RealColumnDefinition);
dbTypeMap.Set<float>(DbType.Single, RealColumnDefinition);
dbTypeMap.Set<float?>(DbType.Single, RealColumnDefinition);
dbTypeMap.Set<double>(DbType.Double, RealColumnDefinition);
dbTypeMap.Set<double?>(DbType.Double, RealColumnDefinition);
DbTypeMap.Set<decimal>(DbType.Decimal, DecimalColumnDefinition);
DbTypeMap.Set<decimal?>(DbType.Decimal, DecimalColumnDefinition);
dbTypeMap.Set<decimal>(DbType.Decimal, DecimalColumnDefinition);
dbTypeMap.Set<decimal?>(DbType.Decimal, DecimalColumnDefinition);
DbTypeMap.Set<byte[]>(DbType.Binary, BlobColumnDefinition);
dbTypeMap.Set<byte[]>(DbType.Binary, BlobColumnDefinition);
return dbTypeMap.Create();
}
public abstract string ProviderName { get; }
@@ -484,19 +490,19 @@ namespace Umbraco.Cms.Infrastructure.Persistence.SqlSyntax
if (type == typeof(string))
{
var valueOrDefault = column.Size != default(int) ? column.Size : DefaultStringLength;
var valueOrDefault = column.Size != default ? column.Size : DefaultStringLength;
return string.Format(StringLengthColumnDefinitionFormat, valueOrDefault);
}
if (type == typeof(decimal))
{
var precision = column.Size != default(int) ? column.Size : DefaultDecimalPrecision;
var scale = column.Precision != default(int) ? column.Precision : DefaultDecimalScale;
var precision = column.Size != default ? column.Size : DefaultDecimalPrecision;
var scale = column.Precision != default ? column.Precision : DefaultDecimalScale;
return string.Format(DecimalColumnDefinitionFormat, precision, scale);
}
var definition = DbTypeMap.ColumnTypeMap.First(x => x.Key == type).Value;
var dbTypeDefinition = column.Size != default(int)
var definition = DbTypeMap.ColumnTypeMap[type];
var dbTypeDefinition = column.Size != default
? $"{definition}({column.Size})"
: definition;
//NOTE Precision is left out

View File

@@ -25,10 +25,10 @@ namespace Umbraco.Cms.Persistence.SqlCe
{
_globalSettings = globalSettings;
BlobColumnDefinition = "IMAGE";
// This is silly to have to do this but the way these inherited classes are structured it's the easiest
// way without an overhaul in type map initialization
DbTypeMap.Set<byte[]>(DbType.Binary, BlobColumnDefinition);
// NOTE: if this column type is used in sqlce, it will prob result in errors since
// SQLCE cannot support this type correctly without 2x columns and a lot of work arounds.
// We don't use this natively within Umbraco but 3rd parties might with SQL server.
DateTimeOffsetColumnDefinition = "DATETIME";
}
public override string ProviderName => Constants.DatabaseProviders.SqlCe;