private CompileResult CompileExpr([NotNull] Expression expr, List <object> queryArgs) { if (expr == null) { throw new NotSupportedException("Expression is NULL"); } if (expr is BinaryExpression) { var bin = (BinaryExpression)expr; var leftr = CompileExpr(bin.Left, queryArgs); var rightr = CompileExpr(bin.Right, queryArgs); //If either side is a parameter and is null, then handle the other side specially (for "is null"/"is not null") string text; if (leftr.CommandText == "?" && leftr.Value == null) { text = CompileNullBinaryExpression(bin, rightr); } else if (rightr.CommandText == "?" && rightr.Value == null) { text = CompileNullBinaryExpression(bin, leftr); } else { text = "(" + leftr.CommandText + " " + GetSqlName(bin) + " " + rightr.CommandText + ")"; } return(new CompileResult { CommandText = text }); } if (expr.NodeType == ExpressionType.Not) { var operandExpr = ((UnaryExpression)expr).Operand; var opr = CompileExpr(operandExpr, queryArgs); var val = opr.Value; if (val is bool) { val = !((bool)val); } return(new CompileResult { CommandText = "NOT(" + opr.CommandText + ")", Value = val }); } if (expr.NodeType == ExpressionType.Call) { var call = (MethodCallExpression)expr; var args = new CompileResult[call.Arguments.Count]; var obj = call.Object != null?CompileExpr(call.Object, queryArgs) : null; for (var i = 0; i < args.Length; i++) { args[i] = CompileExpr(call.Arguments[i], queryArgs); } var sqlCall = ""; if (call.Method.Name == "Like" && args.Length == 2) { sqlCall = "(" + args[0].CommandText + " like " + args[1].CommandText + ")"; } else if (call.Method.Name == "Contains" && args.Length == 2) { sqlCall = "(" + args[1].CommandText + " in " + args[0].CommandText + ")"; } else if (call.Method.Name == "Contains" && args.Length == 1) { if (call.Object != null && call.Object.Type == typeof(string)) { sqlCall = "(" + obj.CommandText + " like ('%' || " + args[0].CommandText + " || '%'))"; } else { sqlCall = "(" + args[0].CommandText + " in " + obj.CommandText + ")"; } } else if (call.Method.Name == "StartsWith" && args.Length == 1) { sqlCall = "(" + obj.CommandText + " like (" + args[0].CommandText + " || '%'))"; } else if (call.Method.Name == "EndsWith" && args.Length == 1) { sqlCall = "(" + obj.CommandText + " like ('%' || " + args[0].CommandText + "))"; } else if (call.Method.Name == "Equals" && args.Length == 1) { sqlCall = "(" + obj.CommandText + " = (" + args[0].CommandText + "))"; } else if (call.Method.Name == "ToLower") { sqlCall = "(lower(" + obj.CommandText + "))"; } else if (call.Method.Name == "ToUpper") { sqlCall = "(upper(" + obj.CommandText + "))"; } else if (call.Method.Name == "Replace" && args.Length == 2) { sqlCall = "(replace(" + obj.CommandText + ", " + args[0].CommandText + ", " + args[1].CommandText + "))"; } else { sqlCall = call.Method.Name.ToLower() + "(" + string.Join(",", args.Select(a => a.CommandText).ToArray()) + ")"; } return(new CompileResult { CommandText = sqlCall }); } if (expr.NodeType == ExpressionType.Constant) { var c = (ConstantExpression)expr; queryArgs.Add(c.Value); return(new CompileResult { CommandText = "?", Value = c.Value }); } if (expr.NodeType == ExpressionType.Convert) { var u = (UnaryExpression)expr; var ty = u.Type; var valr = CompileExpr(u.Operand, queryArgs); return(new CompileResult { CommandText = valr.CommandText, Value = valr.Value != null?ConvertTo(valr.Value, ty) : null }); } if (expr.NodeType == ExpressionType.MemberAccess) { var mem = (MemberExpression)expr; if (mem.Expression != null && mem.Expression.NodeType == ExpressionType.Parameter) { // // This is a column of our table, output just the column name // Need to translate it if that column name is mapped // var columnName = Table.FindColumnWithPropertyName(mem.Member.Name).Name; return(new CompileResult { CommandText = "\"" + columnName + "\"" }); } object obj = null; if (mem.Expression != null) { var r = CompileExpr(mem.Expression, queryArgs); if (r.Value == null) { throw new NotSupportedException("Member access failed to compile expression"); } if (r.CommandText == "?") { queryArgs.RemoveAt(queryArgs.Count - 1); } obj = r.Value; } // // Get the member value // var val = _sqlitePlatform.ReflectionService.GetMemberValue(obj, expr, mem.Member); // // Work special magic for enumerables // if (val != null && val is IEnumerable && !(val is string) && !(val is IEnumerable <byte>)) { var sb = new StringBuilder(); sb.Append("("); var head = ""; foreach (var a in (IEnumerable)val) { queryArgs.Add(a); sb.Append(head); sb.Append("?"); head = ","; } sb.Append(")"); return(new CompileResult { CommandText = sb.ToString(), Value = val }); } queryArgs.Add(val); return(new CompileResult { CommandText = "?", Value = val }); } throw new NotSupportedException("Cannot compile: " + expr.NodeType); }
private CompileResult CompileExpr(Expression expr, List <object> queryArgs) { if (expr == null) { throw new NotSupportedException("Expression is NULL"); } else if (expr is BinaryExpression) { var bin = (BinaryExpression)expr; var leftr = CompileExpr(bin.Left, queryArgs); var rightr = CompileExpr(bin.Right, queryArgs); //If either side is a parameter and is null, then handle the other side specially (for "is null"/"is not null") string text; if (leftr.CommandText == "?" && leftr.Value == null) { text = CompileNullBinaryExpression(bin, rightr); } else if (rightr.CommandText == "?" && rightr.Value == null) { text = CompileNullBinaryExpression(bin, leftr); } else { text = "(" + leftr.CommandText + " " + GetSqlName(bin) + " " + rightr.CommandText + ")"; } return(new CompileResult { CommandText = text }); } else if (expr.NodeType == ExpressionType.Call) { var call = (MethodCallExpression)expr; var args = new CompileResult[call.Arguments.Count]; var obj = call.Object != null?CompileExpr(call.Object, queryArgs) : null; for (var i = 0; i < args.Length; i++) { args[i] = CompileExpr(call.Arguments[i], queryArgs); } var sqlCall = ""; if (call.Method.Name == "Like" && args.Length == 2) { sqlCall = "(" + args[0].CommandText + " like " + args[1].CommandText + ")"; } else if (call.Method.Name == "Contains" && args.Length == 2) { sqlCall = "(" + args[1].CommandText + " in " + args[0].CommandText + ")"; } else if (call.Method.Name == "Contains" && args.Length == 1) { if (call.Object != null && call.Object.Type == typeof(string)) { sqlCall = "(" + obj.CommandText + " like ('%' || " + args[0].CommandText + " || '%'))"; } else { sqlCall = "(" + args[0].CommandText + " in " + obj.CommandText + ")"; } } else if (call.Method.Name == "StartsWith" && args.Length == 1) { sqlCall = "(" + obj.CommandText + " like (" + args[0].CommandText + " || '%'))"; } else if (call.Method.Name == "EndsWith" && args.Length == 1) { sqlCall = "(" + obj.CommandText + " like ('%' || " + args[0].CommandText + "))"; } else { sqlCall = call.Method.Name.ToLower() + "(" + string.Join(",", args.Select(a => a.CommandText).ToArray()) + ")"; } return(new CompileResult { CommandText = sqlCall }); } else if (expr.NodeType == ExpressionType.Constant) { var c = (ConstantExpression)expr; queryArgs.Add(c.Value); return(new CompileResult { CommandText = "?", Value = c.Value }); } else if (expr.NodeType == ExpressionType.Convert) { var u = (UnaryExpression)expr; var ty = u.Type; var valr = CompileExpr(u.Operand, queryArgs); return(new CompileResult { CommandText = valr.CommandText, Value = valr.Value != null?ConvertTo(valr.Value, ty) : null }); } else if (expr.NodeType == ExpressionType.MemberAccess) { var mem = (MemberExpression)expr; if (mem.Expression.NodeType == ExpressionType.Parameter) { // // This is a column of our table, output just the column name // Need to translate it if that column name is mapped // var columnName = Table.FindColumnWithPropertyName(mem.Member.Name).Name; return(new CompileResult { CommandText = "\"" + columnName + "\"" }); } else { object obj = null; if (mem.Expression != null) { var r = CompileExpr(mem.Expression, queryArgs); if (r.Value == null) { throw new NotSupportedException("Member access failed to compile expression"); } if (r.CommandText == "?") { queryArgs.RemoveAt(queryArgs.Count - 1); } obj = r.Value; } // // Get the member value // object val = null; #if !NETFX_CORE if (mem.Member.MemberType == MemberTypes.Property) { #else if (mem.Member is PropertyInfo) { #endif var m = (PropertyInfo)mem.Member; val = m.GetValue(obj, null); #if !NETFX_CORE } else if (mem.Member.MemberType == MemberTypes.Field) { #else } else if (mem.Member is FieldInfo) { #endif #if SILVERLIGHT val = Expression.Lambda(expr).Compile().DynamicInvoke(); #else var m = (FieldInfo)mem.Member; val = m.GetValue(obj); #endif } else { #if !NETFX_CORE throw new NotSupportedException("MemberExpr: " + mem.Member.MemberType.ToString()); #else throw new NotSupportedException("MemberExpr: " + mem.Member.DeclaringType.ToString()); #endif } // // Work special magic for enumerables // if (val != null && val is System.Collections.IEnumerable && !(val is string)) { var sb = new System.Text.StringBuilder(); sb.Append("("); var head = ""; foreach (var a in (System.Collections.IEnumerable)val) { queryArgs.Add(a); sb.Append(head); sb.Append("?"); head = ","; } sb.Append(")"); return(new CompileResult { CommandText = sb.ToString(), Value = val }); } else { queryArgs.Add(val); return(new CompileResult { CommandText = "?", Value = val }); } } } throw new NotSupportedException("Cannot compile: " + expr.NodeType.ToString()); }
private CompileResult CompileExpr(Expression expr, List <object> expr_agrs) { if (expr == null) { throw new NotSupportedException("Expression is NULL"); } if (expr is BinaryExpression) { BinaryExpression bin = (BinaryExpression)expr; CompileResult leftr = CompileExpr(bin.Left, expr_agrs); CompileResult rightr = CompileExpr(bin.Right, expr_agrs); //If either side is a parameter and is null, then handle the other side specially (for "is null"/"is not null") string text; if (leftr.CommandText == "?" && leftr.Value == null) { text = CompileNullBinaryExpression(bin, rightr); } else if (rightr.CommandText == "?" && rightr.Value == null) { text = CompileNullBinaryExpression(bin, leftr); } else { text = "(" + leftr.CommandText + " " + GetSqlName(bin) + " " + rightr.CommandText + ")"; } return(new CompileResult { CommandText = text }); } if (expr.NodeType == ExpressionType.Call) { MethodCallExpression call = (MethodCallExpression)expr; CompileResult[] args = new CompileResult[call.Arguments.Count]; CompileResult obj = call.Object != null?CompileExpr(call.Object, expr_agrs) : null; for (int i = 0; i < args.Length; i++) { args[i] = CompileExpr(call.Arguments[i], expr_agrs); } string sql_call = ""; if (call.Method.Name == "Like" && args.Length == 2) { sql_call = "(" + args[0].CommandText + " LIKE " + args[1].CommandText + ")"; } else if (call.Method.Name == "Contains" && args.Length == 2) { sql_call = "(" + args[1].CommandText + " IN " + args[0].CommandText + ")"; } else if (call.Method.Name == "Contains" && args.Length == 1) { if (call.Object != null && call.Object.Type == typeof(string)) { sql_call = "(" + obj.CommandText + " LIKE ('%' || " + args[0].CommandText + " || '%'))"; } else { sql_call = "(" + args[0].CommandText + " in " + obj.CommandText + ")"; } } else if (call.Method.Name == "StartsWith" && args.Length == 1) { sql_call = "(" + obj.CommandText + " LIKE (" + args[0].CommandText + " || '%'))"; } else if (call.Method.Name == "EndsWith" && args.Length == 1) { sql_call = "(" + obj.CommandText + " LIKE ('%' || " + args[0].CommandText + "))"; } else if (call.Method.Name == "Equals" && args.Length == 1) { sql_call = "(" + obj.CommandText + " = (" + args[0].CommandText + "))"; } else if (call.Method.Name == "ToLower") { sql_call = "(LOWER(" + obj.CommandText + "))"; } else if (call.Method.Name == "ToUpper") { sql_call = "(UPPER(" + obj.CommandText + "))"; } else { sql_call = call.Method.Name.ToLower() + "(" + string.Join(",", args.Select(a => a.CommandText).ToArray()) + ")"; } return(new CompileResult { CommandText = sql_call }); } if (expr.NodeType == ExpressionType.Constant) { ConstantExpression c = (ConstantExpression)expr; expr_agrs.Add(c.Value); return(new CompileResult { CommandText = "?", Value = c.Value }); } if (expr.NodeType == ExpressionType.Convert) { UnaryExpression u = (UnaryExpression)expr; Type ty = u.Type; CompileResult valr = CompileExpr(u.Operand, expr_agrs); return(new CompileResult { CommandText = valr.CommandText, Value = valr.Value != null?ConvertTo(valr.Value, ty) : null }); } if (expr.NodeType == ExpressionType.MemberAccess) { MemberExpression mem = (MemberExpression)expr; if (mem.Expression != null && mem.Expression.NodeType == ExpressionType.Parameter) { // // This is a column of our table, output just the column name // Need to translate it if that column name is mapped // string columnName = this.Table.FindColumnWithPropertyName(mem.Member.Name).Name; return(new CompileResult { CommandText = "\"" + columnName + "\"" }); } object obj = null; if (mem.Expression != null) { CompileResult r = CompileExpr(mem.Expression, expr_agrs); if (r.Value == null) { throw new NotSupportedException("Member access failed to compile expression"); } if (r.CommandText == "?") { expr_agrs.RemoveAt(expr_agrs.Count - 1); } obj = r.Value; } // // Get the member value // object val = null; if (mem.Member.MemberType == MemberTypes.Property) { PropertyInfo m = (PropertyInfo)mem.Member; val = m.GetValue(obj, null); } else if (mem.Member.MemberType == MemberTypes.Field) { FieldInfo m = (FieldInfo)mem.Member; val = m.GetValue(obj); } else { throw new NotSupportedException("MemberExpr: " + mem.Member.MemberType); } // // Work special magic for enumerables // if (val != null && val is IEnumerable && !(val is string) && !(val is IEnumerable <byte>)) { StringBuilder sb = new StringBuilder(); sb.Append("("); string head = ""; foreach (object a in (IEnumerable)val) { expr_agrs.Add(a); sb.Append(head); sb.Append("?"); head = ","; } sb.Append(")"); return(new CompileResult { CommandText = sb.ToString(), Value = val }); } expr_agrs.Add(val); return(new CompileResult { CommandText = "?", Value = val }); } throw new NotSupportedException("Cannot compile: " + expr.NodeType); }
CompileResult CompileExpr(Expression expr, List <object> queryArgs) { if (expr == null) { throw new NotSupportedException("Expression is NULL"); } else if (expr is BinaryExpression) { var bin = (BinaryExpression)expr; var leftr = CompileExpr(bin.Left, queryArgs); var rightr = CompileExpr(bin.Right, queryArgs); var text = "(" + leftr.CommandText + " " + GetSqlName(bin) + " " + rightr.CommandText + ")"; return(new CompileResult { CommandText = text }); } else if (expr.NodeType == ExpressionType.Call) { var call = (MethodCallExpression)expr; var args = new CompileResult[call.Arguments.Count]; for (var i = 0; i < args.Length; i++) { args[i] = CompileExpr(call.Arguments[i], queryArgs); } var sqlCall = ""; if (call.Method.Name == "Like" && args.Length == 2) { sqlCall = "(" + args[0].CommandText + " like " + args[1].CommandText + ")"; } else { sqlCall = call.Method.Name.ToLower() + "(" + string.Join(",", args.Select(a => a.CommandText).ToArray()) + ")"; } return(new CompileResult { CommandText = sqlCall }); } else if (expr.NodeType == ExpressionType.Constant) { var c = (ConstantExpression)expr; queryArgs.Add(c.Value); //Console.WriteLine ("++ constant: {0}", c.Value); return(new CompileResult { CommandText = "?", Value = c.Value }); } else if (expr.NodeType == ExpressionType.Convert) { var u = (UnaryExpression)expr; var ty = u.Type; var valr = CompileExpr(u.Operand, queryArgs); return(new CompileResult { CommandText = valr.CommandText, Value = valr.Value != null?Convert.ChangeType(valr.Value, ty) : null }); } else if (expr.NodeType == ExpressionType.MemberAccess) { var mem = (MemberExpression)expr; if (mem.Expression != null && mem.Expression.NodeType == ExpressionType.Parameter) { // // This is a column of our table, output just the column name // return(new CompileResult { CommandText = Quote(mem.Member.Name) }); } else { object obj = null; if (mem.Expression != null) { var r = CompileExpr(mem.Expression, queryArgs); if (r.Value == null) { throw new NotSupportedException("Member access failed to compile expression"); } if (r.CommandText == "?") { queryArgs.RemoveAt(queryArgs.Count - 1); } obj = r.Value; } if (mem.Member.MemberType == MemberTypes.Property) { var m = (PropertyInfo)mem.Member; var val = m.GetValue(obj, null); queryArgs.Add(val); //Console.WriteLine ("++ property: {0}", val); return(new CompileResult { CommandText = "?", Value = val }); } else if (mem.Member.MemberType == MemberTypes.Field) { var m = (FieldInfo)mem.Member; var val = m.GetValue(obj); queryArgs.Add(val); //Console.WriteLine ("++ field: {0}", val); return(new CompileResult { CommandText = "?", Value = val }); } else { throw new NotSupportedException("MemberExpr: " + mem.Member.MemberType.ToString()); } } } throw new NotSupportedException("Cannot compile: " + expr.NodeType.ToString()); }
private CompileResult CompileExpr(Expression expr, List <object> queryArgs) { if (expr == null) { throw new NotSupportedException("Expression is NULL"); } else if (expr is BinaryExpression) { var bin = (BinaryExpression)expr; // VB turns 'x=="foo"' into 'CompareString(x,"foo",true/false)==0', so we need to unwrap it // http://blogs.msdn.com/b/vbteam/archive/2007/09/18/vb-expression-trees-string-comparisons.aspx if (bin.Left.NodeType == ExpressionType.Call) { var call = (MethodCallExpression)bin.Left; if (call.Method.DeclaringType.FullName == "Microsoft.VisualBasic.CompilerServices.Operators" && call.Method.Name == "CompareString") { bin = Expression.MakeBinary(bin.NodeType, call.Arguments [0], call.Arguments [1]); } } var leftr = CompileExpr(bin.Left, queryArgs); var rightr = CompileExpr(bin.Right, queryArgs); //If either side is a parameter and is null, then handle the other side specially (for "is null"/"is not null") string text; if (leftr.CommandText == "?" && leftr.Value == null) { text = CompileNullBinaryExpression(bin, rightr); } else if (rightr.CommandText == "?" && rightr.Value == null) { text = CompileNullBinaryExpression(bin, leftr); } else { text = "(" + leftr.CommandText + " " + GetSqlName(bin) + " " + rightr.CommandText + ")"; } return(new CompileResult { CommandText = text }); } else if (expr.NodeType == ExpressionType.Not) { var operandExpr = ((UnaryExpression)expr).Operand; var opr = CompileExpr(operandExpr, queryArgs); object val = opr.Value; if (val is bool) { val = !((bool)val); } return(new CompileResult { CommandText = "NOT(" + opr.CommandText + ")", Value = val }); } else if (expr.NodeType == ExpressionType.Call) { var call = (MethodCallExpression)expr; var args = new CompileResult [call.Arguments.Count]; var obj = call.Object != null?CompileExpr(call.Object, queryArgs) : null; for (var i = 0; i < args.Length; i++) { args [i] = CompileExpr(call.Arguments [i], queryArgs); } var sqlCall = ""; if (call.Method.Name == "Like" && args.Length == 2) { sqlCall = "(" + args [0].CommandText + " like " + args [1].CommandText + ")"; } else if (call.Method.Name == "Contains" && args.Length == 2) { sqlCall = "(" + args [1].CommandText + " in " + args [0].CommandText + ")"; } else if (call.Method.Name == "Contains" && args.Length == 1) { if (call.Object != null && call.Object.Type == typeof(string)) { sqlCall = "( instr(" + obj.CommandText + "," + args [0].CommandText + ") >0 )"; } else { sqlCall = "(" + args [0].CommandText + " in " + obj.CommandText + ")"; } } else if (call.Method.Name == "StartsWith" && args.Length >= 1) { var startsWithCmpOp = StringComparison.CurrentCulture; if (args.Length == 2) { startsWithCmpOp = (StringComparison)args [1].Value; } switch (startsWithCmpOp) { case StringComparison.Ordinal: case StringComparison.CurrentCulture: sqlCall = "( substr(" + obj.CommandText + ", 1, " + args [0].Value.ToString().Length + ") = " + args [0].CommandText + ")"; break; case StringComparison.OrdinalIgnoreCase: case StringComparison.CurrentCultureIgnoreCase: sqlCall = "(" + obj.CommandText + " like (" + args [0].CommandText + " || '%'))"; break; } } else if (call.Method.Name == "EndsWith" && args.Length >= 1) { var endsWithCmpOp = StringComparison.CurrentCulture; if (args.Length == 2) { endsWithCmpOp = (StringComparison)args [1].Value; } switch (endsWithCmpOp) { case StringComparison.Ordinal: case StringComparison.CurrentCulture: sqlCall = "( substr(" + obj.CommandText + ", length(" + obj.CommandText + ") - " + args [0].Value.ToString().Length + "+1, " + args [0].Value.ToString().Length + ") = " + args [0].CommandText + ")"; break; case StringComparison.OrdinalIgnoreCase: case StringComparison.CurrentCultureIgnoreCase: sqlCall = "(" + obj.CommandText + " like ('%' || " + args [0].CommandText + "))"; break; } } else if (call.Method.Name == "Equals" && args.Length == 1) { sqlCall = "(" + obj.CommandText + " = (" + args [0].CommandText + "))"; } else if (call.Method.Name == "ToLower") { sqlCall = "(lower(" + obj.CommandText + "))"; } else if (call.Method.Name == "ToUpper") { sqlCall = "(upper(" + obj.CommandText + "))"; } else if (call.Method.Name == "Replace" && args.Length == 2) { sqlCall = "(replace(" + obj.CommandText + "," + args [0].CommandText + "," + args [1].CommandText + "))"; } else { sqlCall = call.Method.Name.ToLower() + "(" + string.Join(",", args.Select(a => a.CommandText).ToArray()) + ")"; } return(new CompileResult { CommandText = sqlCall }); } else if (expr.NodeType == ExpressionType.Constant) { var c = (ConstantExpression)expr; queryArgs.Add(c.Value); return(new CompileResult { CommandText = "?", Value = c.Value }); } else if (expr.NodeType == ExpressionType.Convert) { var u = (UnaryExpression)expr; var ty = u.Type; var valr = CompileExpr(u.Operand, queryArgs); return(new CompileResult { CommandText = valr.CommandText, Value = valr.Value != null?ConvertTo(valr.Value, ty) : null }); } else if (expr.NodeType == ExpressionType.MemberAccess) { var mem = (MemberExpression)expr; var paramExpr = mem.Expression as ParameterExpression; if (paramExpr == null) { var convert = mem.Expression as UnaryExpression; if (convert != null && convert.NodeType == ExpressionType.Convert) { paramExpr = convert.Operand as ParameterExpression; } } if (paramExpr != null) { // // This is a column of our table, output just the column name // Need to translate it if that column name is mapped // var columnName = Table.FindColumnWithPropertyName(mem.Member.Name).Name; return(new CompileResult { CommandText = "\"" + columnName + "\"" }); } else { object obj = null; if (mem.Expression != null) { var r = CompileExpr(mem.Expression, queryArgs); if (r.Value == null) { throw new NotSupportedException("Member access failed to compile expression"); } if (r.CommandText == "?") { queryArgs.RemoveAt(queryArgs.Count - 1); } obj = r.Value; } // // Get the member value // object val = null; if (mem.Member is PropertyInfo) { var m = (PropertyInfo)mem.Member; val = m.GetValue(obj, null); } else if (mem.Member is FieldInfo) { var m = (FieldInfo)mem.Member; val = m.GetValue(obj); } else { throw new NotSupportedException("MemberExpr: " + mem.Member.GetType()); } // // Work special magic for enumerables // if (val != null && val is System.Collections.IEnumerable && !(val is string) && !(val is System.Collections.Generic.IEnumerable <byte>)) { var sb = new System.Text.StringBuilder(); sb.Append("("); var head = ""; foreach (var a in (System.Collections.IEnumerable)val) { queryArgs.Add(a); sb.Append(head); sb.Append("?"); head = ","; } sb.Append(")"); return(new CompileResult { CommandText = sb.ToString(), Value = val }); } else { queryArgs.Add(val); return(new CompileResult { CommandText = "?", Value = val }); } } } throw new NotSupportedException("Cannot compile: " + expr.NodeType.ToString()); }
internal CompileResult CompileExpr(Expression expr, List <object> queryArgs, List <Condition> conditions) { if (expr == null) { throw new NotSupportedException("Expression is NULL"); } else if (expr is BinaryExpression) { var bin = (BinaryExpression)expr; // VB turns 'x=="foo"' into 'CompareString(x,"foo",true/false)==0', so we need to unwrap it // http://blogs.msdn.com/b/vbteam/archive/2007/09/18/vb-expression-trees-string-comparisons.aspx if (bin.Left.NodeType == ExpressionType.Call) { var call = (MethodCallExpression)bin.Left; if (call.Method.DeclaringType.FullName == "Microsoft.VisualBasic.CompilerServices.Operators" && call.Method.Name == "CompareString") { bin = Expression.MakeBinary(bin.NodeType, call.Arguments[0], call.Arguments[1]); } } var leftr = CompileExpr(bin.Left, queryArgs, conditions); var rightr = CompileExpr(bin.Right, queryArgs, conditions); if (leftr.CurrentCondition?.IsComplete ?? false) { conditions.Add(leftr.CurrentCondition); } if (rightr.CurrentCondition?.IsComplete ?? false) { conditions.Add(rightr.CurrentCondition); } if (leftr.CurrentCondition != null && !leftr.CurrentCondition.IsComplete) { Condition joinedCondition = new Condition(leftr.CurrentCondition, rightr.CurrentCondition); if (joinedCondition.IsComplete) { conditions.Add(joinedCondition); conditions.Remove(rightr.CurrentCondition); conditions.Remove(leftr.CurrentCondition); } } //If either side is a parameter and is null, then handle the other side specially (for "is null"/"is not null") string text; if (leftr.CommandText == "?" && leftr.Value == null) { text = CompileNullBinaryExpression(bin, leftr, conditions); //conditions.Insert(0, leftr.CurrentCondition); } else if (rightr.CommandText == "?" && rightr.Value == null) { text = CompileNullBinaryExpression(bin, leftr, conditions); } else { if ((rightr.CommandText == "?") && this is SQLServerTableQuery <T> ) { if (string.IsNullOrEmpty(rightr.CurrentCondition.ColumnName)) { var constCondtion = new Condition($"Constant{Guid.NewGuid():N}", rightr.CurrentCondition.Value); conditions.Insert(0, constCondtion); rightr.CommandText = "@" + constCondtion.ColumnName; } else { rightr.CommandText = "@" + leftr.CurrentCondition.ColumnName.Replace("\"", ""); } } if ((leftr.CommandText == "?") && this is SQLServerTableQuery <T> ) { if (leftr.Value is bool) { leftr.CommandText = "@" + leftr.CurrentCondition.ColumnName.Replace("\"", "") + "=1"; } else { leftr.CommandText = "@" + leftr.CurrentCondition.ColumnName.Replace("\"", ""); } } var _operator = GetSqlName(bin); text = "(" + leftr.CommandText + " " + _operator + " " + rightr.CommandText + " )"; } leftr.CurrentCondition = null; rightr.CurrentCondition = null; return(new CompileResult { CommandText = text }); } else if (expr.NodeType == ExpressionType.Not) { var operandExpr = ((UnaryExpression)expr).Operand; var opr = CompileExpr(operandExpr, queryArgs, conditions); object val = opr.Value; if (val is bool) { val = !((bool)val); } if (this is SQLServerTableQuery <T> ) { if (opr.CommandText.EndsWith("=1")) { opr.CommandText = opr.CommandText.Replace("=1", ""); } Condition condition = null; if (val is not null) { condition = new Condition(opr.CommandText, val); } return(new CompileResult { CommandText = "(" + opr.CommandText + "=0)", Value = val, CurrentCondition = condition }); } else { Condition condition = new Condition(opr.CommandText, val); return(new CompileResult { CommandText = "NOT(" + opr.CommandText + ")", Value = val, CurrentCondition = condition }); } } else if (expr.NodeType == ExpressionType.Call) { Condition CurrentCondition = null; var call = (MethodCallExpression)expr; var args = new CompileResult[call.Arguments.Count]; var obj = call.Object != null?CompileExpr(call.Object, queryArgs, conditions) : null; for (var i = 0; i < args.Length; i++) { args[i] = CompileExpr(call.Arguments[i], queryArgs, conditions); } var sqlCall = ""; if (call.Method.Name == "Like" && args.Length == 2) { sqlCall = "(" + args[0].CommandText + " like " + args[1].CommandText + ")"; } else if (call.Method.Name == "Contains" && args.Length == 2) { sqlCall = "(" + args[1].CommandText + " in " + args[0].CommandText + ")"; } else if (call.Method.Name == "Contains" && args.Length == 1) { if (call.Object != null && call.Object.Type == typeof(string)) { if (this.Connection is SQLServerConnection) { sqlCall = "( (" + obj.CommandText + "LIKE '%'+@" + args[0].CurrentCondition.ColumnName + "+'%') )"; } else { sqlCall = "(" + obj.CommandText + " LIKE '%'||" + args[0].CommandText + "||'%')"; } } else { if (this.Connection is SQLServerConnection) { sqlCall = "(@" + args[0].CurrentCondition.ColumnName + " in " + obj.CommandText + ")"; } else { sqlCall = "(" + args[0].CommandText + " in " + obj.CommandText + ")"; } } CurrentCondition = args[0].CurrentCondition; } else if (call.Method.Name == "StartsWith" && args.Length >= 1) { var startsWithCmpOp = StringComparison.CurrentCulture; if (args.Length == 2) { startsWithCmpOp = (StringComparison)args[1].Value; } switch (startsWithCmpOp) { case StringComparison.Ordinal: case StringComparison.CurrentCulture: sqlCall = "( substr(" + obj.CommandText + ", 1, " + args[0].Value.ToString().Length + ") = " + args[0].CommandText + ")"; break; case StringComparison.OrdinalIgnoreCase: case StringComparison.CurrentCultureIgnoreCase: sqlCall = "(" + obj.CommandText + " like (" + args[0].CommandText + " || '%'))"; break; } } else if (call.Method.Name == "EndsWith" && args.Length >= 1) { var endsWithCmpOp = StringComparison.CurrentCulture; if (args.Length == 2) { endsWithCmpOp = (StringComparison)args[1].Value; } switch (endsWithCmpOp) { case StringComparison.Ordinal: case StringComparison.CurrentCulture: sqlCall = "( substr(" + obj.CommandText + ", length(" + obj.CommandText + ") - " + args[0].Value.ToString().Length + "+1, " + args[0].Value.ToString().Length + ") = " + args[0].CommandText + ")"; break; case StringComparison.OrdinalIgnoreCase: case StringComparison.CurrentCultureIgnoreCase: sqlCall = "(" + obj.CommandText + " like ('%' || " + args[0].CommandText + "))"; break; } } else if (call.Method.Name == "Equals" && args.Length == 1) { sqlCall = "(" + obj.CommandText + " = (" + args[0].CommandText + "))"; } else if (call.Method.Name == "ToLower") { sqlCall = "(lower(" + obj.CommandText + "))"; } else if (call.Method.Name == "ToUpper") { sqlCall = "(upper(" + obj.CommandText + "))"; } else if (call.Method.Name == "Replace" && args.Length == 2) { sqlCall = "(replace(" + obj.CommandText + "," + args[0].CommandText + "," + args[1].CommandText + "))"; } else if (call.Method.Name == "IsNullOrEmpty" && args.Length == 1) { if (this.Connection is SQLServerConnection) { sqlCall = "(@" + args[0].CurrentCondition.ColumnName + " is null or @" + args[0].CurrentCondition.ColumnName + " ='' )"; } else { sqlCall = "( IFNULL(" + args[0].CommandText + ",'')='' )"; } CurrentCondition = args[0].CurrentCondition; } else { sqlCall = call.Method.Name.ToLower() + "(" + string.Join(",", args.Select(a => a.CommandText).ToArray()) + ")"; } return(new CompileResult { CommandText = sqlCall, CurrentCondition = CurrentCondition }); } else if (expr.NodeType == ExpressionType.Constant) { var c = (ConstantExpression)expr; queryArgs.Add(c.Value); //var condition = new Condition(c.Value); //conditions.Add(condition); return(new CompileResult { CommandText = "?", Value = c.Value, CurrentCondition = new Condition(c.Value) }); } else if (expr.NodeType == ExpressionType.Convert) { var u = (UnaryExpression)expr; var ty = u.Type; var valr = CompileExpr(u.Operand, queryArgs, conditions); var truvalue = valr.Value != null?ConvertTo(valr.Value, ty) : null; if (truvalue is int enuTruvalue) { if (u.Operand.Type.IsEnum) { if (u.Operand.Type.IsDefined(typeof(StoreAsTextAttribute), false)) { string text_enum = Enum.GetName(u.Operand.Type, enuTruvalue); if (!string.IsNullOrEmpty(text_enum)) { truvalue = text_enum; } } } } if ((ty == typeof(Guid) || ty == typeof(Guid?)) && truvalue is null) { return(new CompileResult { CommandText = valr.CommandText, Value = null, CurrentCondition = new Condition(valr.CommandText) }); } return(new CompileResult { CommandText = valr.CommandText, Value = truvalue, CurrentCondition = new Condition(valr.CommandText.Replace("\"", String.Empty), truvalue) }); } else if (expr.NodeType == ExpressionType.MemberAccess) { var mem = (MemberExpression)expr; var paramExpr = mem.Expression as ParameterExpression; if (paramExpr == null) { var convert = mem.Expression as UnaryExpression; if (convert != null && convert.NodeType == ExpressionType.Convert) { paramExpr = convert.Operand as ParameterExpression; } } if (paramExpr != null) { // // This is a column of our table, output just the column name // Need to translate it if that column name is mapped // var column = Table.FindColumnWithPropertyName(mem.Member.Name); if (column is null) { throw new KeyNotFoundException($"La columna {mem.Member.Name} no existe en la tabla {Table.TableName}"); } var columnName = column.Name; if (column.ColumnType == typeof(bool) && this.Connection is SQLServerConnection) { return(new CompileResult { CommandText = "\"" + columnName + "\"=1", CurrentCondition = new Condition(columnName) }); } return(new CompileResult { CommandText = "\"" + columnName + "\"", CurrentCondition = new Condition(columnName) }); } else { object obj = null; if (mem.Expression != null) { var r = CompileExpr(mem.Expression, queryArgs, conditions); if (r.Value == null) { throw new NotSupportedException("Member access failed to compile expression"); } if (r.CommandText == "?") { int remove_index = queryArgs.Count - 1; queryArgs.RemoveAt(remove_index); //conditions.RemoveAt(remove_index); } obj = r.Value; } // // Get the member value // object val = null; string fieldname = string.Empty; if (mem.Member is PropertyInfo) { var m = (PropertyInfo)mem.Member; val = m.GetValue(obj, null); fieldname = m.Name; } else if (mem.Member is FieldInfo) { var m = (FieldInfo)mem.Member; val = m.GetValue(obj); fieldname = m.Name; } else { throw new NotSupportedException("MemberExpr: " + mem.Member.GetType()); } // // Work special magic for enumerables // if (val != null && val is System.Collections.IEnumerable && !(val is string) && !(val is System.Collections.Generic.IEnumerable <byte>)) { var sb = new System.Text.StringBuilder(); sb.Append("("); var head = ""; foreach (var a in (System.Collections.IEnumerable)val) { queryArgs.Add(a); sb.Append(head); sb.Append("?"); head = ","; } sb.Append(")"); return(new CompileResult { CommandText = sb.ToString(), Value = val }); } else { queryArgs.Add(val); return(new CompileResult { CommandText = "?", Value = val, CurrentCondition = new Condition(fieldname, val) }); } } } throw new NotSupportedException("Cannot compile: " + expr.NodeType.ToString()); }
private CompileResult CompileExpr(Expression expr, List <object> queryArgs) { if (expr == null) { throw new NotSupportedException("Expression is NULL"); } if (expr is BinaryExpression) { var bin = (BinaryExpression)expr; CompileResult leftr = CompileExpr(bin.Left, queryArgs); CompileResult rightr = CompileExpr(bin.Right, queryArgs); //If either side is a parameter and is null, then handle the other side specially (for "is null"/"is not null") string text; if (leftr.CommandText == "?" && leftr.Value == null) { text = CompileNullBinaryExpression(bin, rightr); } else if (rightr.CommandText == "?" && rightr.Value == null) { text = CompileNullBinaryExpression(bin, leftr); } else { text = "(" + leftr.CommandText + " " + GetSqlName(bin) + " " + rightr.CommandText + ")"; } return(new CompileResult { CommandText = text }); } else if (expr.NodeType == ExpressionType.Call) { var call = (MethodCallExpression)expr; var args = new CompileResult[call.Arguments.Count]; var obj = call.Object != null?CompileExpr(call.Object, queryArgs) : null; string methodName = call.Method.Name; string sqlCall = string.Empty; for (int i = 0; i < args.Length; i++) { args[i] = CompileExpr(call.Arguments[i], queryArgs); } if (methodName == "Contains") { if (args.Length == 1) { // string.Contains("xxx") or list.Contains(x) if (call.Object != null && call.Object.Type == typeof(string)) { sqlCall = "({0} like ('%' || {1} || '%'))"; } else { sqlCall = "({1} in {0})"; } sqlCall = string.Format(sqlCall, obj.CommandText, args[0].CommandText); } else if (args.Length == 2) { sqlCall = string.Format("({0} in {1})", args[1].CommandText, args[0].CommandText); } } else if (methodName == "StartsWith" || methodName == "EndsWith") { if (args.Length == 1) { if (methodName == "StartsWith") { sqlCall = "({0} like ({1} || '%'))"; } else if (methodName == "EndsWith") { sqlCall = "({0} like ('%' || {1}))"; } sqlCall = string.Format(sqlCall, obj.CommandText, args[0].CommandText); } } else if (methodName == "Matches" && args.Length == 2) { sqlCall = "({0} match {1})"; sqlCall = string.Format(sqlCall, args[0].CommandText, args[1].CommandText); } else { var arguments = string.Join(",", args.Select(a => a.CommandText).ToArray()); sqlCall = string.Format("{0}({1})", methodName.ToLower(), arguments); } return(new CompileResult { CommandText = sqlCall }); } else if (expr.NodeType == ExpressionType.Constant) { var c = (ConstantExpression)expr; queryArgs.Add(c.Value); return(new CompileResult { CommandText = "?", Value = c.Value }); } else if (expr.NodeType == ExpressionType.Convert) { var u = (UnaryExpression)expr; Type ty = u.Type; CompileResult valr = CompileExpr(u.Operand, queryArgs); var underlyingType = Nullable.GetUnderlyingType(ty); if (underlyingType != null) { ty = underlyingType; } return(new CompileResult { CommandText = valr.CommandText, Value = valr.Value != null?Convert.ChangeType(valr.Value, ty, null) : null }); } else if (expr.NodeType == ExpressionType.MemberAccess) { var mem = (MemberExpression)expr; if (mem.Expression.NodeType == ExpressionType.Parameter) { // // This is a column of our table, output just the column name // return(new CompileResult { CommandText = "\"" + OrmHelper.GetColumnName(mem.Member) + "\"" }); } else { object obj = null; if (mem.Expression != null) { CompileResult r = CompileExpr(mem.Expression, queryArgs); if (r.Value == null) { throw new NotSupportedException("Member access failed to compile expression"); } if (r.CommandText == "?") { queryArgs.RemoveAt(queryArgs.Count - 1); } obj = r.Value; } // // Get the member value // object val = null; if (mem.Member is PropertyInfo) { var m = (PropertyInfo)mem.Member; val = m.GetValue(obj, null); } else if (mem.Member is FieldInfo) { #if SILVERLIGHT val = Expression.Lambda(expr).Compile().DynamicInvoke(); #else var m = (FieldInfo)mem.Member; val = m.GetValue(obj); #endif } else { throw new NotSupportedException("MemberExpr: " + mem.Member.GetType().Name); } // // Work special magic for enumerables // if (val != null && val is IEnumerable && !(val is string)) { var sb = new StringBuilder(); sb.Append("("); string head = ""; foreach (object a in (IEnumerable)val) { queryArgs.Add(a); sb.Append(head); sb.Append("?"); head = ","; } sb.Append(")"); return(new CompileResult { CommandText = sb.ToString(), Value = val }); } else { queryArgs.Add(val); return(new CompileResult { CommandText = "?", Value = val }); } } } throw new NotSupportedException("Cannot compile: " + expr.NodeType.ToString()); }