private string ProcessFEXP(FEXP exp)
        {
            //if (exp == null) return "";
            var function   = exp.Function;
            var parameters = exp.Parameters != null?exp.Parameters.Select(a => ProcessQueryItem(a)).ToArray() : new string[0];

            switch (function)
            {
            case QueryFunctions.Ascii: return(string.Format("ASCII({0})", parameters[0]));

            case QueryFunctions.Char: return(string.Format("CHAR({0})", parameters[0]));

            case QueryFunctions.CharIndex:
                if (parameters.Length == 2)
                {
                    return(string.Format("CHARINDEX({0}, {1}) - 1", parameters[0], parameters[1]));
                }
                else if (parameters.Length == 3)
                {
                    return(string.Format("CHARINDEX({0}, {1}, {2}) - 1", parameters[0], parameters[1], parameters[2]));
                }
                else
                {
                    throw new QueryBuildException(QueryBuildException.ExceptionTypes.ParameterCountIsWrong);
                }

            case QueryFunctions.Concat: return(string.Format("CONCAT({0})", string.Join(",", parameters)));

            case QueryFunctions.Difference: return(string.Format("DIFFERENCE({0}, {1})", parameters[0], parameters[1]));;

            case QueryFunctions.Format:
                if (parameters.Length == 2)
                {
                    return(string.Format("FORMAT({0}, {1})", parameters[0], parameters[1]));
                }
                else if (parameters.Length == 3)
                {
                    return(string.Format("FORMAT({0}, {1}, {2})", parameters[0], parameters[1], parameters[2]));
                }
                else
                {
                    throw new QueryBuildException(QueryBuildException.ExceptionTypes.ParameterCountIsWrong);
                }

            case QueryFunctions.Left: return(string.Format("LEFT({0}, {1})", parameters[0], parameters[1]));

            case QueryFunctions.Len: return(string.Format("LEN({0})", parameters[0]));

            case QueryFunctions.Lower: return(string.Format("LOWER({0})", parameters[0]));

            case QueryFunctions.Ltrim: return(string.Format("LTRIM({0})", parameters[0]));

            case QueryFunctions.Nchar: return(string.Format("NCHAR({0})", parameters[0]));

            case QueryFunctions.Patindex: return(string.Format("PATINDEX({0}, {1})", parameters[0], parameters[1]));

            case QueryFunctions.Quotename:
                if (parameters.Length == 1)
                {
                    return(string.Format("QUOTENAME({0})", parameters[0]));
                }
                else if (parameters.Length == 2)
                {
                    return(string.Format("QUOTENAME({0}, {1})", parameters[0], parameters[1]));
                }
                else
                {
                    throw new QueryBuildException(QueryBuildException.ExceptionTypes.ParameterCountIsWrong);
                }

            case QueryFunctions.Replace: return(string.Format("REPLACE({0}, {1}, {2})", parameters[0], parameters[1], parameters[2]));

            case QueryFunctions.Replicate: return(string.Format("REPLACE({0}, {1})", parameters[0], parameters[1]));;

            case QueryFunctions.Reverse: return(string.Format("REVERSE({0})", parameters[0]));

            case QueryFunctions.Right: return(string.Format("RIGHT({0}, {1})", parameters[0], parameters[1]));

            case QueryFunctions.Rtrim: return(string.Format("RTRIM({0})", parameters[0]));

            case QueryFunctions.Trim: return(string.Format("LTRIM(RTRIM({0}))", parameters[0]));

            case QueryFunctions.Soundex: return(string.Format("SOUNDEX({0})", parameters[0]));

            case QueryFunctions.Space: return(string.Format("SPACE({0})", parameters[0]));

            case QueryFunctions.Str:
                if (parameters.Length == 1)
                {
                    return(string.Format("STR({0})", parameters[0]));
                }
                else if (parameters.Length == 2)
                {
                    return(string.Format("STR({0}, {1})", parameters[0], parameters[1]));
                }
                else if (parameters.Length == 3)
                {
                    return(string.Format("SRT({0}, {1}, {2})", parameters[0], parameters[1], parameters[2]));
                }
                else
                {
                    throw new QueryBuildException(QueryBuildException.ExceptionTypes.ParameterCountIsWrong);
                }

            case QueryFunctions.String_Escape: return(string.Format("STRING_ESCAPE({0}, {1})", parameters[0], parameters[1]));

            case QueryFunctions.String_Split: return(string.Format("STRING_SPLIT({0}, {1})", parameters[0], parameters[1]));

            case QueryFunctions.Stuff: return(string.Format("STUFF({0}, {1}, {2}, {3})", parameters[0], parameters[1], parameters[2], parameters[3]));

            case QueryFunctions.Substring:
                if (parameters.Length == 2)
                {
                    return(string.Format("SUBSTRING({0}, {1}+1, LEN({0})-{1}+1)", parameters[0], parameters[1]));
                }
                else if (parameters.Length == 3)
                {
                    return(string.Format("SUBSTRING({0}, {1}+1, {2})", parameters[0], parameters[1], parameters[2]));
                }
                else
                {
                    throw new QueryBuildException(QueryBuildException.ExceptionTypes.ParameterCountIsWrong);
                }

            case QueryFunctions.Unicode: return(string.Format("UNICODE({0})", parameters[0]));

            case QueryFunctions.Upper: return(string.Format("UPPER({0})", parameters[0]));

            case QueryFunctions.Abs: return(string.Format("ABS({0})", parameters[0]));

            case QueryFunctions.Acos: return(string.Format("ACOS({0})", parameters[0]));

            case QueryFunctions.Asin: return(string.Format("ASIN({0})", parameters[0]));

            case QueryFunctions.Atan: return(string.Format("ATAN({0})", parameters[0]));

            case QueryFunctions.Atn2: return(string.Format("ATN2({0}, {1})", parameters[0], parameters[1]));

            case QueryFunctions.Ceiling: return(string.Format("CEILING({0})", parameters[0]));

            case QueryFunctions.Cos: return(string.Format("COS({0})", parameters[0]));

            case QueryFunctions.Cot: return(string.Format("COT({0})", parameters[0]));

            case QueryFunctions.Degrees: return(string.Format("DEGREES({0})", parameters[0]));

            case QueryFunctions.Exp: return(string.Format("EXP({0})", parameters[0]));

            case QueryFunctions.Floor: return(string.Format("FLOOR({0})", parameters[0]));

            case QueryFunctions.Log:
                if (parameters.Length == 1)
                {
                    return(string.Format("LOG({0})", parameters[0]));
                }
                else if (parameters.Length == 2)
                {
                    return(string.Format("LOG({0}, {1})", parameters[0], parameters[1]));
                }
                else
                {
                    throw new QueryBuildException(QueryBuildException.ExceptionTypes.ParameterCountIsWrong);
                }

            case QueryFunctions.PI: return("PI()");

            case QueryFunctions.Power: return(string.Format("POWER({0}, {1})", parameters[0], parameters[1]));

            case QueryFunctions.Radians: return(string.Format("RADIANS({0})", parameters[0]));

            case QueryFunctions.Rand:
                if (parameters.Length == 0)
                {
                    return("RAND()");
                }
                else if (parameters.Length == 1)
                {
                    return(string.Format("RAND({0})", parameters[0]));
                }
                else
                {
                    throw new QueryBuildException(QueryBuildException.ExceptionTypes.ParameterCountIsWrong);
                }

            case QueryFunctions.Round:
                if (parameters.Length == 2)
                {
                    return(string.Format("ROUND({0}, {1})", parameters[0], parameters[1]));
                }
                else if (parameters.Length == 3)
                {
                    return(string.Format("ROUND({0}, {1}, {2})", parameters[0], parameters[1], parameters[2]));
                }
                else if (parameters.Length == 1)
                {
                    return(string.Format("ROUND({0}, {1})", parameters[0], 0));
                }
                else
                {
                    throw new QueryBuildException(QueryBuildException.ExceptionTypes.ParameterCountIsWrong);
                }

            case QueryFunctions.Sign: return(string.Format("SIGN({0})", parameters[0]));

            case QueryFunctions.Sin: return(string.Format("SIN({0})", parameters[0]));

            case QueryFunctions.Sqrt: return(string.Format("SQRT({0})", parameters[0]));

            case QueryFunctions.Square: return(string.Format("SQUARE({0})", parameters[0]));

            case QueryFunctions.Tan: return(string.Format("TAN({0})", parameters[0]));

            case QueryFunctions.GetDate: return("GETDATE()");

            case QueryFunctions.Avg: return(string.Format("AVG({0})", parameters[0]));

            case QueryFunctions.Max: return(string.Format("MAX({0})", parameters[0]));

            case QueryFunctions.Min: return(string.Format("MIN({0})", parameters[0]));

            case QueryFunctions.Sum: return(string.Format("SUM({0})", parameters[0]));

            case QueryFunctions.Stdev: return(string.Format("STDEV({0})", parameters[0]));

            case QueryFunctions.Stdevp: return(string.Format("STDEVP({0})", parameters[0]));

            case QueryFunctions.Var: return(string.Format("VAR({0})", parameters[0]));

            case QueryFunctions.Varp: return(string.Format("VARP({0})", parameters[0]));

            case QueryFunctions.Count: return(string.Format("COUNT({0})", parameters[0]));

            case QueryFunctions.Count_Big: return(string.Format("COUNT_BIG({0})", parameters[0]));

            case QueryFunctions.Grouping: return(string.Format("GROUPING({0})", parameters[0]));

            case QueryFunctions.Grouping_Id: return(string.Format("GROUPING_ID({0})", parameters[0]));

            case QueryFunctions.Checksum_Agg: return(string.Format("CHECKSUM_AGG({0})", parameters[0]));

            default: throw new QueryBuildException(QueryBuildException.ExceptionTypes.OperatorNotFound);
            }
            throw new QueryBuildException(QueryBuildException.ExceptionTypes.OperatorUnsuported);
        }
        private static IQueryItem WriteExpression(Expression e)
        {
            BinaryOperator binaryOperator;

            if (binaryOperators.TryGetValue(e.NodeType, out binaryOperator))
            {
                IQueryItem queryItem1 = WriteExpression((e as BinaryExpression).Left);
                IQueryItem queryItem2 = WriteExpression((e as BinaryExpression).Right);
                if ((object)(queryItem1 as VAL) != null && (queryItem1 as VAL).Value == DBNull.Value)
                {
                    if (binaryOperator == BinaryOperator.Equal)
                    {
                        return (IQueryItem) new BEXP()
                               {
                                   Operand1 = queryItem2, Operator = BinaryOperator.IsNull
                               }
                    }
                    ;
                    if (binaryOperator == BinaryOperator.NotEqual)
                    {
                        return (IQueryItem) new BEXP()
                               {
                                   Operand1 = queryItem2, Operator = BinaryOperator.IsNotNull
                               }
                    }
                    ;
                }
                if ((object)(queryItem2 as VAL) != null && (queryItem2 as VAL).Value == DBNull.Value)
                {
                    if (binaryOperator == BinaryOperator.Equal)
                    {
                        return (IQueryItem) new BEXP()
                               {
                                   Operand1 = queryItem1, Operator = BinaryOperator.IsNull
                               }
                    }
                    ;
                    if (binaryOperator == BinaryOperator.NotEqual)
                    {
                        return (IQueryItem) new BEXP()
                               {
                                   Operand1 = queryItem1, Operator = BinaryOperator.IsNotNull
                               }
                    }
                    ;
                }
                return((IQueryItem) new BEXP()
                {
                    Operand1 = queryItem1, Operand2 = queryItem2, Operator = binaryOperator
                });
            }
            if (e.NodeType == ExpressionType.New)
            {
                object obj = Expression.Lambda(e).Compile().DynamicInvoke();
                return((IQueryItem) new VAL()
                {
                    Value = obj
                });
            }
            if (e.NodeType == ExpressionType.Not)
            {
                IQueryItem queryItem = NewHelpers.WriteExpression((e as UnaryExpression).Operand);
                return((IQueryItem) new BEXP()
                {
                    Operand1 = queryItem, Operator = BinaryOperator.Not
                });
            }
            TransformOperator transformOperator;

            if (NewHelpers.transformOperators.TryGetValue(e.NodeType, out transformOperator))
            {
                IQueryItem queryItem1 = NewHelpers.WriteExpression((e as BinaryExpression).Left);
                IQueryItem queryItem2 = NewHelpers.WriteExpression((e as BinaryExpression).Right);
                return((IQueryItem) new TEXP()
                {
                    Operand1 = queryItem1, Operand2 = queryItem2, Operator = transformOperator
                });
            }
            if (e.NodeType == ExpressionType.Negate)
            {
                IQueryItem queryItem = NewHelpers.WriteExpression((e as BinaryExpression).Left);
                return((IQueryItem) new TEXP()
                {
                    Operand1 = queryItem, Operator = TransformOperator.Negate
                });
            }
            if (e is MemberExpression)
            {
                MemberExpression exp = e as MemberExpression;
                KeyValuePair <NewHelpers.FunctionProperty, QueryFunctions>[] array = NewHelpers.functionProperties.Where <KeyValuePair <NewHelpers.FunctionProperty, QueryFunctions> >((Func <KeyValuePair <NewHelpers.FunctionProperty, QueryFunctions>, bool>)(a =>
                {
                    if (a.Key.FunctionName == exp.Member.Name.ToLower())
                    {
                        return(a.Key.ObjectType.IsAssignableFrom(exp.Expression.Type));
                    }
                    return(false);
                })).ToArray <KeyValuePair <NewHelpers.FunctionProperty, QueryFunctions> >();
                if ((uint)array.Length > 0U)
                {
                    IQueryItem queryItem = NewHelpers.WriteExpression(exp.Expression);
                    return((IQueryItem) new FEXP()
                    {
                        Function = array[0].Value, Parameters = new IQueryValue[1] {
                            (IQueryValue)queryItem
                        }
                    });
                }
                if (exp.Expression is ParameterExpression || exp.Expression is MemberExpression && (exp.Expression as MemberExpression).Expression is ParameterExpression)
                {
                    return((IQueryItem) new COL(exp.Member.Name));
                }
                object obj = Expression.Lambda((Expression)exp).Compile().DynamicInvoke();
                if (obj == null)
                {
                    return (IQueryItem) new VAL()
                           {
                               Value = (object)DBNull.Value
                           }
                }
                ;
                if (!obj.GetType().IsArray)
                {
                    return (IQueryItem) new VAL()
                           {
                               Value = obj
                           }
                }
                ;
                return((IQueryItem) new ARR()
                {
                    Values = (IQueryValue[])((Array)obj).Cast <object>().Select <object, VAL>((Func <object, VAL>)(a => new VAL()
                    {
                        Value = a
                    })).ToArray <VAL>()
                });
            }
            if (e is UnaryExpression)
            {
                return(NewHelpers.WriteExpression((e as UnaryExpression).Operand));
            }
            if (e is ConstantExpression)
            {
                return (IQueryItem) new VAL()
                       {
                           Value = Expression.Lambda(e).Compile().DynamicInvoke()
                       }
            }
            ;
            if (!(e is MethodCallExpression))
            {
                return((IQueryItem)null);
            }
            MethodCallExpression methodCallExpression = (MethodCallExpression)e;
            QueryFunctions       queryFunctions;

            if (NewHelpers.aggregteFunctions.TryGetValue(methodCallExpression.Method.Name.ToLower(CultureInfo.InvariantCulture), out queryFunctions) && methodCallExpression.Object is ParameterExpression)
            {
                List <IQueryItem> source = new List <IQueryItem>();
                foreach (Expression expression in methodCallExpression.Arguments)
                {
                    source.Add(NewHelpers.WriteExpression((expression as LambdaExpression).Body));
                }
                if (methodCallExpression.Method.Name.ToLower() == "count")
                {
                    source.Add((IQueryItem)COL.ALL);
                }
                FEXP fexp = new FEXP();
                fexp.Function = queryFunctions;
                IQueryValue[] array = source.Where <IQueryItem>((Func <IQueryItem, bool>)(a => a is IQueryValue)).Cast <IQueryValue>().ToArray <IQueryValue>();
                fexp.Parameters = array;
                return((IQueryItem)fexp);
            }
            if (methodCallExpression.Method.Name.ToLower(CultureInfo.InvariantCulture) == "asc")
            {
                List <IQueryItem> queryItemList = new List <IQueryItem>();
                foreach (Expression expression in methodCallExpression.Arguments)
                {
                    queryItemList.Add(NewHelpers.WriteExpression((expression as LambdaExpression).Body));
                }
                return((IQueryItem) new ASC()
                {
                    Value = (IQueryValue)queryItemList[0]
                });
            }
            if (methodCallExpression.Method.Name.ToLower(CultureInfo.InvariantCulture) == "desc")
            {
                List <IQueryItem> queryItemList = new List <IQueryItem>();
                foreach (Expression expression in methodCallExpression.Arguments)
                {
                    queryItemList.Add(NewHelpers.WriteExpression((expression as LambdaExpression).Body));
                }
                return((IQueryItem) new DESC()
                {
                    Value = (IQueryValue)queryItemList[0]
                });
            }
            if (NewHelpers.staticFunctions.TryGetValue(methodCallExpression.Method.Name.ToLower(CultureInfo.InvariantCulture), out queryFunctions))
            {
                List <IQueryItem> source = new List <IQueryItem>();
                foreach (Expression e1 in methodCallExpression.Arguments)
                {
                    source.Add(NewHelpers.WriteExpression(e1));
                }
                FEXP fexp = new FEXP();
                fexp.Function = queryFunctions;
                IQueryValue[] array = source.Where <IQueryItem>((Func <IQueryItem, bool>)(a => a is IQueryValue)).Cast <IQueryValue>().ToArray <IQueryValue>();
                fexp.Parameters = array;
                return((IQueryItem)fexp);
            }
            if (NewHelpers.instanceFunctions.TryGetValue(methodCallExpression.Method.Name.ToLower(CultureInfo.InvariantCulture), out queryFunctions))
            {
                List <IQueryItem> source = new List <IQueryItem>();
                source.Add(NewHelpers.WriteExpression(methodCallExpression.Object));
                foreach (Expression e1 in methodCallExpression.Arguments)
                {
                    source.Add(NewHelpers.WriteExpression(e1));
                }
                FEXP fexp = new FEXP();
                fexp.Function = queryFunctions;
                IQueryValue[] array = source.Where <IQueryItem>((Func <IQueryItem, bool>)(a => a is IQueryValue)).Cast <IQueryValue>().ToArray <IQueryValue>();
                fexp.Parameters = array;
                return((IQueryItem)fexp);
            }
            if (methodCallExpression.Method.Name.ToLower(CultureInfo.InvariantCulture) == "in")
            {
                IQueryItem queryItem1 = NewHelpers.WriteExpression(methodCallExpression.Arguments[0]);
                IQueryItem queryItem2 = NewHelpers.WriteExpression(methodCallExpression.Arguments[1]);
                return((IQueryItem) new BEXP()
                {
                    Operand1 = queryItem1, Operand2 = queryItem2, Operator = BinaryOperator.In
                });
            }
            if (((IEnumerable <string>) new string[3] {
                "contains", "startswith", "endswith"
            }).Contains <string>(methodCallExpression.Method.Name.ToLower(CultureInfo.InvariantCulture)))
            {
                string            lower         = methodCallExpression.Method.Name.ToLower(CultureInfo.InvariantCulture);
                List <IQueryItem> queryItemList = new List <IQueryItem>();
                queryItemList.Add(NewHelpers.WriteExpression(methodCallExpression.Object));
                foreach (Expression e1 in methodCallExpression.Arguments)
                {
                    queryItemList.Add(NewHelpers.WriteExpression(e1));
                }
                VAL                val            = (VAL)"%";
                IQueryItem         queryItem1     = queryItemList[1];
                List <IQueryValue> queryValueList = new List <IQueryValue>();
                if (lower == "contains" || lower == "endswith")
                {
                    queryValueList.Add((IQueryValue)val);
                }
                queryValueList.Add((IQueryValue)queryItem1);
                if (lower == "contains" || lower == "startswith")
                {
                    queryValueList.Add((IQueryValue)val);
                }
                FEXP fexp = new FEXP();
                fexp.Function = QueryFunctions.Concat;
                IQueryValue[] array = queryValueList.ToArray();
                fexp.Parameters = array;
                IQueryItem queryItem2 = (IQueryItem)fexp;
                BEXP       bexp       = new BEXP();
                bexp.Operator = BinaryOperator.Like;
                IQueryItem queryItem3 = queryItemList[0];
                bexp.Operand1 = queryItem3;
                IQueryItem queryItem4 = queryItem2;
                bexp.Operand2 = queryItem4;
                return((IQueryItem)bexp);
            }
            object obj1 = Expression.Lambda((Expression)methodCallExpression).Compile().DynamicInvoke();

            if (obj1 == null)
            {
                return (IQueryItem) new VAL()
                       {
                           Value = (object)DBNull.Value
                       }
            }
            ;
            if (!obj1.GetType().IsArray)
            {
                return (IQueryItem) new VAL()
                       {
                           Value = obj1
                       }
            }
            ;
            return((IQueryItem) new ARR()
            {
                Values = (IQueryValue[])((Array)obj1).Cast <object>().Select <object, VAL>((Func <object, VAL>)(a => new VAL()
                {
                    Value = a
                })).ToArray <VAL>()
            });
        }