SqlGenerator.cs 28 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880
  1. using Ant.Core;
  2. using Ant.Data;
  3. using Ant.DbExpressions;
  4. using Ant.ORM;
  5. using System;
  6. using System.Collections;
  7. using System.Collections.Generic;
  8. using System.Collections.ObjectModel;
  9. using System.Linq;
  10. using System.Reflection;
  11. using System.Text;
  12. namespace Ant.MySql
  13. {
  14. partial class SqlGenerator : DbExpressionVisitor<DbExpression>
  15. {
  16. public const string ParameterPrefix = "?P_";
  17. internal ISqlBuilder _sqlBuilder = new SqlBuilder();
  18. List<DbParam> _parameters = new List<DbParam>();
  19. static readonly Dictionary<string, Action<DbMethodCallExpression, SqlGenerator>> MethodHandlers = InitMethodHandlers();
  20. static readonly Dictionary<string, Action<DbAggregateExpression, SqlGenerator>> AggregateHandlers = InitAggregateHandlers();
  21. static readonly Dictionary<MethodInfo, Action<DbBinaryExpression, SqlGenerator>> BinaryWithMethodHandlers = InitBinaryWithMethodHandlers();
  22. static readonly Dictionary<Type, string> CastTypeMap = null;
  23. static readonly List<string> CacheParameterNames = null;
  24. static SqlGenerator()
  25. {
  26. Dictionary<Type, string> castTypeMap = new Dictionary<Type, string>();
  27. castTypeMap.Add(typeof(string), "CHAR");
  28. castTypeMap.Add(typeof(byte), "UNSIGNED");
  29. castTypeMap.Add(typeof(sbyte), "SIGNED");
  30. castTypeMap.Add(typeof(Int16), "SIGNED");
  31. castTypeMap.Add(typeof(UInt16), "UNSIGNED");
  32. castTypeMap.Add(typeof(int), "SIGNED");
  33. castTypeMap.Add(typeof(uint), "UNSIGNED");
  34. castTypeMap.Add(typeof(long), "SIGNED");
  35. castTypeMap.Add(typeof(ulong), "UNSIGNED");
  36. castTypeMap.Add(typeof(DateTime), "DATETIME");
  37. castTypeMap.Add(typeof(bool), "SIGNED");
  38. CastTypeMap = Utils.Clone(castTypeMap);
  39. int cacheParameterNameCount = 2 * 12;
  40. List<string> cacheParameterNames = new List<string>(cacheParameterNameCount);
  41. for (int i = 0; i < cacheParameterNameCount; i++)
  42. {
  43. string paramName = ParameterPrefix + i.ToString();
  44. cacheParameterNames.Add(paramName);
  45. }
  46. CacheParameterNames = cacheParameterNames;
  47. }
  48. public ISqlBuilder SqlBuilder { get { return this._sqlBuilder; } }
  49. public List<DbParam> Parameters { get { return this._parameters; } }
  50. public static SqlGenerator CreateInstance()
  51. {
  52. return new SqlGenerator();
  53. }
  54. public override DbExpression Visit(DbEqualExpression exp)
  55. {
  56. DbExpression left = exp.Left;
  57. DbExpression right = exp.Right;
  58. left = DbExpressionExtensions.ParseDbExpression(left);
  59. right = DbExpressionExtensions.ParseDbExpression(right);
  60. //明确 left right 其中一边一定为 null
  61. if (DbExpressionExtensions.AffirmExpressionRetValueIsNull(right))
  62. {
  63. left.Accept(this);
  64. this._sqlBuilder.Append(" IS NULL");
  65. return exp;
  66. }
  67. if (DbExpressionExtensions.AffirmExpressionRetValueIsNull(left))
  68. {
  69. right.Accept(this);
  70. this._sqlBuilder.Append(" IS NULL");
  71. return exp;
  72. }
  73. left.Accept(this);
  74. this._sqlBuilder.Append(" = ");
  75. right.Accept(this);
  76. return exp;
  77. }
  78. public override DbExpression Visit(DbNotEqualExpression exp)
  79. {
  80. DbExpression left = exp.Left;
  81. DbExpression right = exp.Right;
  82. left = DbExpressionExtensions.ParseDbExpression(left);
  83. right = DbExpressionExtensions.ParseDbExpression(right);
  84. //明确 left right 其中一边一定为 null
  85. if (DbExpressionExtensions.AffirmExpressionRetValueIsNull(right))
  86. {
  87. left.Accept(this);
  88. this._sqlBuilder.Append(" IS NOT NULL");
  89. return exp;
  90. }
  91. if (DbExpressionExtensions.AffirmExpressionRetValueIsNull(left))
  92. {
  93. right.Accept(this);
  94. this._sqlBuilder.Append(" IS NOT NULL");
  95. return exp;
  96. }
  97. left.Accept(this);
  98. this._sqlBuilder.Append(" <> ");
  99. right.Accept(this);
  100. return exp;
  101. }
  102. public override DbExpression Visit(DbNotExpression exp)
  103. {
  104. this._sqlBuilder.Append("NOT ");
  105. this._sqlBuilder.Append("(");
  106. exp.Operand.Accept(this);
  107. this._sqlBuilder.Append(")");
  108. return exp;
  109. }
  110. public override DbExpression Visit(DbAndExpression exp)
  111. {
  112. Stack<DbExpression> operands = GatherBinaryExpressionOperand(exp);
  113. this.ConcatOperands(operands, " & ");
  114. return exp;
  115. }
  116. public override DbExpression Visit(DbAndAlsoExpression exp)
  117. {
  118. Stack<DbExpression> operands = GatherBinaryExpressionOperand(exp);
  119. this.ConcatOperands(operands, " AND ");
  120. return exp;
  121. }
  122. public override DbExpression Visit(DbOrExpression exp)
  123. {
  124. Stack<DbExpression> operands = GatherBinaryExpressionOperand(exp);
  125. this.ConcatOperands(operands, " | ");
  126. return exp;
  127. }
  128. public override DbExpression Visit(DbOrElseExpression exp)
  129. {
  130. Stack<DbExpression> operands = GatherBinaryExpressionOperand(exp);
  131. this.ConcatOperands(operands, " OR ");
  132. return exp;
  133. }
  134. // +
  135. public override DbExpression Visit(DbAddExpression exp)
  136. {
  137. MethodInfo method = exp.Method;
  138. if (method != null)
  139. {
  140. Action<DbBinaryExpression, SqlGenerator> handler;
  141. if (BinaryWithMethodHandlers.TryGetValue(method, out handler))
  142. {
  143. handler(exp, this);
  144. return exp;
  145. }
  146. throw UtilExceptions.NotSupportedMethod(exp.Method);
  147. }
  148. Stack<DbExpression> operands = GatherBinaryExpressionOperand(exp);
  149. this.ConcatOperands(operands, " + ");
  150. return exp;
  151. }
  152. // -
  153. public override DbExpression Visit(DbSubtractExpression exp)
  154. {
  155. Stack<DbExpression> operands = GatherBinaryExpressionOperand(exp);
  156. this.ConcatOperands(operands, " - ");
  157. return exp;
  158. }
  159. // *
  160. public override DbExpression Visit(DbMultiplyExpression exp)
  161. {
  162. Stack<DbExpression> operands = GatherBinaryExpressionOperand(exp);
  163. this.ConcatOperands(operands, " * ");
  164. return exp;
  165. }
  166. // /
  167. public override DbExpression Visit(DbDivideExpression exp)
  168. {
  169. Stack<DbExpression> operands = GatherBinaryExpressionOperand(exp);
  170. this.ConcatOperands(operands, " / ");
  171. return exp;
  172. }
  173. // <
  174. public override DbExpression Visit(DbLessThanExpression exp)
  175. {
  176. exp.Left.Accept(this);
  177. this._sqlBuilder.Append(" < ");
  178. exp.Right.Accept(this);
  179. return exp;
  180. }
  181. // <=
  182. public override DbExpression Visit(DbLessThanOrEqualExpression exp)
  183. {
  184. exp.Left.Accept(this);
  185. this._sqlBuilder.Append(" <= ");
  186. exp.Right.Accept(this);
  187. return exp;
  188. }
  189. // >
  190. public override DbExpression Visit(DbGreaterThanExpression exp)
  191. {
  192. exp.Left.Accept(this);
  193. this._sqlBuilder.Append(" > ");
  194. exp.Right.Accept(this);
  195. return exp;
  196. }
  197. // >=
  198. public override DbExpression Visit(DbGreaterThanOrEqualExpression exp)
  199. {
  200. exp.Left.Accept(this);
  201. this._sqlBuilder.Append(" >= ");
  202. exp.Right.Accept(this);
  203. return exp;
  204. }
  205. public override DbExpression Visit(DbAggregateExpression exp)
  206. {
  207. Action<DbAggregateExpression, SqlGenerator> aggregateHandler;
  208. if (!AggregateHandlers.TryGetValue(exp.Method.Name, out aggregateHandler))
  209. {
  210. throw UtilExceptions.NotSupportedMethod(exp.Method);
  211. }
  212. aggregateHandler(exp, this);
  213. return exp;
  214. }
  215. public override DbExpression Visit(DbTableExpression exp)
  216. {
  217. this.QuoteName(exp.Table.Name);
  218. return exp;
  219. }
  220. public override DbExpression Visit(DbColumnAccessExpression exp)
  221. {
  222. this.QuoteName(exp.Table.Name);
  223. this._sqlBuilder.Append(".");
  224. this.QuoteName(exp.Column.Name);
  225. return exp;
  226. }
  227. public override DbExpression Visit(DbFromTableExpression exp)
  228. {
  229. this.AppendTableSegment(exp.Table);
  230. this.VisitDbJoinTableExpressions(exp.JoinTables);
  231. return exp;
  232. }
  233. public override DbExpression Visit(DbJoinTableExpression exp)
  234. {
  235. DbJoinTableExpression joinTablePart = exp;
  236. string joinString = null;
  237. if (joinTablePart.JoinType == JoinType.InnerJoin)
  238. {
  239. joinString = " INNER JOIN ";
  240. }
  241. else if (joinTablePart.JoinType == JoinType.LeftJoin)
  242. {
  243. joinString = " LEFT JOIN ";
  244. }
  245. else if (joinTablePart.JoinType == JoinType.RightJoin)
  246. {
  247. joinString = " RIGHT JOIN ";
  248. }
  249. else
  250. throw new NotSupportedException("JoinType: " + joinTablePart.JoinType);
  251. this._sqlBuilder.Append(joinString);
  252. this.AppendTableSegment(joinTablePart.Table);
  253. this._sqlBuilder.Append(" ON ");
  254. joinTablePart.Condition.Accept(this);
  255. this.VisitDbJoinTableExpressions(joinTablePart.JoinTables);
  256. return exp;
  257. }
  258. public override DbExpression Visit(DbSubQueryExpression exp)
  259. {
  260. this._sqlBuilder.Append("(");
  261. exp.SqlQuery.Accept(this);
  262. this._sqlBuilder.Append(")");
  263. return exp;
  264. }
  265. public override DbExpression Visit(DbSqlQueryExpression exp)
  266. {
  267. //构建常规的查询
  268. this.BuildGeneralSql(exp);
  269. return exp;
  270. }
  271. public override DbExpression Visit(DbInsertExpression exp)
  272. {
  273. this._sqlBuilder.Append("INSERT INTO ");
  274. this.QuoteName(exp.Table.Name);
  275. this._sqlBuilder.Append("(");
  276. bool first = true;
  277. foreach (var item in exp.InsertColumns)
  278. {
  279. if (first)
  280. first = false;
  281. else
  282. {
  283. this._sqlBuilder.Append(",");
  284. }
  285. this.QuoteName(item.Key.Name);
  286. }
  287. this._sqlBuilder.Append(")");
  288. this._sqlBuilder.Append(" VALUES(");
  289. first = true;
  290. foreach (var item in exp.InsertColumns)
  291. {
  292. if (first)
  293. first = false;
  294. else
  295. {
  296. this._sqlBuilder.Append(",");
  297. }
  298. item.Value.Accept(this);
  299. }
  300. this._sqlBuilder.Append(")");
  301. return exp;
  302. }
  303. public override DbExpression Visit(DbUpdateExpression exp)
  304. {
  305. this._sqlBuilder.Append("UPDATE ");
  306. this.QuoteName(exp.Table.Name);
  307. this._sqlBuilder.Append(" SET ");
  308. bool first = true;
  309. foreach (var item in exp.UpdateColumns)
  310. {
  311. if (first)
  312. first = false;
  313. else
  314. this._sqlBuilder.Append(",");
  315. this.QuoteName(item.Key.Name);
  316. this._sqlBuilder.Append("=");
  317. item.Value.Accept(this);
  318. }
  319. this.BuildWhereState(exp.Condition);
  320. return exp;
  321. }
  322. public override DbExpression Visit(DbDeleteExpression exp)
  323. {
  324. this._sqlBuilder.Append("DELETE ");
  325. this.QuoteName(exp.Table.Name);
  326. this._sqlBuilder.Append(" FROM ");
  327. this.QuoteName(exp.Table.Name);
  328. this.BuildWhereState(exp.Condition);
  329. return exp;
  330. }
  331. public override DbExpression Visit(DbCaseWhenExpression exp)
  332. {
  333. this._sqlBuilder.Append("CASE");
  334. foreach (var whenThen in exp.WhenThenPairs)
  335. {
  336. this._sqlBuilder.Append(" WHEN ");
  337. whenThen.When.Accept(this);
  338. this._sqlBuilder.Append(" THEN ");
  339. whenThen.Then.Accept(this);
  340. }
  341. this._sqlBuilder.Append(" ELSE ");
  342. exp.Else.Accept(this);
  343. this._sqlBuilder.Append(" END");
  344. return exp;
  345. }
  346. public override DbExpression Visit(DbConvertExpression exp)
  347. {
  348. DbExpression stripedExp = DbExpressionHelper.StripInvalidConvert(exp);
  349. if (stripedExp.NodeType != DbExpressionType.Convert)
  350. {
  351. stripedExp.Accept(this);
  352. return exp;
  353. }
  354. exp = (DbConvertExpression)stripedExp;
  355. string dbTypeString;
  356. if (TryGetCastTargetDbTypeString(exp.Operand.Type, exp.Type, out dbTypeString, false))
  357. {
  358. this.BuildCastState(exp.Operand, dbTypeString);
  359. }
  360. else
  361. exp.Operand.Accept(this);
  362. return exp;
  363. }
  364. public override DbExpression Visit(DbMethodCallExpression exp)
  365. {
  366. Action<DbMethodCallExpression, SqlGenerator> methodHandler;
  367. if (!MethodHandlers.TryGetValue(exp.Method.Name, out methodHandler))
  368. {
  369. throw UtilExceptions.NotSupportedMethod(exp.Method);
  370. }
  371. methodHandler(exp, this);
  372. return exp;
  373. }
  374. public override DbExpression Visit(DbMemberExpression exp)
  375. {
  376. MemberInfo member = exp.Member;
  377. if (member.DeclaringType == UtilConstants.TypeOfDateTime)
  378. {
  379. if (member == UtilConstants.PropertyInfo_DateTime_Now)
  380. {
  381. this._sqlBuilder.Append("NOW()");
  382. return exp;
  383. }
  384. if (member == UtilConstants.PropertyInfo_DateTime_UtcNow)
  385. {
  386. this._sqlBuilder.Append("UTC_TIMESTAMP()");
  387. return exp;
  388. }
  389. if (member == UtilConstants.PropertyInfo_DateTime_Today)
  390. {
  391. this._sqlBuilder.Append("CURDATE()");
  392. return exp;
  393. }
  394. if (member == UtilConstants.PropertyInfo_DateTime_Date)
  395. {
  396. this._sqlBuilder.Append("DATE(");
  397. exp.Expression.Accept(this);
  398. this._sqlBuilder.Append(")");
  399. return exp;
  400. }
  401. if (IsDbFunction_DATEPART(exp))
  402. {
  403. return exp;
  404. }
  405. }
  406. DbParameterExpression newExp;
  407. if (DbExpressionExtensions.TryParseToParameterExpression(exp, out newExp))
  408. {
  409. return newExp.Accept(this);
  410. }
  411. if (member.Name == "Length" && member.DeclaringType == UtilConstants.TypeOfString)
  412. {
  413. this._sqlBuilder.Append("LENGTH(");
  414. exp.Expression.Accept(this);
  415. this._sqlBuilder.Append(")");
  416. return exp;
  417. }
  418. else if (member.Name == "Value" && Utils.IsNullable(exp.Expression.Type))
  419. {
  420. exp.Expression.Accept(this);
  421. return exp;
  422. }
  423. throw new NotSupportedException(string.Format("'{0}.{1}' is not supported.", member.DeclaringType.FullName, member.Name));
  424. }
  425. public override DbExpression Visit(DbConstantExpression exp)
  426. {
  427. if (exp.Value == null || exp.Value == DBNull.Value)
  428. {
  429. this._sqlBuilder.Append("NULL");
  430. return exp;
  431. }
  432. var objType = exp.Value.GetType();
  433. if (objType == UtilConstants.TypeOfBoolean)
  434. {
  435. this._sqlBuilder.Append(((bool)exp.Value) ? "1" : "0");
  436. return exp;
  437. }
  438. else if (objType == UtilConstants.TypeOfString)
  439. {
  440. this._sqlBuilder.Append("N'", exp.Value, "'");
  441. return exp;
  442. }
  443. else if (objType.IsEnum)
  444. {
  445. this._sqlBuilder.Append(((int)exp.Value).ToString());
  446. return exp;
  447. }
  448. this._sqlBuilder.Append(exp.Value);
  449. return exp;
  450. }
  451. public override DbExpression Visit(DbParameterExpression exp)
  452. {
  453. object paramValue = exp.Value;
  454. Type paramType = exp.Type;
  455. if (paramType.IsEnum)
  456. {
  457. paramType = UtilConstants.TypeOfInt32;
  458. if (paramValue != null)
  459. {
  460. paramValue = (int)paramValue;
  461. }
  462. }
  463. if (paramValue == null)
  464. paramValue = DBNull.Value;
  465. DbParam p;
  466. if (paramValue == DBNull.Value)
  467. {
  468. p = this._parameters.Where(a => Utils.AreEqual(a.Value, paramValue) && a.Type == paramType).FirstOrDefault();
  469. }
  470. else
  471. p = this._parameters.Where(a => Utils.AreEqual(a.Value, paramValue)).FirstOrDefault();
  472. if (p != null)
  473. {
  474. this._sqlBuilder.Append(p.Name);
  475. return exp;
  476. }
  477. string paramName = GenParameterName(this._parameters.Count);
  478. p = DbParam.Create(paramName, paramValue, paramType);
  479. if (paramValue.GetType() == UtilConstants.TypeOfString)
  480. {
  481. if (((string)paramValue).Length <= 4000)
  482. p.Size = 4000;
  483. }
  484. this._parameters.Add(p);
  485. this._sqlBuilder.Append(paramName);
  486. return exp;
  487. }
  488. void AppendTableSegment(DbTableSegment seg)
  489. {
  490. seg.Body.Accept(this);
  491. this._sqlBuilder.Append(" AS ");
  492. this.QuoteName(seg.Alias);
  493. }
  494. internal void AppendColumnSegment(DbColumnSegment seg)
  495. {
  496. seg.Body.Accept(this);
  497. this._sqlBuilder.Append(" AS ");
  498. this.QuoteName(seg.Alias);
  499. }
  500. void AppendOrdering(DbOrdering ordering)
  501. {
  502. if (ordering.OrderType == OrderType.Asc)
  503. {
  504. ordering.Expression.Accept(this);
  505. this._sqlBuilder.Append(" ASC");
  506. return;
  507. }
  508. else if (ordering.OrderType == OrderType.Desc)
  509. {
  510. ordering.Expression.Accept(this);
  511. this._sqlBuilder.Append(" DESC");
  512. return;
  513. }
  514. throw new NotSupportedException("OrderType: " + ordering.OrderType);
  515. }
  516. void VisitDbJoinTableExpressions(List<DbJoinTableExpression> tables)
  517. {
  518. foreach (var table in tables)
  519. {
  520. table.Accept(this);
  521. }
  522. }
  523. void BuildGeneralSql(DbSqlQueryExpression exp)
  524. {
  525. this._sqlBuilder.Append("SELECT ");
  526. List<DbColumnSegment> columns = exp.ColumnSegments;
  527. for (int i = 0; i < columns.Count; i++)
  528. {
  529. DbColumnSegment column = columns[i];
  530. if (i > 0)
  531. this._sqlBuilder.Append(",");
  532. this.AppendColumnSegment(column);
  533. }
  534. this._sqlBuilder.Append(" FROM ");
  535. exp.Table.Accept(this);
  536. this.BuildWhereState(exp.Condition);
  537. this.BuildGroupState(exp);
  538. this.BuildOrderState(exp.Orderings);
  539. if (exp.SkipCount == null && exp.TakeCount == null)
  540. return;
  541. int skipCount = exp.SkipCount ?? 0;
  542. long takeCount = long.MaxValue;
  543. if (exp.TakeCount != null)
  544. takeCount = exp.TakeCount.Value;
  545. this._sqlBuilder.Append(" LIMIT ", skipCount.ToString(), ",", takeCount.ToString());
  546. }
  547. void BuildWhereState(DbExpression whereExpression)
  548. {
  549. if (whereExpression != null)
  550. {
  551. this._sqlBuilder.Append(" WHERE ");
  552. whereExpression.Accept(this);
  553. }
  554. }
  555. void BuildOrderState(List<DbOrdering> orderings)
  556. {
  557. if (orderings.Count > 0)
  558. {
  559. this._sqlBuilder.Append(" ORDER BY ");
  560. this.ConcatOrderings(orderings);
  561. }
  562. }
  563. void ConcatOrderings(List<DbOrdering> orderings)
  564. {
  565. for (int i = 0; i < orderings.Count; i++)
  566. {
  567. if (i > 0)
  568. {
  569. this._sqlBuilder.Append(",");
  570. }
  571. this.AppendOrdering(orderings[i]);
  572. }
  573. }
  574. void BuildGroupState(DbSqlQueryExpression exp)
  575. {
  576. var groupSegments = exp.GroupSegments;
  577. if (groupSegments.Count == 0)
  578. return;
  579. this._sqlBuilder.Append(" GROUP BY ");
  580. for (int i = 0; i < groupSegments.Count; i++)
  581. {
  582. if (i > 0)
  583. this._sqlBuilder.Append(",");
  584. groupSegments[i].Accept(this);
  585. }
  586. if (exp.HavingCondition != null)
  587. {
  588. this._sqlBuilder.Append(" HAVING ");
  589. exp.HavingCondition.Accept(this);
  590. }
  591. }
  592. void ConcatOperands(IEnumerable<DbExpression> operands, string connector)
  593. {
  594. this._sqlBuilder.Append("(");
  595. bool first = true;
  596. foreach (DbExpression operand in operands)
  597. {
  598. if (first)
  599. first = false;
  600. else
  601. this._sqlBuilder.Append(connector);
  602. operand.Accept(this);
  603. }
  604. this._sqlBuilder.Append(")");
  605. return;
  606. }
  607. void QuoteName(string name)
  608. {
  609. if (string.IsNullOrEmpty(name))
  610. throw new ArgumentException("name");
  611. this._sqlBuilder.Append("`", name, "`");
  612. }
  613. void BuildCastState(DbExpression castExp, string targetDbTypeString)
  614. {
  615. this._sqlBuilder.Append("CAST(");
  616. castExp.Accept(this);
  617. this._sqlBuilder.Append(" AS ", targetDbTypeString, ")");
  618. }
  619. bool IsDbFunction_DATEPART(DbMemberExpression exp)
  620. {
  621. MemberInfo member = exp.Member;
  622. if (member == UtilConstants.PropertyInfo_DateTime_Year)
  623. {
  624. DbFunction_DATEPART(this, "YEAR", exp.Expression);
  625. return true;
  626. }
  627. if (member == UtilConstants.PropertyInfo_DateTime_Month)
  628. {
  629. DbFunction_DATEPART(this, "MONTH", exp.Expression);
  630. return true;
  631. }
  632. if (member == UtilConstants.PropertyInfo_DateTime_Day)
  633. {
  634. DbFunction_DATEPART(this, "DAY", exp.Expression);
  635. return true;
  636. }
  637. if (member == UtilConstants.PropertyInfo_DateTime_Hour)
  638. {
  639. DbFunction_DATEPART(this, "HOUR", exp.Expression);
  640. return true;
  641. }
  642. if (member == UtilConstants.PropertyInfo_DateTime_Minute)
  643. {
  644. DbFunction_DATEPART(this, "MINUTE", exp.Expression);
  645. return true;
  646. }
  647. if (member == UtilConstants.PropertyInfo_DateTime_Second)
  648. {
  649. DbFunction_DATEPART(this, "SECOND", exp.Expression);
  650. return true;
  651. }
  652. /* MySql is not supports MILLISECOND */
  653. if (member == UtilConstants.PropertyInfo_DateTime_DayOfWeek)
  654. {
  655. this._sqlBuilder.Append("(");
  656. DbFunction_DATEPART(this, "DAYOFWEEK", exp.Expression);
  657. this._sqlBuilder.Append(" - 1)");
  658. return true;
  659. }
  660. return false;
  661. }
  662. #region BinaryWithMethodHandlers
  663. static Dictionary<MethodInfo, Action<DbBinaryExpression, SqlGenerator>> InitBinaryWithMethodHandlers()
  664. {
  665. var binaryWithMethodHandlers = new Dictionary<MethodInfo, Action<DbBinaryExpression, SqlGenerator>>();
  666. binaryWithMethodHandlers.Add(UtilConstants.MethodInfo_String_Concat_String_String, StringConcat);
  667. binaryWithMethodHandlers.Add(UtilConstants.MethodInfo_String_Concat_Object_Object, StringConcat);
  668. var ret = Utils.Clone(binaryWithMethodHandlers);
  669. return ret;
  670. }
  671. static void StringConcat(DbBinaryExpression exp, SqlGenerator generator)
  672. {
  673. MethodInfo method = exp.Method;
  674. List<DbExpression> operands = new List<DbExpression>();
  675. operands.Add(exp.Right);
  676. DbExpression left = exp.Left;
  677. DbAddExpression e = null;
  678. while ((e = (left as DbAddExpression)) != null && (e.Method == UtilConstants.MethodInfo_String_Concat_String_String || e.Method == UtilConstants.MethodInfo_String_Concat_Object_Object))
  679. {
  680. operands.Add(e.Right);
  681. left = e.Left;
  682. }
  683. operands.Add(left);
  684. DbExpression whenExp = null;
  685. List<DbExpression> operandExps = new List<DbExpression>(operands.Count);
  686. for (int i = operands.Count - 1; i >= 0; i--)
  687. {
  688. DbExpression operand = operands[i];
  689. DbExpression opBody = operand;
  690. if (opBody.Type != UtilConstants.TypeOfString)
  691. {
  692. // 需要 cast type
  693. opBody = DbExpression.Convert(opBody, UtilConstants.TypeOfString);
  694. }
  695. DbExpression equalNullExp = DbExpression.Equal(opBody, UtilConstants.DbConstant_Null_String);
  696. if (whenExp == null)
  697. whenExp = equalNullExp;
  698. else
  699. whenExp = DbExpression.AndAlso(whenExp, equalNullExp);
  700. DbExpression thenExp = DbConstantExpression.StringEmpty;
  701. DbCaseWhenExpression.WhenThenExpressionPair whenThenPair = new DbCaseWhenExpression.WhenThenExpressionPair(equalNullExp, thenExp);
  702. List<DbCaseWhenExpression.WhenThenExpressionPair> whenThenExps = new List<DbCaseWhenExpression.WhenThenExpressionPair>(1);
  703. whenThenExps.Add(whenThenPair);
  704. DbExpression elseExp = opBody;
  705. DbCaseWhenExpression caseWhenExpression = DbExpression.CaseWhen(whenThenExps, elseExp, UtilConstants.TypeOfString);
  706. operandExps.Add(caseWhenExpression);
  707. }
  708. generator._sqlBuilder.Append("CASE", " WHEN ");
  709. whenExp.Accept(generator);
  710. generator._sqlBuilder.Append(" THEN ");
  711. DbConstantExpression.Null.Accept(generator);
  712. generator._sqlBuilder.Append(" ELSE ");
  713. generator._sqlBuilder.Append("CONCAT(");
  714. for (int i = 0; i < operandExps.Count; i++)
  715. {
  716. if (i > 0)
  717. generator._sqlBuilder.Append(",");
  718. operandExps[i].Accept(generator);
  719. }
  720. generator._sqlBuilder.Append(")");
  721. generator._sqlBuilder.Append(" END");
  722. }
  723. #endregion
  724. }
  725. }