28810 d4fd81679d - 修复 因兼容 #184 导致 MySql Enum 表达式解析为 int 的 bug;
- 修复 FreeSql.Provider.MySqlConnector Enum 自定义元素值,导致值计算错误的 bug;
2020-03-31 21:43:07 +08:00

160 lines
7.1 KiB
C#
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

using FreeSql.Internal;
using FreeSql.Internal.Model;
using MySql.Data.MySqlClient;
using System;
using System.Collections.Generic;
using System.Collections.Concurrent;
using System.Data.Common;
namespace FreeSql.MySql
{
class MySqlUtils : CommonUtils
{
public MySqlUtils(IFreeSql orm) : base(orm)
{
}
public override DbParameter AppendParamter(List<DbParameter> _params, string parameterName, ColumnInfo col, Type type, object value)
{
if (string.IsNullOrEmpty(parameterName)) parameterName = $"p_{_params?.Count}";
var ret = new MySqlParameter { ParameterName = QuoteParamterName(parameterName), Value = value };
var dbtype = (MySqlDbType)_orm.CodeFirst.GetDbInfo(type)?.type;
if (col != null)
{
var dbtype2 = (MySqlDbType)_orm.DbFirst.GetDbType(new DatabaseModel.DbColumnInfo { DbTypeText = col.DbTypeText, DbTypeTextFull = col.Attribute.DbType, MaxLength = col.DbSize });
switch (dbtype2)
{
//case MySqlDbType.Binary:
//case MySqlDbType.VarBinary:
// break;
default:
dbtype = dbtype2;
if (col.DbSize != 0) ret.Size = col.DbSize;
if (col.DbPrecision != 0) ret.Precision = col.DbPrecision;
if (col.DbScale != 0) ret.Scale = col.DbScale;
break;
}
}
if (dbtype == MySqlDbType.Geometry)
{
ret.MySqlDbType = MySqlDbType.Text;
if (value != null) ret.Value = (value as MygisGeometry).AsText();
}
else
{
ret.MySqlDbType = dbtype;
if (ret.MySqlDbType == MySqlDbType.Enum && value != null)
ret.Value = EnumValueToMySql(col, value);
}
_params?.Add(ret);
return ret;
}
public override DbParameter[] GetDbParamtersByObject(string sql, object obj) =>
Utils.GetDbParamtersByObject<MySqlParameter>(sql, obj, "@", (name, type, value) =>
{
var ret = new MySqlParameter { ParameterName = $"@{name}", Value = value };
var tp = _orm.CodeFirst.GetDbInfo(type)?.type;
if (tp != null)
{
if ((MySqlDbType)tp.Value == MySqlDbType.Geometry)
{
ret.MySqlDbType = MySqlDbType.Text;
if (value != null) ret.Value = (value as MygisGeometry).AsText();
}
else
{
ret.MySqlDbType = (MySqlDbType)tp.Value;
if (ret.MySqlDbType == MySqlDbType.Enum && value != null)
ret.Value = EnumValueToMySql(null, value);
}
}
return ret;
});
static ConcurrentDictionary<Type, Dictionary<string, int>> _dicEnumNames = new ConcurrentDictionary<Type, Dictionary<string, int>>();
static long EnumValueToMySql(ColumnInfo col, object value) //mysqlConnector 不支持 enumString 作为参数化传递所以要计算出下标值mysql 下标从 1 开始,并且 c# 设置了枚举元素值会影响下标
{
if (value == null) return 0;
if (value is Enum == false) return 0;
var names = _dicEnumNames.GetOrAdd(col?.Attribute.MapType ?? value.GetType(), type =>
{
var dic = new Dictionary<string, int>();
var ns = Enum.GetNames(type);
for (var a = 0; a < ns.Length; a++) dic.Add(ns[a], a + 1);
return dic;
});
return names.TryGetValue(value.ToString(), out var tryval) ? tryval : 0;
}
public override string FormatSql(string sql, params object[] args) => sql?.FormatMySql(args);
public override string QuoteSqlName(params string[] name)
{
if (name.Length == 1)
{
var nametrim = name[0].Trim();
if (nametrim.StartsWith("(") && nametrim.EndsWith(")"))
return nametrim; //原生SQL
if (nametrim.StartsWith("`") && nametrim.EndsWith("`"))
return nametrim;
return $"`{nametrim.Replace(".", "`.`")}`";
}
return $"`{string.Join("`.`", name)}`";
}
public override string TrimQuoteSqlName(string name)
{
var nametrim = name.Trim();
if (nametrim.StartsWith("(") && nametrim.EndsWith(")"))
return nametrim; //原生SQL
return $"{nametrim.Trim('`').Replace("`.`", ".").Replace(".`", ".")}";
}
public override string[] SplitTableName(string name) => GetSplitTableNames(name, '`', '`', 2);
public override string QuoteParamterName(string name) => $"@{(_orm.CodeFirst.IsSyncStructureToLower ? name.ToLower() : name)}";
public override string IsNull(string sql, object value) => $"ifnull({sql}, {value})";
public override string StringConcat(string[] objs, Type[] types) => $"concat({string.Join(", ", objs)})";
public override string Mod(string left, string right, Type leftType, Type rightType) => $"{left} % {right}";
public override string Div(string left, string right, Type leftType, Type rightType) => $"{left} div {right}";
public override string Now => "now()";
public override string NowUtc => "utc_timestamp()";
public override string QuoteWriteParamter(Type type, string paramterName)
{
switch (type.FullName)
{
case "MygisPoint":
case "MygisLineString":
case "MygisPolygon":
case "MygisMultiPoint":
case "MygisMultiLineString":
case "MygisMultiPolygon": return $"ST_GeomFromText({paramterName})";
}
return paramterName;
}
public override string QuoteReadColumn(Type type, Type mapType, string columnName)
{
switch (mapType.FullName)
{
case "MygisPoint":
case "MygisLineString":
case "MygisPolygon":
case "MygisMultiPoint":
case "MygisMultiLineString":
case "MygisMultiPolygon": return $"ST_AsText({columnName})";
}
return columnName;
}
public override string GetNoneParamaterSqlValue(List<DbParameter> specialParams, Type type, object value)
{
if (value == null) return "NULL";
if (type == typeof(byte[])) return $"0x{CommonUtils.BytesSqlRaw(value as byte[])}";
if (type == typeof(TimeSpan) || type == typeof(TimeSpan?))
{
var ts = (TimeSpan)value;
value = $"{Math.Floor(ts.TotalHours)}:{ts.Minutes}:{ts.Seconds}";
}
return FormatSql("{0}", value, 1);
}
}
}