ExpressionWriterSql.cs 45 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288128912901291129212931294129512961297129812991300130113021303130413051306130713081309131013111312131313141315131613171318131913201321132213231324132513261327132813291330133113321333133413351336133713381339134013411342134313441345134613471348134913501351135213531354135513561357135813591360136113621363136413651366136713681369
  1. using System;
  2. using System.Collections.Generic;
  3. using System.Collections.ObjectModel;
  4. using System.IO;
  5. using System.Linq;
  6. using System.Linq.Expressions;
  7. using System.Reflection;
  8. using System.Text;
  9. using System.Text.RegularExpressions;
  10. namespace Common.LambdaToSQL
  11. {
  12. internal enum SqlType : byte
  13. {
  14. Where,
  15. Order
  16. }
  17. /// <summary>
  18. /// 输出一个基于C#分析器的表达示树
  19. /// </summary>
  20. internal class ExpressionWriterSql : ExpressionVisitor
  21. {
  22. private readonly TextWriter _writer;
  23. private int depth = 0;
  24. private string _aiWhereResult = string.Empty;
  25. private string _aiOrdeRsult = string.Empty;
  26. private int AiOrderTime { get; set; } = 0;
  27. private int AiWhereTime { get; set; } = 0;
  28. private SqlType _bizRead = SqlType.Where;
  29. private ExpressionWriterSql(TextWriter writer)
  30. {
  31. this._writer = writer;
  32. }
  33. private static void Write(TextWriter writer, Expression expression)
  34. {
  35. new ExpressionWriterSql(writer).Visit(expression);
  36. }
  37. private static string Write(TextWriter writer, Expression expression, SqlType bizSql)
  38. {
  39. expression = PartialEvaluator.Eval(expression);
  40. ExpressionWriterSql bizR = new ExpressionWriterSql(writer)
  41. {
  42. _bizRead = bizSql
  43. };
  44. bizR.Visit(expression);
  45. string result;
  46. switch (bizSql)
  47. {
  48. case SqlType.Order:
  49. result = Regex.Replace(bizR._aiOrdeRsult, @",\s?$", "");
  50. return result;
  51. case SqlType.Where:
  52. result = Regex.Replace(bizR._aiWhereResult, @"And\s?$", "");
  53. return result; ;
  54. default: return string.Empty;
  55. }
  56. }
  57. private static string WriteToString(Expression expression)
  58. {
  59. StringWriter sw = new StringWriter();
  60. Write(sw, expression);
  61. return sw.ToString();
  62. }
  63. public static string BizWhereWriteToString(Expression expression, SqlType bizSql)
  64. {
  65. StringWriter sw = new StringWriter();
  66. return Write(sw, expression, bizSql);
  67. }
  68. protected enum Indentation
  69. {
  70. Same,
  71. Inner,
  72. Outer
  73. }
  74. protected int IndentationWidth { get; set; } = 2;
  75. protected void WriteLine(Indentation style)
  76. {
  77. this._writer.WriteLine();
  78. // this.Indent(style);
  79. }
  80. private static readonly char[] Splitters = new char[] { '\n', '\r' };
  81. private void Write(string text)
  82. {
  83. switch (_bizRead)
  84. {
  85. case SqlType.Order:
  86. _aiOrdeRsult = _aiOrdeRsult + text;
  87. break;
  88. case SqlType.Where:
  89. _aiWhereResult = _aiWhereResult + text;
  90. break;
  91. }
  92. this._writer.Write(text);
  93. }
  94. protected void Indent(Indentation style)
  95. {
  96. if (style == Indentation.Inner)
  97. {
  98. // this.depth++;
  99. }
  100. else if (style == Indentation.Outer)
  101. {
  102. // this.depth--;
  103. System.Diagnostics.Debug.Assert(this.depth >= 0);
  104. }
  105. }
  106. protected virtual string GetOperator(ExpressionType type)
  107. {
  108. switch (type)
  109. {
  110. case ExpressionType.Not:
  111. return "!";
  112. case ExpressionType.Add:
  113. case ExpressionType.AddChecked:
  114. return "+";
  115. case ExpressionType.Negate:
  116. case ExpressionType.NegateChecked:
  117. case ExpressionType.Subtract:
  118. case ExpressionType.SubtractChecked:
  119. return "-";
  120. case ExpressionType.Multiply:
  121. case ExpressionType.MultiplyChecked:
  122. return "*";
  123. case ExpressionType.Divide:
  124. return "/";
  125. case ExpressionType.Modulo:
  126. return "%";
  127. case ExpressionType.And:
  128. return "&";
  129. case ExpressionType.AndAlso:
  130. return "And";
  131. case ExpressionType.Or:
  132. return "Or";
  133. case ExpressionType.OrElse:
  134. return "Or";
  135. case ExpressionType.LessThan:
  136. return "<";
  137. case ExpressionType.LessThanOrEqual:
  138. return "<=";
  139. case ExpressionType.GreaterThan:
  140. return ">";
  141. case ExpressionType.GreaterThanOrEqual:
  142. return ">=";
  143. case ExpressionType.Equal:
  144. return "=";
  145. case ExpressionType.NotEqual:
  146. return "!=";
  147. case ExpressionType.Coalesce:
  148. return "??";
  149. case ExpressionType.RightShift:
  150. return ">>";
  151. case ExpressionType.LeftShift:
  152. return "<<";
  153. case ExpressionType.ExclusiveOr:
  154. return "^";
  155. default:
  156. return null;
  157. }
  158. }
  159. protected override Expression VisitBinary(BinaryExpression b)
  160. {
  161. this.Write("(");
  162. if (b.NodeType == ExpressionType.Power)
  163. {
  164. this.Write("POWER(");
  165. this.VisitValue(b.Left);
  166. this.Write(", ");
  167. this.VisitValue(b.Right);
  168. this.Write(")");
  169. // return b;
  170. }
  171. else if (b.NodeType == ExpressionType.Coalesce)
  172. {
  173. this.Write("COALESCE(");
  174. this.VisitValue(b.Left);
  175. this.Write(", ");
  176. Expression right = b.Right;
  177. while (right.NodeType == ExpressionType.Coalesce)
  178. {
  179. BinaryExpression rb = (BinaryExpression)right;
  180. this.VisitValue(rb.Left);
  181. this.Write(", ");
  182. right = rb.Right;
  183. }
  184. this.VisitValue(right);
  185. this.Write(")");
  186. // return b;
  187. }
  188. else if (b.NodeType == ExpressionType.LeftShift)
  189. {
  190. this.Write("(");
  191. this.VisitValue(b.Left);
  192. this.Write(" * POWER(2, ");
  193. this.VisitValue(b.Right);
  194. this.Write("))");
  195. // return b;
  196. }
  197. else if (b.NodeType == ExpressionType.RightShift)
  198. {
  199. this.Write("(");
  200. this.VisitValue(b.Left);
  201. this.Write(" / POWER(2, ");
  202. this.VisitValue(b.Right);
  203. this.Write("))");
  204. //return b;
  205. }
  206. else
  207. {
  208. //if (b.Left is MemberExpression)
  209. //{
  210. // if (((MemberExpression)b.Left).Type == typeof(bool) && (_bizRead == SqlType.Where))
  211. // {
  212. // this.Write("(" + ((MemberExpression)b.Left).Member.Name + " = 1)");
  213. // }
  214. // else
  215. // {
  216. // this.Visit(b.Left);
  217. // }
  218. //}
  219. //else
  220. //{
  221. this.Visit(b.Left);
  222. //}
  223. this.Write(" ");
  224. this.Write(GetOperator(b.NodeType));
  225. this.Write(" ");
  226. this.Visit(b.Right);
  227. }
  228. this.Write(")");
  229. return b;
  230. }
  231. protected override Expression VisitUnary(UnaryExpression u)
  232. {
  233. switch (u.NodeType)
  234. {
  235. case ExpressionType.Convert:
  236. case ExpressionType.ConvertChecked:
  237. //this.Write("((");
  238. //this.Write(this.GetTypeName(u.Type));
  239. // this.Write(")");
  240. this.Visit(u.Operand);
  241. //this.Write(")");
  242. break;
  243. case ExpressionType.ArrayLength:
  244. this.Visit(u.Operand);
  245. this.Write(".Length");
  246. break;
  247. case ExpressionType.Quote:
  248. this.Visit(u.Operand);
  249. break;
  250. case ExpressionType.TypeAs:
  251. this.Visit(u.Operand);
  252. this.Write(" as ");
  253. this.Write(this.GetTypeName(u.Type));
  254. break;
  255. case ExpressionType.UnaryPlus:
  256. this.Visit(u.Operand);
  257. break;
  258. default:
  259. this.Write(this.GetOperator(u.NodeType));
  260. this.Visit(u.Operand);
  261. break;
  262. }
  263. return u;
  264. }
  265. protected virtual string GetTypeName(Type type)
  266. {
  267. string name = type.Name;
  268. name = name.Replace('+', '.');
  269. int iGeneneric = name.IndexOf('`');
  270. if (iGeneneric > 0)
  271. {
  272. name = name.Substring(0, iGeneneric);
  273. }
  274. if (type.IsGenericType || type.IsGenericTypeDefinition)
  275. {
  276. StringBuilder sb = new StringBuilder();
  277. sb.Append(name);
  278. sb.Append("<");
  279. var args = type.GetGenericArguments();
  280. for (int i = 0, n = args.Length; i < n; i++)
  281. {
  282. if (i > 0)
  283. {
  284. sb.Append(",");
  285. }
  286. if (type.IsGenericType)
  287. {
  288. sb.Append(this.GetTypeName(args[i]));
  289. }
  290. }
  291. sb.Append(">");
  292. name = sb.ToString();
  293. }
  294. return name;
  295. }
  296. protected override Expression VisitConditional(ConditionalExpression c)
  297. {
  298. this.Visit(c.Test);
  299. this.WriteLine(Indentation.Inner);
  300. this.Write("? ");
  301. this.Visit(c.IfTrue);
  302. this.WriteLine(Indentation.Same);
  303. this.Write(": ");
  304. this.Visit(c.IfFalse);
  305. this.Indent(Indentation.Outer);
  306. return c;
  307. }
  308. protected override IEnumerable<MemberBinding> VisitBindingList(ReadOnlyCollection<MemberBinding> original)
  309. {
  310. for (int i = 0, n = original.Count; i < n; i++)
  311. {
  312. this.VisitBinding(original[i]);
  313. if (i < n - 1)
  314. {
  315. this.Write(",");
  316. this.WriteLine(Indentation.Same);
  317. }
  318. }
  319. return original;
  320. }
  321. private static readonly char[] Special = new char[] { '\n', '\n', '\\' };
  322. protected override Expression VisitConstant(ConstantExpression c)
  323. {
  324. if (c.Value == null)
  325. {
  326. this.Write("null");
  327. }
  328. else if (c.Type == typeof(DateTime) || c.Type == typeof(Guid))
  329. {
  330. this.Write("'");//new DateTime(\"
  331. this.Write(c.Value.ToString());
  332. this.Write("'");//\"
  333. }
  334. else
  335. {
  336. switch (Type.GetTypeCode(c.Value.GetType()))
  337. {
  338. case TypeCode.Boolean:
  339. //if (c.NodeType != ExpressionType.Constant)
  340. this.Write(((bool)c.Value) ? "1" : "0");
  341. break;
  342. case TypeCode.Single:
  343. case TypeCode.Double:
  344. string str = c.Value.ToString();
  345. if (!str.Contains('.'))
  346. {
  347. str += ".0";
  348. }
  349. this.Write(str);
  350. break;
  351. case TypeCode.DateTime:
  352. this.Write("'");//new DateTime(\"
  353. this.Write(c.Value.ToString());
  354. this.Write("'");//\"
  355. break;
  356. case TypeCode.String:
  357. this.Write("'");
  358. this.Write(c.Value.ToString().Replace("'", "\""));
  359. this.Write("'");
  360. break;
  361. default:
  362. this.Write(c.Value.ToString());
  363. break;
  364. }
  365. }
  366. return c;
  367. }
  368. protected override ElementInit VisitElementInitializer(ElementInit initializer)
  369. {
  370. if (initializer.Arguments.Count > 1)
  371. {
  372. this.Write("{");
  373. for (int i = 0, n = initializer.Arguments.Count; i < n; i++)
  374. {
  375. this.Visit(initializer.Arguments[i]);
  376. if (i < n - 1)
  377. {
  378. this.Write(", ");
  379. }
  380. }
  381. this.Write("}");
  382. }
  383. else
  384. {
  385. this.Visit(initializer.Arguments[0]);
  386. }
  387. return initializer;
  388. }
  389. protected override IEnumerable<ElementInit> VisitElementInitializerList(ReadOnlyCollection<ElementInit> original)
  390. {
  391. for (int i = 0, n = original.Count; i < n; i++)
  392. {
  393. this.VisitElementInitializer(original[i]);
  394. if (i < n - 1)
  395. {
  396. this.Write(",");
  397. this.WriteLine(Indentation.Same);
  398. }
  399. }
  400. return original;
  401. }
  402. protected override ReadOnlyCollection<Expression> VisitExpressionList(ReadOnlyCollection<Expression> original)
  403. {
  404. for (int i = 0, n = original.Count; i < n; i++)
  405. {
  406. this.Visit(original[i]);
  407. //if (i < n - 1)
  408. //{
  409. // this.Write(",");
  410. // this.WriteLine(Indentation.Same);
  411. //}
  412. }
  413. return original;
  414. }
  415. protected override Expression VisitInvocation(InvocationExpression iv)
  416. {
  417. this.Write("Invoke(");
  418. this.WriteLine(Indentation.Inner);
  419. this.VisitExpressionList(iv.Arguments);
  420. this.Write(", ");
  421. this.WriteLine(Indentation.Same);
  422. this.Visit(iv.Expression);
  423. this.WriteLine(Indentation.Same);
  424. this.Write(")");
  425. this.Indent(Indentation.Outer);
  426. return iv;
  427. }
  428. protected override Expression VisitLambda(LambdaExpression lambda)
  429. {
  430. if (lambda.Body.NodeType == ExpressionType.MemberAccess)
  431. {
  432. if (((MemberExpression)lambda.Body).Type == typeof(bool) && (_bizRead == SqlType.Where))
  433. {
  434. this.Write(((MemberExpression)lambda.Body).Member.Name + " = 1");
  435. }
  436. else
  437. {
  438. this.Visit(lambda.Body);
  439. return lambda;
  440. }
  441. }
  442. this.Visit(lambda.Body);
  443. return lambda;
  444. }
  445. protected override Expression VisitListInit(ListInitExpression init)
  446. {
  447. this.Visit(init.NewExpression);
  448. this.Write(" {");
  449. this.WriteLine(Indentation.Inner);
  450. this.VisitElementInitializerList(init.Initializers);
  451. this.WriteLine(Indentation.Outer);
  452. this.Write("}");
  453. return init;
  454. }
  455. protected override Expression VisitMemberAccess(MemberExpression m)
  456. {
  457. this.Write(m.Member.Name);
  458. // string t = m.Update.GetType().Name;
  459. if (m.Member.DeclaringType == typeof(string))
  460. {
  461. switch (m.Member.Name)
  462. {
  463. case "Length":
  464. this.Write("LEN(");
  465. this.Visit(m.Expression);
  466. this.Write(")");
  467. return m;
  468. }
  469. }
  470. else if (m.Member.DeclaringType == typeof(DateTime) || m.Member.DeclaringType == typeof(DateTimeOffset))
  471. {
  472. switch (m.Member.Name)
  473. {
  474. case "Day":
  475. this.Write("DAY(");
  476. this.Visit(m.Expression);
  477. this.Write(")");
  478. return m;
  479. case "Month":
  480. this.Write("MONTH(");
  481. this.Visit(m.Expression);
  482. this.Write(")");
  483. return m;
  484. case "Year":
  485. this.Write("YEAR(");
  486. this.Visit(m.Expression);
  487. this.Write(")");
  488. return m;
  489. case "Hour":
  490. this.Write("DATEPART(hour, ");
  491. this.Visit(m.Expression);
  492. this.Write(")");
  493. return m;
  494. case "Minute":
  495. this.Write("DATEPART(minute, ");
  496. this.Visit(m.Expression);
  497. this.Write(")");
  498. return m;
  499. case "Second":
  500. this.Write("DATEPART(second, ");
  501. this.Visit(m.Expression);
  502. this.Write(")");
  503. return m;
  504. case "Millisecond":
  505. this.Write("DATEPART(millisecond, ");
  506. this.Visit(m.Expression);
  507. this.Write(")");
  508. return m;
  509. case "DayOfWeek":
  510. this.Write("(DATEPART(weekday, ");
  511. this.Visit(m.Expression);
  512. this.Write(") - 1)");
  513. return m;
  514. case "DayOfYear":
  515. this.Write("(DATEPART(dayofyear, ");
  516. this.Visit(m.Expression);
  517. this.Write(") - 1)");
  518. return m;
  519. }
  520. }
  521. return base.VisitMemberAccess(m);
  522. }
  523. protected override MemberAssignment VisitMemberAssignment(MemberAssignment assignment)
  524. {
  525. this.Write(assignment.Member.Name);
  526. this.Write(" = ");
  527. this.Visit(assignment.Expression);
  528. return assignment;
  529. }
  530. protected override Expression VisitMemberInit(MemberInitExpression init)
  531. {
  532. this.Visit(init.NewExpression);
  533. this.Write(" {");
  534. this.WriteLine(Indentation.Inner);
  535. this.VisitBindingList(init.Bindings);
  536. this.WriteLine(Indentation.Outer);
  537. this.Write("}");
  538. return init;
  539. }
  540. protected override MemberListBinding VisitMemberListBinding(MemberListBinding binding)
  541. {
  542. this.Write(binding.Member.Name);
  543. this.Write(" = {");
  544. this.WriteLine(Indentation.Inner);
  545. this.VisitElementInitializerList(binding.Initializers);
  546. this.WriteLine(Indentation.Outer);
  547. this.Write("}");
  548. return binding;
  549. }
  550. protected override MemberMemberBinding VisitMemberMemberBinding(MemberMemberBinding binding)
  551. {
  552. this.Write(binding.Member.Name);
  553. this.Write(" = {");
  554. this.WriteLine(Indentation.Inner);
  555. this.VisitBindingList(binding.Bindings);
  556. this.WriteLine(Indentation.Outer);
  557. this.Write("}");
  558. return binding;
  559. }
  560. protected override Expression VisitMethodCall(MethodCallExpression m)
  561. {
  562. //if (m.Object != null)
  563. //{
  564. // this.Visit(m.Object);
  565. //}
  566. //else
  567. //{
  568. // this.Write(this.GetTypeName(m.Method.DeclaringType));
  569. //}
  570. string bizname = m.Method.Name.ToLower();
  571. //if (this.GetTypeName(m.Method.DeclaringType).ToLower() != "queryable")
  572. //{
  573. // this.Write(".");
  574. //}
  575. // this.Write(m.Method.Name);
  576. switch (bizname)
  577. {
  578. case "where":
  579. if (_bizRead == SqlType.Where)
  580. {
  581. AiWhereTime = AiWhereTime + 1;
  582. }
  583. else
  584. {
  585. this.Visit(m.Arguments[0]);
  586. return m;
  587. }
  588. break;
  589. case "orderby":
  590. case "orderbydescending":
  591. case "thenbydescending":
  592. case "thenby":
  593. if (_bizRead == SqlType.Order)
  594. {
  595. AiOrderTime = AiOrderTime + 1;
  596. }
  597. else
  598. {
  599. this.Visit(m.Arguments[0]);
  600. return m;
  601. }
  602. break;
  603. }
  604. //bool bizisw = bizname == "where" || bizname == "orderby" || bizname == "thenby";
  605. //if (bizisw)
  606. //{
  607. // this.Write(m.Method.Name);
  608. //}
  609. //this.VisitExpressionList(m.Arguments);
  610. if (m.Arguments.Count > 1)
  611. {
  612. }
  613. // this.WriteLine(Indentation.Outer);
  614. //if (bizisw)
  615. //{
  616. // this.Write(")");
  617. //}
  618. //return m;
  619. #region
  620. if (m.Method.DeclaringType == typeof(string))
  621. {
  622. switch (m.Method.Name)
  623. {
  624. case "StartsWith":
  625. this.Write("(");
  626. this.Visit(m.Object);
  627. this.Write(" LIKE '");
  628. this.Visit(m.Arguments[0]);
  629. this.Write("%')");
  630. return m;
  631. case "EndsWith":
  632. this.Write("(");
  633. this.Visit(m.Object);
  634. this.Write(" LIKE '%");
  635. this.Visit(m.Arguments[0]);
  636. this.Write("')");
  637. return m;
  638. case "Contains":
  639. this.Write("(");
  640. this.Visit(m.Object);
  641. this.Write(" LIKE '%");
  642. this.Visit(m.Arguments[0]);
  643. this.Write("%')");
  644. return m;
  645. case "Concat":
  646. IList<Expression> args = m.Arguments;
  647. if (args.Count == 1 && args[0].NodeType == ExpressionType.NewArrayInit)
  648. {
  649. args = ((NewArrayExpression)args[0]).Expressions;
  650. }
  651. for (int i = 0, n = args.Count; i < n; i++)
  652. {
  653. if (i > 0) this.Write(" + ");
  654. this.Visit(args[i]);
  655. }
  656. return m;
  657. case "IsNullOrEmpty":
  658. this.Write("(");
  659. this.Visit(m.Arguments[0]);
  660. this.Write(" IS NULL OR ");
  661. this.Visit(m.Arguments[0]);
  662. this.Write(" = '')");
  663. return m;
  664. case "ToUpper":
  665. this.Write("UPPER(");
  666. this.Visit(m.Object);
  667. this.Write(")");
  668. return m;
  669. case "ToLower":
  670. this.Write("LOWER(");
  671. this.Visit(m.Object);
  672. this.Write(")");
  673. return m;
  674. case "Replace":
  675. this.Write("REPLACE(");
  676. this.Visit(m.Object);
  677. this.Write(", ");
  678. this.Visit(m.Arguments[0]);
  679. this.Write(", ");
  680. this.Visit(m.Arguments[1]);
  681. this.Write(")");
  682. return m;
  683. case "Substring":
  684. this.Write("SUBSTRING(");
  685. this.Visit(m.Object);
  686. this.Write(", ");
  687. this.Visit(m.Arguments[0]);
  688. this.Write(" + 1, ");
  689. if (m.Arguments.Count == 2)
  690. {
  691. this.Visit(m.Arguments[1]);
  692. }
  693. else
  694. {
  695. this.Write("8000");
  696. }
  697. this.Write(")");
  698. return m;
  699. case "Remove":
  700. this.Write("STUFF(");
  701. this.Visit(m.Object);
  702. this.Write(", ");
  703. this.Visit(m.Arguments[0]);
  704. this.Write(" + 1, ");
  705. if (m.Arguments.Count == 2)
  706. {
  707. this.Visit(m.Arguments[1]);
  708. }
  709. else
  710. {
  711. this.Write("8000");
  712. }
  713. this.Write(", '')");
  714. return m;
  715. case "IndexOf":
  716. this.Write("(CHARINDEX(");
  717. this.Visit(m.Arguments[0]);
  718. this.Write(", ");
  719. this.Visit(m.Object);
  720. if (m.Arguments.Count == 2 && m.Arguments[1].Type == typeof(int))
  721. {
  722. this.Write(", ");
  723. this.Visit(m.Arguments[1]);
  724. this.Write(" + 1");
  725. }
  726. this.Write(") - 1)");
  727. return m;
  728. case "Trim":
  729. this.Write("RTRIM(LTRIM(");
  730. this.Visit(m.Object);
  731. this.Write("))");
  732. return m;
  733. }
  734. }
  735. else if (m.Method.DeclaringType == typeof(DateTime))
  736. {
  737. switch (m.Method.Name)
  738. {
  739. case "op_Subtract":
  740. if (m.Arguments[1].Type == typeof(DateTime))
  741. {
  742. this.Write("DATEDIFF(");
  743. this.Visit(m.Arguments[0]);
  744. this.Write(", ");
  745. this.Visit(m.Arguments[1]);
  746. this.Write(")");
  747. return m;
  748. }
  749. break;
  750. case "AddYears":
  751. this.Write("DATEADD(YYYY,");
  752. this.Visit(m.Arguments[0]);
  753. this.Write(",");
  754. this.Visit(m.Object);
  755. this.Write(")");
  756. return m;
  757. case "AddMonths":
  758. this.Write("DATEADD(MM,");
  759. this.Visit(m.Arguments[0]);
  760. this.Write(",");
  761. this.Visit(m.Object);
  762. this.Write(")");
  763. return m;
  764. case "AddDays":
  765. this.Write("DATEADD(DAY,");
  766. this.Visit(m.Arguments[0]);
  767. this.Write(",");
  768. this.Visit(m.Object);
  769. this.Write(")");
  770. return m;
  771. case "AddHours":
  772. this.Write("DATEADD(HH,");
  773. this.Visit(m.Arguments[0]);
  774. this.Write(",");
  775. this.Visit(m.Object);
  776. this.Write(")");
  777. return m;
  778. case "AddMinutes":
  779. this.Write("DATEADD(MI,");
  780. this.Visit(m.Arguments[0]);
  781. this.Write(",");
  782. this.Visit(m.Object);
  783. this.Write(")");
  784. return m;
  785. case "AddSeconds":
  786. this.Write("DATEADD(SS,");
  787. this.Visit(m.Arguments[0]);
  788. this.Write(",");
  789. this.Visit(m.Object);
  790. this.Write(")");
  791. return m;
  792. case "AddMilliseconds":
  793. this.Write("DATEADD(MS,");
  794. this.Visit(m.Arguments[0]);
  795. this.Write(",");
  796. this.Visit(m.Object);
  797. this.Write(")");
  798. return m;
  799. }
  800. }
  801. else if (m.Method.DeclaringType == typeof(Decimal))
  802. {
  803. switch (m.Method.Name)
  804. {
  805. case "Add":
  806. case "Subtract":
  807. case "Multiply":
  808. case "Divide":
  809. case "Remainder":
  810. this.Write("(");
  811. this.VisitValue(m.Arguments[0]);
  812. this.Write(" ");
  813. this.Write(GetOperator(m.Method.Name));
  814. this.Write(" ");
  815. this.VisitValue(m.Arguments[1]);
  816. this.Write(")");
  817. return m;
  818. case "Negate":
  819. this.Write("-");
  820. this.Visit(m.Arguments[0]);
  821. this.Write("");
  822. return m;
  823. case "Ceiling":
  824. case "Floor":
  825. this.Write(m.Method.Name.ToUpper());
  826. this.Write("(");
  827. this.Visit(m.Arguments[0]);
  828. this.Write(")");
  829. return m;
  830. case "Round":
  831. if (m.Arguments.Count == 1)
  832. {
  833. this.Write("ROUND(");
  834. this.Visit(m.Arguments[0]);
  835. this.Write(", 0)");
  836. return m;
  837. }
  838. else if (m.Arguments.Count == 2 && m.Arguments[1].Type == typeof(int))
  839. {
  840. this.Write("ROUND(");
  841. this.Visit(m.Arguments[0]);
  842. this.Write(", ");
  843. this.Visit(m.Arguments[1]);
  844. this.Write(")");
  845. return m;
  846. }
  847. break;
  848. case "Truncate":
  849. this.Write("ROUND(");
  850. this.Visit(m.Arguments[0]);
  851. this.Write(", 0, 1)");
  852. return m;
  853. }
  854. }
  855. else if (m.Method.DeclaringType == typeof(Math))
  856. {
  857. switch (m.Method.Name)
  858. {
  859. case "Abs":
  860. case "Acos":
  861. case "Asin":
  862. case "Atan":
  863. case "Cos":
  864. case "Exp":
  865. case "Log10":
  866. case "Sin":
  867. case "Tan":
  868. case "Sqrt":
  869. case "Sign":
  870. case "Ceiling":
  871. case "Floor":
  872. this.Write(m.Method.Name.ToUpper());
  873. this.Write("(");
  874. this.Visit(m.Arguments[0]);
  875. this.Write(")");
  876. return m;
  877. case "Atan2":
  878. this.Write("ATN2(");
  879. this.Visit(m.Arguments[0]);
  880. this.Write(", ");
  881. this.Visit(m.Arguments[1]);
  882. this.Write(")");
  883. return m;
  884. case "Log":
  885. if (m.Arguments.Count == 1)
  886. {
  887. goto case "Log10";
  888. }
  889. break;
  890. case "Pow":
  891. this.Write("POWER(");
  892. this.Visit(m.Arguments[0]);
  893. this.Write(", ");
  894. this.Visit(m.Arguments[1]);
  895. this.Write(")");
  896. return m;
  897. case "Round":
  898. if (m.Arguments.Count == 1)
  899. {
  900. this.Write("ROUND(");
  901. this.Visit(m.Arguments[0]);
  902. this.Write(", 0)");
  903. return m;
  904. }
  905. else if (m.Arguments.Count == 2 && m.Arguments[1].Type == typeof(int))
  906. {
  907. this.Write("ROUND(");
  908. this.Visit(m.Arguments[0]);
  909. this.Write(", ");
  910. this.Visit(m.Arguments[1]);
  911. this.Write(")");
  912. return m;
  913. }
  914. break;
  915. case "Truncate":
  916. this.Write("ROUND(");
  917. this.Visit(m.Arguments[0]);
  918. this.Write(", 0, 1)");
  919. return m;
  920. }
  921. }
  922. if (m.Method.Name == "ToString")
  923. {
  924. if (m.Object.Type != typeof(string))
  925. {
  926. this.Write("CONVERT(NVARCHAR, ");
  927. this.Visit(m.Object);
  928. this.Write(")");
  929. }
  930. else
  931. {
  932. this.Visit(m.Object);
  933. }
  934. return m;
  935. }
  936. else if (!m.Method.IsStatic && m.Method.Name == "CompareTo" && m.Method.ReturnType == typeof(int) && m.Arguments.Count == 1)
  937. {
  938. this.Write("(CASE WHEN ");
  939. this.Visit(m.Object);
  940. this.Write(" = ");
  941. this.Visit(m.Arguments[0]);
  942. this.Write(" THEN 0 WHEN ");
  943. this.Visit(m.Object);
  944. this.Write(" < ");
  945. this.Visit(m.Arguments[0]);
  946. this.Write(" THEN -1 ELSE 1 END)");
  947. return m;
  948. }
  949. else if (m.Method.IsStatic && m.Method.Name == "Compare" && m.Method.ReturnType == typeof(int) && m.Arguments.Count == 2)
  950. {
  951. this.Write("(CASE WHEN ");
  952. this.Visit(m.Arguments[0]);
  953. this.Write(" = ");
  954. this.Visit(m.Arguments[1]);
  955. this.Write(" THEN 0 WHEN ");
  956. this.Visit(m.Arguments[0]);
  957. this.Write(" < ");
  958. this.Visit(m.Arguments[1]);
  959. this.Write(" THEN -1 ELSE 1 END)");
  960. return m;
  961. }
  962. #endregion
  963. if (m.Arguments.Count > 1)
  964. {
  965. this.WriteLine(Indentation.Outer);
  966. }
  967. base.VisitMethodCall(m);
  968. if (m.Arguments.Count > 1)
  969. {
  970. switch (bizname)
  971. {
  972. case "orderbydescending":
  973. case "thenbydescending": _aiOrdeRsult = _aiOrdeRsult + " Desc"; break;
  974. }
  975. if (_bizRead == SqlType.Order)
  976. {
  977. _aiOrdeRsult = _aiOrdeRsult + ",";
  978. }
  979. else
  980. {
  981. _aiWhereResult = _aiWhereResult + " And ";
  982. }
  983. this.WriteLine(Indentation.Outer);
  984. }
  985. return m;
  986. }
  987. private Expression VisitValue(Expression expr)
  988. {
  989. if (IsPredicate(expr))
  990. {
  991. this.Write("CASE WHEN (");
  992. this.Visit(expr);
  993. this.Write(") THEN 1 ELSE 0 END");
  994. return expr;
  995. }
  996. return expr;
  997. }
  998. protected override NewExpression VisitNew(NewExpression nex)
  999. {
  1000. //this.Write("new ");
  1001. //this.Write(this.GetTypeName(nex.Constructor.DeclaringType));
  1002. //this.Write("(");
  1003. //if (nex.Arguments.Count > 1)
  1004. // this.WriteLine(Indentation.Inner);
  1005. //this.VisitExpressionList(nex.Arguments);
  1006. //if (nex.Arguments.Count > 1)
  1007. // this.WriteLine(Indentation.Outer);
  1008. //this.Write(")");
  1009. //return nex;
  1010. if (nex.Constructor.DeclaringType == typeof(DateTime))
  1011. {
  1012. if (nex.Arguments.Count == 3)
  1013. {
  1014. this.Write("Convert(DateTime, ");
  1015. this.Write("Convert(nvarchar, ");
  1016. this.Visit(nex.Arguments[0]);
  1017. this.Write(") + '/' + ");
  1018. this.Write("Convert(nvarchar, ");
  1019. this.Visit(nex.Arguments[1]);
  1020. this.Write(") + '/' + ");
  1021. this.Write("Convert(nvarchar, ");
  1022. this.Visit(nex.Arguments[2]);
  1023. this.Write("))");
  1024. return nex;
  1025. }
  1026. else if (nex.Arguments.Count == 6)
  1027. {
  1028. this.Write("Convert(DateTime, ");
  1029. this.Write("Convert(nvarchar, ");
  1030. this.Visit(nex.Arguments[0]);
  1031. this.Write(") + '/' + ");
  1032. this.Write("Convert(nvarchar, ");
  1033. this.Visit(nex.Arguments[1]);
  1034. this.Write(") + '/' + ");
  1035. this.Write("Convert(nvarchar, ");
  1036. this.Visit(nex.Arguments[2]);
  1037. this.Write(") + ' ' + ");
  1038. this.Write("Convert(nvarchar, ");
  1039. this.Visit(nex.Arguments[3]);
  1040. this.Write(") + ':' + ");
  1041. this.Write("Convert(nvarchar, ");
  1042. this.Visit(nex.Arguments[4]);
  1043. this.Write(") + ':' + ");
  1044. this.Write("Convert(nvarchar, ");
  1045. this.Visit(nex.Arguments[5]);
  1046. this.Write("))");
  1047. return nex;
  1048. }
  1049. }
  1050. return base.VisitNew(nex);
  1051. }
  1052. protected override Expression VisitNewArray(NewArrayExpression na)
  1053. {
  1054. this.Write("new ");
  1055. this.Write(this.GetTypeName(TypeHelper.GetElementType(na.Type)));
  1056. this.Write("[] {");
  1057. if (na.Expressions.Count > 1)
  1058. this.WriteLine(Indentation.Inner);
  1059. this.VisitExpressionList(na.Expressions);
  1060. if (na.Expressions.Count > 1)
  1061. this.WriteLine(Indentation.Outer);
  1062. this.Write("}");
  1063. return na;
  1064. }
  1065. protected override Expression VisitParameter(ParameterExpression p)
  1066. {
  1067. // this.Write(p.Name);
  1068. return p;
  1069. }
  1070. protected override Expression VisitTypeIs(TypeBinaryExpression b)
  1071. {
  1072. this.Visit(b.Expression);
  1073. this.Write(" is ");
  1074. this.Write(this.GetTypeName(b.TypeOperand));
  1075. return b;
  1076. }
  1077. protected override Expression VisitUnknown(Expression expression)
  1078. {
  1079. this.Write(expression.ToString());
  1080. return expression;
  1081. }
  1082. protected virtual bool IsBoolean(Type type)
  1083. {
  1084. return type == typeof(bool) || type == typeof(bool?);
  1085. }
  1086. protected virtual bool IsPredicate(Expression expr)
  1087. {
  1088. switch (expr.NodeType)
  1089. {
  1090. case ExpressionType.And:
  1091. case ExpressionType.AndAlso:
  1092. case ExpressionType.Or:
  1093. case ExpressionType.OrElse:
  1094. return IsBoolean(((BinaryExpression)expr).Type);
  1095. case ExpressionType.Not:
  1096. return IsBoolean(((UnaryExpression)expr).Type);
  1097. case ExpressionType.Equal:
  1098. case ExpressionType.NotEqual:
  1099. case ExpressionType.LessThan:
  1100. case ExpressionType.LessThanOrEqual:
  1101. case ExpressionType.GreaterThan:
  1102. case ExpressionType.GreaterThanOrEqual:
  1103. case (ExpressionType)DbExpressionType.IsNull:
  1104. case (ExpressionType)DbExpressionType.Between:
  1105. case (ExpressionType)DbExpressionType.Exists:
  1106. case (ExpressionType)DbExpressionType.In:
  1107. return true;
  1108. case ExpressionType.Call:
  1109. return IsBoolean(((MethodCallExpression)expr).Type);
  1110. default:
  1111. return false;
  1112. }
  1113. }
  1114. internal enum DbExpressionType
  1115. {
  1116. Table = 1000, // make sure these don't overlap with ExpressionType
  1117. ClientJoin,
  1118. Column,
  1119. Select,
  1120. Projection,
  1121. Entity,
  1122. Join,
  1123. Aggregate,
  1124. Scalar,
  1125. Exists,
  1126. In,
  1127. Grouping,
  1128. AggregateSubquery,
  1129. IsNull,
  1130. Between,
  1131. RowCount,
  1132. NamedValue,
  1133. OuterJoined,
  1134. Insert,
  1135. Update,
  1136. Delete,
  1137. Batch,
  1138. Function,
  1139. Block,
  1140. If,
  1141. Declaration,
  1142. Variable
  1143. }
  1144. protected virtual string GetOperator(string methodName)
  1145. {
  1146. switch (methodName)
  1147. {
  1148. case "Add": return "+";
  1149. case "Subtract": return "-";
  1150. case "Multiply": return "*";
  1151. case "Divide": return "/";
  1152. case "Negate": return "-";
  1153. case "Remainder": return "%";
  1154. default: return null;
  1155. }
  1156. }
  1157. protected virtual string GetOperator(UnaryExpression u)
  1158. {
  1159. switch (u.NodeType)
  1160. {
  1161. case ExpressionType.Negate:
  1162. case ExpressionType.NegateChecked:
  1163. return "-";
  1164. case ExpressionType.UnaryPlus:
  1165. return "+";
  1166. case ExpressionType.Not:
  1167. return IsBoolean(u.Operand.Type) ? "NOT" : "~";
  1168. default:
  1169. return "";
  1170. }
  1171. }
  1172. protected virtual string GetOperator(BinaryExpression b)
  1173. {
  1174. switch (b.NodeType)
  1175. {
  1176. case ExpressionType.And:
  1177. case ExpressionType.AndAlso:
  1178. return (IsBoolean(b.Left.Type)) ? "AND" : "&";
  1179. case ExpressionType.Or:
  1180. case ExpressionType.OrElse:
  1181. return (IsBoolean(b.Left.Type) ? "OR" : "|");
  1182. case ExpressionType.Equal:
  1183. return "=";
  1184. case ExpressionType.NotEqual:
  1185. return "<>";
  1186. case ExpressionType.LessThan:
  1187. return "<";
  1188. case ExpressionType.LessThanOrEqual:
  1189. return "<=";
  1190. case ExpressionType.GreaterThan:
  1191. return ">";
  1192. case ExpressionType.GreaterThanOrEqual:
  1193. return ">=";
  1194. case ExpressionType.Add:
  1195. case ExpressionType.AddChecked:
  1196. return "+";
  1197. case ExpressionType.Subtract:
  1198. case ExpressionType.SubtractChecked:
  1199. return "-";
  1200. case ExpressionType.Multiply:
  1201. case ExpressionType.MultiplyChecked:
  1202. return "*";
  1203. case ExpressionType.Divide:
  1204. return "/";
  1205. case ExpressionType.Modulo:
  1206. return "%";
  1207. case ExpressionType.ExclusiveOr:
  1208. return "^";
  1209. case ExpressionType.LeftShift:
  1210. return "<<";
  1211. case ExpressionType.RightShift:
  1212. return ">>";
  1213. default:
  1214. return "";
  1215. }
  1216. }
  1217. }
  1218. }