Exemplo n.º 1
0
        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);
        }
Exemplo n.º 2
0
        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);
            }
        }
Exemplo n.º 3
0
        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.");
                }
            }
        }
Exemplo n.º 4
0
        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);
        }
Exemplo n.º 5
0
        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
                    });
                }
            }
        }
Exemplo n.º 6
0
        /// <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));
        }
Exemplo n.º 7
0
        /// <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);
        }
Exemplo n.º 8
0
        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);
        }
Exemplo n.º 9
0
        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);
                }
            }
        }
Exemplo n.º 10
0
        /// <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);
        }
Exemplo n.º 11
0
        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);
                }
            }
        }
Exemplo n.º 12
0
        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);
            }
        }