mirror of
https://github.com/nsnail/FreeSql.git
synced 2025-06-19 20:38:16 +08:00
CodeFirst sqlserver支持跨库/跨schema改表名,mysql支持跨库改表名,postgresql支持跨schema改表名
This commit is contained in:
@ -56,7 +56,7 @@ namespace FreeSql {
|
||||
switch(_dataType) {
|
||||
case DataType.MySql: return new MySql.MySqlProvider(_cache, null, _masterConnectionString, _slaveConnectionString, _logger);
|
||||
case DataType.SqlServer: return new SqlServer.SqlServerProvider(_cache, null, _masterConnectionString, _slaveConnectionString, _logger);
|
||||
case DataType.PostgreSQL: return new MySql.MySqlProvider(_cache, null, _masterConnectionString, _slaveConnectionString, _logger);
|
||||
case DataType.PostgreSQL: return new PostgreSQL.PostgreSQLProvider(_cache, null, _masterConnectionString, _slaveConnectionString, _logger);
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
@ -189,29 +189,12 @@ namespace FreeSql {
|
||||
/// <returns></returns>
|
||||
ISelect<T1> Where<T2, T3, T4, T5>(Expression<Func<T1, T2, T3, T4, T5, bool>> exp) where T2 : class where T3 : class where T4 : class where T5 : class;
|
||||
|
||||
/// <summary>
|
||||
/// 模糊查询,选择多个列 OR,WhereLike(a => new[] { a.Title, a.Content }, "%sql%")
|
||||
/// </summary>
|
||||
/// <param name="columns">lambda选择列</param>
|
||||
/// <param name="pattern">查询内容</param>
|
||||
/// <param name="notLike">not like</param>
|
||||
/// <returns></returns>
|
||||
ISelect<T1> WhereLike(Expression<Func<T1, string[]>> columns, string pattern, bool notLike = false);
|
||||
/// <summary>
|
||||
/// 模糊查询,WhereLike(a => a.Title, "%sql")
|
||||
/// </summary>
|
||||
/// <param name="column">lambda选择列</param>
|
||||
/// <param name="pattern">查询内容</param>
|
||||
/// <param name="notLike">not like</param>
|
||||
/// <returns></returns>
|
||||
ISelect<T1> WhereLike(Expression<Func<T1, string>> column, string pattern, bool notLike = false);
|
||||
|
||||
/// <summary>
|
||||
/// 按选择的列分组,GroupBy(a => a.Name) | GroupBy(a => new{a.Name,a.Time}) | GroupBy(a => new[]{"name","time"})
|
||||
/// </summary>
|
||||
/// <param name="columns"></param>
|
||||
/// <returns></returns>
|
||||
ISelect<T1> GroupBy(Expression<Func<T1, object>> columns);
|
||||
ISelect<T1> GroupBy<TKey>(Expression<Func<T1, TKey>> columns);
|
||||
|
||||
/// <summary>
|
||||
/// 按列排序,OrderBy(a => a.Time)
|
||||
|
@ -15,9 +15,6 @@ namespace FreeSql {
|
||||
ISelect<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10> Where(Expression<Func<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, bool>> exp);
|
||||
ISelect<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10> WhereIf(bool condition, Expression<Func<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, bool>> exp);
|
||||
|
||||
ISelect<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10> WhereLike(Expression<Func<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, string[]>> columns, string pattern, bool notLike = false);
|
||||
ISelect<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10> WhereLike(Expression<Func<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, string>> column, string pattern, bool notLike = false);
|
||||
|
||||
ISelect<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10> GroupBy(Expression<Func<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, object>> columns);
|
||||
|
||||
ISelect<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10> OrderBy<TMember>(Expression<Func<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, TMember>> column);
|
||||
|
@ -15,9 +15,6 @@ namespace FreeSql {
|
||||
ISelect<T1, T2> Where(Expression<Func<T1, T2, bool>> exp);
|
||||
ISelect<T1, T2> WhereIf(bool condition, Expression<Func<T1, T2, bool>> exp);
|
||||
|
||||
ISelect<T1, T2> WhereLike(Expression<Func<T1, T2, string[]>> columns, string pattern, bool notLike = false);
|
||||
ISelect<T1, T2> WhereLike(Expression<Func<T1, T2, string>> column, string pattern, bool notLike = false);
|
||||
|
||||
ISelect<T1, T2> GroupBy(Expression<Func<T1, T2, object>> columns);
|
||||
|
||||
ISelect<T1, T2> OrderBy<TMember>(Expression<Func<T1, T2, TMember>> column);
|
||||
|
@ -15,9 +15,6 @@ namespace FreeSql {
|
||||
ISelect<T1, T2, T3> Where(Expression<Func<T1, T2, T3, bool>> exp);
|
||||
ISelect<T1, T2, T3> WhereIf(bool condition, Expression<Func<T1, T2, T3, bool>> exp);
|
||||
|
||||
ISelect<T1, T2, T3> WhereLike(Expression<Func<T1, T2, T3, string[]>> columns, string pattern, bool notLike = false);
|
||||
ISelect<T1, T2, T3> WhereLike(Expression<Func<T1, T2, T3, string>> column, string pattern, bool notLike = false);
|
||||
|
||||
ISelect<T1, T2, T3> GroupBy(Expression<Func<T1, T2, T3, object>> columns);
|
||||
|
||||
ISelect<T1, T2, T3> OrderBy<TMember>(Expression<Func<T1, T2, T3, TMember>> column);
|
||||
|
@ -15,9 +15,6 @@ namespace FreeSql {
|
||||
ISelect<T1, T2, T3, T4> Where(Expression<Func<T1, T2, T3, T4, bool>> exp);
|
||||
ISelect<T1, T2, T3, T4> WhereIf(bool condition, Expression<Func<T1, T2, T3, T4, bool>> exp);
|
||||
|
||||
ISelect<T1, T2, T3, T4> WhereLike(Expression<Func<T1, T2, T3, T4, string[]>> columns, string pattern, bool notLike = false);
|
||||
ISelect<T1, T2, T3, T4> WhereLike(Expression<Func<T1, T2, T3, T4, string>> column, string pattern, bool notLike = false);
|
||||
|
||||
ISelect<T1, T2, T3, T4> GroupBy(Expression<Func<T1, T2, T3, T4, object>> columns);
|
||||
|
||||
ISelect<T1, T2, T3, T4> OrderBy<TMember>(Expression<Func<T1, T2, T3, T4, TMember>> column);
|
||||
|
@ -15,9 +15,6 @@ namespace FreeSql {
|
||||
ISelect<T1, T2, T3, T4, T5> Where(Expression<Func<T1, T2, T3, T4, T5, bool>> exp);
|
||||
ISelect<T1, T2, T3, T4, T5> WhereIf(bool condition, Expression<Func<T1, T2, T3, T4, T5, bool>> exp);
|
||||
|
||||
ISelect<T1, T2, T3, T4, T5> WhereLike(Expression<Func<T1, T2, T3, T4, T5, string[]>> columns, string pattern, bool notLike = false);
|
||||
ISelect<T1, T2, T3, T4, T5> WhereLike(Expression<Func<T1, T2, T3, T4, T5, string>> column, string pattern, bool notLike = false);
|
||||
|
||||
ISelect<T1, T2, T3, T4, T5> GroupBy(Expression<Func<T1, T2, T3, T4, T5, object>> columns);
|
||||
|
||||
ISelect<T1, T2, T3, T4, T5> OrderBy<TMember>(Expression<Func<T1, T2, T3, T4, T5, TMember>> column);
|
||||
|
@ -15,9 +15,6 @@ namespace FreeSql {
|
||||
ISelect<T1, T2, T3, T4, T5, T6> Where(Expression<Func<T1, T2, T3, T4, T5, T6, bool>> exp);
|
||||
ISelect<T1, T2, T3, T4, T5, T6> WhereIf(bool condition, Expression<Func<T1, T2, T3, T4, T5, T6, bool>> exp);
|
||||
|
||||
ISelect<T1, T2, T3, T4, T5, T6> WhereLike(Expression<Func<T1, T2, T3, T4, T5, T6, string[]>> columns, string pattern, bool notLike = false);
|
||||
ISelect<T1, T2, T3, T4, T5, T6> WhereLike(Expression<Func<T1, T2, T3, T4, T5, T6, string>> column, string pattern, bool notLike = false);
|
||||
|
||||
ISelect<T1, T2, T3, T4, T5, T6> GroupBy(Expression<Func<T1, T2, T3, T4, T5, T6, object>> columns);
|
||||
|
||||
ISelect<T1, T2, T3, T4, T5, T6> OrderBy<TMember>(Expression<Func<T1, T2, T3, T4, T5, T6, TMember>> column);
|
||||
|
@ -15,9 +15,6 @@ namespace FreeSql {
|
||||
ISelect<T1, T2, T3, T4, T5, T6, T7> Where(Expression<Func<T1, T2, T3, T4, T5, T6, T7, bool>> exp);
|
||||
ISelect<T1, T2, T3, T4, T5, T6, T7> WhereIf(bool condition, Expression<Func<T1, T2, T3, T4, T5, T6, T7, bool>> exp);
|
||||
|
||||
ISelect<T1, T2, T3, T4, T5, T6, T7> WhereLike(Expression<Func<T1, T2, T3, T4, T5, T6, T7, string[]>> columns, string pattern, bool notLike = false);
|
||||
ISelect<T1, T2, T3, T4, T5, T6, T7> WhereLike(Expression<Func<T1, T2, T3, T4, T5, T6, T7, string>> column, string pattern, bool notLike = false);
|
||||
|
||||
ISelect<T1, T2, T3, T4, T5, T6, T7> GroupBy(Expression<Func<T1, T2, T3, T4, T5, T6, T7, object>> columns);
|
||||
|
||||
ISelect<T1, T2, T3, T4, T5, T6, T7> OrderBy<TMember>(Expression<Func<T1, T2, T3, T4, T5, T6, T7, TMember>> column);
|
||||
|
@ -15,9 +15,6 @@ namespace FreeSql {
|
||||
ISelect<T1, T2, T3, T4, T5, T6, T7, T8> Where(Expression<Func<T1, T2, T3, T4, T5, T6, T7, T8, bool>> exp);
|
||||
ISelect<T1, T2, T3, T4, T5, T6, T7, T8> WhereIf(bool condition, Expression<Func<T1, T2, T3, T4, T5, T6, T7, T8, bool>> exp);
|
||||
|
||||
ISelect<T1, T2, T3, T4, T5, T6, T7, T8> WhereLike(Expression<Func<T1, T2, T3, T4, T5, T6, T7, T8, string[]>> columns, string pattern, bool notLike = false);
|
||||
ISelect<T1, T2, T3, T4, T5, T6, T7, T8> WhereLike(Expression<Func<T1, T2, T3, T4, T5, T6, T7, T8, string>> column, string pattern, bool notLike = false);
|
||||
|
||||
ISelect<T1, T2, T3, T4, T5, T6, T7, T8> GroupBy(Expression<Func<T1, T2, T3, T4, T5, T6, T7, T8, object>> columns);
|
||||
|
||||
ISelect<T1, T2, T3, T4, T5, T6, T7, T8> OrderBy<TMember>(Expression<Func<T1, T2, T3, T4, T5, T6, T7, T8, TMember>> column);
|
||||
|
@ -15,9 +15,6 @@ namespace FreeSql {
|
||||
ISelect<T1, T2, T3, T4, T5, T6, T7, T8, T9> Where(Expression<Func<T1, T2, T3, T4, T5, T6, T7, T8, T9, bool>> exp);
|
||||
ISelect<T1, T2, T3, T4, T5, T6, T7, T8, T9> WhereIf(bool condition, Expression<Func<T1, T2, T3, T4, T5, T6, T7, T8, T9, bool>> exp);
|
||||
|
||||
ISelect<T1, T2, T3, T4, T5, T6, T7, T8, T9> WhereLike(Expression<Func<T1, T2, T3, T4, T5, T6, T7, T8, T9, string[]>> columns, string pattern, bool notLike = false);
|
||||
ISelect<T1, T2, T3, T4, T5, T6, T7, T8, T9> WhereLike(Expression<Func<T1, T2, T3, T4, T5, T6, T7, T8, T9, string>> column, string pattern, bool notLike = false);
|
||||
|
||||
ISelect<T1, T2, T3, T4, T5, T6, T7, T8, T9> GroupBy(Expression<Func<T1, T2, T3, T4, T5, T6, T7, T8, T9, object>> columns);
|
||||
|
||||
ISelect<T1, T2, T3, T4, T5, T6, T7, T8, T9> OrderBy<TMember>(Expression<Func<T1, T2, T3, T4, T5, T6, T7, T8, T9, TMember>> column);
|
||||
|
@ -23,23 +23,6 @@ namespace FreeSql {
|
||||
/// <returns></returns>
|
||||
ISelectFromExpression<T1> WhereIf(bool condition, Expression<Func<T1, bool>> exp);
|
||||
|
||||
/// <summary>
|
||||
/// 模糊查询,选择多个列 OR,WhereLike(a => new[] { a.Title, a.Content }, "%sql%")
|
||||
/// </summary>
|
||||
/// <param name="columns">lambda选择列</param>
|
||||
/// <param name="pattern">查询内容</param>
|
||||
/// <param name="notLike">not like</param>
|
||||
/// <returns></returns>
|
||||
ISelectFromExpression<T1> WhereLike(Expression<Func<T1, string[]>> columns, string pattern, bool notLike = false);
|
||||
/// <summary>
|
||||
/// 模糊查询,WhereLike(a => a.Title, "%sql")
|
||||
/// </summary>
|
||||
/// <param name="column">lambda选择列</param>
|
||||
/// <param name="pattern">查询内容</param>
|
||||
/// <param name="notLike">not like</param>
|
||||
/// <returns></returns>
|
||||
ISelectFromExpression<T1> WhereLike(Expression<Func<T1, string>> column, string pattern, bool notLike = false);
|
||||
|
||||
/// <summary>
|
||||
/// 按选择的列分组,GroupBy(a => a.Name) | GroupBy(a => new{a.Name,a.Time}) | GroupBy(a => new[]{"name","time"})
|
||||
/// </summary>
|
||||
|
46
FreeSql/Interface/Curd/ISelect/ISelectGrouping.cs
Normal file
46
FreeSql/Interface/Curd/ISelect/ISelectGrouping.cs
Normal file
@ -0,0 +1,46 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq.Expressions;
|
||||
using System.Text;
|
||||
|
||||
namespace FreeSql {
|
||||
public interface ISelectGrouping<T1> {
|
||||
/// <summary>
|
||||
/// 按聚合条件过滤,Where(a => a.Count() > 10)
|
||||
/// </summary>
|
||||
/// <param name="exp">lambda表达式</param>
|
||||
/// <returns></returns>
|
||||
ISelectGrouping<T1> Having(Expression<Func<ISelectGroupingAggregate<T1>, bool>> exp);
|
||||
|
||||
/// <summary>
|
||||
/// 按列排序,OrderBy(a => a.Time)
|
||||
/// </summary>
|
||||
/// <typeparam name="TMember"></typeparam>
|
||||
/// <param name="column"></param>
|
||||
/// <returns></returns>
|
||||
ISelectGrouping<T1> OrderBy<TMember>(Expression<Func<ISelectGroupingAggregate<T1>, TMember>> column);
|
||||
/// <summary>
|
||||
/// 按列倒向排序,OrderByDescending(a => a.Time)
|
||||
/// </summary>
|
||||
/// <param name="column">列</param>
|
||||
/// <returns></returns>
|
||||
ISelectGrouping<T1> OrderByDescending<TMember>(Expression<Func<ISelectGroupingAggregate<T1>, TMember>> column);
|
||||
|
||||
/// <summary>
|
||||
/// 执行SQL查询,返回指定字段的记录,记录不存在时返回 Count 为 0 的列表
|
||||
/// </summary>
|
||||
/// <typeparam name="TReturn">返回类型</typeparam>
|
||||
/// <param name="select">选择列</param>
|
||||
/// <returns></returns>
|
||||
List<TReturn> ToList<TReturn>(Expression<Func<ISelectGroupingAggregate<T1>, TReturn>> select);
|
||||
}
|
||||
|
||||
public interface ISelectGroupingAggregate<T1> {
|
||||
T1 Key { get; set; }
|
||||
int Count();
|
||||
T3 Sum<T3>(T3 column);
|
||||
T3 Avg<T3>(T3 column);
|
||||
T3 Max<T3>(T3 column);
|
||||
T3 Min<T3>(T3 column);
|
||||
}
|
||||
}
|
@ -19,15 +19,18 @@ namespace FreeSql.Internal {
|
||||
case ExpressionType.Lambda: return ReadAnonymousField(_tables, field, parent, ref index, (exp as LambdaExpression)?.Body);
|
||||
case ExpressionType.Negate:
|
||||
case ExpressionType.NegateChecked:
|
||||
field.Append(", ").Append(ExpressionLambdaToSql(exp, _tables, null, SelectTableInfoType.From, true)).Append(" as").Append(++index);
|
||||
parent.DbField = $"-{ExpressionLambdaToSql(exp, _tables, null, SelectTableInfoType.From, true)}";
|
||||
field.Append(", ").Append(parent.DbField).Append(" as").Append(++index);
|
||||
return false;
|
||||
case ExpressionType.Convert: return ReadAnonymousField(_tables, field, parent, ref index, (exp as UnaryExpression)?.Operand);
|
||||
case ExpressionType.Constant:
|
||||
var constExp = exp as ConstantExpression;
|
||||
field.Append(", ").Append(constExp?.Value).Append(" as").Append(++index);
|
||||
parent.DbField = _common.FormatSql("{0}", constExp?.Value);
|
||||
field.Append(", ").Append(parent.DbField).Append(" as").Append(++index);
|
||||
return false;
|
||||
case ExpressionType.Call:
|
||||
field.Append(", ").Append(ExpressionLambdaToSql(exp, _tables, null, SelectTableInfoType.From, true)).Append(" as").Append(++index);
|
||||
parent.DbField = ExpressionLambdaToSql(exp, _tables, null, SelectTableInfoType.From, true);
|
||||
field.Append(", ").Append(parent.DbField).Append(" as").Append(++index);
|
||||
return false;
|
||||
case ExpressionType.MemberAccess:
|
||||
if (_common.GetTableByEntity(exp.Type) != null) { //加载表所有字段
|
||||
@ -36,11 +39,13 @@ namespace FreeSql.Internal {
|
||||
parent.Consturctor = map.First().Table.Table.Type.GetConstructor(new Type[0]);
|
||||
parent.ConsturctorType = ReadAnonymousTypeInfoConsturctorType.Properties;
|
||||
for (var idx = 0; idx < map.Count; idx++) {
|
||||
field.Append(", ").Append(map[idx].Table.Alias).Append(".").Append(_common.QuoteSqlName(map[idx].Column.Attribute.Name)).Append(" as").Append(++index);
|
||||
parent.Childs.Add(new ReadAnonymousTypeInfo { CsName = map[idx].Column.CsName });
|
||||
var child = new ReadAnonymousTypeInfo { CsName = map[idx].Column.CsName, DbField = $"{map[idx].Table.Alias}.{_common.QuoteSqlName(map[idx].Column.Attribute.Name)}" };
|
||||
field.Append(", ").Append(child.DbField).Append(" as").Append(++index);
|
||||
parent.Childs.Add(child);
|
||||
}
|
||||
} else {
|
||||
field.Append(", ").Append(ExpressionLambdaToSql(exp, _tables, null, SelectTableInfoType.From, true)).Append(" as").Append(++index);
|
||||
parent.DbField = ExpressionLambdaToSql(exp, _tables, null, SelectTableInfoType.From, true);
|
||||
field.Append(", ").Append(parent.DbField).Append(" as").Append(++index);
|
||||
return false;
|
||||
}
|
||||
return false;
|
||||
|
@ -16,7 +16,7 @@ namespace FreeSql.Internal.CommonProvider {
|
||||
protected string _select = "SELECT ", _orderby, _groupby, _having;
|
||||
protected StringBuilder _where = new StringBuilder();
|
||||
protected List<DbParameter> _params = new List<DbParameter>();
|
||||
protected List<SelectTableInfo> _tables = new List<SelectTableInfo>();
|
||||
internal List<SelectTableInfo> _tables = new List<SelectTableInfo>();
|
||||
protected StringBuilder _join = new StringBuilder();
|
||||
protected (int seconds, string key) _cache = (0, null);
|
||||
protected IFreeSql _orm;
|
||||
@ -227,7 +227,9 @@ namespace FreeSql.Internal.CommonProvider {
|
||||
protected TMember InternalMin<TMember>(Expression exp) => this.ToList<TMember>($"min({_commonExpression.ExpressionSelectColumn_MemberAccess(_tables, null, SelectTableInfoType.From, exp, true)})").FirstOrDefault();
|
||||
protected TMember InternalSum<TMember>(Expression exp) => this.ToList<TMember>($"sum({_commonExpression.ExpressionSelectColumn_MemberAccess(_tables, null, SelectTableInfoType.From, exp, true)})").FirstOrDefault();
|
||||
|
||||
protected TSelect InternalGroupBy(Expression columns) => this.GroupBy(string.Join(", ", _commonExpression.ExpressionSelectColumns_MemberAccess_New_NewArrayInit(_tables, columns, true)));
|
||||
protected TSelect InternalGroupBy(Expression columns) {
|
||||
return this.GroupBy(string.Join(", ", _commonExpression.ExpressionSelectColumns_MemberAccess_New_NewArrayInit(_tables, columns, true)));
|
||||
}
|
||||
protected TSelect InternalJoin(Expression exp, SelectTableInfoType joinType) {
|
||||
_commonExpression.ExpressionJoinLambda(_tables, joinType, exp);
|
||||
return this as TSelect;
|
||||
@ -245,24 +247,6 @@ namespace FreeSql.Internal.CommonProvider {
|
||||
protected List<TReturn> InternalToList<TReturn>(Expression select) => this.ToList<TReturn>(this.GetNewExpressionField(select as NewExpression));
|
||||
|
||||
protected TSelect InternalWhere(Expression exp) => this.Where(_commonExpression.ExpressionWhereLambda(_tables, exp));
|
||||
protected TSelect InternalWhereLikeOr(Expression columns, string pattern, bool notLike) {
|
||||
if (string.IsNullOrEmpty(pattern)) return this as TSelect;
|
||||
var cols = _commonExpression.ExpressionSelectColumns_MemberAccess_New_NewArrayInit(_tables, columns, true);
|
||||
if (cols.Any() == false) return this as TSelect;
|
||||
var filter = "";
|
||||
foreach (var col in cols) {
|
||||
if (string.IsNullOrEmpty(col)) continue;
|
||||
filter += string.Concat(" OR ", _commonUtils.FormatSql($"{col} {(notLike ? "NOT LIKE" : "LIKE")} {{0}}", pattern));
|
||||
}
|
||||
if (string.IsNullOrEmpty(filter)) return this as TSelect;
|
||||
return this.Where(filter.Substring(4));
|
||||
}
|
||||
protected TSelect InternalWhereLike(Expression column, string pattern, bool notLike) {
|
||||
if (string.IsNullOrEmpty(pattern)) return this as TSelect;
|
||||
string col = _commonExpression.ExpressionSelectColumn_MemberAccess(_tables, null, SelectTableInfoType.From, column, true);
|
||||
if (string.IsNullOrEmpty(col)) return this as TSelect;
|
||||
return this.Where(_commonUtils.FormatSql($"{col} {(notLike ? "NOT LIKE" : "LIKE")} {{0}}", pattern));
|
||||
}
|
||||
|
||||
protected TSelect InternalJoin(Expression exp) {
|
||||
return this as TSelect;
|
||||
|
@ -39,9 +39,5 @@ namespace FreeSql.Internal.CommonProvider {
|
||||
ISelect<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10> ISelect<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10>.Where(Expression<Func<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, bool>> exp) => this.Where(_commonExpression.ExpressionWhereLambda(_tables, exp?.Body));
|
||||
|
||||
ISelect<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10> ISelect<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10>.WhereIf(bool condition, Expression<Func<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, bool>> exp) => condition ? this.Where(_commonExpression.ExpressionWhereLambda(_tables, exp?.Body)) : this;
|
||||
|
||||
ISelect<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10> ISelect<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10>.WhereLike(Expression<Func<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, string[]>> columns, string pattern, bool notLike) => this.InternalWhereLikeOr(columns?.Body, pattern, notLike);
|
||||
|
||||
ISelect<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10> ISelect<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10>.WhereLike(Expression<Func<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, string>> column, string pattern, bool notLike) => this.InternalWhereLike(column?.Body, pattern, notLike);
|
||||
}
|
||||
}
|
@ -29,13 +29,6 @@ namespace FreeSql.Internal.CommonProvider {
|
||||
if (_commonExpression.ExpressionSelectColumn_MemberAccess(null, null, SelectTableInfoType.From, expCall.Arguments[0], false) == "1")
|
||||
this.InternalWhere(expCall.Arguments[1]);
|
||||
break;
|
||||
case "WhereLike":
|
||||
var whereLikeArg0 = (expCall.Arguments[0] as UnaryExpression).Operand as LambdaExpression;
|
||||
var whereLikeArg1 = _commonExpression.ExpressionSelectColumn_MemberAccess(null, null, SelectTableInfoType.From, expCall.Arguments[1], false);
|
||||
var whereLikeArg2 = _commonExpression.ExpressionSelectColumn_MemberAccess(null, null, SelectTableInfoType.From, expCall.Arguments[2], false) == "1";
|
||||
if (whereLikeArg0.ReturnType == typeof(string)) this.InternalWhereLike(whereLikeArg0, whereLikeArg1, whereLikeArg2);
|
||||
else this.InternalWhereLikeOr(whereLikeArg0, whereLikeArg1, whereLikeArg2);
|
||||
break;
|
||||
case "GroupBy": this.InternalGroupBy(expCall.Arguments[0]); break;
|
||||
case "OrderBy": this.InternalOrderBy(expCall.Arguments[0]); break;
|
||||
case "OrderByDescending": this.InternalOrderByDescending(expCall.Arguments[0]); break;
|
||||
@ -80,7 +73,7 @@ namespace FreeSql.Internal.CommonProvider {
|
||||
|
||||
public abstract 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) 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;// { this.InternalFrom(exp?.Body); var ret = new Select10Provider<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10>(_orm, _commonUtils, _commonExpression, null); Select0Provider<ISelect<T1>, T1>.CopyData(this, ret); return ret; }
|
||||
|
||||
public ISelect<T1> GroupBy(Expression<Func<T1, object>> columns) => this.InternalGroupBy(columns?.Body);
|
||||
public ISelect<T1> GroupBy<TReturn>(Expression<Func<T1, TReturn>> columns) => this.InternalGroupBy(columns?.Body);
|
||||
|
||||
public TMember Max<TMember>(Expression<Func<T1, TMember>> column) => this.InternalMax<TMember>(column?.Body);
|
||||
|
||||
@ -105,9 +98,5 @@ namespace FreeSql.Internal.CommonProvider {
|
||||
public ISelect<T1> Where<T2, T3, T4, T5>(Expression<Func<T1, T2, T3, T4, T5, bool>> exp) where T2 : class where T3 : class where T4 : class where T5 : class => this.InternalWhere(exp?.Body);
|
||||
|
||||
public ISelect<T1> WhereIf(bool condition, Expression<Func<T1, bool>> exp) => condition ? this.InternalWhere(exp?.Body) : this;
|
||||
|
||||
public ISelect<T1> WhereLike(Expression<Func<T1, string[]>> columns, string pattern, bool notLike) => this.InternalWhereLikeOr(columns?.Body, pattern, notLike);
|
||||
|
||||
public ISelect<T1> WhereLike(Expression<Func<T1, string>> column, string pattern, bool notLike) => this.InternalWhereLike(column?.Body, pattern, notLike);
|
||||
}
|
||||
}
|
@ -31,9 +31,5 @@ namespace FreeSql.Internal.CommonProvider {
|
||||
ISelect<T1, T2> ISelect<T1, T2>.Where(Expression<Func<T1, T2, bool>> exp) => this.Where(_commonExpression.ExpressionWhereLambda(_tables, exp?.Body));
|
||||
|
||||
ISelect<T1, T2> ISelect<T1, T2>.WhereIf(bool condition, Expression<Func<T1, T2, bool>> exp) => condition ? this.Where(_commonExpression.ExpressionWhereLambda(_tables, exp?.Body)) : this;
|
||||
|
||||
ISelect<T1, T2> ISelect<T1, T2>.WhereLike(Expression<Func<T1, T2, string[]>> columns, string pattern, bool notLike) => this.InternalWhereLikeOr(columns?.Body, pattern, notLike);
|
||||
|
||||
ISelect<T1, T2> ISelect<T1, T2>.WhereLike(Expression<Func<T1, T2, string>> column, string pattern, bool notLike) => this.InternalWhereLike(column?.Body, pattern, notLike);
|
||||
}
|
||||
}
|
@ -32,9 +32,5 @@ namespace FreeSql.Internal.CommonProvider {
|
||||
ISelect<T1, T2, T3> ISelect<T1, T2, T3>.Where(Expression<Func<T1, T2, T3, bool>> exp) => this.Where(_commonExpression.ExpressionWhereLambda(_tables, exp?.Body));
|
||||
|
||||
ISelect<T1, T2, T3> ISelect<T1, T2, T3>.WhereIf(bool condition, Expression<Func<T1, T2, T3, bool>> exp) => condition ? this.Where(_commonExpression.ExpressionWhereLambda(_tables, exp?.Body)) : this;
|
||||
|
||||
ISelect<T1, T2, T3> ISelect<T1, T2, T3>.WhereLike(Expression<Func<T1, T2, T3, string[]>> columns, string pattern, bool notLike) => this.InternalWhereLikeOr(columns?.Body, pattern, notLike);
|
||||
|
||||
ISelect<T1, T2, T3> ISelect<T1, T2, T3>.WhereLike(Expression<Func<T1, T2, T3, string>> column, string pattern, bool notLike) => this.InternalWhereLike(column?.Body, pattern, notLike);
|
||||
}
|
||||
}
|
@ -33,9 +33,5 @@ namespace FreeSql.Internal.CommonProvider {
|
||||
ISelect<T1, T2, T3, T4> ISelect<T1, T2, T3, T4>.Where(Expression<Func<T1, T2, T3, T4, bool>> exp) => this.Where(_commonExpression.ExpressionWhereLambda(_tables, exp?.Body));
|
||||
|
||||
ISelect<T1, T2, T3, T4> ISelect<T1, T2, T3, T4>.WhereIf(bool condition, Expression<Func<T1, T2, T3, T4, bool>> exp) => condition ? this.Where(_commonExpression.ExpressionWhereLambda(_tables, exp?.Body)) : this;
|
||||
|
||||
ISelect<T1, T2, T3, T4> ISelect<T1, T2, T3, T4>.WhereLike(Expression<Func<T1, T2, T3, T4, string[]>> columns, string pattern, bool notLike) => this.InternalWhereLikeOr(columns?.Body, pattern, notLike);
|
||||
|
||||
ISelect<T1, T2, T3, T4> ISelect<T1, T2, T3, T4>.WhereLike(Expression<Func<T1, T2, T3, T4, string>> column, string pattern, bool notLike) => this.InternalWhereLike(column?.Body, pattern, notLike);
|
||||
}
|
||||
}
|
||||
|
@ -34,9 +34,5 @@ namespace FreeSql.Internal.CommonProvider {
|
||||
ISelect<T1, T2, T3, T4, T5> ISelect<T1, T2, T3, T4, T5>.Where(Expression<Func<T1, T2, T3, T4, T5, bool>> exp) => this.Where(_commonExpression.ExpressionWhereLambda(_tables, exp?.Body));
|
||||
|
||||
ISelect<T1, T2, T3, T4, T5> ISelect<T1, T2, T3, T4, T5>.WhereIf(bool condition, Expression<Func<T1, T2, T3, T4, T5, bool>> exp) => condition ? this.Where(_commonExpression.ExpressionWhereLambda(_tables, exp?.Body)) : this;
|
||||
|
||||
ISelect<T1, T2, T3, T4, T5> ISelect<T1, T2, T3, T4, T5>.WhereLike(Expression<Func<T1, T2, T3, T4, T5, string[]>> columns, string pattern, bool notLike) => this.InternalWhereLikeOr(columns?.Body, pattern, notLike);
|
||||
|
||||
ISelect<T1, T2, T3, T4, T5> ISelect<T1, T2, T3, T4, T5>.WhereLike(Expression<Func<T1, T2, T3, T4, T5, string>> column, string pattern, bool notLike) => this.InternalWhereLike(column?.Body, pattern, notLike);
|
||||
}
|
||||
}
|
||||
|
@ -35,9 +35,5 @@ namespace FreeSql.Internal.CommonProvider {
|
||||
ISelect<T1, T2, T3, T4, T5, T6> ISelect<T1, T2, T3, T4, T5, T6>.Where(Expression<Func<T1, T2, T3, T4, T5, T6, bool>> exp) => this.Where(_commonExpression.ExpressionWhereLambda(_tables, exp?.Body));
|
||||
|
||||
ISelect<T1, T2, T3, T4, T5, T6> ISelect<T1, T2, T3, T4, T5, T6>.WhereIf(bool condition, Expression<Func<T1, T2, T3, T4, T5, T6, bool>> exp) => condition ? this.Where(_commonExpression.ExpressionWhereLambda(_tables, exp?.Body)) : this;
|
||||
|
||||
ISelect<T1, T2, T3, T4, T5, T6> ISelect<T1, T2, T3, T4, T5, T6>.WhereLike(Expression<Func<T1, T2, T3, T4, T5, T6, string[]>> columns, string pattern, bool notLike) => this.InternalWhereLikeOr(columns?.Body, pattern, notLike);
|
||||
|
||||
ISelect<T1, T2, T3, T4, T5, T6> ISelect<T1, T2, T3, T4, T5, T6>.WhereLike(Expression<Func<T1, T2, T3, T4, T5, T6, string>> column, string pattern, bool notLike) => this.InternalWhereLike(column?.Body, pattern, notLike);
|
||||
}
|
||||
}
|
@ -36,9 +36,5 @@ namespace FreeSql.Internal.CommonProvider {
|
||||
ISelect<T1, T2, T3, T4, T5, T6, T7> ISelect<T1, T2, T3, T4, T5, T6, T7>.Where(Expression<Func<T1, T2, T3, T4, T5, T6, T7, bool>> exp) => this.Where(_commonExpression.ExpressionWhereLambda(_tables, exp?.Body));
|
||||
|
||||
ISelect<T1, T2, T3, T4, T5, T6, T7> ISelect<T1, T2, T3, T4, T5, T6, T7>.WhereIf(bool condition, Expression<Func<T1, T2, T3, T4, T5, T6, T7, bool>> exp) => condition ? this.Where(_commonExpression.ExpressionWhereLambda(_tables, exp?.Body)) : this;
|
||||
|
||||
ISelect<T1, T2, T3, T4, T5, T6, T7> ISelect<T1, T2, T3, T4, T5, T6, T7>.WhereLike(Expression<Func<T1, T2, T3, T4, T5, T6, T7, string[]>> columns, string pattern, bool notLike) => this.InternalWhereLikeOr(columns?.Body, pattern, notLike);
|
||||
|
||||
ISelect<T1, T2, T3, T4, T5, T6, T7> ISelect<T1, T2, T3, T4, T5, T6, T7>.WhereLike(Expression<Func<T1, T2, T3, T4, T5, T6, T7, string>> column, string pattern, bool notLike) => this.InternalWhereLike(column?.Body, pattern, notLike);
|
||||
}
|
||||
}
|
@ -37,9 +37,5 @@ namespace FreeSql.Internal.CommonProvider {
|
||||
ISelect<T1, T2, T3, T4, T5, T6, T7, T8> ISelect<T1, T2, T3, T4, T5, T6, T7, T8>.Where(Expression<Func<T1, T2, T3, T4, T5, T6, T7, T8, bool>> exp) => this.Where(_commonExpression.ExpressionWhereLambda(_tables, exp?.Body));
|
||||
|
||||
ISelect<T1, T2, T3, T4, T5, T6, T7, T8> ISelect<T1, T2, T3, T4, T5, T6, T7, T8>.WhereIf(bool condition, Expression<Func<T1, T2, T3, T4, T5, T6, T7, T8, bool>> exp) => condition ? this.Where(_commonExpression.ExpressionWhereLambda(_tables, exp?.Body)) : this;
|
||||
|
||||
ISelect<T1, T2, T3, T4, T5, T6, T7, T8> ISelect<T1, T2, T3, T4, T5, T6, T7, T8>.WhereLike(Expression<Func<T1, T2, T3, T4, T5, T6, T7, T8, string[]>> columns, string pattern, bool notLike) => this.InternalWhereLikeOr(columns?.Body, pattern, notLike);
|
||||
|
||||
ISelect<T1, T2, T3, T4, T5, T6, T7, T8> ISelect<T1, T2, T3, T4, T5, T6, T7, T8>.WhereLike(Expression<Func<T1, T2, T3, T4, T5, T6, T7, T8, string>> column, string pattern, bool notLike) => this.InternalWhereLike(column?.Body, pattern, notLike);
|
||||
}
|
||||
}
|
@ -38,9 +38,5 @@ namespace FreeSql.Internal.CommonProvider {
|
||||
ISelect<T1, T2, T3, T4, T5, T6, T7, T8, T9> ISelect<T1, T2, T3, T4, T5, T6, T7, T8, T9>.Where(Expression<Func<T1, T2, T3, T4, T5, T6, T7, T8, T9, bool>> exp) => this.Where(_commonExpression.ExpressionWhereLambda(_tables, exp?.Body));
|
||||
|
||||
ISelect<T1, T2, T3, T4, T5, T6, T7, T8, T9> ISelect<T1, T2, T3, T4, T5, T6, T7, T8, T9>.WhereIf(bool condition, Expression<Func<T1, T2, T3, T4, T5, T6, T7, T8, T9, bool>> exp) => condition ? this.Where(_commonExpression.ExpressionWhereLambda(_tables, exp?.Body)) : this;
|
||||
|
||||
ISelect<T1, T2, T3, T4, T5, T6, T7, T8, T9> ISelect<T1, T2, T3, T4, T5, T6, T7, T8, T9>.WhereLike(Expression<Func<T1, T2, T3, T4, T5, T6, T7, T8, T9, string[]>> columns, string pattern, bool notLike) => this.InternalWhereLikeOr(columns?.Body, pattern, notLike);
|
||||
|
||||
ISelect<T1, T2, T3, T4, T5, T6, T7, T8, T9> ISelect<T1, T2, T3, T4, T5, T6, T7, T8, T9>.WhereLike(Expression<Func<T1, T2, T3, T4, T5, T6, T7, T8, T9, string>> column, string pattern, bool notLike) => this.InternalWhereLike(column?.Body, pattern, notLike);
|
||||
}
|
||||
}
|
||||
|
@ -0,0 +1,42 @@
|
||||
//using FreeSql.Internal.Model;
|
||||
//using System;
|
||||
//using System.Collections.Generic;
|
||||
//using System.Linq.Expressions;
|
||||
//using System.Text;
|
||||
|
||||
//namespace FreeSql.Internal.CommonProvider {
|
||||
// public class SelectGroupingProvider<T1, T2> : ISelectGrouping<T1> where T2 : class {
|
||||
|
||||
// internal Select1Provider<T2> _select;
|
||||
// internal ReadAnonymousTypeInfo _map;
|
||||
// internal CommonExpression _comonExp;
|
||||
// internal SelectTableInfo _table;
|
||||
// SelectGroupingProvider(CommonExpression comonExp, Expression exp) {
|
||||
// _comonExp = comonExp;
|
||||
// //var columns = _comonExp.ExpressionSelectColumns_MemberAccess_New_NewArrayInit(_select._tables, columns, true);
|
||||
// _table = new SelectTableInfo { Alias = "", On = "", Table = _comonExp._common.GetTableByEntity(typeof(T1)), Type = SelectTableInfoType.From };
|
||||
// }
|
||||
|
||||
// public ISelectGrouping<T1> Having(Expression<Func<ISelectGroupingAggregate<T1>, bool>> exp) {
|
||||
// _select.Having(_comonExp.ExpressionWhereLambda(new List<SelectTableInfo>(new[] { _table }), exp));
|
||||
// return this;
|
||||
// }
|
||||
|
||||
// public ISelectGrouping<T1> OrderBy<TMember>(Expression<Func<ISelectGroupingAggregate<T1>, TMember>> column) {
|
||||
// var columnMap = new List<SelectColumnInfo>();
|
||||
// _comonExp.ExpressionSelectColumn_MemberAccess(new List<SelectTableInfo>(new[] { _table }), columnMap, SelectTableInfoType.From, column, true);
|
||||
|
||||
// _select.OrderBy();
|
||||
// return this;
|
||||
// }
|
||||
|
||||
// public ISelectGrouping<T1> OrderByDescending<TMember>(Expression<Func<ISelectGroupingAggregate<T1>, TMember>> column) {
|
||||
// _select.OrderBy(" DESC");
|
||||
// return this;
|
||||
// }
|
||||
|
||||
// public List<TReturn> ToList<TReturn>(Expression<Func<ISelectGroupingAggregate<T1>, TReturn>> select) {
|
||||
// throw new NotImplementedException();
|
||||
// }
|
||||
// }
|
||||
//}
|
@ -7,6 +7,7 @@ namespace FreeSql.Internal.Model {
|
||||
class ReadAnonymousTypeInfo {
|
||||
public string CsName { get; set; }
|
||||
public Type CsType { get; set; }
|
||||
public string DbField { get; set; }
|
||||
public ConstructorInfo Consturctor { get; set; }
|
||||
public ReadAnonymousTypeInfoConsturctorType ConsturctorType { get; set; }
|
||||
public List<ReadAnonymousTypeInfo> Childs = new List<ReadAnonymousTypeInfo>();
|
||||
|
@ -48,7 +48,10 @@ namespace FreeSql.Internal {
|
||||
colattr.DbType = Regex.Replace(colattr.DbType, @"\([^\)]+\)", m => Regex.Replace(m.Groups[0].Value, @"\s", ""));
|
||||
colattr.DbDefautValue = trytb.Properties[p.Name].GetValue(Activator.CreateInstance(trytb.Type));
|
||||
if (colattr.DbDefautValue == null && p.PropertyType.FullName == "System.String") colattr.DbDefautValue = string.Empty;
|
||||
if (colattr.DbDefautValue == null) colattr.DbDefautValue = Activator.CreateInstance(p.PropertyType.GenericTypeArguments.FirstOrDefault() ?? p.PropertyType);
|
||||
if (colattr.DbDefautValue == null) {
|
||||
var consturctorType = p.PropertyType.GenericTypeArguments.FirstOrDefault() ?? p.PropertyType;
|
||||
if (consturctorType.GetConstructor(new Type[0]) != null) colattr.DbDefautValue = Activator.CreateInstance(consturctorType);
|
||||
}
|
||||
if (colattr.DbDefautValue == null) colattr.DbDefautValue = "";
|
||||
if (colattr.DbDefautValue.GetType().FullName == "System.DateTime") colattr.DbDefautValue = new DateTime(1970, 1, 1);
|
||||
|
||||
|
@ -80,94 +80,178 @@ namespace FreeSql.MySql {
|
||||
|
||||
public string GetComparisonDDLStatements<TEntity>() => this.GetComparisonDDLStatements(typeof(TEntity));
|
||||
public string GetComparisonDDLStatements(params Type[] entityTypes) {
|
||||
string database = "";
|
||||
using (var conn = _orm.Ado.MasterPool.Get(TimeSpan.FromSeconds(5))) {
|
||||
database = conn.Value.Database;
|
||||
}
|
||||
var sb = new StringBuilder();
|
||||
foreach (var entityType in entityTypes) {
|
||||
if (sb.Length > 0) sb.Append("\r\n");
|
||||
var tb = _commonUtils.GetTableByEntity(entityType);
|
||||
var tboldname = tb.DbOldName?.Split(new[] { '.' }, 2); //旧表名
|
||||
if (tboldname?.Length == 1) tboldname = new[] { database, tboldname[0] };
|
||||
|
||||
var isRenameTable = false;
|
||||
var tbname = tb.DbName.Split(new[] { '.' }, 2);
|
||||
if (tbname.Length == 1) tbname = new[] { database, tbname[0] };
|
||||
if (_orm.Ado.ExecuteScalar(CommandType.Text, "SELECT 1 FROM information_schema.TABLES WHERE table_schema={0} and table_name={1}".FormatMySql(tbname)) == null) { //表不存在
|
||||
|
||||
if (tboldname != null && _orm.Ado.ExecuteScalar(CommandType.Text, "SELECT 1 FROM information_schema.TABLES WHERE table_schema={0} and table_name={1}".FormatMySql(tboldname)) != null) { //旧表存在
|
||||
//修改表名
|
||||
sb.Append("ALTER TABLE ").Append(_commonUtils.QuoteSqlName($"{tboldname[0]}.{tboldname[1]}")).Append(" RENAME TO ").Append(_commonUtils.QuoteSqlName($"{tbname[0]}.{tbname[1]}")).Append(";\r\n");
|
||||
isRenameTable = true;
|
||||
|
||||
} else {
|
||||
//创建表
|
||||
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);
|
||||
if (tbcol.Attribute.IsIdentity && tbcol.Attribute.DbType.IndexOf("AUTO_INCREMENT", StringComparison.CurrentCultureIgnoreCase) == -1) sb.Append(" AUTO_INCREMENT");
|
||||
sb.Append(",");
|
||||
}
|
||||
if (tb.Primarys.Any() == false)
|
||||
sb.Remove(sb.Length - 1, 1);
|
||||
else {
|
||||
sb.Append(" \r\n PRIMARY KEY (");
|
||||
foreach (var tbcol in tb.Primarys) sb.Append(_commonUtils.QuoteSqlName(tbcol.Attribute.Name)).Append(", ");
|
||||
sb.Remove(sb.Length - 2, 2).Append(")");
|
||||
}
|
||||
sb.Append("\r\n) Engine=InnoDB CHARACTER SET utf8;\r\n");
|
||||
continue;
|
||||
var conn = _orm.Ado.MasterPool.Get(TimeSpan.FromSeconds(5));
|
||||
var database = conn.Value.Database;
|
||||
Func<string, string, object> ExecuteScalar = (db, sql) => {
|
||||
if (string.Compare(database, db) != 0) try { conn.Value.ChangeDatabase(db); } catch { }
|
||||
try {
|
||||
using (var cmd = conn.Value.CreateCommand()) {
|
||||
cmd.CommandText = sql;
|
||||
cmd.CommandType = CommandType.Text;
|
||||
return cmd.ExecuteScalar();
|
||||
}
|
||||
} finally {
|
||||
if (string.Compare(database, db) != 0) conn.Value.ChangeDatabase(database);
|
||||
}
|
||||
//对比字段,只可以修改类型、增加字段、有限的修改字段名;保证安全不删除字段
|
||||
var addcols = new Dictionary<string, ColumnInfo>(StringComparer.CurrentCultureIgnoreCase);
|
||||
foreach (var tbcol in tb.Columns) addcols.Add(tbcol.Value.Attribute.Name, tbcol.Value);
|
||||
var surplus = new Dictionary<string, bool>(StringComparer.CurrentCultureIgnoreCase);
|
||||
var dbcols = new List<DbColumnInfo>();
|
||||
var sql = @"select
|
||||
};
|
||||
var sb = new StringBuilder();
|
||||
try {
|
||||
foreach (var entityType in entityTypes) {
|
||||
if (sb.Length > 0) sb.Append("\r\n");
|
||||
var tb = _commonUtils.GetTableByEntity(entityType);
|
||||
var tbname = tb.DbName.Split(new[] { '.' }, 2);
|
||||
if (tbname?.Length == 1) tbname = new[] { database, tbname[0] };
|
||||
|
||||
var tboldname = tb.DbOldName?.Split(new[] { '.' }, 2); //旧表名
|
||||
if (tboldname?.Length == 1) tboldname = new[] { database, tboldname[0] };
|
||||
|
||||
if (string.Compare(tbname[0], database, true) != 0 && ExecuteScalar(database, $"select 1 from pg_database where datname='{tbname[0]}'") == null) //创建数据库
|
||||
sb.Append($"CREATE DATABASE IF NOT EXISTS ").Append(_commonUtils.QuoteSqlName(tbname[0])).Append(" default charset utf8 COLLATE utf8_general_ci;\r\n");
|
||||
|
||||
var sbalter = new StringBuilder();
|
||||
var istmpatler = false; //创建临时表,导入数据,删除旧表,修改
|
||||
if (ExecuteScalar(tbname[0], "SELECT 1 FROM information_schema.TABLES WHERE table_schema={0} and table_name={1}".FormatMySql(tbname)) == null) { //表不存在
|
||||
if (tboldname != null) {
|
||||
if (string.Compare(tboldname[0], tbname[0], true) != 0 && ExecuteScalar(database, $"select 1 from information_schema.schemata where schema_name='{tboldname[0]}'") == null ||
|
||||
ExecuteScalar(tboldname[0], "SELECT 1 FROM information_schema.TABLES WHERE table_schema={0} and table_name={1}".FormatMySql(tboldname)) == null)
|
||||
//数据库或模式或表不存在
|
||||
tboldname = null;
|
||||
}
|
||||
if (tboldname == null) {
|
||||
//创建表
|
||||
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);
|
||||
if (tbcol.Attribute.IsIdentity && tbcol.Attribute.DbType.IndexOf("AUTO_INCREMENT", StringComparison.CurrentCultureIgnoreCase) == -1) sb.Append(" AUTO_INCREMENT");
|
||||
sb.Append(",");
|
||||
}
|
||||
if (tb.Primarys.Any() == false)
|
||||
sb.Remove(sb.Length - 1, 1);
|
||||
else {
|
||||
sb.Append(" \r\n PRIMARY KEY (");
|
||||
foreach (var tbcol in tb.Primarys) sb.Append(_commonUtils.QuoteSqlName(tbcol.Attribute.Name)).Append(", ");
|
||||
sb.Remove(sb.Length - 2, 2).Append(")");
|
||||
}
|
||||
sb.Append("\r\n) Engine=InnoDB CHARACTER SET utf8;\r\n");
|
||||
continue;
|
||||
}
|
||||
//如果新表,旧表在一个数据库下,直接修改表名
|
||||
if (string.Compare(tbname[0], tboldname[0], true) == 0)
|
||||
sbalter.Append("ALTER TABLE ").Append(_commonUtils.QuoteSqlName($"{tboldname[0]}.{tboldname[1]}")).Append(" RENAME TO ").Append(_commonUtils.QuoteSqlName($"{tbname[0]}.{tbname[1]}")).Append(";\r\n");
|
||||
else {
|
||||
//如果新表,旧表不在一起,创建新表,导入数据,删除旧表
|
||||
istmpatler = true;
|
||||
}
|
||||
} else
|
||||
tboldname = null; //如果新表已经存在,不走改表名逻辑
|
||||
|
||||
//对比字段,只可以修改类型、增加字段、有限的修改字段名;保证安全不删除字段
|
||||
var addcols = new Dictionary<string, ColumnInfo>(StringComparer.CurrentCultureIgnoreCase);
|
||||
foreach (var tbcol in tb.Columns) addcols.Add(tbcol.Value.Attribute.Name, tbcol.Value);
|
||||
var surplus = new Dictionary<string, bool>(StringComparer.CurrentCultureIgnoreCase);
|
||||
var dbcols = new List<DbColumnInfo>();
|
||||
var sql = @"select
|
||||
a.column_name,
|
||||
a.column_type,
|
||||
case when a.is_nullable = 'YES' then 1 else 0 end 'is_nullable',
|
||||
case when locate('auto_increment', a.extra) > 0 then 1 else 0 end 'is_identity'
|
||||
from information_schema.columns a
|
||||
where a.table_schema in ({0}) and a.table_name in ({1})".FormatMySql(isRenameTable ? tboldname : tbname);
|
||||
var ds = _orm.Ado.ExecuteArray(CommandType.Text, sql);
|
||||
foreach (var row in ds) {
|
||||
string column = string.Concat(row[0]);
|
||||
string sqlType = string.Concat(row[1]);
|
||||
bool is_nullable = string.Concat(row[2]) == "1";
|
||||
bool is_identity = string.Concat(row[3]) == "1";
|
||||
bool is_unsigned = sqlType.EndsWith(" unsigned");
|
||||
where a.table_schema in ({0}) and a.table_name in ({1})".FormatMySql(tboldname ?? tbname);
|
||||
var ds = _orm.Ado.ExecuteArray(CommandType.Text, sql);
|
||||
var tbstruct = ds.ToDictionary(a => string.Concat(a[0]), a => new {
|
||||
column = string.Concat(a[0]),
|
||||
sqlType = string.Concat(a[1]),
|
||||
is_nullable = string.Concat(a[2]) == "1",
|
||||
is_identity = string.Concat(a[3]) == "1",
|
||||
is_unsigned = string.Concat(a[1]).EndsWith(" unsigned")
|
||||
}, StringComparer.CurrentCultureIgnoreCase);
|
||||
|
||||
if (addcols.TryGetValue(column, out var trycol)) {
|
||||
if ((trycol.Attribute.DbType.IndexOf(" unsigned", StringComparison.CurrentCultureIgnoreCase) != -1) != is_unsigned ||
|
||||
trycol.Attribute.DbType.StartsWith(sqlType, StringComparison.CurrentCultureIgnoreCase) == false ||
|
||||
trycol.Attribute.IsNullable != is_nullable ||
|
||||
trycol.Attribute.IsIdentity != is_identity) {
|
||||
sb.Append("ALTER TABLE ").Append(_commonUtils.QuoteSqlName($"{tbname[0]}.{tbname[1]}")).Append(" MODIFY ").Append(_commonUtils.QuoteSqlName(column)).Append(" ").Append(trycol.Attribute.DbType);
|
||||
if (trycol.Attribute.IsIdentity && trycol.Attribute.DbType.IndexOf("AUTO_INCREMENT", StringComparison.CurrentCultureIgnoreCase) == -1) sb.Append(" AUTO_INCREMENT");
|
||||
sb.Append(";\r\n");
|
||||
if (istmpatler == false) {
|
||||
foreach (var tbcol in tb.Columns.Values) {
|
||||
if (tbstruct.TryGetValue(tbcol.Attribute.Name, out var tbstructcol) ||
|
||||
string.IsNullOrEmpty(tbcol.Attribute.OldName) == false && tbstruct.TryGetValue(tbcol.Attribute.OldName, out tbstructcol)) {
|
||||
if ((tbcol.Attribute.DbType.IndexOf(" unsigned", StringComparison.CurrentCultureIgnoreCase) != -1) != tbstructcol.is_unsigned ||
|
||||
tbcol.Attribute.DbType.StartsWith(tbstructcol.sqlType, StringComparison.CurrentCultureIgnoreCase) == false ||
|
||||
tbcol.Attribute.IsNullable != tbstructcol.is_nullable ||
|
||||
tbcol.Attribute.IsIdentity != tbstructcol.is_identity) {
|
||||
sbalter.Append("ALTER TABLE ").Append(_commonUtils.QuoteSqlName($"{tbname[0]}.{tbname[1]}")).Append(" MODIFY ").Append(_commonUtils.QuoteSqlName(tbstructcol.column)).Append(" ").Append(tbcol.Attribute.DbType);
|
||||
if (tbcol.Attribute.IsIdentity && tbcol.Attribute.DbType.IndexOf("AUTO_INCREMENT", StringComparison.CurrentCultureIgnoreCase) == -1) sbalter.Append(" AUTO_INCREMENT");
|
||||
sbalter.Append(";\r\n");
|
||||
}
|
||||
if (tbstructcol.column == tbcol.Attribute.OldName) {
|
||||
//修改列名
|
||||
sbalter.Append("ALTER TABLE ").Append(_commonUtils.QuoteSqlName($"{tbname[0]}.{tbname[1]}")).Append(" CHANGE COLUMN ").Append(_commonUtils.QuoteSqlName(tbcol.Attribute.OldName)).Append(" ").Append(_commonUtils.QuoteSqlName(tbcol.Attribute.Name)).Append(" ").Append(tbcol.Attribute.DbType);
|
||||
if (tbcol.Attribute.IsIdentity && tbcol.Attribute.DbType.IndexOf("AUTO_INCREMENT", StringComparison.CurrentCultureIgnoreCase) == -1) sb.Append(" AUTO_INCREMENT");
|
||||
sbalter.Append(";\r\n");
|
||||
}
|
||||
continue;
|
||||
}
|
||||
//添加列
|
||||
sbalter.Append("ALTER TABLE ").Append(_commonUtils.QuoteSqlName($"{tbname[0]}.{tbname[1]}")).Append(" ADD ").Append(_commonUtils.QuoteSqlName(tbcol.Attribute.Name)).Append(" ").Append(tbcol.Attribute.DbType);
|
||||
if (tbcol.Attribute.IsIdentity && tbcol.Attribute.DbType.IndexOf("AUTO_INCREMENT", StringComparison.CurrentCultureIgnoreCase) == -1) sbalter.Append(" AUTO_INCREMENT");
|
||||
sbalter.Append(";\r\n");
|
||||
}
|
||||
addcols.Remove(column);
|
||||
} else
|
||||
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(" CHANGE COLUMN ").Append(_commonUtils.QuoteSqlName(addcol.Attribute.OldName)).Append(" ").Append(_commonUtils.QuoteSqlName(addcol.Attribute.Name)).Append(" ").Append(addcol.Attribute.DbType);
|
||||
if (addcol.Attribute.IsIdentity && addcol.Attribute.DbType.IndexOf("AUTO_INCREMENT", StringComparison.CurrentCultureIgnoreCase) == -1) sb.Append(" AUTO_INCREMENT");
|
||||
sb.Append(";\r\n");
|
||||
|
||||
} else { //添加列
|
||||
sb.Append("ALTER TABLE ").Append(_commonUtils.QuoteSqlName($"{tbname[0]}.{tbname[1]}")).Append(" ADD ").Append(_commonUtils.QuoteSqlName(addcol.Attribute.Name)).Append(" ").Append(addcol.Attribute.DbType);
|
||||
if (addcol.Attribute.IsIdentity && addcol.Attribute.DbType.IndexOf("AUTO_INCREMENT", StringComparison.CurrentCultureIgnoreCase) == -1) sb.Append(" AUTO_INCREMENT");
|
||||
sb.Append(";\r\n");
|
||||
}
|
||||
if (istmpatler == false) {
|
||||
sb.Append(sbalter);
|
||||
continue;
|
||||
}
|
||||
|
||||
//创建临时表,数据导进临时表,然后删除原表,将临时表改名为原表名
|
||||
var tablename = tboldname == null ? _commonUtils.QuoteSqlName($"{tbname[0]}.{tbname[1]}") : _commonUtils.QuoteSqlName($"{tboldname[0]}.{tboldname[1]}");
|
||||
var tmptablename = _commonUtils.QuoteSqlName($"{tbname[0]}.FreeSqlTmp_{tbname[1]}");
|
||||
//创建临时表
|
||||
sb.Append("CREATE TABLE IF NOT EXISTS ").Append(tmptablename).Append(" (");
|
||||
foreach (var tbcol in tb.Columns.Values) {
|
||||
sb.Append(" \r\n ").Append(_commonUtils.QuoteSqlName(tbcol.Attribute.Name)).Append(" ");
|
||||
sb.Append(tbcol.Attribute.DbType);
|
||||
if (tbcol.Attribute.IsIdentity && tbcol.Attribute.DbType.IndexOf("AUTO_INCREMENT", StringComparison.CurrentCultureIgnoreCase) == -1) sb.Append(" AUTO_INCREMENT");
|
||||
sb.Append(",");
|
||||
}
|
||||
if (tb.Primarys.Any() == false)
|
||||
sb.Remove(sb.Length - 1, 1);
|
||||
else {
|
||||
sb.Append(" \r\n PRIMARY KEY (");
|
||||
foreach (var tbcol in tb.Primarys) sb.Append(_commonUtils.QuoteSqlName(tbcol.Attribute.Name)).Append(", ");
|
||||
sb.Remove(sb.Length - 2, 2).Append(")");
|
||||
}
|
||||
sb.Append("\r\n) Engine=InnoDB CHARACTER SET utf8;\r\n");
|
||||
sb.Append("INSERT INTO ").Append(tmptablename).Append(" (");
|
||||
foreach (var tbcol in tb.Columns.Values) {
|
||||
if (tbstruct.ContainsKey(tbcol.Attribute.Name) ||
|
||||
string.IsNullOrEmpty(tbcol.Attribute.OldName) == false && tbstruct.ContainsKey(tbcol.Attribute.OldName)) { //导入旧表存在的字段
|
||||
sb.Append(_commonUtils.QuoteSqlName(tbcol.Attribute.Name)).Append(", ");
|
||||
}
|
||||
}
|
||||
sb.Remove(sb.Length - 2, 2).Append(")\r\nSELECT ");
|
||||
foreach (var tbcol in tb.Columns.Values) {
|
||||
if (tbstruct.TryGetValue(tbcol.Attribute.Name, out var tbstructcol) ||
|
||||
string.IsNullOrEmpty(tbcol.Attribute.OldName) == false && tbstruct.TryGetValue(tbcol.Attribute.OldName, out tbstructcol)) {
|
||||
var insertvalue = _commonUtils.QuoteSqlName(tbstructcol.column);
|
||||
if (tbcol.Attribute.DbType.StartsWith(tbstructcol.sqlType, StringComparison.CurrentCultureIgnoreCase) == false) {
|
||||
//var tbcoldbtype = tbcol.Attribute.DbType.Split(' ').First();
|
||||
//insertvalue = $"cast({insertvalue} as {tbcoldbtype})";
|
||||
}
|
||||
if (tbcol.Attribute.IsNullable != tbstructcol.is_nullable) {
|
||||
insertvalue = $"ifnull({insertvalue},{_commonUtils.FormatSql("{0}", tbcol.Attribute.DbDefautValue).Replace("'", "''")})";
|
||||
}
|
||||
sb.Append(insertvalue).Append(", ");
|
||||
}
|
||||
}
|
||||
sb.Remove(sb.Length - 2, 2).Append(" FROM ").Append(tablename).Append(";\r\n");
|
||||
sb.Append("DROP TABLE ").Append(tablename).Append(";\r\n");
|
||||
sb.Append("ALTER TABLE ").Append(tmptablename).Append(" RENAME TO ").Append(_commonUtils.QuoteSqlName($"{tbname[0]}.{tbname[1]}")).Append(";\r\n");
|
||||
}
|
||||
return sb.Length == 0 ? null : sb.ToString();
|
||||
} finally {
|
||||
try {
|
||||
conn.Value.ChangeDatabase(database);
|
||||
_orm.Ado.MasterPool.Return(conn);
|
||||
} catch {
|
||||
_orm.Ado.MasterPool.Return(conn, true);
|
||||
}
|
||||
}
|
||||
return sb.Length == 0 ? null : sb.ToString();
|
||||
}
|
||||
|
||||
ConcurrentDictionary<string, bool> dicSyced = new ConcurrentDictionary<string, bool>();
|
||||
|
@ -101,8 +101,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.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);
|
||||
(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);
|
||||
if (_dicCsToDb.ContainsKey(type.FullName) == false) {
|
||||
lock (_dicCsToDbLock) {
|
||||
if (_dicCsToDb.ContainsKey(type.FullName) == false)
|
||||
@ -118,23 +118,28 @@ namespace FreeSql.PostgreSQL {
|
||||
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);
|
||||
var tbname = tb.DbName.Split(new[] { '.' }, 2);
|
||||
if (tbname?.Length == 1) tbname = new[] { "public", tbname[0] };
|
||||
|
||||
var tboldname = tb.DbOldName?.Split(new[] { '.' }, 2); //旧表名
|
||||
if (tboldname?.Length == 1) tboldname = new[] { "public", tboldname[0] };
|
||||
|
||||
var isRenameTable = false;
|
||||
var tbname = tb.DbName.Split(new[] { '.' }, 2);
|
||||
if (tbname.Length == 1) tbname = new[] { "public", tbname[0] };
|
||||
if (_orm.Ado.ExecuteScalar(CommandType.Text, "select 1 from pg_tables a inner join pg_namespace b on b.nspname = a.schemaname where b.nspname || '.' || a.tablename = {0}.{1}".FormatPostgreSQL(tbname)) == null) { //表不存在
|
||||
if (string.Compare(tbname[0], "public", true) != 0 && _orm.Ado.ExecuteScalar(CommandType.Text, $"select 1 from pg_namespace where nspname='{tbname[0]}'") == null) //创建模式
|
||||
sb.Append("CREATE SCHEMA IF NOT EXISTS ").Append(tbname[0]).Append(";\r\n");
|
||||
|
||||
if (tboldname != null && _orm.Ado.ExecuteScalar(CommandType.Text, "select 1 from pg_tables a inner join pg_namespace b on b.nspname = a.schemaname where b.nspname || '.' || a.tablename = {0}.{1}".FormatPostgreSQL(tboldname)) != null) { //旧表存在
|
||||
//修改表名
|
||||
sb.Append("ALTER TABLE ").Append(_commonUtils.QuoteSqlName($"{tboldname[0]}.{tboldname[1]}")).Append(" RENAME TO ").Append(_commonUtils.QuoteSqlName($"{tbname[0]}.{tbname[1]}")).Append(";\r\n");
|
||||
isRenameTable = true;
|
||||
|
||||
} else {
|
||||
var sbalter = new StringBuilder();
|
||||
var istmpatler = false; //创建临时表,导入数据,删除旧表,修改
|
||||
if (_orm.Ado.ExecuteScalar(CommandType.Text, string.Format("select 1 from pg_tables a inner join pg_namespace b on b.nspname = a.schemaname where b.nspname || '.' || a.tablename = '{0}.{1}'", tbname)) == null) { //表不存在
|
||||
if (tboldname != null) {
|
||||
if (_orm.Ado.ExecuteScalar(CommandType.Text, string.Format("select 1 from pg_tables a inner join pg_namespace b on b.nspname = a.schemaname where b.nspname || '.' || a.tablename = '{0}.{1}'", tboldname)) == null)
|
||||
//旧表不存在
|
||||
tboldname = null;
|
||||
}
|
||||
if (tboldname == null) {
|
||||
//创建表
|
||||
sb.Append("CREATE TABLE IF NOT EXISTS ").Append(_commonUtils.QuoteSqlName($"{tbname[0]}.{tbname[1]}")).Append(" (");
|
||||
foreach (var tbcol in tb.Columns.Values) {
|
||||
@ -151,19 +156,24 @@ namespace FreeSql.PostgreSQL {
|
||||
sb.Append("\r\n) WITH (OIDS=FALSE);\r\n");
|
||||
continue;
|
||||
}
|
||||
}
|
||||
//如果新表,旧表在一个数据库和模式下,直接修改表名
|
||||
if (string.Compare(tbname[0], tboldname[0], true) == 0)
|
||||
sbalter.Append("ALTER TABLE ").Append(_commonUtils.QuoteSqlName($"{tboldname[0]}.{tboldname[1]}")).Append(" RENAME TO ").Append(_commonUtils.QuoteSqlName($"{tbname[1]}")).Append(";\r\n");
|
||||
else {
|
||||
//如果新表,旧表不在一起,创建新表,导入数据,删除旧表
|
||||
istmpatler = true;
|
||||
}
|
||||
} else
|
||||
tboldname = null; //如果新表已经存在,不走改表名逻辑
|
||||
|
||||
//对比字段,只可以修改类型、增加字段、有限的修改字段名;保证安全不删除字段
|
||||
var addcols = new Dictionary<string, ColumnInfo>(StringComparer.CurrentCultureIgnoreCase);
|
||||
foreach (var tbcol in tb.Columns) addcols.Add(tbcol.Value.Attribute.Name, tbcol.Value);
|
||||
var surplus = new Dictionary<string, bool>(StringComparer.CurrentCultureIgnoreCase);
|
||||
var dbcols = new List<DbColumnInfo>();
|
||||
var sql = @"select
|
||||
a.attname,
|
||||
t.typname,
|
||||
case when a.atttypmod > 0 and a.atttypmod < 32767 then a.atttypmod - 4 else a.attlen end len,
|
||||
case when t.typelem = 0 then t.typname else t2.typname end,
|
||||
case when a.attnotnull then '0' else '1' end as is_nullable,
|
||||
case when e.adsrc = 1 then '1' else '0' end as is_identity,
|
||||
e.adsrc,
|
||||
a.attndims
|
||||
from pg_class c
|
||||
inner join pg_attribute a on a.attnum > 0 and a.attrelid = c.oid
|
||||
@ -173,47 +183,96 @@ left join pg_description d on d.objoid = a.attrelid and d.objsubid = a.attnum
|
||||
left join pg_attrdef e on e.adrelid = a.attrelid and e.adnum = a.attnum
|
||||
inner join pg_namespace ns on ns.oid = c.relnamespace
|
||||
inner join pg_namespace ns2 on ns2.oid = t.typnamespace
|
||||
where ns.nspname = {0} and c.relname = {1}".FormatPostgreSQL(isRenameTable ? tboldname : tbname);
|
||||
where ns.nspname = {0} and c.relname = {1}".FormatPostgreSQL(tboldname ?? tbname);
|
||||
var ds = _orm.Ado.ExecuteArray(CommandType.Text, sql);
|
||||
foreach (var row in ds) {
|
||||
string column = string.Concat(row[0]);
|
||||
string sqlType = string.Concat(row[3]);
|
||||
long max_length = long.Parse(string.Concat(row[2]));
|
||||
bool is_nullable = string.Concat(row[4]) == "1";
|
||||
bool is_identity = string.Concat(row[5]).StartsWith(@"nextval('") && string.Concat(row[6]).EndsWith(@"_seq'::regclass)");
|
||||
var attndims = long.Parse(string.Concat(row[6]));
|
||||
if (attndims > 0) sqlType += "[]";
|
||||
var tbstruct = ds.ToDictionary(a => string.Concat(a[0]), a => new {
|
||||
column = string.Concat(a[0]),
|
||||
sqlType = string.Concat(a[3], long.Parse(string.Concat(a[6])) > 0 ? "[]" : ""),
|
||||
max_length = long.Parse(string.Concat(a[2])),
|
||||
is_nullable = string.Concat(a[4]) == "1",
|
||||
is_identity = string.Concat(a[5]).StartsWith(@"nextval('") && string.Concat(a[5]).EndsWith(@"'::regclass)"),
|
||||
attndims = long.Parse(string.Concat(a[6]))
|
||||
}, StringComparer.CurrentCultureIgnoreCase);
|
||||
|
||||
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) {
|
||||
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 (istmpatler == false) {
|
||||
foreach (var tbcol in tb.Columns.Values) {
|
||||
if (tbstruct.TryGetValue(tbcol.Attribute.Name, out var tbstructcol) ||
|
||||
string.IsNullOrEmpty(tbcol.Attribute.OldName) == false && tbstruct.TryGetValue(tbcol.Attribute.OldName, out tbstructcol)) {
|
||||
if (tbcol.Attribute.DbType.StartsWith(tbstructcol.sqlType, StringComparison.CurrentCultureIgnoreCase) == false ||
|
||||
tbcol.Attribute.IsNullable != tbstructcol.is_nullable) {
|
||||
sbalter.Append("ALTER TABLE ").Append(_commonUtils.QuoteSqlName($"{tbname[0]}.{tbname[1]}")).Append(" ALTER COLUMN ").Append(_commonUtils.QuoteSqlName(tbstructcol.column)).Append(" TYPE ").Append(tbcol.Attribute.DbType.ToUpper()).Append(";\r\n");
|
||||
break;
|
||||
}
|
||||
if (tbcol.Attribute.IsIdentity != tbstructcol.is_identity) seqcols.Add((tbcol, tbname, tbcol.Attribute.IsIdentity));
|
||||
if (tbstructcol.column == tbcol.Attribute.OldName) {
|
||||
//修改列名
|
||||
sbalter.Append("ALTER TABLE ").Append(_commonUtils.QuoteSqlName($"{tbname[0]}.{tbname[1]}")).Append(" RENAME COLUMN ").Append(_commonUtils.QuoteSqlName(tbcol.Attribute.OldName)).Append(" TO ").Append(_commonUtils.QuoteSqlName(tbcol.Attribute.Name)).Append(";\r\n");
|
||||
}
|
||||
continue;
|
||||
}
|
||||
if (trycol.Attribute.IsIdentity != is_identity) seqcols.Add((trycol, tbname, trycol.Attribute.IsIdentity));
|
||||
addcols.Remove(column);
|
||||
} else {
|
||||
if (trycol.Attribute.IsIdentity != is_identity) seqcols.Add((trycol, tbname, trycol.Attribute.IsIdentity));
|
||||
surplus.Add(column, true); //记录剩余字段
|
||||
//添加列
|
||||
sbalter.Append("ALTER TABLE ").Append(_commonUtils.QuoteSqlName($"{tbname[0]}.{tbname[1]}")).Append(" ADD COLUMN ").Append(_commonUtils.QuoteSqlName(tbcol.Attribute.Name)).Append(" ").Append(tbcol.Attribute.DbType.ToUpper()).Append(";\r\n");
|
||||
if (tbcol.Attribute.IsIdentity != tbstructcol.is_identity) seqcols.Add((tbcol, tbname, tbcol.Attribute.IsIdentity));
|
||||
}
|
||||
}
|
||||
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");
|
||||
} 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()).Append(";\r\n");
|
||||
if (istmpatler == false) {
|
||||
sb.Append(sbalter);
|
||||
continue;
|
||||
}
|
||||
//创建临时表,数据导进临时表,然后删除原表,将临时表改名为原表名
|
||||
var tablename = tboldname == null ? _commonUtils.QuoteSqlName($"{tbname[0]}.{tbname[1]}") : _commonUtils.QuoteSqlName($"{tboldname[0]}.{tboldname[1]}");
|
||||
var tmptablename = _commonUtils.QuoteSqlName($"{tbname[0]}.FreeSqlTmp_{tbname[1]}");
|
||||
//创建临时表
|
||||
sb.Append("CREATE TABLE IF NOT EXISTS ").Append(tmptablename).Append(" (");
|
||||
foreach (var tbcol in tb.Columns.Values) {
|
||||
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);
|
||||
else {
|
||||
sb.Append(" \r\n CONSTRAINT ").Append(tbname[0]).Append("_").Append(tbname[1]).Append("_pkey PRIMARY KEY (");
|
||||
foreach (var tbcol in tb.Primarys) sb.Append(_commonUtils.QuoteSqlName(tbcol.Attribute.Name)).Append(", ");
|
||||
sb.Remove(sb.Length - 2, 2).Append(")");
|
||||
}
|
||||
sb.Append("\r\n) WITH (OIDS=FALSE);\r\n");
|
||||
sb.Append("INSERT INTO ").Append(tmptablename).Append(" (");
|
||||
foreach (var tbcol in tb.Columns.Values) {
|
||||
if (tbstruct.ContainsKey(tbcol.Attribute.Name) ||
|
||||
string.IsNullOrEmpty(tbcol.Attribute.OldName) == false && tbstruct.ContainsKey(tbcol.Attribute.OldName)) { //导入旧表存在的字段
|
||||
sb.Append(_commonUtils.QuoteSqlName(tbcol.Attribute.Name)).Append(", ");
|
||||
}
|
||||
}
|
||||
sb.Remove(sb.Length - 2, 2).Append(")\r\nSELECT ");
|
||||
foreach (var tbcol in tb.Columns.Values) {
|
||||
if (tbstruct.TryGetValue(tbcol.Attribute.Name, out var tbstructcol) ||
|
||||
string.IsNullOrEmpty(tbcol.Attribute.OldName) == false && tbstruct.TryGetValue(tbcol.Attribute.OldName, out tbstructcol)) {
|
||||
var insertvalue = _commonUtils.QuoteSqlName(tbstructcol.column);
|
||||
if (tbcol.Attribute.DbType.StartsWith(tbstructcol.sqlType, StringComparison.CurrentCultureIgnoreCase) == false) {
|
||||
var tbcoldbtype = tbcol.Attribute.DbType.Split(' ').First();
|
||||
insertvalue = $"cast({insertvalue} as {tbcoldbtype})";
|
||||
}
|
||||
if (tbcol.Attribute.IsNullable != tbstructcol.is_nullable) {
|
||||
insertvalue = $"ifnull({insertvalue},{_commonUtils.FormatSql("{0}", tbcol.Attribute.DbDefautValue).Replace("'", "''")})";
|
||||
}
|
||||
sb.Append(insertvalue).Append(", ");
|
||||
}
|
||||
}
|
||||
sb.Remove(sb.Length - 2, 2).Append(" FROM ").Append(tablename).Append(";\r\n");
|
||||
sb.Append("DROP TABLE ").Append(tablename).Append(";\r\n");
|
||||
sb.Append("ALTER TABLE ").Append(tmptablename).Append(" RENAME TO ").Append(_commonUtils.QuoteSqlName(tbname[1])).Append(";\r\n");
|
||||
}
|
||||
foreach(var seqcol in seqcols) {
|
||||
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(";");
|
||||
sb.Append("ALTER TABLE ").Append(tbname2).Append(" ALTER COLUMN ").Append(colname2).Append(" SET DEFAULT null;\r\n");
|
||||
sb.Append("DROP SEQUENCE IF EXISTS ").Append(seqname).Append(";\r\n");
|
||||
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);");
|
||||
sb.Append("CREATE SEQUENCE ").Append(seqname).Append(";\r\n");
|
||||
sb.Append("ALTER TABLE ").Append(tbname2).Append(" ALTER COLUMN ").Append(colname2).Append(" SET DEFAULT nextval('").Append(seqname).Append("'::regclass);\r\n");
|
||||
sb.Append("SELECT case when max(").Append(colname2).Append(") is null then 0 else setval('").Append(seqname).Append("', max(").Append(colname2).Append(")) end FROM ").Append(tbname2).Append(";\r\n");
|
||||
}
|
||||
}
|
||||
return sb.Length == 0 ? null : sb.ToString();
|
||||
|
@ -195,9 +195,8 @@ namespace FreeSql.PostgreSQL {
|
||||
case "ToUInt32":
|
||||
case "ToUInt64": return $"cast({ExpressionLambdaToSql(exp.Arguments[0], _tables, _selectColumnMap, tbtype, isQuoteName)} as unsigned)";
|
||||
}
|
||||
throw new Exception($"MySqlExpression 未现实函数表达式 {exp} 解析");
|
||||
}
|
||||
throw new Exception($"MySqlExpression 未现实函数表达式 {exp} 解析");
|
||||
throw new Exception($"PostgreSQLExpression 未现实函数表达式 {exp} 解析");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -1,6 +1,6 @@
|
||||
using FreeSql.Internal;
|
||||
using FreeSql.Internal.CommonProvider;
|
||||
using FreeSql.MySql.Curd;
|
||||
using FreeSql.PostgreSQL.Curd;
|
||||
using Microsoft.Extensions.Caching.Distributed;
|
||||
using Microsoft.Extensions.Configuration;
|
||||
using Microsoft.Extensions.Logging;
|
||||
@ -11,15 +11,15 @@ namespace FreeSql.PostgreSQL {
|
||||
|
||||
class PostgreSQLProvider : IFreeSql {
|
||||
|
||||
public ISelect<T1> Select<T1>() where T1 : class => new MySqlSelect<T1>(this, this.InternalCommonUtils, this.InternalCommonExpression, null);
|
||||
public ISelect<T1> Select<T1>(object dywhere) where T1 : class => new MySqlSelect<T1>(this, this.InternalCommonUtils, this.InternalCommonExpression, dywhere);
|
||||
public IInsert<T1> Insert<T1>() where T1 : class => new MySqlInsert<T1>(this, this.InternalCommonUtils, this.InternalCommonExpression);
|
||||
public ISelect<T1> Select<T1>() where T1 : class => new PostgreSQLSelect<T1>(this, this.InternalCommonUtils, this.InternalCommonExpression, null);
|
||||
public ISelect<T1> Select<T1>(object dywhere) where T1 : class => new PostgreSQLSelect<T1>(this, this.InternalCommonUtils, this.InternalCommonExpression, dywhere);
|
||||
public IInsert<T1> Insert<T1>() where T1 : class => new PostgreSQLInsert<T1>(this, this.InternalCommonUtils, this.InternalCommonExpression);
|
||||
public IInsert<T1> Insert<T1>(T1 source) where T1 : class => this.Insert<T1>().AppendData(source);
|
||||
public IInsert<T1> Insert<T1>(IEnumerable<T1> source) where T1 : class => this.Insert<T1>().AppendData(source);
|
||||
public IUpdate<T1> Update<T1>() where T1 : class => new MySqlUpdate<T1>(this, this.InternalCommonUtils, this.InternalCommonExpression, null);
|
||||
public IUpdate<T1> Update<T1>(object dywhere) where T1 : class => new MySqlUpdate<T1>(this, this.InternalCommonUtils, this.InternalCommonExpression, dywhere);
|
||||
public IDelete<T1> Delete<T1>() where T1 : class => new MySqlDelete<T1>(this, this.InternalCommonUtils, this.InternalCommonExpression, null);
|
||||
public IDelete<T1> Delete<T1>(object dywhere) where T1 : class => new MySqlDelete<T1>(this, this.InternalCommonUtils, this.InternalCommonExpression, dywhere);
|
||||
public IUpdate<T1> Update<T1>() where T1 : class => new PostgreSQLUpdate<T1>(this, this.InternalCommonUtils, this.InternalCommonExpression, null);
|
||||
public IUpdate<T1> Update<T1>(object dywhere) where T1 : class => new PostgreSQLUpdate<T1>(this, this.InternalCommonUtils, this.InternalCommonExpression, dywhere);
|
||||
public IDelete<T1> Delete<T1>() where T1 : class => new PostgreSQLDelete<T1>(this, this.InternalCommonUtils, this.InternalCommonExpression, null);
|
||||
public IDelete<T1> Delete<T1>(object dywhere) where T1 : class => new PostgreSQLDelete<T1>(this, this.InternalCommonUtils, this.InternalCommonExpression, dywhere);
|
||||
|
||||
public IAdo Ado { get; }
|
||||
public ICache Cache { get; }
|
||||
@ -29,7 +29,7 @@ namespace FreeSql.PostgreSQL {
|
||||
CacheStrategy = cacheStrategy;
|
||||
if (log == null) log = new LoggerFactory(new[] { new Microsoft.Extensions.Logging.Debug.DebugLoggerProvider() }).CreateLogger("FreeSql.PostgreSQL");
|
||||
|
||||
this.InternalCommonUtils = new MySqlUtils(this);
|
||||
this.InternalCommonUtils = new PostgreSQLUtils(this);
|
||||
this.InternalCommonExpression = new PostgreSQLExpression(this.InternalCommonUtils);
|
||||
|
||||
this.Cache = new CacheProvider(cache, log);
|
||||
|
@ -8,10 +8,10 @@ using System.Linq;
|
||||
|
||||
namespace FreeSql.PostgreSQL {
|
||||
|
||||
class MySqlUtils : CommonUtils {
|
||||
class PostgreSQLUtils : CommonUtils {
|
||||
IFreeSql _orm;
|
||||
public MySqlUtils(IFreeSql mysql) {
|
||||
_orm = mysql;
|
||||
public PostgreSQLUtils(IFreeSql orm) {
|
||||
_orm = orm;
|
||||
}
|
||||
|
||||
internal override DbParameter AppendParamter(List<DbParameter> _params, string parameterName, object value) {
|
||||
@ -24,12 +24,12 @@ namespace FreeSql.PostgreSQL {
|
||||
ParameterName = parameterName,
|
||||
Value = value
|
||||
};
|
||||
if (value.GetType().IsEnum || value.GetType().GenericTypeArguments.FirstOrDefault()?.IsEnum == true) {
|
||||
ret.DataTypeName = "";
|
||||
} else {
|
||||
//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;
|
||||
@ -41,16 +41,16 @@ namespace FreeSql.PostgreSQL {
|
||||
ParameterName = name,
|
||||
Value = value ?? DBNull.Value
|
||||
};
|
||||
if (value.GetType().IsEnum || value.GetType().GenericTypeArguments.FirstOrDefault()?.IsEnum == true) {
|
||||
ret.DataTypeName = "";
|
||||
} else {
|
||||
//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 FormatSql(string sql, params object[] args) => sql?.FormatPostgreSQL(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) => $"coalesce({sql}, {value})";
|
||||
|
@ -72,43 +72,76 @@ namespace FreeSql.SqlServer {
|
||||
|
||||
public string GetComparisonDDLStatements<TEntity>() => this.GetComparisonDDLStatements(typeof(TEntity));
|
||||
public string GetComparisonDDLStatements(params Type[] entityTypes) {
|
||||
var sb = new StringBuilder();
|
||||
foreach (var entityType in entityTypes) {
|
||||
if (sb.Length > 0) sb.Append("\r\n");
|
||||
var tb = _commonUtils.GetTableByEntity(entityType);
|
||||
var tboldname = tb.DbOldName?.Split(new[] { '.' }, 2); //旧表名
|
||||
if (tboldname?.Length == 1) tboldname = new[] { "dbo", tboldname[0] };
|
||||
|
||||
var isRenameTable = false;
|
||||
var tbname = tb.DbName.Split(new[] { '.' }, 2);
|
||||
if (tbname.Length == 1) tbname = new[] { "dbo", tbname[0] };
|
||||
if (_orm.Ado.ExecuteScalar(CommandType.Text, string.Format("select 1 from dbo.sysobjects where id = object_id(N'[{0}].[{1}]') and OBJECTPROPERTY(id, N'IsUserTable') = 1", tbname)) == null) { //表不存在
|
||||
|
||||
if (tboldname != null && _orm.Ado.ExecuteScalar(CommandType.Text, string.Format("select 1 from dbo.sysobjects where id = object_id(N'[{0}].[{1}]') and OBJECTPROPERTY(id, N'IsUserTable') = 1", tboldname)) != null) { //旧表存在
|
||||
//修改表名
|
||||
sb.Append(_commonUtils.FormatSql("EXEC sp_rename {0}, {1};\r\n", _commonUtils.QuoteSqlName($"{tboldname[0]}.{tboldname[1]}"), _commonUtils.QuoteSqlName($"{tbname[0]}.{tbname[1]}")));
|
||||
isRenameTable = true;
|
||||
|
||||
} else {
|
||||
//创建表
|
||||
sb.Append("CREATE TABLE ").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);
|
||||
if (tbcol.Attribute.IsIdentity && tbcol.Attribute.DbType.IndexOf("identity", StringComparison.CurrentCultureIgnoreCase) == -1) sb.Append(" identity(1,1)");
|
||||
if (tbcol.Attribute.IsPrimary) sb.Append(" primary key");
|
||||
sb.Append(",");
|
||||
}
|
||||
sb.Remove(sb.Length - 1, 1).Append("\r\n);\r\n");
|
||||
continue;
|
||||
var conn = _orm.Ado.MasterPool.Get(TimeSpan.FromSeconds(5));
|
||||
var database = conn.Value.Database;
|
||||
Func<string, string, object> ExecuteScalar = (db, sql) => {
|
||||
if (string.Compare(database, db) != 0) try { conn.Value.ChangeDatabase(db); } catch { }
|
||||
try {
|
||||
using (var cmd = conn.Value.CreateCommand()) {
|
||||
cmd.CommandText = sql;
|
||||
cmd.CommandType = CommandType.Text;
|
||||
return cmd.ExecuteScalar();
|
||||
}
|
||||
} finally {
|
||||
if (string.Compare(database, db) != 0) conn.Value.ChangeDatabase(database);
|
||||
}
|
||||
//对比字段,只可以修改类型、增加字段、有限的修改字段名;保证安全不删除字段
|
||||
var addcols = new Dictionary<string, ColumnInfo>(StringComparer.CurrentCultureIgnoreCase);
|
||||
foreach (var tbcol in tb.Columns) addcols.Add(tbcol.Value.Attribute.Name, tbcol.Value);
|
||||
var surplus = new Dictionary<string, bool>(StringComparer.CurrentCultureIgnoreCase);
|
||||
var dbcols = new List<DbColumnInfo>();
|
||||
var sql = string.Format(@"select
|
||||
};
|
||||
var sb = new StringBuilder();
|
||||
try {
|
||||
foreach (var entityType in entityTypes) {
|
||||
if (sb.Length > 0) sb.Append("\r\n");
|
||||
var tb = _commonUtils.GetTableByEntity(entityType);
|
||||
var tbname = tb.DbName.Split(new[] { '.' }, 3);
|
||||
if (tbname?.Length == 1) tbname = new[] { database, "dbo", tbname[0] };
|
||||
if (tbname?.Length == 2) tbname = new[] { database, tbname[0], tbname[1] };
|
||||
|
||||
var tboldname = tb.DbOldName?.Split(new[] { '.' }, 3); //旧表名
|
||||
if (tboldname?.Length == 1) tboldname = new[] { database, "dbo", tboldname[0] };
|
||||
if (tboldname?.Length == 2) tboldname = new[] { database, tboldname[0], tboldname[1] };
|
||||
|
||||
if (string.Compare(tbname[0], database, true) != 0 && ExecuteScalar(database, $"select 1 from sys.databases where name='{tbname[0]}'") == null) //创建数据库
|
||||
ExecuteScalar(database, $"if not exists(select 1 from sys.databases where name='{tbname[0]}')\r\n\tcreate database [{tbname[0]}];");
|
||||
if (string.Compare(tbname[1], "dbo", true) != 0 && ExecuteScalar(tbname[0], $"select 1 from sys.schemas where name='{tbname[1]}'") == null) //创建模式
|
||||
ExecuteScalar(tbname[0], $"create schema [{tbname[1]}] authorization [dbo]");
|
||||
|
||||
var sbalter = new StringBuilder();
|
||||
var istmpatler = false; //创建临时表,导入数据,删除旧表,修改
|
||||
if (ExecuteScalar(tbname[0], $"select 1 from dbo.sysobjects where id = object_id(N'[{tbname[1]}].[{tbname[2]}]') and OBJECTPROPERTY(id, N'IsUserTable') = 1") == null) { //表不存在
|
||||
if (tboldname != null) {
|
||||
if (string.Compare(tboldname[0], tbname[0], true) != 0 && ExecuteScalar(database, $"select 1 from sys.databases where name='{tboldname[0]}'") == null ||
|
||||
string.Compare(tboldname[1], tbname[1], true) != 0 && ExecuteScalar(tboldname[0], $"select 1 from sys.schemas where name='{tboldname[1]}'") == null ||
|
||||
ExecuteScalar(tboldname[0], $"select 1 from dbo.sysobjects where id = object_id(N'[{tboldname[1]}].[{tboldname[2]}]') and OBJECTPROPERTY(id, N'IsUserTable') = 1") == null)
|
||||
//数据库或模式或表不存在
|
||||
tboldname = null;
|
||||
}
|
||||
if (tboldname == null) {
|
||||
//创建新表
|
||||
sb.Append("use ").Append(_commonUtils.QuoteSqlName(tbname[0])).Append(";\r\nCREATE TABLE ").Append(_commonUtils.QuoteSqlName($"{tbname[1]}.{tbname[2]}")).Append(" (");
|
||||
foreach (var tbcol in tb.Columns.Values) {
|
||||
sb.Append(" \r\n ").Append(_commonUtils.QuoteSqlName(tbcol.Attribute.Name)).Append(" ");
|
||||
sb.Append(tbcol.Attribute.DbType);
|
||||
if (tbcol.Attribute.IsIdentity && tbcol.Attribute.DbType.IndexOf("identity", StringComparison.CurrentCultureIgnoreCase) == -1) sb.Append(" identity(1,1)");
|
||||
if (tbcol.Attribute.IsPrimary) sb.Append(" primary key");
|
||||
sb.Append(",");
|
||||
}
|
||||
sb.Remove(sb.Length - 1, 1).Append("\r\n);\r\n");
|
||||
continue;
|
||||
}
|
||||
//如果新表,旧表在一个数据库和模式下,直接修改表名
|
||||
if (string.Compare(tbname[0], tboldname[0], true) == 0 &&
|
||||
string.Compare(tbname[1], tboldname[1], true) == 0)
|
||||
sbalter.Append("use ").Append(_commonUtils.QuoteSqlName(tbname[0])).Append(_commonUtils.FormatSql(";\r\nEXEC sp_rename {0}, {1};\r\n", _commonUtils.QuoteSqlName($"{tboldname[0]}.{tboldname[1]}"), _commonUtils.QuoteSqlName(tbname[2])));
|
||||
else {
|
||||
//如果新表,旧表不在一起,创建新表,导入数据,删除旧表
|
||||
istmpatler = true;
|
||||
}
|
||||
} else
|
||||
tboldname = null; //如果新表已经存在,不走改表名逻辑
|
||||
|
||||
//对比字段,只可以修改类型、增加字段、有限的修改字段名;保证安全不删除字段
|
||||
var sql = string.Format(@"
|
||||
use [{0}];
|
||||
select
|
||||
a.name 'Column'
|
||||
,b.name + case
|
||||
when b.name in ('Char', 'VarChar', 'NChar', 'NVarChar', 'Binary', 'VarBinary') then '(' +
|
||||
@ -124,99 +157,110 @@ inner join sys.types b on b.user_type_id = a.user_type_id
|
||||
left join sys.extended_properties AS c ON c.major_id = a.object_id AND c.minor_id = a.column_id
|
||||
left join sys.tables d on d.object_id = a.object_id
|
||||
left join sys.schemas e on e.schema_id = d.schema_id
|
||||
where a.object_id in (object_id(N'[{0}].[{1}]'))", isRenameTable ? tboldname : tbname);
|
||||
var ds = _orm.Ado.ExecuteArray(CommandType.Text, sql);
|
||||
var tbstruct = ds.ToDictionary(a => string.Concat(a[0]), a => new {
|
||||
column = string.Concat(a[0]),
|
||||
sqlType = string.Concat(a[1]),
|
||||
is_nullable = string.Concat(a[2]) == "1",
|
||||
is_identity = string.Concat(a[3]) == "1"
|
||||
}, StringComparer.CurrentCultureIgnoreCase);
|
||||
var sbalter = new StringBuilder();
|
||||
var istmpatler = false;
|
||||
foreach (var tbcol in tb.Columns.Values) {
|
||||
if (tbstruct.TryGetValue(tbcol.Attribute.Name, out var tbstructcol) ||
|
||||
string.IsNullOrEmpty(tbcol.Attribute.OldName) == false && tbstruct.TryGetValue(tbcol.Attribute.OldName, out tbstructcol)) {
|
||||
if (tbcol.Attribute.DbType.StartsWith(tbstructcol.sqlType, StringComparison.CurrentCultureIgnoreCase) == false ||
|
||||
tbcol.Attribute.IsNullable != tbstructcol.is_nullable ||
|
||||
tbcol.Attribute.IsIdentity != tbstructcol.is_identity) {
|
||||
istmpatler = true;
|
||||
break;
|
||||
}
|
||||
if (tbstructcol.column == tbcol.Attribute.OldName) {
|
||||
//修改列名
|
||||
sbalter.Append(_commonUtils.FormatSql("EXEC sp_rename {0}, {1}, 'COLUMN';\r\n", $"{tbname[0]}.{tbname[1]}.{tbcol.Attribute.OldName}", tbcol.Attribute.Name));
|
||||
where a.object_id in (object_id(N'[{1}].[{2}]'));
|
||||
use " + database, tboldname ?? tbname);
|
||||
var ds = _orm.Ado.ExecuteArray(CommandType.Text, sql);
|
||||
var tbstruct = ds.ToDictionary(a => string.Concat(a[0]), a => new {
|
||||
column = string.Concat(a[0]),
|
||||
sqlType = string.Concat(a[1]),
|
||||
is_nullable = string.Concat(a[2]) == "1",
|
||||
is_identity = string.Concat(a[3]) == "1"
|
||||
}, StringComparer.CurrentCultureIgnoreCase);
|
||||
|
||||
if (istmpatler == false) {
|
||||
foreach (var tbcol in tb.Columns.Values) {
|
||||
if (tbstruct.TryGetValue(tbcol.Attribute.Name, out var tbstructcol) ||
|
||||
string.IsNullOrEmpty(tbcol.Attribute.OldName) == false && tbstruct.TryGetValue(tbcol.Attribute.OldName, out tbstructcol)) {
|
||||
if (tbcol.Attribute.DbType.StartsWith(tbstructcol.sqlType, StringComparison.CurrentCultureIgnoreCase) == false ||
|
||||
tbcol.Attribute.IsNullable != tbstructcol.is_nullable ||
|
||||
tbcol.Attribute.IsIdentity != tbstructcol.is_identity) {
|
||||
istmpatler = true;
|
||||
break;
|
||||
}
|
||||
if (tbstructcol.column == tbcol.Attribute.OldName) {
|
||||
//修改列名
|
||||
sbalter.Append(_commonUtils.FormatSql("EXEC sp_rename {0}, {1}, 'COLUMN';\r\n", $"{tbname[0]}.{tbname[1]}.{tbname[2]}.{tbcol.Attribute.OldName}", tbcol.Attribute.Name));
|
||||
}
|
||||
continue;
|
||||
}
|
||||
//添加列
|
||||
sbalter.Append("ALTER TABLE ").Append(_commonUtils.QuoteSqlName($"{tbname[0]}.{tbname[1]}.{tbname[2]}")).Append(" ADD ").Append(_commonUtils.QuoteSqlName(tbcol.Attribute.Name)).Append(" ").Append(tbcol.Attribute.DbType);
|
||||
if (tbcol.Attribute.IsIdentity && tbcol.Attribute.DbType.IndexOf("identity", StringComparison.CurrentCultureIgnoreCase) == -1) sbalter.Append(" identity(1,1)");
|
||||
var addcoldbdefault = tb.Properties[tbcol.CsName].GetValue(Activator.CreateInstance(tb.Type));
|
||||
if (tbcol.Attribute.IsNullable == false) addcoldbdefault = tbcol.Attribute.DbDefautValue;
|
||||
if (addcoldbdefault != null) sbalter.Append(_commonUtils.FormatSql(" default({0})", addcoldbdefault));
|
||||
sbalter.Append(";\r\n");
|
||||
}
|
||||
}
|
||||
if (istmpatler == false) {
|
||||
sb.Append(sbalter);
|
||||
continue;
|
||||
}
|
||||
//添加列
|
||||
sbalter.Append("ALTER TABLE ").Append(_commonUtils.QuoteSqlName($"{tbname[0]}.{tbname[1]}")).Append(" ADD ").Append(_commonUtils.QuoteSqlName(tbcol.Attribute.Name)).Append(" ").Append(tbcol.Attribute.DbType);
|
||||
if (tbcol.Attribute.IsIdentity && tbcol.Attribute.DbType.IndexOf("identity", StringComparison.CurrentCultureIgnoreCase) == -1) sbalter.Append(" identity(1,1)");
|
||||
var addcoldbdefault = tb.Properties[tbcol.CsName].GetValue(Activator.CreateInstance(tb.Type));
|
||||
if (tbcol.Attribute.IsNullable == false) addcoldbdefault = tbcol.Attribute.DbDefautValue;
|
||||
if (addcoldbdefault != null) sbalter.Append(_commonUtils.FormatSql(" default({0})", addcoldbdefault));
|
||||
sbalter.Append(";\r\n");
|
||||
}
|
||||
if (istmpatler == false) {
|
||||
sb.Append(sbalter);
|
||||
continue;
|
||||
}
|
||||
//创建临时表,数据导进临时表,然后删除原表,将临时表改名为原表名
|
||||
bool idents = false;
|
||||
var tablename = _commonUtils.QuoteSqlName($"{tbname[0]}.{tbname[1]}");
|
||||
var tmptablename = _commonUtils.QuoteSqlName($"{tbname[0]}.TmpFreeSqlTmp_{tbname[1]}");
|
||||
sb.Append("BEGIN TRANSACTION\r\n")
|
||||
.Append("SET QUOTED_IDENTIFIER ON\r\n")
|
||||
.Append("SET ARITHABORT ON\r\n")
|
||||
.Append("SET NUMERIC_ROUNDABORT OFF\r\n")
|
||||
.Append("SET CONCAT_NULL_YIELDS_NULL ON\r\n")
|
||||
.Append("SET ANSI_NULLS ON\r\n")
|
||||
.Append("SET ANSI_PADDING ON\r\n")
|
||||
.Append("SET ANSI_WARNINGS ON\r\n")
|
||||
.Append("COMMIT\r\n");
|
||||
sb.Append("BEGIN TRANSACTION;\r\n");
|
||||
//创建临时表
|
||||
sb.Append("CREATE TABLE ").Append(tmptablename).Append(" (");
|
||||
foreach (var tbcol in tb.Columns.Values) {
|
||||
sb.Append(" \r\n ").Append(_commonUtils.QuoteSqlName(tbcol.Attribute.Name)).Append(" ");
|
||||
sb.Append(tbcol.Attribute.DbType);
|
||||
if (tbcol.Attribute.IsIdentity && tbcol.Attribute.DbType.IndexOf("identity", StringComparison.CurrentCultureIgnoreCase) == -1) sb.Append(" identity(1,1)");
|
||||
if (tbcol.Attribute.IsPrimary) sb.Append(" primary key");
|
||||
sb.Append(",");
|
||||
idents = idents || tbcol.Attribute.IsIdentity;
|
||||
}
|
||||
sb.Remove(sb.Length - 1, 1).Append("\r\n);\r\n");
|
||||
sb.Append("ALTER TABLE ").Append(tmptablename).Append(" SET (LOCK_ESCALATION = TABLE);\r\n");
|
||||
if (idents) sb.Append("SET IDENTITY_INSERT ").Append(tmptablename).Append(" ON;\r\n");
|
||||
sb.Append("IF EXISTS(SELECT 1 FROM ").Append(tablename).Append(")\r\n");
|
||||
sb.Append("\tEXEC('INSERT INTO ").Append(tmptablename).Append(" (");
|
||||
foreach (var tbcol in tb.Columns.Values) {
|
||||
if (tbstruct.ContainsKey(tbcol.Attribute.Name) || tbstruct.ContainsKey(tbcol.Attribute.OldName)) { //导入旧表存在的字段
|
||||
sb.Append(_commonUtils.QuoteSqlName(tbcol.Attribute.Name)).Append(", ");
|
||||
//创建临时表,数据导进临时表,然后删除原表,将临时表改名为原表名
|
||||
bool idents = false;
|
||||
var tablename = tboldname == null ? _commonUtils.QuoteSqlName($"{tbname[0]}.{tbname[1]}.{tbname[2]}") : _commonUtils.QuoteSqlName($"{tboldname[0]}.{tboldname[1]}.{tboldname[2]}");
|
||||
var tmptablename = _commonUtils.QuoteSqlName($"{tbname[0]}.{tbname[1]}.FreeSqlTmp_{tbname[2]}");
|
||||
sb.Append("BEGIN TRANSACTION\r\n")
|
||||
.Append("SET QUOTED_IDENTIFIER ON\r\n")
|
||||
.Append("SET ARITHABORT ON\r\n")
|
||||
.Append("SET NUMERIC_ROUNDABORT OFF\r\n")
|
||||
.Append("SET CONCAT_NULL_YIELDS_NULL ON\r\n")
|
||||
.Append("SET ANSI_NULLS ON\r\n")
|
||||
.Append("SET ANSI_PADDING ON\r\n")
|
||||
.Append("SET ANSI_WARNINGS ON\r\n")
|
||||
.Append("COMMIT\r\n");
|
||||
sb.Append("BEGIN TRANSACTION;\r\n");
|
||||
//创建临时表
|
||||
sb.Append("CREATE TABLE ").Append(tmptablename).Append(" (");
|
||||
foreach (var tbcol in tb.Columns.Values) {
|
||||
sb.Append(" \r\n ").Append(_commonUtils.QuoteSqlName(tbcol.Attribute.Name)).Append(" ");
|
||||
sb.Append(tbcol.Attribute.DbType);
|
||||
if (tbcol.Attribute.IsIdentity && tbcol.Attribute.DbType.IndexOf("identity", StringComparison.CurrentCultureIgnoreCase) == -1) sb.Append(" identity(1,1)");
|
||||
if (tbcol.Attribute.IsPrimary) sb.Append(" primary key");
|
||||
sb.Append(",");
|
||||
idents = idents || tbcol.Attribute.IsIdentity;
|
||||
}
|
||||
}
|
||||
sb.Remove(sb.Length - 2, 2).Append(")\r\n\t\tSELECT ");
|
||||
foreach (var tbcol in tb.Columns.Values) {
|
||||
if (tbstruct.TryGetValue(tbcol.Attribute.Name, out var tbstructcol) ||
|
||||
string.IsNullOrEmpty(tbcol.Attribute.OldName) == false && tbstruct.TryGetValue(tbcol.Attribute.OldName, out tbstructcol)) {
|
||||
var insertvalue = _commonUtils.QuoteSqlName(tbstructcol.column);
|
||||
if (tbcol.Attribute.DbType.StartsWith(tbstructcol.sqlType, StringComparison.CurrentCultureIgnoreCase) == false) {
|
||||
var tbcoldbtype = tbcol.Attribute.DbType.Split(' ').First();
|
||||
insertvalue = $"cast({insertvalue} as {tbcoldbtype})";
|
||||
sb.Remove(sb.Length - 1, 1).Append("\r\n);\r\n");
|
||||
sb.Append("ALTER TABLE ").Append(tmptablename).Append(" SET (LOCK_ESCALATION = TABLE);\r\n");
|
||||
if (idents) sb.Append("SET IDENTITY_INSERT ").Append(tmptablename).Append(" ON;\r\n");
|
||||
sb.Append("IF EXISTS(SELECT 1 FROM ").Append(tablename).Append(")\r\n");
|
||||
sb.Append("\tEXEC('INSERT INTO ").Append(tmptablename).Append(" (");
|
||||
foreach (var tbcol in tb.Columns.Values) {
|
||||
if (tbstruct.ContainsKey(tbcol.Attribute.Name) ||
|
||||
string.IsNullOrEmpty(tbcol.Attribute.OldName) == false && tbstruct.ContainsKey(tbcol.Attribute.OldName)) { //导入旧表存在的字段
|
||||
sb.Append(_commonUtils.QuoteSqlName(tbcol.Attribute.Name)).Append(", ");
|
||||
}
|
||||
if (tbcol.Attribute.IsNullable != tbstructcol.is_nullable) {
|
||||
insertvalue = $"isnull({insertvalue},{_commonUtils.FormatSql("{0}", tbcol.Attribute.DbDefautValue).Replace("'", "''")})";
|
||||
}
|
||||
sb.Append(insertvalue).Append(", ");
|
||||
}
|
||||
sb.Remove(sb.Length - 2, 2).Append(")\r\n\t\tSELECT ");
|
||||
foreach (var tbcol in tb.Columns.Values) {
|
||||
if (tbstruct.TryGetValue(tbcol.Attribute.Name, out var tbstructcol) ||
|
||||
string.IsNullOrEmpty(tbcol.Attribute.OldName) == false && tbstruct.TryGetValue(tbcol.Attribute.OldName, out tbstructcol)) {
|
||||
var insertvalue = _commonUtils.QuoteSqlName(tbstructcol.column);
|
||||
if (tbcol.Attribute.DbType.StartsWith(tbstructcol.sqlType, StringComparison.CurrentCultureIgnoreCase) == false) {
|
||||
var tbcoldbtype = tbcol.Attribute.DbType.Split(' ').First();
|
||||
insertvalue = $"cast({insertvalue} as {tbcoldbtype})";
|
||||
}
|
||||
if (tbcol.Attribute.IsNullable != tbstructcol.is_nullable) {
|
||||
insertvalue = $"isnull({insertvalue},{_commonUtils.FormatSql("{0}", tbcol.Attribute.DbDefautValue).Replace("'", "''")})";
|
||||
}
|
||||
sb.Append(insertvalue).Append(", ");
|
||||
}
|
||||
}
|
||||
sb.Remove(sb.Length - 2, 2).Append(" FROM ").Append(tablename).Append(" WITH (HOLDLOCK TABLOCKX)');\r\n");
|
||||
if (idents) sb.Append("SET IDENTITY_INSERT ").Append(tmptablename).Append(" OFF;\r\n");
|
||||
sb.Append("DROP TABLE ").Append(tablename).Append(";\r\n");
|
||||
sb.Append("EXECUTE sp_rename N'").Append(tmptablename).Append("', N'").Append(tbname[2]).Append("', 'OBJECT' ;\r\n");
|
||||
sb.Append("COMMIT;\r\n");
|
||||
}
|
||||
return sb.Length == 0 ? null : sb.ToString();
|
||||
} finally {
|
||||
try {
|
||||
conn.Value.ChangeDatabase(database);
|
||||
_orm.Ado.MasterPool.Return(conn);
|
||||
} catch {
|
||||
_orm.Ado.MasterPool.Return(conn, true);
|
||||
}
|
||||
sb.Remove(sb.Length - 2, 2).Append(" FROM ").Append(tablename).Append(" WITH (HOLDLOCK TABLOCKX)');\r\n");
|
||||
if (idents) sb.Append("SET IDENTITY_INSERT ").Append(tmptablename).Append(" OFF;\r\n");
|
||||
sb.Append("DROP TABLE ").Append(tablename).Append(";\r\n");
|
||||
sb.Append("EXECUTE sp_rename N'").Append(tmptablename).Append("', N'").Append(tbname[1]).Append("', 'OBJECT' ;\r\n");
|
||||
sb.Append("COMMIT;\r\n");
|
||||
}
|
||||
return sb.Length == 0 ? null : sb.ToString();
|
||||
}
|
||||
|
||||
ConcurrentDictionary<string, bool> dicSyced = new ConcurrentDictionary<string, bool>();
|
||||
|
Reference in New Issue
Block a user