using System; using System.Data; using System.Linq; using Umbraco.Core.Persistence.Querying; namespace Umbraco.Core.Persistence.SqlSyntax { /// /// Abstract class for defining MS sql implementations /// /// public abstract class MicrosoftSqlSyntaxProviderBase : SqlSyntaxProviderBase where TSyntax : ISqlSyntaxProvider { protected MicrosoftSqlSyntaxProviderBase() { AutoIncrementDefinition = "IDENTITY(1,1)"; GuidColumnDefinition = "UniqueIdentifier"; RealColumnDefinition = "FLOAT"; BoolColumnDefinition = "BIT"; DecimalColumnDefinition = "DECIMAL(38,6)"; TimeColumnDefinition = "TIME"; //SQLSERVER 2008+ BlobColumnDefinition = "VARBINARY(MAX)"; InitColumnTypeMap(); } public override string RenameTable => "sp_rename '{0}', '{1}'"; public override string AddColumn => "ALTER TABLE {0} ADD {1}"; public override string GetQuotedTableName(string tableName) { if (tableName.Contains(".") == false) return $"[{tableName}]"; var tableNameParts = tableName.Split(new[] { '.' }, 2); return $"[{tableNameParts[0]}].[{tableNameParts[1]}]"; } public override string GetQuotedColumnName(string columnName) => $"[{columnName}]"; public override string GetQuotedName(string name) => $"[{name}]"; public override string GetStringColumnEqualComparison(string column, int paramIndex, TextColumnType columnType) { switch (columnType) { case TextColumnType.NVarchar: return base.GetStringColumnEqualComparison(column, paramIndex, columnType); case TextColumnType.NText: //MSSQL doesn't allow for = comparison with NText columns but allows this syntax return $"{column} LIKE @{paramIndex}"; default: throw new ArgumentOutOfRangeException(nameof(columnType)); } } public override string GetStringColumnWildcardComparison(string column, int paramIndex, TextColumnType columnType) { switch (columnType) { case TextColumnType.NVarchar: return base.GetStringColumnWildcardComparison(column, paramIndex, columnType); case TextColumnType.NText: //MSSQL doesn't allow for upper methods with NText columns return $"{column} LIKE @{paramIndex}"; default: throw new ArgumentOutOfRangeException(nameof(columnType)); } } [Obsolete("Use the overload with the parameter index instead")] public override string GetStringColumnStartsWithComparison(string column, string value, TextColumnType columnType) { switch (columnType) { case TextColumnType.NVarchar: return base.GetStringColumnStartsWithComparison(column, value, columnType); case TextColumnType.NText: //MSSQL doesn't allow for upper methods with NText columns return $"{column} LIKE '{value}%'"; default: throw new ArgumentOutOfRangeException(nameof(columnType)); } } [Obsolete("Use the overload with the parameter index instead")] public override string GetStringColumnEndsWithComparison(string column, string value, TextColumnType columnType) { switch (columnType) { case TextColumnType.NVarchar: return base.GetStringColumnEndsWithComparison(column, value, columnType); case TextColumnType.NText: //MSSQL doesn't allow for upper methods with NText columns return $"{column} LIKE '%{value}'"; default: throw new ArgumentOutOfRangeException(nameof(columnType)); } } [Obsolete("Use the overload with the parameter index instead")] public override string GetStringColumnContainsComparison(string column, string value, TextColumnType columnType) { switch (columnType) { case TextColumnType.NVarchar: return base.GetStringColumnContainsComparison(column, value, columnType); case TextColumnType.NText: //MSSQL doesn't allow for upper methods with NText columns return $"{column} LIKE '%{value}%'"; default: throw new ArgumentOutOfRangeException(nameof(columnType)); } } [Obsolete("Use the overload with the parameter index instead")] public override string GetStringColumnWildcardComparison(string column, string value, TextColumnType columnType) { switch (columnType) { case TextColumnType.NVarchar: return base.GetStringColumnContainsComparison(column, value, columnType); case TextColumnType.NText: //MSSQL doesn't allow for upper methods with NText columns return $"{column} LIKE '{value}'"; default: throw new ArgumentOutOfRangeException(nameof(columnType)); } } /// /// This uses a the DbTypeMap created and custom mapping to resolve the SqlDbType /// /// /// public virtual SqlDbType GetSqlDbType(Type clrType) { var dbType = DbTypeMap.ColumnDbTypeMap.First(x => x.Key == clrType).Value; return GetSqlDbType(dbType); } /// /// Returns the mapped SqlDbType for the DbType specified /// /// /// public virtual SqlDbType GetSqlDbType(DbType dbType) { SqlDbType sqlDbType; //SEE: https://msdn.microsoft.com/en-us/library/cc716729(v=vs.110).aspx // and https://msdn.microsoft.com/en-us/library/yy6y35y8%28v=vs.110%29.aspx?f=255&MSPPError=-2147217396 switch (dbType) { case DbType.AnsiString: sqlDbType = SqlDbType.VarChar; break; case DbType.Binary: sqlDbType = SqlDbType.VarBinary; break; case DbType.Byte: sqlDbType = SqlDbType.TinyInt; break; case DbType.Boolean: sqlDbType = SqlDbType.Bit; break; case DbType.Currency: sqlDbType = SqlDbType.Money; break; case DbType.Date: sqlDbType = SqlDbType.Date; break; case DbType.DateTime: sqlDbType = SqlDbType.DateTime; break; case DbType.Decimal: sqlDbType = SqlDbType.Decimal; break; case DbType.Double: sqlDbType = SqlDbType.Float; break; case DbType.Guid: sqlDbType = SqlDbType.UniqueIdentifier; break; case DbType.Int16: sqlDbType = SqlDbType.SmallInt; break; case DbType.Int32: sqlDbType = SqlDbType.Int; break; case DbType.Int64: sqlDbType = SqlDbType.BigInt; break; case DbType.Object: sqlDbType = SqlDbType.Variant; break; case DbType.SByte: throw new NotSupportedException("Inferring a SqlDbType from SByte is not supported."); case DbType.Single: sqlDbType = SqlDbType.Real; break; case DbType.String: sqlDbType = SqlDbType.NVarChar; break; case DbType.Time: sqlDbType = SqlDbType.Time; break; case DbType.UInt16: throw new NotSupportedException("Inferring a SqlDbType from UInt16 is not supported."); case DbType.UInt32: throw new NotSupportedException("Inferring a SqlDbType from UInt32 is not supported."); case DbType.UInt64: throw new NotSupportedException("Inferring a SqlDbType from UInt64 is not supported."); case DbType.VarNumeric: throw new NotSupportedException("Inferring a VarNumeric from UInt64 is not supported."); case DbType.AnsiStringFixedLength: sqlDbType = SqlDbType.Char; break; case DbType.StringFixedLength: sqlDbType = SqlDbType.NChar; break; case DbType.Xml: sqlDbType = SqlDbType.Xml; break; case DbType.DateTime2: sqlDbType = SqlDbType.DateTime2; break; case DbType.DateTimeOffset: sqlDbType = SqlDbType.DateTimeOffset; break; default: throw new ArgumentOutOfRangeException(); } return sqlDbType; } } }