Esempio n. 1
0
        /// <summary>
        /// 访问 IDbQueryable.Contains 方法
        /// </summary>
        /// <param name="m">字段或属性表达式</param>
        protected override Expression VisitQueryableContains(MethodCallExpression m)
        {
            ITranslateContext context  = _builder.TranslateContext;
            DbQueryable       subquery = m.Arguments[0].Evaluate().Value as DbQueryable;

            subquery.Parameterized = _builder.Parameterized;

            // 可能会有几级嵌套,这里用 Builder.Ident 标记是第几层级
            string[] subs       = new[] { "p", "u", "v", "w", "x" };
            var      newContext = context != null?TranslateContext.Copy(context, subs[_builder.Indent]) : null;

            bool isDelete = context != null && ((SQLiteTranslateContext)context).IsDelete;
            var  cmd      = subquery.Translate(_builder.Indent + 1, false, newContext) as DbSelectCommand;

            if (this.NotOperands != null && this.NotOperands.Contains(m))
            {
                _builder.Append("NOT ");
            }
            _builder.Append("EXISTS(");
            _builder.Append(cmd.CommandText);

            if (((DbSelectCommand)cmd).WhereFragment.Length > 0)
            {
                _builder.Append(" AND ");
            }
            else
            {
                _builder.Append("WHERE ");
            }
            _builder.Append(cmd.SelectedColumnText);
            _builder.Append(" = ");

            // exists 不能用别名
            if (isDelete)
            {
                var typeRuntime = TypeRuntimeInfoCache.GetRuntimeInfo(((MemberExpression)m.Arguments[1]).Expression.Type);
                _builder.AppendTable(typeRuntime.TableSchema, typeRuntime.TableName, typeRuntime.IsTemporary);
                _builder.Append('.');
            }

            _visitor.Visit(m.Arguments[1]);
            _builder.Append(")");

            return(m);
        }
        /// <summary>
        /// 解析 SQL 命令
        /// <para>
        /// 返回的已经解析语义中执行批次用 null 分开
        /// </para>
        /// </summary>
        /// <param name="dbQueryables">查询语句</param>
        /// <returns></returns>
        public override List <DbRawCommand> Translate(List <object> dbQueryables)
        {
            bool haveBegin            = false;
            ITranslateContext context = null;
            var sqlList = new List <DbRawCommand>();

            for (int i = 0; i < dbQueryables.Count; i++)
            {
                object obj = dbQueryables[i];
                if (obj == null)
                {
                    continue;
                }

                if (obj is IDbQueryable)
                {
                    DbQueryable dbQuery = (DbQueryable)obj;
                    dbQuery.Parameterized = true;
                    if (context == null)
                    {
                        context = this.CreateTranslateContext(dbQuery.DbContext);
                    }
                    if (context.Parameters == null)
                    {
                        context.Parameters = new List <IDbDataParameter>(8);
                    }

                    var cmd = dbQuery.Translate(0, true, context);
                    if (cmd is DbSelectCommand)
                    {
                        // 查询单独执行
                        if (sqlList.Count > 0 && (i - 1) >= 0 && sqlList[sqlList.Count - 1] != null)
                        {
                            sqlList.Add(null);
                        }

                        sqlList.Add(cmd);
                        sqlList.Add(null);
                        context            = this.CreateTranslateContext(dbQuery.DbContext);
                        context.Parameters = new List <IDbDataParameter>(8);
                    }
                    else
                    {
                        // 增删改
                        if (!haveBegin)
                        {
                            sqlList.Add(new DbRawCommand("BEGIN"));
                            haveBegin = true;
                        }
                        sqlList.Add(cmd);
                        if (cmd.Parameters != null && cmd.Parameters.Count > 1000)
                        {
                            // 1000个参数,就要重新分批
                            if (haveBegin)
                            {
                                sqlList.Add(new DbRawCommand("END;"));
                                haveBegin = false;
                                sqlList.Add(null);
                            }
                            context            = this.CreateTranslateContext(dbQuery.DbContext);
                            context.Parameters = new List <IDbDataParameter>(8);
                        }

                        if (i + 1 < dbQueryables.Count)
                        {
                            // 检查下一条是否是选择语句
                            bool isQuery = false;
                            if (dbQueryables[i + 1] is IDbQueryable)
                            {
                                var tree = ((DbQueryable)dbQueryables[i + 1]).Parse();
                                isQuery = tree is DbQuerySelectTree;
                            }
                            else if ((dbQueryables[i + 1] is string))
                            {
                                string sql    = dbQueryables[i + 1].ToString();
                                string method = string.Empty;
                                if (sql.Length > 6)
                                {
                                    method = sql.Substring(0, 6).Trim().ToUpper();
                                }
                                isQuery = method == "SELECT";
                            }
                            else if (dbQueryables[i + 1] is DbRawSql)
                            {
                                string sql    = ((DbRawSql)dbQueryables[i + 1]).CommandText;
                                string method = string.Empty;
                                if (sql.Length > 6)
                                {
                                    method = sql.Substring(0, 6).Trim().ToUpper();
                                }
                                isQuery = method == "SELECT";
                            }

                            // 如果下一条是SELECT 语句,则需要结束当前语句块
                            if (isQuery)
                            {
                                if (haveBegin)
                                {
                                    sqlList.Add(new DbRawCommand("END;"));
                                    haveBegin = false;
                                    sqlList.Add(null);
                                }
                                context            = this.CreateTranslateContext(dbQuery.DbContext);
                                context.Parameters = new List <IDbDataParameter>(8);
                            }
                        }
                    }
                }
                else if (obj is DbRawSql || obj is string)
                {
                    string sql = string.Empty;
                    if (obj is string)
                    {
                        sql = obj.ToString();
                    }
                    else
                    {
                        DbRawSql rawSql = (DbRawSql)obj;
                        // 解析参数
                        object[] args = null;
                        if (rawSql.Parameters != null)
                        {
                            args = rawSql.Parameters.Select(x => this.Constor.GetSqlValue(x, context)).ToArray();
                        }
                        sql = rawSql.CommandText;
                        if (args != null && args.Length > 0)
                        {
                            sql = string.Format(sql, args);
                        }
                    }


                    string methodName = string.Empty;
                    if (sql.Length > 6)
                    {
                        methodName = sql.Substring(0, 6).Trim().ToUpper();
                    }
                    if (methodName == "SELECT")
                    {
                        if (sqlList.Count > 0 && (i - 1) >= 0 && sqlList[sqlList.Count - 1] != null)
                        {
                            sqlList.Add(null);
                        }
                    }


                    var cmd = new DbRawCommand(sql, context.Parameters, CommandType.Text);
                    sqlList.Add(cmd);

                    if (methodName == "SELECT")
                    {
                        sqlList.Add(cmd);
                        sqlList.Add(null);
                        context            = this.CreateTranslateContext(obj is DbRawSql ? ((DbRawSql)obj).DbContext : null);
                        context.Parameters = new List <IDbDataParameter>(8);
                    }
                    else if (cmd.Parameters != null && cmd.Parameters.Count > 1000)
                    {
                        // 1000个参数,就要重新分批
                        if (haveBegin)
                        {
                            sqlList.Add(new DbRawCommand("END;"));
                            sqlList.Add(null);
                            haveBegin = false;
                        }
                        context            = this.CreateTranslateContext(obj is DbRawSql ? ((DbRawSql)obj).DbContext : null);
                        context.Parameters = new List <IDbDataParameter>(8);
                    }
                }
                else
                {
                    if (!haveBegin)
                    {
                        sqlList.Add(new DbRawCommand("BEGIN"));
                        haveBegin = true;
                    }
                    // 解析批量插入操作
                    List <IDbQueryable> bulkList = obj as List <IDbQueryable>;
                    if (bulkList != null && bulkList.Count > 0)
                    {
                        this.TranslateBulk(sqlList, bulkList);
                    }
                }

                if (haveBegin && i == dbQueryables.Count - 1)
                {
                    sqlList.Add(new DbRawCommand("END;"));
                }
            }

            return(sqlList);
        }