/// <summary> /// 使用临时表形式,生成更新若干数据对象语句, /// 要求数据库拥有<see cref="EDbCapable.TemporaryTable"/> /// 和<see cref="EDbCapable.ModifyJoin"/>两个特性 /// </summary> /// <param name="context">生成上下文。</param> /// <param name="content">更新表达式。</param> /// <returns>语句片段。</returns> protected virtual SqlFragment GenerateForUpdateTempTable(GenerateContext context, DbExpression content) { var data = (GenerateDataForUpdate)context.Data; var name = data.TargetName; var block = new BlockFragment(context); UpdateFragment mainUpdate = null; TemporaryTableFragment temptable = null; var members = data.GetTables().SelectMany(a => a.Members); foreach (var unit in data.GetUnits()) { TemporaryTableFragment current = null; if (temptable == null) { current = new TemporaryTableFragment(context, members); } else { current = new TemporaryTableFragment(context, temptable.Name, members); } GenerateForUpdateRegister(context, content, current); var metadata = unit.Table; var update = new UpdateFragment(context, metadata, name); update.AddSource(update.Target, current); GenerateForUpdateMembers(context, unit, update, current); update.Target.Join(current, metadata.Keys.Concat(metadata.Concurrencys)); block.Add(update); if (unit == data.MainUnit) { mainUpdate = update; } if (temptable == null) { temptable = current; } else { current.Members.ForEach(m => temptable.GetMember(m.Property)); } } block.Insert(0, GenerateCreateTemplateTable(context, temptable, data.CommitObject, data.Items)); if (data.ReturnMembers.Any()) { var target = data.SubUnits == null ? mainUpdate.Target : new InheritFragment(context, data.Table); var select = new SelectFragment(context, target); select.Members.AddRange(data.ReturnMembers.Select(a => target.GetMember(a.Metadata))); var datatable = temptable.Clone(); select.AddSource(datatable); target.Join(datatable, data.Table.Keys); block.Add(select); data.GenerateOutput(); } data.SetConcurrencyExpectCount(data.TableCount + 1); return(block); }
/// <summary> /// 生成更新单个数据对象语句。 /// </summary> /// <param name="context">生成上下文</param> /// <param name="content">更新表达式。</param> /// <returns>语句片段。</returns> protected virtual SqlFragment GenerateForUpdateSingle(GenerateContext context, DbExpression content) { var data = (GenerateDataForUpdate)context.Data; var block = new BlockFragment(context); UpdateFragment mainUpdate = null; var name = data.TargetName; GenerateForUpdateRegister(context, content, data.CommitObject); foreach (var unit in data.GetUnits()) { var metadata = unit.Table; var update = new UpdateFragment(context, metadata, name); data.CommitObject.Parent = update; GenerateForUpdateMembers(context, unit, update, data.CommitObject); update.Where = update.Target.JoinCondition(data.CommitObject, metadata.Keys.Union(metadata.Concurrencys)); block.Add(update); if (unit == data.MainUnit) { mainUpdate = update; } } if (data.ReturnMembers.Any()) { var target = data.SubUnits == null ? mainUpdate.Target : new InheritFragment(context, data.Table); var select = new SelectFragment(context, target); select.Members.AddRange(data.ReturnMembers.Select(a => target.GetMember(a.Metadata))); select.Where = target.JoinCondition(data.CommitObject, data.Table.Keys); block.Add(select); data.GenerateOutput(); } data.SetConcurrencyExpectCount(data.TableCount); return(block); }
private void GenerateForInsertReturnStatement(GenerateContext context, BlockFragment block, ISourceFragment target, TemporaryTableFragment temptable) { var data = (GenerateDataForInsert)context.Data; if (data.ReturnMembers.Any()) { if (data.SubUnits != null) { target = new InheritFragment(context, data.Table); } var select = new SelectFragment(context, target); select.Members.AddRange(data.ReturnMembers.Select(a => target.GetMember(a.Metadata))); if (temptable == null) { select.Where = target.JoinCondition(data.CommitObject, data.Table.Keys); } else { var datatable = temptable.Clone(); select.AddSource(datatable); target.Join(datatable, data.Table.Keys); } block.Add(select); } }
/// <summary> /// 使用临时表形式,生成删除若干数据对象(多个主键)语句, /// 要求数据库拥有<see cref="EDbCapable.TemporaryTable"/> /// 和<see cref="EDbCapable.ModifyJoin"/>两个特性。 /// </summary> /// <param name="context">生成上下文。</param> /// <returns>语句片段。</returns> protected virtual SqlFragment GenerateForInsertTempTable(GenerateContext context) { var data = (GenerateDataForInsert)context.Data; var members = data.GetTables().SelectMany(a => a.Members); var createtable = new CreateTempTableFragment(context, members); var temptable = createtable.Table; var insert = new InsertValueFragment(context, temptable, data.CommitObject, data.Items); var mainunit = (CommitKeyUnit)data.MainUnit; mainunit.Keys.ForEach(member => GenerateForInsertMembers(insert, member)); data.CommitObject.Parent = insert; foreach (var unit in data.GetUnits()) { unit.Members.ForEach(member => GenerateForInsertMembers(insert, member)); } var block = new BlockFragment(context, createtable, insert); InsertFragment mainInsert = null; foreach (var unit in data.GetUnits().OfType <CommitKeyUnit>()) { mainInsert = context.Insert(temptable, unit); block.Add(mainInsert); } GenerateForInsertReturnStatement(context, block, mainInsert.Target, temptable); return(block); }
/// <summary> /// 生成删除单个数据对象语句 /// </summary> /// <param name="context">生成上下文</param> /// <returns>语句片段。</returns> protected virtual SqlFragment GenerateForDeleteSingle(GenerateContext context) { var data = (GenerateDataForDelete)context.Data; var block = new BlockFragment(context); var name = data.TargetName; foreach (var table in data.GetTables()) { var delete = new DeleteFragment(context, table, name); delete.Where = delete.Target.JoinCondition(data.CommitObject, table.Keys.Union(table.Concurrencys)); block.Add(delete); } data.SetConcurrencyExpectCount(data.TableCount); return(block); }
/// <summary> /// 表达式生成删除语句。 /// </summary> /// <param name="context">生成上下文。</param> /// <param name="content">生成表达式。</param> /// <returns>语句片段。</returns> protected virtual SqlFragment GenerateForDeleteStatement(GenerateContext context, DbExpression content) { var data = (StatementContent)context.Data; var item = data.ItemEpxression; var source = CreateSource(context, content) as QueryBaseFragment; var table = data.Table; if (table.InheritSets.Length == 0) { var target = (TableFragment)GetSource(context, item); target.Name = context.ConvertName(data.TargetName); var delete = new DeleteFragment(context, target) { Where = source.Where, Take = source.Take }; delete.AddSource(source.Sources.Where(a => a != target)); return(delete); } else { var createtable = new CreateTempTableFragment(context, table.Keys); var insert = new InsertFragment(context, createtable.Table, source); insert.Members.AddRange(createtable.Table.Members); foreach (var key in table.Keys) { RetrievalMember(context, source, new DbMemberExpression(key.Member, item), null, false); } var block = new BlockFragment(context, createtable, insert); foreach (var subtable in table.InheritSets.Concat(new TableMetadata[] { table }).Reverse()) { var current = new TableFragment(context, subtable); var delete = new DeleteFragment(context, current); var temptable = new TemporaryTableFragment(context, table.Keys, createtable.Table.Name); current.Join(temptable, table.Keys); delete.AddSource(temptable); block.Add(delete); } return(block); } }
/// <summary> /// 生成插入若干数据对象语句。 /// </summary> /// <param name="context">生成上下文。</param> /// <returns>语句片段。</returns> protected virtual SqlFragment GenerateForInsertSimple(GenerateContext context) { var data = (GenerateDataForInsert)context.Data; var name = data.TargetName; var block = new BlockFragment(context); var mainunit = (CommitKeyUnit)data.MainUnit; InsertValueFragment mainInsert = null; foreach (var unit in data.GetUnits().OfType <CommitKeyUnit>()) { var target = new TableFragment(context, unit.Table, name); var insert = new InsertValueFragment(context, target, data.CommitObject, data.Items); data.CommitObject.Parent = insert; unit.Keys.Concat(unit.Members).ForEach(member => GenerateForInsertMembers(insert, member)); block.Add(insert); mainInsert = insert; } GenerateForInsertReturnStatement(context, block, mainInsert.Target, null); return(block); }
/// <summary> /// 生成删除若干数据对象(单个主键)语句。 /// </summary> /// <param name="context">生成上下文。</param> /// <returns>语句片段。</returns> protected virtual SqlFragment GenerateForDeleteKey(GenerateContext context) { var data = (GenerateDataForDelete)context.Data; var block = new BlockFragment(context); var key = data.Table.Keys[0]; var member = (CommitMemberFragment)data.CommitObject.GetMember(key); var values = new ValueListFragment(context, member, data.Items); var name = data.TargetName; foreach (var table in data.GetTables()) { var delete = new DeleteFragment(context, table, name); var keyMember = delete.Target.GetMember(key); delete.Where = new ScalarFragment(context, values, keyMember) { Function = SupportMembers.Enumerable.Contains }; block.Add(delete); } return(block); }
/// <summary> /// 生成用于插入的语句片段。 /// </summary> /// <param name="context">生成上下文。</param> /// <param name="content">插入表达式。</param> /// <returns>生成结果。</returns> protected virtual SqlFragment GenerateForInsertStatement(GenerateContext context, DbExpression content) { var data = (StatementContent)context.Data; var newitem = (DbNewExpression)data.ItemEpxression; var source = CreateSource(context, content) as QueryBaseFragment; var metadata = data.Table; if (metadata.InheritSets.Length == 0) { var target = new TableFragment(context, metadata, data.TargetName); var insert = new InsertFragment(context, target, source); GenerateForInsertStatementMembers(context, newitem, source, insert, member => metadata.Members[member]); return(insert); } else { var allsource = metadata.InheritSets.Concat(new TableMetadata[] { metadata }); var allmembers = allsource.SelectMany(a => a.Members).ToDictionary(a => a.Member, a => a); var createtable = new CreateTempTableFragment(context, newitem.Members.Keys.OfType <PropertyInfo>().Select(a => allmembers[a])); var insert = new InsertFragment(context, createtable.Table, source); GenerateForInsertStatementMembers(context, newitem, source, insert, member => allmembers[member]); var block = new BlockFragment(context, createtable, insert); var query = from a in newitem.Members.Keys.OfType <PropertyInfo>().Select(m => allmembers[m]) group a by a.Table into g select new { g.Key, Members = g }; var prefixMembers = query.First().Members.Where(a => a.IsKey); foreach (var g in query) { IEnumerable <ColumnMetadata> currentMembers = g.Members; if (g.Key.InheritSets.Length > 0) { currentMembers = prefixMembers.Concat(g.Members); } var current = new TemporaryTableFragment(context, currentMembers, createtable.Table.Name); block.Add(context.Insert(current, g.Key, currentMembers)); } return(block); } }
/// <summary> /// 使用临时表形式,生成删除若干数据对象(多个主键)语句, /// 要求数据库拥有<see cref="EDbCapable.TemporaryTable"/> /// 和<see cref="EDbCapable.ModifyJoin"/>两个特性。 /// </summary> /// <param name="context">生成上下文。</param> /// <returns>语句片段。</returns> protected virtual SqlFragment GenerateForDeleteKeysTempTable(GenerateContext context) { var data = (GenerateDataForDelete)context.Data; var block = new BlockFragment(context) { GenerateCreateTemplateTable(context, data.CommitObject, data.Items, data.Table.Keys.Concat(data.ConcurrencyMembers)) }; var temptable = ((CreateTempTableFragment)block.First()).Table; var name = data.TargetName; foreach (var metadata in data.GetTables()) { var delete = new DeleteFragment(context, metadata, name); var current = delete.Target; var currenttemptable = new TemporaryTableFragment(context, temptable.Name, metadata.Keys.Union(metadata.Concurrencys)); delete.AddSource(currenttemptable); current.Join(currenttemptable, metadata.Keys.Union(metadata.Concurrencys)); block.Add(delete); } data.SetConcurrencyExpectCount(data.TableCount + 1); return(block); }
/// <summary> /// 表达式生成更新语句。 /// </summary> /// <param name="context">生成上下文。</param> /// <param name="content">生成表达式。</param> /// <returns>语句片段。</returns> protected virtual SqlFragment GenerateForUpdateStatement(GenerateContext context, DbExpression content) { SourceFragment GetRootSource(ISourceFragment query) { if (query is SelectFragment select) { return(GetRootSource(select.Sources.FirstOrDefault())); } else if (query is TableFragment || query is InheritFragment) { return((SourceFragment)query); } return(null); } var data = (StatementContent)context.Data; var newitem = (DbNewExpression)data.ItemEpxression; var source = CreateSource(context, content) as QueryBaseFragment; var metadata = data.Table; if (metadata.InheritSets.Length == 0) { TableFragment target = GetRootSource(source) as TableFragment; if (target == null) { target = new TableFragment(context, metadata, data.TargetName); } var update = new UpdateFragment(context, target) { Where = source.Where, Take = source.Take }; update.AddSource(source.Sources); foreach (var item in newitem.Members) { update.SetValue(metadata.Members[(PropertyInfo)item.Key], update.CreateExpression(item.Value)); } return(update); } else { var allmembers = metadata.InheritSets.SelectMany(a => a.Members) .Concat(metadata.Members).ToDictionary(a => a.Member, a => a); InheritFragment inherit = GetRootSource(source) as InheritFragment; if (inherit == null) { inherit = new InheritFragment(context, metadata); } var updates = inherit.Tables.ToDictionary(a => a.Metadata, a => { var target = inherit.Tables.Single(b => b.Metadata == a.Metadata); var update = new UpdateFragment(context, target) { Where = source.Where, Take = source.Take }; update.AddSource(source.Sources); return(update); }); foreach (var item in newitem.Members) { var column = allmembers[(PropertyInfo)item.Key]; var update = updates[column.Table]; foreach (var s in source.Sources) { s.Parent = update; } update.SetValue(column, update.CreateExpression(item.Value)); } var block = new BlockFragment(context); block.Add(updates.Values.Where(a => a.Values.Any()).OfType <ISqlFragment>()); return(block); } }
/// <summary> /// 生成插入单个数据对象语句,对象的主键是标识列。 /// </summary> /// <param name="context">生成上下文。</param> /// <returns>语句片段。</returns> protected virtual SqlFragment GenerateForInsertIdentitySingle(GenerateContext context) { var getidentity = context.Translate(Expression.Call(null, SupportMembers.DbFunctions.GetIdentity)); var data = (GenerateDataForInsert)context.Data; var identityunit = (CommitIdentityUnit)data.MainUnit; var keyVars = new Dictionary <ColumnMetadata, VariableFragment>(); var identityCreate = new CreateVariableFragment(context, identityunit.Identity.Metadata.Member.PropertyType); keyVars.Add(identityunit.Identity.Metadata, identityCreate.Name); var block = new BlockFragment(context); if (!context.Feature.HasCapable(EDbCapable.ImplicitDeclareVariable)) { block.Add(identityCreate); } var name = data.TargetName; var maintarget = new TableFragment(context, identityunit.Table, name); { var insert = new InsertValueFragment(context, maintarget, data.CommitObject, data.Items); data.CommitObject.Parent = insert; identityunit.Members.ForEach(member => { if (member.Metadata.IsKey && member.ValueType == ECommitValueType.Expression) { var expMember = (CommitExpressionMember)member; var exp = insert.CreateExpression(expMember.Expression); var expVar = new CreateVariableFragment(context, member.Metadata.Member.PropertyType); block.Add(expVar); block.Add(context.Assign(expVar.Name, exp)); keyVars.Add(member.Metadata, expVar.Name); } else { GenerateForInsertMembers(insert, member); } }); block.Add(insert); block.Add(context.Assign(identityCreate.Name, insert.CreateExpression(getidentity))); } if (data.SubUnits != null) { foreach (var unit in data.SubUnits) { var target = new TableFragment(context, unit.Table); var insert = new InsertValueFragment(context, target, data.CommitObject, data.Items); data.CommitObject.Parent = insert; unit.Keys.ForEach(member => { if (keyVars.TryGetValue(member.Metadata, out VariableFragment value)) { insert.SetValue(member.Metadata, value); } else { GenerateForInsertMembers(insert, member); } }); unit.Members.ForEach(member => GenerateForInsertMembers(insert, member)); block.Add(insert); } } if (data.ReturnMembers.Any()) { ISourceFragment target = maintarget; if (data.SubUnits != null) { target = new InheritFragment(context, data.Table); } var select = new SelectFragment(context, target); select.Members.AddRange(data.ReturnMembers.Select(a => target.GetMember(a.Metadata))); select.Where = data.Table.Keys.Select(key => context.Equal(target.GetMember(key), keyVars.ContainsKey(key) ? (IExpressionFragment)keyVars[key] : data.CommitObject.GetMember(key))).Merge(); block.Add(select); } return(block); }