From 36c8a45e478598e43bb7b1152373d91d7a7c04d7 Mon Sep 17 00:00:00 2001 From: 2881099 <2881099@qq.com> Date: Tue, 30 May 2023 18:21:57 +0800 Subject: [PATCH] =?UTF-8?q?-=20=E5=A2=9E=E5=8A=A0=20IInsertOrUpdate.Update?= =?UTF-8?q?Set=20=E6=8C=87=E5=AE=9A=E6=9B=B4=E6=96=B0=EF=BC=9B?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- Examples/base_entity/Program.cs | 16 ++++-- FreeSql.DbContext/FreeSql.DbContext.xml | 9 ---- FreeSql/FreeSql.xml | 10 ++++ FreeSql/Interface/Curd/IInsertOrUpdate.cs | 10 ++++ .../CommonProvider/InsertOrUpdateProvider.cs | 50 +++++++++++++++++++ .../Internal/CommonProvider/UpdateProvider.cs | 8 ++- .../MySql/Curd/CustomMySqlInsertOrUpdate.cs | 19 ++++++- .../Oracle/Curd/CustomOracleInsertOrUpdate.cs | 14 ++++-- .../Curd/CustomPostgreSQLInsertOrUpdate.cs | 21 +++++++- .../Curd/CustomSqlServerInsertOrUpdate.cs | 14 ++++-- .../Curd/DamengInsertOrUpdate.cs | 14 ++++-- .../Curd/FirebirdInsertOrUpdate.cs | 14 ++++-- .../Curd/GBaseInsertOrUpdate.cs | 14 ++++-- .../Curd/KingbaseESInsertOrUpdate.cs | 21 +++++++- .../Curd/MySqlInsertOrUpdate.cs | 19 ++++++- .../Dameng/Curd/OdbcDamengInsertOrUpdate.cs | 14 ++++-- .../Curd/OdbcKingbaseESInsertOrUpdate.cs | 21 +++++++- .../MySql/Curd/OdbcMySqlInsertOrUpdate.cs | 19 ++++++- .../Oracle/Curd/OdbcOracleInsertOrUpdate.cs | 14 ++++-- .../Curd/OdbcPostgreSQLInsertOrUpdate.cs | 21 +++++++- .../Curd/OdbcSqlServerInsertOrUpdate.cs | 14 ++++-- .../Curd/OracleInsertOrUpdate.cs | 14 ++++-- .../Curd/PostgreSQLInsertOrUpdate.cs | 21 +++++++- .../Curd/QuestDbInsertOrUpdate.cs | 21 +++++++- .../Curd/ShenTongInsertOrUpdate.cs | 14 ++++-- .../Curd/SqlServerInsertOrUpdate.cs | 14 ++++-- .../Curd/XuguInsertOrUpdate.cs | 14 ++++-- 27 files changed, 369 insertions(+), 85 deletions(-) diff --git a/Examples/base_entity/Program.cs b/Examples/base_entity/Program.cs index 21e5ca4f..d79842c0 100644 --- a/Examples/base_entity/Program.cs +++ b/Examples/base_entity/Program.cs @@ -566,14 +566,14 @@ namespace base_entity .UseConnectionString(FreeSql.DataType.MySql, "Data Source=127.0.0.1;Port=3306;User ID=root;Password=root;Initial Catalog=cccddd;Charset=utf8;SslMode=none;min pool size=1;Max pool size=2;AllowLoadLocalInfile=true") - .UseConnectionString(FreeSql.DataType.SqlServer, "Data Source=.;Integrated Security=True;Initial Catalog=freesqlTest;Pooling=true;Max Pool Size=3;TrustServerCertificate=true") + //.UseConnectionString(FreeSql.DataType.SqlServer, "Data Source=.;Integrated Security=True;Initial Catalog=freesqlTest;Pooling=true;Max Pool Size=3;TrustServerCertificate=true") - //.UseConnectionString(FreeSql.DataType.PostgreSQL, "Host=192.168.164.10;Port=5432;Username=postgres;Password=123456;Database=tedb;Pooling=true;Maximum Pool Size=2") + .UseConnectionString(FreeSql.DataType.PostgreSQL, "Host=192.168.164.10;Port=5432;Username=postgres;Password=123456;Database=tedb;Pooling=true;Maximum Pool Size=2") //.UseConnectionString(FreeSql.DataType.PostgreSQL, "Host=192.168.164.10;Port=5432;Username=postgres;Password=123456;Database=toc;Pooling=true;Maximum Pool Size=2") - //.UseNameConvert(FreeSql.Internal.NameConvertType.ToLower) + .UseNameConvert(FreeSql.Internal.NameConvertType.ToLower) - .UseConnectionString(FreeSql.DataType.Oracle, "user id=user1;password=123456;data source=//127.0.0.1:1521/XE;Pooling=true;Max Pool Size=2") - .UseNameConvert(FreeSql.Internal.NameConvertType.ToUpper) + //.UseConnectionString(FreeSql.DataType.Oracle, "user id=user1;password=123456;data source=//127.0.0.1:1521/XE;Pooling=true;Max Pool Size=2") + //.UseNameConvert(FreeSql.Internal.NameConvertType.ToUpper) //.UseConnectionString(FreeSql.DataType.Dameng, "server=127.0.0.1;port=5236;user id=2user;password=123456789;database=2user;poolsize=5;min pool size=1") //.UseNameConvert(FreeSql.Internal.NameConvertType.ToUpper) @@ -601,6 +601,12 @@ namespace base_entity BaseEntity.Initialization(fsql, () => _asyncUow.Value); #endregion + var iouSetSql01 = fsql.InsertOrUpdate() + .SetSource(Enumerable.Range(0, 5).Select(a => new User1 { Id = Guid.NewGuid(), Nickname = $"nickname{a}", Username = $"username{a}", Description = $"desc{a}" }).ToArray()) + .UpdateSet((a, b) => a.Sort == b.Sort + 10) + .UpdateSet((a, b) => a.Nickname == "xxx") + .ToSql(); + var sqlastable1 = fsql.Select(101).AsTable((t, o) => "current_detail_230501").ToSql(); var sqlastable2 = fsql.Update(101).AsTable("current_detail_230501").Set(t => t.StatuId, 1).ToSql(); var sqlastable3 = fsql.Delete(101).AsTable("current_detail_230501").ToSql(); diff --git a/FreeSql.DbContext/FreeSql.DbContext.xml b/FreeSql.DbContext/FreeSql.DbContext.xml index 26522f10..537315e2 100644 --- a/FreeSql.DbContext/FreeSql.DbContext.xml +++ b/FreeSql.DbContext/FreeSql.DbContext.xml @@ -800,14 +800,5 @@ - - - 批量注入 Repository,可以参考代码自行调整 - - - - - - diff --git a/FreeSql/FreeSql.xml b/FreeSql/FreeSql.xml index 9f25ee32..9dd32b35 100644 --- a/FreeSql/FreeSql.xml +++ b/FreeSql/FreeSql.xml @@ -1921,6 +1921,16 @@ 属性名,或者字段名 + + + 设置列的联表值,格式: + UpdateSet((a, b) => a.Clicks == b.xxx) + UpdateSet((a, b) => a.Clicks == a.Clicks + 1) + + + + + 设置表名规则,可用于分库/分表,参数1:默认表名;返回值:新表名; diff --git a/FreeSql/Interface/Curd/IInsertOrUpdate.cs b/FreeSql/Interface/Curd/IInsertOrUpdate.cs index 1e019c50..76e3ee20 100644 --- a/FreeSql/Interface/Curd/IInsertOrUpdate.cs +++ b/FreeSql/Interface/Curd/IInsertOrUpdate.cs @@ -86,6 +86,16 @@ namespace FreeSql /// IInsertOrUpdate UpdateColumns(string[] columns); + /// + /// 设置列的联表值,格式: + /// UpdateSet((a, b) => a.Clicks == b.xxx) + /// UpdateSet((a, b) => a.Clicks == a.Clicks + 1) + /// + /// + /// + /// + IInsertOrUpdate UpdateSet(Expression> exp); + /// /// 设置表名规则,可用于分库/分表,参数1:默认表名;返回值:新表名; /// diff --git a/FreeSql/Internal/CommonProvider/InsertOrUpdateProvider.cs b/FreeSql/Internal/CommonProvider/InsertOrUpdateProvider.cs index ed8dd94d..a45373c5 100644 --- a/FreeSql/Internal/CommonProvider/InsertOrUpdateProvider.cs +++ b/FreeSql/Internal/CommonProvider/InsertOrUpdateProvider.cs @@ -23,6 +23,7 @@ namespace FreeSql.Internal.CommonProvider public bool _doNothing = false; public Dictionary _updateIgnore = new Dictionary(StringComparer.CurrentCultureIgnoreCase); public Dictionary _auditValueChangedDict = new Dictionary(StringComparer.CurrentCultureIgnoreCase); + public Dictionary _updateSetDict = new Dictionary(); public TableInfo _table; public ColumnInfo[] _tempPrimarys; public Func _tableRule; @@ -87,6 +88,55 @@ namespace FreeSql.Internal.CommonProvider return this; } + public IInsertOrUpdate UpdateSet(Expression> exp) + { + var body = exp?.Body; + var nodeType = body?.NodeType; + if (nodeType == ExpressionType.Convert) + { + body = (body as UnaryExpression)?.Operand; + nodeType = body?.NodeType; + } + switch (nodeType) + { + case ExpressionType.Equal: + break; + default: + throw new Exception("格式错了,请使用 .Set((a,b) => a.name == b.xname)"); + } + + var equalBinaryExp = body as BinaryExpression; + var cols = new List(); + _commonExpression.ExpressionSelectColumn_MemberAccess(null, null, cols, SelectTableInfoType.From, equalBinaryExp.Left, true, null); + if (cols.Count != 1) return this; + var col = cols[0].Column; + var valueSql = ""; + + if (equalBinaryExp.Right.IsParameter()) + { + var tmpQuery = _orm.Select(); + var tmpQueryProvider = tmpQuery as Select0Provider; + tmpQueryProvider._tables[0].Alias = "t1"; + tmpQueryProvider._tables[0].Parameter = exp.Parameters[0]; + tmpQueryProvider._tables[1].Alias = "t2"; + tmpQueryProvider._tables[1].Parameter = exp.Parameters[1]; + var valueExp = Expression.Lambda>(Expression.Convert(equalBinaryExp.Right, typeof(object)), exp.Parameters); + tmpQuery.GroupBy(valueExp); + valueSql = tmpQueryProvider._groupby?.Remove(0, " \r\nGROUP BY ".Length); + } + else + { + valueSql = _commonExpression.ExpressionLambdaToSql(equalBinaryExp.Right, new CommonExpression.ExpTSC + { + isQuoteName = true, + mapType = equalBinaryExp.Right is BinaryExpression ? null : col.Attribute.MapType + }); + } + if (string.IsNullOrEmpty(valueSql)) return this; + _updateSetDict[col.Attribute.Name] = valueSql; + return this; + } + public static void AuditDataValue(object sender, IEnumerable data, IFreeSql orm, TableInfo table, Dictionary changedDict) { if (data?.Any() != true) return; diff --git a/FreeSql/Internal/CommonProvider/UpdateProvider.cs b/FreeSql/Internal/CommonProvider/UpdateProvider.cs index 02a8c04d..29dfb2aa 100644 --- a/FreeSql/Internal/CommonProvider/UpdateProvider.cs +++ b/FreeSql/Internal/CommonProvider/UpdateProvider.cs @@ -894,7 +894,9 @@ namespace FreeSql.Internal.CommonProvider var sb = new StringBuilder(); sb.Append(_commonUtils.QuoteSqlName(col.Attribute.Name)).Append(" = "); - var valsameIf = col.Attribute.MapType.IsNumberType() || col.Attribute.MapType == typeof(string) || col.Attribute.MapType.NullableTypeOrThis().IsEnum; + var valsameIf = col.Attribute.MapType.IsNumberType() || + new[] { typeof(string), typeof(DateTime), typeof(DateTime?) }.Contains(col.Attribute.MapType) || + col.Attribute.MapType.NullableTypeOrThis().IsEnum; var ds = _source.Select(a => col.GetDbValue(a)).ToArray(); if (valsameIf && ds.All(a => object.Equals(a, ds[0]))) { @@ -1149,7 +1151,9 @@ namespace FreeSql.Internal.CommonProvider sb.Append(col.DbUpdateValue); else { - var valsameIf = col.Attribute.MapType.IsNumberType() || col.Attribute.MapType == typeof(string) || col.Attribute.MapType.NullableTypeOrThis().IsEnum; + var valsameIf = col.Attribute.MapType.IsNumberType() || + new[] { typeof(string), typeof(DateTime), typeof(DateTime?) }.Contains(col.Attribute.MapType) || + col.Attribute.MapType.NullableTypeOrThis().IsEnum; var ds = _source.Select(a => col.GetDbValue(a)).ToArray(); if (valsameIf && ds.All(a => object.Equals(a, ds[0]))) { diff --git a/Providers/FreeSql.Provider.Custom/MySql/Curd/CustomMySqlInsertOrUpdate.cs b/Providers/FreeSql.Provider.Custom/MySql/Curd/CustomMySqlInsertOrUpdate.cs index 1e68594b..8ad61e35 100644 --- a/Providers/FreeSql.Provider.Custom/MySql/Curd/CustomMySqlInsertOrUpdate.cs +++ b/Providers/FreeSql.Provider.Custom/MySql/Curd/CustomMySqlInsertOrUpdate.cs @@ -4,6 +4,7 @@ using System.Collections.Generic; using System.Data.Common; using System.Linq; using System.Text; +using System.Text.RegularExpressions; namespace FreeSql.Custom.MySql { @@ -62,10 +63,26 @@ namespace FreeSql.Custom.MySql insert.InsertIdentity(); if (_doNothing == false) { - var cols = _table.Columns.Values.Where(a => _tempPrimarys.Contains(a) == false && a.Attribute.CanUpdate == true && a.Attribute.IsIdentity == false && _updateIgnore.ContainsKey(a.Attribute.Name) == false); + var cols = _table.Columns.Values.Where(a => _updateSetDict.ContainsKey(a.Attribute.Name) || + _tempPrimarys.Contains(a) == false && a.Attribute.CanUpdate == true && a.Attribute.IsIdentity == false && _updateIgnore.ContainsKey(a.Attribute.Name) == false); sql = new CustomMySqlOnDuplicateKeyUpdate(insert) .UpdateColumns(cols.Select(a => a.Attribute.Name).ToArray()) .ToSql(); + if (_updateSetDict.Any()) + { + var findregex = new Regex("(t1|t2)." + _commonUtils.QuoteSqlName("test").Replace("test", "(\\w+)")); + foreach (var usd in _updateSetDict) + { + var field = _commonUtils.QuoteSqlName(usd.Key); + var findsql = $"{field} = VALUES({field})"; + var usdval = findregex.Replace(usd.Value, m => + { + if (m.Groups[1].Value == "t1") return _commonUtils.QuoteSqlName(m.Groups[2].Value); + return $"VALUES({_commonUtils.QuoteSqlName(m.Groups[2].Value)})"; + }); + sql = sql.Replace(findsql, $"{field} = {usdval}"); + } + } } else { diff --git a/Providers/FreeSql.Provider.Custom/Oracle/Curd/CustomOracleInsertOrUpdate.cs b/Providers/FreeSql.Provider.Custom/Oracle/Curd/CustomOracleInsertOrUpdate.cs index 5bdf2ad2..696fd8e5 100644 --- a/Providers/FreeSql.Provider.Custom/Oracle/Curd/CustomOracleInsertOrUpdate.cs +++ b/Providers/FreeSql.Provider.Custom/Oracle/Curd/CustomOracleInsertOrUpdate.cs @@ -39,14 +39,18 @@ namespace FreeSql.Custom.Oracle WriteSourceSelectUnionAll(data, sb, dbParams); sb.Append(" ) t2 ON (").Append(string.Join(" AND ", _tempPrimarys.Select(a => $"t1.{_commonUtils.QuoteSqlName(a.Attribute.Name)} = t2.{_commonUtils.QuoteSqlName(a.Attribute.Name)}"))).Append(") \r\n"); - var cols = _table.Columns.Values.Where(a => _tempPrimarys.Contains(a) == false && a.Attribute.CanUpdate == true && a.Attribute.IsIdentity == false && _updateIgnore.ContainsKey(a.Attribute.Name) == false); + var cols = _table.Columns.Values.Where(a => _updateSetDict.ContainsKey(a.Attribute.Name) || + _tempPrimarys.Contains(a) == false && a.Attribute.CanUpdate == true && a.Attribute.IsIdentity == false && _updateIgnore.ContainsKey(a.Attribute.Name) == false); if (_doNothing == false && cols.Any()) sb.Append("WHEN MATCHED THEN \r\n") .Append(" update set ").Append(string.Join(", ", cols.Select(a => - a.Attribute.IsVersion && a.Attribute.MapType != typeof(byte[]) ? - $"{_commonUtils.QuoteSqlName(a.Attribute.Name)} = t1.{_commonUtils.QuoteSqlName(a.Attribute.Name)} + 1" : - $"{_commonUtils.QuoteSqlName(a.Attribute.Name)} = t2.{_commonUtils.QuoteSqlName(a.Attribute.Name)}" - ))).Append(" \r\n"); + { + if (_updateSetDict.TryGetValue(a.Attribute.Name, out var valsql)) + return $"{_commonUtils.QuoteSqlName(a.Attribute.Name)} = {valsql}"; + return a.Attribute.IsVersion && a.Attribute.MapType != typeof(byte[]) ? + $"{_commonUtils.QuoteSqlName(a.Attribute.Name)} = t1.{_commonUtils.QuoteSqlName(a.Attribute.Name)} + 1" : + $"{_commonUtils.QuoteSqlName(a.Attribute.Name)} = t2.{_commonUtils.QuoteSqlName(a.Attribute.Name)}"; + }))).Append(" \r\n"); cols = _table.Columns.Values.Where(a => a.Attribute.CanInsert == true); if (tempPrimaryIsIdentity == false) cols = cols.Where(a => a.Attribute.IsIdentity == false || string.IsNullOrEmpty(a.DbInsertValue) == false); diff --git a/Providers/FreeSql.Provider.Custom/PostgreSQL/Curd/CustomPostgreSQLInsertOrUpdate.cs b/Providers/FreeSql.Provider.Custom/PostgreSQL/Curd/CustomPostgreSQLInsertOrUpdate.cs index f45e05e9..ed3716f1 100644 --- a/Providers/FreeSql.Provider.Custom/PostgreSQL/Curd/CustomPostgreSQLInsertOrUpdate.cs +++ b/Providers/FreeSql.Provider.Custom/PostgreSQL/Curd/CustomPostgreSQLInsertOrUpdate.cs @@ -3,6 +3,7 @@ using System.Collections.Generic; using System.Data.Common; using System.Linq; using System.Text; +using System.Text.RegularExpressions; namespace FreeSql.Custom.PostgreSQL { @@ -57,11 +58,29 @@ namespace FreeSql.Custom.PostgreSQL { var ocdu = new CustomPostgreSQLOnConflictDoUpdate(insert.InsertIdentity()); ocdu._tempPrimarys = _tempPrimarys; - var cols = _table.Columns.Values.Where(a => _tempPrimarys.Contains(a) == false && a.Attribute.CanUpdate == true && a.Attribute.IsIdentity == false && _updateIgnore.ContainsKey(a.Attribute.Name) == false); + var cols = _table.Columns.Values.Where(a => _updateSetDict.ContainsKey(a.Attribute.Name) || + _tempPrimarys.Contains(a) == false && a.Attribute.CanUpdate == true && a.Attribute.IsIdentity == false && _updateIgnore.ContainsKey(a.Attribute.Name) == false); ocdu.UpdateColumns(cols.Select(a => a.Attribute.Name).ToArray()); if (_doNothing == true || cols.Any() == false) ocdu.DoNothing(); sql = ocdu.ToSql(); + + if (_updateSetDict.Any()) + { + var findregex = new Regex("(t1|t2)." + _commonUtils.QuoteSqlName("test").Replace("test", "(\\w+)")); + var tableName = _commonUtils.QuoteSqlName(TableRuleInvoke()); + foreach (var usd in _updateSetDict) + { + var field = _commonUtils.QuoteSqlName(usd.Key); + var findsql = $"{field} = EXCLUDED.{field}"; + var usdval = findregex.Replace(usd.Value, m => + { + if (m.Groups[1].Value == "t1") return $"{tableName}.{_commonUtils.QuoteSqlName(m.Groups[2].Value)}"; + return $"EXCLUDED.{_commonUtils.QuoteSqlName(m.Groups[2].Value)}"; + }); + sql = sql.Replace(findsql, $"{field} = {usdval}"); + } + } } if (string.IsNullOrEmpty(sql)) return null; if (insert._params?.Any() == true) dbParams.AddRange(insert._params); diff --git a/Providers/FreeSql.Provider.Custom/SqlServer/Curd/CustomSqlServerInsertOrUpdate.cs b/Providers/FreeSql.Provider.Custom/SqlServer/Curd/CustomSqlServerInsertOrUpdate.cs index 60d9f245..d862228a 100644 --- a/Providers/FreeSql.Provider.Custom/SqlServer/Curd/CustomSqlServerInsertOrUpdate.cs +++ b/Providers/FreeSql.Provider.Custom/SqlServer/Curd/CustomSqlServerInsertOrUpdate.cs @@ -41,14 +41,18 @@ namespace FreeSql.Custom.SqlServer WriteSourceSelectUnionAll(data, sb, dbParams); sb.Append(" ) t2 ON (").Append(string.Join(" AND ", _tempPrimarys.Select(a => $"t1.{_commonUtils.QuoteSqlName(a.Attribute.Name)} = t2.{_commonUtils.QuoteSqlName(a.Attribute.Name)}"))).Append(") \r\n"); - var cols = _table.Columns.Values.Where(a => _tempPrimarys.Contains(a) == false && a.Attribute.CanUpdate == true && a.Attribute.IsIdentity == false && _updateIgnore.ContainsKey(a.Attribute.Name) == false); + var cols = _table.Columns.Values.Where(a => _updateSetDict.ContainsKey(a.Attribute.Name) || + _tempPrimarys.Contains(a) == false && a.Attribute.CanUpdate == true && a.Attribute.IsIdentity == false && _updateIgnore.ContainsKey(a.Attribute.Name) == false); if (_doNothing == false && cols.Any()) sb.Append("WHEN MATCHED THEN \r\n") .Append(" update set ").Append(string.Join(", ", cols.Select(a => - a.Attribute.IsVersion && a.Attribute.MapType != typeof(byte[]) ? - $"{_commonUtils.QuoteSqlName(a.Attribute.Name)} = t1.{_commonUtils.QuoteSqlName(a.Attribute.Name)} + 1" : - $"{_commonUtils.QuoteSqlName(a.Attribute.Name)} = t2.{_commonUtils.QuoteSqlName(a.Attribute.Name)}" - ))).Append(" \r\n"); + { + if (_updateSetDict.TryGetValue(a.Attribute.Name, out var valsql)) + return $"{_commonUtils.QuoteSqlName(a.Attribute.Name)} = {valsql}"; + return a.Attribute.IsVersion && a.Attribute.MapType != typeof(byte[]) ? + $"{_commonUtils.QuoteSqlName(a.Attribute.Name)} = t1.{_commonUtils.QuoteSqlName(a.Attribute.Name)} + 1" : + $"{_commonUtils.QuoteSqlName(a.Attribute.Name)} = t2.{_commonUtils.QuoteSqlName(a.Attribute.Name)}"; + }))).Append(" \r\n"); cols = _table.Columns.Values.Where(a => a.Attribute.CanInsert == true); if (tempPrimaryIsIdentity == false) cols = cols.Where(a => a.Attribute.IsIdentity == false || string.IsNullOrEmpty(a.DbInsertValue) == false); diff --git a/Providers/FreeSql.Provider.Dameng/Curd/DamengInsertOrUpdate.cs b/Providers/FreeSql.Provider.Dameng/Curd/DamengInsertOrUpdate.cs index 8893c1f1..1436b6fc 100644 --- a/Providers/FreeSql.Provider.Dameng/Curd/DamengInsertOrUpdate.cs +++ b/Providers/FreeSql.Provider.Dameng/Curd/DamengInsertOrUpdate.cs @@ -39,14 +39,18 @@ namespace FreeSql.Dameng.Curd WriteSourceSelectUnionAll(data, sb, dbParams); sb.Append(" ) t2 ON (").Append(string.Join(" AND ", _tempPrimarys.Select(a => $"t1.{_commonUtils.QuoteSqlName(a.Attribute.Name)} = t2.{_commonUtils.QuoteSqlName(a.Attribute.Name)}"))).Append(") \r\n"); - var cols = _table.Columns.Values.Where(a => _tempPrimarys.Contains(a) == false && a.Attribute.CanUpdate == true && a.Attribute.IsIdentity == false && _updateIgnore.ContainsKey(a.Attribute.Name) == false); + var cols = _table.Columns.Values.Where(a => _updateSetDict.ContainsKey(a.Attribute.Name) || + _tempPrimarys.Contains(a) == false && a.Attribute.CanUpdate == true && a.Attribute.IsIdentity == false && _updateIgnore.ContainsKey(a.Attribute.Name) == false); if (_doNothing == false && cols.Any()) sb.Append("WHEN MATCHED THEN \r\n") .Append(" update set ").Append(string.Join(", ", cols.Select(a => - a.Attribute.IsVersion && a.Attribute.MapType != typeof(byte[]) ? - $"{_commonUtils.QuoteSqlName(a.Attribute.Name)} = t1.{_commonUtils.QuoteSqlName(a.Attribute.Name)} + 1" : - $"{_commonUtils.QuoteSqlName(a.Attribute.Name)} = t2.{_commonUtils.QuoteSqlName(a.Attribute.Name)}" - ))).Append(" \r\n"); + { + if (_updateSetDict.TryGetValue(a.Attribute.Name, out var valsql)) + return $"{_commonUtils.QuoteSqlName(a.Attribute.Name)} = {valsql}"; + return a.Attribute.IsVersion && a.Attribute.MapType != typeof(byte[]) ? + $"{_commonUtils.QuoteSqlName(a.Attribute.Name)} = t1.{_commonUtils.QuoteSqlName(a.Attribute.Name)} + 1" : + $"{_commonUtils.QuoteSqlName(a.Attribute.Name)} = t2.{_commonUtils.QuoteSqlName(a.Attribute.Name)}"; + }))).Append(" \r\n"); cols = _table.Columns.Values.Where(a => a.Attribute.CanInsert == true); if (tempPrimaryIsIdentity == false) cols = cols.Where(a => a.Attribute.IsIdentity == false || string.IsNullOrEmpty(a.DbInsertValue) == false); diff --git a/Providers/FreeSql.Provider.Firebird/Curd/FirebirdInsertOrUpdate.cs b/Providers/FreeSql.Provider.Firebird/Curd/FirebirdInsertOrUpdate.cs index bd9bda60..c2ffe814 100644 --- a/Providers/FreeSql.Provider.Firebird/Curd/FirebirdInsertOrUpdate.cs +++ b/Providers/FreeSql.Provider.Firebird/Curd/FirebirdInsertOrUpdate.cs @@ -39,14 +39,18 @@ namespace FreeSql.Firebird.Curd WriteSourceSelectUnionAll(data, sb, dbParams); sb.Append(" ) t2 ON (").Append(string.Join(" AND ", _tempPrimarys.Select(a => $"t1.{_commonUtils.QuoteSqlName(a.Attribute.Name)} = t2.{_commonUtils.QuoteSqlName(a.Attribute.Name)}"))).Append(") \r\n"); - var cols = _table.Columns.Values.Where(a => _tempPrimarys.Contains(a) == false && a.Attribute.CanUpdate == true && a.Attribute.IsIdentity == false && _updateIgnore.ContainsKey(a.Attribute.Name) == false); + var cols = _table.Columns.Values.Where(a => _updateSetDict.ContainsKey(a.Attribute.Name) || + _tempPrimarys.Contains(a) == false && a.Attribute.CanUpdate == true && a.Attribute.IsIdentity == false && _updateIgnore.ContainsKey(a.Attribute.Name) == false); if (_doNothing == false && cols.Any()) sb.Append("WHEN MATCHED THEN \r\n") .Append(" update set ").Append(string.Join(", ", cols.Select(a => - a.Attribute.IsVersion && a.Attribute.MapType != typeof(byte[]) ? - $"{_commonUtils.QuoteSqlName(a.Attribute.Name)} = t1.{_commonUtils.QuoteSqlName(a.Attribute.Name)} + 1" : - $"{_commonUtils.QuoteSqlName(a.Attribute.Name)} = t2.{_commonUtils.QuoteSqlName(a.Attribute.Name)}" - ))).Append(" \r\n"); + { + if (_updateSetDict.TryGetValue(a.Attribute.Name, out var valsql)) + return $"{_commonUtils.QuoteSqlName(a.Attribute.Name)} = {valsql}"; + return a.Attribute.IsVersion && a.Attribute.MapType != typeof(byte[]) ? + $"{_commonUtils.QuoteSqlName(a.Attribute.Name)} = t1.{_commonUtils.QuoteSqlName(a.Attribute.Name)} + 1" : + $"{_commonUtils.QuoteSqlName(a.Attribute.Name)} = t2.{_commonUtils.QuoteSqlName(a.Attribute.Name)}"; + }))).Append(" \r\n"); cols = _table.Columns.Values.Where(a => a.Attribute.CanInsert == true); if (tempPrimaryIsIdentity == false) cols = cols.Where(a => a.Attribute.IsIdentity == false || string.IsNullOrEmpty(a.DbInsertValue) == false); diff --git a/Providers/FreeSql.Provider.GBase/Curd/GBaseInsertOrUpdate.cs b/Providers/FreeSql.Provider.GBase/Curd/GBaseInsertOrUpdate.cs index 4b6756c4..66719f42 100644 --- a/Providers/FreeSql.Provider.GBase/Curd/GBaseInsertOrUpdate.cs +++ b/Providers/FreeSql.Provider.GBase/Curd/GBaseInsertOrUpdate.cs @@ -39,14 +39,18 @@ namespace FreeSql.GBase.Curd WriteSourceSelectUnionAll(data, sb, dbParams); sb.Append(" ) t2 ON (").Append(string.Join(" AND ", _tempPrimarys.Select(a => $"t1.{_commonUtils.QuoteSqlName(a.Attribute.Name)} = t2.{_commonUtils.QuoteSqlName(a.Attribute.Name)}"))).Append(") \r\n"); - var cols = _table.Columns.Values.Where(a => _tempPrimarys.Contains(a) == false && a.Attribute.CanUpdate == true && a.Attribute.IsIdentity == false && _updateIgnore.ContainsKey(a.Attribute.Name) == false); + var cols = _table.Columns.Values.Where(a => _updateSetDict.ContainsKey(a.Attribute.Name) || + _tempPrimarys.Contains(a) == false && a.Attribute.CanUpdate == true && a.Attribute.IsIdentity == false && _updateIgnore.ContainsKey(a.Attribute.Name) == false); if (_doNothing == false && cols.Any()) sb.Append("WHEN MATCHED THEN \r\n") .Append(" update set ").Append(string.Join(", ", cols.Select(a => - a.Attribute.IsVersion && a.Attribute.MapType != typeof(byte[]) ? - $"t1.{_commonUtils.QuoteSqlName(a.Attribute.Name)} = t1.{_commonUtils.QuoteSqlName(a.Attribute.Name)} + 1" : - $"t1.{_commonUtils.QuoteSqlName(a.Attribute.Name)} = t2.{_commonUtils.QuoteSqlName(a.Attribute.Name)}" - ))).Append(" \r\n"); + { + if (_updateSetDict.TryGetValue(a.Attribute.Name, out var valsql)) + return $"t1.{_commonUtils.QuoteSqlName(a.Attribute.Name)} = {valsql}"; + return a.Attribute.IsVersion && a.Attribute.MapType != typeof(byte[]) ? + $"t1.{_commonUtils.QuoteSqlName(a.Attribute.Name)} = t1.{_commonUtils.QuoteSqlName(a.Attribute.Name)} + 1" : + $"t1.{_commonUtils.QuoteSqlName(a.Attribute.Name)} = t2.{_commonUtils.QuoteSqlName(a.Attribute.Name)}"; + }))).Append(" \r\n"); cols = _table.Columns.Values.Where(a => a.Attribute.CanInsert == true); if (tempPrimaryIsIdentity == false) cols = cols.Where(a => a.Attribute.IsIdentity == false || string.IsNullOrEmpty(a.DbInsertValue) == false); diff --git a/Providers/FreeSql.Provider.KingbaseES/Curd/KingbaseESInsertOrUpdate.cs b/Providers/FreeSql.Provider.KingbaseES/Curd/KingbaseESInsertOrUpdate.cs index f87ac788..511c0961 100644 --- a/Providers/FreeSql.Provider.KingbaseES/Curd/KingbaseESInsertOrUpdate.cs +++ b/Providers/FreeSql.Provider.KingbaseES/Curd/KingbaseESInsertOrUpdate.cs @@ -3,6 +3,7 @@ using System.Collections.Generic; using System.Data.Common; using System.Linq; using System.Text; +using System.Text.RegularExpressions; namespace FreeSql.KingbaseES { @@ -57,11 +58,29 @@ namespace FreeSql.KingbaseES { var ocdu = new KingbaseESOnConflictDoUpdate(insert.InsertIdentity()); ocdu._tempPrimarys = _tempPrimarys; - var cols = _table.Columns.Values.Where(a => _tempPrimarys.Contains(a) == false && a.Attribute.CanUpdate == true && a.Attribute.IsIdentity == false && _updateIgnore.ContainsKey(a.Attribute.Name) == false); + var cols = _table.Columns.Values.Where(a => _updateSetDict.ContainsKey(a.Attribute.Name) || + _tempPrimarys.Contains(a) == false && a.Attribute.CanUpdate == true && a.Attribute.IsIdentity == false && _updateIgnore.ContainsKey(a.Attribute.Name) == false); ocdu.UpdateColumns(cols.Select(a => a.Attribute.Name).ToArray()); if (_doNothing == true || cols.Any() == false) ocdu.DoNothing(); sql = ocdu.ToSql(); + + if (_updateSetDict.Any()) + { + var findregex = new Regex("(t1|t2)." + _commonUtils.QuoteSqlName("test").Replace("test", "(\\w+)")); + var tableName = _commonUtils.QuoteSqlName(TableRuleInvoke()); + foreach (var usd in _updateSetDict) + { + var field = _commonUtils.QuoteSqlName(usd.Key); + var findsql = $"{field} = EXCLUDED.{field}"; + var usdval = findregex.Replace(usd.Value, m => + { + if (m.Groups[1].Value == "t1") return $"{tableName}.{_commonUtils.QuoteSqlName(m.Groups[2].Value)}"; + return $"EXCLUDED.{_commonUtils.QuoteSqlName(m.Groups[2].Value)}"; + }); + sql = sql.Replace(findsql, $"{field} = {usdval}"); + } + } } if (string.IsNullOrEmpty(sql)) return null; if (insert._params?.Any() == true) dbParams.AddRange(insert._params); diff --git a/Providers/FreeSql.Provider.MySql/Curd/MySqlInsertOrUpdate.cs b/Providers/FreeSql.Provider.MySql/Curd/MySqlInsertOrUpdate.cs index d75c3a28..2afc1ca9 100644 --- a/Providers/FreeSql.Provider.MySql/Curd/MySqlInsertOrUpdate.cs +++ b/Providers/FreeSql.Provider.MySql/Curd/MySqlInsertOrUpdate.cs @@ -4,6 +4,7 @@ using System.Collections.Generic; using System.Data.Common; using System.Linq; using System.Text; +using System.Text.RegularExpressions; namespace FreeSql.MySql.Curd { @@ -62,10 +63,26 @@ namespace FreeSql.MySql.Curd insert.InsertIdentity(); if (_doNothing == false) { - var cols = _table.Columns.Values.Where(a => _tempPrimarys.Contains(a) == false && a.Attribute.CanUpdate == true && a.Attribute.IsIdentity == false && _updateIgnore.ContainsKey(a.Attribute.Name) == false); + var cols = _table.Columns.Values.Where(a => _updateSetDict.ContainsKey(a.Attribute.Name) || + _tempPrimarys.Contains(a) == false && a.Attribute.CanUpdate == true && a.Attribute.IsIdentity == false && _updateIgnore.ContainsKey(a.Attribute.Name) == false); sql = new OnDuplicateKeyUpdate(insert) .UpdateColumns(cols.Select(a => a.Attribute.Name).ToArray()) .ToSql(); + if (_updateSetDict.Any()) + { + var findregex = new Regex("(t1|t2)." + _commonUtils.QuoteSqlName("test").Replace("test", "(\\w+)")); + foreach (var usd in _updateSetDict) + { + var field = _commonUtils.QuoteSqlName(usd.Key); + var findsql = $"{field} = VALUES({field})"; + var usdval = findregex.Replace(usd.Value, m => + { + if (m.Groups[1].Value == "t1") return _commonUtils.QuoteSqlName(m.Groups[2].Value); + return $"VALUES({_commonUtils.QuoteSqlName(m.Groups[2].Value)})"; + }); + sql = sql.Replace(findsql, $"{field} = {usdval}"); + } + } } else { diff --git a/Providers/FreeSql.Provider.Odbc/Dameng/Curd/OdbcDamengInsertOrUpdate.cs b/Providers/FreeSql.Provider.Odbc/Dameng/Curd/OdbcDamengInsertOrUpdate.cs index d35c1097..5f1debb7 100644 --- a/Providers/FreeSql.Provider.Odbc/Dameng/Curd/OdbcDamengInsertOrUpdate.cs +++ b/Providers/FreeSql.Provider.Odbc/Dameng/Curd/OdbcDamengInsertOrUpdate.cs @@ -39,14 +39,18 @@ namespace FreeSql.Odbc.Dameng WriteSourceSelectUnionAll(data, sb, dbParams); sb.Append(" ) t2 ON (").Append(string.Join(" AND ", _tempPrimarys.Select(a => $"t1.{_commonUtils.QuoteSqlName(a.Attribute.Name)} = t2.{_commonUtils.QuoteSqlName(a.Attribute.Name)}"))).Append(") \r\n"); - var cols = _table.Columns.Values.Where(a => _tempPrimarys.Contains(a) == false && a.Attribute.CanUpdate == true && a.Attribute.IsIdentity == false && _updateIgnore.ContainsKey(a.Attribute.Name) == false); + var cols = _table.Columns.Values.Where(a => _updateSetDict.ContainsKey(a.Attribute.Name) || + _tempPrimarys.Contains(a) == false && a.Attribute.CanUpdate == true && a.Attribute.IsIdentity == false && _updateIgnore.ContainsKey(a.Attribute.Name) == false); if (_doNothing == false && cols.Any()) sb.Append("WHEN MATCHED THEN \r\n") .Append(" update set ").Append(string.Join(", ", cols.Select(a => - a.Attribute.IsVersion && a.Attribute.MapType != typeof(byte[]) ? - $"{_commonUtils.QuoteSqlName(a.Attribute.Name)} = t1.{_commonUtils.QuoteSqlName(a.Attribute.Name)} + 1" : - $"{_commonUtils.QuoteSqlName(a.Attribute.Name)} = t2.{_commonUtils.QuoteSqlName(a.Attribute.Name)}" - ))).Append(" \r\n"); + { + if (_updateSetDict.TryGetValue(a.Attribute.Name, out var valsql)) + return $"{_commonUtils.QuoteSqlName(a.Attribute.Name)} = {valsql}"; + return a.Attribute.IsVersion && a.Attribute.MapType != typeof(byte[]) ? + $"{_commonUtils.QuoteSqlName(a.Attribute.Name)} = t1.{_commonUtils.QuoteSqlName(a.Attribute.Name)} + 1" : + $"{_commonUtils.QuoteSqlName(a.Attribute.Name)} = t2.{_commonUtils.QuoteSqlName(a.Attribute.Name)}"; + }))).Append(" \r\n"); cols = _table.Columns.Values.Where(a => a.Attribute.CanInsert == true); if (tempPrimaryIsIdentity == false) cols = cols.Where(a => a.Attribute.IsIdentity == false || string.IsNullOrEmpty(a.DbInsertValue) == false); diff --git a/Providers/FreeSql.Provider.Odbc/KingbaseES/Curd/OdbcKingbaseESInsertOrUpdate.cs b/Providers/FreeSql.Provider.Odbc/KingbaseES/Curd/OdbcKingbaseESInsertOrUpdate.cs index a307b2ca..d5bb8565 100644 --- a/Providers/FreeSql.Provider.Odbc/KingbaseES/Curd/OdbcKingbaseESInsertOrUpdate.cs +++ b/Providers/FreeSql.Provider.Odbc/KingbaseES/Curd/OdbcKingbaseESInsertOrUpdate.cs @@ -4,6 +4,7 @@ using System.Collections.Generic; using System.Data.Common; using System.Linq; using System.Text; +using System.Text.RegularExpressions; namespace FreeSql.Odbc.KingbaseES { @@ -58,11 +59,29 @@ namespace FreeSql.Odbc.KingbaseES { var ocdu = new OdbcKingbaseESOnConflictDoUpdate(insert.InsertIdentity()); ocdu._tempPrimarys = _tempPrimarys; - var cols = _table.Columns.Values.Where(a => _tempPrimarys.Contains(a) == false && a.Attribute.CanUpdate == true && a.Attribute.IsIdentity == false && _updateIgnore.ContainsKey(a.Attribute.Name) == false); + var cols = _table.Columns.Values.Where(a => _updateSetDict.ContainsKey(a.Attribute.Name) || + _tempPrimarys.Contains(a) == false && a.Attribute.CanUpdate == true && a.Attribute.IsIdentity == false && _updateIgnore.ContainsKey(a.Attribute.Name) == false); ocdu.UpdateColumns(cols.Select(a => a.Attribute.Name).ToArray()); if (_doNothing == true || cols.Any() == false) ocdu.DoNothing(); sql = ocdu.ToSql(); + + if (_updateSetDict.Any()) + { + var findregex = new Regex("(t1|t2)." + _commonUtils.QuoteSqlName("test").Replace("test", "(\\w+)")); + var tableName = _commonUtils.QuoteSqlName(TableRuleInvoke()); + foreach (var usd in _updateSetDict) + { + var field = _commonUtils.QuoteSqlName(usd.Key); + var findsql = $"{field} = EXCLUDED.{field}"; + var usdval = findregex.Replace(usd.Value, m => + { + if (m.Groups[1].Value == "t1") return $"{tableName}.{_commonUtils.QuoteSqlName(m.Groups[2].Value)}"; + return $"EXCLUDED.{_commonUtils.QuoteSqlName(m.Groups[2].Value)}"; + }); + sql = sql.Replace(findsql, $"{field} = {usdval}"); + } + } } if (string.IsNullOrEmpty(sql)) return null; if (insert._params?.Any() == true) dbParams.AddRange(insert._params); diff --git a/Providers/FreeSql.Provider.Odbc/MySql/Curd/OdbcMySqlInsertOrUpdate.cs b/Providers/FreeSql.Provider.Odbc/MySql/Curd/OdbcMySqlInsertOrUpdate.cs index 5aefcaf9..83d90f1d 100644 --- a/Providers/FreeSql.Provider.Odbc/MySql/Curd/OdbcMySqlInsertOrUpdate.cs +++ b/Providers/FreeSql.Provider.Odbc/MySql/Curd/OdbcMySqlInsertOrUpdate.cs @@ -4,6 +4,7 @@ using System.Collections.Generic; using System.Data.Common; using System.Linq; using System.Text; +using System.Text.RegularExpressions; namespace FreeSql.Odbc.MySql { @@ -62,10 +63,26 @@ namespace FreeSql.Odbc.MySql insert.InsertIdentity(); if (_doNothing == false) { - var cols = _table.Columns.Values.Where(a => _tempPrimarys.Contains(a) == false && a.Attribute.CanUpdate == true && a.Attribute.IsIdentity == false && _updateIgnore.ContainsKey(a.Attribute.Name) == false); + var cols = _table.Columns.Values.Where(a => _updateSetDict.ContainsKey(a.Attribute.Name) || + _tempPrimarys.Contains(a) == false && a.Attribute.CanUpdate == true && a.Attribute.IsIdentity == false && _updateIgnore.ContainsKey(a.Attribute.Name) == false); sql = new OdbcMySqlOnDuplicateKeyUpdate(insert) .UpdateColumns(cols.Select(a => a.Attribute.Name).ToArray()) .ToSql(); + if (_updateSetDict.Any()) + { + var findregex = new Regex("(t1|t2)." + _commonUtils.QuoteSqlName("test").Replace("test", "(\\w+)")); + foreach (var usd in _updateSetDict) + { + var field = _commonUtils.QuoteSqlName(usd.Key); + var findsql = $"{field} = VALUES({field})"; + var usdval = findregex.Replace(usd.Value, m => + { + if (m.Groups[1].Value == "t1") return _commonUtils.QuoteSqlName(m.Groups[2].Value); + return $"VALUES({_commonUtils.QuoteSqlName(m.Groups[2].Value)})"; + }); + sql = sql.Replace(findsql, $"{field} = {usdval}"); + } + } } else { diff --git a/Providers/FreeSql.Provider.Odbc/Oracle/Curd/OdbcOracleInsertOrUpdate.cs b/Providers/FreeSql.Provider.Odbc/Oracle/Curd/OdbcOracleInsertOrUpdate.cs index b70eb435..72da5a97 100644 --- a/Providers/FreeSql.Provider.Odbc/Oracle/Curd/OdbcOracleInsertOrUpdate.cs +++ b/Providers/FreeSql.Provider.Odbc/Oracle/Curd/OdbcOracleInsertOrUpdate.cs @@ -39,14 +39,18 @@ namespace FreeSql.Odbc.Oracle WriteSourceSelectUnionAll(data, sb, dbParams); sb.Append(" ) t2 ON (").Append(string.Join(" AND ", _tempPrimarys.Select(a => $"t1.{_commonUtils.QuoteSqlName(a.Attribute.Name)} = t2.{_commonUtils.QuoteSqlName(a.Attribute.Name)}"))).Append(") \r\n"); - var cols = _table.Columns.Values.Where(a => _tempPrimarys.Contains(a) == false && a.Attribute.CanUpdate == true && a.Attribute.IsIdentity == false && _updateIgnore.ContainsKey(a.Attribute.Name) == false); + var cols = _table.Columns.Values.Where(a => _updateSetDict.ContainsKey(a.Attribute.Name) || + _tempPrimarys.Contains(a) == false && a.Attribute.CanUpdate == true && a.Attribute.IsIdentity == false && _updateIgnore.ContainsKey(a.Attribute.Name) == false); if (_doNothing == false && cols.Any()) sb.Append("WHEN MATCHED THEN \r\n") .Append(" update set ").Append(string.Join(", ", cols.Select(a => - a.Attribute.IsVersion && a.Attribute.MapType != typeof(byte[]) ? - $"{_commonUtils.QuoteSqlName(a.Attribute.Name)} = t1.{_commonUtils.QuoteSqlName(a.Attribute.Name)} + 1" : - $"{_commonUtils.QuoteSqlName(a.Attribute.Name)} = t2.{_commonUtils.QuoteSqlName(a.Attribute.Name)}" - ))).Append(" \r\n"); + { + if (_updateSetDict.TryGetValue(a.Attribute.Name, out var valsql)) + return $"{_commonUtils.QuoteSqlName(a.Attribute.Name)} = {valsql}"; + return a.Attribute.IsVersion && a.Attribute.MapType != typeof(byte[]) ? + $"{_commonUtils.QuoteSqlName(a.Attribute.Name)} = t1.{_commonUtils.QuoteSqlName(a.Attribute.Name)} + 1" : + $"{_commonUtils.QuoteSqlName(a.Attribute.Name)} = t2.{_commonUtils.QuoteSqlName(a.Attribute.Name)}"; + }))).Append(" \r\n"); cols = _table.Columns.Values.Where(a => a.Attribute.CanInsert == true); if (tempPrimaryIsIdentity == false) cols = cols.Where(a => a.Attribute.IsIdentity == false || string.IsNullOrEmpty(a.DbInsertValue) == false); diff --git a/Providers/FreeSql.Provider.Odbc/PostgreSQL/Curd/OdbcPostgreSQLInsertOrUpdate.cs b/Providers/FreeSql.Provider.Odbc/PostgreSQL/Curd/OdbcPostgreSQLInsertOrUpdate.cs index 2c6b2f6f..e0a60d74 100644 --- a/Providers/FreeSql.Provider.Odbc/PostgreSQL/Curd/OdbcPostgreSQLInsertOrUpdate.cs +++ b/Providers/FreeSql.Provider.Odbc/PostgreSQL/Curd/OdbcPostgreSQLInsertOrUpdate.cs @@ -3,6 +3,7 @@ using System.Collections.Generic; using System.Data.Common; using System.Linq; using System.Text; +using System.Text.RegularExpressions; namespace FreeSql.Odbc.PostgreSQL { @@ -57,11 +58,29 @@ namespace FreeSql.Odbc.PostgreSQL { var ocdu = new OdbcPostgreSQLOnConflictDoUpdate(insert.InsertIdentity()); ocdu._tempPrimarys = _tempPrimarys; - var cols = _table.Columns.Values.Where(a => _tempPrimarys.Contains(a) == false && a.Attribute.CanUpdate == true && a.Attribute.IsIdentity == false && _updateIgnore.ContainsKey(a.Attribute.Name) == false); + var cols = _table.Columns.Values.Where(a => _updateSetDict.ContainsKey(a.Attribute.Name) || + _tempPrimarys.Contains(a) == false && a.Attribute.CanUpdate == true && a.Attribute.IsIdentity == false && _updateIgnore.ContainsKey(a.Attribute.Name) == false); ocdu.UpdateColumns(cols.Select(a => a.Attribute.Name).ToArray()); if (_doNothing == true || cols.Any() == false) ocdu.DoNothing(); sql = ocdu.ToSql(); + + if (_updateSetDict.Any()) + { + var findregex = new Regex("(t1|t2)." + _commonUtils.QuoteSqlName("test").Replace("test", "(\\w+)")); + var tableName = _commonUtils.QuoteSqlName(TableRuleInvoke()); + foreach (var usd in _updateSetDict) + { + var field = _commonUtils.QuoteSqlName(usd.Key); + var findsql = $"{field} = EXCLUDED.{field}"; + var usdval = findregex.Replace(usd.Value, m => + { + if (m.Groups[1].Value == "t1") return $"{tableName}.{_commonUtils.QuoteSqlName(m.Groups[2].Value)}"; + return $"EXCLUDED.{_commonUtils.QuoteSqlName(m.Groups[2].Value)}"; + }); + sql = sql.Replace(findsql, $"{field} = {usdval}"); + } + } } if (string.IsNullOrEmpty(sql)) return null; if (insert._params?.Any() == true) dbParams.AddRange(insert._params); diff --git a/Providers/FreeSql.Provider.Odbc/SqlServer/Curd/OdbcSqlServerInsertOrUpdate.cs b/Providers/FreeSql.Provider.Odbc/SqlServer/Curd/OdbcSqlServerInsertOrUpdate.cs index b53974dc..8db1590f 100644 --- a/Providers/FreeSql.Provider.Odbc/SqlServer/Curd/OdbcSqlServerInsertOrUpdate.cs +++ b/Providers/FreeSql.Provider.Odbc/SqlServer/Curd/OdbcSqlServerInsertOrUpdate.cs @@ -41,14 +41,18 @@ namespace FreeSql.Odbc.SqlServer WriteSourceSelectUnionAll(data, sb, dbParams); sb.Append(" ) t2 ON (").Append(string.Join(" AND ", _tempPrimarys.Select(a => $"t1.{_commonUtils.QuoteSqlName(a.Attribute.Name)} = t2.{_commonUtils.QuoteSqlName(a.Attribute.Name)}"))).Append(") \r\n"); - var cols = _table.Columns.Values.Where(a => _tempPrimarys.Contains(a) == false && a.Attribute.CanUpdate == true && a.Attribute.IsIdentity == false && _updateIgnore.ContainsKey(a.Attribute.Name) == false); + var cols = _table.Columns.Values.Where(a => _updateSetDict.ContainsKey(a.Attribute.Name) || + _tempPrimarys.Contains(a) == false && a.Attribute.CanUpdate == true && a.Attribute.IsIdentity == false && _updateIgnore.ContainsKey(a.Attribute.Name) == false); if (_doNothing == false && cols.Any()) sb.Append("WHEN MATCHED THEN \r\n") .Append(" update set ").Append(string.Join(", ", cols.Select(a => - a.Attribute.IsVersion && a.Attribute.MapType != typeof(byte[]) ? - $"{_commonUtils.QuoteSqlName(a.Attribute.Name)} = t1.{_commonUtils.QuoteSqlName(a.Attribute.Name)} + 1" : - $"{_commonUtils.QuoteSqlName(a.Attribute.Name)} = t2.{_commonUtils.QuoteSqlName(a.Attribute.Name)}" - ))).Append(" \r\n"); + { + if (_updateSetDict.TryGetValue(a.Attribute.Name, out var valsql)) + return $"{_commonUtils.QuoteSqlName(a.Attribute.Name)} = {valsql}"; + return a.Attribute.IsVersion && a.Attribute.MapType != typeof(byte[]) ? + $"{_commonUtils.QuoteSqlName(a.Attribute.Name)} = t1.{_commonUtils.QuoteSqlName(a.Attribute.Name)} + 1" : + $"{_commonUtils.QuoteSqlName(a.Attribute.Name)} = t2.{_commonUtils.QuoteSqlName(a.Attribute.Name)}"; + }))).Append(" \r\n"); cols = _table.Columns.Values.Where(a => a.Attribute.CanInsert == true); if (tempPrimaryIsIdentity == false) cols = cols.Where(a => a.Attribute.IsIdentity == false || string.IsNullOrEmpty(a.DbInsertValue) == false); diff --git a/Providers/FreeSql.Provider.Oracle/Curd/OracleInsertOrUpdate.cs b/Providers/FreeSql.Provider.Oracle/Curd/OracleInsertOrUpdate.cs index ace26d30..f2612dbb 100644 --- a/Providers/FreeSql.Provider.Oracle/Curd/OracleInsertOrUpdate.cs +++ b/Providers/FreeSql.Provider.Oracle/Curd/OracleInsertOrUpdate.cs @@ -39,14 +39,18 @@ namespace FreeSql.Oracle.Curd WriteSourceSelectUnionAll(data, sb, dbParams); sb.Append(" ) t2 ON (").Append(string.Join(" AND ", _tempPrimarys.Select(a => $"t1.{_commonUtils.QuoteSqlName(a.Attribute.Name)} = t2.{_commonUtils.QuoteSqlName(a.Attribute.Name)}"))).Append(") \r\n"); - var cols = _table.Columns.Values.Where(a => _tempPrimarys.Contains(a) == false && a.Attribute.CanUpdate == true && a.Attribute.IsIdentity == false && _updateIgnore.ContainsKey(a.Attribute.Name) == false); + var cols = _table.Columns.Values.Where(a => _updateSetDict.ContainsKey(a.Attribute.Name) || + _tempPrimarys.Contains(a) == false && a.Attribute.CanUpdate == true && a.Attribute.IsIdentity == false && _updateIgnore.ContainsKey(a.Attribute.Name) == false); if (_doNothing == false && cols.Any()) sb.Append("WHEN MATCHED THEN \r\n") .Append(" update set ").Append(string.Join(", ", cols.Select(a => - a.Attribute.IsVersion && a.Attribute.MapType != typeof(byte[]) ? - $"{_commonUtils.QuoteSqlName(a.Attribute.Name)} = t1.{_commonUtils.QuoteSqlName(a.Attribute.Name)} + 1" : - $"{_commonUtils.QuoteSqlName(a.Attribute.Name)} = t2.{_commonUtils.QuoteSqlName(a.Attribute.Name)}" - ))).Append(" \r\n"); + { + if (_updateSetDict.TryGetValue(a.Attribute.Name, out var valsql)) + return $"{_commonUtils.QuoteSqlName(a.Attribute.Name)} = {valsql}"; + return a.Attribute.IsVersion && a.Attribute.MapType != typeof(byte[]) ? + $"{_commonUtils.QuoteSqlName(a.Attribute.Name)} = t1.{_commonUtils.QuoteSqlName(a.Attribute.Name)} + 1" : + $"{_commonUtils.QuoteSqlName(a.Attribute.Name)} = t2.{_commonUtils.QuoteSqlName(a.Attribute.Name)}"; + }))).Append(" \r\n"); cols = _table.Columns.Values.Where(a => a.Attribute.CanInsert == true); if (tempPrimaryIsIdentity == false) cols = cols.Where(a => a.Attribute.IsIdentity == false || string.IsNullOrEmpty(a.DbInsertValue) == false); diff --git a/Providers/FreeSql.Provider.PostgreSQL/Curd/PostgreSQLInsertOrUpdate.cs b/Providers/FreeSql.Provider.PostgreSQL/Curd/PostgreSQLInsertOrUpdate.cs index 64f3b31a..01b215bb 100644 --- a/Providers/FreeSql.Provider.PostgreSQL/Curd/PostgreSQLInsertOrUpdate.cs +++ b/Providers/FreeSql.Provider.PostgreSQL/Curd/PostgreSQLInsertOrUpdate.cs @@ -3,6 +3,7 @@ using System.Collections.Generic; using System.Data.Common; using System.Linq; using System.Text; +using System.Text.RegularExpressions; namespace FreeSql.PostgreSQL.Curd { @@ -57,11 +58,29 @@ namespace FreeSql.PostgreSQL.Curd { var ocdu = new OnConflictDoUpdate(insert.InsertIdentity()); ocdu._tempPrimarys = _tempPrimarys; - var cols = _table.Columns.Values.Where(a => _tempPrimarys.Contains(a) == false && a.Attribute.CanUpdate == true && a.Attribute.IsIdentity == false && _updateIgnore.ContainsKey(a.Attribute.Name) == false); + var cols = _table.Columns.Values.Where(a => _updateSetDict.ContainsKey(a.Attribute.Name) || + _tempPrimarys.Contains(a) == false && a.Attribute.CanUpdate == true && a.Attribute.IsIdentity == false && _updateIgnore.ContainsKey(a.Attribute.Name) == false); ocdu.UpdateColumns(cols.Select(a => a.Attribute.Name).ToArray()); if (_doNothing == true || cols.Any() == false) ocdu.DoNothing(); sql = ocdu.ToSql(); + + if (_updateSetDict.Any()) + { + var findregex = new Regex("(t1|t2)." + _commonUtils.QuoteSqlName("test").Replace("test", "(\\w+)")); + var tableName = _commonUtils.QuoteSqlName(TableRuleInvoke()); + foreach (var usd in _updateSetDict) + { + var field = _commonUtils.QuoteSqlName(usd.Key); + var findsql = $"{field} = EXCLUDED.{field}"; + var usdval = findregex.Replace(usd.Value, m => + { + if (m.Groups[1].Value == "t1") return $"{tableName}.{_commonUtils.QuoteSqlName(m.Groups[2].Value)}"; + return $"EXCLUDED.{_commonUtils.QuoteSqlName(m.Groups[2].Value)}"; + }); + sql = sql.Replace(findsql, $"{field} = {usdval}"); + } + } } if (string.IsNullOrEmpty(sql)) return null; if (insert._params?.Any() == true) dbParams.AddRange(insert._params); diff --git a/Providers/FreeSql.Provider.QuestDb/Curd/QuestDbInsertOrUpdate.cs b/Providers/FreeSql.Provider.QuestDb/Curd/QuestDbInsertOrUpdate.cs index 5e4af026..5db6154a 100644 --- a/Providers/FreeSql.Provider.QuestDb/Curd/QuestDbInsertOrUpdate.cs +++ b/Providers/FreeSql.Provider.QuestDb/Curd/QuestDbInsertOrUpdate.cs @@ -3,6 +3,7 @@ using System.Collections.Generic; using System.Data.Common; using System.Linq; using System.Text; +using System.Text.RegularExpressions; namespace FreeSql.QuestDb.Curd { @@ -57,11 +58,29 @@ namespace FreeSql.QuestDb.Curd { var ocdu = new OnConflictDoUpdate(insert.InsertIdentity()); ocdu._tempPrimarys = _tempPrimarys; - var cols = _table.Columns.Values.Where(a => _tempPrimarys.Contains(a) == false && a.Attribute.CanUpdate == true && a.Attribute.IsIdentity == false && _updateIgnore.ContainsKey(a.Attribute.Name) == false); + var cols = _table.Columns.Values.Where(a => _updateSetDict.ContainsKey(a.Attribute.Name) || + _tempPrimarys.Contains(a) == false && a.Attribute.CanUpdate == true && a.Attribute.IsIdentity == false && _updateIgnore.ContainsKey(a.Attribute.Name) == false); ocdu.UpdateColumns(cols.Select(a => a.Attribute.Name).ToArray()); if (_doNothing == true || cols.Any() == false) ocdu.DoNothing(); sql = ocdu.ToSql(); + + if (_updateSetDict.Any()) + { + var findregex = new Regex("(t1|t2)." + _commonUtils.QuoteSqlName("test").Replace("test", "(\\w+)")); + var tableName = _commonUtils.QuoteSqlName(TableRuleInvoke()); + foreach (var usd in _updateSetDict) + { + var field = _commonUtils.QuoteSqlName(usd.Key); + var findsql = $"{field} = EXCLUDED.{field}"; + var usdval = findregex.Replace(usd.Value, m => + { + if (m.Groups[1].Value == "t1") return $"{tableName}.{_commonUtils.QuoteSqlName(m.Groups[2].Value)}"; + return $"EXCLUDED.{_commonUtils.QuoteSqlName(m.Groups[2].Value)}"; + }); + sql = sql.Replace(findsql, $"{field} = {usdval}"); + } + } } if (string.IsNullOrEmpty(sql)) return null; if (insert._params?.Any() == true) dbParams.AddRange(insert._params); diff --git a/Providers/FreeSql.Provider.ShenTong/Curd/ShenTongInsertOrUpdate.cs b/Providers/FreeSql.Provider.ShenTong/Curd/ShenTongInsertOrUpdate.cs index 6bdd3648..009f3287 100644 --- a/Providers/FreeSql.Provider.ShenTong/Curd/ShenTongInsertOrUpdate.cs +++ b/Providers/FreeSql.Provider.ShenTong/Curd/ShenTongInsertOrUpdate.cs @@ -39,14 +39,18 @@ namespace FreeSql.ShenTong.Curd WriteSourceSelectUnionAll(data, sb, dbParams); sb.Append(" ) t2 ON (").Append(string.Join(" AND ", _tempPrimarys.Select(a => $"t1.{_commonUtils.QuoteSqlName(a.Attribute.Name)} = t2.{_commonUtils.QuoteSqlName(a.Attribute.Name)}"))).Append(") \r\n"); - var cols = _table.Columns.Values.Where(a => _tempPrimarys.Contains(a) == false && a.Attribute.CanUpdate == true && a.Attribute.IsIdentity == false && _updateIgnore.ContainsKey(a.Attribute.Name) == false); + var cols = _table.Columns.Values.Where(a => _updateSetDict.ContainsKey(a.Attribute.Name) || + _tempPrimarys.Contains(a) == false && a.Attribute.CanUpdate == true && a.Attribute.IsIdentity == false && _updateIgnore.ContainsKey(a.Attribute.Name) == false); if (_doNothing == false && cols.Any()) sb.Append("WHEN MATCHED THEN \r\n") .Append(" update set ").Append(string.Join(", ", cols.Select(a => - a.Attribute.IsVersion && a.Attribute.MapType != typeof(byte[]) ? - $"{_commonUtils.QuoteSqlName(a.Attribute.Name)} = t1.{_commonUtils.QuoteSqlName(a.Attribute.Name)} + 1" : - $"{_commonUtils.QuoteSqlName(a.Attribute.Name)} = t2.{_commonUtils.QuoteSqlName(a.Attribute.Name)}" - ))).Append(" \r\n"); + { + if (_updateSetDict.TryGetValue(a.Attribute.Name, out var valsql)) + return $"{_commonUtils.QuoteSqlName(a.Attribute.Name)} = {valsql}"; + return a.Attribute.IsVersion && a.Attribute.MapType != typeof(byte[]) ? + $"{_commonUtils.QuoteSqlName(a.Attribute.Name)} = t1.{_commonUtils.QuoteSqlName(a.Attribute.Name)} + 1" : + $"{_commonUtils.QuoteSqlName(a.Attribute.Name)} = t2.{_commonUtils.QuoteSqlName(a.Attribute.Name)}"; + }))).Append(" \r\n"); cols = _table.Columns.Values.Where(a => a.Attribute.CanInsert == true); if (tempPrimaryIsIdentity == false) cols = cols.Where(a => a.Attribute.IsIdentity == false || string.IsNullOrEmpty(a.DbInsertValue) == false); diff --git a/Providers/FreeSql.Provider.SqlServer/Curd/SqlServerInsertOrUpdate.cs b/Providers/FreeSql.Provider.SqlServer/Curd/SqlServerInsertOrUpdate.cs index 562c687a..37fa76da 100644 --- a/Providers/FreeSql.Provider.SqlServer/Curd/SqlServerInsertOrUpdate.cs +++ b/Providers/FreeSql.Provider.SqlServer/Curd/SqlServerInsertOrUpdate.cs @@ -41,14 +41,18 @@ namespace FreeSql.SqlServer.Curd WriteSourceSelectUnionAll(data, sb, dbParams); sb.Append(" ) t2 ON (").Append(string.Join(" AND ", _tempPrimarys.Select(a => $"t1.{_commonUtils.QuoteSqlName(a.Attribute.Name)} = t2.{_commonUtils.QuoteSqlName(a.Attribute.Name)}"))).Append(") \r\n"); - var cols = _table.Columns.Values.Where(a => _tempPrimarys.Contains(a) == false && a.Attribute.CanUpdate == true && a.Attribute.IsIdentity == false && _updateIgnore.ContainsKey(a.Attribute.Name) == false); + var cols = _table.Columns.Values.Where(a => _updateSetDict.ContainsKey(a.Attribute.Name) || + _tempPrimarys.Contains(a) == false && a.Attribute.CanUpdate == true && a.Attribute.IsIdentity == false && _updateIgnore.ContainsKey(a.Attribute.Name) == false); if (_doNothing == false && cols.Any()) sb.Append("WHEN MATCHED THEN \r\n") .Append(" update set ").Append(string.Join(", ", cols.Select(a => - a.Attribute.IsVersion && a.Attribute.MapType != typeof(byte[]) ? - $"{_commonUtils.QuoteSqlName(a.Attribute.Name)} = t1.{_commonUtils.QuoteSqlName(a.Attribute.Name)} + 1" : - $"{_commonUtils.QuoteSqlName(a.Attribute.Name)} = t2.{_commonUtils.QuoteSqlName(a.Attribute.Name)}" - ))).Append(" \r\n"); + { + if (_updateSetDict.TryGetValue(a.Attribute.Name, out var valsql)) + return $"{_commonUtils.QuoteSqlName(a.Attribute.Name)} = {valsql}"; + return a.Attribute.IsVersion && a.Attribute.MapType != typeof(byte[]) ? + $"{_commonUtils.QuoteSqlName(a.Attribute.Name)} = t1.{_commonUtils.QuoteSqlName(a.Attribute.Name)} + 1" : + $"{_commonUtils.QuoteSqlName(a.Attribute.Name)} = t2.{_commonUtils.QuoteSqlName(a.Attribute.Name)}"; + }))).Append(" \r\n"); cols = _table.Columns.Values.Where(a => a.Attribute.CanInsert == true); if (tempPrimaryIsIdentity == false) cols = cols.Where(a => a.Attribute.IsIdentity == false || string.IsNullOrEmpty(a.DbInsertValue) == false); diff --git a/Providers/FreeSql.Provider.Xugu/Curd/XuguInsertOrUpdate.cs b/Providers/FreeSql.Provider.Xugu/Curd/XuguInsertOrUpdate.cs index 0ba04315..8186d645 100644 --- a/Providers/FreeSql.Provider.Xugu/Curd/XuguInsertOrUpdate.cs +++ b/Providers/FreeSql.Provider.Xugu/Curd/XuguInsertOrUpdate.cs @@ -45,14 +45,18 @@ namespace FreeSql.Xugu.Curd WriteSourceSelectUnionAll(data, sb, dbParams); sb.Append(" ) t2 ON (").Append(string.Join(" AND ", _tempPrimarys.Select(a => $"t1.{_commonUtils.QuoteSqlName(a.Attribute.Name)} = t2.{_commonUtils.QuoteSqlName(a.Attribute.Name)}"))).Append(") \r\n"); - var cols = _table.Columns.Values.Where(a => _tempPrimarys.Contains(a) == false && a.Attribute.CanUpdate == true && a.Attribute.IsIdentity == false && _updateIgnore.ContainsKey(a.Attribute.Name) == false); + var cols = _table.Columns.Values.Where(a => _updateSetDict.ContainsKey(a.Attribute.Name) || + _tempPrimarys.Contains(a) == false && a.Attribute.CanUpdate == true && a.Attribute.IsIdentity == false && _updateIgnore.ContainsKey(a.Attribute.Name) == false); if (_doNothing == false && cols.Any()) sb.Append("WHEN MATCHED THEN \r\n") .Append(" update set ").Append(string.Join(", ", cols.Select(a => - a.Attribute.IsVersion && a.Attribute.MapType != typeof(byte[]) ? - $"{_commonUtils.QuoteSqlName(a.Attribute.Name)} = t1.{_commonUtils.QuoteSqlName(a.Attribute.Name)} + 1" : - $"{_commonUtils.QuoteSqlName(a.Attribute.Name)} = t2.{_commonUtils.QuoteSqlName(a.Attribute.Name)}" - ))).Append(" \r\n"); + { + if (_updateSetDict.TryGetValue(a.Attribute.Name, out var valsql)) + return $"{_commonUtils.QuoteSqlName(a.Attribute.Name)} = {valsql}"; + return a.Attribute.IsVersion && a.Attribute.MapType != typeof(byte[]) ? + $"{_commonUtils.QuoteSqlName(a.Attribute.Name)} = t1.{_commonUtils.QuoteSqlName(a.Attribute.Name)} + 1" : + $"{_commonUtils.QuoteSqlName(a.Attribute.Name)} = t2.{_commonUtils.QuoteSqlName(a.Attribute.Name)}"; + }))).Append(" \r\n"); cols = _table.Columns.Values.Where(a => a.Attribute.CanInsert == true); if (tempPrimaryIsIdentity == false) cols = cols.Where(a => a.Attribute.IsIdentity == false || string.IsNullOrEmpty(a.DbInsertValue) == false);