/// <summary> /// 初始化 <see cref="SQLiteUpdateExpressionVisitor"/> 类的新实例 /// </summary> /// <param name="ag">表别名解析器</param> /// <param name="builder">SQL 语句生成器</param> /// <param name="tree">更新语义</param> /// <param name="alias">指定的表达式别名</param> internal SQLiteUpdateExpressionVisitor(AliasGenerator ag, ISqlBuilder builder, DbQueryUpdateTree tree, string alias) : base(ag, builder) { _tree = tree; _alias = alias; _builder = builder; _visitedStack = base.VisitedStack; }
// 解析查询语义 private static IDbQueryTree Parse(IDbQueryable source, Type elmentType, 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 fromType = null; DbRawSql rawSql = null; bool isDistinct = false; bool isAny = false; bool isSubquery = false; int? skip = null; int? take = null; int? outerIndex = null; List <DbExpression> wheres = null; // WHERE List <DbExpression> havings = null; // HAVING List <DbExpression> joins = null; // JOIN List <DbExpression> orderBys = null; // ORDER BY List <DbExpression> includes = null; // ORDER BY List <DbQuerySelectTree> unions = null; // UNION ALL Expression pickExpression = null; 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 || isSubquery) { outerIndex = index; break; } #region 解析片断 switch (item.DbExpressionType) { case DbExpressionType.None: case DbExpressionType.All: continue; case DbExpressionType.Any: isAny = true; if (item.Expressions != null) { if (wheres == null) { wheres = new List <DbExpression>(); } wheres.Add(item); } break; case DbExpressionType.AsSubquery: isSubquery = true; continue; case DbExpressionType.Union: var constExpression = item.Expressions[0] as ConstantExpression; var uQuery = constExpression.Value as IDbQueryable; var u = DbQueryableParser.Parse(uQuery, constExpression.Type.GetGenericArguments()[0], 0); if (unions == null) { unions = new List <DbQuerySelectTree>(); } unions.Add((DbQuerySelectTree)u); // 如果下一个不是 union,就使用嵌套 if (index + 1 <= source.DbExpressions.Count - 1 && source.DbExpressions[index + 1].DbExpressionType != DbExpressionType.Union) { isSubquery = true; } continue; case DbExpressionType.Include: if (includes == null) { includes = new List <DbExpression>(); } includes.Add(item); continue; case DbExpressionType.GroupBy: group = item; continue; case DbExpressionType.GetTable: fromType = (item.Expressions[0] as ConstantExpression).Value as Type; if (fromType == null) { string text = (item.Expressions[0] as ConstantExpression).Value as string; if (text != null) { rawSql = new DbRawSql(null, text, (object[])(item.Expressions[1] as ConstantExpression).Value); } } 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) { if (wheres == null) { wheres = new List <DbExpression>(); } wheres.Add(item); } continue; case DbExpressionType.Distinct: isDistinct = true; continue; case DbExpressionType.First: case DbExpressionType.FirstOrDefault: take = 1; if (item.Expressions != null) { if (wheres == null) { wheres = new List <DbExpression>(); } wheres.Add(item); } continue; case DbExpressionType.Join: case DbExpressionType.LeftOuterJoin: case DbExpressionType.RightOuterJoin: pickExpression = item.Expressions[3]; var j = item; // GetTable 的参数 var inner = (j.Expressions[0] as ConstantExpression).Value as IDbQueryable; if (inner.DbExpressions.Count == 1 && inner.DbExpressions[0].DbExpressionType == DbExpressionType.GetTable) { // 区别 GetTable 有三个重载,这里处理指定外键路径的重载 if (inner.DbExpressions[0].Expressions.Length == 2 && (inner.DbExpressions[0].Expressions[0] as ConstantExpression).Value is Type) { var expressions = new Expression[item.Expressions.Length + 1]; Array.Copy(item.Expressions, expressions, item.Expressions.Length); expressions[expressions.Length - 1] = inner.DbExpressions[0].Expressions[1]; j = new DbExpression(item.DbExpressionType, expressions); } } if (joins == null) { joins = new List <DbExpression>(); } joins.Add(j); continue; case DbExpressionType.OrderBy: case DbExpressionType.OrderByDescending: if (orderBys == null) { orderBys = new List <DbExpression>(); } orderBys.Add(item); continue; case DbExpressionType.Select: pickExpression = item.Expressions != null ? item.Expressions[0] : null; continue; case DbExpressionType.SelectMany: pickExpression = item.Expressions[1]; if (IsCrossJoinExression(source.DbExpressions, item, startIndex)) { if (joins == null) { joins = new List <DbExpression>(); } joins.Add(item); } continue; case DbExpressionType.Single: case DbExpressionType.SingleOrDefault: take = 1; if (item.Expressions != null) { if (wheres == null) { wheres = new List <DbExpression>(); } wheres.Add(item); } 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: if (orderBys == null) { orderBys = new List <DbExpression>(); } orderBys.Add(item); continue; case DbExpressionType.Where: if (item.Expressions != null) { if (group == null) { if (wheres == null) { wheres = new List <DbExpression>(); } wheres.Add(item); } else { if (havings == null) { havings = new List <DbExpression>(); } havings.Add(item); } } 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 的所有字段 if (insert == null && delete == null && update == null && pickExpression == null && aggregate == null) { pickExpression = Expression.Constant(fromType ?? elmentType); } DbExpression select = new DbExpression(DbExpressionType.Select, pickExpression); if (fromType == null) { fromType = elmentType; } var result_Query = new DbQuerySelectTree(); result_Query.From = fromType; result_Query.FromSql = rawSql; 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 = select; result_Query.Wheres = wheres; result_Query.Havings = havings; #region 更新语义 if (update != null) { var result_Update = new DbQueryUpdateTree(); 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.Select = result_Query; return(result_Update); } #endregion #region 除语义 else if (delete != null) { var result_Delete = new DbQueryDeleteTree(); var constantExpression = delete.Expressions != null ? delete.Expressions[0] as ConstantExpression : null; if (constantExpression != null) { result_Delete.Entity = constantExpression.Value; } result_Delete.Select = result_Query; return(result_Delete); } #endregion #region 插入语义 else if (insert != null) { var result_Insert = new DbQueryInsertTree(); 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.Select = result_Query; result_Insert.Bulk = ((DbQueryable)source).Bulk; return(result_Insert); } #endregion #region 择语义 else if (pickExpression != null) { // 检查嵌套查询语义 result_Query = DbQueryableParser.TryParseOutQuery(result_Query); } #endregion #region 嵌套语义 // 解析嵌套查询 if (outerIndex != null) { // todo => elementType ??? var outQueryTree = DbQueryableParser.Parse(source, elmentType, outerIndex.Value); var result_Insert = outQueryTree as DbQueryInsertTree; var result_Update = outQueryTree as DbQueryUpdateTree; var result_Delete = outQueryTree as DbQueryDeleteTree; if (result_Insert != null) { if (result_Insert.Select != null) { result_Insert.Select.Subquery = result_Query; } else { result_Insert.Select = result_Query; } return(result_Insert); } else if (result_Update != null) { if (result_Update.Select != null) { result_Update.Select.Subquery = result_Query; } else { result_Update.Select = result_Query; } return(result_Update); } else if (result_Delete != null) { if (result_Delete.Select != null) { result_Delete.Select.Subquery = result_Query; } else { result_Delete.Select = result_Query; } return(result_Delete); } else { // 指定子查询 var iterator = (DbQuerySelectTree)outQueryTree; while (iterator.Subquery != null) { iterator = iterator.Subquery; } iterator.Subquery = result_Query; //// ?? AsSubquery(a=>a),那么它所有的外层字段都要基于里层的字段 //if (isSubquery && startIndex == 0) // LimitSelector((DbQuerySelectTree)outQueryTree); // 如果外层是统计,内层没有分页,则不需要排序 iterator = (DbQuerySelectTree)outQueryTree; while (iterator.Subquery != null) { // 没有分页的嵌套统计,不需要排序 if (iterator.Aggregate != null && !(iterator.Subquery.Take > 0 || iterator.Subquery.Skip > 0) && iterator.Subquery.OrderBys != null && iterator.Subquery.OrderBys.Count > 0) { iterator.Subquery.OrderBys = new List <DbExpression>(0); } // 继续下一轮迭代 iterator = iterator.Subquery; } return(outQueryTree); } } #endregion // 查询表达式 return(result_Query); }
/// <summary> /// 创建 UPDATE 命令 /// </summary> /// <param name="tree">查询语义</param> /// <param name="context">解析上下文</param> /// <returns></returns> protected abstract DbRawCommand TranslateUpdateCommand <T>(DbQueryUpdateTree tree, ITranslateContext context);