Example #1
0
        protected override void ApplyNodeSpecificSemantics(QueryModel queryModel,
                                                           ClauseGenerationContext clauseGenerationContext)
        {
            var nestClause = new NestClause(
                ResultSelector.Parameters[1].Name,
                ResultSelector.Parameters[1].Type,
                InnerSequence,
                GetResolvedKeySelector(clauseGenerationContext),
                IsLeftOuterNest);

            clauseGenerationContext.AddContextInfo(this, nestClause);
            queryModel.BodyClauses.Add(nestClause);

            var selectClause = queryModel.SelectClause;

            selectClause.Selector = GetResolvedResultSelector(clauseGenerationContext);
        }
Example #2
0
 /// <summary>
 ///     Clones this clause.
 /// </summary>
 /// <param name="cloneContext">The clones of all query source clauses are registered with this <see cref="CloneContext" />.</param>
 /// <returns></returns>
 public virtual NestClause Clone(CloneContext cloneContext)
 {
     var clone = new NestClause(ItemName, ItemType, InnerSequence, KeySelector, IsLeftOuterNest);
     return clone;
 }
Example #3
0
        /// <summary>
        ///     Clones this clause.
        /// </summary>
        /// <param name="cloneContext">The clones of all query source clauses are registered with this <see cref="CloneContext" />.</param>
        /// <returns></returns>
        public virtual NestClause Clone(CloneContext cloneContext)
        {
            var clone = new NestClause(ItemName, ItemType, InnerSequence, KeySelector, IsLeftOuterNest);

            return(clone);
        }
        /// <summary>
        /// Visits a nest against a constant expression, which must be an IBucketQueryable implementation
        /// </summary>
        /// <param name="nestClause">Nest clause being visited</param>
        /// <param name="constantExpression">Constant expression that is the InnerSequence of the NestClause</param>
        /// <param name="itemName">Name to be used when referencing the data being nested</param>
        /// <returns>N1QlFromQueryPart to be added to the QueryPartsAggregator</returns>
        private N1QlFromQueryPart VisitConstantExpressionNestClause(NestClause nestClause, ConstantExpression constantExpression, string itemName)
        {
            string bucketName = null;

            if (constantExpression != null)
            {
                var bucketQueryable = constantExpression.Value as IBucketQueryable;
                if (bucketQueryable != null)
                {
                    bucketName = bucketQueryable.BucketName;
                }
            }

            if (bucketName == null)
            {
                throw new NotSupportedException("N1QL Nests Must Be Against IBucketQueryable");
            }

            return new N1QlFromQueryPart()
            {
                Source = N1QlHelpers.EscapeIdentifier(bucketName),
                ItemName = itemName,
                OnKeys = GetN1QlExpression(nestClause.KeySelector),
                JoinType = nestClause.IsLeftOuterNest ? "LEFT OUTER NEST" : "INNER NEST"
            };
        }
        /// <summary>
        /// Visits a nest against either a constant expression of IBucketQueryable, or a subquery based on an IBucketQueryable
        /// </summary>
        /// <param name="nestClause">Nest clause being visited</param>
        /// <returns>N1QlFromQueryPart to be added to the QueryPartsAggregator</returns>
        private N1QlFromQueryPart ParseNestClause(NestClause nestClause)
        {
            switch (nestClause.InnerSequence.NodeType)
            {
                case ExpressionType.Constant:
                    return VisitConstantExpressionNestClause(nestClause, nestClause.InnerSequence as ConstantExpression,
                        GetExtentName(nestClause));

                case SubQueryExpression.ExpressionType: // SubQueryExpression
                    var subQuery = nestClause.InnerSequence as SubQueryExpression;
                    if ((subQuery == null) || subQuery.QueryModel.ResultOperators.Any() || subQuery.QueryModel.MainFromClause.FromExpression.NodeType != ExpressionType.Constant)
                    {
                        throw new NotSupportedException("Unsupported Nest Inner Sequence");
                    }

                    // Generate a temporary item name to use on the NEST statement, which we can then reference in the LET statement

                    var genItemName = _queryGenerationContext.ExtentNameProvider.GetUnlinkedExtentName();
                    var fromPart = VisitConstantExpressionNestClause(nestClause,
                        subQuery.QueryModel.MainFromClause.FromExpression as ConstantExpression, genItemName);

                    // Put any where clauses in the sub query in an ARRAY filtering clause using a LET statement

                    var whereClauseString = string.Join(" AND ",
                        subQuery.QueryModel.BodyClauses.OfType<WhereClause>()
                            .Select(p => GetN1QlExpression(p.Predicate)));

                    var letPart = new N1QlLetQueryPart()
                    {
                        ItemName = GetExtentName(nestClause),
                        Value =
                            string.Format("ARRAY {0} FOR {0} IN {1} WHEN {2} END",
                                GetExtentName(subQuery.QueryModel.MainFromClause),
                                genItemName,
                                whereClauseString)
                    };

                    _queryPartsAggregator.AddLetPart(letPart);

                    if (!nestClause.IsLeftOuterNest)
                    {
                        // This is an INNER NEST, but the inner sequence filter is being applied after the NEST operation is done
                        // So we need to put an additional filter to drop rows with an empty array result

                        _queryPartsAggregator.AddWherePart("(ARRAY_LENGTH({0}) > 0)", letPart.ItemName);
                    }

                    return fromPart;

                default:
                    throw new NotSupportedException("Unsupported Nest Inner Sequence");
            }
        }
        public void VisitNestClause(NestClause nestClause, QueryModel queryModel, int index)
        {
            EnsureNotArraySubquery();

            _queryPartsAggregator.AddFromPart(ParseNestClause(nestClause));
        }
        protected override void ApplyNodeSpecificSemantics(QueryModel queryModel,
            ClauseGenerationContext clauseGenerationContext)
        {
            var nestClause = new NestClause(
                ResultSelector.Parameters[1].Name,
                ResultSelector.Parameters[1].Type,
                InnerSequence,
                GetResolvedKeySelector(clauseGenerationContext),
                IsLeftOuterNest);

            clauseGenerationContext.AddContextInfo(this, nestClause);
            queryModel.BodyClauses.Add(nestClause);

            var selectClause = queryModel.SelectClause;
            selectClause.Selector = GetResolvedResultSelector(clauseGenerationContext);
        }