1 #region MIT license 2 // 3 // MIT license 4 // 5 // Copyright (c) 2007-2008 Jiri Moudry, Pascal Craponne 6 // 7 // Permission is hereby granted, free of charge, to any person obtaining a copy 8 // of this software and associated documentation files (the "Software"), to deal 9 // in the Software without restriction, including without limitation the rights 10 // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 11 // copies of the Software, and to permit persons to whom the Software is 12 // furnished to do so, subject to the following conditions: 13 // 14 // The above copyright notice and this permission notice shall be included in 15 // all copies or substantial portions of the Software. 16 // 17 // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 18 // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 19 // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 20 // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 21 // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 22 // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 23 // THE SOFTWARE. 24 // 25 #endregion 26 27 using System; 28 using System.Collections.Generic; 29 using System.Linq; 30 using System.Linq.Expressions; 31 32 using DbLinq.Data.Linq.Sugar; 33 using DbLinq.Data.Linq.Sugar.ExpressionMutator; 34 using DbLinq.Data.Linq.Sugar.Expressions; 35 36 namespace DbLinq.Data.Linq.Sugar.Implementation 37 { 38 internal class SpecialExpressionTranslator : ISpecialExpressionTranslator 39 { 40 /// <summary> 41 /// Translate a hierarchy's SpecialExpressions to Expressions 42 /// </summary> 43 /// <param name="expression"></param> 44 /// <returns></returns> Translate(Expression expression)45 public Expression Translate(Expression expression) 46 { 47 return expression.Recurse(Analyzer); 48 } 49 Analyzer(Expression expression)50 protected virtual Expression Analyzer(Expression expression) 51 { 52 if (expression is SpecialExpression) 53 return Translate((SpecialExpression)expression); 54 else if (expression is StartIndexOffsetExpression) 55 return Translate(((StartIndexOffsetExpression)expression).InnerExpression); 56 return expression; 57 } 58 59 /// <summary> 60 /// Translates a SpecialExpression to standard Expression equivalent 61 /// </summary> 62 /// <param name="specialExpression"></param> 63 /// <returns></returns> Translate(SpecialExpression specialExpression)64 protected virtual Expression Translate(SpecialExpression specialExpression) 65 { 66 var operands = specialExpression.Operands.ToList(); 67 switch (specialExpression.SpecialNodeType) // SETuse 68 { 69 case SpecialExpressionType.IsNull: 70 return TranslateIsNull(operands); 71 case SpecialExpressionType.IsNotNull: 72 return TranslateIsNotNull(operands); 73 case SpecialExpressionType.Concat: 74 return TranslateConcat(operands); 75 //case SpecialExpressionType.Count: 76 // break; 77 //case SpecialExpressionType.Like: 78 // break; 79 //case SpecialExpressionType.Min: 80 // break; 81 //case SpecialExpressionType.Max: 82 // break; 83 //case SpecialExpressionType.Sum: 84 // break; 85 //case SpecialExpressionType.Average: 86 // break; 87 case SpecialExpressionType.StringLength: 88 return TranslateStringLength(operands); 89 case SpecialExpressionType.ToUpper: 90 return GetStandardCallInvoke("ToUpper", operands); 91 case SpecialExpressionType.ToLower: 92 return GetStandardCallInvoke("ToLower", operands); 93 //case SpecialExpressionType.In: 94 // break; 95 96 case SpecialExpressionType.StringInsert: 97 return GetStandardCallInvoke("Insert", operands); 98 case SpecialExpressionType.Substring: 99 case SpecialExpressionType.Trim: 100 case SpecialExpressionType.LTrim: 101 case SpecialExpressionType.RTrim: 102 case SpecialExpressionType.Replace: 103 case SpecialExpressionType.Remove: 104 case SpecialExpressionType.IndexOf: 105 case SpecialExpressionType.Year: 106 case SpecialExpressionType.Month: 107 case SpecialExpressionType.Day: 108 case SpecialExpressionType.Hour: 109 case SpecialExpressionType.Minute: 110 case SpecialExpressionType.Millisecond: 111 case SpecialExpressionType.Date: 112 return GetStandardCallInvoke(specialExpression.SpecialNodeType.ToString(), operands); 113 case SpecialExpressionType.Now: 114 return GetDateTimeNowCall(operands); 115 case SpecialExpressionType.DateDiffInMilliseconds: 116 return GetCallDateDiffInMilliseconds(operands); 117 default: 118 throw Error.BadArgument("S0078: Implement translator for {0}", specialExpression.SpecialNodeType); 119 120 } 121 } 122 GetCallDateDiffInMilliseconds(List<Expression> operands)123 private Expression GetCallDateDiffInMilliseconds(List<Expression> operands) 124 { 125 return Expression.MakeMemberAccess(Expression.Subtract(operands.First(), operands.ElementAt(1)), 126 typeof(TimeSpan).GetProperty("TotalMilliseconds")); 127 } 128 GetDateTimeNowCall(List<Expression> operands)129 private Expression GetDateTimeNowCall(List<Expression> operands) 130 { 131 return Expression.Call(typeof(DateTime).GetProperty("Now").GetGetMethod()); 132 } 133 TranslateStringLength(List<Expression> operands)134 private Expression TranslateStringLength(List<Expression> operands) 135 { 136 return Expression.MakeMemberAccess(operands[0], typeof(string).GetProperty("Length")); 137 } 138 GetStandardCallInvoke(string methodName, List<Expression> operands)139 protected virtual Expression GetStandardCallInvoke(string methodName, List<Expression> operands) 140 { 141 var parametersExpressions = operands.Skip(1); 142 return Expression.Call(operands[0], 143 operands[0].Type.GetMethod(methodName, parametersExpressions.Select(op => op.Type).ToArray()), 144 parametersExpressions); 145 } 146 147 //protected virtual Expression TranslateRemove(List<Expression> operands) 148 //{ 149 // if (operands.Count > 2) 150 // { 151 // return Expression.Call(operands[0], 152 // typeof(string).GetMethod("Remove", new[] { typeof(int), typeof(int) }), 153 // operands[1], operands[2]); 154 // } 155 // return Expression.Call(operands[0], 156 // typeof(string).GetMethod("Remove", new[] { typeof(int) }), 157 // operands[1]); 158 //} 159 160 //protected virtual Expression TranslateStringIndexOf(List<Expression> operands) 161 //{ 162 // if (operands.Count == 2 && operands[1].Type == typeof(string)) 163 // { 164 // return Expression.Call(operands[0], 165 // typeof(string).GetMethod("IndexOf", new[] { typeof(string)}), 166 // operands[1]); 167 // } 168 // throw new NotSupportedException(); 169 //} 170 171 //protected virtual Expression TranslateReplace(List<Expression> operands) 172 //{ 173 // if (operands.ElementAt(1).Type == typeof(string)) 174 // { 175 // return Expression.Call(operands[0], 176 // typeof(string).GetMethod("Replace", new[] { typeof(string), typeof(string) }), 177 // operands[1], operands[2]); 178 // } 179 // return Expression.Call(operands[0], 180 // typeof(string).GetMethod("Replace", new[] { typeof(char), typeof(char) }), 181 // operands[1], operands[2]); 182 //} 183 //protected virtual Expression TranslateInsertString(List<Expression> operands) 184 //{ 185 // return Expression.Call(operands.First(), typeof(string).GetMethod("Insert"), operands[1], operands[2]); 186 //} 187 188 //protected virtual Expression TranslateTrim(List<Expression> operands) 189 //{ 190 // return Expression.Call(operands.First(), typeof(string).GetMethod("Trim", new Type[] { })); 191 //} 192 //protected virtual Expression TranslateSubString(List<Expression> operands) 193 //{ 194 // if (operands.Count > 2) 195 // { 196 // return Expression.Call(operands[0], 197 // typeof(string).GetMethod("Substring", new[] { operands[1].Type, operands[2].Type }), 198 // operands[1], operands[2]); 199 // } 200 201 // return Expression.Call(operands[0], 202 // typeof(string).GetMethod("Substring", new[] { operands[1].Type }), 203 // operands[1]); 204 //} 205 206 //protected virtual Expression TranslateToLower(List<Expression> operands) 207 //{ 208 // return Expression.Call(operands[0], typeof(string).GetMethod("ToLower", new Type[0])); 209 //} 210 211 //protected virtual Expression TranslateToUpper(List<Expression> operands) 212 //{ 213 // return Expression.Call(operands[0], typeof(string).GetMethod("ToUpper", new Type[0])); 214 //} 215 TranslateConcat(List<Expression> operands)216 protected virtual Expression TranslateConcat(List<Expression> operands) 217 { 218 return Expression.Add(operands[0], operands[1]); 219 } 220 TranslateIsNotNull(List<Expression> operands)221 protected virtual Expression TranslateIsNotNull(List<Expression> operands) 222 { 223 return Expression.NotEqual(operands[0], Expression.Constant(null)); 224 } 225 TranslateIsNull(List<Expression> operands)226 protected virtual Expression TranslateIsNull(List<Expression> operands) 227 { 228 return Expression.Equal(operands[0], Expression.Constant(null)); 229 } 230 } 231 }