private TableIdentifier Join(Aliaser aliaser, UpdateStatement statement, SchemaMember schema) { if (schema == null || schema.Token.Property.IsSimplex) { return(null); } //获取关联的源 ISource source = schema.Parent == null ? statement.Table : statement.From.Get(schema.Path); //第一步:处理模式成员所在的继承实体的关联 if (schema.Ancestors != null) { foreach (var ancestor in schema.Ancestors) { source = statement.Join(aliaser, source, ancestor, schema.FullPath); } } //第二步:处理模式成员(导航属性)的关联 var join = statement.Join(aliaser, source, schema); var target = (TableIdentifier)join.Target; statement.Tables.Add(target); //返回关联的目标表 return(target); }
private IEnumerable <JoinClause> Join(Aliaser aliaser, DeleteStatement statement, TableIdentifier table, string fullPath = null) { if (table == null || table.Entity == null) { yield break; } var super = table.Entity.GetBaseEntity(); while (super != null) { var clause = JoinClause.Create(table, fullPath, name => statement.From.TryGet(name, out var join) ? (JoinClause)join : null, entity => new TableIdentifier(entity, aliaser.Generate())); if (!statement.From.Contains(clause)) { statement.From.Add(clause); statement.Tables.Add((TableIdentifier)clause.Target); } super = super.GetBaseEntity(); yield return(clause); } }
private void GenerateSortings(Aliaser aliaser, SelectStatement statement, TableIdentifier origin, Sorting[] sortings) { if (sortings == null || sortings.Length == 0) { return; } statement.OrderBy = new OrderByClause(); foreach (var sorting in sortings) { if (string.IsNullOrEmpty(sorting.Name)) { continue; } var source = statement.From(origin, sorting.Name, aliaser, null, out var property); var simplex = property.IsSimplex ? (IDataEntitySimplexProperty)property : throw new DataException($"The specified '{property.Entity.Name}.{property.Name}' is a composite(navigation) property that is not sortable."); if (simplex.IsPrimaryKey || simplex.Sortable) { statement.OrderBy.Add(source.CreateField(property), sorting.Mode); } else { throw new DataException($"The specified '{property.Entity.Name}.{property.Name}' property is not sortable and must be enabled for sorting before it can be sorted."); } } }
private DeleteStatement BuildInherit(Aliaser aliaser, DeleteStatement master, IDataEntity entity) { var statement = new DeleteStatement(entity); var reference = master.Returning.Table.Identifier(); if (entity.Key.Length == 1) { var select = new SelectStatement(reference); select.Select.Members.Add(reference.CreateField(master.Returning.Table.Fields.First().Name)); statement.Where = Expression.In(statement.Table.CreateField(entity.Key[0]), select); } else { var join = new JoinClause(TEMPORARY_ALIAS, reference, JoinType.Inner); foreach (var key in entity.Key) { join.Conditions.Add( Expression.Equal( statement.Table.CreateField(key), reference.CreateField(key))); } statement.From.Add(join); } master.Slaves.Add(statement); return(statement); }
private void GenerateGrouping(Aliaser aliaser, SelectStatement statement, Grouping grouping) { if (grouping == null) { return; } if (grouping.Keys != null && grouping.Keys.Length > 0) { //创建分组子句 statement.GroupBy = new GroupByClause(); foreach (var key in grouping.Keys) { var source = statement.From(key.Name, aliaser, null, out var property); if (property.IsComplex) { throw new DataException($"The grouping key '{property.Name}' can not be a complex property."); } statement.GroupBy.Keys.Add(source.CreateField(property)); statement.Select.Members.Add(source.CreateField(property.GetFieldName(out var alias), key.Alias ?? alias)); } if (grouping.Filter != null) { statement.GroupBy.Having = statement.Where(grouping.Filter, aliaser, false); } } foreach (var aggregate in grouping.Aggregates) { if (string.IsNullOrEmpty(aggregate.Name) || aggregate.Name == "*") { statement.Select.Members.Add( new AggregateExpression(aggregate.Function, aggregate.Distinct, Expression.Constant(0)) { Alias = string.IsNullOrEmpty(aggregate.Alias) ? aggregate.Function.ToString() : aggregate.Alias }); } else { var source = statement.From(aggregate.Name, aliaser, null, out var property); if (property.IsComplex) { throw new DataException($"The field '{property.Name}' of aggregate function can not be a complex property."); } statement.Select.Members.Add( new AggregateExpression(aggregate.Function, aggregate.Distinct, source.CreateField(property)) { Alias = string.IsNullOrEmpty(aggregate.Alias) ? aggregate.Name : aggregate.Alias }); } } }
/// <inheritdoc /> public JoinClause Join(Aliaser aliaser, ISource source, SchemaMember schema) { if (schema.Token.Property.IsSimplex) { return(null); } return(this.Join(aliaser, source, (IDataEntityComplexProperty)schema.Token.Property, schema.FullPath)); }
/// <inheritdoc /> public JoinClause Join(Aliaser aliaser, ISource source, IDataEntity target, string fullPath = null) { var clause = JoinClause.Create(source, target, fullPath, name => this.From.TryGet(name, out var join) ? (JoinClause)join : null, entity => new TableIdentifier(entity, aliaser.Generate())); if (!this.From.Contains(clause)) { this.From.Add(clause); } return(clause); }
private DeleteStatement BuildSlave(Aliaser aliaser, DeleteStatement master, SchemaMember schema) { var complex = (IDataEntityComplexProperty)schema.Token.Property; var statement = new DeleteStatement(complex.Foreign); var reference = master.Returning.Table.Identifier(); if (complex.Links.Length == 1) { var select = new SelectStatement(reference); select.Select.Members.Add(reference.CreateField(complex.Links[0].GetAnchors().Last())); statement.Where = Expression.In(statement.Table.CreateField(complex.Links[0].Foreign), select); } else { var join = new JoinClause(TEMPORARY_ALIAS, reference, JoinType.Inner); foreach (var link in complex.Links) { var anchor = link.GetAnchors().Last(); join.Conditions.Add( Expression.Equal( statement.Table.CreateField(link.Foreign), reference.CreateField(anchor.Name))); } statement.From.Add(join); } var super = statement.Entity.GetBaseEntity(); if (super != null || schema.HasChildren) { this.BuildReturning(aliaser, statement, schema.Children); } else { master.Slaves.Add(statement); } return(statement); }
private void Join(Aliaser aliaser, DeleteStatement statement, TableIdentifier table, SchemaMember schema) { if (table == null || schema == null || schema.Token.Property.IsSimplex) { return; } //不可变复合属性不支持任何写操作,即在删除操作中不能包含不可变复合属性 if (schema.Token.Property.Immutable) { throw new DataException($"The '{schema.FullPath}' is an immutable complex(navigation) property and does not support the delete operation."); } var join = statement.Join(aliaser, table, schema); var target = (TableIdentifier)join.Target; statement.Tables.Add(target); //生成当前导航属性表的继承链关联集 var joins = this.Join(aliaser, statement, target, schema.FullPath); if (schema.HasChildren) { foreach (var child in schema.Children) { if (joins != null) { join = joins.FirstOrDefault(j => ((TableIdentifier)j.Target).Entity == child.Token.Property.Entity); if (join != null) { target = (TableIdentifier)join.Target; } } this.Join(aliaser, statement, target, child); } } }
/// <inheritdoc /> public JoinClause Join(Aliaser aliaser, ISource source, IDataEntityComplexProperty complex, string fullPath = null) { var joins = JoinClause.Create(source, complex, fullPath, name => this.From.TryGet(name, out var join) ? (JoinClause)join : null, entity => new TableIdentifier(entity, aliaser.Generate())); JoinClause last = null; foreach (var join in joins) { if (!this.From.Contains(join)) { this.From.Add(join); } last = join; } //返回最后一个Join子句 return(last); }
private void GenerateSchema(Aliaser aliaser, SelectStatement statement, ISource origin, SchemaMember member) { if (member.Ancestors != null) { foreach (var ancestor in member.Ancestors) { origin = statement.Join(aliaser, origin, ancestor, member.Path); } } if (member.Token.Property.IsComplex) { var complex = (IDataEntityComplexProperty)member.Token.Property; //一对多的导航属性对应一个新语句(新语句别名即为该导航属性的全称) if (complex.Multiplicity == DataAssociationMultiplicity.Many) { var slave = new SelectStatement(complex.Foreign, member.FullPath) { Paging = member.Paging }; var table = slave.Table; if (complex.ForeignProperty != null) { if (complex.ForeignProperty.IsSimplex) { slave.Select.Members.Add(slave.Table.CreateField(complex.ForeignProperty)); } else { table = (TableIdentifier)slave.Join(aliaser, slave.Table, (IDataEntityComplexProperty)complex.ForeignProperty).Target; } } statement.Slaves.Add(slave); //为一对多的导航属性增加必须的链接字段及对应的条件参数 foreach (var link in complex.Links) { foreach (var anchor in link.GetAnchors()) { if (anchor.IsComplex) { origin = statement.Join(aliaser, origin, (IDataEntityComplexProperty)anchor); } else { var principalField = origin.CreateField(anchor); principalField.Alias = "$" + member.FullPath + ":" + anchor.Name; statement.Select.Members.Add(principalField); var foreignField = slave.Table.CreateField(link.ForeignKey); foreignField.Alias = null; if (slave.Where == null) { slave.Where = Expression.Equal(foreignField, slave.Parameters.Add(anchor.Name, link.ForeignKey.Type)); } else { slave.Where = Expression.AndAlso(slave.Where, Expression.Equal(foreignField, slave.Parameters.Add(anchor.Name, link.ForeignKey.Type))); } } } } //为导航属性增加约束过滤条件 if (complex.HasConstraints()) { foreach (var constraint in complex.Constraints) { slave.Where = Expression.AndAlso(slave.Where, Expression.Equal( table.CreateField(constraint.Name), complex.GetConstraintValue(constraint))); } } if (member.Sortings != null) { this.GenerateSortings(aliaser, slave, table, member.Sortings); } if (member.HasChildren) { foreach (var child in member.Children) { this.GenerateSchema(aliaser, slave, table, child); } } return; } //对于一对一的导航属性,创建其关联子句即可 origin = statement.Join(aliaser, origin, complex, member.FullPath); //确保导航属性的外链表的主键都在 if (member.HasChildren) { foreach (var key in complex.Foreign.Key) { if (!member.Children.Contains(key.Name)) { member.Append(new SchemaMember(key)); } } } } else { var field = origin.CreateField(member.Token.Property); //只有数据模式元素是导航子元素以及与当前语句的别名不同(相同则表示为同级),才需要指定字段引用的别名 if (member.Parent != null && !string.Equals(member.Path, statement.Alias, StringComparison.OrdinalIgnoreCase)) { if (string.IsNullOrEmpty(statement.Alias)) { field.Alias = member.FullPath; } else { field.Alias = Zongsoft.Common.StringExtension.TrimStart(member.FullPath, statement.Alias + ".", StringComparison.OrdinalIgnoreCase); } } statement.Select.Members.Add(field); } if (member.HasChildren) { foreach (var child in member.Children) { this.GenerateSchema(aliaser, statement, origin, child); } } }
private void BuildReturning(Aliaser aliaser, DeleteStatement statement, IEnumerable <SchemaMember> schemas) { statement.Returning = new ReturningClause(TableDefinition.Temporary()); foreach (var key in statement.Entity.Key) { statement.Returning.Table.Field(key); statement.Returning.Append(statement.Table.CreateField(key), ReturningClause.ReturningMode.Deleted); } var super = statement.Entity.GetBaseEntity(); while (super != null) { this.BuildInherit(aliaser, statement, super); super = super.GetBaseEntity(); } foreach (var schema in schemas) { if (schema.Token.Property.IsSimplex) { continue; } var complex = (IDataEntityComplexProperty)schema.Token.Property; ISource src = complex.Entity == statement.Entity ? statement.Table : statement.Join(aliaser, statement.Table, complex.Entity); foreach (var link in complex.Links) { var anchors = link.GetAnchors(); if (anchors.Length > 1) { continue; } ISource source = statement.Table; foreach (var anchor in link.GetAnchors()) { if (anchor.IsComplex) { source = statement.Join(aliaser, source, (IDataEntityComplexProperty)anchor); } else { //某些导航属性可能与主键相同,表定义的字段定义方法(TableDefinition.Field(...))可避免同名字段的重复定义 if (statement.Returning.Table.Field((IDataEntitySimplexProperty)anchor) != null) { statement.Returning.Append(src.CreateField(anchor.Name), ReturningClause.ReturningMode.Deleted); } } } } this.BuildSlave(aliaser, statement, schema); } }