コード例 #1
0
        public bool TryMatch(Expression expression, MainQueryParts queryParts, Action <Expression> visitExpression)
        {
            var sq = expression as SubQueryExpression;

            return(sq != null &&
                   sq.QueryModel.ResultOperators.Count == 1 &&
                   sq.QueryModel.ResultOperators[0] is SumResultOperator &&
                   CheckShortCircuitSum(sq, queryParts, visitExpression));
        }
コード例 #2
0
        public static void ProcessExpression(Expression linqExpression, MainQueryParts query, QueryModel queryModel)
        {
            var visitor =
                new SelectGeneratorExpressionTreeVisitor(
                    query,
                    queryModel.ResultOperators.Any(it => it is AllResultOperator));

            visitor.VisitExpression(linqExpression);
        }
コード例 #3
0
        public bool TryMatch(Expression expression, MainQueryParts queryParts, Action <Expression> visitExpression, QueryContext context)
        {
            var sq = expression as SubQueryExpression;

            return(sq != null &&
                   sq.QueryModel.ResultOperators.Count == 1 &&
                   (sq.QueryModel.ResultOperators[0] is CountResultOperator || sq.QueryModel.ResultOperators[0] is LongCountResultOperator) &&
                   CheckShortCircuitCount(sq, queryParts, visitExpression));
        }
コード例 #4
0
        public SqlCommandData(MainQueryParts query)
        {
            this.Query = query;
            Statement  = query.BuildSqlString();
            var mainIndex = query.Selects.FindIndex(it => it.QuerySource == query.MainFrom);

            if (mainIndex > 0)
            {
                var main = query.Selects[mainIndex];
                query.Selects.RemoveAt(mainIndex);
                query.Selects.Insert(0, main);
            }
        }
コード例 #5
0
        private static Func <string, T> ProjectExpression <T>(SubQueryExpression sqe, QueryParts parts)
        {
            var mqp =
                new MainQueryParts(
                    parts.Locator,
                    parts.ConverterFactory,
                    parts.Simplifications,
                    parts.ExpressionMatchers,
                    parts.MemberMatchers,
                    parts.ProjectionMatchers);
            var subquery = SubqueryGeneratorQueryModelVisitor.ParseSubquery(sqe.QueryModel, mqp, parts.ContextName, parts.Context.Select());

            var newExpression = sqe.QueryModel.SelectClause.Selector as NewExpression;

            if (newExpression != null)
            {
                return(ProjectNew <T>(newExpression, parts, subquery));
            }
            return(ProjectMapping <T>(sqe, parts, subquery));
        }
コード例 #6
0
        private static bool CheckShortCircuitCount(SubQueryExpression expression, MainQueryParts queryParts, Action <Expression> visitExpression)
        {
            var subquery = SubqueryGeneratorQueryModelVisitor.ParseSubquery(expression.QueryModel, queryParts, true);

            if (subquery.ShouldQueryInMemory)
            {
                throw new NotImplementedException("Unsupported subquery. Please provide more info about query.");
                //return false;
            }

            var cnt = queryParts.CurrentSelectIndex;

            var mq = subquery.MainFrom.FromExpression as QuerySourceReferenceExpression;

            if (mq != null && subquery.Joins.Count == 0 && subquery.AdditionalJoins.Count == 0 && subquery.Conditions.Count == 0)
            {
                if (mq.ReferencedQuerySource.ItemType.IsGrouping())
                {
                    queryParts.AddSelectPart(
                        expression.QueryModel.MainFromClause,
                        "ARRAY_UPPER(\"{0}\".\"Values\", 1) AS \"_count_helper_{1}\"".With(mq.ReferencedQuerySource.ItemName, cnt),
                        "_count_helper_" + cnt,
                        expression.QueryModel.ResultTypeOverride,
                        (_, dr) => dr.IsDBNull(cnt) ? 0 : Convert.ChangeType(dr.GetValue(cnt), expression.QueryModel.ResultTypeOverride));
                    return(true);
                }
            }

            var sql = subquery.BuildSqlString(false);

            queryParts.AddSelectPart(
                expression.QueryModel.MainFromClause,
                @"(SELECT COUNT(""{1}"") FROM ({2}) ""{1}"") AS ""{0}"" ".With(
                    "_subquery_" + cnt,
                    expression.QueryModel.MainFromClause.ItemName,
                    sql),
                "_count_" + cnt,
                expression.QueryModel.ResultTypeOverride,
                (_, dr) => dr.IsDBNull(cnt) ? 0 : Convert.ChangeType(dr.GetValue(cnt), expression.QueryModel.ResultTypeOverride));
            return(true);
        }
コード例 #7
0
        private static bool CheckShortCircuitSum(SubQueryExpression expression, MainQueryParts queryParts, Action <Expression> visitExpression)
        {
            var subquery = SubqueryGeneratorQueryModelVisitor.ParseSubquery(expression.QueryModel, queryParts, true);

            if (subquery.ShouldQueryInMemory)
            {
                throw new NotImplementedException("Unsupported subquery. Please provide more info about query.");
                //return false;
            }

            var sql = subquery.BuildSqlString(false);
            var cnt = queryParts.CurrentSelectIndex;

            var selector = expression.QueryModel.SelectClause.Selector as MemberExpression;

            if (selector == null)
            {
                return(false);
            }

            var type = expression.QueryModel.ResultTypeOverride;

            if (type.IsNullable())
            {
                type = type.GetGenericArguments()[0];
            }

            queryParts.AddSelectPart(
                expression.QueryModel.MainFromClause,
                @"(SELECT SUM((""{1}"").""{3}"") FROM ({2}) ""{1}"") AS ""{0}""".With(
                    "_subquery_" + cnt,
                    expression.QueryModel.MainFromClause.ItemName,
                    sql,
                    selector.Member.Name),
                "_sum_" + cnt,
                expression.QueryModel.ResultTypeOverride,
                (_, __, dr) => dr.IsDBNull(cnt) ? 0 : Convert.ChangeType(dr.GetValue(cnt), type));
            return(true);
        }
コード例 #8
0
        public SqlGeneratorQueryModelVisitor(MainQueryParts queryParts)
        {
            Contract.Requires(queryParts != null);

            this.QueryParts = queryParts;
        }
コード例 #9
0
        public DataTable Analyze(
            IEnumerable <string> dimensions,
            IEnumerable <string> facts,
            IEnumerable <KeyValuePair <string, bool> > order,
            ISpecification <TSource> filter,
            int?limit,
            int?offset)
        {
            var usedDimensions = new List <string>();
            var usedFacts      = new List <string>();
            var customOrder    = new List <KeyValuePair <string, bool> >();

            if (dimensions != null)
            {
                usedDimensions.AddRange(dimensions);
            }
            if (facts != null)
            {
                usedFacts.AddRange(facts);
            }
            if (order != null)
            {
                foreach (var o in order)
                {
                    if (o.Key != null)
                    {
                        customOrder.Add(new KeyValuePair <string, bool>(o.Key, o.Value));
                    }
                }
            }

            ValidateInput(usedDimensions, usedFacts, customOrder.Select(it => it.Key));

            var sb    = new StringBuilder();
            var alias = filter != null?filter.IsSatisfied.Parameters.First().Name : "it";

            if (offset != null)
            {
                sb.Append("SELECT ");
                sb.Append(string.Join(", ", usedDimensions.UnionAll(usedFacts).Select(it => "\"" + it + "\"")));
                sb.AppendLine(" FROM (");
            }
            if (limit != null || offset != null)
            {
                sb.Append("SELECT /*+ FIRST_ROWS(n) */ ");
                sb.Append(string.Join(", ", usedDimensions.UnionAll(usedFacts).Select(it => "\"" + it + "\"")));
                if (offset != null)
                {
                    sb.Append(", RowNum rn$");
                }
                sb.AppendLine(" FROM (");
            }
            sb.Append("SELECT ");
            foreach (var d in usedDimensions)
            {
                sb.AppendFormat("{0} AS \"{1}\", ", CubeDimensions[d](alias), d);
            }
            foreach (var f in usedFacts)
            {
                sb.AppendFormat("{0} AS \"{1}\", ", CubeFacts[f](alias), f);
            }
            sb.Length -= 2;
            sb.AppendLine();
            sb.AppendFormat("FROM {0} \"{1}\"", Source, alias);
            sb.AppendLine();

            var command = DatabaseQuery.NewCommand();

            if (filter != null)
            {
                var cf = Locator.Resolve <IOracleConverterFactory>();
                var ep = Locator.Resolve <IExtensibilityProvider>();
                var qp =
                    new MainQueryParts(
                        Locator,
                        cf,
                        ep.ResolvePlugins <IQuerySimplification>(),
                        ep.ResolvePlugins <IExpressionMatcher>(),
                        ep.ResolvePlugins <IMemberMatcher>(),
                        new IProjectionMatcher[0]);
                var linq   = new Queryable <TSource>(new QueryExecutor(DatabaseQuery, Locator, cf, ep)).Filter(filter);
                var parser = QueryParser.CreateDefault();
                var model  = parser.GetParsedQuery(linq.Expression);
                if (model.BodyClauses.Count > 0)
                {
                    sb.AppendLine("WHERE");
                    for (int i = 0; i < model.BodyClauses.Count; i++)
                    {
                        var wc = model.BodyClauses[i] as WhereClause;
                        sb.Append("	");
                        if (i > 0)
                        {
                            sb.Append("AND ");
                        }
                        sb.Append(qp.GetSqlExpression(wc.Predicate));
                    }
                }
                foreach (var p in qp.Parameters.Parameters)
                {
                    command.Parameters.Add(p);
                }
            }
            sb.AppendLine();
            if (usedDimensions.Count > 0)
            {
                sb.Append("GROUP BY ");
                sb.AppendLine(string.Join(", ", usedDimensions.Select(it => CubeDimensions[it](alias))));
            }
            if (customOrder.Count > 0)
            {
                sb.Append("ORDER BY ");
                sb.AppendLine(string.Join(", ", customOrder.Select(it => "\"{0}\" {1}".With(it.Key, it.Value ? string.Empty : "DESC"))));
            }
            if (limit != null || offset != null)
            {
                sb.AppendLine(") sq$");
                if (limit != null)
                {
                    sb.Append("WHERE RowNum <= ");
                    sb.Append(limit.Value + (offset != null ? offset.Value : 0));
                }
            }
            if (offset != null)
            {
                sb.AppendLine(") sq$");
                sb.Append("WHERE sq$.rn$ > ");
                sb.Append(offset.Value);
            }
            command.CommandText = sb.ToString();
            return(DatabaseQuery.Fill(command));
        }
コード例 #10
0
 private SelectGeneratorExpressionTreeVisitor(MainQueryParts query, bool simple)
 {
     this.Query    = query;
     this.IsSimple = simple;
 }
コード例 #11
0
        internal string PrepareSql(
            List <string> usedDimensions,
            List <string> usedFacts,
            IEnumerable <KeyValuePair <string, bool> > order,
            ISpecification <TSource> filter,
            int?limit,
            int?offset)
        {
            var customOrder = new List <KeyValuePair <string, bool> >();

            if (order != null)
            {
                foreach (var o in order)
                {
                    if (o.Key != null)
                    {
                        customOrder.Add(new KeyValuePair <string, bool>(o.Key, o.Value));
                    }
                }
            }

            ValidateInput(usedDimensions, usedFacts, customOrder.Select(it => it.Key));

            var sb    = new StringBuilder();
            var alias = filter != null?filter.IsSatisfied.Parameters.First().Name : "it";

            sb.Append("SELECT ROW(");
            foreach (var d in usedDimensions)
            {
                sb.Append(CubeDimensions[d](alias));
                sb.Append(',');
            }
            foreach (var f in usedFacts)
            {
                sb.Append(CubeFacts[f](alias));
                sb.Append(',');
            }
            sb.Length--;
            sb.AppendFormat(") FROM {0} \"{1}\" ", Source, alias);
            if (filter != null)
            {
                MainQueryParts.AddFilter(Locator, DatabaseQuery, filter, sb);
            }
            if (usedDimensions.Count > 0)
            {
                sb.Append(" GROUP BY ");
                foreach (var d in usedDimensions)
                {
                    sb.Append(CubeDimensions[d](alias));
                    sb.Append(',');
                }
                sb.Length--;
            }
            if (customOrder.Count > 0)
            {
                sb.Append(" ORDER BY ");
                foreach (var kv in customOrder)
                {
                    if (CubeDimensions.ContainsKey(kv.Key))
                    {
                        sb.Append(CubeDimensions[kv.Key](alias));
                    }
                    else if (CubeFacts.ContainsKey(kv.Key))
                    {
                        sb.Append(CubeFacts[kv.Key](alias));
                    }
                    else
                    {
                        sb.AppendFormat("\"{0}\"", kv.Key);
                    }
                    if (kv.Value == false)
                    {
                        sb.Append(" DESC");
                    }
                    sb.Append(", ");
                }
                sb.Length -= 2;
            }
            if (limit != null)
            {
                sb.Append(" LIMIT ").Append(limit.Value);
            }
            if (offset != null)
            {
                sb.Append(" OFFSET ").Append(offset.Value);
            }
            return(sb.ToString());
        }