// 解析查询语义
        static IDbQueryableInfo <TElement> Parse <TElement>(IDbQueryable <TElement> source, int startIndex)
        {
            // 目的:将query 转换成增/删/改/查
            // 1、from a in context.GetTable<T>() select a 此时query里面可能没有SELECT 表达式
            // 2、Take 视为一个查询的结束位,如有更多查询,应使用嵌套查询
            // 3、uion 分页查询也使嵌套语义
            // 4、uion 后面跟着 WHERE,GROUP BY,SELECT,JOIN语句时需要使用嵌套查询

            Type type       = null;
            bool isDistinct = false;
            bool isAny      = false;
            bool subQuery   = false;
            int? skip       = null;
            int? take       = null;
            int? outerIndex = null;
            var  conditions = new List <Expression>();          // WHERE
            var  havings    = new List <Expression>();          // HAVING
            var  joins      = new List <DbExpression>();        // JOIN
            var  orderBys   = new List <DbExpression>();        // ORDER BY
            var  includes   = new List <DbExpression>();        // ORDER BY
            var  unions     = new List <IDbQueryableInfo <TElement> >();

            Expression   select    = null;                      // SELECT #
            DbExpression insert    = null;                      // INSERT #
            DbExpression update    = null;                      // UPDATE #
            DbExpression delete    = null;                      // DELETE #
            DbExpression group     = null;                      // GROUP BY #
            DbExpression aggregate = null;                      // SUM&MAX  #

            for (int index = startIndex; index < source.DbExpressions.Count; index++)
            {
                DbExpression item = source.DbExpressions[index];

                // Take(n)
                if (take != null || (skip != null && item.DbExpressionType != DbExpressionType.Take) || isDistinct || subQuery)
                {
                    outerIndex = index;
                    break;
                }

                #region 解析片断

                switch (item.DbExpressionType)
                {
                case DbExpressionType.None:
                case DbExpressionType.All:
                    continue;

                case DbExpressionType.Any:
                    isAny = true;
                    if (item.Expressions != null)
                    {
                        conditions.Add(item.Expressions[0]);
                    }
                    break;

                case DbExpressionType.AsSubQuery:
                    subQuery = true;
                    continue;

                case DbExpressionType.Union:
                    var uQuery = (item.Expressions[0] as ConstantExpression).Value as IDbQueryable <TElement>;
                    var u      = DbQueryParser.Parse(uQuery);
                    unions.Add(u);

                    // 如果下一个不是 union,就使用嵌套
                    if (index + 1 <= source.DbExpressions.Count - 1 && source.DbExpressions[index + 1].DbExpressionType != DbExpressionType.Union)
                    {
                        subQuery = true;
                    }
                    continue;

                case DbExpressionType.Include:
                    includes.Add(item);
                    continue;

                case DbExpressionType.GroupBy:
                    group = item;
                    continue;

                case DbExpressionType.GetTable:
                    type = (item.Expressions[0] as ConstantExpression).Value as Type;
                    continue;

                case DbExpressionType.Average:
                case DbExpressionType.Min:
                case DbExpressionType.Sum:
                case DbExpressionType.Max:
                    aggregate = item;
                    continue;

                case DbExpressionType.Count:
                    aggregate = item;
                    if (item.Expressions != null)
                    {
                        conditions.Add(item.Expressions[0]);
                    }
                    continue;

                case DbExpressionType.Distinct:
                    isDistinct = true;
                    continue;

                case DbExpressionType.First:
                case DbExpressionType.FirstOrDefault:
                    take = 1;
                    if (item.Expressions != null)
                    {
                        conditions.Add(item.Expressions[0]);
                    }
                    continue;

                case DbExpressionType.Join:
                case DbExpressionType.GroupJoin:
                case DbExpressionType.GroupRightJoin:
                    select = item.Expressions[3];
                    joins.Add(item);
                    continue;

                case DbExpressionType.OrderBy:
                case DbExpressionType.OrderByDescending:
                    orderBys.Add(item);
                    continue;

                case DbExpressionType.Select:
                    select = item.Expressions != null ? item.Expressions[0] : null;
                    continue;

                case DbExpressionType.SelectMany:
                    select = item.Expressions[1];
                    if (IsSelectMany(source.DbExpressions, item, startIndex))
                    {
                        joins.Add(item);
                    }
                    continue;

                case DbExpressionType.Single:
                case DbExpressionType.SingleOrDefault:
                    take = 1;
                    if (item.Expressions != null)
                    {
                        conditions.Add(item.Expressions[0]);
                    }
                    continue;

                case DbExpressionType.Skip:
                    skip = (int)(item.Expressions[0] as ConstantExpression).Value;
                    continue;

                case DbExpressionType.Take:
                    take = (int)(item.Expressions[0] as ConstantExpression).Value;
                    continue;

                case DbExpressionType.ThenBy:
                case DbExpressionType.ThenByDescending:
                    orderBys.Add(item);
                    continue;

                case DbExpressionType.Where:
                    var predicate = group == null ? conditions : havings;
                    if (item.Expressions != null)
                    {
                        predicate.Add(item.Expressions[0]);
                    }
                    continue;

                case DbExpressionType.Insert:
                    insert = item;
                    continue;

                case DbExpressionType.Update:
                    update = item;
                    continue;

                case DbExpressionType.Delete:
                    delete = item;
                    continue;

                default:
                    throw new NotSupportedException(string.Format("{0} is not support.", item.DbExpressionType));
                }

                #endregion
            }

            // 没有解析到INSERT/DELETE/UPDATE/SELECT表达式,并且没有相关聚合函数,则默认选择 FromEntityType 的所有字段
            bool pickAllColumns = insert == null && delete == null && update == null && select == null && aggregate == null;
            if (pickAllColumns)
            {
                select = Expression.Constant(type ?? typeof(TElement));
            }

            var result_Query = new DbQueryableInfo_Select <TElement>();
            result_Query.FromEntityType = type;
            result_Query.HasDistinct    = isDistinct;
            result_Query.HasAny         = isAny;
            result_Query.Joins          = joins;
            result_Query.OrderBys       = orderBys;
            result_Query.GroupBy        = group;
            result_Query.Aggregate      = aggregate;
            result_Query.Unions         = unions;
            result_Query.Includes       = includes;
            result_Query.Skip           = skip != null ? skip.Value : 0;
            result_Query.Take           = take != null ? take.Value : 0;
            result_Query.Select         = new DbExpression(DbExpressionType.Select, select);
            result_Query.Condtion       = new DbExpression(DbExpressionType.Where, CombineCondition(conditions));
            result_Query.Having         = new DbExpression(DbExpressionType.None, CombineCondition(havings));
            result_Query.SourceQuery    = source;

            #region 更新语义

            if (update != null)
            {
                var result_Update      = new DbQueryableInfo_Update <TElement>();
                var constantExpression = update.Expressions != null ? update.Expressions[0] as ConstantExpression : null;
                if (constantExpression != null)
                {
                    result_Update.Entity = constantExpression.Value;
                }
                else
                {
                    result_Update.Expression = update.Expressions[0];
                }
                result_Update.SelectInfo  = result_Query;
                result_Update.SourceQuery = source;
                return(result_Update);
            }

            #endregion

            #region  除语义

            else if (delete != null)
            {
                var result_Delete      = new DbQueryableInfo_Delete <TElement>();
                var constantExpression = delete.Expressions != null ? delete.Expressions[0] as ConstantExpression : null;
                if (constantExpression != null)
                {
                    result_Delete.Entity = constantExpression.Value;
                }
                result_Delete.SelectInfo  = result_Query;
                result_Delete.SourceQuery = source;
                return(result_Delete);
            }

            #endregion

            #region 插入语义

            else if (insert != null)
            {
                var result_Insert = new DbQueryableInfo_Insert <TElement>();
                if (insert.Expressions != null)
                {
                    result_Insert.Entity = (insert.Expressions[0] as ConstantExpression).Value;
                    if (insert.Expressions.Length > 1)
                    {
                        result_Insert.EntityColumns = (insert.Expressions[1] as ConstantExpression).Value as IList <Expression>;
                    }
                }
                result_Insert.SelectInfo  = result_Query;
                result_Insert.Bulk        = source.Bulk;
                result_Insert.SourceQuery = source;
                source.DbQueryInfo        = result_Insert;
                return(result_Insert);
            }

            #endregion

            #region  择语义

            else if (select != null)
            {
                // 检查嵌套查询语义
                result_Query = DbQueryParser.ParseOutQuery(result_Query);
                // 查询来源
                result_Query.SourceQuery = source;
            }

            #endregion

            #region 嵌套语义

            // 解析嵌套查询
            if (outerIndex != null)
            {
                var outQuery = DbQueryParser.Parse <TElement>(source, outerIndex.Value);
                var nQuery   = outQuery as DbQueryableInfo_Insert <TElement>;
                var uQuery   = outQuery as DbQueryableInfo_Update <TElement>;
                if (nQuery != null)
                {
                    if (nQuery.SelectInfo != null)
                    {
                        nQuery.SelectInfo.SubQueryInfo = result_Query;
                    }
                    else
                    {
                        nQuery.SelectInfo = result_Query;
                    }
                    nQuery.SourceQuery = source;
                    return(nQuery);
                }
                else if (uQuery != null)
                {
                    if (uQuery.SelectInfo != null)
                    {
                        uQuery.SelectInfo.SubQueryInfo = result_Query;
                    }
                    else
                    {
                        uQuery.SelectInfo = result_Query;
                    }
                    uQuery.SourceQuery = source;
                    return(uQuery);
                }
                else
                {
                    var rootQuery = outQuery;
                    while (rootQuery.SubQueryInfo != null)
                    {
                        rootQuery = rootQuery.SubQueryInfo;
                    }
                    rootQuery.SubQueryInfo = result_Query;
                    outQuery.SourceQuery   = source;

                    // 如果外层是统计,内层没有分页,则不需要排序
                    rootQuery = outQuery;
                    while (rootQuery.SubQueryInfo != null)
                    {
                        var myOutQuery = rootQuery as IDbQueryableInfo_Select;
                        var mySubQuery = rootQuery.SubQueryInfo as IDbQueryableInfo_Select;
                        // 没有分页的嵌套统计,不需要排序
                        if (myOutQuery.Aggregate != null && !(mySubQuery.Take > 0 || mySubQuery.Skip > 0) && mySubQuery.OrderBys.Count > 0)
                        {
                            mySubQuery.OrderBys = new List <DbExpression>(0);
                        }
                        // 继续下一轮迭代
                        rootQuery = rootQuery.SubQueryInfo;
                    }

                    return(outQuery);
                }
            }

            #endregion

            // 查询表达式
            return(result_Query);
        }
Example #2
0
 /// <summary>
 /// 初始化 <see cref="SQLiteUpdateExpressionVisitor"/> 类的新实例
 /// </summary>
 internal SQLiteUpdateExpressionVisitor(IDbQueryProvider provider, TableAliasCache aliases, DbQueryableInfo_Update <T> uQueryInfo, string alias)
     : base(provider, aliases, uQueryInfo.Expression)
 {
     _alias      = alias;
     _provider   = provider;
     _uQueryInfo = uQueryInfo;
     _expression = base.Expression;
 }
Example #3
0
        // 解析查询语义
        static IDbQueryableInfo <TElement> Parse <TElement>(IDbQueryable <TElement> dbQuery, int startIndex)
        {
            // 目的:将query 转换成增/删/改/查
            // 1、from a in context.GetTable<T>() select a 此时query里面可能没有SELECT 表达式
            // 2、Take 视为一个查询的结束位,如有更多查询,应使用嵌套查询
            // 3、uion 分页查询也使嵌套语义
            // 4、uion 后面跟着 WHERE,GROUP BY,SELECT,JOIN语句时需要使用嵌套查询

            Type type              = null;
            bool isDistinct        = false;
            bool isAny             = false;
            bool subQuery          = false;
            int? skip              = null;
            int? take              = null;
            int? outerIndex        = null;
            var  whereExpressions  = new List <Expression>();   // WHERE
            var  havingExpressions = new List <Expression>();   // HAVING
            var  joins             = new List <DbExpression>(); // JOIN
            var  orderBys          = new List <DbExpression>(); // ORDER BY
            var  includes          = new List <DbExpression>(); // ORDER BY
            var  unions            = new List <IDbQueryableInfo <TElement> >();

            Expression   selectExpression  = null;            // SELECT #
            DbExpression insertExpression  = null;            // INSERT #
            DbExpression updateExpression  = null;            // UPDATE #
            DbExpression deleteExpression  = null;            // DELETE #
            DbExpression groupByExpression = null;            // GROUP BY #
            DbExpression statisExpression  = null;            // SUM/MAX  #

            for (int index = startIndex; index < dbQuery.DbExpressions.Count; index++)
            {
                DbExpression curExpr = dbQuery.DbExpressions[index];

                // Take(n)
                if (take != null || (skip != null && curExpr.DbExpressionType != DbExpressionType.Take) || isDistinct || subQuery)
                {
                    outerIndex = index;
                    break;
                }

                #region 解析片断

                switch (curExpr.DbExpressionType)
                {
                case DbExpressionType.None:
                case DbExpressionType.All:
                    continue;

                case DbExpressionType.Any:
                    isAny = true;
                    if (curExpr.Expressions != null)
                    {
                        whereExpressions.Add(curExpr.Expressions[0]);
                    }
                    break;

                case DbExpressionType.AsSubQuery:
                    subQuery = true;
                    continue;

                case DbExpressionType.Union:
                    var uQuery = (curExpr.Expressions[0] as ConstantExpression).Value as IDbQueryable <TElement>;
                    var u      = DbQueryParser.Parse(uQuery);
                    unions.Add(u);

                    // 如果下一个不是 union,就使用嵌套
                    if (index + 1 <= dbQuery.DbExpressions.Count - 1 && dbQuery.DbExpressions[index + 1].DbExpressionType != DbExpressionType.Union)
                    {
                        subQuery = true;
                    }
                    continue;

                case DbExpressionType.Include:
                    includes.Add(curExpr);
                    continue;

                case DbExpressionType.GroupBy:
                    groupByExpression = curExpr;
                    continue;

                case DbExpressionType.GetTable:
                    type = (curExpr.Expressions[0] as ConstantExpression).Value as Type;
                    continue;

                case DbExpressionType.Average:
                case DbExpressionType.Min:
                case DbExpressionType.Sum:
                case DbExpressionType.Max:
                    statisExpression = curExpr;
                    continue;

                case DbExpressionType.Count:
                    statisExpression = curExpr;
                    if (curExpr.Expressions != null)
                    {
                        whereExpressions.Add(curExpr.Expressions[0]);
                    }
                    continue;

                case DbExpressionType.Distinct:
                    isDistinct = true;
                    continue;

                case DbExpressionType.First:
                case DbExpressionType.FirstOrDefault:
                    take = 1;
                    if (curExpr.Expressions != null)
                    {
                        whereExpressions.Add(curExpr.Expressions[0]);
                    }
                    continue;

                case DbExpressionType.Join:
                case DbExpressionType.GroupJoin:
                case DbExpressionType.GroupRightJoin:
                    selectExpression = curExpr.Expressions[3];
                    joins.Add(curExpr);
                    continue;

                case DbExpressionType.OrderBy:
                case DbExpressionType.OrderByDescending:
                    orderBys.Add(curExpr);
                    continue;

                case DbExpressionType.Select:
                    selectExpression = curExpr.Expressions != null ? curExpr.Expressions[0] : null;
                    continue;

                case DbExpressionType.SelectMany:
                    selectExpression = curExpr.Expressions[1];
                    if (IsSelectMany(dbQuery.DbExpressions, curExpr, startIndex))
                    {
                        joins.Add(curExpr);
                    }
                    continue;

                case DbExpressionType.Single:
                case DbExpressionType.SingleOrDefault:
                    take = 1;
                    if (curExpr.Expressions != null)
                    {
                        whereExpressions.Add(curExpr.Expressions[0]);
                    }
                    continue;

                case DbExpressionType.Skip:
                    skip = (int)(curExpr.Expressions[0] as ConstantExpression).Value;
                    continue;

                case DbExpressionType.Take:
                    take = (int)(curExpr.Expressions[0] as ConstantExpression).Value;
                    continue;

                case DbExpressionType.ThenBy:
                case DbExpressionType.ThenByDescending:
                    orderBys.Add(curExpr);
                    continue;

                case DbExpressionType.Where:
                    var predicate = groupByExpression == null ? whereExpressions : havingExpressions;
                    if (curExpr.Expressions != null)
                    {
                        predicate.Add(curExpr.Expressions[0]);
                    }
                    continue;

                case DbExpressionType.Insert:
                    insertExpression = curExpr;
                    continue;

                case DbExpressionType.Update:
                    updateExpression = curExpr;
                    continue;

                case DbExpressionType.Delete:
                    deleteExpression = curExpr;
                    continue;

                default:
                    throw new NotSupportedException(string.Format("{0} is not support.", curExpr.DbExpressionType));
                }

                #endregion
            }

            // 没有解析到INSERT/DELETE/UPDATE/SELECT表达式,并且没有相关统计函数,则默认选择FromType的所有字段
            bool useFullFields = insertExpression == null && deleteExpression == null && updateExpression == null && selectExpression == null && statisExpression == null;
            if (useFullFields)
            {
                selectExpression = Expression.Constant(type ?? typeof(TElement));
            }

            var sQueryInfo = new DbQueryableInfo_Select <TElement>();
            sQueryInfo.FromType          = type;
            sQueryInfo.HasDistinct       = isDistinct;
            sQueryInfo.HasAny            = isAny;
            sQueryInfo.Joins             = joins;
            sQueryInfo.OrderBys          = orderBys;
            sQueryInfo.GroupByExpression = groupByExpression;
            sQueryInfo.StatisExpression  = statisExpression;
            sQueryInfo.Unions            = unions;
            sQueryInfo.Includes          = includes;
            sQueryInfo.Skip             = skip != null ? skip.Value : 0;
            sQueryInfo.Take             = take != null ? take.Value : 0;
            sQueryInfo.SelectExpression = new DbExpression(DbExpressionType.Select, selectExpression);
            sQueryInfo.WhereExpression  = new DbExpression(DbExpressionType.Where, CombineWhere(whereExpressions));
            sQueryInfo.HavingExpression = new DbExpression(DbExpressionType.None, CombineWhere(havingExpressions));
            sQueryInfo.SourceQuery      = dbQuery;

            #region 更新语义

            if (updateExpression != null)
            {
                var uQueryInfo         = new DbQueryableInfo_Update <TElement>();
                var constantExpression = updateExpression.Expressions != null ? updateExpression.Expressions[0] as ConstantExpression : null;
                if (constantExpression != null)
                {
                    uQueryInfo.Entity = constantExpression.Value;
                }
                else
                {
                    uQueryInfo.Expression = updateExpression.Expressions[0];
                }
                uQueryInfo.SelectInfo  = sQueryInfo;
                uQueryInfo.SourceQuery = dbQuery;
                return(uQueryInfo);
            }

            #endregion

            #region  除语义

            else if (deleteExpression != null)
            {
                var dQueryInfo         = new DbQueryableInfo_Delete <TElement>();
                var constantExpression = deleteExpression.Expressions != null ? deleteExpression.Expressions[0] as ConstantExpression : null;
                if (constantExpression != null)
                {
                    dQueryInfo.Entity = constantExpression.Value;
                }
                dQueryInfo.SelectInfo  = sQueryInfo;
                dQueryInfo.SourceQuery = dbQuery;
                return(dQueryInfo);
            }

            #endregion

            #region 插入语义

            else if (insertExpression != null)
            {
                var nQueryInfo = new DbQueryableInfo_Insert <TElement>();
                if (insertExpression.Expressions != null)
                {
                    nQueryInfo.Entity = (insertExpression.Expressions[0] as ConstantExpression).Value;
                    if (insertExpression.Expressions.Length > 1)
                    {
                        nQueryInfo.EntityColumns = (insertExpression.Expressions[1] as ConstantExpression).Value as IList <Expression>;
                    }
                }
                nQueryInfo.SelectInfo  = sQueryInfo;
                nQueryInfo.Bulk        = dbQuery.Bulk;
                nQueryInfo.SourceQuery = dbQuery;
                dbQuery.DbQueryInfo    = nQueryInfo;
                return(nQueryInfo);
            }

            #endregion

            #region  择语义

            else if (selectExpression != null)
            {
                // 检查嵌套查询语义
                sQueryInfo = DbQueryParser.TryBuildOutQuery(sQueryInfo);
                // 查询来源
                sQueryInfo.SourceQuery = dbQuery;
            }

            #endregion

            #region 嵌套语义

            // 解析嵌套查询
            if (outerIndex != null)
            {
                var outQuery = DbQueryParser.Parse <TElement>(dbQuery, outerIndex.Value);
                var nQuery   = outQuery as DbQueryableInfo_Insert <TElement>;
                var uQuery   = outQuery as DbQueryableInfo_Update <TElement>;
                if (nQuery != null)
                {
                    if (nQuery.SelectInfo != null)
                    {
                        nQuery.SelectInfo.SubQueryInfo = sQueryInfo;
                    }
                    else
                    {
                        nQuery.SelectInfo = sQueryInfo;
                    }
                    nQuery.SourceQuery = dbQuery;
                    return(nQuery);
                }
                else if (uQuery != null)
                {
                    if (uQuery.SelectInfo != null)
                    {
                        uQuery.SelectInfo.SubQueryInfo = sQueryInfo;
                    }
                    else
                    {
                        uQuery.SelectInfo = sQueryInfo;
                    }
                    uQuery.SourceQuery = dbQuery;
                    return(uQuery);
                }
                else
                {
                    var rootQuery = outQuery;
                    while (rootQuery.SubQueryInfo != null)
                    {
                        rootQuery = rootQuery.SubQueryInfo;
                    }
                    rootQuery.SubQueryInfo = sQueryInfo;
                    outQuery.SourceQuery   = dbQuery;

                    // 如果外层是统计,内层没有分页,则不需要排序
                    rootQuery = outQuery;
                    while (rootQuery.SubQueryInfo != null)
                    {
                        var myOutQuery = rootQuery as IDbQueryableInfo_Select;
                        var mySubQuery = rootQuery.SubQueryInfo as IDbQueryableInfo_Select;
                        // 没有分页的嵌套统计,不需要排序
                        if (myOutQuery.StatisExpression != null && !(mySubQuery.Take > 0 || mySubQuery.Skip > 0) && mySubQuery.OrderBys.Count > 0)
                        {
                            mySubQuery.OrderBys = new List <DbExpression>(0);
                        }
                        // 继续下一轮迭代
                        rootQuery = rootQuery.SubQueryInfo;
                    }

                    return(outQuery);
                }
            }

            #endregion

            // 查询表达式
            return(sQueryInfo);
        }