コード例 #1
0
        /// <summary>
        ///     Creates a subquery based on this SelectExpression and makes that table the single entry in
        ///     <see cref="Tables" />. Clears all other top-level aspects of this SelectExpression.
        /// </summary>
        /// <returns>
        ///     A SelectExpression.
        /// </returns>
        public virtual SelectExpression PushDownSubquery()
        {
            _subqueryDepth++;

            var subquery = new SelectExpression(_querySqlGeneratorFactory, _queryCompilationContext, SystemAliasPrefix);

            var columnAliasCounter = 0;

            foreach (var expression in _projection)
            {
                var aliasExpression = expression as AliasExpression;

                if (aliasExpression != null)
                {
                    var columnExpression = aliasExpression.TryGetColumnExpression();

                    if (columnExpression != null &&
                        subquery._projection.OfType <AliasExpression>()
                        .Any(ae => (ae.Alias ?? ae.TryGetColumnExpression()?.Name) == (aliasExpression.Alias ?? columnExpression.Name)))
                    {
                        aliasExpression.Alias = "c" + columnAliasCounter++;
                    }
                }
                else
                {
                    aliasExpression = new AliasExpression("c" + columnAliasCounter++, expression);
                }

                subquery._projection.Add(aliasExpression);
            }

            subquery.AddTables(_tables);
            subquery.AddToOrderBy(_orderBy);

            subquery.Predicate = Predicate;

            subquery._limit           = _limit;
            subquery._offset          = _offset;
            subquery._isDistinct      = _isDistinct;
            subquery._subqueryDepth   = _subqueryDepth;
            subquery.ProjectStarAlias = ProjectStarAlias;
            subquery.IsProjectStar    = IsProjectStar || !subquery._projection.Any();

            _limit           = null;
            _offset          = null;
            _isDistinct      = false;
            ProjectStarAlias = null;

            Predicate = null;

            ClearTables();
            ClearProjection();
            ClearOrderBy();

            AddTable(subquery, createUniqueAlias: false);
            ProjectStarAlias = subquery.Alias;

            return(subquery);
        }
コード例 #2
0
 /// <summary>
 ///     Creates a new instance of a ColumnReferenceExpression.
 /// </summary>
 /// <param name="aliasExpression"> The referenced AliasExpression. </param>
 /// <param name="tableExpression"> The target table expression. </param>
 public ColumnReferenceExpression(
     [NotNull] AliasExpression aliasExpression,
     [NotNull] TableExpressionBase tableExpression)
     : this(
         Check.NotNull(aliasExpression, nameof(aliasExpression)).Alias,
         aliasExpression,
         Check.NotNull(tableExpression, nameof(tableExpression)))
 {
 }
コード例 #3
0
ファイル: InExpression.cs プロジェクト: lodejard/AllNetCore
        public InExpression(
            [NotNull] AliasExpression operand,
            [NotNull] SelectExpression subQuery)
        {
            Check.NotNull(operand, nameof(operand));
            Check.NotNull(subQuery, nameof(subQuery));

            Operand  = operand;
            SubQuery = subQuery;
        }
コード例 #4
0
ファイル: InExpression.cs プロジェクト: lodejard/AllNetCore
        public InExpression(
            [NotNull] AliasExpression operand,
            [NotNull] IReadOnlyList <Expression> values)
        {
            Check.NotNull(operand, nameof(operand));
            Check.NotNull(values, nameof(values));

            Operand = operand;
            Values  = values;
        }
コード例 #5
0
        // TODO: Make polymorphic
        public virtual Expression UpdateColumnExpression(
            [NotNull] Expression expression,
            [NotNull] TableExpressionBase tableExpression)
        {
            Check.NotNull(expression, nameof(expression));
            Check.NotNull(tableExpression, nameof(tableExpression));

            var columnExpression = expression as ColumnExpression;

            if (columnExpression != null)
            {
                return(new ColumnExpression(columnExpression.Name, columnExpression.Property, tableExpression));
            }

            var aliasExpression = expression as AliasExpression;

            if (aliasExpression != null)
            {
                var newAliasExpression
                    = new AliasExpression(
                          aliasExpression.Alias,
                          UpdateColumnExpression(aliasExpression.Expression, tableExpression))
                    {
                    SourceMember = aliasExpression.SourceMember
                    };

                return(newAliasExpression);
            }

            switch (expression.NodeType)
            {
            case ExpressionType.Coalesce:
            {
                var binaryExpression = (BinaryExpression)expression;
                var left             = UpdateColumnExpression(binaryExpression.Left, tableExpression);
                var right            = UpdateColumnExpression(binaryExpression.Right, tableExpression);
                return(binaryExpression.Update(left, binaryExpression.Conversion, right));
            }

            case ExpressionType.Conditional:
            {
                var conditionalExpression = (ConditionalExpression)expression;
                var test    = UpdateColumnExpression(conditionalExpression.Test, tableExpression);
                var ifTrue  = UpdateColumnExpression(conditionalExpression.IfTrue, tableExpression);
                var ifFalse = UpdateColumnExpression(conditionalExpression.IfFalse, tableExpression);
                return(conditionalExpression.Update(test, ifTrue, ifFalse));
            }
            }

            return(expression);
        }
コード例 #6
0
        /// <summary>
        ///     Adds a column to the ORDER BY of this SelectExpression.
        /// </summary>
        /// <param name="column"> The column name. </param>
        /// <param name="property"> The corresponding EF property. </param>
        /// <param name="table"> The target table. </param>
        /// <param name="orderingDirection"> The ordering direction. </param>
        /// <returns>
        ///     An AliasExpression corresponding to the expression added to the ORDER BY.
        /// </returns>
        public virtual AliasExpression AddToOrderBy(
            [NotNull] string column,
            [NotNull] IProperty property,
            [NotNull] TableExpressionBase table,
            OrderingDirection orderingDirection)
        {
            Check.NotEmpty(column, nameof(column));
            Check.NotNull(property, nameof(property));
            Check.NotNull(table, nameof(table));

            var columnExpression = new ColumnExpression(column, property, table);
            var aliasExpression  = new AliasExpression(columnExpression);

            if (_orderBy.FindIndex(o => o.Expression.TryGetColumnExpression()?.Equals(columnExpression) ?? false) == -1)
            {
                _orderBy.Add(new Ordering(aliasExpression, orderingDirection));
            }

            return(aliasExpression);
        }
コード例 #7
0
        /// <summary>
        ///     Adds a ColumnExpression to the projection.
        /// </summary>
        /// <param name="columnExpression"> The column expression. </param>
        /// <returns>
        ///     The corresponding index of the added expression in <see cref="Projection"/>.
        /// </returns>
        public virtual int AddToProjection([NotNull] ColumnExpression columnExpression)
        {
            Check.NotNull(columnExpression, nameof(columnExpression));

            var projectionIndex
                = _projection
                  .FindIndex(e =>
            {
                var ce = e.TryGetColumnExpression();

                return(ce != null &&
                       ce.Property == columnExpression.Property &&
                       ce.Name == columnExpression.Name &&
                       ce.TableAlias == columnExpression.TableAlias);
            });

            if (projectionIndex == -1)
            {
                var aliasExpression = new AliasExpression(columnExpression);

                // Alias != null means SelectExpression in subquery which needs projections to have unique aliases
                if (Alias != null)
                {
                    var currentAlias = columnExpression.Name;
                    var uniqueAlias  = CreateUniqueProjectionAlias(currentAlias);

                    if (!string.Equals(currentAlias, uniqueAlias, StringComparison.OrdinalIgnoreCase))
                    {
                        aliasExpression.Alias = uniqueAlias;
                    }
                }

                projectionIndex = _projection.Count;

                _projection.Add(aliasExpression);

                IsProjectStar = false;
            }

            return(projectionIndex);
        }
コード例 #8
0
        /// <summary>
        ///     Adds multiple expressions to the ORDER BY of this SelectExpression.
        /// </summary>
        /// <param name="orderings"> The orderings expressions. </param>
        public virtual void AddToOrderBy([NotNull] IEnumerable <Ordering> orderings)
        {
            Check.NotNull(orderings, nameof(orderings));

            foreach (var ordering in orderings)
            {
                var aliasExpression  = ordering.Expression as AliasExpression;
                var columnExpression = ordering.Expression as ColumnExpression;

                if (aliasExpression != null)
                {
                    var newAlias = new AliasExpression(aliasExpression.Alias, aliasExpression.Expression);
                    _orderBy.Add(new Ordering(newAlias, ordering.OrderingDirection));
                }
                else if (columnExpression != null)
                {
                    _orderBy.Add(new Ordering(new AliasExpression(columnExpression), ordering.OrderingDirection));
                }
                else
                {
                    _orderBy.Add(ordering);
                }
            }
        }
コード例 #9
0
        /// <summary>
        ///     Adds an <see cref="AliasExpression" /> to the projection.
        /// </summary>
        /// <param name="aliasExpression"> The alias expression. </param>
        /// <returns>
        ///     The corresponding index of the added expression in <see cref="Projection" />.
        /// </returns>
        public virtual int AddToProjection([NotNull] AliasExpression aliasExpression)
        {
            Check.NotNull(aliasExpression, nameof(aliasExpression));

            var alias            = aliasExpression.Alias;
            var expression       = aliasExpression.Expression;
            var columnExpression = expression as ColumnExpression;

            var projectionIndex
                = _projection
                  .FindIndex(e =>
            {
                var ae = e as AliasExpression;
                var ce = e.TryGetColumnExpression();

                return((ce != null &&
                        columnExpression != null &&
                        ce.Name == columnExpression.Name &&
                        ce.TableAlias == columnExpression.TableAlias) ||
                       ae?.Expression == expression);
            });

            if (projectionIndex == -1)
            {
                // Alias != null means SelectExpression in subquery which needs projections to have unique aliases
                if (Alias != null)
                {
                    var currentAlias = alias ?? columnExpression?.Name ?? expression.NodeType.ToString();
                    var uniqueAlias  = CreateUniqueProjectionAlias(currentAlias);

                    if (columnExpression == null ||
                        !string.Equals(currentAlias, uniqueAlias, StringComparison.OrdinalIgnoreCase))
                    {
                        alias = uniqueAlias;
                    }
                }

                projectionIndex = _projection.Count;

                if (alias != null)
                {
                    foreach (var orderByAliasExpression
                             in _orderBy.Select(o => o.Expression).OfType <AliasExpression>())
                    {
                        if (orderByAliasExpression.TryGetColumnExpression() == null)
                        {
                            // TODO: This seems bad
                            if (orderByAliasExpression.Expression.ToString() == expression.ToString())
                            {
                                orderByAliasExpression.Alias       = alias;
                                orderByAliasExpression.IsProjected = true;
                            }
                        }
                    }
                }

                _projection.Add(new AliasExpression(alias, expression));

                IsProjectStar = false;
            }

            return(projectionIndex);
        }
コード例 #10
0
        // TODO: Make polymorphic
        public virtual Expression UpdateColumnExpression(
            [NotNull] Expression expression,
            [NotNull] TableExpressionBase tableExpression)
        {
            Check.NotNull(expression, nameof(expression));
            Check.NotNull(tableExpression, nameof(tableExpression));

            var columnExpression = expression as ColumnExpression;

            if (columnExpression != null)
            {
                return new ColumnExpression(columnExpression.Name, columnExpression.Property, tableExpression);
            }

            var aliasExpression = expression as AliasExpression;

            if (aliasExpression != null)
            {
                var newAliasExpression
                    = new AliasExpression(
                        aliasExpression.Alias,
                        UpdateColumnExpression(aliasExpression.Expression, tableExpression))
                    {
                        SourceMember = aliasExpression.SourceMember
                    };

                return newAliasExpression;
            }

            switch (expression.NodeType)
            {
                case ExpressionType.Coalesce:
                {
                    var binaryExpression = (BinaryExpression)expression;
                    var left = UpdateColumnExpression(binaryExpression.Left, tableExpression);
                    var right = UpdateColumnExpression(binaryExpression.Right, tableExpression);
                    return binaryExpression.Update(left, binaryExpression.Conversion, right);
                }
                case ExpressionType.Conditional:
                {
                    var conditionalExpression = (ConditionalExpression)expression;
                    var test = UpdateColumnExpression(conditionalExpression.Test, tableExpression);
                    var ifTrue = UpdateColumnExpression(conditionalExpression.IfTrue, tableExpression);
                    var ifFalse = UpdateColumnExpression(conditionalExpression.IfFalse, tableExpression);
                    return conditionalExpression.Update(test, ifTrue, ifFalse);
                }
            }

            return expression;
        }
コード例 #11
0
 private bool Equals(AliasExpression other)
 => string.Equals(_alias, other._alias) &&
 Equals(_expression, other._expression);
コード例 #12
0
 /// <summary>
 ///     Adds an <see cref="AliasExpression"/> to the projection.
 /// </summary>
 /// <param name="aliasExpression"> The alias expression. </param>
 /// <returns>
 ///     The corresponding index of the added expression in <see cref="Projection"/>.
 /// </returns>
 public virtual int AddToProjection([NotNull] AliasExpression aliasExpression)
 => AddAliasToProjection(aliasExpression.Alias, aliasExpression.Expression);
コード例 #13
0
        public virtual SelectExpression PushDownSubquery()
        {
            _subqueryDepth++;

            var subquery = new SelectExpression(_querySqlGeneratorFactory, _queryCompilationContext, SystemAliasPrefix);

            var columnAliasCounter = 0;

            foreach (var expression in _projection)
            {
                var aliasExpression = expression as AliasExpression;

                if (aliasExpression != null)
                {
                    var columnExpression = aliasExpression.TryGetColumnExpression();

                    if (columnExpression != null
                        && subquery._projection.OfType<AliasExpression>()
                            .Any(ae => ae.TryGetColumnExpression()?.Name == columnExpression.Name))
                    {
                        aliasExpression.Alias = "c" + columnAliasCounter++;
                    }
                }
                else
                {
                    aliasExpression = new AliasExpression("c" + columnAliasCounter++, expression);
                }

                subquery._projection.Add(aliasExpression);
            }

            subquery.AddTables(_tables);
            subquery.AddToOrderBy(_orderBy);

            subquery.Predicate = Predicate;

            subquery._limit = _limit;
            subquery._offset = _offset;
            subquery._isDistinct = _isDistinct;
            subquery._subqueryDepth = _subqueryDepth;
            subquery.IsProjectStar = IsProjectStar || !subquery._projection.Any();

            _limit = null;
            _offset = null;
            _isDistinct = false;

            Predicate = null;

            ClearTables();
            ClearProjection();
            ClearOrderBy();

            AddTable(subquery, createUniqueAlias: false);

            return subquery;
        }
コード例 #14
0
            private Expression VisitSelectExpression(SelectExpression selectExpression)
            {
                base.Visit(selectExpression);

                if (!RequiresRowNumberPaging(selectExpression))
                {
                    return selectExpression;
                }

                var subQuery = selectExpression.PushDownSubquery();

                foreach (var projection in subQuery.Projection)
                {
                    var alias = projection as AliasExpression;
                    var column = projection as ColumnExpression;

                    if (column != null)
                    {
                        column = new ColumnExpression(column.Name, column.Property, subQuery);
                        selectExpression.AddToProjection(column);
                        continue;
                    }

                    column = alias?.TryGetColumnExpression();

                    if (column != null)
                    {
                        column = new ColumnExpression(alias.Alias ?? column.Name, column.Property, subQuery);
                        alias = new AliasExpression(alias.Alias, column);
                        selectExpression.AddToProjection(alias);
                    }
                    else
                    {
                        column = new ColumnExpression(alias?.Alias, alias.Expression.Type, subQuery);
                        selectExpression.AddToProjection(column);
                    }
                }

                if (subQuery.OrderBy.Count == 0)
                {
                    subQuery.AddToOrderBy(
                        new Ordering(new SqlFunctionExpression("@@RowCount", typeof(int)), OrderingDirection.Asc));
                }

                var columnExpression = new ColumnExpression(RowNumberColumnName, typeof(int), subQuery);
                var rowNumber = new RowNumberExpression(columnExpression, subQuery.OrderBy);

                subQuery.ClearOrderBy();
                subQuery.AddToProjection(rowNumber, false);

                Expression predicate = null;

                var offset = subQuery.Offset ?? Expression.Constant(0);

                if (subQuery.Offset != null)
                {
                    predicate = Expression.GreaterThan(columnExpression, offset);
                }

                if (subQuery.Limit != null)
                {
                    var constantValue = (subQuery.Limit as ConstantExpression)?.Value;
                    var offsetValue = (offset as ConstantExpression)?.Value;

                    var limitExpression
                        = constantValue != null
                          && offsetValue != null
                            ? (Expression)Expression.Constant((int)offsetValue + (int)constantValue)
                            : Expression.Add(offset, subQuery.Limit);

                    var expression = Expression.LessThanOrEqual(columnExpression, limitExpression);

                    if (predicate != null)
                    {
                        expression = Expression.AndAlso(predicate, expression);
                    }

                    predicate = expression;
                }

                selectExpression.Predicate = predicate;

                return selectExpression;
            }
コード例 #15
0
 private bool Equals(AliasExpression other)
     => Equals(_expression, other._expression)
        && string.Equals(_alias, other._alias);
コード例 #16
0
        public virtual int AddToProjection([NotNull] ColumnExpression columnExpression)
        {
            Check.NotNull(columnExpression, nameof(columnExpression));

            var projectionIndex
                = _projection
                    .FindIndex(e =>
                        {
                            var ce = e.TryGetColumnExpression();

                            return ce?.Property == columnExpression.Property
                                   && ce?.Type == columnExpression.Type
                                   && ce.TableAlias == columnExpression.TableAlias;
                        });

            if (projectionIndex == -1)
            {
                var aliasExpression = new AliasExpression(columnExpression);

                if (Alias != null)
                {
                    var currentAlias = columnExpression.Name;
                    var uniqueAlias = CreateUniqueProjectionAlias(currentAlias);

                    if (!string.Equals(currentAlias, uniqueAlias, StringComparison.OrdinalIgnoreCase))
                    {
                        aliasExpression.Alias = uniqueAlias;
                    }
                }

                projectionIndex = _projection.Count;

                _projection.Add(aliasExpression);

                IsProjectStar = false;
            }

            return projectionIndex;
        }
コード例 #17
0
        public virtual AliasExpression AddToOrderBy(
            [NotNull] string column,
            [NotNull] IProperty property,
            [NotNull] TableExpressionBase table,
            OrderingDirection orderingDirection)
        {
            Check.NotEmpty(column, nameof(column));
            Check.NotNull(property, nameof(property));
            Check.NotNull(table, nameof(table));

            var columnExpression = new ColumnExpression(column, property, table);
            var aliasExpression = new AliasExpression(columnExpression);

            if (_orderBy.FindIndex(o => o.Expression.TryGetColumnExpression()?.Equals(columnExpression) ?? false) == -1)
            {
                _orderBy.Add(new Ordering(aliasExpression, orderingDirection));
            }

            return aliasExpression;
        }
コード例 #18
0
        /// <summary>
        ///     Creates a subquery based on this SelectExpression and makes that table the single entry in
        ///     <see cref="Tables" />. Clears all other top-level aspects of this SelectExpression.
        /// </summary>
        /// <returns>
        ///     A SelectExpression.
        /// </returns>
        public virtual SelectExpression PushDownSubquery()
        {
            _subqueryDepth++;

            var subquery = new SelectExpression(Dependencies, _queryCompilationContext, SystemAliasPrefix);

            var columnAliasCounter = 0;

            foreach (var expression in _projection)
            {
                var aliasExpression = expression as AliasExpression;

                if (aliasExpression != null)
                {
                    var columnExpression = aliasExpression.TryGetColumnExpression();

                    if ((columnExpression != null &&
                         subquery._projection.OfType <AliasExpression>()
                         .Any(ae => (ae.Alias ?? ae.TryGetColumnExpression()?.Name) == (aliasExpression.Alias ?? columnExpression.Name))) ||
                        columnExpression == null)
                    {
                        aliasExpression.Alias = "c" + columnAliasCounter++;
                    }
                }
                else
                {
                    aliasExpression = new AliasExpression("c" + columnAliasCounter++, expression);
                }

                subquery._projection.Add(aliasExpression);
            }

            subquery.AddTables(_tables);
            subquery.AddToOrderBy(_orderBy);

            subquery.Predicate = Predicate;

            subquery._limit           = _limit;
            subquery._offset          = _offset;
            subquery._isDistinct      = _isDistinct;
            subquery._subqueryDepth   = _subqueryDepth;
            subquery.ProjectStarTable = ProjectStarTable;
            subquery.IsProjectStar    = IsProjectStar || !subquery._projection.Any();

            _limit           = null;
            _offset          = null;
            _isDistinct      = false;
            ProjectStarTable = null;

            Predicate = null;

            ClearTables();
            ClearProjection();
            ClearOrderBy();

            _tables.Add(subquery);
            ProjectStarTable = subquery;

            foreach (var ordering in subquery.OrderBy)
            {
                var expression = ordering.Expression;

                var aliasExpression = expression as AliasExpression;
                if (aliasExpression != null)
                {
                    if (aliasExpression.Alias != null)
                    {
                        _orderBy.Add(
                            new Ordering(
                                new ColumnExpression(aliasExpression.Alias, aliasExpression.Type, subquery),
                                ordering.OrderingDirection));
                    }
                    else
                    {
                        var newExpression = UpdateColumnExpression(aliasExpression.Expression, subquery);

                        _orderBy.Add(
                            new Ordering(
                                new AliasExpression(newExpression), ordering.OrderingDirection));
                    }
                }
                else
                {
                    if (!subquery.IsProjectStar)
                    {
                        subquery.AddToProjection(expression);
                    }

                    var newExpression = UpdateColumnExpression(expression, subquery);

                    _orderBy.Add(
                        new Ordering(
                            new AliasExpression(newExpression), ordering.OrderingDirection));
                }
            }

            if (subquery.Limit == null &&
                subquery.Offset == null)
            {
                subquery.ClearOrderBy();
            }

            return(subquery);
        }
コード例 #19
0
        public virtual void AddToOrderBy([NotNull] IEnumerable<Ordering> orderings)
        {
            Check.NotNull(orderings, nameof(orderings));

            foreach (var ordering in orderings)
            {
                var aliasExpression = ordering.Expression as AliasExpression;
                var columnExpression = ordering.Expression as ColumnExpression;

                if (aliasExpression != null)
                {
                    var newAlias = new AliasExpression(aliasExpression.Alias, aliasExpression.Expression);
                    _orderBy.Add(new Ordering(newAlias, ordering.OrderingDirection));
                }
                else if (columnExpression != null)
                {
                    _orderBy.Add(new Ordering(new AliasExpression(columnExpression), ordering.OrderingDirection));
                }
                else
                {
                    _orderBy.Add(ordering);
                }
            }
        }