/// <inheritdoc/> protected override SqlFragment GenerateForUpdateContent(GenerateContext context, DbExpression content) { var data = (UpdateContent)context.Data; data.SetConcurrencyExpectCount(1); RegisterExpressionForCommit(context, content, data.CommitObject); UpdateFragment update = null; if (data.Items.Count == 1) { update = data.UpdateByKeys(data.Unit, data.TargetName); } else { var values = new ValuesFragment(context, data.CommitObject, data.Items, data.Table); RegisterExpressionForCommit(context, content, values); update = data.UpdateByTemptable(data.Unit, values, data.TargetName); } if (data.ReturnMembers.Any()) { foreach (var member in data.ReturnMembers) { var metadata = member.Metadata; update.ReturnMembers.Add(update.Target.GetMember(metadata)); } data.GenerateOutput(); } return(update); }
/// <summary> /// 生成更新单个关系对象语句。 /// </summary> /// <param name="context">生成上下文。</param> /// <returns>语句片段。</returns> protected virtual SqlFragment GenerateForRelationUpdate(GenerateContext context) { var data = (RelationContent)context.Data; var metadata = data.Items.Navigate; var update = new UpdateFragment(context, data.Table); update.AddSource(update.Target); if (data.IsAddRelation) { var source = data.CommitObject; foreach (var pair in metadata.Pairs) { update.SetValue(pair.ForeignKey, source.GetMember(pair.PrincipalKey)); } } else { var nullfargment = new SimpleFragment(context, "NULL"); foreach (var pair in metadata.Pairs) { update.SetValue(pair.ForeignKey, nullfargment); } } update.Where = update.Target.JoinCondition(data.CommitObject, data.Table.Keys); return(update); }
/// <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); }
internal static UpdateFragment UpdateByTemptable(this ContentBase data, CommitUnitBase unit, SourceFragment current, DbName name = null) { var context = data.GenerateContext; var metadata = unit.Table; var update = new UpdateFragment(context, metadata, name); update.AddSource(update.Target, current); data.SetCommitMembers(update, unit, current); update.Target.Join(current, data.UnionConcurrencyMembers(metadata, metadata.Keys)); return(update); }
internal static UpdateFragment UpdateByKeys(this ContentBase data, CommitUnitBase unit, DbName name = null) { var context = data.GenerateContext; var metadata = unit.Table; var update = new UpdateFragment(context, metadata, name); data.CommitObject.Parent = update; data.SetCommitMembers(update, unit); update.Where = update.Target.JoinCondition(data.CommitObject, data.UnionConcurrencyMembers(metadata, metadata.Keys)); return(update); }
private static void SetCommitMembers(this ContentBase data, UpdateFragment update, CommitUnitBase unit, ISourceFragment source = null) { source = source ?? data.CommitObject; foreach (var member in unit.Members) { switch (member.ValueType) { case ECommitValueType.Constant: update.SetValue(member.Metadata, source.GetMember(member.Metadata)); break; case ECommitValueType.Expression: var exp = (CommitExpressionMember)member; update.SetValue(member.Metadata, update.CreateExpression(exp.Expression)); break; } } }
/// <summary> /// 生成更新若干关系对象(单个主键)语句。 /// </summary> /// <param name="context">生成上下文。</param> /// <returns>语句片段。</returns> protected virtual SqlFragment GenerateForRelationDeleteKey(GenerateContext context) { var data = (RelationContent)context.Data; var metadata = data.Items.Navigate; var update = new UpdateFragment(context, data.Table); update.AddSource(update.Target); metadata.Pairs.ForEach( pair => update.SetValue(pair.ForeignKey, new SimpleFragment(context, "NULL"))); var member = new CommitMemberFragment(context, data.Loader, update, data.Table.Keys[0].Member); var values = new ValueListFragment(context, member, data.Items); var keyMember = update.Target.GetMember(data.Table.Keys[0]); update.Where = new ScalarFragment(context, values, keyMember) { Function = SupportMembers.Enumerable.Contains }; return(update); }
/// <inheritdoc/> protected override SqlFragment GenerateForRelation(GenerateContext context, DbExpression content) { var data = (RelationContent)context.Data; if (data.Items.Count > 1) { var metadata = data.Items.Navigate; if (data.IsAddRelation && !metadata.IsComposite) { var columns = data.Source.Keys.Concat(metadata.Pairs.Select(a => a.ForeignKey)); var values = new ValuesFragment(context, data.CommitObject, data.Items); data.Source.Keys.ForEach(key => values.SetValue(key)); if (data.IsAddRelation) { metadata.Pairs.ForEach( pair => values.SetValue(pair.ForeignKey, data.CommitObject.GetMember(pair.PrincipalKey))); } var update = new UpdateFragment(context, data.Table); update.AddSource(update.Target, values); foreach (var pair in metadata.Pairs) { update.SetValue(pair.ForeignKey, values.GetMember(pair.ForeignKey)); } update.Target.Join(values, data.Table.Keys); return(update); } else if (!data.IsAddRelation && metadata.IsComposite) { var composite = (CompositeNavigateMetadata)data.Items.Navigate; var values = new ValuesFragment(context, data.CommitObject, data.Items); composite.Pairs.ForEach(pair => values.SetValue(pair.ForeignKey, data.CommitObject.GetMember(pair.PrincipalKey))); composite.CompositePairs.ForEach(pair => values.SetValue(pair.ForeignKey, data.CommitObject.GetMember(pair.PrincipalKey))); var target = new TableFragment(context, data.Table); var delete = new DeleteFragment(context, target); delete.AddSource(values); target.Join(values, composite.Pairs.Select(a => a.ForeignKey).Concat(composite.CompositePairs.Select(a => a.ForeignKey))); return(delete); } } return(base.GenerateForRelation(context, content)); }
private SqlFragment GenerateForInsertIdentityMultipleRepeat(GenerateContext context, CommitIdentityUnit mainunit, ColumnMetadata rowindex, TemporaryTableFragment temporaryTable, RowIndexFragment rowindexfragment, GenerateDataForInsert data, out TableFragment whileTarget) { var repeatfragment = new RepeatBlockFragment(context, data.Items); var block = repeatfragment.Block; var whileInsert = context.Insert(temporaryTable, mainunit.Table, mainunit.Members.Where(a => a.ValueType != ECommitValueType.Database).Select(a => a.Metadata)); var whileSelect = (QueryBaseFragment)whileInsert.Query; whileSelect.Where = context.Equal(temporaryTable.GetMember(rowindex), new RowIndexFragment(context)); block.Add(whileInsert); var whileUpdate = new UpdateFragment(context, temporaryTable); var getidentity = whileUpdate.CreateExpression( context.Translate(Expression.Call(null, SupportMembers.DbFunctions.GetIdentity))); whileUpdate.SetValue(mainunit.Identity.Metadata, getidentity); whileUpdate.Where = context.Equal(temporaryTable.GetMember(rowindex), new RowIndexFragment(context)); block.Add(whileUpdate); whileTarget = (TableFragment)whileInsert.Target; return(repeatfragment); }
private WhileFragment GenerateForInsertIdentityMultipleWhile(GenerateContext context, CommitIdentityUnit mainunit, CreateVariableFragment index, ColumnMetadata rowindex, TemporaryTableFragment temporaryTable, RowIndexFragment rowindexfragment, out TableFragment whileTarget) { var whilefragment = new WhileFragment(context, context.LessThan(index.Name, rowindexfragment)); var block = whilefragment.Block; var whileInsert = context.Insert(temporaryTable, mainunit.Table, mainunit.Members.Where(a => a.ValueType != ECommitValueType.Database).Select(a => a.Metadata)); var whileSelect = (QueryBaseFragment)whileInsert.Query; whileSelect.Where = context.Equal(temporaryTable.GetMember(rowindex), index.Name); block.Add(whileInsert); var whileUpdate = new UpdateFragment(context, temporaryTable); var getidentity = whileUpdate.CreateExpression( context.Translate(Expression.Call(null, SupportMembers.DbFunctions.GetIdentity))); whileUpdate.SetValue(mainunit.Identity.Metadata, getidentity); whileUpdate.Where = context.Equal(temporaryTable.GetMember(rowindex), index.Name); block.Add(whileUpdate); block.Add(context.Assign(index.Name, context.Add(index.Name, context.StatementString("1")))); whileTarget = (TableFragment)whileInsert.Target; return(whilefragment); }
/// <summary> /// 使用临时表形式,生成更新关系语句, /// 要求数据库拥有<see cref="EDbCapable.TemporaryTable"/> /// 和<see cref="EDbCapable.ModifyJoin"/>两个特性。 /// </summary> /// <param name="context">生成上下文。</param> /// <returns>语句片段。</returns> protected virtual SqlFragment GenerateForRelationUpdateTempTable(GenerateContext context) { var data = (RelationContent)context.Data; var metadata = data.Items.Navigate; var block = new BlockFragment(context); var createtemptable = new CreateTempTableFragment(context, data.IsAddRelation ? data.Source.Keys.Concat(metadata.Pairs.Select(a => a.ForeignKey)) : data.Source.Keys); var insert = new InsertValueFragment(context, createtemptable.Table, data.CommitObject, data.Items); data.Source.Keys.ForEach(key => insert.SetValue(key)); if (data.IsAddRelation) { metadata.Pairs.ForEach( pair => insert.SetValue(pair.ForeignKey, data.CommitObject.GetMember(pair.PrincipalKey))); } var temptable = createtemptable.Table; var update = new UpdateFragment(context, data.Table); update.AddSource(update.Target, temptable); if (data.IsAddRelation) { foreach (var pair in metadata.Pairs) { update.SetValue(pair.ForeignKey, temptable.GetMember(pair.ForeignKey)); } } else { var nullfargment = new SimpleFragment(context, "NULL"); foreach (var pair in metadata.Pairs) { update.SetValue(pair.ForeignKey, nullfargment); } } update.Target.Join(temptable, data.Table.Keys); return(new BlockFragment(context, createtemptable, insert, update)); }
/// <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); } }
//生成更新表达式。 private void GenerateForUpdateMembers(GenerateContext context, CommitUnitBase unit, UpdateFragment update, ISourceFragment source) { foreach (var member in unit.Members) { switch (member.ValueType) { case ECommitValueType.Constant: update.SetValue(member.Metadata, source.GetMember(member.Metadata)); break; case ECommitValueType.Expression: var exp = (CommitExpressionMember)member; update.SetValue(member.Metadata, update.CreateExpression(exp.Expression)); break; } } }