示例#1
0
        public ICriteria SetProjection(IProjection projection)
        {
            if (projection is ProjectionList)
            {
                throw new NotSupportedException("Projection lists are not (yet) supported in sharded criteria.");
            }

            if (projection is Distinct)
            {
                ApplyActionToShards(c => c.SetProjection(projection));
                this.exitOperationBuilder.Distinct = true;
                return(this);
            }

            if (!projection.IsAggregate)
            {
                ApplyActionToShards(c => c.SetProjection(projection));
                return(this);
            }

            string aggregationName = projection.ToString();

            if (aggregationName.StartsWith("avg", StringComparison.OrdinalIgnoreCase))
            {
                var projectionList = Projections.ProjectionList()
                                     .Add(projection)
                                     .Add(Projections.RowCount());
                ApplyActionToShards(c => c.SetProjection(projectionList));
                this.exitOperationBuilder.Aggregation =
                    c => AggregationUtil.Average(c, GetFieldSelector(0), GetFieldSelector(1));
                return(this);
            }

            if (aggregationName.StartsWith("sum", StringComparison.OrdinalIgnoreCase))
            {
                ApplyActionToShards(c => c.SetProjection(projection));
                this.exitOperationBuilder.Aggregation = c => AggregationUtil.Sum(c, GetFieldSelector(0));
                return(this);
            }

            if (aggregationName.StartsWith("count", StringComparison.OrdinalIgnoreCase))
            {
                ApplyActionToShards(c => c.SetProjection(projection));
                this.exitOperationBuilder.Aggregation = c => AggregationUtil.SumInt64(c, GetFieldSelector(0));
                return(this);
            }

            if (aggregationName.StartsWith("min", StringComparison.OrdinalIgnoreCase))
            {
                ApplyActionToShards(c => c.SetProjection(projection));
                this.exitOperationBuilder.Aggregation = c => AggregationUtil.Min(c, GetFieldSelector(0));
                return(this);
            }

            if (aggregationName.StartsWith("max", StringComparison.OrdinalIgnoreCase))
            {
                ApplyActionToShards(c => c.SetProjection(projection));
                this.exitOperationBuilder.Aggregation = c => AggregationUtil.Max(c, GetFieldSelector(0));
                return(this);
            }

            var message = string.Format(
                CultureInfo.InvariantCulture,
                "Aggregate projection '{0}' is currently not supported across shards.",
                aggregationName);

            Log.Error(message);
            throw new NotSupportedException(message);
        }
        private bool CanCopy(IASTNode node, out Action <IASTNode> copyTransformer)
        {
            copyTransformer = null;

            IASTNode child;

            switch (node.Type)
            {
            case HqlSqlWalker.SKIP:
                child = node.GetFirstChild();

                if (TryGetParameterName(child, out var skipParameterName))
                {
                    this.exitOperationBuilder.FirstResult = (int)namedParameters[skipParameterName].Item1;
                }
                else if (TryGetInt32(child, out var firstResult))
                {
                    this.exitOperationBuilder.FirstResult = firstResult;
                }
                return(false);

            case HqlSqlWalker.TAKE:
                child = node.GetFirstChild();

                if (TryGetParameterName(child, out var takeParameterName))
                {
                    this.exitOperationBuilder.MaxResults = (int)namedParameters[takeParameterName].Item1;
                }
                else if (TryGetInt32(child, out var maxResults))
                {
                    this.exitOperationBuilder.MaxResults = maxResults;
                }
                return(false);

            case HqlSqlWalker.ORDER:
                ExtractOrders(node);
                return(true);

            case HqlSqlWalker.AGGREGATE:
                if ("avg".Equals(node.Text, StringComparison.OrdinalIgnoreCase))
                {
                    goto case HqlSqlWalker.AVG;
                }
                if ("min".Equals(node.Text, StringComparison.OrdinalIgnoreCase))
                {
                    goto case HqlSqlWalker.MIN;
                }
                else if ("max".Equals(node.Text, StringComparison.OrdinalIgnoreCase))
                {
                    goto case HqlSqlWalker.MAX;
                }

                throw new NotSupportedException(string.Format(
                                                    CultureInfo.InvariantCulture,
                                                    "HQL aggregate function '{0}' is currently not supported across shards.",
                                                    node.Text));

            case HqlSqlWalker.AVG:
                ThrowIfAggregationInComplexSelectList(node);

                this.exitOperationBuilder.Aggregation = c => AggregationUtil.Average(c, GetFieldSelector(0), GetFieldSelector(1));
                copyTransformer = TransformUnshardedAverageNode;
                return(true);

            case HqlSqlWalker.COUNT:
                ThrowIfAggregationInComplexSelectList(node);
                this.exitOperationBuilder.Aggregation = c => AggregationUtil.SumInt64(c, o => o);
                return(true);

            case HqlSqlWalker.MIN:
                ThrowIfAggregationInComplexSelectList(node);
                this.exitOperationBuilder.Aggregation = c => AggregationUtil.Min(c, o => o);
                return(true);

            case HqlSqlWalker.MAX:
                ThrowIfAggregationInComplexSelectList(node);
                this.exitOperationBuilder.Aggregation = c => AggregationUtil.Max(c, o => o);
                return(true);

            case HqlSqlWalker.SUM:
                ThrowIfAggregationInComplexSelectList(node);
                this.exitOperationBuilder.Aggregation = c => AggregationUtil.Sum(c, o => o);
                return(true);
            }

            return(true);
        }