SqlGenerator.cs 34 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053
  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.SqlServer
  13. {
  14. /// <summary>
  15. /// 组装SQL类
  16. /// </summary>
  17. partial class SqlGenerator : DbExpressionVisitor<DbExpression>
  18. {
  19. public const string ParameterPrefix = "@P_";
  20. internal ISqlBuilder _sqlBuilder = new SqlBuilder();
  21. List<DbParam> _parameters = new List<DbParam>();
  22. DbValueExpressionVisitor _valueExpressionVisitor = null;
  23. /// <summary>
  24. /// 解决表达式中的方法
  25. /// </summary>
  26. static readonly Dictionary<string, Action<DbMethodCallExpression, SqlGenerator>> MethodHandlers = InitMethodHandlers();
  27. /// <summary>
  28. ///
  29. /// </summary>
  30. static readonly Dictionary<string, Action<DbAggregateExpression, SqlGenerator>> AggregateHandlers = InitAggregateHandlers();
  31. /// <summary>
  32. ///
  33. /// </summary>
  34. static readonly Dictionary<MethodInfo, Action<DbBinaryExpression, SqlGenerator>> BinaryWithMethodHandlers = InitBinaryWithMethodHandlers();
  35. static readonly Dictionary<Type, string> CastTypeMap = null;
  36. public static readonly ReadOnlyCollection<DbExpressionType> SafeDbExpressionTypes = null;
  37. static readonly List<string> CacheParameterNames = null;
  38. static SqlGenerator()
  39. {
  40. List<DbExpressionType> list = new List<DbExpressionType>();
  41. list.Add(DbExpressionType.MemberAccess);
  42. list.Add(DbExpressionType.ColumnAccess);
  43. list.Add(DbExpressionType.Constant);
  44. list.Add(DbExpressionType.Parameter);
  45. list.Add(DbExpressionType.Convert);
  46. SafeDbExpressionTypes = list.AsReadOnly();
  47. Dictionary<Type, string> castTypeMap = new Dictionary<Type, string>();
  48. castTypeMap.Add(typeof(string), "NVARCHAR(MAX)");
  49. castTypeMap.Add(typeof(byte), "TINYINT");
  50. castTypeMap.Add(typeof(Int16), "SMALLINT");
  51. castTypeMap.Add(typeof(int), "INT");
  52. castTypeMap.Add(typeof(long), "BIGINT");
  53. castTypeMap.Add(typeof(decimal), "DECIMAL(19,0)");//I think this will be a bug.
  54. castTypeMap.Add(typeof(double), "FLOAT");
  55. castTypeMap.Add(typeof(float), "REAL");
  56. castTypeMap.Add(typeof(bool), "BIT");
  57. castTypeMap.Add(typeof(DateTime), "DATETIME");
  58. castTypeMap.Add(typeof(Guid), "UNIQUEIDENTIFIER");
  59. CastTypeMap = Utils.Clone(castTypeMap);
  60. int cacheParameterNameCount = 2 * 12;
  61. List<string> cacheParameterNames = new List<string>(cacheParameterNameCount);
  62. for (int i = 0; i < cacheParameterNameCount; i++)
  63. {
  64. string paramName = ParameterPrefix + i.ToString();
  65. cacheParameterNames.Add(paramName);
  66. }
  67. CacheParameterNames = cacheParameterNames;
  68. }
  69. public ISqlBuilder SqlBuilder { get { return this._sqlBuilder; } }
  70. public List<DbParam> Parameters { get { return this._parameters; } }
  71. DbValueExpressionVisitor ValueExpressionVisitor
  72. {
  73. get
  74. {
  75. if (this._valueExpressionVisitor == null)
  76. this._valueExpressionVisitor = new DbValueExpressionVisitor(this);
  77. return this._valueExpressionVisitor;
  78. }
  79. }
  80. public static SqlGenerator CreateInstance()
  81. {
  82. return new SqlGenerator();
  83. }
  84. /// <summary>
  85. /// 解析Lambda等于表达式
  86. /// </summary>
  87. /// <param name="exp"></param>
  88. /// <returns></returns>
  89. public override DbExpression Visit(DbEqualExpression exp)
  90. {
  91. DbExpression left = exp.Left;
  92. DbExpression right = exp.Right;
  93. left = DbExpressionExtensions.ParseDbExpression(left);
  94. right = DbExpressionExtensions.ParseDbExpression(right);
  95. //明确 left right 其中一边一定为 null
  96. if (DbExpressionExtensions.AffirmExpressionRetValueIsNull(right))
  97. {
  98. left.Accept(this);
  99. this._sqlBuilder.Append(" IS NULL");
  100. return exp;
  101. }
  102. if (DbExpressionExtensions.AffirmExpressionRetValueIsNull(left))
  103. {
  104. right.Accept(this);
  105. this._sqlBuilder.Append(" IS NULL");
  106. return exp;
  107. }
  108. left.Accept(this);
  109. this._sqlBuilder.Append(" = ");
  110. right.Accept(this);
  111. return exp;
  112. }
  113. /// <summary>
  114. /// 解析Lambda不等于表达式
  115. /// </summary>
  116. /// <param name="exp"></param>
  117. /// <returns></returns>
  118. public override DbExpression Visit(DbNotEqualExpression exp)
  119. {
  120. DbExpression left = exp.Left;
  121. DbExpression right = exp.Right;
  122. left = DbExpressionExtensions.ParseDbExpression(left);
  123. right = DbExpressionExtensions.ParseDbExpression(right);
  124. //明确 left right 其中一边一定为 null
  125. if (DbExpressionExtensions.AffirmExpressionRetValueIsNull(right))
  126. {
  127. left.Accept(this);
  128. this._sqlBuilder.Append(" IS NOT NULL");
  129. return exp;
  130. }
  131. if (DbExpressionExtensions.AffirmExpressionRetValueIsNull(left))
  132. {
  133. right.Accept(this);
  134. this._sqlBuilder.Append(" IS NOT NULL");
  135. return exp;
  136. }
  137. left.Accept(this);
  138. this._sqlBuilder.Append(" <> ");
  139. right.Accept(this);
  140. return exp;
  141. }
  142. /// <summary>
  143. /// 解析Lambda表达式NOT
  144. /// </summary>
  145. /// <param name="exp"></param>
  146. /// <returns></returns>
  147. public override DbExpression Visit(DbNotExpression exp)
  148. {
  149. this._sqlBuilder.Append("NOT ");
  150. this._sqlBuilder.Append("(");
  151. exp.Operand.Accept(this);
  152. this._sqlBuilder.Append(")");
  153. return exp;
  154. }
  155. /// <summary>
  156. /// 解析Lambda等于表达式&符号
  157. /// </summary>
  158. /// <param name="exp"></param>
  159. /// <returns></returns>
  160. public override DbExpression Visit(DbAndExpression exp)
  161. {
  162. Stack<DbExpression> operands = GatherBinaryExpressionOperand(exp);
  163. this.ConcatOperands(operands, " & ");
  164. return exp;
  165. }
  166. /// <summary>
  167. /// 解析Lambda等于表达式
  168. /// </summary>
  169. /// <param name="exp"></param>
  170. /// <returns></returns>
  171. public override DbExpression Visit(DbAndAlsoExpression exp)
  172. {
  173. Stack<DbExpression> operands = GatherBinaryExpressionOperand(exp);
  174. this.ConcatOperands(operands, " AND ");
  175. return exp;
  176. }
  177. /// <summary>
  178. /// 解析Lambda等于表达式
  179. /// </summary>
  180. /// <param name="exp"></param>
  181. /// <returns></returns>
  182. public override DbExpression Visit(DbOrExpression exp)
  183. {
  184. Stack<DbExpression> operands = GatherBinaryExpressionOperand(exp);
  185. this.ConcatOperands(operands, " | ");
  186. return exp;
  187. }
  188. /// <summary>
  189. /// 解析Lambda等于表达式
  190. /// </summary>
  191. /// <param name="exp"></param>
  192. /// <returns></returns>
  193. public override DbExpression Visit(DbOrElseExpression exp)
  194. {
  195. Stack<DbExpression> operands = GatherBinaryExpressionOperand(exp);
  196. this.ConcatOperands(operands, " OR ");
  197. return exp;
  198. }
  199. // +
  200. public override DbExpression Visit(DbAddExpression exp)
  201. {
  202. MethodInfo method = exp.Method;
  203. if (method != null)
  204. {
  205. Action<DbBinaryExpression, SqlGenerator> handler;
  206. if (BinaryWithMethodHandlers.TryGetValue(method, out handler))
  207. {
  208. handler(exp, this);
  209. return exp;
  210. }
  211. throw UtilExceptions.NotSupportedMethod(exp.Method);
  212. }
  213. Stack<DbExpression> operands = GatherBinaryExpressionOperand(exp);
  214. this.ConcatOperands(operands, " + ");
  215. return exp;
  216. }
  217. // -
  218. public override DbExpression Visit(DbSubtractExpression exp)
  219. {
  220. Stack<DbExpression> operands = GatherBinaryExpressionOperand(exp);
  221. this.ConcatOperands(operands, " - ");
  222. return exp;
  223. }
  224. // *
  225. public override DbExpression Visit(DbMultiplyExpression exp)
  226. {
  227. Stack<DbExpression> operands = GatherBinaryExpressionOperand(exp);
  228. this.ConcatOperands(operands, " * ");
  229. return exp;
  230. }
  231. // /
  232. public override DbExpression Visit(DbDivideExpression exp)
  233. {
  234. Stack<DbExpression> operands = GatherBinaryExpressionOperand(exp);
  235. this.ConcatOperands(operands, " / ");
  236. return exp;
  237. }
  238. // <
  239. public override DbExpression Visit(DbLessThanExpression exp)
  240. {
  241. exp.Left.Accept(this);
  242. this._sqlBuilder.Append(" < ");
  243. exp.Right.Accept(this);
  244. return exp;
  245. }
  246. // <=
  247. public override DbExpression Visit(DbLessThanOrEqualExpression exp)
  248. {
  249. exp.Left.Accept(this);
  250. this._sqlBuilder.Append(" <= ");
  251. exp.Right.Accept(this);
  252. return exp;
  253. }
  254. // >
  255. public override DbExpression Visit(DbGreaterThanExpression exp)
  256. {
  257. exp.Left.Accept(this);
  258. this._sqlBuilder.Append(" > ");
  259. exp.Right.Accept(this);
  260. return exp;
  261. }
  262. // >=
  263. public override DbExpression Visit(DbGreaterThanOrEqualExpression exp)
  264. {
  265. exp.Left.Accept(this);
  266. this._sqlBuilder.Append(" >= ");
  267. exp.Right.Accept(this);
  268. return exp;
  269. }
  270. public override DbExpression Visit(DbAggregateExpression exp)
  271. {
  272. Action<DbAggregateExpression, SqlGenerator> aggregateHandler;
  273. if (!AggregateHandlers.TryGetValue(exp.Method.Name, out aggregateHandler))
  274. {
  275. throw UtilExceptions.NotSupportedMethod(exp.Method);
  276. }
  277. aggregateHandler(exp, this);
  278. return exp;
  279. }
  280. /// <summary>
  281. /// 解析数据库的表名
  282. /// </summary>
  283. /// <param name="exp"></param>
  284. /// <returns></returns>
  285. public override DbExpression Visit(DbTableExpression exp)
  286. {
  287. this.QuoteName(exp.Table.Name);
  288. return exp;
  289. }
  290. /// <summary>
  291. /// 解析数据库的列名
  292. /// </summary>
  293. /// <param name="exp"></param>
  294. /// <returns></returns>
  295. public override DbExpression Visit(DbColumnAccessExpression exp)
  296. {
  297. this.QuoteName(exp.Table.Name);
  298. this._sqlBuilder.Append(".");
  299. this.QuoteName(exp.Column.Name);
  300. return exp;
  301. }
  302. public override DbExpression Visit(DbFromTableExpression exp)
  303. {
  304. this.AppendTableSegment(exp.Table);
  305. this.VisitDbJoinTableExpressions(exp.JoinTables);
  306. return exp;
  307. }
  308. public override DbExpression Visit(DbJoinTableExpression exp)
  309. {
  310. DbJoinTableExpression joinTablePart = exp;
  311. string joinString = null;
  312. if (joinTablePart.JoinType == JoinType.InnerJoin)
  313. {
  314. joinString = " INNER JOIN ";
  315. }
  316. else if (joinTablePart.JoinType == JoinType.LeftJoin)
  317. {
  318. joinString = " LEFT JOIN ";
  319. }
  320. else if (joinTablePart.JoinType == JoinType.RightJoin)
  321. {
  322. joinString = " RIGHT JOIN ";
  323. }
  324. else if (joinTablePart.JoinType == JoinType.FullJoin)
  325. {
  326. joinString = " FULL JOIN ";
  327. }
  328. else
  329. throw new NotSupportedException("JoinType: " + joinTablePart.JoinType);
  330. this._sqlBuilder.Append(joinString);
  331. this.AppendTableSegment(joinTablePart.Table);
  332. this._sqlBuilder.Append(" ON ");
  333. joinTablePart.Condition.Accept(this);
  334. this.VisitDbJoinTableExpressions(joinTablePart.JoinTables);
  335. return exp;
  336. }
  337. public override DbExpression Visit(DbSubQueryExpression exp)
  338. {
  339. this._sqlBuilder.Append("(");
  340. exp.SqlQuery.Accept(this);
  341. this._sqlBuilder.Append(")");
  342. return exp;
  343. }
  344. public override DbExpression Visit(DbSqlQueryExpression exp)
  345. {
  346. if (exp.SkipCount != null)
  347. {
  348. this.BuildLimitSql(exp);
  349. return exp;
  350. }
  351. else
  352. {
  353. //构建常规的查询
  354. this.BuildGeneralSql(exp);
  355. return exp;
  356. }
  357. throw new NotImplementedException();
  358. }
  359. public override DbExpression Visit(DbInsertExpression exp)
  360. {
  361. this._sqlBuilder.Append("INSERT INTO ");
  362. this.QuoteName(exp.Table.Name);
  363. this._sqlBuilder.Append("(");
  364. bool first = true;
  365. foreach (var item in exp.InsertColumns)
  366. {
  367. if (first)
  368. first = false;
  369. else
  370. {
  371. this._sqlBuilder.Append(",");
  372. }
  373. this.QuoteName(item.Key.Name);
  374. }
  375. this._sqlBuilder.Append(")");
  376. this._sqlBuilder.Append(" VALUES(");
  377. first = true;
  378. foreach (var item in exp.InsertColumns)
  379. {
  380. if (first)
  381. first = false;
  382. else
  383. {
  384. this._sqlBuilder.Append(",");
  385. }
  386. item.Value.Accept(this.ValueExpressionVisitor);
  387. }
  388. this._sqlBuilder.Append(")");
  389. return exp;
  390. }
  391. public override DbExpression Visit(DbUpdateExpression exp)
  392. {
  393. this._sqlBuilder.Append("UPDATE ");
  394. this.QuoteName(exp.Table.Name);
  395. this._sqlBuilder.Append(" SET ");
  396. bool first = true;
  397. foreach (var item in exp.UpdateColumns)
  398. {
  399. if (first)
  400. first = false;
  401. else
  402. this._sqlBuilder.Append(",");
  403. this.QuoteName(item.Key.Name);
  404. this._sqlBuilder.Append("=");
  405. item.Value.Accept(this.ValueExpressionVisitor);
  406. }
  407. this.BuildWhereState(exp.Condition);
  408. return exp;
  409. }
  410. public override DbExpression Visit(DbDeleteExpression exp)
  411. {
  412. this._sqlBuilder.Append("DELETE ");
  413. this.QuoteName(exp.Table.Name);
  414. this.BuildWhereState(exp.Condition);
  415. return exp;
  416. }
  417. // then 部分必须返回 C# type,所以得判断是否是诸如 a>1,a=b,in,like 等等的情况,如果是则将其构建成一个 case when
  418. public override DbExpression Visit(DbCaseWhenExpression exp)
  419. {
  420. this._sqlBuilder.Append("CASE");
  421. foreach (var whenThen in exp.WhenThenPairs)
  422. {
  423. // then 部分得判断是否是诸如 a>1,a=b,in,like 等等的情况,如果是则将其构建成一个 case when
  424. this._sqlBuilder.Append(" WHEN ");
  425. whenThen.When.Accept(this);
  426. this._sqlBuilder.Append(" THEN ");
  427. EnsureDbExpressionReturnCSharpBoolean(whenThen.Then).Accept(this);
  428. }
  429. this._sqlBuilder.Append(" ELSE ");
  430. EnsureDbExpressionReturnCSharpBoolean(exp.Else).Accept(this);
  431. this._sqlBuilder.Append(" END");
  432. return exp;
  433. }
  434. public override DbExpression Visit(DbConvertExpression exp)
  435. {
  436. DbExpression stripedExp = DbExpressionHelper.StripInvalidConvert(exp);
  437. if (stripedExp.NodeType != DbExpressionType.Convert)
  438. {
  439. EnsureDbExpressionReturnCSharpBoolean(stripedExp).Accept(this);
  440. return exp;
  441. }
  442. exp = (DbConvertExpression)stripedExp;
  443. string dbTypeString;
  444. if (TryGetCastTargetDbTypeString(exp.Operand.Type, exp.Type, out dbTypeString))
  445. {
  446. this.BuildCastState(EnsureDbExpressionReturnCSharpBoolean(exp.Operand), dbTypeString);
  447. }
  448. else
  449. EnsureDbExpressionReturnCSharpBoolean(exp.Operand).Accept(this);
  450. return exp;
  451. }
  452. public override DbExpression Visit(DbMethodCallExpression exp)
  453. {
  454. Action<DbMethodCallExpression, SqlGenerator> methodHandler;
  455. if (!MethodHandlers.TryGetValue(exp.Method.Name, out methodHandler))
  456. {
  457. throw UtilExceptions.NotSupportedMethod(exp.Method);
  458. }
  459. methodHandler(exp, this);
  460. return exp;
  461. }
  462. public override DbExpression Visit(DbMemberExpression exp)
  463. {
  464. MemberInfo member = exp.Member;
  465. if (member.DeclaringType == UtilConstants.TypeOfDateTime)
  466. {
  467. if (member == UtilConstants.PropertyInfo_DateTime_Now)
  468. {
  469. this._sqlBuilder.Append("GETDATE()");
  470. return exp;
  471. }
  472. if (member == UtilConstants.PropertyInfo_DateTime_UtcNow)
  473. {
  474. this._sqlBuilder.Append("GETUTCDATE()");
  475. return exp;
  476. }
  477. if (member == UtilConstants.PropertyInfo_DateTime_Today)
  478. {
  479. BuildCastState("GETDATE()", "DATE");
  480. return exp;
  481. }
  482. if (member == UtilConstants.PropertyInfo_DateTime_Date)
  483. {
  484. BuildCastState(exp.Expression, "DATE");
  485. return exp;
  486. }
  487. if (IsDbFunction_DATEPART(exp))
  488. {
  489. return exp;
  490. }
  491. }
  492. DbParameterExpression newExp;
  493. if (DbExpressionExtensions.TryParseToParameterExpression(exp, out newExp))
  494. {
  495. return newExp.Accept(this);
  496. }
  497. if (member.Name == "Length" && member.DeclaringType == UtilConstants.TypeOfString)
  498. {
  499. this._sqlBuilder.Append("LEN(");
  500. exp.Expression.Accept(this);
  501. this._sqlBuilder.Append(")");
  502. return exp;
  503. }
  504. else if (member.Name == "Value" && Utils.IsNullable(exp.Expression.Type))
  505. {
  506. exp.Expression.Accept(this);
  507. return exp;
  508. }
  509. throw new NotSupportedException(string.Format("'{0}.{1}' is not supported.", member.DeclaringType.FullName, member.Name));
  510. }
  511. public override DbExpression Visit(DbConstantExpression exp)
  512. {
  513. if (exp.Value == null || exp.Value == DBNull.Value)
  514. {
  515. this._sqlBuilder.Append("NULL");
  516. return exp;
  517. }
  518. var objType = exp.Value.GetType();
  519. if (objType == UtilConstants.TypeOfBoolean)
  520. {
  521. this._sqlBuilder.Append(((bool)exp.Value) ? "CAST(1 AS BIT)" : "CAST(0 AS BIT)");
  522. return exp;
  523. }
  524. else if (objType == UtilConstants.TypeOfString)
  525. {
  526. this._sqlBuilder.Append("N'", exp.Value, "'");
  527. return exp;
  528. }
  529. else if (objType.IsEnum)
  530. {
  531. this._sqlBuilder.Append(((int)exp.Value).ToString());
  532. return exp;
  533. }
  534. this._sqlBuilder.Append(exp.Value);
  535. return exp;
  536. }
  537. public override DbExpression Visit(DbParameterExpression exp)
  538. {
  539. object paramValue = exp.Value;
  540. Type paramType = exp.Type;
  541. if (paramType.IsEnum)
  542. {
  543. paramType = UtilConstants.TypeOfInt32;
  544. if (paramValue != null)
  545. {
  546. paramValue = (int)paramValue;
  547. }
  548. }
  549. if (paramValue == null)
  550. paramValue = DBNull.Value;
  551. DbParam p;
  552. if (paramValue == DBNull.Value)
  553. {
  554. p = this._parameters.Where(a => Utils.AreEqual(a.Value, paramValue) && a.Type == paramType).FirstOrDefault();
  555. }
  556. else
  557. p = this._parameters.Where(a => Utils.AreEqual(a.Value, paramValue)).FirstOrDefault();
  558. if (p != null)
  559. {
  560. this._sqlBuilder.Append(p.Name);
  561. return exp;
  562. }
  563. string paramName = GenParameterName(this._parameters.Count);
  564. p = DbParam.Create(paramName, paramValue, paramType);
  565. if (paramValue.GetType() == UtilConstants.TypeOfString)
  566. {
  567. if (((string)paramValue).Length <= 4000)
  568. p.Size = 4000;
  569. }
  570. this._parameters.Add(p);
  571. this._sqlBuilder.Append(paramName);
  572. return exp;
  573. }
  574. void AppendTableSegment(DbTableSegment seg)
  575. {
  576. seg.Body.Accept(this);
  577. this._sqlBuilder.Append(" AS ");
  578. this.QuoteName(seg.Alias);
  579. }
  580. internal void AppendColumnSegment(DbColumnSegment seg)
  581. {
  582. seg.Body.Accept(this.ValueExpressionVisitor);
  583. this._sqlBuilder.Append(" AS ");
  584. this.QuoteName(seg.Alias);
  585. }
  586. void AppendOrdering(DbOrdering ordering)
  587. {
  588. if (ordering.OrderType == OrderType.Asc)
  589. {
  590. ordering.Expression.Accept(this);
  591. this._sqlBuilder.Append(" ASC");
  592. return;
  593. }
  594. else if (ordering.OrderType == OrderType.Desc)
  595. {
  596. ordering.Expression.Accept(this);
  597. this._sqlBuilder.Append(" DESC");
  598. return;
  599. }
  600. throw new NotSupportedException("OrderType: " + ordering.OrderType);
  601. }
  602. void VisitDbJoinTableExpressions(List<DbJoinTableExpression> tables)
  603. {
  604. foreach (var table in tables)
  605. {
  606. table.Accept(this);
  607. }
  608. }
  609. /// <summary>
  610. /// 组装SQL语句
  611. /// </summary>
  612. /// <param name="exp"></param>
  613. void BuildGeneralSql(DbSqlQueryExpression exp)
  614. {
  615. this._sqlBuilder.Append("SELECT ");
  616. if (exp.TakeCount != null)
  617. this._sqlBuilder.Append("TOP (", exp.TakeCount.ToString(), ") ");
  618. List<DbColumnSegment> columns = exp.ColumnSegments;
  619. for (int i = 0; i < columns.Count; i++)
  620. {
  621. DbColumnSegment column = columns[i];
  622. if (i > 0)
  623. this._sqlBuilder.Append(",");
  624. this.AppendColumnSegment(column);
  625. }
  626. this._sqlBuilder.Append(" FROM ");
  627. exp.Table.Accept(this);
  628. // this._sqlBuilder.Append(" with(nolock) ");
  629. this.BuildWhereState(exp.Condition);
  630. this.BuildGroupState(exp);
  631. this.BuildOrderState(exp.Orderings);
  632. }
  633. /// <summary>
  634. /// 组装老数据库2012之前的分页SQL
  635. /// </summary>
  636. /// <param name="exp"></param>
  637. protected virtual void BuildLimitSql(DbSqlQueryExpression exp)
  638. {
  639. this._sqlBuilder.Append("SELECT ");
  640. if (exp.TakeCount != null)
  641. this._sqlBuilder.Append("TOP (", exp.TakeCount.ToString(), ") ");
  642. string tableAlias = "T";
  643. List<DbColumnSegment> columns = exp.ColumnSegments;
  644. for (int i = 0; i < columns.Count; i++)
  645. {
  646. DbColumnSegment column = columns[i];
  647. if (i > 0)
  648. this._sqlBuilder.Append(",");
  649. this.QuoteName(tableAlias);
  650. this._sqlBuilder.Append(".");
  651. this.QuoteName(column.Alias);
  652. this._sqlBuilder.Append(" AS ");
  653. this.QuoteName(column.Alias);
  654. }
  655. this._sqlBuilder.Append(" FROM ");
  656. this._sqlBuilder.Append("(");
  657. //------------------------//
  658. this._sqlBuilder.Append("SELECT ");
  659. for (int i = 0; i < columns.Count; i++)
  660. {
  661. DbColumnSegment column = columns[i];
  662. if (i > 0)
  663. this._sqlBuilder.Append(",");
  664. column.Body.Accept(this.ValueExpressionVisitor);
  665. this._sqlBuilder.Append(" AS ");
  666. this.QuoteName(column.Alias);
  667. }
  668. List<DbOrdering> orderings = exp.Orderings;
  669. if (orderings.Count == 0)
  670. {
  671. DbOrdering ordering = new DbOrdering(UtilConstants.DbParameter_1, OrderType.Asc);
  672. orderings = new List<DbOrdering>(1);
  673. orderings.Add(ordering);
  674. }
  675. string row_numberName = CreateRowNumberName(columns);
  676. this._sqlBuilder.Append(",ROW_NUMBER() OVER(ORDER BY ");
  677. this.ConcatOrderings(orderings);
  678. this._sqlBuilder.Append(") AS ");
  679. this.QuoteName(row_numberName);
  680. this._sqlBuilder.Append(" FROM ");
  681. exp.Table.Accept(this);
  682. this.BuildWhereState(exp.Condition);
  683. this.BuildGroupState(exp);
  684. //------------------------//
  685. this._sqlBuilder.Append(")");
  686. this._sqlBuilder.Append(" AS ");
  687. this.QuoteName(tableAlias);
  688. this._sqlBuilder.Append(" WHERE ");
  689. this.QuoteName(tableAlias);
  690. this._sqlBuilder.Append(".");
  691. this.QuoteName(row_numberName);
  692. this._sqlBuilder.Append(" > ");
  693. this._sqlBuilder.Append(exp.SkipCount.ToString());
  694. }
  695. /// <summary>
  696. /// 组装查询条件
  697. /// </summary>
  698. /// <param name="whereExpression"></param>
  699. internal void BuildWhereState(DbExpression whereExpression)
  700. {
  701. if (whereExpression != null)
  702. {
  703. this._sqlBuilder.Append(" WHERE ");
  704. whereExpression.Accept(this);
  705. }
  706. }
  707. /// <summary>
  708. /// 组装排序
  709. /// </summary>
  710. /// <param name="orderings"></param>
  711. internal void BuildOrderState(List<DbOrdering> orderings)
  712. {
  713. if (orderings.Count > 0)
  714. {
  715. this._sqlBuilder.Append(" ORDER BY ");
  716. this.ConcatOrderings(orderings);
  717. }
  718. }
  719. void ConcatOrderings(List<DbOrdering> orderings)
  720. {
  721. for (int i = 0; i < orderings.Count; i++)
  722. {
  723. if (i > 0)
  724. {
  725. this._sqlBuilder.Append(",");
  726. }
  727. this.AppendOrdering(orderings[i]);
  728. }
  729. }
  730. /// <summary>
  731. /// 组装GroupBy条件
  732. /// </summary>
  733. /// <param name="exp"></param>
  734. internal void BuildGroupState(DbSqlQueryExpression exp)
  735. {
  736. var groupSegments = exp.GroupSegments;
  737. if (groupSegments.Count == 0)
  738. return;
  739. this._sqlBuilder.Append(" GROUP BY ");
  740. for (int i = 0; i < groupSegments.Count; i++)
  741. {
  742. if (i > 0)
  743. this._sqlBuilder.Append(",");
  744. groupSegments[i].Accept(this);
  745. }
  746. if (exp.HavingCondition != null)
  747. {
  748. this._sqlBuilder.Append(" HAVING ");
  749. exp.HavingCondition.Accept(this);
  750. }
  751. }
  752. void ConcatOperands(IEnumerable<DbExpression> operands, string connector)
  753. {
  754. this._sqlBuilder.Append("(");
  755. bool first = true;
  756. foreach (DbExpression operand in operands)
  757. {
  758. if (first)
  759. first = false;
  760. else
  761. this._sqlBuilder.Append(connector);
  762. operand.Accept(this);
  763. }
  764. this._sqlBuilder.Append(")");
  765. return;
  766. }
  767. void QuoteName(string name)
  768. {
  769. if (string.IsNullOrEmpty(name))
  770. throw new ArgumentException("name");
  771. this._sqlBuilder.Append("[", name, "]");
  772. }
  773. void BuildCastState(DbExpression castExp, string targetDbTypeString)
  774. {
  775. this._sqlBuilder.Append("CAST(");
  776. castExp.Accept(this);
  777. this._sqlBuilder.Append(" AS ", targetDbTypeString, ")");
  778. }
  779. void BuildCastState(object castObject, string targetDbTypeString)
  780. {
  781. this._sqlBuilder.Append("CAST(", castObject, " AS ", targetDbTypeString, ")");
  782. }
  783. bool IsDbFunction_DATEPART(DbMemberExpression exp)
  784. {
  785. MemberInfo member = exp.Member;
  786. if (member == UtilConstants.PropertyInfo_DateTime_Year)
  787. {
  788. DbFunction_DATEPART(this, "YEAR", exp.Expression);
  789. return true;
  790. }
  791. if (member == UtilConstants.PropertyInfo_DateTime_Month)
  792. {
  793. DbFunction_DATEPART(this, "MONTH", exp.Expression);
  794. return true;
  795. }
  796. if (member == UtilConstants.PropertyInfo_DateTime_Day)
  797. {
  798. DbFunction_DATEPART(this, "DAY", exp.Expression);
  799. return true;
  800. }
  801. if (member == UtilConstants.PropertyInfo_DateTime_Hour)
  802. {
  803. DbFunction_DATEPART(this, "HOUR", exp.Expression);
  804. return true;
  805. }
  806. if (member == UtilConstants.PropertyInfo_DateTime_Minute)
  807. {
  808. DbFunction_DATEPART(this, "MINUTE", exp.Expression);
  809. return true;
  810. }
  811. if (member == UtilConstants.PropertyInfo_DateTime_Second)
  812. {
  813. DbFunction_DATEPART(this, "SECOND", exp.Expression);
  814. return true;
  815. }
  816. if (member == UtilConstants.PropertyInfo_DateTime_Millisecond)
  817. {
  818. DbFunction_DATEPART(this, "MILLISECOND", exp.Expression);
  819. return true;
  820. }
  821. if (member == UtilConstants.PropertyInfo_DateTime_DayOfWeek)
  822. {
  823. this._sqlBuilder.Append("(");
  824. DbFunction_DATEPART(this, "WEEKDAY", exp.Expression);
  825. this._sqlBuilder.Append(" - 1)");
  826. return true;
  827. }
  828. return false;
  829. }
  830. #region BinaryWithMethodHandlers
  831. static Dictionary<MethodInfo, Action<DbBinaryExpression, SqlGenerator>> InitBinaryWithMethodHandlers()
  832. {
  833. var binaryWithMethodHandlers = new Dictionary<MethodInfo, Action<DbBinaryExpression, SqlGenerator>>();
  834. binaryWithMethodHandlers.Add(UtilConstants.MethodInfo_String_Concat_String_String, StringConcat);
  835. binaryWithMethodHandlers.Add(UtilConstants.MethodInfo_String_Concat_Object_Object, StringConcat);
  836. var ret = Utils.Clone(binaryWithMethodHandlers);
  837. return ret;
  838. }
  839. static void StringConcat(DbBinaryExpression exp, SqlGenerator generator)
  840. {
  841. MethodInfo method = exp.Method;
  842. List<DbExpression> operands = new List<DbExpression>();
  843. operands.Add(exp.Right);
  844. DbExpression left = exp.Left;
  845. DbAddExpression e = null;
  846. while ((e = (left as DbAddExpression)) != null && (e.Method == UtilConstants.MethodInfo_String_Concat_String_String || e.Method == UtilConstants.MethodInfo_String_Concat_Object_Object))
  847. {
  848. operands.Add(e.Right);
  849. left = e.Left;
  850. }
  851. operands.Add(left);
  852. DbExpression whenExp = null;
  853. List<DbExpression> operandExps = new List<DbExpression>(operands.Count);
  854. for (int i = operands.Count - 1; i >= 0; i--)
  855. {
  856. DbExpression operand = operands[i];
  857. DbExpression opBody = operand;
  858. if (opBody.Type != UtilConstants.TypeOfString)
  859. {
  860. // 需要 cast type
  861. opBody = DbExpression.Convert(opBody, UtilConstants.TypeOfString);
  862. }
  863. DbExpression equalNullExp = DbExpression.Equal(opBody, UtilConstants.DbConstant_Null_String);
  864. if (whenExp == null)
  865. whenExp = equalNullExp;
  866. else
  867. whenExp = DbExpression.AndAlso(whenExp, equalNullExp);
  868. DbExpression thenExp = DbConstantExpression.StringEmpty;
  869. DbCaseWhenExpression.WhenThenExpressionPair whenThenPair = new DbCaseWhenExpression.WhenThenExpressionPair(equalNullExp, thenExp);
  870. List<DbCaseWhenExpression.WhenThenExpressionPair> whenThenExps = new List<DbCaseWhenExpression.WhenThenExpressionPair>(1);
  871. whenThenExps.Add(whenThenPair);
  872. DbExpression elseExp = opBody;
  873. DbCaseWhenExpression caseWhenExpression = DbExpression.CaseWhen(whenThenExps, elseExp, UtilConstants.TypeOfString);
  874. operandExps.Add(caseWhenExpression);
  875. }
  876. generator._sqlBuilder.Append("CASE", " WHEN ");
  877. whenExp.Accept(generator);
  878. generator._sqlBuilder.Append(" THEN ");
  879. DbConstantExpression.Null.Accept(generator);
  880. generator._sqlBuilder.Append(" ELSE ");
  881. generator._sqlBuilder.Append("(");
  882. for (int i = 0; i < operandExps.Count; i++)
  883. {
  884. if (i > 0)
  885. generator._sqlBuilder.Append(" + ");
  886. operandExps[i].Accept(generator);
  887. }
  888. generator._sqlBuilder.Append(")");
  889. generator._sqlBuilder.Append(" END");
  890. }
  891. #endregion
  892. }
  893. }