Ejemplo n.º 1
0
        protected override Expression VisitSubQueryExpression(SubQueryExpression expression)
        {
            if (ProcessedExpressions.Contains(expression))
            {
                return(expression);
            }

            if (DataSources.Count == 0)
            {
                DataSources.Add(Query.MainFrom.FromExpression);
                DataSources.AddRange(Query.Joins.Select(it => it.InnerSequence));
                DataSources.AddRange(Query.AdditionalJoins.Select(it => it.FromExpression));
            }

            var model = expression.QueryModel;

            if (model.BodyClauses.Count == 0 &&
                DataSources.Contains(model.MainFromClause.FromExpression))
            {
                return(expression);
            }

            ProcessedExpressions.Add(expression);

            foreach (var candidate in Query.ProjectionMatchers)
            {
                if (candidate.TryMatch(expression, Query, exp => VisitExpression(exp)))
                {
                    return(expression);
                }
            }

            var subquery = SubqueryGeneratorQueryModelVisitor.ParseSubquery(expression.QueryModel, Query, true, Query.ContextName, Query.Context.Select());

            var cnt = Query.CurrentSelectIndex;
            //TODO true or false
            var sql = subquery.BuildSqlString(true);

            var selector  = model.SelectClause.Selector;
            var projector = (IExecuteFunc)Activator.CreateInstance(typeof(GenericProjection <>).MakeGenericType(selector.Type), model);
            var ssd       = SelectSubqueryData.Create(Query, subquery);

            if (subquery.ResultOperators.Any(it => it is FirstResultOperator))
            {
                //TODO fix later
                Query.AddSelectPart(
                    expression.QueryModel.MainFromClause,
                    @"(SELECT ""{1}"" FROM ({2}) ""{1}"" WHERE RowNum = 1) AS ""{0}""".With(
                        "_first_or_default_" + cnt,
                        expression.QueryModel.MainFromClause.ItemName,
                        sql),
                    "_first_or_default_" + cnt,
                    expression.QueryModel.ResultTypeOverride,
                    (rom, dr) =>
                {
                    if (dr.IsDBNull(cnt))
                    {
                        return(null);
                    }
                    var tuple  = new[] { dr.GetValue(cnt).ToString() };
                    var result = ssd.ProcessRow(rom, tuple);
                    return(projector.Eval(result));
                });
            }
            else
            {
                //TODO fix later
                Query.AddSelectPart(
                    expression.QueryModel.MainFromClause,
                    @"(SELECT ARRAY_AGG(""{1}"") FROM ({2}) ""{1}"") AS ""{0}""".With(
                        "_subquery_" + cnt,
                        expression.QueryModel.MainFromClause.ItemName,
                        sql),
                    "_subquery_" + cnt,
                    expression.QueryModel.ResultTypeOverride,
                    (rom, dr) =>
                {
                    //TODO fix later
                    return(null);

                    /*
                     * string[] array;
                     * if (dr.IsDBNull(cnt))
                     *      array = new string[0];
                     * else
                     * {
                     *      var value = dr.GetValue(cnt);
                     *      array = value is string[] ? value as string[] : OracleRecordConverter.ParseArray(dr.GetString(cnt));
                     * }
                     * var resultItems = new List<ResultObjectMapping>();
                     * array.Foreach(it => resultItems.Add(ssd.ProcessRow(rom, it)));
                     * return projector.Process(resultItems);*/
                });
            }
            return(expression);
        }
Ejemplo n.º 2
0
        protected override Expression VisitSubQueryExpression(SubQueryExpression expression)
        {
            if (ProcessedExpressions.Contains(expression))
            {
                return(expression);
            }

            if (DataSources.Count == 0)
            {
                DataSources.Add(Query.MainFrom.FromExpression);
                DataSources.AddRange(Query.Joins.Select(it => it.InnerSequence));
                DataSources.AddRange(Query.AdditionalJoins.Select(it => it.FromExpression));
            }

            var model = expression.QueryModel;

            if (model.BodyClauses.Count == 0 &&
                DataSources.Contains(model.MainFromClause.FromExpression))
            {
                return(expression);
            }

            ProcessedExpressions.Add(expression);

            foreach (var candidate in Query.ProjectionMatchers)
            {
                if (candidate.TryMatch(expression, Query, exp => VisitExpression(exp), Query.Context))
                {
                    return(expression);
                }
            }

            var subquery = SubqueryGeneratorQueryModelVisitor.ParseSubquery(expression.QueryModel, Query, true);

            var cnt = Query.CurrentSelectIndex;
            //TODO true or false
            var sql = subquery.BuildSqlString(true);

            var selector  = model.SelectClause.Selector;
            var projector = (IExecuteFunc)Activator.CreateInstance(typeof(GenericProjection <>).MakeGenericType(selector.Type), model);
            var ssd       = SelectSubqueryData.Create(Query, subquery);

            if (subquery.ResultOperators.Any(it => it is FirstResultOperator))
            {
                Query.AddSelectPart(
                    expression.QueryModel.MainFromClause,
                    @"(SELECT ""{1}"" FROM ({2}) ""{1}"" LIMIT 1) AS ""{0}""".With(
                        "_first_or_default_" + cnt,
                        expression.QueryModel.MainFromClause.ItemName,
                        sql),
                    "_first_or_default_" + cnt,
                    expression.QueryModel.ResultTypeOverride,
                    (rom, reader, dr) =>
                {
                    if (dr.IsDBNull(cnt))
                    {
                        return(null);
                    }
                    var tuple  = new[] { dr.GetValue(cnt).ToString() };
                    var result = ssd.ProcessRow(rom, reader, tuple);
                    return(projector.Eval(result));
                });
            }
            else
            {
                Query.AddSelectPart(
                    expression.QueryModel.MainFromClause,
                    @"(SELECT ARRAY_AGG(""{1}"") FROM ({2}) ""{1}"") AS ""{0}""".With(
                        "_subquery_" + cnt,
                        expression.QueryModel.MainFromClause.ItemName,
                        sql),
                    "_subquery_" + cnt,
                    expression.QueryModel.ResultTypeOverride,
                    (rom, reader, dr) =>
                {
                    object[] array;
                    if (dr.IsDBNull(cnt))
                    {
                        array = new string[0];
                    }
                    else
                    {
                        var value = dr.GetValue(cnt);
                        if (value is string[])
                        {
                            array = value as string[];
                        }
                        else
                        {
                            var obj = dr.GetValue(cnt);
                            //TODO fix dead code usage
                            var tr = obj as TextReader;
                            if (tr != null)
                            {
                                array = PostgresRecordConverter.ParseArray(tr.ReadToEnd());
                            }
                            else
                            {
                                array = PostgresRecordConverter.ParseArray(obj as string);
                            }
                        }
                    }
                    var resultItems = new ResultObjectMapping[array.Length];
                    for (int i = 0; i < array.Length; i++)
                    {
                        resultItems[i] = ssd.ProcessRow(rom, reader, array[i]);
                    }
                    return(projector.Process(resultItems));
                });
            }
            return(expression);
        }