示例#1
0
        internal FromClauseBase TryToSimplifyAdditionalFrom(AdditionalFromClause additionalFrom)
        {
            FromClauseBase from = additionalFrom;
            var            sqe  = from.FromExpression as SubQueryExpression;

            if (sqe != null)
            {
                var subquery = SubqueryGeneratorQueryModelVisitor.ParseSubquery(sqe.QueryModel, this, ContextName, Context.Select());
                if (subquery.Joins.Count > 0 ||
                    subquery.ResultOperators.Any(it => it is CastResultOperator == false && it is DefaultIfEmptyResultOperator == false) ||
                    subquery.AdditionalJoins.Count > 0)
                {
                    return(from);
                }
                return(TryToSimplifyMainFrom(sqe.QueryModel.MainFromClause));
            }
            return(from);
        }
        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));
        }
示例#3
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);
        }
示例#4
0
        private void TryToSimplifyMainFrom()
        {
            var from = MainFrom;
            var sqe  = from.FromExpression as SubQueryExpression;

            do
            {
                from = sqe.QueryModel.MainFromClause;
                var subquery = SubqueryGeneratorQueryModelVisitor.ParseSubquery(sqe.QueryModel, this);
                if (subquery.Conditions.Count > 0 ||
                    subquery.Joins.Count > 0 ||
                    subquery.ResultOperators.Any(it => it is CastResultOperator == false && it is DefaultIfEmptyResultOperator == false) ||
                    subquery.AdditionalJoins.Count > 0)
                {
                    return;
                }
                sqe = from.FromExpression as SubQueryExpression;
            } while (sqe != null);
            from.ItemName = MainFrom.ItemName;
            MainFrom      = from;
        }
示例#5
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);
        }
示例#6
0
        //TODO vjerojatno ponekad ne treba ignorirati expression
        public string GetQuerySourceFromExpression(string name, Type type, Expression fromExpression)
        {
            var me = fromExpression as MemberExpression;

            if (me != null)
            {
                var src = BuildMemberPath(me, true);
                if (src != null)
                {
                    return(@"(SELECT sq as ""{1}"" FROM unnest({0}) sq) AS ""{1}""".With(src, name));
                }
            }

            var sqe = fromExpression as SubQueryExpression;

            if (sqe != null)
            {
                if (sqe.QueryModel.CanUseMain())
                {
                    return(GetQuerySourceFromExpression(name, type, sqe.QueryModel.MainFromClause.FromExpression));
                }
                //TODO hack za replaceanje generiranog id-a
                var subquery = SubqueryGeneratorQueryModelVisitor.ParseSubquery(sqe.QueryModel, this);
                var sql      = "({0}) AS \"{1}\"".With(subquery.BuildSqlString(true), name);
                var grouping = sqe.QueryModel.ResultOperators.FirstOrDefault(it => it is GroupResultOperator) as GroupResultOperator;
                if (grouping == null && subquery.Selects.Count == 1)
                {
                    return(sql.Replace("\"" + sqe.QueryModel.MainFromClause.ItemName + "\"", "\"" + name + "\""));
                }
                return(sql);
            }

            var ce = fromExpression as ConstantExpression;

            if (ce != null)
            {
                var queryable = ce.Value as IQueryable;
                if (queryable != null)
                {
                    return(GetQueryableExpression(name, queryable));
                }
                if (ce.Type.IsArray || ce.Value is Array)
                {
                    return(FormatStringArray(ce.Value, name, ce.Type));
                }
                else if (ce.Value is IEnumerable)
                {
                    return(FormatStringEnumerable(ce.Value, name, ce.Type));
                }
                return("(SELECT {0} AS \"{1}\") AS \"{1}\"".With(ce.Value, name));
            }

            var nae = fromExpression as NewArrayExpression;

            if (nae != null)
            {
                if (nae.Expressions.Count == 0)
                {
                    //TODO support for zero
                    throw new NotSupportedException("Expecting NewArray expressions. None found");
                }
                var inner = string.Join(" UNION ALL ", nae.Expressions.Select(it => "SELECT {0} AS \"{1}\"".With(GetSqlExpression(it), name)));
                return("(" + inner + ") AS \"{0}\" ".With(name));
            }

            if (fromExpression is QuerySourceReferenceExpression && fromExpression.Type.IsGrouping())
            {
                var qse = fromExpression as QuerySourceReferenceExpression;
                return
                    ("(SELECT (\"{0}\".\"Values\")[i].* FROM generate_series(1, array_upper(\"{0}\".\"Values\", 1)) i) AS \"{1}\"".With(
                         qse.ReferencedQuerySource.ItemName,
                         name));
            }

            var pe = fromExpression as ParameterExpression;

            if (pe != null)
            {
                return("UNNEST({0}\"{1}\") AS \"{2}\"".With(ContextName, pe.Name, name));
            }

            return(FromSqlSource(name, type));
        }
示例#7
0
        //TODO vjerojatno ponekad ne treba ignorirati expression
        public string GetQuerySourceFromExpression(string name, Type type, Expression fromExpression)
        {
            var me = fromExpression as MemberExpression;

            if (me != null)
            {
                var qse = me.Expression as QuerySourceReferenceExpression;
                if (qse != null)
                {
                    return(@"TABLE(""{0}"".""{1}"") ""{2}""".With(
                               qse.ReferencedQuerySource.ItemName,
                               me.Member.Name,
                               name));
                }
            }

            var sqe = fromExpression as SubQueryExpression;

            if (sqe != null)
            {
                if (sqe.QueryModel.CanUseMain())
                {
                    return(GetQuerySourceFromExpression(name, type, sqe.QueryModel.MainFromClause.FromExpression));
                }
                //TODO hack za replaceanje generiranog id-a
                var subquery = SubqueryGeneratorQueryModelVisitor.ParseSubquery(sqe.QueryModel, this, ContextName, Context.Select());
                var grouping = sqe.QueryModel.ResultOperators.FirstOrDefault(it => it is GroupResultOperator) as GroupResultOperator;
                if (grouping == null && subquery.Selects.Count == 1)
                {
                    if (sqe.QueryModel.ResultOperators.Any(it => it is UnionResultOperator || it is ConcatResultOperator))
                    {
                        var ind = subquery.Selects[0].Sql.IndexOf(" AS ");
                        if (ind > 0)
                        {
                            var asName = subquery.Selects[0].Sql.Substring(ind + 4).Trim().Replace("\"", "");
                            if (asName != name)
                            {
                                subquery.Selects[0].Sql = subquery.Selects[0].Sql.Substring(0, ind + 4) + "\"" + name + "\"";
                            }
                        }
                        else
                        {
                            subquery.Selects[0].Sql = subquery.Selects[0].Sql + " AS \"" + name + "\"";
                        }
                        return("(" + subquery.BuildSqlString(true) + ") \"" + name + "\"");
                    }
                    return("(" + subquery.BuildSqlString(true).Replace("\"" + sqe.QueryModel.MainFromClause.ItemName + "\"", "\"" + name + "\"") + ") \"" + name + "\"");
                }
                return("(" + subquery.BuildSqlString(true) + ") \"" + name + "\"");
            }

            var ce = fromExpression as ConstantExpression;

            if (ce != null)
            {
                var queryable = ce.Value as IQueryable;
                if (queryable != null)
                {
                    return(GetQueryableExpression(name, queryable));
                }
                var ien   = ce.Value as IEnumerable;
                var array = ien != null?ien.Cast <object>().ToArray() : null;

                var firstElem = array != null?array.FirstOrDefault(it => it != null) : null;

                var elementType = firstElem != null?firstElem.GetType()
                                      : ce.Type.IsArray ? ce.Type.GetElementType()
                                        : ce.Type.IsGenericType ? ce.Type.GetGenericArguments()[0]
                                        : null;

                if (Context.CanUseParams && elementType != null)
                {
                    var factory = ConverterFactory.GetVarrayParameterFactory(elementType);
                    if (factory != null)
                    {
                        var p = Parameters.Add(factory(ce.Value as IEnumerable));
                        return(@"(SELECT sq$.OBJECT_VALUE as ""{1}"" FROM TABLE({0}) sq$)".With(p, name));
                    }
                }
                if (ce.Type.IsArray || ce.Value is Array)
                {
                    return(FormatStringArray(ce.Value, name, ce.Type));
                }
                else if (ce.Value is IEnumerable)
                {
                    return(FormatStringEnumerable(ce.Value, name, ce.Type));
                }
                //TODO: sql injection!?
                return("(SELECT {0} AS \"{1}\" FROM dual) \"{1}\"".With(ce.Value, name));
            }

            var nae = fromExpression as NewArrayExpression;

            if (nae != null)
            {
                if (nae.Expressions.Count == 0)
                {
                    //TODO support for zero
                    throw new NotImplementedException("Expecting NewArrayExpression arguments. None found.");
                }
                var inner = string.Join(" UNION ALL ", nae.Expressions.Select(it => "SELECT {0} AS \"{1}\"".With(GetSqlExpression(it), name)));
                return("(" + inner + ") \"{0}\" ".With(name));
            }

            if (fromExpression is QuerySourceReferenceExpression && fromExpression.Type.IsGrouping())
            {
                var qse = fromExpression as QuerySourceReferenceExpression;
                //TODO: convert to Oracle version
                return
                    ("(SELECT (\"{0}\".\"Values\")[i].* FROM generate_series(1, array_upper(\"{0}\".\"Values\", 1)) i) AS \"{1}\"".With(
                         qse.ReferencedQuerySource.ItemName,
                         name));
            }

            var pe = fromExpression as ParameterExpression;

            if (pe != null)
            {
                return("TABLE({0}\"{1}\") \"{2}\"".With(ContextName, pe.Name, name));
            }

            return(FromSqlSource(name, type));
        }