/src/Util.Datas/Sql/Builders/Core/SqlBuilderBase.cs

https://github.com/dotnetcore/Util · C# · 672 lines · 336 code · 80 blank · 256 comment · 21 complexity · 337a93b01f6f8b44bd4503a540bb8161 MD5 · raw file

  1. using System;
  2. using System.Collections.Generic;
  3. using System.Linq;
  4. using System.Text;
  5. using Util.Datas.Sql.Builders.Clauses;
  6. using Util.Datas.Sql.Builders.Filters;
  7. using Util.Datas.Sql.Matedatas;
  8. using Util.Domains.Repositories;
  9. using Util.Helpers;
  10. namespace Util.Datas.Sql.Builders.Core {
  11. /// <summary>
  12. /// Sql生成器
  13. /// </summary>
  14. public abstract class SqlBuilderBase : ISqlBuilder, IClauseAccessor, IUnionAccessor, ICteAccessor {
  15. #region 字段
  16. /// <summary>
  17. /// 参数管理器
  18. /// </summary>
  19. private IParameterManager _parameterManager;
  20. /// <summary>
  21. /// Sql方言
  22. /// </summary>
  23. private IDialect _dialect;
  24. /// <summary>
  25. /// Select子句
  26. /// </summary>
  27. private ISelectClause _selectClause;
  28. /// <summary>
  29. /// From子句
  30. /// </summary>
  31. private IFromClause _fromClause;
  32. /// <summary>
  33. /// Join子句
  34. /// </summary>
  35. private IJoinClause _joinClause;
  36. /// <summary>
  37. /// Where子句
  38. /// </summary>
  39. private IWhereClause _whereClause;
  40. /// <summary>
  41. /// GroupBy子句
  42. /// </summary>
  43. private IGroupByClause _groupByClause;
  44. /// <summary>
  45. /// OrderBy子句
  46. /// </summary>
  47. private IOrderByClause _orderByClause;
  48. /// <summary>
  49. /// 参数字面值解析器
  50. /// </summary>
  51. private IParamLiteralsResolver _paramLiteralsResolver;
  52. /// <summary>
  53. /// 是否已添加过滤器
  54. /// </summary>
  55. private bool _isAddFilters;
  56. /// <summary>
  57. /// 已排除过滤器集合
  58. /// </summary>
  59. private List<Type> _excludedFilters;
  60. #endregion
  61. #region 构造方法
  62. /// <summary>
  63. /// 初始化Sql生成器
  64. /// </summary>
  65. /// <param name="matedata">实体元数据解析器</param>
  66. /// <param name="tableDatabase">表数据库</param>
  67. /// <param name="parameterManager">参数管理器</param>
  68. protected SqlBuilderBase( IEntityMatedata matedata = null,ITableDatabase tableDatabase = null, IParameterManager parameterManager = null ) {
  69. EntityMatedata = matedata;
  70. TableDatabase = tableDatabase;
  71. _parameterManager = parameterManager;
  72. EntityResolver = new EntityResolver( matedata );
  73. AliasRegister = new EntityAliasRegister();
  74. Pager = new Pager();
  75. UnionItems = new List<BuilderItem>();
  76. CteItems = new List<BuilderItem>();
  77. _excludedFilters = new List<Type>();
  78. }
  79. #endregion
  80. #region 属性
  81. /// <summary>
  82. /// 实体元数据解析器
  83. /// </summary>
  84. protected IEntityMatedata EntityMatedata { get; private set; }
  85. /// <summary>
  86. /// 表数据库
  87. /// </summary>
  88. protected ITableDatabase TableDatabase { get; private set; }
  89. /// <summary>
  90. /// 实体解析器
  91. /// </summary>
  92. protected IEntityResolver EntityResolver { get; private set; }
  93. /// <summary>
  94. /// 实体别名注册器
  95. /// </summary>
  96. protected IEntityAliasRegister AliasRegister { get; private set; }
  97. /// <summary>
  98. /// 参数管理器
  99. /// </summary>
  100. protected IParameterManager ParameterManager => _parameterManager ?? ( _parameterManager = CreateParameterManager() );
  101. /// <summary>
  102. /// Sql方言
  103. /// </summary>
  104. protected IDialect Dialect => _dialect ?? ( _dialect = GetDialect() );
  105. /// <summary>
  106. /// Select子句
  107. /// </summary>
  108. public ISelectClause SelectClause => _selectClause ?? ( _selectClause = CreateSelectClause() );
  109. /// <summary>
  110. /// From子句
  111. /// </summary>
  112. public IFromClause FromClause => _fromClause ?? ( _fromClause = CreateFromClause() );
  113. /// <summary>
  114. /// Join子句
  115. /// </summary>
  116. public IJoinClause JoinClause => _joinClause ?? ( _joinClause = CreateJoinClause() );
  117. /// <summary>
  118. /// Where子句
  119. /// </summary>
  120. public IWhereClause WhereClause => _whereClause ?? ( _whereClause = CreatewWhereClause() );
  121. /// <summary>
  122. /// GroupBy子句
  123. /// </summary>
  124. public IGroupByClause GroupByClause => _groupByClause ?? ( _groupByClause = CreateGroupByClause() );
  125. /// <summary>
  126. /// OrderBy子句
  127. /// </summary>
  128. public IOrderByClause OrderByClause => _orderByClause ?? ( _orderByClause = CreateOrderByClause() );
  129. /// <summary>
  130. /// 参数字面值解析器
  131. /// </summary>
  132. protected IParamLiteralsResolver ParamLiteralsResolver => _paramLiteralsResolver ?? ( _paramLiteralsResolver = GetParamLiteralsResolver() );
  133. /// <summary>
  134. /// 跳过行数参数名
  135. /// </summary>
  136. protected string OffsetParam { get; private set; }
  137. /// <summary>
  138. /// 限制行数参数名
  139. /// </summary>
  140. protected string LimitParam { get; private set; }
  141. /// <summary>
  142. /// 联合操作项集合
  143. /// </summary>
  144. public List<BuilderItem> UnionItems { get; private set; }
  145. /// <summary>
  146. /// 公用表表达式CTE集合
  147. /// </summary>
  148. public List<BuilderItem> CteItems { get; private set; }
  149. /// <summary>
  150. /// 分页
  151. /// </summary>
  152. public IPager Pager { get; private set; }
  153. /// <summary>
  154. /// 是否包含联合操作
  155. /// </summary>
  156. public bool IsUnion => UnionItems.Count > 0;
  157. /// <summary>
  158. /// 是否包含分组操作
  159. /// </summary>
  160. public bool IsGroup => GroupByClause.IsGroup;
  161. #endregion
  162. #region 工厂方法
  163. /// <summary>
  164. /// 创建参数管理器
  165. /// </summary>
  166. protected virtual IParameterManager CreateParameterManager() {
  167. return new ParameterManager( Dialect );
  168. }
  169. /// <summary>
  170. /// 获取Sql方言
  171. /// </summary>
  172. protected abstract IDialect GetDialect();
  173. /// <summary>
  174. /// 创建Select子句
  175. /// </summary>
  176. protected virtual ISelectClause CreateSelectClause() {
  177. return new SelectClause( this, Dialect, EntityResolver, AliasRegister );
  178. }
  179. /// <summary>
  180. /// 创建From子句
  181. /// </summary>
  182. protected virtual IFromClause CreateFromClause() {
  183. return new FromClause( this, Dialect, EntityResolver, AliasRegister, TableDatabase );
  184. }
  185. /// <summary>
  186. /// 创建Join子句
  187. /// </summary>
  188. protected virtual IJoinClause CreateJoinClause() {
  189. return new JoinClause( this, Dialect, EntityResolver, AliasRegister, ParameterManager,TableDatabase );
  190. }
  191. /// <summary>
  192. /// 创建Where子句
  193. /// </summary>
  194. protected virtual IWhereClause CreatewWhereClause() {
  195. return new WhereClause( this, Dialect, EntityResolver, AliasRegister, ParameterManager );
  196. }
  197. /// <summary>
  198. /// 创建分组子句
  199. /// </summary>
  200. protected virtual IGroupByClause CreateGroupByClause() {
  201. return new GroupByClause( Dialect, EntityResolver, AliasRegister );
  202. }
  203. /// <summary>
  204. /// 创建排序子句
  205. /// </summary>
  206. protected virtual IOrderByClause CreateOrderByClause() {
  207. return new OrderByClause( Dialect, EntityResolver, AliasRegister );
  208. }
  209. /// <summary>
  210. /// 获取参数字面值解析器
  211. /// </summary>
  212. protected virtual IParamLiteralsResolver GetParamLiteralsResolver() {
  213. return new ParamLiteralsResolver();
  214. }
  215. #endregion
  216. #region Clone(复制Sql生成器)
  217. /// <summary>
  218. /// 复制Sql生成器
  219. /// </summary>
  220. public abstract ISqlBuilder Clone();
  221. /// <summary>
  222. /// 复制Sql生成器
  223. /// </summary>
  224. /// <param name="sqlBuilder">源生成器</param>
  225. protected void Clone( SqlBuilderBase sqlBuilder ) {
  226. EntityMatedata = sqlBuilder.EntityMatedata;
  227. _parameterManager = sqlBuilder._parameterManager?.Clone();
  228. EntityResolver = sqlBuilder.EntityResolver ?? new EntityResolver( EntityMatedata );
  229. AliasRegister = sqlBuilder.AliasRegister?.Clone() ?? new EntityAliasRegister();
  230. _selectClause = sqlBuilder._selectClause?.Clone( this, AliasRegister );
  231. _fromClause = sqlBuilder._fromClause?.Clone( this, AliasRegister );
  232. _joinClause = sqlBuilder._joinClause?.Clone( this, AliasRegister, _parameterManager );
  233. _whereClause = sqlBuilder._whereClause?.Clone( this, AliasRegister, _parameterManager );
  234. _groupByClause = sqlBuilder._groupByClause?.Clone( AliasRegister );
  235. _orderByClause = sqlBuilder._orderByClause?.Clone( AliasRegister );
  236. Pager = sqlBuilder.Pager;
  237. OffsetParam = sqlBuilder.OffsetParam;
  238. LimitParam = sqlBuilder.LimitParam;
  239. UnionItems = sqlBuilder.UnionItems.Select( t => new BuilderItem( t.Name, t.Builder.Clone() ) ).ToList();
  240. CteItems = sqlBuilder.CteItems.Select( t => new BuilderItem( t.Name, t.Builder.Clone() ) ).ToList();
  241. _excludedFilters = sqlBuilder._excludedFilters;
  242. }
  243. #endregion
  244. #region Clear(清空)
  245. /// <summary>
  246. /// 清空
  247. /// </summary>
  248. public ISqlBuilder Clear() {
  249. AliasRegister = new EntityAliasRegister();
  250. ClearSelect();
  251. ClearFrom();
  252. ClearJoin();
  253. ClearWhere();
  254. ClearGroupBy();
  255. ClearOrderBy();
  256. ClearSqlParams();
  257. ClearPageParams();
  258. ClearUnionBuilders();
  259. ClearCte();
  260. return this;
  261. }
  262. /// <summary>
  263. /// 清空Select子句
  264. /// </summary>
  265. public ISqlBuilder ClearSelect() {
  266. _selectClause = CreateSelectClause();
  267. return this;
  268. }
  269. /// <summary>
  270. /// 清空From子句
  271. /// </summary>
  272. public ISqlBuilder ClearFrom() {
  273. _fromClause = CreateFromClause();
  274. return this;
  275. }
  276. /// <summary>
  277. /// 清空Join子句
  278. /// </summary>
  279. public ISqlBuilder ClearJoin() {
  280. _joinClause = CreateJoinClause();
  281. return this;
  282. }
  283. /// <summary>
  284. /// 清空Where子句
  285. /// </summary>
  286. public ISqlBuilder ClearWhere() {
  287. _isAddFilters = false;
  288. _whereClause = CreatewWhereClause();
  289. return this;
  290. }
  291. /// <summary>
  292. /// 清空GroupBy子句
  293. /// </summary>
  294. public ISqlBuilder ClearGroupBy() {
  295. _groupByClause = CreateGroupByClause();
  296. return this;
  297. }
  298. /// <summary>
  299. /// 清空OrderBy子句
  300. /// </summary>
  301. public ISqlBuilder ClearOrderBy() {
  302. _orderByClause = CreateOrderByClause();
  303. return this;
  304. }
  305. /// <summary>
  306. /// 清空Sql参数
  307. /// </summary>
  308. public ISqlBuilder ClearSqlParams() {
  309. _parameterManager.Clear();
  310. return this;
  311. }
  312. /// <summary>
  313. /// 清空分页参数
  314. /// </summary>
  315. public ISqlBuilder ClearPageParams() {
  316. Pager = null;
  317. OffsetParam = null;
  318. LimitParam = null;
  319. return this;
  320. }
  321. /// <summary>
  322. /// 清空联合操作项
  323. /// </summary>
  324. public ISqlBuilder ClearUnionBuilders() {
  325. UnionItems = new List<BuilderItem>();
  326. return this;
  327. }
  328. /// <summary>
  329. /// 清空公用表表达式
  330. /// </summary>
  331. public ISqlBuilder ClearCte() {
  332. CteItems = new List<BuilderItem>();
  333. return this;
  334. }
  335. #endregion
  336. #region New(创建Sql生成器)
  337. /// <summary>
  338. /// 创建Sql生成器
  339. /// </summary>
  340. public abstract ISqlBuilder New();
  341. #endregion
  342. #region ToDebugSql(生成调试Sql语句)
  343. /// <summary>
  344. /// 生成调试Sql语句
  345. /// </summary>
  346. public virtual string ToDebugSql() {
  347. return GetDebugSql( ToSql() );
  348. }
  349. /// <summary>
  350. /// 获取调试Sql
  351. /// </summary>
  352. private string GetDebugSql( string sql ) {
  353. var parameters = GetParams();
  354. foreach( var parameter in parameters )
  355. sql = Regex.Replace( sql, $@"{parameter.Key}\b", ParamLiteralsResolver.GetParamLiterals( parameter.Value ) );
  356. return sql;
  357. }
  358. #endregion
  359. #region ToSql(生成Sql语句)
  360. /// <summary>
  361. /// 生成Sql语句
  362. /// </summary>
  363. public virtual string ToSql() {
  364. Init();
  365. Validate();
  366. var result = new StringBuilder();
  367. CreateSql( result );
  368. return result.ToString().Trim();
  369. }
  370. /// <summary>
  371. /// 初始化
  372. /// </summary>
  373. public virtual void Init() {
  374. OrderByClause.OrderBy( Pager?.Order );
  375. }
  376. /// <summary>
  377. /// 验证
  378. /// </summary>
  379. public virtual void Validate() {
  380. FromClause.Validate();
  381. OrderByClause.Validate( IsLimit );
  382. }
  383. /// <summary>
  384. /// 是否限制行数
  385. /// </summary>
  386. protected bool IsLimit => string.IsNullOrWhiteSpace( LimitParam ) == false;
  387. /// <summary>
  388. /// 创建Sql语句
  389. /// </summary>
  390. protected virtual void CreateSql( StringBuilder result ) {
  391. CreateCte( result );
  392. if( _isAddFilters == false )
  393. AddFilters();
  394. if( IsUnion ) {
  395. CreateSqlByUnion( result );
  396. return;
  397. }
  398. CreateSqlByNoUnion( result );
  399. }
  400. /// <summary>
  401. /// 创建CTE
  402. /// </summary>
  403. protected virtual void CreateCte( StringBuilder result ) {
  404. if( CteItems.Count == 0 )
  405. return;
  406. var cte = new StringBuilder();
  407. cte.Append( $"{GetCteKeyWord()} " );
  408. foreach( var item in CteItems ) {
  409. cte.AppendLine( $"{Dialect.SafeName( item.Name )} " );
  410. cte.AppendLine( $"As ({item.Builder.ToSql()})," );
  411. }
  412. result.AppendLine( cte.ToString().RemoveEnd( $",{Common.Line}" ) );
  413. }
  414. /// <summary>
  415. /// 获取CTE关键字
  416. /// </summary>
  417. protected virtual string GetCteKeyWord() {
  418. return "With";
  419. }
  420. /// <summary>
  421. /// 创建Sql语句 - 联合
  422. /// </summary>
  423. protected void CreateSqlByUnion( StringBuilder result ) {
  424. result.Append( "(" );
  425. AppendSelect( result );
  426. AppendFrom( result );
  427. AppendSql( result, JoinClause.ToSql() );
  428. AppendSql( result, WhereClause.ToSql() );
  429. AppendSql( result, GroupByClause.ToSql() );
  430. AppendSql( result, ")" );
  431. foreach( var operation in UnionItems ) {
  432. AppendSql( result, operation.Name );
  433. AppendSql( result, $"({operation.Builder.ToSql()}" );
  434. AppendSql( result, ")" );
  435. }
  436. AppendSql( result, OrderByClause.ToSql() );
  437. AppendLimit( result );
  438. }
  439. /// <summary>
  440. /// 创建Sql语句
  441. /// </summary>
  442. protected void CreateSqlByNoUnion( StringBuilder result ) {
  443. AppendSelect( result );
  444. AppendFrom( result );
  445. AppendSql( result, JoinClause.ToSql() );
  446. AppendSql( result, WhereClause.ToSql() );
  447. AppendSql( result, GroupByClause.ToSql() );
  448. AppendSql( result, OrderByClause.ToSql() );
  449. AppendLimit( result );
  450. }
  451. /// <summary>
  452. /// 添加Sql
  453. /// </summary>
  454. protected void AppendSql( StringBuilder result, string sql ) {
  455. if( string.IsNullOrWhiteSpace( sql ) )
  456. return;
  457. result.AppendLine( $"{sql} " );
  458. }
  459. /// <summary>
  460. /// 添加Select子句
  461. /// </summary>
  462. protected virtual void AppendSelect( StringBuilder result ) {
  463. var sql = SelectClause.ToSql();
  464. if( string.IsNullOrWhiteSpace( sql ) )
  465. throw new InvalidOperationException( "必须设置Select子句" );
  466. AppendSql( result, sql );
  467. }
  468. /// <summary>
  469. /// 添加From子句
  470. /// </summary>
  471. protected virtual void AppendFrom( StringBuilder result ) {
  472. var sql = FromClause.ToSql();
  473. if( string.IsNullOrWhiteSpace( sql ) )
  474. throw new InvalidOperationException( "必须设置From子句" );
  475. AppendSql( result, sql );
  476. }
  477. /// <summary>
  478. /// 添加过滤器列表
  479. /// </summary>
  480. protected void AddFilters() {
  481. _isAddFilters = true;
  482. var context = new SqlContext( Dialect, AliasRegister, EntityMatedata, ParameterManager, this );
  483. SqlFilterCollection.Filters.ForEach(filter => {
  484. if (_excludedFilters.Count > 0 && _excludedFilters.Exists(x => x == filter.GetType()))
  485. return;
  486. filter.Filter(context);
  487. });
  488. }
  489. /// <summary>
  490. /// 添加分页Sql
  491. /// </summary>
  492. private void AppendLimit( StringBuilder result ) {
  493. if( IsLimit )
  494. AppendSql( result, CreateLimitSql() );
  495. }
  496. /// <summary>
  497. /// 创建分页Sql
  498. /// </summary>
  499. protected abstract string CreateLimitSql();
  500. #endregion
  501. #region AddParam(添加参数)
  502. /// <summary>
  503. /// 添加参数
  504. /// </summary>
  505. /// <param name="name">参数名</param>
  506. /// <param name="value">参数值</param>
  507. public ISqlBuilder AddParam( string name, object value ) {
  508. ParameterManager.Add( name, value );
  509. return this;
  510. }
  511. #endregion
  512. #region GetParams(获取参数)
  513. /// <summary>
  514. /// 获取参数
  515. /// </summary>
  516. public IReadOnlyDictionary<string, object> GetParams() {
  517. return ParameterManager.GetParams();
  518. }
  519. #endregion
  520. #region GetCondition(获取查询条件)
  521. /// <summary>
  522. /// 获取查询条件
  523. /// </summary>
  524. public string GetCondition() {
  525. return WhereClause.GetCondition();
  526. }
  527. #endregion
  528. #region Page(设置分页)
  529. /// <summary>
  530. /// 设置跳过行数
  531. /// </summary>
  532. /// <param name="count">跳过的行数</param>
  533. public ISqlBuilder Skip( int count ) {
  534. var param = GetOffsetParam();
  535. ParameterManager.Add( param, count );
  536. return this;
  537. }
  538. /// <summary>
  539. /// 获取跳过行数的参数名
  540. /// </summary>
  541. protected string GetOffsetParam() {
  542. if( string.IsNullOrWhiteSpace( OffsetParam ) == false )
  543. return OffsetParam;
  544. OffsetParam = ParameterManager.GenerateName();
  545. ParameterManager.Add( OffsetParam, 0 );
  546. return OffsetParam;
  547. }
  548. /// <summary>
  549. /// 设置获取行数
  550. /// </summary>
  551. /// <param name="count">获取的行数</param>
  552. public ISqlBuilder Take( int count ) {
  553. var param = GetLimitParam();
  554. ParameterManager.Add( param, count );
  555. Pager.PageSize = count;
  556. return this;
  557. }
  558. /// <summary>
  559. /// 获取限制行数的参数名
  560. /// </summary>
  561. protected string GetLimitParam() {
  562. if( string.IsNullOrWhiteSpace( LimitParam ) == false )
  563. return LimitParam;
  564. LimitParam = ParameterManager.GenerateName();
  565. return LimitParam;
  566. }
  567. /// <summary>
  568. /// 设置分页
  569. /// </summary>
  570. /// <param name="pager">分页参数</param>
  571. public ISqlBuilder Page( IPager pager ) {
  572. if( pager == null )
  573. return this;
  574. Pager = pager;
  575. Skip( pager.GetSkipCount() ).Take( pager.PageSize );
  576. return this;
  577. }
  578. #endregion
  579. #region IgnoreFilter(忽略过滤器)
  580. /// <summary>
  581. /// 忽略过滤器
  582. /// </summary>
  583. /// <typeparam name="TSqlFilter">Sql过滤器类型</typeparam>
  584. public virtual ISqlBuilder IgnoreFilter<TSqlFilter>() where TSqlFilter : ISqlFilter {
  585. if (_excludedFilters.Exists(x => x == typeof(TSqlFilter)))
  586. return this;
  587. _excludedFilters.Add(typeof(TSqlFilter));
  588. return this;
  589. }
  590. #endregion
  591. }
  592. }