表达式函数,增加DateTime/TimeSpan,并且开始测试与整理

This commit is contained in:
28810
2018-12-20 20:00:33 +08:00
parent 6f8a047149
commit 572aa1d8ee
21 changed files with 1542 additions and 460 deletions

View File

@ -160,11 +160,27 @@ namespace FreeSql.Internal {
case ExpressionType.Lambda: return ExpressionLambdaToSql((exp as LambdaExpression)?.Body, _tables, _selectColumnMap, tbtype, isQuoteName);
case ExpressionType.Convert: return ExpressionLambdaToSql((exp as UnaryExpression)?.Operand, _tables, _selectColumnMap, tbtype, isQuoteName);
case ExpressionType.Constant: return _common.FormatSql("{0}", (exp as ConstantExpression)?.Value);
case ExpressionType.Call:
var exp3 = exp as MethodCallExpression;
if (exp3.Object.Type.FullName == "System.String") return ExpressionLambdaToSqlCallString(exp3, _tables, _selectColumnMap, tbtype, isQuoteName);
if (exp3.Object.Type.FullName == "System.Math") return ExpressionLambdaToSqlCallMath(exp3, _tables, _selectColumnMap, tbtype, isQuoteName);
if (exp3.Object.Type.FullName == "System.DateTime" || exp3.Object.Type.GenericTypeArguments.FirstOrDefault()?.FullName == "System.DateTime") return ExpressionLambdaToSqlCallDateTime(exp3, _tables, _selectColumnMap, tbtype, isQuoteName);
if (exp3.Object.Type.FullName == "System.TimeSpan" || exp3.Object.Type.GenericTypeArguments.FirstOrDefault()?.FullName == "System.TimeSpan") return ExpressionLambdaToSqlCallTimeSpan(exp3, _tables, _selectColumnMap, tbtype, isQuoteName);
throw new Exception($"MySqlExpression 未现实函数表达式 {exp3} 解析");
case ExpressionType.MemberAccess:
var exp4 = exp as MemberExpression;
var extRet = "";
if (exp4.Expression == null && exp4.Type.FullName == "System.DateTime" && exp4.Member.Name == "Now") return ExpressionLambdaToSqlMemberAccessDateTime(exp4, _tables, _selectColumnMap, tbtype, isQuoteName);
if (exp4.Expression.Type.FullName == "System.String") extRet = ExpressionLambdaToSqlMemberAccessString(exp4, _tables, _selectColumnMap, tbtype, isQuoteName);
else if (exp4.Expression.Type.FullName == "System.Math") extRet = ExpressionLambdaToSqlMemberAccessMath(exp4, _tables, _selectColumnMap, tbtype, isQuoteName);
else if (exp4.Expression.Type.FullName == "System.DateTime" || exp4.Type.GenericTypeArguments.FirstOrDefault()?.FullName == "System.DateTime") extRet = ExpressionLambdaToSqlMemberAccessDateTime(exp4, _tables, _selectColumnMap, tbtype, isQuoteName);
else if (exp4.Expression.Type.FullName == "System.TimeSpan" || exp4.Type.GenericTypeArguments.FirstOrDefault()?.FullName == "System.TimeSpan") extRet = ExpressionLambdaToSqlMemberAccessTimeSpan(exp4, _tables, _selectColumnMap, tbtype, isQuoteName);
if (string.IsNullOrEmpty(extRet) == false) return extRet;
var expStack = new Stack<Expression>();
expStack.Push(exp);
MethodCallExpression callExp = null;
var exp2 = (exp as MemberExpression).Expression;
var exp2 = exp4.Expression;
while (true) {
switch(exp2.NodeType) {
case ExpressionType.Constant:
@ -188,7 +204,7 @@ namespace FreeSql.Internal {
break;
}
if (expStack.First().NodeType != ExpressionType.Parameter) return _common.FormatSql("{0}", Expression.Lambda(exp).Compile().DynamicInvoke());
if (callExp != null) return ExpressionLambdaToSqlCall(callExp, _tables, _selectColumnMap, tbtype, isQuoteName);
if (callExp != null) return ExpressionLambdaToSql(callExp, _tables, _selectColumnMap, tbtype, isQuoteName);
if (_tables == null) {
var pp = expStack.Pop() as ParameterExpression;
var memberExp = expStack.Pop() as MemberExpression;
@ -255,7 +271,6 @@ namespace FreeSql.Internal {
}
if (isQuoteName) name2 = _common.QuoteSqlName(name2);
return $"{alias2}.{name2}";
case ExpressionType.Call: return ExpressionLambdaToSqlCall(exp as MethodCallExpression, _tables, _selectColumnMap, tbtype, isQuoteName);
}
if (dicExpressionOperator.TryGetValue(exp.NodeType, out var tryoper) == false) return "";
var expBinary = exp as BinaryExpression;
@ -268,10 +283,17 @@ namespace FreeSql.Internal {
left = tmp;
}
if (right == "NULL") tryoper = tryoper == "=" ? " IS " : " IS NOT ";
if (tryoper == "+" && (expBinary.Left.Type.FullName == "System.String" || expBinary.Right.Type.FullName == "System.String")) return _common.StringConcat(left, right, expBinary.Left.Type, expBinary.Right.Type);
return $"{left} {tryoper} {right}";
}
internal abstract string ExpressionLambdaToSqlCall(MethodCallExpression exp, List<SelectTableInfo> _tables, List<SelectColumnInfo> _selectColumnMap, SelectTableInfoType tbtype, bool isQuoteName);
internal abstract string ExpressionLambdaToSqlMemberAccessString(MemberExpression exp, List<SelectTableInfo> _tables, List<SelectColumnInfo> _selectColumnMap, SelectTableInfoType tbtype, bool isQuoteName);
internal abstract string ExpressionLambdaToSqlMemberAccessMath(MemberExpression exp, List<SelectTableInfo> _tables, List<SelectColumnInfo> _selectColumnMap, SelectTableInfoType tbtype, bool isQuoteName);
internal abstract string ExpressionLambdaToSqlMemberAccessDateTime(MemberExpression exp, List<SelectTableInfo> _tables, List<SelectColumnInfo> _selectColumnMap, SelectTableInfoType tbtype, bool isQuoteName);
internal abstract string ExpressionLambdaToSqlMemberAccessTimeSpan(MemberExpression exp, List<SelectTableInfo> _tables, List<SelectColumnInfo> _selectColumnMap, SelectTableInfoType tbtype, bool isQuoteName);
internal abstract string ExpressionLambdaToSqlCallString(MethodCallExpression exp, List<SelectTableInfo> _tables, List<SelectColumnInfo> _selectColumnMap, SelectTableInfoType tbtype, bool isQuoteName);
internal abstract string ExpressionLambdaToSqlCallMath(MethodCallExpression exp, List<SelectTableInfo> _tables, List<SelectColumnInfo> _selectColumnMap, SelectTableInfoType tbtype, bool isQuoteName);
internal abstract string ExpressionLambdaToSqlCallDateTime(MethodCallExpression exp, List<SelectTableInfo> _tables, List<SelectColumnInfo> _selectColumnMap, SelectTableInfoType tbtype, bool isQuoteName);
internal abstract string ExpressionLambdaToSqlCallTimeSpan(MethodCallExpression exp, List<SelectTableInfo> _tables, List<SelectColumnInfo> _selectColumnMap, SelectTableInfoType tbtype, bool isQuoteName);
}
}

View File

@ -16,6 +16,7 @@ namespace FreeSql.Internal {
internal abstract string QuoteSqlName(string name);
internal abstract string QuoteParamterName(string name);
internal abstract string IsNull(string sql, object value);
internal abstract string StringConcat(string left, string right, Type leftType, Type rightType);
internal ICodeFirst CodeFirst { get; set; }
internal TableInfo GetTableByEntity(Type entity) => Utils.GetTableByEntity(entity, this);

View File

@ -10,7 +10,10 @@ namespace FreeSql.MySql.Curd {
class MySqlSelect<T1> : FreeSql.Internal.CommonProvider.Select1Provider<T1> where T1 : class {
internal static string ToSqlStatic(CommonUtils _commonUtils, string _select, string field, StringBuilder _join, StringBuilder _where, string _groupby, string _having, string _orderby, int _skip, int _limit, List<SelectTableInfo> _tables) {
internal static string ToSqlStatic(CommonUtils _commonUtils, string _select, string field, StringBuilder _join, StringBuilder _where, string _groupby, string _having, string _orderby, int _skip, int _limit, List<SelectTableInfo> _tables, IFreeSql _orm) {
if (_orm.CodeFirst.IsAutoSyncStructure)
_orm.CodeFirst.SyncStructure(_tables.Select(a => a.Table.Type).ToArray());
var sb = new StringBuilder();
sb.Append(_select).Append(field).Append(" \r\nFROM ");
var tbsjoin = _tables.Where(a => a.Type != SelectTableInfoType.From).ToArray();
@ -73,42 +76,42 @@ namespace FreeSql.MySql.Curd {
public override ISelect<T1, T2, T3, T4, T5, T6, T7, T8> From<T2, T3, T4, T5, T6, T7, T8>(Expression<Func<ISelectFromExpression<T1>, T2, T3, T4, T5, T6, T7, T8, ISelectFromExpression<T1>>> exp) { this.InternalFrom(exp?.Body); var ret = new MySqlSelect<T1, T2, T3, T4, T5, T6, T7, T8>(_orm, _commonUtils, _commonExpression, null); MySqlSelect<T1>.CopyData(this, ret); return ret; }
public override ISelect<T1, T2, T3, T4, T5, T6, T7, T8, T9> From<T2, T3, T4, T5, T6, T7, T8, T9>(Expression<Func<ISelectFromExpression<T1>, T2, T3, T4, T5, T6, T7, T8, T9, ISelectFromExpression<T1>>> exp) { this.InternalFrom(exp?.Body); var ret = new MySqlSelect<T1, T2, T3, T4, T5, T6, T7, T8, T9>(_orm, _commonUtils, _commonExpression, null); MySqlSelect<T1>.CopyData(this, ret); return ret; }
public override ISelect<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10> From<T2, T3, T4, T5, T6, T7, T8, T9, T10>(Expression<Func<ISelectFromExpression<T1>, T2, T3, T4, T5, T6, T7, T8, T9, T10, ISelectFromExpression<T1>>> exp) { this.InternalFrom(exp?.Body); var ret = new MySqlSelect<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10>(_orm, _commonUtils, _commonExpression, null); MySqlSelect<T1>.CopyData(this, ret); return ret; }
public override string ToSql(string field = null) => ToSqlStatic(_commonUtils, _select, field ?? this.GetAllField().field, _join, _where, _groupby, _having, _orderby, _skip, _limit, _tables);
public override string ToSql(string field = null) => ToSqlStatic(_commonUtils, _select, field ?? this.GetAllField().field, _join, _where, _groupby, _having, _orderby, _skip, _limit, _tables, _orm);
}
class MySqlSelect<T1, T2> : FreeSql.Internal.CommonProvider.Select2Provider<T1, T2> where T1 : class where T2 : class {
public MySqlSelect(IFreeSql orm, CommonUtils commonUtils, CommonExpression commonExpression, object dywhere) : base(orm, commonUtils, commonExpression, dywhere) { }
public override string ToSql(string field = null) => MySqlSelect<T1>.ToSqlStatic(_commonUtils, _select, field ?? this.GetAllField().field, _join, _where, _groupby, _having, _orderby, _skip, _limit, _tables);
public override string ToSql(string field = null) => MySqlSelect<T1>.ToSqlStatic(_commonUtils, _select, field ?? this.GetAllField().field, _join, _where, _groupby, _having, _orderby, _skip, _limit, _tables, _orm);
}
class MySqlSelect<T1, T2, T3> : FreeSql.Internal.CommonProvider.Select3Provider<T1, T2, T3> where T1 : class where T2 : class where T3 : class {
public MySqlSelect(IFreeSql orm, CommonUtils commonUtils, CommonExpression commonExpression, object dywhere) : base(orm, commonUtils, commonExpression, dywhere) { }
public override string ToSql(string field = null) => MySqlSelect<T1>.ToSqlStatic(_commonUtils, _select, field ?? this.GetAllField().field, _join, _where, _groupby, _having, _orderby, _skip, _limit, _tables);
public override string ToSql(string field = null) => MySqlSelect<T1>.ToSqlStatic(_commonUtils, _select, field ?? this.GetAllField().field, _join, _where, _groupby, _having, _orderby, _skip, _limit, _tables, _orm);
}
class MySqlSelect<T1, T2, T3, T4> : FreeSql.Internal.CommonProvider.Select4Provider<T1, T2, T3, T4> where T1 : class where T2 : class where T3 : class where T4 : class {
public MySqlSelect(IFreeSql orm, CommonUtils commonUtils, CommonExpression commonExpression, object dywhere) : base(orm, commonUtils, commonExpression, dywhere) { }
public override string ToSql(string field = null) => MySqlSelect<T1>.ToSqlStatic(_commonUtils, _select, field ?? this.GetAllField().field, _join, _where, _groupby, _having, _orderby, _skip, _limit, _tables);
public override string ToSql(string field = null) => MySqlSelect<T1>.ToSqlStatic(_commonUtils, _select, field ?? this.GetAllField().field, _join, _where, _groupby, _having, _orderby, _skip, _limit, _tables, _orm);
}
class MySqlSelect<T1, T2, T3, T4, T5> : FreeSql.Internal.CommonProvider.Select5Provider<T1, T2, T3, T4, T5> where T1 : class where T2 : class where T3 : class where T4 : class where T5 : class {
public MySqlSelect(IFreeSql orm, CommonUtils commonUtils, CommonExpression commonExpression, object dywhere) : base(orm, commonUtils, commonExpression, dywhere) { }
public override string ToSql(string field = null) => MySqlSelect<T1>.ToSqlStatic(_commonUtils, _select, field ?? this.GetAllField().field, _join, _where, _groupby, _having, _orderby, _skip, _limit, _tables);
public override string ToSql(string field = null) => MySqlSelect<T1>.ToSqlStatic(_commonUtils, _select, field ?? this.GetAllField().field, _join, _where, _groupby, _having, _orderby, _skip, _limit, _tables, _orm);
}
class MySqlSelect<T1, T2, T3, T4, T5, T6> : FreeSql.Internal.CommonProvider.Select6Provider<T1, T2, T3, T4, T5, T6> where T1 : class where T2 : class where T3 : class where T4 : class where T5 : class where T6 : class {
public MySqlSelect(IFreeSql orm, CommonUtils commonUtils, CommonExpression commonExpression, object dywhere) : base(orm, commonUtils, commonExpression, dywhere) { }
public override string ToSql(string field = null) => MySqlSelect<T1>.ToSqlStatic(_commonUtils, _select, field ?? this.GetAllField().field, _join, _where, _groupby, _having, _orderby, _skip, _limit, _tables);
public override string ToSql(string field = null) => MySqlSelect<T1>.ToSqlStatic(_commonUtils, _select, field ?? this.GetAllField().field, _join, _where, _groupby, _having, _orderby, _skip, _limit, _tables, _orm);
}
class MySqlSelect<T1, T2, T3, T4, T5, T6, T7> : FreeSql.Internal.CommonProvider.Select7Provider<T1, T2, T3, T4, T5, T6, T7> where T1 : class where T2 : class where T3 : class where T4 : class where T5 : class where T6 : class where T7 : class {
public MySqlSelect(IFreeSql orm, CommonUtils commonUtils, CommonExpression commonExpression, object dywhere) : base(orm, commonUtils, commonExpression, dywhere) { }
public override string ToSql(string field = null) => MySqlSelect<T1>.ToSqlStatic(_commonUtils, _select, field ?? this.GetAllField().field, _join, _where, _groupby, _having, _orderby, _skip, _limit, _tables);
public override string ToSql(string field = null) => MySqlSelect<T1>.ToSqlStatic(_commonUtils, _select, field ?? this.GetAllField().field, _join, _where, _groupby, _having, _orderby, _skip, _limit, _tables, _orm);
}
class MySqlSelect<T1, T2, T3, T4, T5, T6, T7, T8> : FreeSql.Internal.CommonProvider.Select8Provider<T1, T2, T3, T4, T5, T6, T7, T8> where T1 : class where T2 : class where T3 : class where T4 : class where T5 : class where T6 : class where T7 : class where T8 : class {
public MySqlSelect(IFreeSql orm, CommonUtils commonUtils, CommonExpression commonExpression, object dywhere) : base(orm, commonUtils, commonExpression, dywhere) { }
public override string ToSql(string field = null) => MySqlSelect<T1>.ToSqlStatic(_commonUtils, _select, field ?? this.GetAllField().field, _join, _where, _groupby, _having, _orderby, _skip, _limit, _tables);
public override string ToSql(string field = null) => MySqlSelect<T1>.ToSqlStatic(_commonUtils, _select, field ?? this.GetAllField().field, _join, _where, _groupby, _having, _orderby, _skip, _limit, _tables, _orm);
}
class MySqlSelect<T1, T2, T3, T4, T5, T6, T7, T8, T9> : FreeSql.Internal.CommonProvider.Select9Provider<T1, T2, T3, T4, T5, T6, T7, T8, T9> where T1 : class where T2 : class where T3 : class where T4 : class where T5 : class where T6 : class where T7 : class where T8 : class where T9 : class {
public MySqlSelect(IFreeSql orm, CommonUtils commonUtils, CommonExpression commonExpression, object dywhere) : base(orm, commonUtils, commonExpression, dywhere) { }
public override string ToSql(string field = null) => MySqlSelect<T1>.ToSqlStatic(_commonUtils, _select, field ?? this.GetAllField().field, _join, _where, _groupby, _having, _orderby, _skip, _limit, _tables);
public override string ToSql(string field = null) => MySqlSelect<T1>.ToSqlStatic(_commonUtils, _select, field ?? this.GetAllField().field, _join, _where, _groupby, _having, _orderby, _skip, _limit, _tables, _orm);
}
class MySqlSelect<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10> : FreeSql.Internal.CommonProvider.Select10Provider<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10> where T1 : class where T2 : class where T3 : class where T4 : class where T5 : class where T6 : class where T7 : class where T8 : class where T9 : class where T10 : class {
public MySqlSelect(IFreeSql orm, CommonUtils commonUtils, CommonExpression commonExpression, object dywhere) : base(orm, commonUtils, commonExpression, dywhere) { }
public override string ToSql(string field = null) => MySqlSelect<T1>.ToSqlStatic(_commonUtils, _select, field ?? this.GetAllField().field, _join, _where, _groupby, _having, _orderby, _skip, _limit, _tables);
public override string ToSql(string field = null) => MySqlSelect<T1>.ToSqlStatic(_commonUtils, _select, field ?? this.GetAllField().field, _join, _where, _groupby, _having, _orderby, _skip, _limit, _tables, _orm);
}
}

View File

@ -23,6 +23,7 @@ namespace FreeSql.MySql {
}
}
}
static DateTime dt1970 = new DateTime(1970, 1, 1);
public override object AddslashesProcessParam(object param) {
if (param == null) return "NULL";
if (param is bool || param is bool?)
@ -33,21 +34,24 @@ namespace FreeSql.MySql {
return ((Enum)param).ToInt64();
else if (decimal.TryParse(string.Concat(param), out var trydec))
return param;
else if (param is DateTime) {
DateTime dt = (DateTime)param;
return string.Concat("'", dt.ToString("yyyy-MM-dd HH:mm:ss"), "'");
} else if (param is DateTime?) {
DateTime? dt = param as DateTime?;
return string.Concat("'", dt.Value.ToString("yyyy-MM-dd HH:mm:ss"), "'");
else if (param is DateTime)
return string.Concat("'", ((DateTime)param).ToString("yyyy-MM-dd HH:mm:ss"), "'");
else if (param is DateTime?)
return string.Concat("'", (param as DateTime?).Value.ToString("yyyy-MM-dd HH:mm:ss"), "'");
else if (param is TimeSpan) {
var ts = (TimeSpan)param;
return string.Concat("'", ts.Ticks > 0 ? "" : "-", ts.TotalHours, dt1970.AddTicks(Math.Abs(ts.Ticks)).ToString(":mm:ss.fff"), "'");
} else if (param is TimeSpan) {
var ts = (param as TimeSpan?).Value;
return string.Concat("'", ts.Ticks > 0 ? "" : "-", ts.TotalHours, dt1970.AddTicks(Math.Abs(ts.Ticks)).ToString(":mm:ss.fff"), "'");
} else if (param is IEnumerable) {
var sb = new StringBuilder();
var ie = param as IEnumerable;
foreach (var z in ie) sb.Append(",").Append(AddslashesProcessParam(z));
return sb.Length == 0 ? "(NULL)" : sb.Remove(0, 1).Insert(0, "(").Append(")").ToString();
} else {
return string.Concat("'", param.ToString().Replace("'", "''"), "'");
//if (param is string) return string.Concat('N', nparms[a]);
}
return string.Concat("'", param.ToString().Replace("'", "''"), "'");
//if (param is string) return string.Concat('N', nparms[a]);
}
protected override DbCommand CreateCommand() {

View File

@ -169,12 +169,21 @@ where a.table_schema in ({0}) and a.table_name in ({1})".FormatMySql(isRenameTab
return sb.Length == 0 ? null : sb.ToString();
}
Dictionary<string, bool> dicSyced = new Dictionary<string, bool>();
public bool SyncStructure<TEntity>() => this.SyncStructure(typeof(TEntity));
public bool SyncStructure(params Type[] entityTypes) {
var ddl = this.GetComparisonDDLStatements(entityTypes);
if (string.IsNullOrEmpty(ddl)) return true;
if (entityTypes == null) return true;
var syncTypes = entityTypes.Where(a => dicSyced.ContainsKey(a.FullName) == false).ToArray();
if (syncTypes.Any() == false) return true;
var ddl = this.GetComparisonDDLStatements(syncTypes);
if (string.IsNullOrEmpty(ddl)) {
foreach (var syncType in syncTypes) dicSyced.Add(syncType.FullName, true);
return true;
}
try {
return _orm.Ado.ExecuteNonQuery(CommandType.Text, ddl) > 0;
var affrows = _orm.Ado.ExecuteNonQuery(CommandType.Text, ddl);
foreach (var syncType in syncTypes) dicSyced.Add(syncType.FullName, true);
return affrows > 0;
} catch {
return false;
}

View File

@ -2,6 +2,7 @@
using FreeSql.Internal.Model;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Linq.Expressions;
namespace FreeSql.MySql {
@ -9,150 +10,174 @@ namespace FreeSql.MySql {
public MySqlExpression(CommonUtils common) : base(common) { }
internal override string ExpressionLambdaToSqlCall(MethodCallExpression exp, List<SelectTableInfo> _tables, List<SelectColumnInfo> _selectColumnMap, SelectTableInfoType tbtype, bool isQuoteName) {
if (exp.Object.Type.FullName == "System.String") {
var left = ExpressionLambdaToSql(exp.Object, _tables, _selectColumnMap, tbtype, isQuoteName);
switch (exp.Method.Name) {
case "StartsWith":
case "EndsWith":
case "Contains":
var args0Value = ExpressionLambdaToSql(exp.Arguments[0], _tables, _selectColumnMap, tbtype, isQuoteName);
if (args0Value == "NULL") return $"({left}) IS NULL";
if (exp.Method.Name == "StartsWith") return $"({left}) LIKE {(args0Value.StartsWith("'") ? args0Value.Insert(1, "%") : $"concat('%', {args0Value})")}";
if (exp.Method.Name == "EndsWith") return $"({left}) LIKE {(args0Value.EndsWith("'") ? args0Value.Insert(args0Value.Length - 1, "%") : $"concat({args0Value}, '%')")}";
if (args0Value.StartsWith("'") && args0Value.EndsWith("'")) return $"({left}) LIKE {args0Value.Insert(1, "%").Insert(args0Value.Length, "%")}";
return $"({left}) like concat('%', {args0Value}, '%')";
case "ToLower": return $"lower({left})";
case "ToUpper": return $"upper({left})";
case "Substring": return $"substr({left}, {ExpressionLambdaToSql(exp.Arguments[0], _tables, _selectColumnMap, tbtype, isQuoteName)} + 1, {ExpressionLambdaToSql(exp.Arguments[1], _tables, _selectColumnMap, tbtype, isQuoteName)})";
case "Length": return $"char_length({left})";
case "IndexOf":
var indexOfFindStr = ExpressionLambdaToSql(exp.Arguments[0], _tables, _selectColumnMap, tbtype, isQuoteName);
if (exp.Arguments.Count > 1 && exp.Arguments[1].Type.FullName == "System.Int32") return $"(locate({left}, {indexOfFindStr}, ParseLambdaToSql(exp.Arguments[1], _tables, _selectColumnMap, tbtype, isQuoteName) + 1) - 1)";
return $"(locate({left}, {indexOfFindStr}) - 1)";
case "PadLeft": return $"lpad({left}, {ExpressionLambdaToSql(exp.Arguments[0], _tables, _selectColumnMap, tbtype, isQuoteName)}, {ExpressionLambdaToSql(exp.Arguments[1], _tables, _selectColumnMap, tbtype, isQuoteName)})";
case "PadRight": return $"rpad({left}, {ExpressionLambdaToSql(exp.Arguments[0], _tables, _selectColumnMap, tbtype, isQuoteName)}, {ExpressionLambdaToSql(exp.Arguments[1], _tables, _selectColumnMap, tbtype, isQuoteName)})";
case "Trim":
case "TrimStart":
case "TrimEnd":
if (exp.Arguments.Count == 0) {
if (exp.Method.Name == "Trim") return $"trim({left})";
if (exp.Method.Name == "TrimStart") return $"ltrim({left})";
if (exp.Method.Name == "TrimStart") return $"rtrim({left})";
internal override string ExpressionLambdaToSqlMemberAccessString(MemberExpression exp, List<SelectTableInfo> _tables, List<SelectColumnInfo> _selectColumnMap, SelectTableInfoType tbtype, bool isQuoteName) {
var left = ExpressionLambdaToSql(exp.Expression, _tables, _selectColumnMap, tbtype, isQuoteName);
switch (exp.Member.Name) {
case "Length": return $"char_length({left})";
}
return null;
}
internal override string ExpressionLambdaToSqlMemberAccessMath(MemberExpression exp, List<SelectTableInfo> _tables, List<SelectColumnInfo> _selectColumnMap, SelectTableInfoType tbtype, bool isQuoteName) {
var left = ExpressionLambdaToSql(exp.Expression, _tables, _selectColumnMap, tbtype, isQuoteName);
switch (exp.Member.Name) {
case "PI": return $"pi()";
}
return null;
}
internal override string ExpressionLambdaToSqlMemberAccessDateTime(MemberExpression exp, List<SelectTableInfo> _tables, List<SelectColumnInfo> _selectColumnMap, SelectTableInfoType tbtype, bool isQuoteName) {
if (exp.Expression == null && exp.Member.Name == "Now") return "now()";
var left = ExpressionLambdaToSql(exp.Expression, _tables, _selectColumnMap, tbtype, isQuoteName);
switch (exp.Member.Name) {
case "DayOfWeek": return $"(dayofweek({left}) - 1)";
case "Day": return $"dayofmonth({left})";
case "DayOfYear": return $"dayofyear({left})";
case "Month": return $"month({left})";
case "Year": return $"year({left})";
case "Hour": return $"hour({left})";
case "Minute": return $"minute({left})";
case "Second": return $"second({left})";
case "Millisecond": return $"floor(microsecond({left}) / 1000)";
case "Ticks": return $"(time_to_sec({left}) * 10000000 + 621355968000000000)";
}
return null;
}
internal override string ExpressionLambdaToSqlMemberAccessTimeSpan(MemberExpression exp, List<SelectTableInfo> _tables, List<SelectColumnInfo> _selectColumnMap, SelectTableInfoType tbtype, bool isQuoteName) {
var left = ExpressionLambdaToSql(exp.Expression, _tables, _selectColumnMap, tbtype, isQuoteName);
switch (exp.Member.Name) {
case "Days": return $"floor(time_to_sec({left}) / {60 * 60 * 24})";
case "Hours": return $"extract(hour from {left})";
case "Milliseconds": return $"floor(extract(microsecond from {left}) / 1000)";
case "Minutes": return $"extract(minute from {left})";
case "Seconds": return $"extract(second from {left})";
case "Ticks": return $"(time_to_sec({left}) * 10000000 + extract(microsecond from {left}) * 10)";
case "TotalDays": return $"floor(extract(hour from {left}) / 24)";
case "TotalHours": return $"floor(time_to_sec({left}) / {60 * 60})";
case "TotalMilliseconds": return $"(time_to_sec({left}) * 1000 + floor(extract(microsecond from {left}) / 1000))";
case "TotalMinutes": return $"floor(time_to_sec({left}) / 60)";
case "TotalSeconds": return $"time_to_sec({left})";
}
return null;
}
internal override string ExpressionLambdaToSqlCallString(MethodCallExpression exp, List<SelectTableInfo> _tables, List<SelectColumnInfo> _selectColumnMap, SelectTableInfoType tbtype, bool isQuoteName) {
var left = ExpressionLambdaToSql(exp.Object, _tables, _selectColumnMap, tbtype, isQuoteName);
switch (exp.Method.Name) {
case "StartsWith":
case "EndsWith":
case "Contains":
var args0Value = ExpressionLambdaToSql(exp.Arguments[0], _tables, _selectColumnMap, tbtype, isQuoteName);
if (args0Value == "NULL") return $"({left}) IS NULL";
if (exp.Method.Name == "StartsWith") return $"({left}) LIKE {(args0Value.StartsWith("'") ? args0Value.Insert(1, "%") : $"concat('%', {args0Value})")}";
if (exp.Method.Name == "EndsWith") return $"({left}) LIKE {(args0Value.EndsWith("'") ? args0Value.Insert(args0Value.Length - 1, "%") : $"concat({args0Value}, '%')")}";
if (args0Value.StartsWith("'") && args0Value.EndsWith("'")) return $"({left}) LIKE {args0Value.Insert(1, "%").Insert(args0Value.Length, "%")}";
return $"({left}) LIKE concat('%', {args0Value}, '%')";
case "ToLower": return $"lower({left})";
case "ToUpper": return $"upper({left})";
case "Substring":
var substrArgs1 = ExpressionLambdaToSql(exp.Arguments[0], _tables, _selectColumnMap, tbtype, isQuoteName);
if (long.TryParse(substrArgs1, out var testtrylng1)) substrArgs1 = (testtrylng1 + 1).ToString();
else substrArgs1 += " + 1";
if (exp.Arguments.Count == 1) return $"substr({left}, {substrArgs1})";
return $"substr({left}, {substrArgs1}, {ExpressionLambdaToSql(exp.Arguments[1], _tables, _selectColumnMap, tbtype, isQuoteName)})";
case "IndexOf":
var indexOfFindStr = ExpressionLambdaToSql(exp.Arguments[0], _tables, _selectColumnMap, tbtype, isQuoteName);
if (exp.Arguments.Count > 1 && exp.Arguments[1].Type.FullName == "System.Int32") {
var locateArgs1 = ExpressionLambdaToSql(exp.Arguments[1], _tables, _selectColumnMap, tbtype, isQuoteName);
if (long.TryParse(locateArgs1, out var testtrylng2)) locateArgs1 = (testtrylng2 + 1).ToString();
else locateArgs1 += " + 1";
return $"(locate({left}, {indexOfFindStr}, {locateArgs1}) - 1)";
}
return $"(locate({left}, {indexOfFindStr}) - 1)";
case "PadLeft":
if (exp.Arguments.Count == 1) return $"lpad({left}, {ExpressionLambdaToSql(exp.Arguments[0], _tables, _selectColumnMap, tbtype, isQuoteName)})";
return $"lpad({left}, {ExpressionLambdaToSql(exp.Arguments[0], _tables, _selectColumnMap, tbtype, isQuoteName)}, {ExpressionLambdaToSql(exp.Arguments[1], _tables, _selectColumnMap, tbtype, isQuoteName)})";
case "PadRight":
if (exp.Arguments.Count == 1) return $"rpad({left}, {ExpressionLambdaToSql(exp.Arguments[0], _tables, _selectColumnMap, tbtype, isQuoteName)})";
return $"rpad({left}, {ExpressionLambdaToSql(exp.Arguments[0], _tables, _selectColumnMap, tbtype, isQuoteName)}, {ExpressionLambdaToSql(exp.Arguments[1], _tables, _selectColumnMap, tbtype, isQuoteName)})";
case "Trim":
case "TrimStart":
case "TrimEnd":
if (exp.Arguments.Count == 0) {
if (exp.Method.Name == "Trim") return $"trim({left})";
if (exp.Method.Name == "TrimStart") return $"ltrim({left})";
if (exp.Method.Name == "TrimEnd") return $"rtrim({left})";
}
foreach (var argsTrim02 in exp.Arguments) {
var argsTrim01s = new[] { argsTrim02 };
if (argsTrim02.NodeType == ExpressionType.NewArrayInit) {
var arritem = argsTrim02 as NewArrayExpression;
argsTrim01s = arritem.Expressions.ToArray();
}
foreach (var argsTrim01 in exp.Arguments) {
foreach (var argsTrim01 in argsTrim01s) {
if (exp.Method.Name == "Trim") left = $"trim({ExpressionLambdaToSql(argsTrim01, _tables, _selectColumnMap, tbtype, isQuoteName)} from {left})";
if (exp.Method.Name == "TrimStart") left = $"trim(leading {ExpressionLambdaToSql(argsTrim01, _tables, _selectColumnMap, tbtype, isQuoteName)} from {left})";
if (exp.Method.Name == "TrimStart") left = $"trim(trailing {ExpressionLambdaToSql(argsTrim01, _tables, _selectColumnMap, tbtype, isQuoteName)} from {left})";
if (exp.Method.Name == "TrimEnd") left = $"trim(trailing {ExpressionLambdaToSql(argsTrim01, _tables, _selectColumnMap, tbtype, isQuoteName)} from {left})";
}
return left;
case "Replace": return $"replace({left}, {ExpressionLambdaToSql(exp.Arguments[0], _tables, _selectColumnMap, tbtype, isQuoteName)}, {ExpressionLambdaToSql(exp.Arguments[1], _tables, _selectColumnMap, tbtype, isQuoteName)})";
case "CompareTo": return $"strcmp({left}, {ExpressionLambdaToSql(exp.Arguments[0], _tables, _selectColumnMap, tbtype, isQuoteName)})";
}
}
return left;
case "Replace": return $"replace({left}, {ExpressionLambdaToSql(exp.Arguments[0], _tables, _selectColumnMap, tbtype, isQuoteName)}, {ExpressionLambdaToSql(exp.Arguments[1], _tables, _selectColumnMap, tbtype, isQuoteName)})";
case "CompareTo": return $"strcmp({left}, {ExpressionLambdaToSql(exp.Arguments[0], _tables, _selectColumnMap, tbtype, isQuoteName)})";
}
throw new Exception($"MySqlExpression 未现实函数表达式 {exp} 解析");
}
if (exp.Object.Type.FullName == "System.Math") {
switch (exp.Method.Name) {
case "Abs": return $"abs({ExpressionLambdaToSql(exp.Arguments[0], _tables, _selectColumnMap, tbtype, isQuoteName)})";
case "Sign": return $"sign({ExpressionLambdaToSql(exp.Arguments[0], _tables, _selectColumnMap, tbtype, isQuoteName)})";
case "Floor": return $"floor({ExpressionLambdaToSql(exp.Arguments[0], _tables, _selectColumnMap, tbtype, isQuoteName)})";
case "Round":
if (exp.Arguments.Count > 1 && exp.Arguments[1].Type.FullName == "System.Int32") return $"round({ExpressionLambdaToSql(exp.Arguments[0], _tables, _selectColumnMap, tbtype, isQuoteName)}, {ExpressionLambdaToSql(exp.Arguments[1], _tables, _selectColumnMap, tbtype, isQuoteName)})";
return $"round({ExpressionLambdaToSql(exp.Arguments[0], _tables, _selectColumnMap, tbtype, isQuoteName)})";
case "Exp": return $"exp({ExpressionLambdaToSql(exp.Arguments[0], _tables, _selectColumnMap, tbtype, isQuoteName)})";
case "Log": return $"log({ExpressionLambdaToSql(exp.Arguments[0], _tables, _selectColumnMap, tbtype, isQuoteName)})";
case "Log10": return $"log10({ExpressionLambdaToSql(exp.Arguments[0], _tables, _selectColumnMap, tbtype, isQuoteName)})";
case "Pow": return $"pow({ExpressionLambdaToSql(exp.Arguments[0], _tables, _selectColumnMap, tbtype, isQuoteName)})";
case "Sqrt": return $"sqrt({ExpressionLambdaToSql(exp.Arguments[0], _tables, _selectColumnMap, tbtype, isQuoteName)})";
case "PI": return $"pi()";
case "Cos": return $"cos({ExpressionLambdaToSql(exp.Arguments[0], _tables, _selectColumnMap, tbtype, isQuoteName)})";
case "Sin": return $"sin({ExpressionLambdaToSql(exp.Arguments[0], _tables, _selectColumnMap, tbtype, isQuoteName)})";
case "Tan": return $"tan({ExpressionLambdaToSql(exp.Arguments[0], _tables, _selectColumnMap, tbtype, isQuoteName)})";
case "Acos": return $"acos({ExpressionLambdaToSql(exp.Arguments[0], _tables, _selectColumnMap, tbtype, isQuoteName)})";
case "Asin": return $"asin({ExpressionLambdaToSql(exp.Arguments[0], _tables, _selectColumnMap, tbtype, isQuoteName)})";
case "Atan": return $"atan({ExpressionLambdaToSql(exp.Arguments[0], _tables, _selectColumnMap, tbtype, isQuoteName)})";
case "Atan2": return $"atan2({ExpressionLambdaToSql(exp.Arguments[0], _tables, _selectColumnMap, tbtype, isQuoteName)}, {ExpressionLambdaToSql(exp.Arguments[1], _tables, _selectColumnMap, tbtype, isQuoteName)})";
case "Truncate": return $"truncate({ExpressionLambdaToSql(exp.Arguments[0], _tables, _selectColumnMap, tbtype, isQuoteName)}, 0)";
}
internal override string ExpressionLambdaToSqlCallMath(MethodCallExpression exp, List<SelectTableInfo> _tables, List<SelectColumnInfo> _selectColumnMap, SelectTableInfoType tbtype, bool isQuoteName) {
switch (exp.Method.Name) {
case "Abs": return $"abs({ExpressionLambdaToSql(exp.Arguments[0], _tables, _selectColumnMap, tbtype, isQuoteName)})";
case "Sign": return $"sign({ExpressionLambdaToSql(exp.Arguments[0], _tables, _selectColumnMap, tbtype, isQuoteName)})";
case "Floor": return $"floor({ExpressionLambdaToSql(exp.Arguments[0], _tables, _selectColumnMap, tbtype, isQuoteName)})";
case "Ceiling": return $"ceiling({ExpressionLambdaToSql(exp.Arguments[0], _tables, _selectColumnMap, tbtype, isQuoteName)})";
case "Round":
if (exp.Arguments.Count > 1 && exp.Arguments[1].Type.FullName == "System.Int32") return $"round({ExpressionLambdaToSql(exp.Arguments[0], _tables, _selectColumnMap, tbtype, isQuoteName)}, {ExpressionLambdaToSql(exp.Arguments[1], _tables, _selectColumnMap, tbtype, isQuoteName)})";
return $"round({ExpressionLambdaToSql(exp.Arguments[0], _tables, _selectColumnMap, tbtype, isQuoteName)})";
case "Exp": return $"exp({ExpressionLambdaToSql(exp.Arguments[0], _tables, _selectColumnMap, tbtype, isQuoteName)})";
case "Log": return $"log({ExpressionLambdaToSql(exp.Arguments[0], _tables, _selectColumnMap, tbtype, isQuoteName)})";
case "Log10": return $"log10({ExpressionLambdaToSql(exp.Arguments[0], _tables, _selectColumnMap, tbtype, isQuoteName)})";
case "Pow": return $"pow({ExpressionLambdaToSql(exp.Arguments[0], _tables, _selectColumnMap, tbtype, isQuoteName)}, {ExpressionLambdaToSql(exp.Arguments[1], _tables, _selectColumnMap, tbtype, isQuoteName)})";
case "Sqrt": return $"sqrt({ExpressionLambdaToSql(exp.Arguments[0], _tables, _selectColumnMap, tbtype, isQuoteName)})";
case "Cos": return $"cos({ExpressionLambdaToSql(exp.Arguments[0], _tables, _selectColumnMap, tbtype, isQuoteName)})";
case "Sin": return $"sin({ExpressionLambdaToSql(exp.Arguments[0], _tables, _selectColumnMap, tbtype, isQuoteName)})";
case "Tan": return $"tan({ExpressionLambdaToSql(exp.Arguments[0], _tables, _selectColumnMap, tbtype, isQuoteName)})";
case "Acos": return $"acos({ExpressionLambdaToSql(exp.Arguments[0], _tables, _selectColumnMap, tbtype, isQuoteName)})";
case "Asin": return $"asin({ExpressionLambdaToSql(exp.Arguments[0], _tables, _selectColumnMap, tbtype, isQuoteName)})";
case "Atan": return $"atan({ExpressionLambdaToSql(exp.Arguments[0], _tables, _selectColumnMap, tbtype, isQuoteName)})";
case "Atan2": return $"atan2({ExpressionLambdaToSql(exp.Arguments[0], _tables, _selectColumnMap, tbtype, isQuoteName)}, {ExpressionLambdaToSql(exp.Arguments[1], _tables, _selectColumnMap, tbtype, isQuoteName)})";
case "Truncate": return $"truncate({ExpressionLambdaToSql(exp.Arguments[0], _tables, _selectColumnMap, tbtype, isQuoteName)}, 0)";
}
throw new Exception($"MySqlExpression 未现实函数表达式 {exp} 解析");
}
//dayofweek = DayOfWeek
//dayofmonth = Day
//dayofyear = DayOfYear
//month = Month
//year = Year
//hour = Hour
//minute = Minute
//second = Second
/*
* date_add(date,interval expr type)
date_sub(date,interval expr type)
adddate(date,interval expr type)
subdate(date,interval expr type)
对日期时间进行加减法运算
(adddate()和subdate()是date_add()和date_sub()的同义词,也
可以用运算符+和-而不是函数
date是一个datetime或date值,expr对date进行加减法的一个表
达式字符串type指明表达式expr应该如何被解释
 [type值 含义 期望的expr格式]:
 second 秒 seconds
 minute 分钟 minutes
 hour 时间 hours
 day 天 days
 month 月 months
 year 年 years
 minute_second 分钟和秒 "minutes:seconds"
 hour_minute 小时和分钟 "hours:minutes"
 day_hour 天和小时 "days hours"
 year_month 年和月 "years-months"
 hour_second 小时, 分钟, "hours:minutes:seconds"
 day_minute 天, 小时, 分钟 "days hours:minutes"
 day_second 天, 小时, 分钟, 秒 "days
hours:minutes:seconds"
 expr中允许任何标点做分隔符,如果所有是date值时结果是一个
date值,否则结果是一个datetime值)
 如果type关键词不完整,则mysql从右端取值,day_second因为缺
少小时分钟等于minute_second)
 如果增加month、year_month或year,天数大于结果月份的最大天
数则使用最大天数)
mysql> select "1997-12-31 23:59:59" + interval 1 second;
  -> 1998-01-01 00:00:00
mysql> select interval 1 day + "1997-12-31";
  -> 1998-01-01
mysql> select "1998-01-01" - interval 1 second;
  -> 1997-12-31 23:59:59
mysql> select date_add("1997-12-31 23:59:59",interval 1
second);
  -> 1998-01-01 00:00:00
mysql> select date_add("1997-12-31 23:59:59",interval 1
day);
  -> 1998-01-01 23:59:59
mysql> select date_add("1997-12-31 23:59:59",interval
"1:1" minute_second);
  -> 1998-01-01 00:01:00
mysql> select date_sub("1998-01-01 00:00:00",interval "1
1:1:1" day_second);
  -> 1997-12-30 22:58:59
mysql> select date_add("1998-01-01 00:00:00", interval "-1
10" day_hour);
  -> 1997-12-30 14:00:00
mysql> select date_sub("1998-01-02", interval 31 day);
  -> 1997-12-02
mysql> select extract(year from "1999-07-02");
  -> 1999
mysql> select extract(year_month from "1999-07-02
01:02:03");
  -> 199907
mysql> select extract(day_minute from "1999-07-02
01:02:03");
  -> 20102
*/
//convert
var xxx = DateTime.Now.ToString("");
internal override string ExpressionLambdaToSqlCallDateTime(MethodCallExpression exp, List<SelectTableInfo> _tables, List<SelectColumnInfo> _selectColumnMap, SelectTableInfoType tbtype, bool isQuoteName) {
var left = ExpressionLambdaToSql(exp.Object, _tables, _selectColumnMap, tbtype, isQuoteName);
var args1 = ExpressionLambdaToSql(exp.Arguments[0], _tables, _selectColumnMap, tbtype, isQuoteName);
switch (exp.Method.Name) {
case "Add": return $"date_add({left}, interval (time_to_sec({args1}) * 1000000 + extract(microsecond from {args1})) microsecond)";
case "AddDays": return $"date_add({left}, interval {args1} day)";
case "AddHours": return $"date_add({left}, interval {args1} hour)";
case "AddMilliseconds": return $"date_add({left}, interval {args1} microsecond)";
case "AddMinutes": return $"date_add({left}, interval {args1} minute)";
case "AddMonths": return $"date_add({left}, interval {args1} month)";
case "AddSeconds": return $"date_add({left}, interval {args1} second)";
case "AddTicks": return $"date_add({left}, interval ({args1}) / 10 microsecond)";
case "AddYears": return $"date_add({left}, interval {args1} year)";
case "Subtract":
if (exp.Arguments[0].Type.FullName == "System.DateTime" || exp.Arguments[0].Type.GenericTypeArguments.FirstOrDefault()?.FullName == "System.DateTime")
return $"({left} - {args1})";
if (exp.Arguments[0].Type.FullName == "System.TimeSpan" || exp.Arguments[0].Type.GenericTypeArguments.FirstOrDefault()?.FullName == "System.TimeSpan")
return $"date_sub({left}, interval (time_to_sec({args1}) * 1000000 + extract(microsecond from {args1})) microsecond)";
break;
}
throw new Exception($"MySqlExpression 未现实函数表达式 {exp} 解析");
}
internal override string ExpressionLambdaToSqlCallTimeSpan(MethodCallExpression exp, List<SelectTableInfo> _tables, List<SelectColumnInfo> _selectColumnMap, SelectTableInfoType tbtype, bool isQuoteName) {
var left = ExpressionLambdaToSql(exp.Object, _tables, _selectColumnMap, tbtype, isQuoteName);
var args1 = ExpressionLambdaToSql(exp.Arguments[0], _tables, _selectColumnMap, tbtype, isQuoteName);
switch (exp.Method.Name) {
case "Add": return $"(date_add('1970-1-1', interval (time_to_sec({left}) * 1000000 + extract(microsecond from {left}) + time_to_sec({args1}) * 1000000 + extract(microsecond from {args1})) microsecond)) microsecond) - date_add('1970-1-1', interval 0 microsecond) second))";
case "Subtract": return $"(date_add('1970-1-1', interval (time_to_sec({left}) * 1000000 + extract(microsecond from {left}) - time_to_sec({args1}) * 1000000 - extract(microsecond from {args1})) microsecond) - date_add('1970-1-1', interval 0 second))";
}
throw new Exception($"MySqlExpression 未现实函数表达式 {exp} 解析");
}
}

View File

@ -44,5 +44,6 @@ namespace FreeSql.MySql {
internal override string QuoteSqlName(string name) => $"`{name.Trim('`').Replace(".", "`.`")}`";
internal override string QuoteParamterName(string name) => $"?{name}";
internal override string IsNull(string sql, object value) => $"ifnull({sql}, {value})";
internal override string StringConcat(string left, string right, Type leftType, Type rightType) => $"concat({left}, {right})";
}
}

View File

@ -10,7 +10,10 @@ namespace FreeSql.PostgreSQL.Curd {
class PostgreSQLSelect<T1> : FreeSql.Internal.CommonProvider.Select1Provider<T1> where T1 : class {
internal static string ToSqlStatic(CommonUtils _commonUtils, string _select, string field, StringBuilder _join, StringBuilder _where, string _groupby, string _having, string _orderby, int _skip, int _limit, List<SelectTableInfo> _tables) {
internal static string ToSqlStatic(CommonUtils _commonUtils, string _select, string field, StringBuilder _join, StringBuilder _where, string _groupby, string _having, string _orderby, int _skip, int _limit, List<SelectTableInfo> _tables, IFreeSql _orm) {
if (_orm.CodeFirst.IsAutoSyncStructure)
_orm.CodeFirst.SyncStructure(_tables.Select(a => a.Table.Type).ToArray());
var sb = new StringBuilder();
sb.Append(_select).Append(field).Append(" \r\nFROM ");
var tbsjoin = _tables.Where(a => a.Type != SelectTableInfoType.From).ToArray();
@ -75,42 +78,42 @@ namespace FreeSql.PostgreSQL.Curd {
public override ISelect<T1, T2, T3, T4, T5, T6, T7, T8> From<T2, T3, T4, T5, T6, T7, T8>(Expression<Func<ISelectFromExpression<T1>, T2, T3, T4, T5, T6, T7, T8, ISelectFromExpression<T1>>> exp) { this.InternalFrom(exp?.Body); var ret = new PostgreSQLSelect<T1, T2, T3, T4, T5, T6, T7, T8>(_orm, _commonUtils, _commonExpression, null); PostgreSQLSelect<T1>.CopyData(this, ret); return ret; }
public override ISelect<T1, T2, T3, T4, T5, T6, T7, T8, T9> From<T2, T3, T4, T5, T6, T7, T8, T9>(Expression<Func<ISelectFromExpression<T1>, T2, T3, T4, T5, T6, T7, T8, T9, ISelectFromExpression<T1>>> exp) { this.InternalFrom(exp?.Body); var ret = new PostgreSQLSelect<T1, T2, T3, T4, T5, T6, T7, T8, T9>(_orm, _commonUtils, _commonExpression, null); PostgreSQLSelect<T1>.CopyData(this, ret); return ret; }
public override ISelect<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10> From<T2, T3, T4, T5, T6, T7, T8, T9, T10>(Expression<Func<ISelectFromExpression<T1>, T2, T3, T4, T5, T6, T7, T8, T9, T10, ISelectFromExpression<T1>>> exp) { this.InternalFrom(exp?.Body); var ret = new PostgreSQLSelect<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10>(_orm, _commonUtils, _commonExpression, null); PostgreSQLSelect<T1>.CopyData(this, ret); return ret; }
public override string ToSql(string field = null) => ToSqlStatic(_commonUtils, _select, field ?? this.GetAllField().field, _join, _where, _groupby, _having, _orderby, _skip, _limit, _tables);
public override string ToSql(string field = null) => ToSqlStatic(_commonUtils, _select, field ?? this.GetAllField().field, _join, _where, _groupby, _having, _orderby, _skip, _limit, _tables, _orm);
}
class PostgreSQLSelect<T1, T2> : FreeSql.Internal.CommonProvider.Select2Provider<T1, T2> where T1 : class where T2 : class {
public PostgreSQLSelect(IFreeSql orm, CommonUtils commonUtils, CommonExpression commonExpression, object dywhere) : base(orm, commonUtils, commonExpression, dywhere) { }
public override string ToSql(string field = null) => PostgreSQLSelect<T1>.ToSqlStatic(_commonUtils, _select, field ?? this.GetAllField().field, _join, _where, _groupby, _having, _orderby, _skip, _limit, _tables);
public override string ToSql(string field = null) => PostgreSQLSelect<T1>.ToSqlStatic(_commonUtils, _select, field ?? this.GetAllField().field, _join, _where, _groupby, _having, _orderby, _skip, _limit, _tables, _orm);
}
class PostgreSQLSelect<T1, T2, T3> : FreeSql.Internal.CommonProvider.Select3Provider<T1, T2, T3> where T1 : class where T2 : class where T3 : class {
public PostgreSQLSelect(IFreeSql orm, CommonUtils commonUtils, CommonExpression commonExpression, object dywhere) : base(orm, commonUtils, commonExpression, dywhere) { }
public override string ToSql(string field = null) => PostgreSQLSelect<T1>.ToSqlStatic(_commonUtils, _select, field ?? this.GetAllField().field, _join, _where, _groupby, _having, _orderby, _skip, _limit, _tables);
public override string ToSql(string field = null) => PostgreSQLSelect<T1>.ToSqlStatic(_commonUtils, _select, field ?? this.GetAllField().field, _join, _where, _groupby, _having, _orderby, _skip, _limit, _tables, _orm);
}
class PostgreSQLSelect<T1, T2, T3, T4> : FreeSql.Internal.CommonProvider.Select4Provider<T1, T2, T3, T4> where T1 : class where T2 : class where T3 : class where T4 : class {
public PostgreSQLSelect(IFreeSql orm, CommonUtils commonUtils, CommonExpression commonExpression, object dywhere) : base(orm, commonUtils, commonExpression, dywhere) { }
public override string ToSql(string field = null) => PostgreSQLSelect<T1>.ToSqlStatic(_commonUtils, _select, field ?? this.GetAllField().field, _join, _where, _groupby, _having, _orderby, _skip, _limit, _tables);
public override string ToSql(string field = null) => PostgreSQLSelect<T1>.ToSqlStatic(_commonUtils, _select, field ?? this.GetAllField().field, _join, _where, _groupby, _having, _orderby, _skip, _limit, _tables, _orm);
}
class PostgreSQLSelect<T1, T2, T3, T4, T5> : FreeSql.Internal.CommonProvider.Select5Provider<T1, T2, T3, T4, T5> where T1 : class where T2 : class where T3 : class where T4 : class where T5 : class {
public PostgreSQLSelect(IFreeSql orm, CommonUtils commonUtils, CommonExpression commonExpression, object dywhere) : base(orm, commonUtils, commonExpression, dywhere) { }
public override string ToSql(string field = null) => PostgreSQLSelect<T1>.ToSqlStatic(_commonUtils, _select, field ?? this.GetAllField().field, _join, _where, _groupby, _having, _orderby, _skip, _limit, _tables);
public override string ToSql(string field = null) => PostgreSQLSelect<T1>.ToSqlStatic(_commonUtils, _select, field ?? this.GetAllField().field, _join, _where, _groupby, _having, _orderby, _skip, _limit, _tables, _orm);
}
class PostgreSQLSelect<T1, T2, T3, T4, T5, T6> : FreeSql.Internal.CommonProvider.Select6Provider<T1, T2, T3, T4, T5, T6> where T1 : class where T2 : class where T3 : class where T4 : class where T5 : class where T6 : class {
public PostgreSQLSelect(IFreeSql orm, CommonUtils commonUtils, CommonExpression commonExpression, object dywhere) : base(orm, commonUtils, commonExpression, dywhere) { }
public override string ToSql(string field = null) => PostgreSQLSelect<T1>.ToSqlStatic(_commonUtils, _select, field ?? this.GetAllField().field, _join, _where, _groupby, _having, _orderby, _skip, _limit, _tables);
public override string ToSql(string field = null) => PostgreSQLSelect<T1>.ToSqlStatic(_commonUtils, _select, field ?? this.GetAllField().field, _join, _where, _groupby, _having, _orderby, _skip, _limit, _tables, _orm);
}
class PostgreSQLSelect<T1, T2, T3, T4, T5, T6, T7> : FreeSql.Internal.CommonProvider.Select7Provider<T1, T2, T3, T4, T5, T6, T7> where T1 : class where T2 : class where T3 : class where T4 : class where T5 : class where T6 : class where T7 : class {
public PostgreSQLSelect(IFreeSql orm, CommonUtils commonUtils, CommonExpression commonExpression, object dywhere) : base(orm, commonUtils, commonExpression, dywhere) { }
public override string ToSql(string field = null) => PostgreSQLSelect<T1>.ToSqlStatic(_commonUtils, _select, field ?? this.GetAllField().field, _join, _where, _groupby, _having, _orderby, _skip, _limit, _tables);
public override string ToSql(string field = null) => PostgreSQLSelect<T1>.ToSqlStatic(_commonUtils, _select, field ?? this.GetAllField().field, _join, _where, _groupby, _having, _orderby, _skip, _limit, _tables, _orm);
}
class PostgreSQLSelect<T1, T2, T3, T4, T5, T6, T7, T8> : FreeSql.Internal.CommonProvider.Select8Provider<T1, T2, T3, T4, T5, T6, T7, T8> where T1 : class where T2 : class where T3 : class where T4 : class where T5 : class where T6 : class where T7 : class where T8 : class {
public PostgreSQLSelect(IFreeSql orm, CommonUtils commonUtils, CommonExpression commonExpression, object dywhere) : base(orm, commonUtils, commonExpression, dywhere) { }
public override string ToSql(string field = null) => PostgreSQLSelect<T1>.ToSqlStatic(_commonUtils, _select, field ?? this.GetAllField().field, _join, _where, _groupby, _having, _orderby, _skip, _limit, _tables);
public override string ToSql(string field = null) => PostgreSQLSelect<T1>.ToSqlStatic(_commonUtils, _select, field ?? this.GetAllField().field, _join, _where, _groupby, _having, _orderby, _skip, _limit, _tables, _orm);
}
class PostgreSQLSelect<T1, T2, T3, T4, T5, T6, T7, T8, T9> : FreeSql.Internal.CommonProvider.Select9Provider<T1, T2, T3, T4, T5, T6, T7, T8, T9> where T1 : class where T2 : class where T3 : class where T4 : class where T5 : class where T6 : class where T7 : class where T8 : class where T9 : class {
public PostgreSQLSelect(IFreeSql orm, CommonUtils commonUtils, CommonExpression commonExpression, object dywhere) : base(orm, commonUtils, commonExpression, dywhere) { }
public override string ToSql(string field = null) => PostgreSQLSelect<T1>.ToSqlStatic(_commonUtils, _select, field ?? this.GetAllField().field, _join, _where, _groupby, _having, _orderby, _skip, _limit, _tables);
public override string ToSql(string field = null) => PostgreSQLSelect<T1>.ToSqlStatic(_commonUtils, _select, field ?? this.GetAllField().field, _join, _where, _groupby, _having, _orderby, _skip, _limit, _tables, _orm);
}
class PostgreSQLSelect<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10> : FreeSql.Internal.CommonProvider.Select10Provider<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10> where T1 : class where T2 : class where T3 : class where T4 : class where T5 : class where T6 : class where T7 : class where T8 : class where T9 : class where T10 : class {
public PostgreSQLSelect(IFreeSql orm, CommonUtils commonUtils, CommonExpression commonExpression, object dywhere) : base(orm, commonUtils, commonExpression, dywhere) { }
public override string ToSql(string field = null) => PostgreSQLSelect<T1>.ToSqlStatic(_commonUtils, _select, field ?? this.GetAllField().field, _join, _where, _groupby, _having, _orderby, _skip, _limit, _tables);
public override string ToSql(string field = null) => PostgreSQLSelect<T1>.ToSqlStatic(_commonUtils, _select, field ?? this.GetAllField().field, _join, _where, _groupby, _having, _orderby, _skip, _limit, _tables, _orm);
}
}

View File

@ -23,6 +23,7 @@ namespace FreeSql.PostgreSQL {
}
}
}
static DateTime dt1970 = new DateTime(1970, 1, 1);
public override object AddslashesProcessParam(object param) {
if (param == null) return "NULL";
if (param is bool || param is bool?)
@ -31,12 +32,16 @@ namespace FreeSql.PostgreSQL {
return string.Concat("'", param.ToString().Replace("'", "''"), "'");
else if (decimal.TryParse(string.Concat(param), out var trydec))
return param;
else if (param is DateTime) {
DateTime dt = (DateTime)param;
return string.Concat("'", dt.ToString("yyyy-MM-dd HH:mm:ss.ffffff"), "'");
} else if (param is DateTime?) {
DateTime? dt = param as DateTime?;
return string.Concat("'", dt.Value.ToString("yyyy-MM-dd HH:mm:ss.ffffff"), "'");
else if (param is DateTime)
return string.Concat("'", ((DateTime)param).ToString("yyyy-MM-dd HH:mm:ss.ffffff"), "'");
else if (param is DateTime?)
return string.Concat("'", (param as DateTime?).Value.ToString("yyyy-MM-dd HH:mm:ss.ffffff"), "'");
else if (param is TimeSpan) {
var ts = (TimeSpan)param;
return string.Concat("'", ts.Ticks > 0 ? "" : "-", ts.TotalHours, dt1970.AddTicks(Math.Abs(ts.Ticks)).ToString(":mm:ss.ffffff"), "'");
} else if (param is TimeSpan) {
var ts = (param as TimeSpan?).Value;
return string.Concat("'", ts.Ticks > 0 ? "" : "-", ts.TotalHours, dt1970.AddTicks(Math.Abs(ts.Ticks)).ToString(":mm:ss.ffffff"), "'");
} else if (param is IEnumerable) {
var sb = new StringBuilder();
var ie = param as IEnumerable;

View File

@ -100,8 +100,8 @@ namespace FreeSql.PostgreSQL {
if (enumType == null && type.FullName.StartsWith("System.Nullable`1[") && type.GenericTypeArguments.Length == 1 && type.GenericTypeArguments.First().IsEnum) enumType = type.GenericTypeArguments.First();
if (enumType != null) {
var newItem = enumType.GetCustomAttributes(typeof(FlagsAttribute), false).Any() ?
(NpgsqlDbType.Bigint, "int8", $"int8{(type.IsEnum ? " NOT NULL" : "")}", false, type.IsEnum ? false : true) :
(NpgsqlDbType.Integer, "int4", $"int4{(type.IsEnum ? " NOT NULL" : "")}", false, type.IsEnum ? false : true);
(NpgsqlDbType.Varchar, "varchar", $"varchar(32){(type.IsEnum ? " NOT NULL" : "")}", false, type.IsEnum ? false : true) :
(NpgsqlDbType.Varchar, "varchar", $"varchar(32){(type.IsEnum ? " NOT NULL" : "")}", false, type.IsEnum ? false : true);
if (_dicCsToDb.ContainsKey(type.FullName) == false) {
lock (_dicCsToDbLock) {
if (_dicCsToDb.ContainsKey(type.FullName) == false)
@ -116,6 +116,7 @@ namespace FreeSql.PostgreSQL {
public string GetComparisonDDLStatements<TEntity>() => this.GetComparisonDDLStatements(typeof(TEntity));
public string GetComparisonDDLStatements(params Type[] entityTypes) {
var sb = new StringBuilder();
var seqcols = new List<(ColumnInfo, string[], bool)>(); //序列
foreach (var entityType in entityTypes) {
if (sb.Length > 0) sb.Append("\r\n");
var tb = _commonUtils.GetTableByEntity(entityType);
@ -134,13 +135,10 @@ namespace FreeSql.PostgreSQL {
} else {
//创建表
var seqcols = new List<ColumnInfo>();
sb.Append("CREATE TABLE IF NOT EXISTS ").Append(_commonUtils.QuoteSqlName($"{tbname[0]}.{tbname[1]}")).Append(" (");
foreach (var tbcol in tb.Columns.Values) {
sb.Append(" \r\n ").Append(_commonUtils.QuoteSqlName(tbcol.Attribute.Name)).Append(" ");
sb.Append(tbcol.Attribute.DbType.ToUpper());
if (tbcol.Attribute.IsIdentity && tbcol.Attribute.DbType.IndexOf("serial", StringComparison.CurrentCultureIgnoreCase) == -1) seqcols.Add(tbcol);
sb.Append(",");
sb.Append(" \r\n ").Append(_commonUtils.QuoteSqlName(tbcol.Attribute.Name)).Append(" ").Append(tbcol.Attribute.DbType.ToUpper()).Append(",");
if (tbcol.Attribute.IsIdentity) seqcols.Add((tbcol, tbname, true));
}
if (tb.Primarys.Any() == false)
sb.Remove(sb.Length - 1, 1);
@ -187,38 +185,54 @@ where ns.nspname = {0} and c.relname = {1}".FormatPostgreSQL(isRenameTable ? tbo
if (addcols.TryGetValue(column, out var trycol)) {
if (trycol.Attribute.DbType.ToLower().StartsWith(sqlType.ToLower()) == false ||
(trycol.Attribute.DbType.IndexOf("NOT NULL") == -1) != is_nullable ||
trycol.Attribute.IsIdentity != is_identity) {
sb.Append("ALTER TABLE ").Append(_commonUtils.QuoteSqlName($"{tbname[0]}.{tbname[1]}")).Append(" ALTER COLUMN ").Append(_commonUtils.QuoteSqlName(column)).Append(" TYPE ").Append(trycol.Attribute.DbType.ToUpper());
if (trycol.Attribute.IsIdentity) sb.Append(" AUTO_INCREMENT");
sb.Append(";\r\n");
(trycol.Attribute.DbType.IndexOf("NOT NULL") == -1) != is_nullable) {
sb.Append("ALTER TABLE ").Append(_commonUtils.QuoteSqlName($"{tbname[0]}.{tbname[1]}")).Append(" ALTER COLUMN ").Append(_commonUtils.QuoteSqlName(column)).Append(" TYPE ").Append(trycol.Attribute.DbType.ToUpper()).Append(";\r\n");
}
if (trycol.Attribute.IsIdentity != is_identity) seqcols.Add((trycol, tbname, trycol.Attribute.IsIdentity));
addcols.Remove(column);
} else
} else {
if (trycol.Attribute.IsIdentity != is_identity) seqcols.Add((trycol, tbname, trycol.Attribute.IsIdentity));
surplus.Add(column, true); //记录剩余字段
}
}
foreach (var addcol in addcols.Values) {
if (string.IsNullOrEmpty(addcol.Attribute.OldName) == false && surplus.ContainsKey(addcol.Attribute.OldName)) { //修改列名
sb.Append("ALTER TABLE ").Append(_commonUtils.QuoteSqlName($"{tbname[0]}.{tbname[1]}")).Append(" RENAME COLUMN ").Append(_commonUtils.QuoteSqlName(addcol.Attribute.OldName)).Append(" TO ").Append(_commonUtils.QuoteSqlName(addcol.Attribute.Name)).Append(";\r\n");
if (addcol.Attribute.IsIdentity) sb.Append(" AUTO_INCREMENT");
sb.Append(";\r\n");
} else { //添加列
sb.Append("ALTER TABLE ").Append(_commonUtils.QuoteSqlName($"{tbname[0]}.{tbname[1]}")).Append(" ADD COLUMN ").Append(_commonUtils.QuoteSqlName(addcol.Attribute.Name)).Append(" ").Append(addcol.Attribute.DbType.ToUpper());
if (addcol.Attribute.IsIdentity) sb.Append(" AUTO_INCREMENT");
sb.Append(";\r\n");
sb.Append("ALTER TABLE ").Append(_commonUtils.QuoteSqlName($"{tbname[0]}.{tbname[1]}")).Append(" ADD COLUMN ").Append(_commonUtils.QuoteSqlName(addcol.Attribute.Name)).Append(" ").Append(addcol.Attribute.DbType.ToUpper()).Append(";\r\n");
}
}
}
foreach(var seqcol in seqcols) {
var tbname = seqcol.Item2;
var seqname = Utils.GetCsName($"{tbname[0]}.{tbname[1]}_{seqcol.Item1.Attribute.Name}_sequence_name");
var tbname2 = _commonUtils.QuoteSqlName($"{tbname[0]}.{tbname[1]}");
var colname2 = _commonUtils.QuoteSqlName(seqcol.Item1.Attribute.Name);
sb.Append("ALTER TABLE ").Append(tbname2).Append(" ALTER COLUMN ").Append(colname2).Append(" SET DEFAULT null;");
sb.Append("DROP SEQUENCE IF EXISTS ").Append(seqname).Append(";");
if (seqcol.Item3) {
sb.Append("CREATE SEQUENCE ").Append(seqname).Append(" START WITH (select coalesce(max(").Append(colname2).Append("),1) from ").Append(tbname2).Append(");");
sb.Append("ALTER TABLE ").Append(tbname2).Append(" ALTER COLUMN ").Append(colname2).Append(" SET DEFAULT nextval('").Append(seqname).Append("'::regclass);");
}
}
return sb.Length == 0 ? null : sb.ToString();
}
Dictionary<string, bool> dicSyced = new Dictionary<string, bool>();
public bool SyncStructure<TEntity>() => this.SyncStructure(typeof(TEntity));
public bool SyncStructure(params Type[] entityTypes) {
var ddl = this.GetComparisonDDLStatements(entityTypes);
if (string.IsNullOrEmpty(ddl)) return true;
if (entityTypes == null) return true;
var syncTypes = entityTypes.Where(a => dicSyced.ContainsKey(a.FullName) == false).ToArray();
if (syncTypes.Any() == false) return true;
var ddl = this.GetComparisonDDLStatements(syncTypes);
if (string.IsNullOrEmpty(ddl)) {
foreach (var syncType in syncTypes) dicSyced.Add(syncType.FullName, true);
return true;
}
try {
return _orm.Ado.ExecuteNonQuery(CommandType.Text, ddl) > 0;
var affrows = _orm.Ado.ExecuteNonQuery(CommandType.Text, ddl);
foreach (var syncType in syncTypes) dicSyced.Add(syncType.FullName, true);
return affrows > 0;
} catch {
return false;
}

View File

@ -2,6 +2,7 @@
using FreeSql.Internal.Model;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Linq.Expressions;
namespace FreeSql.PostgreSQL {
@ -9,151 +10,176 @@ namespace FreeSql.PostgreSQL {
public PostgreSQLExpression(CommonUtils common) : base(common) { }
internal override string ExpressionLambdaToSqlCall(MethodCallExpression exp, List<SelectTableInfo> _tables, List<SelectColumnInfo> _selectColumnMap, SelectTableInfoType tbtype, bool isQuoteName) {
if (exp.Object.Type.FullName == "System.String") {
var left = ExpressionLambdaToSql(exp.Object, _tables, _selectColumnMap, tbtype, isQuoteName);
switch (exp.Method.Name) {
case "StartsWith":
case "EndsWith":
case "Contains":
var args0Value = ExpressionLambdaToSql(exp.Arguments[0], _tables, _selectColumnMap, tbtype, isQuoteName);
if (args0Value == "NULL") return $"({left}) IS NULL";
if (exp.Method.Name == "StartsWith") return $"({left}) LIKE {(args0Value.StartsWith("'") ? args0Value.Insert(1, "%") : $"concat('%', {args0Value})")}";
if (exp.Method.Name == "EndsWith") return $"({left}) LIKE {(args0Value.EndsWith("'") ? args0Value.Insert(args0Value.Length - 1, "%") : $"concat({args0Value}, '%')")}";
if (args0Value.StartsWith("'") && args0Value.EndsWith("'")) return $"({left}) LIKE {args0Value.Insert(1, "%").Insert(args0Value.Length, "%")}";
return $"({left}) like concat('%', {args0Value}, '%')";
case "ToLower": return $"lower({left})";
case "ToUpper": return $"upper({left})";
case "Substring": return $"substr({left}, {ExpressionLambdaToSql(exp.Arguments[0], _tables, _selectColumnMap, tbtype, isQuoteName)} + 1, {ExpressionLambdaToSql(exp.Arguments[1], _tables, _selectColumnMap, tbtype, isQuoteName)})";
case "Length": return $"char_length({left})";
case "IndexOf":
var indexOfFindStr = ExpressionLambdaToSql(exp.Arguments[0], _tables, _selectColumnMap, tbtype, isQuoteName);
if (exp.Arguments.Count > 1 && exp.Arguments[1].Type.FullName == "System.Int32") return $"(locate({left}, {indexOfFindStr}, ParseLambdaToSql(exp.Arguments[1], _tables, _selectColumnMap, tbtype, isQuoteName) + 1) - 1)";
return $"(locate({left}, {indexOfFindStr}) - 1)";
case "PadLeft": return $"lpad({left}, {ExpressionLambdaToSql(exp.Arguments[0], _tables, _selectColumnMap, tbtype, isQuoteName)}, {ExpressionLambdaToSql(exp.Arguments[1], _tables, _selectColumnMap, tbtype, isQuoteName)})";
case "PadRight": return $"rpad({left}, {ExpressionLambdaToSql(exp.Arguments[0], _tables, _selectColumnMap, tbtype, isQuoteName)}, {ExpressionLambdaToSql(exp.Arguments[1], _tables, _selectColumnMap, tbtype, isQuoteName)})";
case "Trim":
case "TrimStart":
case "TrimEnd":
if (exp.Arguments.Count == 0) {
if (exp.Method.Name == "Trim") return $"trim({left})";
if (exp.Method.Name == "TrimStart") return $"ltrim({left})";
if (exp.Method.Name == "TrimStart") return $"rtrim({left})";
}
foreach (var argsTrim01 in exp.Arguments) {
if (exp.Method.Name == "Trim") left = $"trim({ExpressionLambdaToSql(argsTrim01, _tables, _selectColumnMap, tbtype, isQuoteName)} from {left})";
if (exp.Method.Name == "TrimStart") left = $"trim(leading {ExpressionLambdaToSql(argsTrim01, _tables, _selectColumnMap, tbtype, isQuoteName)} from {left})";
if (exp.Method.Name == "TrimStart") left = $"trim(trailing {ExpressionLambdaToSql(argsTrim01, _tables, _selectColumnMap, tbtype, isQuoteName)} from {left})";
}
return left;
case "Replace": return $"replace({left}, {ExpressionLambdaToSql(exp.Arguments[0], _tables, _selectColumnMap, tbtype, isQuoteName)}, {ExpressionLambdaToSql(exp.Arguments[1], _tables, _selectColumnMap, tbtype, isQuoteName)})";
case "CompareTo": return $"strcmp({left}, {ExpressionLambdaToSql(exp.Arguments[0], _tables, _selectColumnMap, tbtype, isQuoteName)})";
}
internal override string ExpressionLambdaToSqlMemberAccessString(MemberExpression exp, List<SelectTableInfo> _tables, List<SelectColumnInfo> _selectColumnMap, SelectTableInfoType tbtype, bool isQuoteName) {
var left = ExpressionLambdaToSql(exp.Expression, _tables, _selectColumnMap, tbtype, isQuoteName);
switch (exp.Member.Name) {
case "Length": return $"char_length({left})";
}
throw new Exception($"PostgreSQLExpression 未现实函数表达式 {exp} 解析");
}
if (exp.Object.Type.FullName == "System.Math") {
switch (exp.Method.Name) {
case "Abs": return $"abs({ExpressionLambdaToSql(exp.Arguments[0], _tables, _selectColumnMap, tbtype, isQuoteName)})";
case "Sign": return $"sign({ExpressionLambdaToSql(exp.Arguments[0], _tables, _selectColumnMap, tbtype, isQuoteName)})";
case "Floor": return $"floor({ExpressionLambdaToSql(exp.Arguments[0], _tables, _selectColumnMap, tbtype, isQuoteName)})";
case "Round":
if (exp.Arguments.Count > 1 && exp.Arguments[1].Type.FullName == "System.Int32") return $"round({ExpressionLambdaToSql(exp.Arguments[0], _tables, _selectColumnMap, tbtype, isQuoteName)}, {ExpressionLambdaToSql(exp.Arguments[1], _tables, _selectColumnMap, tbtype, isQuoteName)})";
return $"round({ExpressionLambdaToSql(exp.Arguments[0], _tables, _selectColumnMap, tbtype, isQuoteName)})";
case "Exp": return $"exp({ExpressionLambdaToSql(exp.Arguments[0], _tables, _selectColumnMap, tbtype, isQuoteName)})";
case "Log": return $"log({ExpressionLambdaToSql(exp.Arguments[0], _tables, _selectColumnMap, tbtype, isQuoteName)})";
case "Log10": return $"log10({ExpressionLambdaToSql(exp.Arguments[0], _tables, _selectColumnMap, tbtype, isQuoteName)})";
case "Pow": return $"pow({ExpressionLambdaToSql(exp.Arguments[0], _tables, _selectColumnMap, tbtype, isQuoteName)})";
case "Sqrt": return $"sqrt({ExpressionLambdaToSql(exp.Arguments[0], _tables, _selectColumnMap, tbtype, isQuoteName)})";
case "PI": return $"pi()";
case "Cos": return $"cos({ExpressionLambdaToSql(exp.Arguments[0], _tables, _selectColumnMap, tbtype, isQuoteName)})";
case "Sin": return $"sin({ExpressionLambdaToSql(exp.Arguments[0], _tables, _selectColumnMap, tbtype, isQuoteName)})";
case "Tan": return $"tan({ExpressionLambdaToSql(exp.Arguments[0], _tables, _selectColumnMap, tbtype, isQuoteName)})";
case "Acos": return $"acos({ExpressionLambdaToSql(exp.Arguments[0], _tables, _selectColumnMap, tbtype, isQuoteName)})";
case "Asin": return $"asin({ExpressionLambdaToSql(exp.Arguments[0], _tables, _selectColumnMap, tbtype, isQuoteName)})";
case "Atan": return $"atan({ExpressionLambdaToSql(exp.Arguments[0], _tables, _selectColumnMap, tbtype, isQuoteName)})";
case "Atan2": return $"atan2({ExpressionLambdaToSql(exp.Arguments[0], _tables, _selectColumnMap, tbtype, isQuoteName)}, {ExpressionLambdaToSql(exp.Arguments[1], _tables, _selectColumnMap, tbtype, isQuoteName)})";
case "Truncate": return $"truncate({ExpressionLambdaToSql(exp.Arguments[0], _tables, _selectColumnMap, tbtype, isQuoteName)}, 0)";
}
internal override string ExpressionLambdaToSqlMemberAccessMath(MemberExpression exp, List<SelectTableInfo> _tables, List<SelectColumnInfo> _selectColumnMap, SelectTableInfoType tbtype, bool isQuoteName) {
var left = ExpressionLambdaToSql(exp.Expression, _tables, _selectColumnMap, tbtype, isQuoteName);
switch (exp.Member.Name) {
case "PI": return $"pi()";
}
throw new Exception($"PostgreSQLExpression 未现实函数表达式 {exp} 解析");
}
//dayofweek = DayOfWeek
//dayofmonth = Day
//dayofyear = DayOfYear
//month = Month
//year = Year
//hour = Hour
//minute = Minute
//second = Second
/*
* date_add(date,interval expr type)
date_sub(date,interval expr type)
adddate(date,interval expr type)
subdate(date,interval expr type)
对日期时间进行加减法运算
(adddate()和subdate()是date_add()和date_sub()的同义词,也
可以用运算符+和-而不是函数
date是一个datetime或date值,expr对date进行加减法的一个表
达式字符串type指明表达式expr应该如何被解释
 [type值 含义 期望的expr格式]:
 second 秒 seconds
 minute 分钟 minutes
 hour 时间 hours
 day 天 days
 month 月 months
 year 年 years
 minute_second 分钟和秒 "minutes:seconds"
 hour_minute 小时和分钟 "hours:minutes"
 day_hour 天和小时 "days hours"
 year_month 年和月 "years-months"
 hour_second 小时, 分钟, "hours:minutes:seconds"
 day_minute 天, 小时, 分钟 "days hours:minutes"
 day_second 天, 小时, 分钟, 秒 "days
hours:minutes:seconds"
 expr中允许任何标点做分隔符,如果所有是date值时结果是一个
date值,否则结果是一个datetime值)
 如果type关键词不完整,则mysql从右端取值,day_second因为缺
少小时分钟等于minute_second)
 如果增加month、year_month或year,天数大于结果月份的最大天
数则使用最大天数)
mysql> select "1997-12-31 23:59:59" + interval 1 second;
internal override string ExpressionLambdaToSqlMemberAccessDateTime(MemberExpression exp, List<SelectTableInfo> _tables, List<SelectColumnInfo> _selectColumnMap, SelectTableInfoType tbtype, bool isQuoteName) {
if (exp.Expression == null && exp.Member.Name == "Now") return "current_timestamp";
var left = ExpressionLambdaToSql(exp.Expression, _tables, _selectColumnMap, tbtype, isQuoteName);
switch (exp.Member.Name) {
case "DayOfWeek": return $"extract(dow from ({left})::timestamp)";
case "Day": return $"extract(day from ({left})::timestamp)";
case "DayOfYear": return $"extract(doy from ({left})::timestamp)";
case "Month": return $"extract(month from ({left})::timestamp)";
case "Year": return $"extract(year from ({left})::timestamp)";
case "Hour": return $"extract(hour from ({left})::timestamp)";
case "Minute": return $"extract(minute from ({left})::timestamp)";
case "Second": return $"extract(second from ({left})::timestamp)";
case "Millisecond": return $"(extract(milliseconds from ({left})::timestamp) - extract(second from ({left})::timestamp) * 1000)";
case "Ticks": return $"(extract(epoch from ({left})::timestamp) * 10000000 + 621355968000000000)";
}
throw new Exception($"PostgreSQLExpression 未现实函数表达式 {exp} 解析");
}
  -> 1998-01-01 00:00:00
mysql> select interval 1 day + "1997-12-31";
  -> 1998-01-01
mysql> select "1998-01-01" - interval 1 second;
  -> 1997-12-31 23:59:59
mysql> select date_add("1997-12-31 23:59:59",interval 1
second);
  -> 1998-01-01 00:00:00
mysql> select date_add("1997-12-31 23:59:59",interval 1
day);
  -> 1998-01-01 23:59:59
mysql> select date_add("1997-12-31 23:59:59",interval
"1:1" minute_second);
  -> 1998-01-01 00:01:00
mysql> select date_sub("1998-01-01 00:00:00",interval "1
1:1:1" day_second);
  -> 1997-12-30 22:58:59
mysql> select date_add("1998-01-01 00:00:00", interval "-1
10" day_hour);
  -> 1997-12-30 14:00:00
mysql> select date_sub("1998-01-02", interval 31 day);
  -> 1997-12-02
mysql> select extract(year from "1999-07-02");
  -> 1999
mysql> select extract(year_month from "1999-07-02
01:02:03");
  -> 199907
mysql> select extract(day_minute from "1999-07-02
01:02:03");
  -> 20102
*/
internal override string ExpressionLambdaToSqlMemberAccessTimeSpan(MemberExpression exp, List<SelectTableInfo> _tables, List<SelectColumnInfo> _selectColumnMap, SelectTableInfoType tbtype, bool isQuoteName) {
var left = ExpressionLambdaToSql(exp.Expression, _tables, _selectColumnMap, tbtype, isQuoteName);
switch (exp.Member.Name) {
case "Days": return $"floor(extract(epoch from ({left})::interval) / {60 * 60 * 24})";
case "Hours": return $"extract(hour from ({left})::interval)";
case "Milliseconds": return $"(extract(milliseconds from ({left})::interval) - extract(second from ({left})::interval) * 1000)";
case "Minutes": return $"extract(minute from ({left})::interval)";
case "Seconds": return $"extract(second from ({left})::interval)";
case "Ticks": return $"(extract(epoch from ({left})::interval) * 10000000)";
case "TotalDays": return $"floor(extract(epoch from ({left})::interval) / {60 * 60 * 24})";
case "TotalHours": return $"floor(extract(epoch from ({left})::interval) / {60 * 60})";
case "TotalMilliseconds": return $"(epoch from ({left})::interval + extract(milliseconds from ({left})::interval) - extract(second from ({left})::interval) * 1000)";
case "TotalMinutes": return $"floor(extract(epoch from ({left})::interval) / 60)";
case "TotalSeconds": return $"extract(epoch from ({left})::interval)";
}
throw new Exception($"PostgreSQLExpression 未现实函数表达式 {exp} 解析");
}
internal override string ExpressionLambdaToSqlCallString(MethodCallExpression exp, List<SelectTableInfo> _tables, List<SelectColumnInfo> _selectColumnMap, SelectTableInfoType tbtype, bool isQuoteName) {
var left = ExpressionLambdaToSql(exp.Object, _tables, _selectColumnMap, tbtype, isQuoteName);
switch (exp.Method.Name) {
case "StartsWith":
case "EndsWith":
case "Contains":
var args0Value = ExpressionLambdaToSql(exp.Arguments[0], _tables, _selectColumnMap, tbtype, isQuoteName);
if (args0Value == "NULL") return $"({left}) IS NULL";
var likeOpt = "LIKE";
if (exp.Arguments.Count > 1) {
if (exp.Arguments[1].Type == typeof(bool) ||
exp.Arguments[1].Type == typeof(StringComparison) && ExpressionLambdaToSql(exp.Arguments[0], _tables, _selectColumnMap, tbtype, isQuoteName).Contains("IgnoreCase")) likeOpt = "ILIKE";
}
if (exp.Method.Name == "StartsWith") return $"({left}) {likeOpt} {(args0Value.StartsWith("'") ? args0Value.Insert(1, "%") : $"('%' || ({args0Value})::varchar)")}";
if (exp.Method.Name == "EndsWith") return $"({left}) {likeOpt} {(args0Value.EndsWith("'") ? args0Value.Insert(args0Value.Length - 1, "%") : $"(({args0Value})::varchar || '%')")}";
if (args0Value.StartsWith("'") && args0Value.EndsWith("'")) return $"({left}) {likeOpt} {args0Value.Insert(1, "%").Insert(args0Value.Length, "%")}";
return $"({left}) {likeOpt} ('%' || ({args0Value})::varchar || '%')";
case "ToLower": return $"lower({left})";
case "ToUpper": return $"upper({left})";
case "Substring":
var substrArgs1 = ExpressionLambdaToSql(exp.Arguments[0], _tables, _selectColumnMap, tbtype, isQuoteName);
if (long.TryParse(substrArgs1, out var testtrylng1)) substrArgs1 = (testtrylng1 + 1).ToString();
else substrArgs1 += " + 1";
if (exp.Arguments.Count == 1) return $"substr({left}, {substrArgs1})";
return $"substr({left}, {substrArgs1}, {ExpressionLambdaToSql(exp.Arguments[1], _tables, _selectColumnMap, tbtype, isQuoteName)})";
case "IndexOf": return $"(strpos({left}, {ExpressionLambdaToSql(exp.Arguments[0], _tables, _selectColumnMap, tbtype, isQuoteName)}) - 1)";
case "PadLeft":
if (exp.Arguments.Count == 1) return $"lpad({left}, {ExpressionLambdaToSql(exp.Arguments[0], _tables, _selectColumnMap, tbtype, isQuoteName)})";
return $"lpad({left}, {ExpressionLambdaToSql(exp.Arguments[0], _tables, _selectColumnMap, tbtype, isQuoteName)}, {ExpressionLambdaToSql(exp.Arguments[1], _tables, _selectColumnMap, tbtype, isQuoteName)})";
case "PadRight":
if (exp.Arguments.Count == 1) return $"rpad({left}, {ExpressionLambdaToSql(exp.Arguments[0], _tables, _selectColumnMap, tbtype, isQuoteName)})";
return $"rpad({left}, {ExpressionLambdaToSql(exp.Arguments[0], _tables, _selectColumnMap, tbtype, isQuoteName)}, {ExpressionLambdaToSql(exp.Arguments[1], _tables, _selectColumnMap, tbtype, isQuoteName)})";
case "Trim":
case "TrimStart":
case "TrimEnd":
if (exp.Arguments.Count == 0) {
if (exp.Method.Name == "Trim") return $"trim({left})";
if (exp.Method.Name == "TrimStart") return $"ltrim({left})";
if (exp.Method.Name == "TrimEnd") return $"rtrim({left})";
}
var trimArg = "";
foreach (var argsTrim02 in exp.Arguments) {
var argsTrim01s = new[] { argsTrim02 };
if (argsTrim02.NodeType == ExpressionType.NewArrayInit) {
var arritem = argsTrim02 as NewArrayExpression;
argsTrim01s = arritem.Expressions.ToArray();
}
foreach (var argsTrim01 in argsTrim01s) {
var trimChr = ExpressionLambdaToSql(argsTrim01, _tables, _selectColumnMap, tbtype, isQuoteName).Trim('"');
if (trimChr.Length == 1) trimArg += trimChr;
else trimArg += $" || ({trimArg})";
}
}
if (exp.Method.Name == "Trim") left = $"trim({left}, {trimArg})";
if (exp.Method.Name == "TrimStart") left = $"ltrim({left}, {trimArg})";
if (exp.Method.Name == "TrimEnd") left = $"rtrim({left}, {trimArg})";
return left;
case "Replace": return $"replace({left}, {ExpressionLambdaToSql(exp.Arguments[0], _tables, _selectColumnMap, tbtype, isQuoteName)}, {ExpressionLambdaToSql(exp.Arguments[1], _tables, _selectColumnMap, tbtype, isQuoteName)})";
case "CompareTo": return $"strcmp({left}, {ExpressionLambdaToSql(exp.Arguments[0], _tables, _selectColumnMap, tbtype, isQuoteName)})";
}
throw new Exception($"PostgreSQLExpression 未现实函数表达式 {exp} 解析");
}
//convert
var xxx = DateTime.Now.ToString("");
internal override string ExpressionLambdaToSqlCallMath(MethodCallExpression exp, List<SelectTableInfo> _tables, List<SelectColumnInfo> _selectColumnMap, SelectTableInfoType tbtype, bool isQuoteName) {
switch (exp.Method.Name) {
case "Abs": return $"abs({ExpressionLambdaToSql(exp.Arguments[0], _tables, _selectColumnMap, tbtype, isQuoteName)})";
case "Sign": return $"sign({ExpressionLambdaToSql(exp.Arguments[0], _tables, _selectColumnMap, tbtype, isQuoteName)})";
case "Floor": return $"floor({ExpressionLambdaToSql(exp.Arguments[0], _tables, _selectColumnMap, tbtype, isQuoteName)})";
case "Ceiling": return $"ceiling({ExpressionLambdaToSql(exp.Arguments[0], _tables, _selectColumnMap, tbtype, isQuoteName)})";
case "Round":
if (exp.Arguments.Count > 1 && exp.Arguments[1].Type.FullName == "System.Int32") return $"round({ExpressionLambdaToSql(exp.Arguments[0], _tables, _selectColumnMap, tbtype, isQuoteName)}, {ExpressionLambdaToSql(exp.Arguments[1], _tables, _selectColumnMap, tbtype, isQuoteName)})";
return $"round({ExpressionLambdaToSql(exp.Arguments[0], _tables, _selectColumnMap, tbtype, isQuoteName)})";
case "Exp": return $"exp({ExpressionLambdaToSql(exp.Arguments[0], _tables, _selectColumnMap, tbtype, isQuoteName)})";
case "Log": return $"log({ExpressionLambdaToSql(exp.Arguments[0], _tables, _selectColumnMap, tbtype, isQuoteName)})";
case "Log10": return $"log10({ExpressionLambdaToSql(exp.Arguments[0], _tables, _selectColumnMap, tbtype, isQuoteName)})";
case "Pow": return $"pow({ExpressionLambdaToSql(exp.Arguments[0], _tables, _selectColumnMap, tbtype, isQuoteName)}, {ExpressionLambdaToSql(exp.Arguments[1], _tables, _selectColumnMap, tbtype, isQuoteName)})";
case "Sqrt": return $"sqrt({ExpressionLambdaToSql(exp.Arguments[0], _tables, _selectColumnMap, tbtype, isQuoteName)})";
case "Cos": return $"cos({ExpressionLambdaToSql(exp.Arguments[0], _tables, _selectColumnMap, tbtype, isQuoteName)})";
case "Sin": return $"sin({ExpressionLambdaToSql(exp.Arguments[0], _tables, _selectColumnMap, tbtype, isQuoteName)})";
case "Tan": return $"tan({ExpressionLambdaToSql(exp.Arguments[0], _tables, _selectColumnMap, tbtype, isQuoteName)})";
case "Acos": return $"acos({ExpressionLambdaToSql(exp.Arguments[0], _tables, _selectColumnMap, tbtype, isQuoteName)})";
case "Asin": return $"asin({ExpressionLambdaToSql(exp.Arguments[0], _tables, _selectColumnMap, tbtype, isQuoteName)})";
case "Atan": return $"atan({ExpressionLambdaToSql(exp.Arguments[0], _tables, _selectColumnMap, tbtype, isQuoteName)})";
case "Atan2": return $"atan2({ExpressionLambdaToSql(exp.Arguments[0], _tables, _selectColumnMap, tbtype, isQuoteName)}, {ExpressionLambdaToSql(exp.Arguments[1], _tables, _selectColumnMap, tbtype, isQuoteName)})";
case "Truncate": return $"trunc({ExpressionLambdaToSql(exp.Arguments[0], _tables, _selectColumnMap, tbtype, isQuoteName)}, 0)";
}
throw new Exception($"PostgreSQLExpression 未现实函数表达式 {exp} 解析");
}
throw new Exception($"MySqlExpression 未现实函数表达式 {exp} 解析");
internal override string ExpressionLambdaToSqlCallDateTime(MethodCallExpression exp, List<SelectTableInfo> _tables, List<SelectColumnInfo> _selectColumnMap, SelectTableInfoType tbtype, bool isQuoteName) {
var left = ExpressionLambdaToSql(exp.Object, _tables, _selectColumnMap, tbtype, isQuoteName);
var args1 = ExpressionLambdaToSql(exp.Arguments[0], _tables, _selectColumnMap, tbtype, isQuoteName);
switch (exp.Method.Name) {
case "Add": return $"(({left})::timestamp + ({args1})::interval)";
case "AddDays": return $"(({left})::timestamp + (({args1}) || ' day')::interval)";
case "AddHours": return $"(({left})::timestamp + (({args1}) || ' hour')::interval)";
case "AddMilliseconds": return $"(({left})::timestamp + (({args1}) || ' milliseconds')::interval)";
case "AddMinutes": return $"(({left})::timestamp + (({args1}) || ' minute')::interval)";
case "AddMonths": return $"(({left})::timestamp + (({args1}) || ' month')::interval)";
case "AddSeconds": return $"(({left})::timestamp + (({args1}) || ' second')::interval)";
case "AddTicks": return $"(({left})::timestamp + (({args1}) / 10 || ' microseconds')::interval)";
case "AddYears": return $"(({left})::timestamp + (({args1}) || ' year')::interval)";
case "Subtract":
if (exp.Arguments[0].Type.FullName == "System.DateTime" || exp.Arguments[0].Type.GenericTypeArguments.FirstOrDefault()?.FullName == "System.DateTime")
return $"(({left})::timestamp - ({args1})::timestamp)";
if (exp.Arguments[0].Type.FullName == "System.TimeSpan" || exp.Arguments[0].Type.GenericTypeArguments.FirstOrDefault()?.FullName == "System.TimeSpan")
return $"(({left})::timestamp - ({args1})::interval)";
break;
}
throw new Exception($"PostgreSQLExpression 未现实函数表达式 {exp} 解析");
}
internal override string ExpressionLambdaToSqlCallTimeSpan(MethodCallExpression exp, List<SelectTableInfo> _tables, List<SelectColumnInfo> _selectColumnMap, SelectTableInfoType tbtype, bool isQuoteName) {
var left = ExpressionLambdaToSql(exp.Object, _tables, _selectColumnMap, tbtype, isQuoteName);
var args1 = ExpressionLambdaToSql(exp.Arguments[0], _tables, _selectColumnMap, tbtype, isQuoteName);
switch (exp.Method.Name) {
case "Add": return $"(({left})::interval + ({args1})::interval)";
case "Subtract": return $"(({left})::interval - ({args1})::interval)";
}
throw new Exception($"PostgreSQLExpression 未现实函数表达式 {exp} 解析");
}
}
}

View File

@ -1,8 +1,10 @@
using FreeSql.Internal;
using MySql.Data.MySqlClient;
using Npgsql;
using NpgsqlTypes;
using System;
using System.Collections.Generic;
using System.Data.Common;
using System.Linq;
namespace FreeSql.PostgreSQL {
@ -14,35 +16,44 @@ namespace FreeSql.PostgreSQL {
internal override DbParameter AppendParamter(List<DbParameter> _params, string parameterName, object value) {
if (string.IsNullOrEmpty(parameterName)) parameterName = $"p_{_params?.Count}";
MySqlParameter ret = null;
if (value == null) ret = new MySqlParameter { ParameterName = $"{parameterName}", Value = DBNull.Value };
NpgsqlParameter ret = null;
if (value == null) ret = new NpgsqlParameter { ParameterName = $"{parameterName}", Value = DBNull.Value };
else {
var type = value.GetType();
ret = new MySqlParameter {
ret = new NpgsqlParameter {
ParameterName = parameterName,
Value = value
};
var tp = _orm.CodeFirst.GetDbInfo(type)?.type;
if (tp != null) ret.MySqlDbType = (MySqlDbType)tp.Value;
if (value.GetType().IsEnum || value.GetType().GenericTypeArguments.FirstOrDefault()?.IsEnum == true) {
ret.DataTypeName = "";
} else {
var tp = _orm.CodeFirst.GetDbInfo(type)?.type;
if (tp != null) ret.NpgsqlDbType = (NpgsqlDbType)tp.Value;
}
}
_params?.Add(ret);
return ret;
}
internal override DbParameter[] GetDbParamtersByObject(string sql, object obj) =>
Utils.GetDbParamtersByObject<MySqlParameter>(sql, obj, "?", (name, type, value) => {
var cp = new MySqlParameter {
Utils.GetDbParamtersByObject<NpgsqlParameter>(sql, obj, "@", (name, type, value) => {
var ret = new NpgsqlParameter {
ParameterName = name,
Value = value ?? DBNull.Value
};
var tp = _orm.CodeFirst.GetDbInfo(type)?.type;
if (tp != null) cp.MySqlDbType = (MySqlDbType)tp.Value;
return cp;
if (value.GetType().IsEnum || value.GetType().GenericTypeArguments.FirstOrDefault()?.IsEnum == true) {
ret.DataTypeName = "";
} else {
var tp = _orm.CodeFirst.GetDbInfo(type)?.type;
if (tp != null) ret.NpgsqlDbType = (NpgsqlDbType)tp.Value;
}
return ret;
});
internal override string FormatSql(string sql, params object[] args) => sql?.FormatMySql(args);
internal override string QuoteSqlName(string name) => $"`{name.Trim('`').Replace(".", "`.`")}`";
internal override string QuoteParamterName(string name) => $"?{name}";
internal override string IsNull(string sql, object value) => $"ifnull({sql}, {value})";
internal override string QuoteSqlName(string name) => $"\"{name.Trim('"').Replace(".", "\".\"")}\"";
internal override string QuoteParamterName(string name) => $"@{name}";
internal override string IsNull(string sql, object value) => $"coalesce({sql}, {value})";
internal override string StringConcat(string left, string right, Type leftType, Type rightType) => $"{left} || {right}";
}
}

View File

@ -10,7 +10,10 @@ namespace FreeSql.SqlServer.Curd {
class SqlServerSelect<T1> : FreeSql.Internal.CommonProvider.Select1Provider<T1> where T1 : class {
internal static string ToSqlStatic(CommonUtils _commonUtils, string _select, string field, StringBuilder _join, StringBuilder _where, string _groupby, string _having, string _orderby, int _skip, int _limit, List<SelectTableInfo> _tables) {
internal static string ToSqlStatic(CommonUtils _commonUtils, string _select, string field, StringBuilder _join, StringBuilder _where, string _groupby, string _having, string _orderby, int _skip, int _limit, List<SelectTableInfo> _tables, IFreeSql _orm) {
if (_orm.CodeFirst.IsAutoSyncStructure)
_orm.CodeFirst.SyncStructure(_tables.Select(a => a.Table.Type).ToArray());
var sb = new StringBuilder();
sb.Append(_select);
if (_limit > 0) sb.Append("TOP ").Append(_skip + _limit).Append(" ");
@ -85,42 +88,42 @@ namespace FreeSql.SqlServer.Curd {
public override ISelect<T1, T2, T3, T4, T5, T6, T7, T8> From<T2, T3, T4, T5, T6, T7, T8>(Expression<Func<ISelectFromExpression<T1>, T2, T3, T4, T5, T6, T7, T8, ISelectFromExpression<T1>>> exp) { this.InternalFrom(exp?.Body); var ret = new SqlServerSelect<T1, T2, T3, T4, T5, T6, T7, T8>(_orm, _commonUtils, _commonExpression, null); SqlServerSelect<T1>.CopyData(this, ret); return ret; }
public override ISelect<T1, T2, T3, T4, T5, T6, T7, T8, T9> From<T2, T3, T4, T5, T6, T7, T8, T9>(Expression<Func<ISelectFromExpression<T1>, T2, T3, T4, T5, T6, T7, T8, T9, ISelectFromExpression<T1>>> exp) { this.InternalFrom(exp?.Body); var ret = new SqlServerSelect<T1, T2, T3, T4, T5, T6, T7, T8, T9>(_orm, _commonUtils, _commonExpression, null); SqlServerSelect<T1>.CopyData(this, ret); return ret; }
public override ISelect<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10> From<T2, T3, T4, T5, T6, T7, T8, T9, T10>(Expression<Func<ISelectFromExpression<T1>, T2, T3, T4, T5, T6, T7, T8, T9, T10, ISelectFromExpression<T1>>> exp) { this.InternalFrom(exp?.Body); var ret = new SqlServerSelect<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10>(_orm, _commonUtils, _commonExpression, null); SqlServerSelect<T1>.CopyData(this, ret); return ret; }
public override string ToSql(string field = null) => ToSqlStatic(_commonUtils, _select, field ?? this.GetAllField().field, _join, _where, _groupby, _having, _orderby, _skip, _limit, _tables);
public override string ToSql(string field = null) => ToSqlStatic(_commonUtils, _select, field ?? this.GetAllField().field, _join, _where, _groupby, _having, _orderby, _skip, _limit, _tables, _orm);
}
class SqlServerSelect<T1, T2> : FreeSql.Internal.CommonProvider.Select2Provider<T1, T2> where T1 : class where T2 : class {
public SqlServerSelect(IFreeSql orm, CommonUtils commonUtils, CommonExpression commonExpression, object dywhere) : base(orm, commonUtils, commonExpression, dywhere) { }
public override string ToSql(string field = null) => SqlServerSelect<T1>.ToSqlStatic(_commonUtils, _select, field ?? this.GetAllField().field, _join, _where, _groupby, _having, _orderby, _skip, _limit, _tables);
public override string ToSql(string field = null) => SqlServerSelect<T1>.ToSqlStatic(_commonUtils, _select, field ?? this.GetAllField().field, _join, _where, _groupby, _having, _orderby, _skip, _limit, _tables, _orm);
}
class SqlServerSelect<T1, T2, T3> : FreeSql.Internal.CommonProvider.Select3Provider<T1, T2, T3> where T1 : class where T2 : class where T3 : class {
public SqlServerSelect(IFreeSql orm, CommonUtils commonUtils, CommonExpression commonExpression, object dywhere) : base(orm, commonUtils, commonExpression, dywhere) { }
public override string ToSql(string field = null) => SqlServerSelect<T1>.ToSqlStatic(_commonUtils, _select, field ?? this.GetAllField().field, _join, _where, _groupby, _having, _orderby, _skip, _limit, _tables);
public override string ToSql(string field = null) => SqlServerSelect<T1>.ToSqlStatic(_commonUtils, _select, field ?? this.GetAllField().field, _join, _where, _groupby, _having, _orderby, _skip, _limit, _tables, _orm);
}
class SqlServerSelect<T1, T2, T3, T4> : FreeSql.Internal.CommonProvider.Select4Provider<T1, T2, T3, T4> where T1 : class where T2 : class where T3 : class where T4 : class {
public SqlServerSelect(IFreeSql orm, CommonUtils commonUtils, CommonExpression commonExpression, object dywhere) : base(orm, commonUtils, commonExpression, dywhere) { }
public override string ToSql(string field = null) => SqlServerSelect<T1>.ToSqlStatic(_commonUtils, _select, field ?? this.GetAllField().field, _join, _where, _groupby, _having, _orderby, _skip, _limit, _tables);
public override string ToSql(string field = null) => SqlServerSelect<T1>.ToSqlStatic(_commonUtils, _select, field ?? this.GetAllField().field, _join, _where, _groupby, _having, _orderby, _skip, _limit, _tables, _orm);
}
class SqlServerSelect<T1, T2, T3, T4, T5> : FreeSql.Internal.CommonProvider.Select5Provider<T1, T2, T3, T4, T5> where T1 : class where T2 : class where T3 : class where T4 : class where T5 : class {
public SqlServerSelect(IFreeSql orm, CommonUtils commonUtils, CommonExpression commonExpression, object dywhere) : base(orm, commonUtils, commonExpression, dywhere) { }
public override string ToSql(string field = null) => SqlServerSelect<T1>.ToSqlStatic(_commonUtils, _select, field ?? this.GetAllField().field, _join, _where, _groupby, _having, _orderby, _skip, _limit, _tables);
public override string ToSql(string field = null) => SqlServerSelect<T1>.ToSqlStatic(_commonUtils, _select, field ?? this.GetAllField().field, _join, _where, _groupby, _having, _orderby, _skip, _limit, _tables, _orm);
}
class SqlServerSelect<T1, T2, T3, T4, T5, T6> : FreeSql.Internal.CommonProvider.Select6Provider<T1, T2, T3, T4, T5, T6> where T1 : class where T2 : class where T3 : class where T4 : class where T5 : class where T6 : class {
public SqlServerSelect(IFreeSql orm, CommonUtils commonUtils, CommonExpression commonExpression, object dywhere) : base(orm, commonUtils, commonExpression, dywhere) { }
public override string ToSql(string field = null) => SqlServerSelect<T1>.ToSqlStatic(_commonUtils, _select, field ?? this.GetAllField().field, _join, _where, _groupby, _having, _orderby, _skip, _limit, _tables);
public override string ToSql(string field = null) => SqlServerSelect<T1>.ToSqlStatic(_commonUtils, _select, field ?? this.GetAllField().field, _join, _where, _groupby, _having, _orderby, _skip, _limit, _tables, _orm);
}
class SqlServerSelect<T1, T2, T3, T4, T5, T6, T7> : FreeSql.Internal.CommonProvider.Select7Provider<T1, T2, T3, T4, T5, T6, T7> where T1 : class where T2 : class where T3 : class where T4 : class where T5 : class where T6 : class where T7 : class {
public SqlServerSelect(IFreeSql orm, CommonUtils commonUtils, CommonExpression commonExpression, object dywhere) : base(orm, commonUtils, commonExpression, dywhere) { }
public override string ToSql(string field = null) => SqlServerSelect<T1>.ToSqlStatic(_commonUtils, _select, field ?? this.GetAllField().field, _join, _where, _groupby, _having, _orderby, _skip, _limit, _tables);
public override string ToSql(string field = null) => SqlServerSelect<T1>.ToSqlStatic(_commonUtils, _select, field ?? this.GetAllField().field, _join, _where, _groupby, _having, _orderby, _skip, _limit, _tables, _orm);
}
class SqlServerSelect<T1, T2, T3, T4, T5, T6, T7, T8> : FreeSql.Internal.CommonProvider.Select8Provider<T1, T2, T3, T4, T5, T6, T7, T8> where T1 : class where T2 : class where T3 : class where T4 : class where T5 : class where T6 : class where T7 : class where T8 : class {
public SqlServerSelect(IFreeSql orm, CommonUtils commonUtils, CommonExpression commonExpression, object dywhere) : base(orm, commonUtils, commonExpression, dywhere) { }
public override string ToSql(string field = null) => SqlServerSelect<T1>.ToSqlStatic(_commonUtils, _select, field ?? this.GetAllField().field, _join, _where, _groupby, _having, _orderby, _skip, _limit, _tables);
public override string ToSql(string field = null) => SqlServerSelect<T1>.ToSqlStatic(_commonUtils, _select, field ?? this.GetAllField().field, _join, _where, _groupby, _having, _orderby, _skip, _limit, _tables, _orm);
}
class SqlServerSelect<T1, T2, T3, T4, T5, T6, T7, T8, T9> : FreeSql.Internal.CommonProvider.Select9Provider<T1, T2, T3, T4, T5, T6, T7, T8, T9> where T1 : class where T2 : class where T3 : class where T4 : class where T5 : class where T6 : class where T7 : class where T8 : class where T9 : class {
public SqlServerSelect(IFreeSql orm, CommonUtils commonUtils, CommonExpression commonExpression, object dywhere) : base(orm, commonUtils, commonExpression, dywhere) { }
public override string ToSql(string field = null) => SqlServerSelect<T1>.ToSqlStatic(_commonUtils, _select, field ?? this.GetAllField().field, _join, _where, _groupby, _having, _orderby, _skip, _limit, _tables);
public override string ToSql(string field = null) => SqlServerSelect<T1>.ToSqlStatic(_commonUtils, _select, field ?? this.GetAllField().field, _join, _where, _groupby, _having, _orderby, _skip, _limit, _tables, _orm);
}
class SqlServerSelect<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10> : FreeSql.Internal.CommonProvider.Select10Provider<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10> where T1 : class where T2 : class where T3 : class where T4 : class where T5 : class where T6 : class where T7 : class where T8 : class where T9 : class where T10 : class {
public SqlServerSelect(IFreeSql orm, CommonUtils commonUtils, CommonExpression commonExpression, object dywhere) : base(orm, commonUtils, commonExpression, dywhere) { }
public override string ToSql(string field = null) => SqlServerSelect<T1>.ToSqlStatic(_commonUtils, _select, field ?? this.GetAllField().field, _join, _where, _groupby, _having, _orderby, _skip, _limit, _tables);
public override string ToSql(string field = null) => SqlServerSelect<T1>.ToSqlStatic(_commonUtils, _select, field ?? this.GetAllField().field, _join, _where, _groupby, _having, _orderby, _skip, _limit, _tables, _orm);
}
}

View File

@ -23,6 +23,7 @@ namespace FreeSql.SqlServer {
}
}
}
static DateTime dt1970 = new DateTime(1970, 1, 1);
public override object AddslashesProcessParam(object param) {
if (param == null) return "NULL";
if (param is bool || param is bool?)
@ -31,12 +32,16 @@ namespace FreeSql.SqlServer {
return string.Concat("'", param.ToString().Replace("'", "''"), "'");
else if (decimal.TryParse(string.Concat(param), out var trydec))
return param;
else if (param is DateTime) {
DateTime dt = (DateTime)param;
return string.Concat("'", dt.ToString("yyyy-MM-dd HH:mm:ss.ffffff"), "'");
} else if (param is DateTime?) {
DateTime? dt = param as DateTime?;
return string.Concat("'", dt.Value.ToString("yyyy-MM-dd HH:mm:ss.ffffff"), "'");
else if (param is DateTime)
return string.Concat("'", ((DateTime)param).ToString("yyyy-MM-dd HH:mm:ss.fff"), "'");
else if (param is DateTime?)
return string.Concat("'", (param as DateTime?).Value.ToString("yyyy-MM-dd HH:mm:ss.fff"), "'");
else if (param is TimeSpan) {
var ts = (TimeSpan)param;
return string.Concat("'", dt1970.Add(ts).ToString("yyyy-MM-dd HH:mm:ss.fff"), "'");
} else if (param is TimeSpan) {
var ts = (param as TimeSpan?).Value;
return string.Concat("'", dt1970.Add(ts).ToString("yyyy-MM-dd HH:mm:ss.fff"), "'");
} else if (param is IEnumerable) {
var sb = new StringBuilder();
var ie = param as IEnumerable;

View File

@ -160,12 +160,21 @@ where a.object_id in (object_id(N'[{0}].[{1}]'))", isRenameTable ? tboldname : t
return sb.Length == 0 ? null : sb.ToString();
}
Dictionary<string, bool> dicSyced = new Dictionary<string, bool>();
public bool SyncStructure<TEntity>() => this.SyncStructure(typeof(TEntity));
public bool SyncStructure(params Type[] entityTypes) {
var ddl = this.GetComparisonDDLStatements(entityTypes);
if (string.IsNullOrEmpty(ddl)) return true;
if (entityTypes == null) return true;
var syncTypes = entityTypes.Where(a => dicSyced.ContainsKey(a.FullName) == false).ToArray();
if (syncTypes.Any() == false) return true;
var ddl = this.GetComparisonDDLStatements(syncTypes);
if (string.IsNullOrEmpty(ddl)) {
foreach (var syncType in syncTypes) dicSyced.Add(syncType.FullName, true);
return true;
}
try {
return _orm.Ado.ExecuteNonQuery(CommandType.Text, ddl) > 0;
var affrows = _orm.Ado.ExecuteNonQuery(CommandType.Text, ddl);
foreach (var syncType in syncTypes) dicSyced.Add(syncType.FullName, true);
return affrows > 0;
} catch {
return false;
}

View File

@ -2,6 +2,7 @@
using FreeSql.Internal.Model;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Linq.Expressions;
namespace FreeSql.SqlServer {
@ -9,73 +10,146 @@ namespace FreeSql.SqlServer {
public SqlServerExpression(CommonUtils common) : base(common) { }
internal override string ExpressionLambdaToSqlCall(MethodCallExpression exp, List<SelectTableInfo> _tables, List<SelectColumnInfo> _selectColumnMap, SelectTableInfoType tbtype, bool isQuoteName) {
if (exp.Object.Type.FullName == "System.String") {
var left = ExpressionLambdaToSql(exp.Object, _tables, _selectColumnMap, tbtype, isQuoteName);
switch (exp.Method.Name) {
case "StartsWith":
case "EndsWith":
case "Contains":
var args0Value = ExpressionLambdaToSql(exp.Arguments[0], _tables, _selectColumnMap, tbtype, isQuoteName);
if (args0Value == "NULL") return $"({left}) IS NULL";
if (exp.Method.Name == "StartsWith") return $"({left}) LIKE {(args0Value.StartsWith("'") ? args0Value.Insert(1, "%") : $"concat('%', {args0Value})")}";
if (exp.Method.Name == "EndsWith") return $"({left}) LIKE {(args0Value.EndsWith("'") ? args0Value.Insert(args0Value.Length - 1, "%") : $"concat({args0Value}, '%')")}";
if (args0Value.StartsWith("'") && args0Value.EndsWith("'")) return $"({left}) LIKE {args0Value.Insert(1, "%").Insert(args0Value.Length, "%")}";
return $"({left}) like concat('%', {args0Value}, '%')";
case "ToLower": return $"lower({left})";
case "ToUpper": return $"upper({left})";
case "Substring": return $"substr({left}, {ExpressionLambdaToSql(exp.Arguments[0], _tables, _selectColumnMap, tbtype, isQuoteName)} + 1, {ExpressionLambdaToSql(exp.Arguments[1], _tables, _selectColumnMap, tbtype, isQuoteName)})";
case "Length": return $"char_length({left})";
case "IndexOf":
var indexOfFindStr = ExpressionLambdaToSql(exp.Arguments[0], _tables, _selectColumnMap, tbtype, isQuoteName);
if (exp.Arguments.Count > 1 && exp.Arguments[1].Type.FullName == "System.Int32") return $"(locate({left}, {indexOfFindStr}, ParseLambdaToSql(exp.Arguments[1], _tables, _selectColumnMap, tbtype, isQuoteName) + 1) - 1)";
return $"(locate({left}, {indexOfFindStr}) - 1)";
case "PadLeft": return $"lpad({left}, {ExpressionLambdaToSql(exp.Arguments[0], _tables, _selectColumnMap, tbtype, isQuoteName)}, {ExpressionLambdaToSql(exp.Arguments[1], _tables, _selectColumnMap, tbtype, isQuoteName)})";
case "PadRight": return $"rpad({left}, {ExpressionLambdaToSql(exp.Arguments[0], _tables, _selectColumnMap, tbtype, isQuoteName)}, {ExpressionLambdaToSql(exp.Arguments[1], _tables, _selectColumnMap, tbtype, isQuoteName)})";
case "Trim":
case "TrimStart":
case "TrimEnd":
if (exp.Arguments.Count == 0) {
if (exp.Method.Name == "Trim") return $"trim({left})";
if (exp.Method.Name == "TrimStart") return $"ltrim({left})";
if (exp.Method.Name == "TrimStart") return $"rtrim({left})";
}
foreach (var argsTrim01 in exp.Arguments) {
if (exp.Method.Name == "Trim") left = $"trim({ExpressionLambdaToSql(argsTrim01, _tables, _selectColumnMap, tbtype, isQuoteName)} from {left})";
if (exp.Method.Name == "TrimStart") left = $"trim(leading {ExpressionLambdaToSql(argsTrim01, _tables, _selectColumnMap, tbtype, isQuoteName)} from {left})";
if (exp.Method.Name == "TrimStart") left = $"trim(trailing {ExpressionLambdaToSql(argsTrim01, _tables, _selectColumnMap, tbtype, isQuoteName)} from {left})";
}
return left;
case "Replace": return $"replace({left}, {ExpressionLambdaToSql(exp.Arguments[0], _tables, _selectColumnMap, tbtype, isQuoteName)}, {ExpressionLambdaToSql(exp.Arguments[1], _tables, _selectColumnMap, tbtype, isQuoteName)})";
case "CompareTo": return $"strcmp({left}, {ExpressionLambdaToSql(exp.Arguments[0], _tables, _selectColumnMap, tbtype, isQuoteName)})";
}
internal override string ExpressionLambdaToSqlMemberAccessString(MemberExpression exp, List<SelectTableInfo> _tables, List<SelectColumnInfo> _selectColumnMap, SelectTableInfoType tbtype, bool isQuoteName) {
var left = ExpressionLambdaToSql(exp.Expression, _tables, _selectColumnMap, tbtype, isQuoteName);
switch (exp.Member.Name) {
case "Length": return $"len({left})";
}
throw new Exception($"SqlServerExpression 未现实函数表达式 {exp} 解析");
}
if (exp.Object.Type.FullName == "System.Math") {
switch (exp.Method.Name) {
case "Abs": return $"abs({ExpressionLambdaToSql(exp.Arguments[0], _tables, _selectColumnMap, tbtype, isQuoteName)})";
case "Sign": return $"sign({ExpressionLambdaToSql(exp.Arguments[0], _tables, _selectColumnMap, tbtype, isQuoteName)})";
case "Floor": return $"floor({ExpressionLambdaToSql(exp.Arguments[0], _tables, _selectColumnMap, tbtype, isQuoteName)})";
case "Round":
if (exp.Arguments.Count > 1 && exp.Arguments[1].Type.FullName == "System.Int32") return $"round({ExpressionLambdaToSql(exp.Arguments[0], _tables, _selectColumnMap, tbtype, isQuoteName)}, {ExpressionLambdaToSql(exp.Arguments[1], _tables, _selectColumnMap, tbtype, isQuoteName)})";
return $"round({ExpressionLambdaToSql(exp.Arguments[0], _tables, _selectColumnMap, tbtype, isQuoteName)})";
case "Exp": return $"exp({ExpressionLambdaToSql(exp.Arguments[0], _tables, _selectColumnMap, tbtype, isQuoteName)})";
case "Log": return $"log({ExpressionLambdaToSql(exp.Arguments[0], _tables, _selectColumnMap, tbtype, isQuoteName)})";
case "Log10": return $"log10({ExpressionLambdaToSql(exp.Arguments[0], _tables, _selectColumnMap, tbtype, isQuoteName)})";
case "Pow": return $"pow({ExpressionLambdaToSql(exp.Arguments[0], _tables, _selectColumnMap, tbtype, isQuoteName)})";
case "Sqrt": return $"sqrt({ExpressionLambdaToSql(exp.Arguments[0], _tables, _selectColumnMap, tbtype, isQuoteName)})";
case "PI": return $"pi()";
case "Cos": return $"cos({ExpressionLambdaToSql(exp.Arguments[0], _tables, _selectColumnMap, tbtype, isQuoteName)})";
case "Sin": return $"sin({ExpressionLambdaToSql(exp.Arguments[0], _tables, _selectColumnMap, tbtype, isQuoteName)})";
case "Tan": return $"tan({ExpressionLambdaToSql(exp.Arguments[0], _tables, _selectColumnMap, tbtype, isQuoteName)})";
case "Acos": return $"acos({ExpressionLambdaToSql(exp.Arguments[0], _tables, _selectColumnMap, tbtype, isQuoteName)})";
case "Asin": return $"asin({ExpressionLambdaToSql(exp.Arguments[0], _tables, _selectColumnMap, tbtype, isQuoteName)})";
case "Atan": return $"atan({ExpressionLambdaToSql(exp.Arguments[0], _tables, _selectColumnMap, tbtype, isQuoteName)})";
case "Atan2": return $"atan2({ExpressionLambdaToSql(exp.Arguments[0], _tables, _selectColumnMap, tbtype, isQuoteName)}, {ExpressionLambdaToSql(exp.Arguments[1], _tables, _selectColumnMap, tbtype, isQuoteName)})";
case "Truncate": return $"truncate({ExpressionLambdaToSql(exp.Arguments[0], _tables, _selectColumnMap, tbtype, isQuoteName)}, 0)";
}
internal override string ExpressionLambdaToSqlMemberAccessMath(MemberExpression exp, List<SelectTableInfo> _tables, List<SelectColumnInfo> _selectColumnMap, SelectTableInfoType tbtype, bool isQuoteName) {
var left = ExpressionLambdaToSql(exp.Expression, _tables, _selectColumnMap, tbtype, isQuoteName);
switch (exp.Member.Name) {
case "PI": return $"pi()";
}
throw new Exception($"SqlServerExpression 未现实函数表达式 {exp} 解析");
}
internal override string ExpressionLambdaToSqlMemberAccessDateTime(MemberExpression exp, List<SelectTableInfo> _tables, List<SelectColumnInfo> _selectColumnMap, SelectTableInfoType tbtype, bool isQuoteName) {
if (exp.Expression == null && exp.Member.Name == "Now") return "getdate()";
var left = ExpressionLambdaToSql(exp.Expression, _tables, _selectColumnMap, tbtype, isQuoteName);
switch (exp.Member.Name) {
case "DayOfWeek": return $"(datepart(weekday, {left}) - 1)";
case "Day": return $"datepart(day, {left})";
case "DayOfYear": return $"datepart(dayofyear, {left})";
case "Month": return $"datepart(month, {left})";
case "Year": return $"datepart(year, {left})";
case "Hour": return $"datepart(hour, {left})";
case "Minute": return $"datepart(minute, {left})";
case "Second": return $"datepart(second, {left})";
case "Millisecond": return $"datepart(millisecond, {left})";
case "Ticks": return $"(datediff(second, '1970-1-1', {left}) * 10000000 + 621355968000000000)";
}
throw new Exception($"SqlServerExpression 未现实函数表达式 {exp} 解析");
}
internal override string ExpressionLambdaToSqlMemberAccessTimeSpan(MemberExpression exp, List<SelectTableInfo> _tables, List<SelectColumnInfo> _selectColumnMap, SelectTableInfoType tbtype, bool isQuoteName) {
var left = ExpressionLambdaToSql(exp.Expression, _tables, _selectColumnMap, tbtype, isQuoteName);
switch (exp.Member.Name) {
case "Days": return $"datediff(day, '1970-1-1', {left})";
case "Hours": return $"datepart(hour, '1970-1-1', {left})";
case "Milliseconds": return $"datepart(millisecond, {left})";
case "Minutes": return $"datepart(minute, {left})";
case "Seconds": return $"datepart(second, {left})";
case "Ticks": return $"(datediff(millisecond, '1970-1-1', {left}) * 10000)";
case "TotalDays": return $"datediff(day, '1970-1-1', {left})";
case "TotalHours": return $"datediff(hour, '1970-1-1', {left})";
case "TotalMilliseconds": return $"datediff(millisecond, '1970-1-1', {left})";
case "TotalMinutes": return $"datediff(minute, '1970-1-1', {left})";
case "TotalSeconds": return $"datediff(second, '1970-1-1', {left})";
}
throw new Exception($"SqlServerExpression 未现实函数表达式 {exp} 解析");
}
internal override string ExpressionLambdaToSqlCallString(MethodCallExpression exp, List<SelectTableInfo> _tables, List<SelectColumnInfo> _selectColumnMap, SelectTableInfoType tbtype, bool isQuoteName) {
var left = ExpressionLambdaToSql(exp.Object, _tables, _selectColumnMap, tbtype, isQuoteName);
switch (exp.Method.Name) {
case "StartsWith":
case "EndsWith":
case "Contains":
var args0Value = ExpressionLambdaToSql(exp.Arguments[0], _tables, _selectColumnMap, tbtype, isQuoteName);
if (args0Value == "NULL") return $"({left}) IS NULL";
if (exp.Method.Name == "StartsWith") return $"({left}) LIKE {(args0Value.StartsWith("'") ? args0Value.Insert(1, "%") : $"('%' + cast({args0Value} as nvarchar))")}";
if (exp.Method.Name == "EndsWith") return $"({left}) LIKE {(args0Value.EndsWith("'") ? args0Value.Insert(args0Value.Length - 1, "%") : $"(cast({args0Value} as nvarchar) + '%')")}";
if (args0Value.StartsWith("'") && args0Value.EndsWith("'")) return $"({left}) LIKE {args0Value.Insert(1, "%").Insert(args0Value.Length, "%")}";
return $"({left}) LIKE ('%' + cast({args0Value} as nvarchar) + '%')";
case "ToLower": return $"lower({left})";
case "ToUpper": return $"upper({left})";
case "Substring":
var substrArgs1 = ExpressionLambdaToSql(exp.Arguments[0], _tables, _selectColumnMap, tbtype, isQuoteName);
if (long.TryParse(substrArgs1, out var testtrylng1)) substrArgs1 = (testtrylng1 + 1).ToString();
else substrArgs1 += " + 1";
if (exp.Arguments.Count == 1) return $"substring({left}, {substrArgs1})";
return $"substring({left}, {substrArgs1}, {ExpressionLambdaToSql(exp.Arguments[1], _tables, _selectColumnMap, tbtype, isQuoteName)})";
case "IndexOf":
var indexOfFindStr = ExpressionLambdaToSql(exp.Arguments[0], _tables, _selectColumnMap, tbtype, isQuoteName);
if (exp.Arguments.Count > 1 && exp.Arguments[1].Type.FullName == "System.Int32") return $"(charindex({left}, {indexOfFindStr}, {ExpressionLambdaToSql(exp.Arguments[1], _tables, _selectColumnMap, tbtype, isQuoteName)} + 1) - 1)";
return $"(locate({left}, {indexOfFindStr}) - 1)";
case "PadLeft":
if (exp.Arguments.Count == 1) return $"lpad({left}, {ExpressionLambdaToSql(exp.Arguments[0], _tables, _selectColumnMap, tbtype, isQuoteName)})";
return $"lpad({left}, {ExpressionLambdaToSql(exp.Arguments[0], _tables, _selectColumnMap, tbtype, isQuoteName)}, {ExpressionLambdaToSql(exp.Arguments[1], _tables, _selectColumnMap, tbtype, isQuoteName)})";
case "PadRight":
if (exp.Arguments.Count == 1) return $"rpad({left}, {ExpressionLambdaToSql(exp.Arguments[0], _tables, _selectColumnMap, tbtype, isQuoteName)})";
return $"rpad({left}, {ExpressionLambdaToSql(exp.Arguments[0], _tables, _selectColumnMap, tbtype, isQuoteName)}, {ExpressionLambdaToSql(exp.Arguments[1], _tables, _selectColumnMap, tbtype, isQuoteName)})";
case "Trim": return $"ltrim(rtrim({left}))";
case "TrimStart": return $"ltrim({left})";
case "TrimEnd": return $"rtrim({left})";
case "Replace": return $"replace({left}, {ExpressionLambdaToSql(exp.Arguments[0], _tables, _selectColumnMap, tbtype, isQuoteName)}, {ExpressionLambdaToSql(exp.Arguments[1], _tables, _selectColumnMap, tbtype, isQuoteName)})";
case "CompareTo": return $"strcmp({left}, {ExpressionLambdaToSql(exp.Arguments[0], _tables, _selectColumnMap, tbtype, isQuoteName)})";
}
throw new Exception($"SqlServerExpression 未现实函数表达式 {exp} 解析");
}
internal override string ExpressionLambdaToSqlCallMath(MethodCallExpression exp, List<SelectTableInfo> _tables, List<SelectColumnInfo> _selectColumnMap, SelectTableInfoType tbtype, bool isQuoteName) {
switch (exp.Method.Name) {
case "Abs": return $"abs({ExpressionLambdaToSql(exp.Arguments[0], _tables, _selectColumnMap, tbtype, isQuoteName)})";
case "Sign": return $"sign({ExpressionLambdaToSql(exp.Arguments[0], _tables, _selectColumnMap, tbtype, isQuoteName)})";
case "Floor": return $"floor({ExpressionLambdaToSql(exp.Arguments[0], _tables, _selectColumnMap, tbtype, isQuoteName)})";
case "Ceiling": return $"ceiling({ExpressionLambdaToSql(exp.Arguments[0], _tables, _selectColumnMap, tbtype, isQuoteName)})";
case "Round":
if (exp.Arguments.Count > 1 && exp.Arguments[1].Type.FullName == "System.Int32") return $"round({ExpressionLambdaToSql(exp.Arguments[0], _tables, _selectColumnMap, tbtype, isQuoteName)}, {ExpressionLambdaToSql(exp.Arguments[1], _tables, _selectColumnMap, tbtype, isQuoteName)})";
return $"round({ExpressionLambdaToSql(exp.Arguments[0], _tables, _selectColumnMap, tbtype, isQuoteName)})";
case "Exp": return $"exp({ExpressionLambdaToSql(exp.Arguments[0], _tables, _selectColumnMap, tbtype, isQuoteName)})";
case "Log": return $"log({ExpressionLambdaToSql(exp.Arguments[0], _tables, _selectColumnMap, tbtype, isQuoteName)})";
case "Log10": return $"log10({ExpressionLambdaToSql(exp.Arguments[0], _tables, _selectColumnMap, tbtype, isQuoteName)})";
case "Pow": return $"power({ExpressionLambdaToSql(exp.Arguments[0], _tables, _selectColumnMap, tbtype, isQuoteName)}, {ExpressionLambdaToSql(exp.Arguments[1], _tables, _selectColumnMap, tbtype, isQuoteName)})";
case "Sqrt": return $"sqrt({ExpressionLambdaToSql(exp.Arguments[0], _tables, _selectColumnMap, tbtype, isQuoteName)})";
case "Cos": return $"cos({ExpressionLambdaToSql(exp.Arguments[0], _tables, _selectColumnMap, tbtype, isQuoteName)})";
case "Sin": return $"sin({ExpressionLambdaToSql(exp.Arguments[0], _tables, _selectColumnMap, tbtype, isQuoteName)})";
case "Tan": return $"tan({ExpressionLambdaToSql(exp.Arguments[0], _tables, _selectColumnMap, tbtype, isQuoteName)})";
case "Acos": return $"acos({ExpressionLambdaToSql(exp.Arguments[0], _tables, _selectColumnMap, tbtype, isQuoteName)})";
case "Asin": return $"asin({ExpressionLambdaToSql(exp.Arguments[0], _tables, _selectColumnMap, tbtype, isQuoteName)})";
case "Atan": return $"atan({ExpressionLambdaToSql(exp.Arguments[0], _tables, _selectColumnMap, tbtype, isQuoteName)})";
case "Atan2": return $"atan2({ExpressionLambdaToSql(exp.Arguments[0], _tables, _selectColumnMap, tbtype, isQuoteName)}, {ExpressionLambdaToSql(exp.Arguments[1], _tables, _selectColumnMap, tbtype, isQuoteName)})";
case "Truncate": return $"floor({ExpressionLambdaToSql(exp.Arguments[0], _tables, _selectColumnMap, tbtype, isQuoteName)}, 0)";
}
throw new Exception($"SqlServerExpression 未现实函数表达式 {exp} 解析");
}
internal override string ExpressionLambdaToSqlCallDateTime(MethodCallExpression exp, List<SelectTableInfo> _tables, List<SelectColumnInfo> _selectColumnMap, SelectTableInfoType tbtype, bool isQuoteName) {
var left = ExpressionLambdaToSql(exp.Object, _tables, _selectColumnMap, tbtype, isQuoteName);
var args1 = ExpressionLambdaToSql(exp.Arguments[0], _tables, _selectColumnMap, tbtype, isQuoteName);
switch (exp.Method.Name) {
case "Add": return $"dateadd(millisecond, datediff(millisecond, '1970-1-1', {args1}), {left})";
case "AddDays": return $"dateadd(day, {args1}, {left})";
case "AddHours": return $"dateadd(hour, {args1}, {left})";
case "AddMilliseconds": return $"dateadd(millisecond, {args1}, {left})";
case "AddMinutes": return $"dateadd(minute, {args1}, {left})";
case "AddMonths": return $"dateadd(month, {args1}, {left})";
case "AddSeconds": return $"dateadd(second, {args1}, {left})";
case "AddTicks": return $"dateadd(millisecond, {args1} / 10000, {left})";
case "AddYears": return $"dateadd(year, {args1}, {left})";
case "Subtract": return $"dateadd(millisecond, -datediff(millisecond, '1970-1-1', {args1}), {left})";
}
throw new Exception($"SqlServerExpression 未现实函数表达式 {exp} 解析");
}
internal override string ExpressionLambdaToSqlCallTimeSpan(MethodCallExpression exp, List<SelectTableInfo> _tables, List<SelectColumnInfo> _selectColumnMap, SelectTableInfoType tbtype, bool isQuoteName) {
var left = ExpressionLambdaToSql(exp.Object, _tables, _selectColumnMap, tbtype, isQuoteName);
var args1 = ExpressionLambdaToSql(exp.Arguments[0], _tables, _selectColumnMap, tbtype, isQuoteName);
switch (exp.Method.Name) {
case "Add": return $"dateadd(millisecond, datediff(millisecond, '1970-1-1', {args1}), {left})";
case "Subtract": return $"dateadd(millisecond, -datediff(millisecond, '1970-1-1', {args1}), {left})";
}
throw new Exception($"SqlServerExpression 未现实函数表达式 {exp} 解析");
}
}

View File

@ -45,5 +45,6 @@ namespace FreeSql.SqlServer {
internal override string QuoteSqlName(string name) => $"[{name.TrimStart('[').TrimEnd(']').Replace(".", "].[")}]";
internal override string QuoteParamterName(string name) => $"@{name}";
internal override string IsNull(string sql, object value) => $"isnull({sql}, {value})";
internal override string StringConcat(string left, string right, Type leftType, Type rightType) => $"{(leftType.FullName == "System.String" ? left : $"cast({left} as nvarchar)")} + {(rightType.FullName == "System.String" ? right : $"cast({right} as nvarchar)")}";
}
}