예제 #1
0
        public void Render(ISqlBuilder builder, params Expression[] args)
        {
            if (args.Length != 2)
            {
                throw new NotSupportedException(string.Format(Res.ArgumentCountError, "Right()", "", " 2 "));
            }
            //Right(t0.descript,case when CHARINDEX('c',t0.descript) = 0 then 0 else
            //(LEN(t0.descript)- (CHARINDEX('c',t0.descript)+LEN('c'))+1) end)

            builder.Append("Right(");
            builder.Visit(args[0]);
            builder.Append(",IIF(InStr(");
            builder.Visit(args[0]);
            builder.Append(",");
            builder.Visit(args[1]);
            builder.Append(") = 0,0,(LEN(");
            builder.Visit(args[0]);
            builder.Append(") - (InStr(");
            builder.Visit(args[0]);
            builder.Append(",");
            builder.Visit(args[1]);
            builder.Append(")+LEN(");
            builder.Visit(args[1]);
            builder.Append("))+1)))");
        }
예제 #2
0
 public void Render(ISqlBuilder builder, params Expression[] args)
 {
     //SUBSTRING(userName,1,2)+'ddd'+SUBSTRING(userName,3,LEN(userName))
     if (args.Length != 3)
     {
         throw new NotSupportedException(string.Format(Res.ArgumentCountError, "Insert", "", "3"));
     }
     //var secondStartIndex = Expression.Constant((int)(args[1] as ConstantExpression).Value + 1);
     builder.Append("(CASE WHEN ");
     builder.Visit(args[1]);
     builder.Append(" > LEN(");
     builder.Visit(args[0]);
     builder.Append(") THEN null ELSE (SUBSTRING(");
     builder.Visit(args[0]);
     builder.Append(",1,");
     builder.Visit(Expression.Subtract(Expression.Property(args[1], "Value"), Expression.Constant(1, Types.Int32)));
     builder.Append(") + ");
     builder.Visit(args[2]);
     builder.Append(" + SUBSTRING(");
     builder.Visit(args[0]);
     builder.Append(",");
     builder.Visit(args[1]);
     builder.Append(",LEN(");
     builder.Visit(args[0]);
     builder.Append("))) END)");
 }
예제 #3
0
        public void Render(ISqlBuilder builder, params Expression[] args)
        {
            if (args.Length != 2 && args.Length != 3)
            {
                throw new ArgumentException(string.Format(Res.ArgumentCountError, "CASE", "", " 2 or 3 "));
            }

            var whens = (args[0] as ICollection<Expression>).ToArray();
            var thens = (args[1] as ICollection<Expression>).ToArray();
            var @else = args[2] as Expression;

            builder.Append("CASE");

            var lenght = whens.Length;
            for (int i = 0; i < lenght; i++)
            {
                builder.Append(" WHEN ");
                builder.Visit(whens[i]);
                builder.Append(" THEN ");
                builder.Visit(thens[i]);
            }

            if (@else != null)
            {
                builder.Append(" ELSE ");
                builder.Visit(@else);
            }

            builder.Append(" END");
        }
예제 #4
0
        public void Render(ISqlBuilder builder, params Expression[] args)
        {
            var value = args[1];
            var constExp = args[2] as ConstantExpression;
            if (constExp != null)
            {
                value = FormatValue(value,
                    (bool)constExp.Value
                    , (bool)(args[3] as ConstantExpression).Value
                    , (bool)(args[4] as ConstantExpression).Value);
            }
            else
            {
                var nv = args[2] as NamedValueExpression;
                if (nv != null)
                {
                    constExp = nv.Value as ConstantExpression;
                    value = FormatValue(value,
                   (bool)constExp.Value
                   , (bool)((args[3] as NamedValueExpression).Value as  ConstantExpression).Value
                   , (bool)((args[4] as NamedValueExpression).Value as ConstantExpression).Value);
                }
            }

            builder.Append("(");
            builder.Visit(args[0]);
            builder.Append(" LIKE ");
            builder.Visit(value);
            builder.Append(")");
        }
예제 #5
0
 public void Render(ISqlBuilder builder, params Expression[] args)
 {
     if (args == null)
         throw new NotSupportedException("args");
     //if (args.Length != 1)
     //    throw new NotSupportedException("'IsNullOrWhiteSpace' function takes  1 arguments");
     var isNot = args.Length == 2;
     if (isNot)
     {
         builder.Append("(");
         builder.Visit(args[0]);
         builder.Append(" IS NOT NULL OR ");
         builder.Visit(args[0]);
         builder.Append(" <> '' OR LTRIM(");
         builder.Visit(args[0]);
         builder.Append(") = '')");
     }
     else
     {
         builder.Append("(");
         builder.Visit(args[0]);
         builder.Append(" IS NULL OR ");
         builder.Visit(args[0]);
         builder.Append(" = '' OR LTRIM(");
         builder.Visit(args[0]);
         builder.Append(") = '')");
     }
 }
예제 #6
0
        public void Render(ISqlBuilder builder, params Expression[] args)
        {
            if (args == null || (args.Length != 2 && args.Length != 3))
            {
                throw new NotSupportedException(string.Format(Res.ArgumentCountError, "substring", "", "2 or 3"));
            }
            builder.Append("CASE WHEN LENGTH(");
            builder.Visit(args[1]);
            builder.Append(") > LENGTH(");
            builder.Visit(args[0]);
            builder.Append(") THEN NULL ELSE SUBSTR(");
            builder.Visit(args[0]);
            builder.Append(",").Visit(args[1]);
            if (args.Length == 2)
            {
                builder.Append(",LENGTH(").Visit(args[0]);
                builder.Append(")");

            }
            else
            {
                builder.Append(",").Visit(args[2]);
            }
            builder.Append(") END");
        }
예제 #7
0
 public virtual void Render(ISqlBuilder builder, params Expression[] args)
 {
     builder.Append(name);
     builder.Append("(");
     builder.VisitEnumerable(args);
     builder.Append(")");
 }
예제 #8
0
 public void Render(ISqlBuilder ctx, params Expression[] args)
 {
     if (args.Length != 3)
     {
         throw new NotSupportedException(string.Format(Res.ArgumentCountError, "Insert", "", "3"));
     }
     var secondStartIndex = args[1];// Expression.Constant((int)(args[1] as ConstantExpression).Value + 1);
     ctx.Append("(CASE WHEN ");
     ctx.Visit(secondStartIndex);
     ctx.Append(" > LENGTH(");
     ctx.Visit(args[0]);
     ctx.Append(") THEN null ELSE (SUBSTR(");
     ctx.Visit(args[0]);
     ctx.Append(",1,");
     ctx.Visit(Expression.Subtract(Expression.Property(args[1], "Value"), Expression.Constant(1, Types.Int32)));
     ctx.Append(") || ");
     ctx.Visit(args[2]);
     ctx.Append(" || SUBSTR(");
     ctx.Visit(args[0]);
     ctx.AppendFormat(",");
     ctx.Visit(secondStartIndex);
     ctx.Append(",LENGTH(");
     ctx.Visit(args[0]);
     ctx.Append(")))END)");
 }
예제 #9
0
        public void Render(ISqlBuilder visitor, params Expression[] args)
        {
            var whens = (args[0] as ICollection<Expression>).ToArray();
            var thens = (args[1] as ICollection<Expression>).ToArray();
            var @else = args[2] as Expression;

            var lenght = whens.Length;
            for (int i = 0; i < lenght; i++)
            {
                if (i != 0)
                    visitor.Append(",");

                visitor.Append("IIF(");
                visitor.Visit(whens[i]);
                visitor.Append(",");
                visitor.Visit(thens[i]);

                if (i == lenght - 1)
                {
                    if (@else != null)
                    {
                        visitor.Append(",");
                        visitor.Visit(@else);
                    }
                    for (var j = i; j >= 0; j--)
                        visitor.Append(")");

                }

            }
        }
예제 #10
0
 public void Render(ISqlBuilder builder, params Expression[] args)
 {
     if (args.Length != 2 && args.Length != 3)
     {
         throw new NotSupportedException(string.Format(Res.ArgumentCountError, "PadRight", "", "2 or 3"));
     }
     builder.Append("CASE WHEN LEN(");
     builder.Visit(args[0]);
     builder.Append(") >= ");
     builder.Visit(args[1]);
     builder.Append(" THEN ");
     builder.Visit(args[0]);
     builder.Append(" ELSE (");
     builder.Visit(args[0]);
     builder.Append("+");
     if (args.Length == 2)
     {
         builder.Append("SPACE(");
         builder.Visit(args[1]);
         builder.Append(" - LEN(");
         builder.Visit(args[0]);
         builder.Append(")))");
     }
     else
     {
         builder.Append("REPLICATE(");
         builder.Visit(args[2]);
         builder.Append(",");
         builder.Visit(args[1]);
         builder.Append(" - LEN(");
         builder.Visit(args[0]);
         builder.Append(")))");
     }
     builder.Append(" END");
 }
예제 #11
0
 public virtual void Render(ISqlBuilder visitor, params Expression[] args)
 {
     var targetArg = args[0];
     visitor.Append("RTRIM(LTRIM(");
     visitor.Visit(targetArg);
     visitor.Append("))");
 }
예제 #12
0
 public void Render(ISqlBuilder visitor, params Expression[] args)
 {
     if (args == null || (args.Length != 2 && args.Length != 3))
     {
         throw new NotSupportedException(string.Format(Res.ArgumentCountError, "remove()", "", " 2 or 3 "));
     }
     visitor.Append("IIF((LEN(");
     visitor.Visit(args[0]);
     visitor.Append(") < ");
     visitor.Visit(args[1]);
     visitor.Append("),NULL,REPLACE(");
     visitor.Visit(args[0]);
     visitor.Append(",MID(");
     visitor.Visit(args[0]);
     visitor.Append(",");
     visitor.Visit(args[1]);
     if (args.Length == 2)
     {
         visitor.Append(",8000)");
     }
     else
     {
         visitor.Append(",");
         visitor.Visit(args[2]);
         visitor.Append(")");
     }
     visitor.Append(",''))");
 }
예제 #13
0
 public void SetupTest()
 {
     _sqlBuilder = MockRepository.GenerateMock<ISqlBuilder>();
     _paramMgr = MockRepository.GenerateMock<IParameterManager>();
     _queryBuilder = new QueryBuilder( _sqlBuilder, _paramMgr );
     _result = _queryBuilder.Add( _inputSql );
 }
 internal SqlStatementFormatter(EntityDescriptor mainEntityDescriptor, EntityMapping mainEntityMapping, ISqlBuilder mainEntitySqlBuilder)
 {
     this.MainEntityType = mainEntityDescriptor.EntityType;
     this.MainEntityDescriptor = mainEntityDescriptor;
     this.MainEntitySqlBuilder = mainEntitySqlBuilder;
     this.MainEntityMapping = mainEntityMapping;
 }
 /// <summary>
 /// Default constructor.
 /// </summary>
 /// <param name="mainEntityDescriptor">Main entity descriptor</param>
 /// <param name="mainEntityMapping">Main entity mappings</param>
 /// <param name="mainEntitySqlBuilder">SQL mapper for the main entity</param>
 /// <param name="forceColumnAsTableColumnResolution">If true, the format identifier 'C' will be treated as 'TC' </param>
 internal SqlStatementFormatter(EntityDescriptor mainEntityDescriptor, EntityMapping mainEntityMapping, ISqlBuilder mainEntitySqlBuilder, bool forceColumnAsTableColumnResolution)
 {
     _forceColumnAsTableColumnResolution = forceColumnAsTableColumnResolution;
     this.MainEntityType = mainEntityDescriptor.EntityType;
     this.MainEntityDescriptor = mainEntityDescriptor;
     this.MainEntitySqlBuilder = mainEntitySqlBuilder;
     this.MainEntityMapping = mainEntityMapping;            
 }
예제 #16
0
 public void SetupTest()
 {
     _sqlBuilder = MockRepository.GenerateMock<ISqlBuilder>();
     _paramMgr = MockRepository.GenerateMock<IParameterManager>();
     _paramMgr.Stub( m => m.AddParameters( _parameterValue ) ).Return( _paramNames );
     _queryBuilder = new QueryBuilder( _sqlBuilder, _paramMgr );
     _result = _queryBuilder.Add( _inputSql, _parameterValue );
 }
예제 #17
0
        public void Render(ISqlBuilder builder, params Expression[] args)
        {
            if (args != null && args.Length > 0)
                throw new ArgumentException(string.Format(Res.ArgumentCountError, Name, "no", ""));

            builder.Append(Name);
            builder.Append("()");
        }
예제 #18
0
        public void Render(ISqlBuilder builder, params Expression[] args)
        {
            if (args == null)
                throw new NotSupportedException("args");
            if (args.Length != 2 && args.Length != 3)
                throw new NotSupportedException(string.Format(Res.ArgumentCountError, "LastIndexOf", "", "2 or 3"));
            builder.Append("CASE WHEN INSTR(");
            builder.Visit(args[0]);
            builder.Append(",");
            builder.Visit(args[1]);
            builder.Append(") = 0 then  -1  else");
            if (args.Length == 3)
            {
                builder.Append("(CASE WHEN (INSTR(");
                builder.Append("SUBSTRING(");
                builder.Visit(args[0]);
                builder.Append(",1,");
                //args[2] = Expression.Subtract(Expression.Property(args[2], "Value"), Expression.Constant(1, Types.Int32));
                builder.Visit(args[2]);
                builder.Append("),");
                builder.Visit(args[1]);

                builder.Append(")) = 0 or (");
                builder.Visit(args[2]);
                builder.Append(" > LENGTH(");
                builder.Visit(args[0]);
                builder.Append(")) THEN -1 ELSE LENGTH(SUBSTRING(");

                builder.Visit(args[0]);
                builder.Append(",1,");
                builder.Visit(args[2]);
                builder.Append(")) - (INSTR(");
                builder.Append("REVERSE(SUBSTRING(");
                builder.Visit(args[0]);
                builder.Append(",1,");
                builder.Visit(args[2]);
                builder.Append(")),");
                builder.Append("REVERSE(");
                builder.Visit(args[1]);
                builder.Append(")) + LENGTH(");
                builder.Visit(args[1]);
                builder.Append(") -1) END ) END");

            }
            else
            {
                builder.Append("  (LENGTH(");
                builder.Visit(args[0]);
                builder.Append(")- (INSTR(");
                builder.Append("REVERSE(");
                builder.Visit(args[0]);
                builder.Append("),REVERSE(");
                builder.Visit(args[1]);
                builder.Append(")) + LENGTH(");
                builder.Visit(args[1]);
                builder.Append(") - 1)) END");
            }
        }
예제 #19
0
        public void Render(ISqlBuilder builder, params Expression[] args)
        {
            if (args == null)
                throw new NotSupportedException("args");
            if (args.Length != 2 && args.Length != 3)
                throw new NotSupportedException(string.Format(Res.ArgumentCountError, "LastIndexOf()", "", " 2 or 3 "));
            //var isChar = args[1].Type == Types.Char;
            builder.Append("IIF(INSTR(");
            builder.Visit(args[0]);
            builder.Append(",");
            builder.Visit(args[1]);
            builder.Append(") = 0,-1,");
            if (args.Length == 3)
            {
                //args[2] = Expression.Constant((int)(args[2] as ConstantExpression).Value + 1);
                builder.Append("(IIf((INSTR(");
                builder.Append("MID(");
                builder.Visit(args[0]);
                builder.Append(",1,");
                builder.Visit(args[2]);
                builder.Append("),");
                builder.Visit(args[1]);
                builder.Append(") = 0) OR (");
                builder.Visit(args[2]);
                builder.Append(" > LEN(");
                builder.Visit(args[0]);
                builder.Append(")),-1 ,(LEN(MID(");
                builder.Visit(args[0]);
                builder.Append(",1,");
                builder.Visit(args[2]);
                builder.Append(")) - (INSTR(");
                builder.Append("STRREVERSE(MID(");
                builder.Visit(args[0]);
                builder.Append(",1,");
                builder.Visit(args[2]);
                builder.Append(")),");

                builder.Append("STRREVERSE(");
                builder.Visit(args[1]);
                builder.Append(")) + LEN(");
                builder.Visit(args[1]);
                builder.Append(")-1)))))");

            }
            else
            {
                builder.Append("(LEN(");
                builder.Visit(args[0]);
                builder.Append(")- (INSTR(STRREVERSE(");
                builder.Visit(args[0]);
                builder.Append("),STRREVERSE(");
                builder.Visit(args[1]);
                builder.Append(")) + LEN(");
                builder.Visit(args[1]);
                builder.Append(")-1)))");

            }
        }
예제 #20
0
 public static IDataDriver Get(SqlConfig config, ISqlBuilder sqlBuilder)
 {
     switch (config.DataDriverType)
     {
         case DataDriverType.Sqlite:
             return new SqliteDriver(config, sqlBuilder);
     }
     return null;
 }
예제 #21
0
 public void Render(ISqlBuilder builder, params Expression[] args)
 {
     var datePart = (DateParts)(args[0] as ConstantExpression).Value;
     IFunctionView f;
     if (functions.TryGetValue(datePart, out f))
         f.Render(builder, args[1], args[2]);
     else
         throw new NotSupportedException(string.Format(Res.NotSupported, "The 'DatePart." + datePart, ""));
 }
예제 #22
0
 public QueryBuilder()
 {
     ExpressionLanguageParser = ObjectFactory.Get<IExpressionLanguageParser>();
     ExpressionDispatcher = ObjectFactory.Get<IExpressionDispatcher>();
     PrequelAnalyzer = ObjectFactory.Get<IPrequelAnalyzer>();
     ExpressionOptimizer = ObjectFactory.Get<IExpressionOptimizer>();
     SpecialExpressionTranslator = ObjectFactory.Get<ISpecialExpressionTranslator>();
     SqlBuilder = ObjectFactory.Get<ISqlBuilder>();
 }
예제 #23
0
 public void Render(ISqlBuilder builder, params Expression[] args)
 {
     if (args.Length == 1)
     {
         builder.Append("DATE_FORMAT(");
         builder.Visit(args[0]);
         builder.Append(",'%H:%i:%s')");
     }
 }
예제 #24
0
 public void Render(ISqlBuilder builder, params Expression[] args)
 {
     builder.Append("CDate(");
     builder.Visit(args[0]);
     builder.Append(" & '/' & ");
     builder.Visit(args[1]);
     builder.Append(" & '/' & ");
     builder.Visit(args[2]);
     builder.Append(")");
 }
		protected override string GetDescription(SqlCaluseBuilderItemWithData builderItem, ISqlBuilder builder)
		{
			string result = string.Empty;

			if ((Guid)builderItem.Data == Guid.Empty)
				result = "NULL";
			else
				result = builder.CheckUnicodeQuotationMark(builderItem.Data.ToString());

			return result;
		}
예제 #26
0
        public void Render(ISqlBuilder builder, params Expression[] args)
        {
            var year = args[0];
            var month = args[1];

            builder.Append("(CASE");
            builder.Append(" WHEN ");
            builder.Visit(year);
            builder.Append("% 4 = 0 AND(");
            builder.Visit(year);
        }
예제 #27
0
 public void Render(ISqlBuilder builder, params Expression[] args)
 {
     builder.Append("TRUNC(");
     builder.Append(Name);
     builder.Append("(");
     builder.Visit(args[0]);
     builder.Append(")");
     builder.Append(",");
     builder.Append(MaxDecimalDigits);
     builder.Append(")");
 }
예제 #28
0
 public void Render(ISqlBuilder visitor, params Expression[] args)
 {
     if (args == null)
         throw new ArgumentNullException("args");
     if (args.Length != 2 && args.Length != 3)
         throw new ArgumentException(string.Format(Res.ArgumentCountError, "remove", "", "2 or 3"));
     if (args.Length == 2)
         LocateWith2Params.Render(visitor, args);
     else
         LocateWith3Params.Render(visitor, args);
 }
예제 #29
0
        public void Render(ISqlBuilder visitor, params Expression[] args)
        {
            if (args.Length != 2)
                throw new ArgumentException(string.Format(Res.ArgumentCountError, "dateadd", "", " 2 "));

            var addPart = (args[1] as ConstantExpression).Value;

            visitor.Append("(");
            visitor.Visit(args[0]);
            visitor.Append(" + interval '" + addPart.ToString() + "' " + Type.ToString() + ")");
        }
예제 #30
0
 public void Render(ISqlBuilder builder, params Expression[] args)
 {
     builder.Append("IIF(");
     builder.Visit(args[0]);
     builder.Append(" = ");
     builder.Visit(args[1]);
     builder.Append(", 0, IIF(");
     builder.Visit(args[0]);
     builder.Append(" < ");
     builder.Visit(args[1]);
     builder.Append(", -1, 1))");
 }
 /// <summary>
 /// Adds a custom implementation of <see cref="ISqlBuilder"/>
 /// for the specified ADO.NET connection type.
 /// </summary>
 /// <param name="connectionType">
 /// The ADO.NET conncetion type to use the <paramref name="builder"/> with.
 /// Example: <c>typeof(SqlConnection)</c>.
 /// </param>
 /// <param name="builder">An implementation of the <see cref="ISqlBuilder"/> interface.</param>
 public static void AddSqlBuilder(Type connectionType, ISqlBuilder builder) => _sqlBuilders[connectionType.Name.ToLower()] = builder;
예제 #32
0
 /// <summary>
 /// 设置子查询条件
 /// </summary>
 /// <param name="builder">Sql生成器</param>
 /// <param name="expression">列名表达式,范例:t => t.Name</param>
 /// <param name="action">子查询操作</param>
 /// <param name="condition">该值为true时添加查询条件,否则忽略</param>
 /// <param name="operator">运算符</param>
 public static ISqlBuilder WhereIf <TEntity>(this ISqlBuilder builder, Expression <Func <TEntity, object> > expression, Action <ISqlBuilder> action,
                                             bool condition, Operator @operator = Operator.Equal) where TEntity : class
 {
     return(condition ? builder.Where(expression, action, @operator) : builder);
 }
예제 #33
0
        protected Dictionary <string, string> GetEasyJoinInfo(Expression joinExpression, ref string shortName, ISqlBuilder builder, params Type[] entityTypeArray)
        {
            Dictionary <string, string> result = new Dictionary <string, string>();
            var lambdaParameters = ((LambdaExpression)joinExpression).Parameters.ToList();

            shortName = lambdaParameters.First().Name;
            var index = 1;

            foreach (var item in entityTypeArray)
            {
                result.Add(UtilConstants.Space + lambdaParameters[index].Name, item.Name);
                ++index;
            }
            return(result);
        }
예제 #34
0
 /// <summary>
 /// 初始化Oracle 表连接子句
 /// </summary>
 /// <param name="sqlBuilder">Sql生成器</param>
 /// <param name="dialect">方言</param>
 /// <param name="resolver">实体解析器</param>
 /// <param name="register">实体注册器</param>
 /// <param name="parameterManager">参数管理器</param>
 /// <param name="tableDatabase">表数据库</param>
 public OracleJoinClause(ISqlBuilder sqlBuilder, IDialect dialect, IEntityResolver resolver, IEntityAliasRegister register,
                         IParameterManager parameterManager, ITableDatabase tableDatabase)
     : base(sqlBuilder, dialect, resolver, register, parameterManager, tableDatabase)
 {
 }
예제 #35
0
        // LEFT OR INNER JOIN
        private void AppendLfInJoin(ISqlBuilder jf, ISqlBuilder wf, ISqlBuilder on, DbExpression exp, TableAliasCache aliases)
        {
            bool             useExists = false;
            LambdaExpression left      = exp.Expressions[1] as LambdaExpression;
            LambdaExpression right     = exp.Expressions[2] as LambdaExpression;
            NewExpression    body1     = left.Body as NewExpression;
            NewExpression    body2     = right.Body as NewExpression;

            // t0(t1)
            string alias = body1 == null
                ? aliases.GetTableAlias(exp.Expressions[2])
                : aliases.GetTableAlias(right.Parameters[0]);//(body2.Arguments[0]);

            IDbQueryable sQuery = (IDbQueryable)((exp.Expressions[0] as ConstantExpression).Value);

            if (sQuery.DbExpressions.Count == 1 && sQuery.DbExpressions[0].DbExpressionType == DbExpressionType.GetTable)
            {
                if (!_appendedKeyword)
                {
                    jf.AppendNewLine();
                    jf.Append(_keywordName);
                    _appendedKeyword = true;
                }
                else
                {
                    jf.Append(',');
                    jf.AppendNewLine();
                    jf.Append("     ");
                }

                jf.Append(' ');
                Type type        = exp.Expressions[0].Type.GetGenericArguments()[0];
                var  typeRuntime = TypeRuntimeInfoCache.GetRuntimeInfo(type);
                jf.AppendMember(typeRuntime.TableName, !typeRuntime.IsTemporary);

                jf.Append(' ');
                jf.Append(alias);
                if (on.Length > 0)
                {
                    on.Append(" AND ");
                }
            }
            else
            {
                useExists = true;
                if ((wf != null && wf.Length > 0) || (on != null && on.Length > 0))
                {
                    if (wf != null && wf.Length > 0)
                    {
                        wf.Append("AND ");
                    }
                    wf.AppendNewLine();
                }

                wf.Append("EXISTS(");
                wf.Indent += 1;
                wf.AppendNewLine();
                wf.Append("SELECT 1 FROM(");
                var cmd = sQuery.Resolve(wf.Indent + 1, false, wf.Parameters);
                wf.Append(cmd.CommandText);
                wf.AppendNewLine();
                wf.Append(')');
                wf.Append(' ');
                wf.Append(alias);
                wf.Append(" WHERE ");
            }

            ISqlBuilder tbuilder = useExists ? wf : on;

            if (body1 == null)
            {
                tbuilder.AppendMember(aliases, left.Body.ReduceUnary());
                tbuilder.Append(" = ");
                tbuilder.AppendMember(aliases, right.Body.ReduceUnary());
            }
            else
            {
                for (int index = 0; index < body1.Arguments.Count; ++index)
                {
                    tbuilder.AppendMember(aliases, body1.Arguments[index]);
                    tbuilder.Append(" = ");
                    tbuilder.AppendMember(aliases, body2.Arguments[index]);
                    if (index < body1.Arguments.Count - 1)
                    {
                        tbuilder.Append(" AND ");
                    }
                }
            }

            if (useExists)
            {
                wf.Indent -= 1;
                wf.AppendNewLine();
                wf.Append(')');
            }
        }
        // 创建 SELECT 命令
        protected override Command ResolveSelectCommand <T>(DbQueryableInfo_Select <T> dbQuery, int indent, bool isOuter, ResolveToken token)
        {
            // 说明:
            // 1.OFFSET 前必须要有 'ORDER BY',即 'Skip' 子句前必须使用 'OrderBy' 子句
            // 2.在有聚合函数的<MAX,MIN...>情况下,如果有 'Distinct' 'GroupBy' 'Skip' 'Take' 子句,则需要使用嵌套查询
            // 3.'Any' 子句将翻译成 IF EXISTS...
            // 4.分组再分页时需要使用嵌套查询,此时子查询不需要 'OrderBy' 子句,但最外层则需要
            // 5.'Skip' 'Take' 子句视为语义结束符,在其之后的子句将使用嵌套查询
            // 6.导航属性中有 1:n 关系的,需要使用嵌套查询,否则分页查询会有问题

            // 导航属性中有1:n关系,只统计主表
            // 例:AccountList = a.Client.AccountList,
            var subQuery = dbQuery.SubQueryInfo as DbQueryableInfo_Select <T>;

            if (dbQuery.HasMany && subQuery != null && subQuery.Aggregate != null)
            {
                dbQuery = subQuery;
            }

            bool useStatis = dbQuery.Aggregate != null;
            // 没有聚合函数或者使用 'Skip' 子句,则解析OrderBy
            // 导航属性如果使用嵌套,除非有 TOP 或者 OFFSET 子句,否则不能用ORDER BY
            string alias0      = token != null && !string.IsNullOrEmpty(token.TableAliasName) ? (token.TableAliasName + "0") : "t0";
            bool   useSubQuery = dbQuery.HasDistinct || dbQuery.GroupBy != null || dbQuery.Skip > 0 || dbQuery.Take > 0;
            bool   useOrderBy  = (!useStatis || dbQuery.Skip > 0) && !dbQuery.HasAny && (!dbQuery.SubQueryOfMany || (dbQuery.Skip > 0 || dbQuery.Take > 0));

            IDbQueryable    sourceQuery = dbQuery.SourceQuery;
            var             context     = (SqlServerDbContext)sourceQuery.DbContext;
            TableAliasCache aliases     = this.PrepareTableAlias <T>(dbQuery, token);
            MapperCommand   cmd         = new SqlServerMapperCommand(context, aliases, token)
            {
                HasMany = dbQuery.HasMany
            };
            ISqlBuilder jf = cmd.JoinFragment;
            ISqlBuilder wf = cmd.WhereFragment;

            jf.Indent = indent;

            #region 嵌套查询

            if (useStatis && useSubQuery)
            {
                // SELECT
                jf.Append("SELECT ");
                jf.AppendNewLine();

                // SELECT COUNT(1)
                var visitor2 = new AggregateExpressionVisitor(this, aliases, dbQuery.Aggregate, dbQuery.GroupBy, alias0);
                visitor2.Write(jf);
                cmd.AddNavMembers(visitor2.NavMembers);

                // SELECT COUNT(1) FROM
                jf.AppendNewLine();
                jf.Append("FROM ( ");

                indent   += 1;
                jf.Indent = indent;
            }

            #endregion 嵌套查询

            #region  择子句

            // SELECT 子句
            if (jf.Indent > 0)
            {
                jf.AppendNewLine();
            }
            if (dbQuery.HasAny)
            {
                jf.Append("IF EXISTS(");
                indent   += 1;
                jf.Indent = indent;
                jf.AppendNewLine();
            }

            jf.Append("SELECT ");

            if (useStatis && !useSubQuery)
            {
                // 如果有聚合函数,并且不是嵌套的话,则直接使用SELECT <MAX,MIN...>,不需要解析选择的字段
                jf.AppendNewLine();
                var visitor2 = new AggregateExpressionVisitor(this, aliases, dbQuery.Aggregate, dbQuery.GroupBy);
                visitor2.Write(jf);
                cmd.AddNavMembers(visitor2.NavMembers);
            }
            else
            {
                // DISTINCT 子句
                if (dbQuery.HasDistinct)
                {
                    jf.Append("DISTINCT ");
                }
                // TOP 子句
                if (dbQuery.Take > 0 && dbQuery.Skip == 0)
                {
                    jf.AppendFormat("TOP({0})", this.DbValue.GetSqlValue(dbQuery.Take, token));
                }
                // Any
                if (dbQuery.HasAny)
                {
                    jf.Append("TOP 1 1");
                }

                #region 字段

                if (!dbQuery.HasAny)
                {
                    // SELECT 范围
                    var visitor2 = new ColumnExpressionVisitor(this, aliases, dbQuery);
                    visitor2.Write(jf);

                    cmd.PickColumns    = visitor2.PickColumns;
                    cmd.PickColumnText = visitor2.PickColumnText;
                    cmd.Navigations    = visitor2.Navigations;
                    cmd.AddNavMembers(visitor2.NavMembers);
                }

                #endregion 字段
            }

            #endregion  择子句

            #region 顺序解析

            // FROM 子句
            jf.AppendNewLine();
            jf.Append("FROM ");
            if (dbQuery.SubQueryInfo != null)
            {
                // 子查询
                jf.Append('(');
                Command cmd2 = this.ResolveSelectCommand <T>(dbQuery.SubQueryInfo as DbQueryableInfo_Select <T>, indent + 1, false, token);
                jf.Append(cmd2.CommandText);
                jf.AppendNewLine();
                jf.Append(") ");
                jf.Append(alias0);
                jf.Append(' ');
            }
            else
            {
                var typeRuntime = TypeRuntimeInfoCache.GetRuntimeInfo(dbQuery.FromEntityType);
                jf.AppendMember(typeRuntime.TableName, !typeRuntime.IsTemporary);
                jf.Append(' ');
                jf.Append(alias0);
                jf.Append(' ');
                if (context.NoLock && !string.IsNullOrEmpty(this._widthNoLock))
                {
                    jf.Append(this._widthNoLock);
                }
            }

            // LEFT<INNER> JOIN 子句
            ExpressionVisitorBase visitor = new SqlServerJoinExpressionVisitor(context, aliases, dbQuery.Joins);
            visitor.Write(jf);

            wf.Indent = jf.Indent;

            // WHERE 子句
            visitor = new WhereExpressionVisitor(this, aliases, dbQuery.Condtion);
            visitor.Write(wf);
            cmd.AddNavMembers(visitor.NavMembers);

            // GROUP BY 子句
            visitor = new GroupByExpressionVisitor(this, aliases, dbQuery.GroupBy);
            visitor.Write(wf);
            cmd.AddNavMembers(visitor.NavMembers);

            // HAVING 子句
            visitor = new HavingExpressionVisitor(this, aliases, dbQuery.Having, dbQuery.GroupBy);
            visitor.Write(wf);
            cmd.AddNavMembers(visitor.NavMembers);

            // ORDER 子句
            if (dbQuery.OrderBys.Count > 0 && useOrderBy)
            {
                visitor = new OrderByExpressionVisitor(this, aliases, dbQuery.OrderBys, dbQuery.GroupBy);
                visitor.Write(wf);
                cmd.AddNavMembers(visitor.NavMembers);
            }

            #endregion 顺序解析

            #region 分页查询

            if (dbQuery.Skip > 0)
            {
                if (dbQuery.OrderBys.Count == 0)
                {
                    throw new XFrameworkException("The method 'OrderBy' must be called before 'Skip'.");
                }
                wf.AppendNewLine();
                wf.Append("OFFSET ");
                wf.Append(this.DbValue.GetSqlValue(dbQuery.Skip, token));
                wf.Append(" ROWS");

                if (dbQuery.Take > 0)
                {
                    wf.Append(" FETCH NEXT ");
                    wf.Append(this.DbValue.GetSqlValue(dbQuery.Take, token));
                    wf.Append(" ROWS ONLY ");
                }
            }

            #endregion 分页查询

            #region 嵌套查询

            if (useStatis && useSubQuery)
            {
                cmd.CombineFragments();
                indent   -= 1;
                jf.Indent = indent;
                jf.AppendNewLine();
                jf.Append(") ");
                jf.Append(alias0);
                jf.Append(' ');
            }

            #endregion 嵌套查询

            #region 嵌套导航

            if (dbQuery.HasMany && subQuery.Aggregate == null && subQuery != null && subQuery.OrderBys.Count > 0 && !(subQuery.Skip > 0 || subQuery.Take > 0))
            {
                // TODO Include 从表,没分页,OrderBy 报错
                cmd.CombineFragments();
                visitor = new OrderByExpressionVisitor(this, aliases, subQuery.OrderBys);
                visitor.Write(jf);
            }

            #endregion 嵌套导航

            #region 并集查询

            // UNION 子句
            if (dbQuery.Unions != null && dbQuery.Unions.Count > 0)
            {
                cmd.CombineFragments();
                for (int index = 0; index < dbQuery.Unions.Count; index++)
                {
                    jf.AppendNewLine();
                    jf.Append("UNION ALL");
                    if (indent == 0)
                    {
                        jf.AppendNewLine();
                    }
                    Command cmd2 = this.ResolveSelectCommand <T>(dbQuery.Unions[index] as DbQueryableInfo_Select <T>, indent, isOuter, token);
                    jf.Append(cmd2.CommandText);
                }
            }

            #endregion 并集查询

            #region Any 子句

            // 'Any' 子句
            if (dbQuery.HasAny)
            {
                cmd.CombineFragments();
                indent   -= 1;
                jf.Indent = indent;
                jf.AppendNewLine();
                jf.Append(") SELECT 1 ELSE SELECT 0");
            }

            #endregion Any 子句

            return(cmd);
        }
        // 创建 UPDATE 命令
        protected override Command ResolveUpdateCommand <T>(DbQueryableInfo_Update <T> dbQuery, ResolveToken token)
        {
            ISqlBuilder  builder     = this.CreateSqlBuilder(token);
            var          typeRuntime = TypeRuntimeInfoCache.GetRuntimeInfo <T>();
            IDbQueryable sourceQuery = dbQuery.SourceQuery;
            var          context     = (SqlServerDbContext)sourceQuery.DbContext;

            builder.Append("UPDATE t0 SET");
            builder.AppendNewLine();

            if (dbQuery.Entity != null)
            {
                object      entity       = dbQuery.Entity;
                ISqlBuilder whereBuilder = this.CreateSqlBuilder(token);
                bool        useKey       = false;
                int         length       = 0;

                foreach (var invoker in typeRuntime.Invokers)
                {
                    var column = invoker.Column;
                    if (column != null && column.IsIdentity)
                    {
                        goto gotoLabel;                                      // fix issue# 自增列同时又是主键
                    }
                    if (column != null && column.NoMapped)
                    {
                        continue;
                    }
                    if (invoker.Column != null && column.DbType is SqlDbType && (SqlDbType)column.DbType == SqlDbType.Timestamp)
                    {
                        continue;                                                                                                          // 行版本号
                    }
                    if (invoker.ForeignKey != null)
                    {
                        continue;
                    }
                    if (invoker.Member.MemberType == System.Reflection.MemberTypes.Method)
                    {
                        continue;
                    }

                    builder.AppendMember("t0", invoker.Member.Name);
                    builder.Append(" = ");

gotoLabel:
                    var value = invoker.Invoke(entity);
                    var seg = this.DbValue.GetSqlValueWidthDefault(value, token, column);

                    if (column == null || !column.IsIdentity)
                    {
                        builder.Append(seg);
                        length = builder.Length;
                        builder.Append(',');
                        builder.AppendNewLine();
                    }

                    if (column != null && column.IsKey)
                    {
                        useKey = true;
                        whereBuilder.AppendMember("t0", invoker.Member.Name);
                        whereBuilder.Append(" = ");
                        whereBuilder.Append(seg);
                        whereBuilder.Append(" AND ");
                    }
                }

                if (!useKey)
                {
                    throw new XFrameworkException("Update<T>(T value) require entity must have key column.");
                }

                builder.Length       = length;
                whereBuilder.Length -= 5;

                builder.AppendNewLine();
                builder.Append("FROM ");
                builder.AppendMember(typeRuntime.TableName, !typeRuntime.IsTemporary);
                builder.Append(" t0");

                builder.AppendNewLine();
                builder.Append("WHERE ");
                builder.Append(whereBuilder);
            }
            else if (dbQuery.Expression != null)
            {
                TableAliasCache       aliases = this.PrepareTableAlias <T>(dbQuery.SelectInfo, token);
                ExpressionVisitorBase visitor = null;
                visitor = new UpdateExpressionVisitor(this, aliases, dbQuery.Expression);
                visitor.Write(builder);

                builder.AppendNewLine();
                builder.Append("FROM ");
                builder.AppendMember(typeRuntime.TableName, !typeRuntime.IsTemporary);
                builder.AppendAs("t0");

                var cmd2 = new SqlServerMapperCommand(context, aliases, token)
                {
                    HasMany = dbQuery.SelectInfo.HasMany
                };

                visitor = new SqlServerJoinExpressionVisitor(context, aliases, dbQuery.SelectInfo.Joins);
                visitor.Write(cmd2.JoinFragment);

                visitor = new WhereExpressionVisitor(this, aliases, dbQuery.SelectInfo.Condtion);
                visitor.Write(cmd2.WhereFragment);
                cmd2.AddNavMembers(visitor.NavMembers);

                builder.Append(cmd2.CommandText);
            }

            return(new Command(builder.ToString(), builder.Token != null ? builder.Token.Parameters : null, System.Data.CommandType.Text));
        }
예제 #38
0
 /// <summary>
 /// 克隆
 /// </summary>
 /// <param name="builder">Sql生成器</param>
 /// <param name="register">实体别名注册器</param>
 /// <param name="parameterManager">参数管理器</param>
 /// <returns></returns>
 public virtual IWhereClause Clone(ISqlBuilder builder, IEntityAliasRegister register, IParameterManager parameterManager)
 {
     return(new WhereClause(builder, _dialect, _resolver, register, parameterManager,
                            new SqlCondition(_condition?.GetCondition())));
 }
예제 #39
0
 /// <summary>
 /// 设置子查询条件
 /// </summary>
 /// <typeparam name="TEntity">实体类型</typeparam>
 /// <param name="expression">列名表达式</param>
 /// <param name="builder">子查询Sql生成器</param>
 /// <param name="operator">运算符</param>
 public void Where <TEntity>(Expression <Func <TEntity, object> > expression, ISqlBuilder builder, Operator @operator = Operator.Equal) where TEntity : class
 {
     Where(_helper.GetColumn(expression), builder, @operator);
 }
예제 #40
0
        // 创建 UPDATE 命令
        protected override Command ParseUpdateCommand <T>(DbQueryableInfo_Update <T> uQueryInfo, ResolveToken token)
        {
            ISqlBuilder builder     = this.CreateSqlBuilder(token);
            var         typeRuntime = TypeRuntimeInfoCache.GetRuntimeInfo <T>();

            builder.Append("UPDATE ");
            builder.AppendMember(typeRuntime.TableName, !typeRuntime.IsTemporary);
            builder.Append(" SET");
            builder.AppendNewLine();

            if (uQueryInfo.Entity != null)
            {
                object      entity       = uQueryInfo.Entity;
                ISqlBuilder whereBuilder = this.CreateSqlBuilder(token);
                bool        useKey       = false;
                int         length       = 0;

                foreach (var invoker in typeRuntime.Invokers)
                {
                    var column = invoker.Column;
                    if (column != null && column.IsIdentity)
                    {
                        goto gotoLabel;                                      // fix issue# 自增列同时又是主键
                    }
                    if (column != null && column.NoMapped)
                    {
                        continue;
                    }
                    if (invoker.Column != null && column.DbType is SqlDbType && (SqlDbType)column.DbType == SqlDbType.Timestamp)
                    {
                        continue;                                                                                                          // 行版本号
                    }
                    if (invoker.ForeignKey != null)
                    {
                        continue;
                    }
                    if (invoker.Member.MemberType == System.Reflection.MemberTypes.Method)
                    {
                        continue;
                    }

                    builder.AppendMember(invoker.Member.Name);
                    builder.Append(" = ");

gotoLabel:
                    var value = invoker.Invoke(entity);
                    var seg = this.DbValue.GetSqlValueWidthDefault(value, token, column);

                    if (column == null || !column.IsIdentity)
                    {
                        builder.Append(seg);
                        length = builder.Length;
                        builder.Append(',');
                        builder.AppendNewLine();
                    }

                    if (column != null && column.IsKey)
                    {
                        useKey = true;
                        whereBuilder.AppendMember(invoker.Member.Name);
                        whereBuilder.Append(" = ");
                        whereBuilder.Append(seg);
                        whereBuilder.Append(" AND ");
                    }
                }

                if (!useKey)
                {
                    throw new XFrameworkException("Update<T>(T value) require entity must have key column.");
                }

                builder.Length       = length;
                whereBuilder.Length -= 5;

                builder.AppendNewLine();
                builder.Append("WHERE ");
                builder.Append(whereBuilder);
            }
            else if (uQueryInfo.Expression != null)
            {
                // SELECT 表达式
                LambdaExpression lambda = uQueryInfo.Expression as LambdaExpression;
                var        body         = lambda.Body;
                Expression expression   = null;
                if (body.NodeType == ExpressionType.MemberInit)
                {
                    var memberInit = body as MemberInitExpression;
                    var bindings   = new List <MemberBinding>(memberInit.Bindings);
                    foreach (var invoker in typeRuntime.KeyInvokers)
                    {
                        var member  = Expression.MakeMemberAccess(lambda.Parameters[0], invoker.Member);
                        var binding = Expression.Bind(invoker.Member, member);
                        if (!bindings.Any(x => x.Member == invoker.Member))
                        {
                            bindings.Add(binding);
                        }
                    }
                    expression = Expression.MemberInit(memberInit.NewExpression, bindings);
                }
                else if (body.NodeType == ExpressionType.New)
                {
                    var newExpression = body as NewExpression;
                    var bindings      = new List <MemberBinding>();
                    for (int i = 0; i < newExpression.Members.Count; i++)
                    {
                        var invoker = typeRuntime.GetInvoker(newExpression.Members[i].Name);
                        var binding = Expression.Bind(invoker.Member, newExpression.Arguments[i].Type != invoker.DataType
                            ? Expression.Convert(newExpression.Arguments[i], invoker.DataType)
                            : newExpression.Arguments[i]);
                        bindings.Add(binding);
                    }

                    foreach (var invoker in typeRuntime.KeyInvokers)
                    {
                        var member  = Expression.MakeMemberAccess(lambda.Parameters[0], invoker.Member);
                        var binding = Expression.Bind(invoker.Member, member);
                        if (!bindings.Any(x => x.Member == invoker.Member))
                        {
                            bindings.Add(binding);
                        }
                    }

                    var newExpression2 = Expression.New(typeRuntime.ConstructInvoker.Constructor);
                    expression = Expression.MemberInit(newExpression2, bindings);
                }

                // 解析查询以确定是否需要嵌套
                uQueryInfo.SelectInfo.SelectExpression = new DbExpression(DbExpressionType.Select, expression);
                var cmd = (MappingCommand)this.ParseSelectCommand <T>(uQueryInfo.SelectInfo, 1, false, null);

                if ((cmd.NavMembers != null && cmd.NavMembers.Count > 0) || uQueryInfo.SelectInfo.Joins.Count > 0)
                {
                    if (typeRuntime.KeyInvokers == null || typeRuntime.KeyInvokers.Count == 0)
                    {
                        throw new XFrameworkException("Update<T>(Expression<Func<T, object>> updateExpression) require entity must have key column.");
                    }

                    // SET 字段
                    var visitor = new SQLiteUpdateExpressionVisitor <T>(this, null, uQueryInfo, null);
                    visitor.ParseCommand = this.ParseSelectCommand;
                    visitor.Write(builder);

                    // WHERE部分
                    builder.AppendNewLine();
                    builder.Append("WHERE EXISTS");
                    visitor.VisitArgument(uQueryInfo.SelectInfo.SelectExpression.Expressions[0], true);
                }
                else
                {
                    // 直接 SQL 的 UPDATE 语法
                    TableAliasCache aliases = this.PrepareAlias <T>(uQueryInfo.SelectInfo, token);
                    var             visitor = new SQLiteUpdateExpressionVisitor <T>(this, aliases, uQueryInfo, null);
                    visitor.ParseCommand = this.ParseSelectCommand;
                    visitor.Write(builder);

                    var visitor2 = new WhereExpressionVisitor(this, null, uQueryInfo.SelectInfo.WhereExpression);
                    visitor2.Write(builder);
                }
            }

            builder.Append(';');
            return(new Command(builder.ToString(), builder.Token != null ? builder.Token.Parameters : null, System.Data.CommandType.Text));
        }
예제 #41
0
        // 创建 DELETE 命令
        protected override Command ParseDeleteCommand <T>(DbQueryableInfo_Delete <T> dQueryInfo, ResolveToken token)
        {
            ISqlBuilder     builder     = this.CreateSqlBuilder(token);
            TypeRuntimeInfo typeRuntime = TypeRuntimeInfoCache.GetRuntimeInfo <T>();

            builder.Append("DELETE FROM ");
            builder.AppendMember(typeRuntime.TableName, !typeRuntime.IsTemporary);
            builder.Append(" ");

            if (dQueryInfo.Entity != null)
            {
                if (typeRuntime.KeyInvokers == null || typeRuntime.KeyInvokers.Count == 0)
                {
                    throw new XFrameworkException("Delete<T>(T value) require entity must have key column.");
                }

                object entity = dQueryInfo.Entity;

                builder.AppendNewLine();
                builder.Append("WHERE ");

                foreach (var invoker in typeRuntime.KeyInvokers)
                {
                    var column = invoker.Column;
                    var value  = invoker.Invoke(entity);
                    var seg    = this.DbValue.GetSqlValue(value, token, column);

                    builder.AppendMember(invoker.Member.Name);
                    builder.Append(" = ");
                    builder.Append(seg);
                    builder.Append(" AND ");
                }
                builder.Length -= 5;
            }
            else if (dQueryInfo.SelectInfo != null)
            {
                LambdaExpression lambda = null;
                var dbQuery             = dQueryInfo.SourceQuery;
                if (dbQuery.DbExpressions != null && dbQuery.DbExpressions.Count > 1)
                {
                    switch (dbQuery.DbExpressions[1].DbExpressionType)
                    {
                    case DbExpressionType.Join:
                    case DbExpressionType.GroupJoin:
                    case DbExpressionType.GroupRightJoin:
                        lambda = (LambdaExpression)dbQuery.DbExpressions[1].Expressions[1];
                        break;

                    case DbExpressionType.Select:
                    case DbExpressionType.SelectMany:
                        lambda = (LambdaExpression)dbQuery.DbExpressions[1].Expressions[0];
                        break;
                    }
                }
                if (lambda == null)
                {
                    DbExpression dbExpression = dQueryInfo.SelectInfo.SelectExpression;
                    dbExpression = dQueryInfo.SelectInfo.WhereExpression;
                    if (dbExpression != null && dbExpression.Expressions != null)
                    {
                        lambda = (LambdaExpression)dbExpression.Expressions[0];
                    }
                }

                // 解析查询以确定是否需要嵌套
                var parameter  = Expression.Parameter(typeof(SQLiteRowId), lambda != null ? lambda.Parameters[0].Name : "x");
                var expression = Expression.MakeMemberAccess(parameter, (_rowIdExpression.Body as MemberExpression).Member);
                dQueryInfo.SelectInfo.SelectExpression = new DbExpression(DbExpressionType.Select, expression);
                var cmd = (MappingCommand)this.ParseSelectCommand <T>(dQueryInfo.SelectInfo, 1, false, null);
                if (token != null && token.Extendsions == null)
                {
                    token.Extendsions = new Dictionary <string, object>();
                    if (!token.Extendsions.ContainsKey("SQLiteDelete"))
                    {
                        token.Extendsions.Add("SQLiteDelete", null);
                    }
                }

                if ((cmd.NavMembers != null && cmd.NavMembers.Count > 0) || dQueryInfo.SelectInfo.Joins.Count > 0)
                {
                    cmd = (MappingCommand)this.ParseSelectCommand <T>(dQueryInfo.SelectInfo, 1, false, token);
                    builder.Append("WHERE ");
                    builder.AppendMember("RowID");
                    builder.Append(" IN(");
                    builder.AppendNewLine(cmd.CommandText);
                    builder.Append(')');
                }
                else
                {
                    TableAliasCache       aliases = this.PrepareAlias <T>(dQueryInfo.SelectInfo, token);
                    ExpressionVisitorBase visitor = null;

                    visitor = new JoinExpressionVisitor(this, aliases, dQueryInfo.SelectInfo.Joins);
                    visitor.Write(builder);

                    visitor = new WhereExpressionVisitor(this, null, dQueryInfo.SelectInfo.WhereExpression);
                    visitor.Write(builder);
                }
            }

            builder.Append(';');
            return(new Command(builder.ToString(), builder.Token != null ? builder.Token.Parameters : null, System.Data.CommandType.Text));
        }
예제 #42
0
        // 创建 INSRT 命令
        protected override Command ParseInsertCommand <T>(DbQueryableInfo_Insert <T> nQueryInfo, ResolveToken token)
        {
            ISqlBuilder     builder     = this.CreateSqlBuilder(token);
            TypeRuntimeInfo typeRuntime = TypeRuntimeInfoCache.GetRuntimeInfo <T>();
            TableAliasCache aliases     = new TableAliasCache();

            if (nQueryInfo.Entity != null)
            {
                object      entity         = nQueryInfo.Entity;
                ISqlBuilder columnsBuilder = this.CreateSqlBuilder(token);
                ISqlBuilder valuesBuilder  = this.CreateSqlBuilder(token);

                // 指定插入列
                MemberInvokerCollection invokers = typeRuntime.Invokers;
                if (nQueryInfo.EntityColumns != null && nQueryInfo.EntityColumns.Count > 0)
                {
                    invokers = new MemberInvokerCollection();
                    for (int i = 0; i < nQueryInfo.EntityColumns.Count; i++)
                    {
                        Expression curExpr = nQueryInfo.EntityColumns[i];
                        if (curExpr.NodeType == ExpressionType.Lambda)
                        {
                            curExpr = (curExpr as LambdaExpression).Body.ReduceUnary();
                        }
                        if (curExpr.NodeType != ExpressionType.MemberAccess)
                        {
                            throw new XFrameworkException("Can't read field name from expression {0}", nQueryInfo.EntityColumns[i]);
                        }

                        MemberExpression member = curExpr as MemberExpression;
                        string           name   = member.Member.Name;
                        invokers[name] = typeRuntime.Invokers[name];
                    }
                }

                foreach (var invoker in invokers)
                {
                    var column = invoker.Column;
                    if (column != null && column.NoMapped)
                    {
                        continue;
                    }
                    if (invoker.ForeignKey != null)
                    {
                        continue;
                    }
                    if (invoker.Member.MemberType == System.Reflection.MemberTypes.Method)
                    {
                        continue;
                    }

                    if (invoker != nQueryInfo.AutoIncrement)
                    {
                        columnsBuilder.AppendMember(invoker.Member.Name);
                        columnsBuilder.Append(',');

                        var    value = invoker.Invoke(entity);
                        string seg   = this.DbValue.GetSqlValueWidthDefault(value, token, column);
                        valuesBuilder.Append(seg);
                        valuesBuilder.Append(',');
                    }
                }
                columnsBuilder.Length -= 1;
                valuesBuilder.Length  -= 1;

                if (nQueryInfo.Bulk == null || !nQueryInfo.Bulk.OnlyValue)
                {
                    builder.Append("INSERT INTO ");
                    builder.AppendMember(typeRuntime.TableName, !typeRuntime.IsTemporary);
                    builder.Append('(');
                    builder.Append(columnsBuilder);
                    builder.Append(')');
                    builder.AppendNewLine();
                    builder.AppendNewTab();
                    builder.Append("VALUES");
                }

                builder.Append('(');
                builder.Append(valuesBuilder);
                builder.Append(')');
                if (nQueryInfo.Bulk != null && !nQueryInfo.Bulk.IsEndPos)
                {
                    builder.Append(",");
                }

                if (nQueryInfo.Bulk == null && nQueryInfo.AutoIncrement != null)
                {
                    builder.Append(';');
                    builder.AppendNewLine();

                    builder.AppendFormat("SELECT LAST_INSERT_ROWID()", typeRuntime.TableName, nQueryInfo.AutoIncrement.Member.Name);
                    builder.Append(" AS ");
                    builder.Append(this.QuotePrefix);
                    builder.Append(Constant.AUTOINCREMENTNAME);
                    builder.Append(this.QuoteSuffix);
                }
            }
            else if (nQueryInfo.SelectInfo != null)
            {
                builder.Append("INSERT INTO ");
                builder.AppendMember(typeRuntime.TableName, !typeRuntime.IsTemporary);
                builder.Append('(');

                int            i    = 0;
                MappingCommand cmd2 = this.ParseSelectCommandImpl(nQueryInfo.SelectInfo, 0, false, token) as MappingCommand;
                //for (int i = 0; i < seg.Columns.Count; i++)
                foreach (var column in cmd2.PickColumns)
                {
                    builder.AppendMember(column.Name);
                    if (i < cmd2.PickColumns.Count - 1)
                    {
                        builder.Append(',');
                    }
                    i++;
                }

                builder.Append(')');
                builder.AppendNewLine();
                builder.Append(cmd2.CommandText);
            }

            if (nQueryInfo.Bulk == null || nQueryInfo.Bulk.IsEndPos)
            {
                builder.Append(';');
            }
            return(new Command(builder.ToString(), builder.Token != null ? builder.Token.Parameters : null, System.Data.CommandType.Text));
        }
예제 #43
0
        // 创建 SELECT 命令
        protected override Command ResolveSelectCommand <T>(DbQueryableInfo_Select <T> dbQuery, int indent, bool isOuter, ResolveToken token)
        {
            // 说明:
            // 1.OFFSET 前必须要有 'ORDER BY',即 'Skip' 子句前必须使用 'OrderBy' 子句
            // 2.在有聚合函数的<MAX,MIN...>情况下,如果有 'Distinct' 'GroupBy' 'Skip' 'Take' 子句,则需要使用嵌套查询
            // 3.'Any' 子句将翻译成 IF EXISTS...
            // 4.分组再分页时需要使用嵌套查询,此时子查询不需要 'OrderBy' 子句,但最外层则需要
            // 5.'Skip' 'Take' 子句视为语义结束符,在其之后的子句将使用嵌套查询
            // 6.导航属性中有 1:n 关系的,需要使用嵌套查询,否则分页查询会有问题
            // 8.如果有分页,则使用嵌套
            // 9.如果有分页还有OrderBy,则使用嵌套的嵌套

            // 导航属性中有1:n关系,只统计主表
            // 例:AccountList = a.Client.AccountList,
            var subQuery = dbQuery.SubQueryInfo as DbQueryableInfo_Select <T>;

            if (dbQuery.HasMany && subQuery != null && subQuery.Aggregate != null)
            {
                dbQuery = subQuery;
            }

            bool   useStatis  = dbQuery.Aggregate != null;
            bool   useNesting = dbQuery.HasDistinct || dbQuery.GroupBy != null || dbQuery.Skip > 0 || dbQuery.Take > 0;
            string alias0     = token != null && !string.IsNullOrEmpty(token.TableAliasName) ? (token.TableAliasName + "0") : "t0";
            // 没有聚合函数或者使用 'Skip' 子句,则解析OrderBy
            // 导航属性如果使用嵌套,除非有 TOP 或者 OFFSET 子句,否则不能用ORDER BY
            bool useOrderBy = (!useStatis || dbQuery.Skip > 0) && !dbQuery.HasAny && (!dbQuery.SubQueryOfMany || (dbQuery.Skip > 0 || dbQuery.Take > 0));

            TableAliasCache aliases = this.PrepareTableAlias <T>(dbQuery, token);
            MapperCommand   cmd     = new MapperCommand(this, aliases, token)
            {
                HasMany = dbQuery.HasMany
            };
            ISqlBuilder jf = cmd.JoinFragment;
            ISqlBuilder wf = cmd.WhereFragment;

            (jf as OracleSqlBuilder).IsOuter = isOuter;

            jf.Indent = indent;

            #region 嵌套查询

            if (useStatis && useNesting)
            {
                // SELECT
                jf.Append("SELECT ");
                jf.AppendNewLine();

                // SELECT COUNT(1)
                var visitor2 = new AggregateExpressionVisitor(this, aliases, dbQuery.Aggregate, dbQuery.GroupBy, alias0);
                visitor2.Write(jf);
                cmd.AddNavMembers(visitor2.NavMembers);

                // SELECT COUNT(1) FROM
                jf.AppendNewLine();
                jf.Append("FROM ( ");

                indent   += 1;
                jf.Indent = indent;
                (jf as OracleSqlBuilder).IsOuter = false;
            }

            #endregion

            #region  择子句

            // SELECT 子句
            if (jf.Indent > 0)
            {
                jf.AppendNewLine();
            }
            jf.Append("SELECT ");

            if (dbQuery.HasAny)
            {
                jf.Append("CASE WHEN COUNT(1) = 1 THEN 1 ELSE 0 END FROM (");
                indent   += 1;
                jf.Indent = indent;
                jf.AppendNewLine();
                jf.Append("SELECT 1 ");
            }

            if (useStatis && !useNesting)
            {
                // 如果有聚合函数,并且不是嵌套的话,则直接使用SELECT <MAX,MIN...>,不需要解析选择的字段
                jf.AppendNewLine();
                var visitor2 = new AggregateExpressionVisitor(this, aliases, dbQuery.Aggregate, dbQuery.GroupBy);
                visitor2.Write(jf);
                cmd.AddNavMembers(visitor2.NavMembers);
            }
            else
            {
                // DISTINCT 子句
                if (dbQuery.HasDistinct)
                {
                    jf.Append("DISTINCT ");
                }

                #region  择字段

                if (!dbQuery.HasAny)
                {
                    // SELECT 范围
                    ISqlBuilder sf = this.CreateSqlBuilder(token);
                    sf.Indent = jf.Indent + ((dbQuery.Skip > 0 || dbQuery.Take > 0) ? 2 : 0);
                    (sf as OracleSqlBuilder).IsOuter = (dbQuery.Skip > 0 || dbQuery.Take > 0) ? false : (jf as OracleSqlBuilder).IsOuter;

                    var visitor2 = new ColumnExpressionVisitor(this, aliases, dbQuery);
                    visitor2.Write(sf);

                    cmd.PickColumns    = visitor2.PickColumns;
                    cmd.PickColumnText = visitor2.PickColumnText;
                    cmd.Navigations    = visitor2.Navigations;
                    cmd.AddNavMembers(visitor2.NavMembers);

                    // 分页,产生两层嵌套
                    if (dbQuery.Skip > 0 || dbQuery.Take > 0)
                    {
                        // 第一层嵌套
                        int index = 0;
                        jf.AppendNewLine();
                        foreach (var column in cmd.PickColumns)
                        {
                            jf.AppendMember(alias0, column.Name);
                            jf.AppendAs(column.NewName);
                            index += 1;
                            if (index < cmd.PickColumns.Count)
                            {
                                jf.Append(',');
                                jf.AppendNewLine();
                            }
                        }

                        jf.AppendNewLine();
                        jf.Append("FROM(");

                        // 第二层嵌套
                        indent   += 1;
                        isOuter   = false;
                        jf.Indent = indent;
                        (jf as OracleSqlBuilder).IsOuter = isOuter;
                        jf.AppendNewLine();

                        jf.Append("SELECT");
                        jf.AppendNewLine();

                        foreach (var column in cmd.PickColumns)
                        {
                            jf.AppendMember(alias0, column.NewName);
                            jf.AppendAs(column.NewName);
                            jf.Append(',');
                            jf.AppendNewLine();
                        }
                        jf.Append("ROWNUM AS Row_Number0");
                        jf.AppendNewLine();
                        jf.Append("FROM(");

                        // 第三层嵌套
                        indent   += 1;
                        jf.Indent = indent;
                        jf.AppendNewLine();
                        jf.Append("SELECT");
                    }

                    jf.Append(sf);
                }

                #endregion
            }

            #endregion

            #region 顺序解析

            // FROM 子句
            jf.AppendNewLine();
            jf.Append("FROM ");
            if (dbQuery.SubQueryInfo != null)
            {
                // 子查询
                jf.Append('(');
                Command cmd2 = this.ResolveSelectCommand <T>(dbQuery.SubQueryInfo as DbQueryableInfo_Select <T>, indent + 1, false, token);
                jf.Append(cmd2.CommandText);
                jf.AppendNewLine();
                jf.Append(") ");
                jf.Append(alias0);
                jf.Append(' ');
            }
            else
            {
                var typeRuntime = TypeRuntimeInfoCache.GetRuntimeInfo(dbQuery.FromEntityType);
                jf.AppendMember(typeRuntime.TableName, !typeRuntime.IsTemporary);
                jf.Append(' ');
                jf.Append(alias0);
                jf.Append(' ');
            }

            // LEFT<INNER> JOIN 子句
            ExpressionVisitorBase visitor = new JoinExpressionVisitor(this, aliases, dbQuery.Joins);
            visitor.Write(jf);

            wf.Indent = jf.Indent;

            // WHERE 子句
            visitor = new WhereExpressionVisitor(this, aliases, dbQuery.Condtion);
            visitor.Write(wf);
            cmd.AddNavMembers(visitor.NavMembers);

            // GROUP BY 子句
            visitor = new GroupByExpressionVisitor(this, aliases, dbQuery.GroupBy);
            visitor.Write(wf);
            cmd.AddNavMembers(visitor.NavMembers);

            // HAVING 子句
            visitor = new HavingExpressionVisitor(this, aliases, dbQuery.Having, dbQuery.GroupBy);
            visitor.Write(wf);
            cmd.AddNavMembers(visitor.NavMembers);

            // ORDER 子句
            if (dbQuery.OrderBys.Count > 0 && useOrderBy)
            {
                visitor = new OrderByExpressionVisitor(this, aliases, dbQuery.OrderBys, dbQuery.GroupBy);
                visitor.Write(wf);
                cmd.AddNavMembers(visitor.NavMembers);
            }

            #endregion

            #region 嵌套查询

            if (useStatis && useNesting)
            {
                cmd.CombineFragments();
                indent   -= 1;
                jf.Indent = indent;
                jf.AppendNewLine();
                jf.Append(") ");
                jf.Append(alias0);
            }

            #endregion

            #region 嵌套导航

            // TODO Include 从表,没分页,OrderBy 报错
            if (dbQuery.HasMany && subQuery != null && subQuery.OrderBys.Count > 0 && subQuery.Aggregate == null && !(subQuery.Skip > 0 || subQuery.Take > 0))
            {
                // OrderBy("a.CloudServer.CloudServerName");
                cmd.CombineFragments();
                visitor = new OrderByExpressionVisitor(this, aliases, subQuery.OrderBys);//, null, "t0");
                visitor.Write(jf);
            }

            #endregion

            #region 并集查询

            // UNION 子句
            if (dbQuery.Unions != null && dbQuery.Unions.Count > 0)
            {
                cmd.CombineFragments();
                for (int index = 0; index < dbQuery.Unions.Count; index++)
                {
                    jf.AppendNewLine();
                    jf.Append("UNION ALL");
                    if (indent == 0)
                    {
                        jf.AppendNewLine();
                    }
                    Command cmd2 = this.ResolveSelectCommand <T>(dbQuery.Unions[index] as DbQueryableInfo_Select <T>, indent, isOuter, token);
                    jf.Append(cmd2.CommandText);
                }
            }

            #endregion

            #region 分页查询

            if (dbQuery.Take > 0 || dbQuery.Skip > 0)
            {
                // 合并 WHERE
                cmd.CombineFragments();

                indent   -= 1;
                jf.Indent = indent;
                jf.AppendNewLine();
                jf.Append(") ");
                jf.Append(alias0);

                indent   -= 1;
                jf.Indent = indent;
                jf.AppendNewLine();
                jf.Append(") ");
                jf.Append(alias0);

                jf.AppendNewLine();
                jf.Append("WHERE ");
                if (dbQuery.Skip > 0)
                {
                    jf.AppendMember(alias0, "Row_Number0");
                    jf.Append(" > ");
                    jf.Append(this.DbValue.GetSqlValue(dbQuery.Skip, token));
                }
                if (dbQuery.Take > 0)
                {
                    if (dbQuery.Skip > 0)
                    {
                        jf.Append(" AND ");
                    }
                    jf.AppendMember(alias0, "Row_Number0");
                    jf.Append(" <= ");
                    jf.Append(this.DbValue.GetSqlValue((dbQuery.Skip + dbQuery.Take), token));
                }
            }

            #endregion

            #region Any 子句

            // 'Any' 子句
            if (dbQuery.HasAny)
            {
                // 产生 WHERE 子句
                cmd.CombineFragments();
                // 如果没有分页,则显式指定只查一笔记录
                if (dbQuery.Take == 0 && dbQuery.Skip == 0)
                {
                    if (dbQuery.Condtion != null && dbQuery.Condtion.Expressions != null)
                    {
                        jf.Append(" AND ROWNUM <= 1");
                    }
                    else
                    {
                        jf.AppendNewLine();
                        jf.Append("WHERE  ROWNUM <= 1");
                    }
                }

                indent   -= 1;
                jf.Indent = indent;
                jf.AppendNewLine();
                jf.Append(") ");
                jf.Append(alias0);
            }

            #endregion

            return(cmd);
        }
            // 添加导航属性关联
            protected override void AppendNavigation()
            {
                if (base.NavMembers == null || base.NavMembers.Count == 0)
                {
                    return;
                }

                // 如果有一对多的导航属性,肯定会产生嵌套查询。那么内层查询别名肯定是t0,所以需要清掉
                if (this.HasMany)
                {
                    _aliases = new TableAliasCache(_aliases.Declared);
                }
                //开始产生LEFT JOIN 子句
                ISqlBuilder builder = this.JoinFragment;

                foreach (var kvp in base.NavMembers)
                {
                    string              key         = kvp.Key;
                    MemberExpression    m           = kvp.Value;
                    TypeRuntimeInfo     typeRuntime = TypeRuntimeInfoCache.GetRuntimeInfo(m.Expression.Type);
                    ForeignKeyAttribute attribute   = typeRuntime.GetInvokerAttribute <ForeignKeyAttribute>(m.Member.Name);

                    string innerKey   = string.Empty;
                    string outerKey   = key;
                    string innerAlias = string.Empty;

                    if (!m.Expression.Acceptable())
                    {
                        innerKey = m.Expression.NodeType == ExpressionType.Parameter
                            ? (m.Expression as ParameterExpression).Name
                            : (m.Expression as MemberExpression).Member.Name;
                    }
                    else
                    {
                        MemberExpression mLeft = null;
                        if (m.Expression.NodeType == ExpressionType.MemberAccess)
                        {
                            mLeft = m.Expression as MemberExpression;
                        }
                        else if (m.Expression.NodeType == ExpressionType.Call)
                        {
                            mLeft = (m.Expression as MethodCallExpression).Object as MemberExpression;
                        }
                        string name = TypeRuntimeInfoCache.GetRuntimeInfo(mLeft.Type).TableName;
                        innerAlias = _aliases.GetJoinTableAlias(name);

                        if (string.IsNullOrEmpty(innerAlias))
                        {
                            string keyLeft = mLeft.GetKeyWidthoutAnonymous();
                            if (base.NavMembers.ContainsKey(keyLeft))
                            {
                                innerKey = keyLeft;
                            }
                            innerAlias = _aliases.GetNavigationTableAlias(innerKey);
                        }
                    }

                    string alias1 = !string.IsNullOrEmpty(innerAlias) ? innerAlias : _aliases.GetTableAlias(innerKey);
                    string alias2 = _aliases.GetNavigationTableAlias(outerKey);


                    builder.AppendNewLine();
                    builder.Append("LEFT JOIN ");
                    Type type = m.Type;
                    if (type.IsGenericType)
                    {
                        type = type.GetGenericArguments()[0];
                    }
                    var typeRuntime2 = TypeRuntimeInfoCache.GetRuntimeInfo(type);
                    builder.AppendMember(typeRuntime2.TableName, !typeRuntime2.IsTemporary);
                    builder.Append(" ");
                    builder.Append(alias2);

                    bool withNoLock = !typeRuntime2.IsTemporary && _context.NoLock && !string.IsNullOrEmpty(_provider.WidthNoLock);
                    if (withNoLock)
                    {
                        builder.Append(' ');
                        builder.Append(_provider.WidthNoLock);
                    }

                    builder.Append(" ON ");
                    for (int i = 0; i < attribute.InnerKeys.Length; i++)
                    {
                        builder.Append(alias1);
                        builder.Append('.');
                        builder.AppendMember(attribute.InnerKeys[i]);
                        builder.Append(" = ");
                        builder.Append(alias2);
                        builder.Append('.');
                        builder.AppendMember(attribute.OuterKeys[i]);

                        if (i < attribute.InnerKeys.Length - 1)
                        {
                            builder.Append(" AND ");
                        }
                    }
                }
            }
            // LEFT OR INNER JOIN
            private void AppendLfInJoin(ISqlBuilder builder, DbExpression dbExpression, TableAliasCache aliases)
            {
                bool withNoLock = false;

                builder.Append(' ');
                IDbQueryable dbQuery = (IDbQueryable)((dbExpression.Expressions[0] as ConstantExpression).Value);

                if (dbQuery.DbExpressions.Count == 1 && dbQuery.DbExpressions[0].DbExpressionType == DbExpressionType.GetTable)
                {
                    Type type        = dbExpression.Expressions[0].Type.GetGenericArguments()[0];
                    var  typeRuntime = TypeRuntimeInfoCache.GetRuntimeInfo(type);
                    builder.AppendMember(typeRuntime.TableName, !typeRuntime.IsTemporary);

                    withNoLock = !typeRuntime.IsTemporary && _context.NoLock && !string.IsNullOrEmpty(_provider.WidthNoLock);
                }
                else
                {
                    // 嵌套
                    var cmd = dbQuery.Resolve(builder.Indent + 1, false, builder.Token);
                    builder.Append("(");
                    builder.Append(cmd.CommandText);
                    builder.AppendNewLine();
                    builder.Append(')');
                }


                var left  = dbExpression.Expressions[1] as LambdaExpression;
                var right = dbExpression.Expressions[2] as LambdaExpression;

                // t0(t1)
                string alias = !(left.Body.NodeType == ExpressionType.New || left.Body.NodeType == ExpressionType.MemberInit)
                    ? aliases.GetTableAlias(dbExpression.Expressions[2])
                    : aliases.GetTableAlias(right.Parameters[0]);

                builder.Append(' ');
                builder.Append(alias);
                builder.Append(' ');

                if (withNoLock)
                {
                    builder.Append(_provider.WidthNoLock);
                    builder.Append(' ');
                }

                // ON a.Name = b.Name AND a.Id = b.Id
                builder.Append("ON ");

                if (left.Body.NodeType == ExpressionType.New)
                {
                    var body1 = left.Body as NewExpression;
                    var body2 = right.Body as NewExpression;

                    for (int index = 0; index < body1.Arguments.Count; ++index)
                    {
                        builder.AppendMember(aliases, body1.Arguments[index]);
                        builder.Append(" = ");
                        builder.AppendMember(aliases, body2.Arguments[index]);
                        if (index < body1.Arguments.Count - 1)
                        {
                            builder.Append(" AND ");
                        }
                    }
                }
                else if (left.Body.NodeType == ExpressionType.MemberInit)
                {
                    var body1 = left.Body as MemberInitExpression;
                    var body2 = right.Body as MemberInitExpression;

                    for (int index = 0; index < body1.Bindings.Count; ++index)
                    {
                        builder.AppendMember(aliases, (body1.Bindings[index] as MemberAssignment).Expression);
                        builder.Append(" = ");
                        builder.AppendMember(aliases, (body2.Bindings[index] as MemberAssignment).Expression);
                        if (index < body1.Bindings.Count - 1)
                        {
                            builder.Append(" AND ");
                        }
                    }
                }
                else
                {
                    builder.AppendMember(aliases, left.Body.ReduceUnary());
                    builder.Append(" = ");
                    builder.AppendMember(aliases, right.Body.ReduceUnary());
                }
            }
 protected override string GetDescription(SqlCaluseBuilderItemWithData builderItem, ISqlBuilder builder)
 {
     return(builderItem.Data.ToString());
 }
        // 创建 INSRT 命令
        protected override Command ResolveInsertCommand <T>(DbQueryableInfo_Insert <T> dbQuery, ResolveToken token)
        {
            TableAliasCache aliases     = new TableAliasCache();
            ISqlBuilder     builder     = this.CreateSqlBuilder(token);
            TypeRuntimeInfo typeRuntime = TypeRuntimeInfoCache.GetRuntimeInfo <T>();

            if (dbQuery.Entity != null)
            {
                object      entity         = dbQuery.Entity;
                ISqlBuilder columnsBuilder = this.CreateSqlBuilder(token);
                ISqlBuilder valuesBuilder  = this.CreateSqlBuilder(token);

                // 指定插入列
                MemberInvokerCollection invokers = typeRuntime.Invokers;
                if (dbQuery.EntityColumns != null && dbQuery.EntityColumns.Count > 0)
                {
                    invokers = new MemberInvokerCollection();
                    for (int i = 0; i < dbQuery.EntityColumns.Count; i++)
                    {
                        Expression curExpr = dbQuery.EntityColumns[i];
                        if (curExpr.NodeType == ExpressionType.Lambda)
                        {
                            curExpr = (curExpr as LambdaExpression).Body.ReduceUnary();
                        }
                        if (curExpr.NodeType != ExpressionType.MemberAccess)
                        {
                            throw new XFrameworkException("ERR {0}: Only support MemberAccess expression.", dbQuery.EntityColumns[i]);
                        }

                        MemberExpression member = curExpr as MemberExpression;
                        string           name   = member.Member.Name;
                        invokers[name] = typeRuntime.Invokers[name];
                    }
                }

                foreach (var invoker in invokers)
                {
                    var column = invoker.Column;
                    if (column != null && column.NoMapped)
                    {
                        continue;
                    }
                    if (invoker.ForeignKey != null)
                    {
                        continue;
                    }
                    if (invoker.Column != null && column.DbType is SqlDbType && (SqlDbType)column.DbType == SqlDbType.Timestamp)
                    {
                        continue;                                                                                                          // 行版本号
                    }
                    if (invoker.Member.MemberType == System.Reflection.MemberTypes.Method)
                    {
                        continue;
                    }

                    if (invoker != dbQuery.AutoIncrement)
                    {
                        columnsBuilder.AppendMember(invoker.Member.Name);
                        columnsBuilder.Append(',');

                        var    value = invoker.Invoke(entity);
                        string seg   = this.DbValue.GetSqlValueWidthDefault(value, token, column);
                        valuesBuilder.Append(seg);
                        valuesBuilder.Append(',');
                    }
                }

                columnsBuilder.Length -= 1;
                valuesBuilder.Length  -= 1;

                if (dbQuery.Bulk == null || !dbQuery.Bulk.OnlyValue)
                {
                    builder.Append("INSERT INTO ");
                    builder.AppendMember(typeRuntime.TableName, !typeRuntime.IsTemporary);
                    builder.Append('(');
                    builder.Append(columnsBuilder);
                    builder.Append(')');
                    builder.AppendNewLine();
                    builder.AppendNewTab();
                    builder.Append("VALUES");
                }

                builder.Append('(');
                builder.Append(valuesBuilder);
                builder.Append(')');
                if (dbQuery.Bulk != null && !dbQuery.Bulk.IsEndPos)
                {
                    builder.Append(",");
                }

                if (dbQuery.Bulk == null && dbQuery.AutoIncrement != null)
                {
                    builder.AppendNewLine();
                    builder.Append("SELECT SCOPE_IDENTITY()");
                    builder.AppendAs(Constant.AUTOINCREMENTNAME);
                }
            }
            else if (dbQuery.SelectInfo != null)
            {
                builder.Append("INSERT INTO ");
                builder.AppendMember(typeRuntime.TableName, !typeRuntime.IsTemporary);
                builder.Append('(');

                int           i    = 0;
                MapperCommand cmd2 = this.ResolveSelectCommand(dbQuery.SelectInfo, 0, true, token) as MapperCommand;
                foreach (Column column in cmd2.PickColumns)
                {
                    builder.AppendMember(column.NewName);
                    if (i < cmd2.PickColumns.Count - 1)
                    {
                        builder.Append(',');
                    }
                    i++;
                }

                builder.Append(')');
                builder.AppendNewLine();
                builder.Append(cmd2.CommandText);
            }

            return(new Command(builder.ToString(), builder.Token != null ? builder.Token.Parameters : null, System.Data.CommandType.Text));
        }
예제 #48
0
 public BaseRepository()
 {
     _sqlBuilder = new SqlBuilderFactory <T>(this).CreateBuilder();
 }
예제 #49
0
 /// <summary>
 /// Initializes a new instance of the <see cref="SqlExpression{TEntity}"/>
 /// class using the specified <see cref="ISqlBuilder"/>.
 /// </summary>
 /// <param name="sqlBuilder">The <see cref="ISqlBuilder"/> instance.</param>
 public SqlExpression(ISqlBuilder sqlBuilder)
 {
     SqlBuilder = sqlBuilder;
 }
예제 #50
0
        public void Render(ISqlBuilder builder, params Expression[] args)
        {
            if (args.Length != 2)
            {
                throw new ArgumentException(string.Format(Res.ArgumentCountError, "datediff", "", "2"));
            }
            switch (Type)
            {
            case DateParts.Year:
                builder.Append(" CAST(STRFTIME('%Y',");
                builder.Visit(args[1]);
                builder.Append(") AS INT) - ");
                builder.Append(" CAST(STRFTIME('%Y',");
                builder.Visit(args[0]);
                builder.Append(") AS INT)");
                break;

            case DateParts.Month:
                builder.Append(" (CAST(STRFTIME('%Y',");
                builder.Visit(args[1]);
                builder.Append(") AS INT) - ");
                builder.Append(" CAST(STRFTIME('%Y',");
                builder.Visit(args[0]);
                builder.Append(") AS INT))*12");
                builder.Append(" + ");
                builder.Append(" CAST(STRFTIME('%m',");
                builder.Visit(args[1]);
                builder.Append(") AS INT) - ");
                builder.Append(" CAST(STRFTIME('%m',");
                builder.Visit(args[0]);
                builder.Append(") AS INT)");
                break;

            case DateParts.Day:
                builder.Append(" FLOOR((");
                builder.Append(" JULIANDAY(");
                builder.Visit(args[1]);
                builder.Append(") - ");
                builder.Append(" JULIANDAY(");
                builder.Visit(args[0]);
                builder.Append(")))");

                break;

            case DateParts.Hour:
                builder.Append(" FLOOR((");
                builder.Append(" JULIANDAY(");
                builder.Visit(args[1]);
                builder.Append(") - ");
                builder.Append(" JULIANDAY(");
                builder.Visit(args[0]);
                builder.Append("))*24)");
                break;

            case DateParts.Minute:
                builder.Append(" FLOOR((");
                builder.Append(" JULIANDAY(");
                builder.Visit(args[1]);
                builder.Append(") - ");
                builder.Append(" JULIANDAY(");
                builder.Visit(args[0]);
                builder.Append("))*24*60)");
                break;

            case DateParts.Second:
                builder.Append(" FLOOR((");
                builder.Append(" JULIANDAY(");
                builder.Visit(args[1]);
                builder.Append(") - ");
                builder.Append(" JULIANDAY(");
                builder.Visit(args[0]);
                builder.Append("))*24*60*60)");
                break;

            case DateParts.Millisecond:
                builder.Append(" FLOOR((");
                builder.Append(" JULIANDAY(");
                builder.Visit(args[1]);
                builder.Append(") - ");
                builder.Append(" JULIANDAY(");
                builder.Visit(args[0]);
                builder.Append("))*24*60*60*1000)");
                break;

            case DateParts.Week:
                builder.Append(" FLOOR(ROUND((");
                builder.Append(" JULIANDAY(");
                builder.Visit(args[1]);
                builder.Append(") - ");
                builder.Append(" JULIANDAY(");
                builder.Visit(args[0]);
                builder.Append(")) , 0)/7)");
                break;
            }
        }
        /// <summary>
        /// 设置子查询条件
        /// </summary>
        /// <typeparam name="TEntity">实体类型</typeparam>
        /// <param name="sqlQuery">Sql查询对象</param>
        /// <param name="expression">列名表达式,范例:t => t.Name</param>
        /// <param name="builder">子查询Sql生成器</param>
        /// <param name="condition">该值为true时添加查询条件,否则忽略</param>
        /// <param name="operator">运算符</param>
        public static ISqlQuery WhereIf <TEntity>(this ISqlQuery sqlQuery, Expression <Func <TEntity, object> > expression, ISqlBuilder builder,
                                                  bool condition, Operator @operator = Operator.Equal) where TEntity : class
        {
            var sqlBuilder = sqlQuery.GetBuilder();

            sqlBuilder.WhereIf(expression, builder, condition, @operator);
            return(sqlQuery);
        }
예제 #52
0
 /// <summary>
 /// 初始化Sql查询对象
 /// </summary>
 /// <param name="sqlBuilder">Sql生成器</param>
 /// <param name="database">数据库</param>
 protected SqlQueryBase(ISqlBuilder sqlBuilder, IDatabase database = null)
 {
     Builder   = sqlBuilder ?? throw new ArgumentNullException(nameof(sqlBuilder));
     _database = database;
 }
예제 #53
0
 protected override string GetDescription(SqlCaluseBuilderItemWithData builderItem, ISqlBuilder builder)
 {
     return("NULL");
 }
예제 #54
0
 /// <summary>
 /// 设置查询条件
 /// </summary>
 /// <param name="builder">Sql生成器</param>
 /// <param name="expression">查询条件表达式,范例:t => t.Name.Contains("a") &amp;&amp; ( t.Code == "b" || t.Age > 1 )</param>
 /// <param name="condition">该值为true时添加查询条件,否则忽略</param>
 public static ISqlBuilder WhereIf <TEntity>(this ISqlBuilder builder, Expression <Func <TEntity, bool> > expression, bool condition) where TEntity : class
 {
     return(condition ? builder.Where(expression) : builder);
 }
예제 #55
0
 /// <summary>
 /// 设置Not In条件
 /// </summary>
 /// <param name="source">源</param>
 /// <param name="expression">列名表达式</param>
 /// <param name="builder">Sql生成器</param>
 public static ISqlBuilder NotIn <TEntity>(this ISqlBuilder source, Expression <Func <TEntity, object> > expression, ISqlBuilder builder) where TEntity : class
 {
     if (source == null)
     {
         throw new ArgumentNullException(nameof(source));
     }
     if (source is IClauseAccessor accessor)
     {
         accessor.WhereClause.NotIn(expression, builder);
     }
     return(source);
 }
예제 #56
0
        // 创建 UPDATE 命令
        protected override Command ResolveUpdateCommand <T>(DbQueryableInfo_Update <T> dbQuery, ResolveToken token)
        {
            ISqlBuilder builder     = this.CreateSqlBuilder(token);
            var         typeRuntime = TypeRuntimeInfoCache.GetRuntimeInfo <T>();

            builder.Append("UPDATE ");
            builder.AppendMember(typeRuntime.TableName, !typeRuntime.IsTemporary);
            builder.Append(" t0 SET");
            builder.AppendNewLine();

            if (dbQuery.Entity != null)
            {
                object      entity       = dbQuery.Entity;
                ISqlBuilder whereBuilder = this.CreateSqlBuilder(token);
                bool        useKey       = false;
                int         length       = 0;


                foreach (var invoker in typeRuntime.Invokers)
                {
                    var column = invoker.Column;
                    if (column != null && column.IsIdentity)
                    {
                        goto gotoLabel;                                      // fix issue# 自增列同时又是主键
                    }
                    if (column != null && column.NoMapped)
                    {
                        continue;
                    }
                    if (invoker.ForeignKey != null)
                    {
                        continue;
                    }
                    if (invoker.Member.MemberType == System.Reflection.MemberTypes.Method)
                    {
                        continue;
                    }

                    builder.AppendMember(invoker.Member.Name);
                    builder.Append(" = ");

gotoLabel:

                    if (column == null || !column.IsIdentity)
                    {
                        var value = invoker.Invoke(entity);
                        var seg   = this.DbValue.GetSqlValueWidthDefault(value, token, column);

                        builder.Append(seg);
                        length = builder.Length;
                        builder.Append(',');
                        builder.AppendNewLine();
                    }

                    if (column != null && column.IsKey)
                    {
                        useKey = true;
                    }
                }

                if (!useKey)
                {
                    throw new XFrameworkException("Update<T>(T value) require T must have key column.");
                }


                // ORACLE 需要注意参数顺序问题
                int index = -1;
                foreach (var invoker in typeRuntime.KeyInvokers)
                {
                    var column = invoker.Column;
                    var value  = invoker.Invoke(entity);
                    var seg    = this.DbValue.GetSqlValueWidthDefault(value, token, column);
                    index += 1;

                    whereBuilder.AppendMember(invoker.Member.Name);
                    whereBuilder.Append(" = ");
                    whereBuilder.Append(seg);
                    if (index < typeRuntime.KeyInvokers.Count - 1)
                    {
                        whereBuilder.Append(" AND ");
                    }
                }

                builder.Length = length;
                builder.AppendNewLine();
                builder.Append("WHERE ");
                builder.Append(whereBuilder);
            }
            else if (dbQuery.Expression != null)
            {
                // SELECT 表达式
                LambdaExpression lambda = dbQuery.Expression as LambdaExpression;
                var        body         = lambda.Body;
                Expression expression   = null;
                if (body.NodeType == ExpressionType.MemberInit)
                {
                    var memberInit = body as MemberInitExpression;
                    var bindings   = new List <MemberBinding>(memberInit.Bindings);
                    foreach (var invoker in typeRuntime.KeyInvokers)
                    {
                        var member  = Expression.MakeMemberAccess(lambda.Parameters[0], invoker.Member);
                        var binding = Expression.Bind(invoker.Member, member);
                        if (!bindings.Any(x => x.Member == invoker.Member))
                        {
                            bindings.Add(binding);
                        }
                    }
                    expression = Expression.MemberInit(memberInit.NewExpression, bindings);
                }
                else if (body.NodeType == ExpressionType.New)
                {
                    var newExpression = body as NewExpression;
                    var bindings      = new List <MemberBinding>();
                    for (int i = 0; i < newExpression.Members.Count; i++)
                    {
                        var invoker = typeRuntime.GetInvoker(newExpression.Members[i].Name);
                        var binding = Expression.Bind(invoker.Member, newExpression.Arguments[i].Type != invoker.DataType
                            ? Expression.Convert(newExpression.Arguments[i], invoker.DataType)
                            : newExpression.Arguments[i]);
                        bindings.Add(binding);
                    }

                    foreach (var invoker in typeRuntime.KeyInvokers)
                    {
                        var member  = Expression.MakeMemberAccess(lambda.Parameters[0], invoker.Member);
                        var binding = Expression.Bind(invoker.Member, member);
                        if (!bindings.Any(x => x.Member == invoker.Member))
                        {
                            bindings.Add(binding);
                        }
                    }

                    var newExpression2 = Expression.New(typeRuntime.ConstructInvoker.Constructor);
                    expression = Expression.MemberInit(newExpression2, bindings);
                }

                // 解析查询以确定是否需要嵌套
                dbQuery.SelectInfo.Select = new DbExpression(DbExpressionType.Select, expression);
                var cmd = (MapperCommand)this.ResolveSelectCommand <T>(dbQuery.SelectInfo, 1, false, null);//, token);

                if ((cmd.NavMembers != null && cmd.NavMembers.Count > 0) || dbQuery.SelectInfo.Joins.Count > 0)
                {
                    // 无法使用 DISTINCT, GROUP BY 等子句从视图中选择 ROWID 或采样。UPDATE 不能用rowid
                    // 有导航属性或者关联查询,使用 MERGE INTO 语法。要求必须有主键

                    if (typeRuntime.KeyInvokers == null || typeRuntime.KeyInvokers.Count == 0)
                    {
                        throw new XFrameworkException("Update<T>(Expression<Func<T, object>> updateExpression) require entity must have key column.");
                    }

                    builder.Length = 0;
                    builder.Append("MERGE INTO ");
                    builder.AppendMember(typeRuntime.TableName, !typeRuntime.IsTemporary);
                    builder.AppendNewLine(" t0");
                    builder.Append("USING (");

                    cmd = (MapperCommand)this.ResolveSelectCommand <T>(dbQuery.SelectInfo, 1, false, token);
                    builder.AppendNewLine(cmd.CommandText);
                    builder.Append(") t1 ON (");
                    foreach (var invoker in typeRuntime.KeyInvokers)
                    {
                        builder.AppendMember("t0", invoker.Name);
                        builder.Append(" = ");
                        builder.AppendMember("t1", invoker.Name);
                        builder.Append(" AND ");
                    }
                    builder.Length -= 5;
                    builder.Append(')');

                    // UPDATE
                    builder.AppendNewLine();
                    builder.AppendNewLine("WHEN MATCHED THEN UPDATE SET ");

                    // SET 字段
                    var visitor = new OracleUpdateExpressionVisitor(this, null, dbQuery.Expression);
                    visitor.Write(builder);
                }
                else
                {
                    // 直接 SQL 的 UPDATE 语法
                    TableAliasCache       aliases = this.PrepareTableAlias <T>(dbQuery.SelectInfo, token);
                    ExpressionVisitorBase visitor = null;
                    visitor = new UpdateExpressionVisitor(this, aliases, dbQuery.Expression);
                    visitor.Write(builder);

                    visitor = new WhereExpressionVisitor(this, aliases, dbQuery.SelectInfo.Condtion);
                    visitor.Write(builder);
                }
            }

            builder.Append(';');
            return(new Command(builder.ToString(), builder.Token != null ? builder.Token.Parameters : null, System.Data.CommandType.Text));
        }
예제 #57
0
 /// <summary>
 /// 初始化From子句
 /// </summary>
 /// <param name="builder">Sql生成器</param>
 /// <param name="dialect">方言</param>
 /// <param name="resolver">实体解析器</param>
 /// <param name="register">实体别名注册器</param>
 /// <param name="tableDatabase">表数据库</param>
 /// <param name="table">表</param>
 public OracleFromClause(ISqlBuilder builder, IDialect dialect, IEntityResolver resolver, IEntityAliasRegister register, ITableDatabase tableDatabase, SqlItem table = null)
     : base(builder, dialect, resolver, register, tableDatabase, table)
 {
 }
예제 #58
0
 /// <summary>
 /// Register a builder, you can only have one builder per application.
 /// </summary>
 /// <param name="sqlBuilder">The builder.</param>
 /// <returns>The builder.</returns>
 public static ISqlBuilder Register(ISqlBuilder sqlBuilder)
 {
     return(Register(sqlBuilder, false));
 }
예제 #59
0
        // 创建 SELECT 命令
        Command ParseSelectCommandImpl <T>(DbQueryableInfo_Select <T> sQueryInfo, int indent, bool isOuter, ResolveToken token)
        {
            // 说明:
            // 1.OFFSET 前必须要有 'ORDER BY',即 'Skip' 子句前必须使用 'OrderBy' 子句
            // 2.在有统计函数的<MAX,MIN...>情况下,如果有 'Distinct' 'GroupBy' 'Skip' 'Take' 子句,则需要使用嵌套查询
            // 3.'Any' 子句将翻译成 IF EXISTS...
            // 4.分组再分页时需要使用嵌套查询,此时子查询不需要 'OrderBy' 子句,但最外层则需要
            // 5.'Skip' 'Take' 子句视为语义结束符,在其之后的子句将使用嵌套查询
            // 6.导航属性中有 1:n 关系的,需要使用嵌套查询,否则分页查询会有问题


            // 导航属性中有1:n关系,只统计主表
            // 例:AccountList = a.Client.AccountList,
            DbQueryableInfo_Select <T> subQuery = sQueryInfo.SubQueryInfo as DbQueryableInfo_Select <T>;

            if (sQueryInfo.HasMany && subQuery != null && subQuery.StatisExpression != null)
            {
                sQueryInfo = subQuery;
            }

            bool   useStatis  = sQueryInfo.StatisExpression != null;
            bool   useNesting = sQueryInfo.HasDistinct || sQueryInfo.GroupByExpression != null || sQueryInfo.Skip > 0 || sQueryInfo.Take > 0;
            string alias0     = token != null && !string.IsNullOrEmpty(token.TableAliasName) ? (token.TableAliasName + "0") : "t0";
            // 没有统计函数或者使用 'Skip' 子句,则解析OrderBy
            // 导航属性如果使用嵌套,除非有 TOP 或者 OFFSET 子句,否则不能用ORDER BY
            bool useOrderBy = (!useStatis || sQueryInfo.Skip > 0) && !sQueryInfo.HasAny && (!sQueryInfo.SubQueryByMany || (sQueryInfo.Skip > 0 || sQueryInfo.Take > 0));

            IDbQueryable    dbQueryable = sQueryInfo.SourceQuery;
            TableAliasCache aliases     = this.PrepareAlias <T>(sQueryInfo, token);
            MappingCommand  cmd         = new MappingCommand(this, aliases, token)
            {
                HasMany = sQueryInfo.HasMany
            };
            ISqlBuilder jf = cmd.JoinFragment;
            ISqlBuilder wf = cmd.WhereFragment;

            jf.Indent = indent;

            #region 嵌套查询

            if (useStatis && useNesting)
            {
                // SELECT
                jf.Append("SELECT ");
                jf.AppendNewLine();

                // SELECT COUNT(1)
                var visitor2 = new StatisExpressionVisitor(this, aliases, sQueryInfo.StatisExpression, sQueryInfo.GroupByExpression, alias0);
                visitor2.Write(jf);
                cmd.AddNavMembers(visitor2.NavMembers);

                // SELECT COUNT(1) FROM
                jf.AppendNewLine();
                jf.Append("FROM ( ");

                indent   += 1;
                jf.Indent = indent;
            }

            #endregion

            #region  择子句

            // SELECT 子句
            if (jf.Indent > 0)
            {
                jf.AppendNewLine();
            }
            jf.Append("SELECT ");

            if (sQueryInfo.HasAny)
            {
                jf.Append("CASE WHEN COUNT(1) = 1 THEN 1 ELSE 0 END FROM (");
                indent   += 1;
                jf.Indent = indent;
                jf.AppendNewLine();
                jf.Append("SELECT 1 ");
            }

            if (useStatis && !useNesting)
            {
                // 如果有统计函数,并且不是嵌套的话,则直接使用SELECT <MAX,MIN...>,不需要解析选择的字段
                jf.AppendNewLine();
                var visitor2 = new StatisExpressionVisitor(this, aliases, sQueryInfo.StatisExpression, sQueryInfo.GroupByExpression);
                visitor2.Write(jf);
                cmd.AddNavMembers(visitor2.NavMembers);
            }
            else
            {
                // DISTINCT 子句
                if (sQueryInfo.HasDistinct)
                {
                    jf.Append("DISTINCT ");
                }

                #region  择字段

                if (!sQueryInfo.HasAny)
                {
                    // SELECT 范围
                    var visitor2 = new ColumnExpressionVisitor(this, aliases, sQueryInfo);
                    visitor2.Write(jf);

                    cmd.PickColumns    = visitor2.PickColumns;
                    cmd.PickColumnText = visitor2.PickColumnText;
                    cmd.Navigations    = visitor2.Navigations;
                    cmd.AddNavMembers(visitor2.NavMembers);
                }

                #endregion
            }

            #endregion

            #region 顺序解析

            // FROM 子句
            jf.AppendNewLine();
            jf.Append("FROM ");
            if (sQueryInfo.SubQueryInfo != null)
            {
                // 子查询
                jf.Append('(');
                Command cmd2 = this.ParseSelectCommandImpl <T>(sQueryInfo.SubQueryInfo as DbQueryableInfo_Select <T>, indent + 1, false, token);
                jf.Append(cmd2.CommandText);
                jf.AppendNewLine();
                jf.Append(") ");
                jf.Append(alias0);
                jf.Append(' ');
            }
            else
            {
                var typeRuntime = TypeRuntimeInfoCache.GetRuntimeInfo(sQueryInfo.FromType);
                jf.AppendMember(typeRuntime.TableName, !typeRuntime.IsTemporary);
                jf.Append(' ');
                jf.Append(alias0);
                jf.Append(' ');
            }

            // LEFT<INNER> JOIN 子句
            ExpressionVisitorBase visitor = new JoinExpressionVisitor(this, aliases, sQueryInfo.Joins);
            visitor.Write(jf);

            wf.Indent = jf.Indent;

            // WHERE 子句
            visitor = new WhereExpressionVisitor(this, aliases, sQueryInfo.WhereExpression);
            visitor.Write(wf);
            cmd.AddNavMembers(visitor.NavMembers);

            // GROUP BY 子句
            visitor = new GroupByExpressionVisitor(this, aliases, sQueryInfo.GroupByExpression);
            visitor.Write(wf);
            cmd.AddNavMembers(visitor.NavMembers);

            // HAVING 子句
            visitor = new HavingExpressionVisitor(this, aliases, sQueryInfo.HavingExpression, sQueryInfo.GroupByExpression);
            visitor.Write(wf);
            cmd.AddNavMembers(visitor.NavMembers);

            // ORDER 子句
            if (sQueryInfo.OrderBys.Count > 0 && useOrderBy)
            {
                visitor = new OrderByExpressionVisitor(this, aliases, sQueryInfo.OrderBys, sQueryInfo.GroupByExpression);
                visitor.Write(wf);
                cmd.AddNavMembers(visitor.NavMembers);
            }

            #endregion

            #region 分页查询

            if (sQueryInfo.Take > 0)
            {
                wf.AppendNewLine().AppendFormat("LIMIT {0}", this.DbValue.GetSqlValue(sQueryInfo.Take, token));
            }
            else if (sQueryInfo.Take == 0 && sQueryInfo.Skip > 0)
            {
                wf.AppendNewLine().AppendFormat("LIMIT {0}", this.DbValue.GetSqlValue(-1, token));
            }
            if (sQueryInfo.Skip > 0)
            {
                wf.AppendFormat(" OFFSET {0}", this.DbValue.GetSqlValue(sQueryInfo.Skip, token));
            }

            #endregion

            #region 嵌套查询

            if (useStatis && useNesting)
            {
                cmd.CombineFragments();
                indent   -= 1;
                jf.Indent = indent;
                jf.AppendNewLine();
                jf.Append(") ");
                jf.Append(alias0);
            }

            #endregion

            #region 嵌套导航

            // TODO Include 从表,没分页,OrderBy 报错
            if (sQueryInfo.HasMany && subQuery != null && subQuery.OrderBys.Count > 0 && subQuery.StatisExpression == null && !(subQuery.Skip > 0 || subQuery.Take > 0))
            {
                cmd.CombineFragments();
                visitor = new OrderByExpressionVisitor(this, aliases, subQuery.OrderBys);//, null, "t0");
                visitor.Write(jf);
            }

            #endregion

            #region 并集查询

            // UNION 子句
            if (sQueryInfo.Unions != null && sQueryInfo.Unions.Count > 0)
            {
                cmd.CombineFragments();
                for (int index = 0; index < sQueryInfo.Unions.Count; index++)
                {
                    jf.AppendNewLine();
                    jf.Append("UNION ALL");
                    if (indent == 0)
                    {
                        jf.AppendNewLine();
                    }
                    Command cmd2 = this.ParseSelectCommand <T>(sQueryInfo.Unions[index] as DbQueryableInfo_Select <T>, indent, isOuter, token);
                    jf.Append(cmd2.CommandText);
                }
            }

            #endregion

            #region Any 子句

            // 'Any' 子句
            if (sQueryInfo.HasAny)
            {
                // 产生 WHERE 子句
                cmd.CombineFragments();

                // 如果没有分页,则显式指定只查一笔记录
                if (sQueryInfo.Take == 0 && sQueryInfo.Skip == 0)
                {
                    jf.AppendNewLine();
                    jf.Append("LIMIT 1");
                }

                indent   -= 1;
                jf.Indent = indent;
                jf.AppendNewLine();
                jf.Append(") ");
                jf.Append(alias0);
            }

            #endregion

            return(cmd);
        }
예제 #60
0
        // 创建 INSRT 命令
        protected override Command ResolveInsertCommand <T>(DbQueryableInfo_Insert <T> dbQuery, ResolveToken token)
        {
            ISqlBuilder     builder     = this.CreateSqlBuilder(token);
            TypeRuntimeInfo typeRuntime = TypeRuntimeInfoCache.GetRuntimeInfo <T>();
            TableAliasCache aliases     = new TableAliasCache();

            if (dbQuery.Entity != null)
            {
                // 如果没有Sequence列,使用 INSERT ALL INTO 语法,否则就一条一条逐行写入~~
                // 批量 INSERT,自增列不会自动赋值

                object      entity         = dbQuery.Entity;
                ISqlBuilder columnsBuilder = this.CreateSqlBuilder(token);
                ISqlBuilder valuesBuilder  = this.CreateSqlBuilder(token);

                // 指定插入列
                MemberInvokerCollection invokers = typeRuntime.Invokers;
                if (dbQuery.EntityColumns != null && dbQuery.EntityColumns.Count > 0)
                {
                    invokers = new MemberInvokerCollection();
                    for (int i = 0; i < dbQuery.EntityColumns.Count; i++)
                    {
                        Expression curExpr = dbQuery.EntityColumns[i];
                        if (curExpr.NodeType == ExpressionType.Lambda)
                        {
                            curExpr = (curExpr as LambdaExpression).Body.ReduceUnary();
                        }
                        if (curExpr.NodeType != ExpressionType.MemberAccess)
                        {
                            throw new XFrameworkException("Can't read field name from expression {0}", dbQuery.EntityColumns[i]);
                        }

                        MemberExpression member = curExpr as MemberExpression;
                        string           name   = member.Member.Name;
                        invokers[name] = typeRuntime.Invokers[name];
                    }
                }

                // 自增列参数
                IDbDataParameter seqParameter = null;
                // 自增列标记
                ColumnAttribute seqColumn = null;
                foreach (var invoker in invokers)
                {
                    var column = invoker.Column;
                    if (column != null && column.NoMapped)
                    {
                        continue;
                    }
                    if (invoker.ForeignKey != null)
                    {
                        continue;
                    }
                    if (invoker.Member.MemberType == System.Reflection.MemberTypes.Method)
                    {
                        continue;
                    }

                    columnsBuilder.AppendMember(invoker.Member.Name);
                    columnsBuilder.Append(',');

                    if (invoker == dbQuery.AutoIncrement)
                    {
                        seqColumn = column;
                        if (dbQuery.Bulk == null)
                        {
                            // 非批量INSERT,产生一个 OUTPUT 类型的参数
                            string pName    = string.Format("{0}p{1}", this.ParameterPrefix, token.Parameters.Count);
                            var    database = dbQuery.SourceQuery.DbContext.Database;
                            seqParameter = database.CreateParameter(pName, -1, direction: ParameterDirection.Output);
                            token.Parameters.Add(seqParameter);
                            valuesBuilder.Append(seqParameter.ParameterName);
                            valuesBuilder.Append(',');
                        }
                        else
                        {
                            valuesBuilder.Append(((OracleColumnAttribute)column).SEQName);
                            valuesBuilder.Append(".NEXTVAL");
                            valuesBuilder.Append(',');
                        }
                    }
                    else
                    {
                        var    value = invoker.Invoke(entity);
                        string seg   = this.DbValue.GetSqlValueWidthDefault(value, token, column);
                        valuesBuilder.Append(seg);
                        valuesBuilder.Append(',');
                    }
                }
                columnsBuilder.Length -= 1;
                valuesBuilder.Length  -= 1;

                if (dbQuery.Bulk == null)
                {
                    // 非批量INSERT,产生一个 OUTPUT 类型的参数
                    if (seqParameter != null)
                    {
                        seqParameter.Direction = ParameterDirection.Output;
                        seqParameter.DbType    = DbType.Int64;
                        builder.Append("SELECT ");
                        builder.Append(((OracleColumnAttribute)seqColumn).SEQName);
                        builder.Append(".NEXTVAL INTO ");
                        builder.Append(seqParameter.ParameterName);
                        builder.Append(" FROM DUAL;");
                        builder.AppendNewLine();
                        //useSEQ = true;
                    }
                    builder.Append("INSERT ");
                }
                else
                {
                    // 批量 INSERT
                    if (!dbQuery.Bulk.OnlyValue || seqColumn != null)
                    {
                        builder.Append("INSERT ");
                    }
                    // 如果有自增列则不使用 INSERT ALL INTO 语法
                    if (!dbQuery.Bulk.OnlyValue && seqColumn == null)
                    {
                        builder.Append("ALL ");
                    }
                }

                builder.Append("INTO ");
                builder.AppendMember(typeRuntime.TableName, !typeRuntime.IsTemporary);
                builder.Append('(');
                builder.Append(columnsBuilder);
                builder.Append(')');
                builder.AppendNewLine();
                builder.AppendNewTab();
                builder.Append("VALUES");
                builder.Append('(');
                builder.Append(valuesBuilder);
                builder.Append(')');

                if (dbQuery.Bulk == null)
                {
                    builder.Append(';');
                }
                else
                {
                    if (seqColumn != null)
                    {
                        if (dbQuery.Bulk.IsEndPos)
                        {
                            builder.Append(";");
                        }
                        else
                        {
                            builder.AppendNewLine(";");
                        }
                    }
                    else
                    {
                        builder.AppendNewLine();
                        if (dbQuery.Bulk.IsEndPos)
                        {
                            builder.Append("SELECT 1 FROM DUAL;");
                        }
                    }
                }
            }
            else if (dbQuery.SelectInfo != null)
            {
                builder.Append("INSERT INTO ");
                builder.AppendMember(typeRuntime.TableName, !typeRuntime.IsTemporary);
                builder.Append('(');

                int           i    = 0;
                MapperCommand cmd2 = this.ResolveSelectCommand(dbQuery.SelectInfo, 0, false, token) as MapperCommand;
                foreach (var column in cmd2.PickColumns)
                {
                    builder.AppendMember(column.Name);
                    if (i < cmd2.PickColumns.Count - 1)
                    {
                        builder.Append(',');
                    }
                    i++;
                }

                builder.Append(')');
                builder.AppendNewLine();
                builder.Append(cmd2.CommandText);
                builder.Append(';');
            }

            var cmd = new Command(builder.ToString(), builder.Token != null ? builder.Token.Parameters : null, System.Data.CommandType.Text);

            return(cmd);
        }