Files
SqlSugar/Src/Asp.Net/SqlSugar/Abstract/SqlBuilderProvider/QueryBuilder.cs

482 lines
17 KiB
C#
Raw Normal View History

2017-01-07 21:54:51 +08:00
using System;
using System.Collections.Generic;
using System.Data.SqlClient;
using System.Linq;
2017-03-05 16:18:49 +08:00
using System.Linq.Expressions;
2017-01-07 21:54:51 +08:00
using System.Text;
2017-04-29 20:27:55 +08:00
using System.Text.RegularExpressions;
2017-01-07 21:54:51 +08:00
namespace SqlSugar
{
2017-04-29 20:27:55 +08:00
public abstract class QueryBuilder : IDMLBuilder
2017-01-07 21:54:51 +08:00
{
2017-04-26 01:52:29 +08:00
2017-04-29 20:27:55 +08:00
public QueryBuilder()
2017-04-26 01:52:29 +08:00
{
2017-04-30 22:49:41 +08:00
this.Parameters = new List<SugarParameter>();
2017-04-26 01:52:29 +08:00
}
2017-04-25 01:04:55 +08:00
#region Private Fileds
2017-05-27 16:44:48 +08:00
protected List<JoinQueryInfo> _JoinQueryInfos;
2017-06-18 07:16:50 +08:00
protected Dictionary<string, string> _EasyJoinInfos;
2017-01-07 21:54:51 +08:00
private List<string> _WhereInfos;
2017-04-30 16:56:41 +08:00
private string _HavingInfos;
2017-05-27 16:44:48 +08:00
protected string _TableNameString;
2017-04-25 01:04:55 +08:00
#endregion
2017-01-07 21:54:51 +08:00
2017-04-25 01:04:55 +08:00
#region Service object
2017-04-29 20:27:55 +08:00
public StringBuilder sql { get; set; }
2017-03-05 16:18:49 +08:00
public SqlSugarClient Context { get; set; }
2017-04-09 07:30:15 +08:00
public ILambdaExpressions LambdaExpressions { get; set; }
2017-04-26 01:52:29 +08:00
public ISqlBuilder Builder { get; set; }
2017-04-25 01:04:55 +08:00
#endregion
2017-01-07 21:54:51 +08:00
2017-04-25 01:04:55 +08:00
#region Splicing basic
2017-04-27 01:17:46 +08:00
public bool IsCount { get; set; }
2017-01-07 21:54:51 +08:00
public int? Skip { get; set; }
2017-07-14 01:32:56 +08:00
public int ExternalPageIndex { get; set; }
public int ExternalPageSize { get; set; }
2017-01-07 21:54:51 +08:00
public int? Take { get; set; }
public string OrderByValue { get; set; }
2017-03-05 16:18:49 +08:00
public object SelectValue { get; set; }
public string SelectCacheKey { get; set; }
2017-03-08 14:01:41 +08:00
public string EntityName { get; set; }
2017-05-27 17:36:50 +08:00
public Type EntityType { get; set; }
2017-01-07 21:54:51 +08:00
public string TableWithString { get; set; }
public string GroupByValue { get; set; }
2017-06-13 01:54:39 +08:00
public string PartitionByValue { get; set; }
2017-01-07 21:54:51 +08:00
public int WhereIndex { get; set; }
public int JoinIndex { get; set; }
2017-06-10 02:26:19 +08:00
public bool IsDisabledGobalFilter { get; set; }
2017-04-30 22:49:41 +08:00
public virtual List<SugarParameter> Parameters { get; set; }
2017-06-18 07:16:50 +08:00
public Dictionary<string, string> EasyJoinInfos
{
get
{
2017-08-25 22:25:29 +08:00
_EasyJoinInfos = UtilMethods.IsNullReturnNew(_EasyJoinInfos);
2017-06-18 07:16:50 +08:00
return _EasyJoinInfos;
}
set { _EasyJoinInfos = value; }
}
2017-04-25 01:04:55 +08:00
public virtual List<JoinQueryInfo> JoinQueryInfos
{
get
{
2017-08-25 22:25:29 +08:00
_JoinQueryInfos = UtilMethods.IsNullReturnNew(_JoinQueryInfos);
2017-04-25 01:04:55 +08:00
return _JoinQueryInfos;
}
set { _JoinQueryInfos = value; }
}
public virtual string TableShortName { get; set; }
public virtual List<string> WhereInfos
{
get
{
2017-08-25 22:25:29 +08:00
_WhereInfos = UtilMethods.IsNullReturnNew(_WhereInfos);
2017-04-25 01:04:55 +08:00
return _WhereInfos;
}
set { _WhereInfos = value; }
}
2017-04-30 16:56:41 +08:00
public virtual string HavingInfos
{
get
{
return _HavingInfos;
}
set
{
_HavingInfos = value;
}
}
2017-04-25 01:04:55 +08:00
#endregion
#region Lambada Type
public ResolveExpressType SelectType
{
get
{
return this.IsSingle() ? ResolveExpressType.SelectSingle : ResolveExpressType.SelectMultiple;
}
}
public ResolveExpressType WheretType
{
get
{
return this.IsSingle() ? ResolveExpressType.WhereSingle : ResolveExpressType.WhereMultiple;
}
}
#endregion
2017-01-07 21:54:51 +08:00
2017-04-25 01:06:18 +08:00
#region Sql Template
2017-01-07 21:54:51 +08:00
public virtual string SqlTemplate
{
get
{
2017-04-29 20:27:55 +08:00
return "SELECT {0} FROM {1}{2}{3}{4} ";
2017-01-07 21:54:51 +08:00
}
}
public virtual string JoinTemplate
{
get
{
2017-04-29 20:27:55 +08:00
return "{0}JOIN {1}{2}ON {3} ";
2017-01-07 21:54:51 +08:00
}
}
2017-04-27 00:55:02 +08:00
public virtual string PageTempalte
{
get
{
2017-07-08 01:22:14 +08:00
return @"SELECT * FROM ({0}) T WHERE RowIndex BETWEEN {1} AND {2}";
2017-04-29 20:27:55 +08:00
}
}
2017-07-14 03:03:49 +08:00
public virtual string ExternalPageTempalte
{
get
{
return @"SELECT * FROM ({0}) T WHERE RowIndex2 BETWEEN {1} AND {2}";
}
}
2017-04-29 20:27:55 +08:00
public virtual string DefaultOrderByTemplate
{
get
{
2017-08-28 01:18:06 +08:00
return "ORDER BY "+this.Builder.SqlDateNow+" ";
2017-04-29 20:27:55 +08:00
}
}
public virtual string OrderByTemplate
{
get
{
return "ORDER BY ";
}
}
public virtual string GroupByTemplate
{
get
{
return "GROUP BY ";
}
}
2017-06-13 01:54:39 +08:00
public virtual string PartitionByTemplate
{
get
{
return "PARTITION BY ";
}
}
2017-04-29 20:27:55 +08:00
public virtual string MaxTemplate
{
get
{
return "MAX({0})";
}
}
public virtual string MinTemplate
{
get
{
return "MIN({0})";
}
}
public virtual string SumTemplate
{
get
{
return "SUM({0})";
}
}
public virtual string AvgTemplate
{
get
{
return "AVG({0})";
}
}
2017-04-30 16:56:41 +08:00
public virtual string InTemplate
{
get
{
2017-04-29 20:27:55 +08:00
return "{0} IN ({1}) ";
2017-04-27 00:55:02 +08:00
}
}
2017-04-25 01:04:55 +08:00
#endregion
#region Common Methods
public virtual bool IsSingle()
2017-01-07 21:54:51 +08:00
{
2017-06-18 07:16:50 +08:00
var isSingle = Builder.QueryBuilder.JoinQueryInfos.IsNullOrEmpty() && !EasyJoinInfos.Any();
2017-04-25 01:04:55 +08:00
return isSingle;
}
public virtual ExpressionResult GetExpressionValue(Expression expression, ResolveExpressType resolveType)
{
ILambdaExpressions resolveExpress = this.LambdaExpressions;
2017-04-26 01:52:29 +08:00
this.LambdaExpressions.Clear();
2017-04-29 20:27:55 +08:00
resolveExpress.JoinQueryInfos = Builder.QueryBuilder.JoinQueryInfos;
2017-06-16 02:21:29 +08:00
resolveExpress.IsSingle = IsSingle();
2017-04-25 01:04:55 +08:00
resolveExpress.MappingColumns = Context.MappingColumns;
resolveExpress.MappingTables = Context.MappingTables;
2017-05-01 14:23:13 +08:00
resolveExpress.IgnoreComumnList = Context.IgnoreColumns;
2017-04-25 01:04:55 +08:00
resolveExpress.Resolve(expression, resolveType);
2017-04-30 22:49:41 +08:00
this.Parameters.AddRange(resolveExpress.Parameters);
2017-04-25 01:04:55 +08:00
var reval = resolveExpress.Result;
2017-09-16 21:27:31 +08:00
var isSingleTableHasSubquery = IsSingle() && resolveExpress.SingleTableNameSubqueryShortName.IsValuable();
if (isSingleTableHasSubquery) {
Check.Exception(!string.IsNullOrEmpty(this.TableShortName) && resolveExpress.SingleTableNameSubqueryShortName != this.TableShortName, "{0} and {1} need same name");
this.TableShortName = resolveExpress.SingleTableNameSubqueryShortName;
}
2017-04-25 01:04:55 +08:00
return reval;
}
public virtual string ToSqlString()
{
2017-07-14 11:04:23 +08:00
string oldOrderBy = this.OrderByValue;
2017-07-14 12:16:56 +08:00
string externalOrderBy = oldOrderBy;
2017-09-12 14:05:52 +08:00
var isIgnoreOrderBy = this.IsCount&&this.PartitionByValue.IsNullOrEmpty();
2017-08-11 12:32:49 +08:00
AppendFilter();
2017-04-29 20:27:55 +08:00
sql = new StringBuilder();
2017-07-08 01:41:59 +08:00
if (this.OrderByValue == null && (Skip != null || Take != null)) this.OrderByValue = " ORDER BY GetDate() ";
2017-07-08 01:22:14 +08:00
if (this.PartitionByValue.IsValuable())
{
this.OrderByValue = this.PartitionByValue + this.OrderByValue;
}
2017-07-08 01:41:59 +08:00
var isRowNumber = Skip != null || Take != null;
var rowNumberString = string.Format(",ROW_NUMBER() OVER({0}) AS RowIndex ", GetOrderByString);
2017-08-09 12:44:45 +08:00
string groupByValue = GetGroupByString + HavingInfos;
string orderByValue = (!isRowNumber && this.OrderByValue.IsValuable()) ? GetOrderByString : null;
2017-09-12 14:05:52 +08:00
if (isIgnoreOrderBy) { orderByValue = null; }
2017-08-09 12:44:45 +08:00
sql.AppendFormat(SqlTemplate, GetSelectValue, GetTableNameString, GetWhereValueString, groupByValue, orderByValue);
2017-09-12 14:05:52 +08:00
sql.Replace(UtilConstants.ReplaceKey, isRowNumber ? (isIgnoreOrderBy ? null : rowNumberString) : null);
if (isIgnoreOrderBy) { this.OrderByValue = oldOrderBy; return sql.ToString(); }
2017-07-14 11:04:23 +08:00
var result = ToPageSql(sql.ToString(), this.Take, this.Skip);
if (ExternalPageIndex > 0)
{
2017-08-11 12:32:49 +08:00
if (externalOrderBy.IsNullOrEmpty())
{
2017-07-14 12:16:56 +08:00
externalOrderBy = " ORDER BY GetDate() ";
}
2017-08-11 12:32:49 +08:00
result = string.Format("SELECT *,ROW_NUMBER() OVER({0}) AS RowIndex2 FROM ({1}) ExternalTable ", GetExternalOrderBy(externalOrderBy), result);
result = ToPageSql2(result, ExternalPageIndex, ExternalPageSize, true);
2017-07-14 01:42:25 +08:00
}
2017-07-14 02:35:55 +08:00
this.OrderByValue = oldOrderBy;
2017-07-14 01:42:25 +08:00
return result;
2017-07-14 01:32:56 +08:00
}
2017-08-11 12:32:49 +08:00
public virtual void AppendFilter()
{
if (!IsDisabledGobalFilter && this.Context.QueryFilter.GeFilterList.IsValuable())
{
var gobalFilterList = this.Context.QueryFilter.GeFilterList.Where(it => it.FilterName.IsNullOrEmpty()).ToList();
foreach (var item in gobalFilterList.Where(it => it.IsJoinQuery == !IsSingle()))
{
var filterResult = item.FilterValue(this.Context);
WhereInfos.Add(this.Builder.AppendWhereOrAnd(this.WhereInfos.IsNullOrEmpty(), filterResult.Sql));
var filterParamters = this.Context.Ado.GetParameters(filterResult.Parameters);
if (filterParamters.IsValuable())
{
this.Parameters.AddRange(filterParamters);
}
}
}
}
2017-07-16 02:38:23 +08:00
public virtual string GetExternalOrderBy(string externalOrderBy)
{
return Regex.Replace(externalOrderBy, @"\[\w+\]\.", "");
}
2017-07-14 11:04:23 +08:00
public virtual string ToCountSql(string sql)
{
2017-07-14 02:35:55 +08:00
2017-07-14 11:04:23 +08:00
return string.Format(" SELECT COUNT(1) FROM ({0}) CountTable ", sql);
2017-07-14 02:35:55 +08:00
}
2017-07-14 11:04:23 +08:00
public virtual string ToPageSql(string sql, int? take, int? skip, bool isExternal = false)
2017-07-14 01:32:56 +08:00
{
2017-07-14 11:04:23 +08:00
string temp = isExternal ? ExternalPageTempalte : PageTempalte;
2017-07-14 01:32:56 +08:00
if (skip != null && take == null)
2017-04-27 00:55:02 +08:00
{
2017-07-14 03:03:49 +08:00
return string.Format(temp, sql.ToString(), skip.ObjToInt() + 1, long.MaxValue);
2017-04-27 00:55:02 +08:00
}
2017-07-14 01:32:56 +08:00
else if (skip == null && take != null)
2017-04-27 00:55:02 +08:00
{
2017-07-14 03:03:49 +08:00
return string.Format(temp, sql.ToString(), 1, take.ObjToInt());
2017-04-27 00:55:02 +08:00
}
2017-07-14 01:32:56 +08:00
else if (skip != null && take != null)
2017-04-27 00:55:02 +08:00
{
2017-07-14 03:03:49 +08:00
return string.Format(temp, sql.ToString(), skip.ObjToInt() + 1, skip.ObjToInt() + take.ObjToInt());
2017-04-27 00:55:02 +08:00
}
2017-04-29 20:27:55 +08:00
else
{
return sql.ToString();
2017-04-27 00:55:02 +08:00
}
2017-01-07 21:54:51 +08:00
}
2017-07-14 11:04:23 +08:00
public virtual string ToPageSql2(string sql, int? pageIndex, int? pageSize, bool isExternal = false)
{
string temp = isExternal ? ExternalPageTempalte : PageTempalte;
return string.Format(temp, sql.ToString(), (pageIndex - 1) * pageSize+1, pageIndex * pageSize);
}
2017-04-25 01:04:55 +08:00
public virtual string ToJoinString(JoinQueryInfo joinInfo)
{
return string.Format(
this.JoinTemplate,
2017-08-25 22:22:12 +08:00
joinInfo.JoinType.ToString() + UtilConstants.Space,
Builder.GetTranslationTableName(joinInfo.TableName) + UtilConstants.Space,
2017-09-11 12:38:58 +08:00
joinInfo.ShortName + UtilConstants.Space + TableWithString,
2017-04-25 01:04:55 +08:00
joinInfo.JoinWhere);
}
public virtual void Clear()
{
this.Skip = 0;
this.Take = 0;
2017-04-29 20:27:55 +08:00
this.sql = null;
2017-04-25 01:04:55 +08:00
this.WhereIndex = 0;
2017-04-30 22:49:41 +08:00
this.Parameters = null;
2017-04-25 01:04:55 +08:00
this.GroupByValue = null;
this._TableNameString = null;
this.WhereInfos = null;
this.JoinQueryInfos = null;
}
2017-04-29 20:27:55 +08:00
public virtual bool IsComplexModel(string sql)
{
return Regex.IsMatch(sql, @"AS \[\w+\.\w+\]");
}
2017-04-25 01:04:55 +08:00
#endregion
2017-03-08 14:01:41 +08:00
2017-04-25 01:04:55 +08:00
#region Get SQL Partial
2017-03-05 16:18:49 +08:00
public virtual string GetSelectValue
2017-01-07 21:54:51 +08:00
{
get
{
2017-03-05 16:18:49 +08:00
string reval = string.Empty;
2017-04-25 01:04:55 +08:00
if (this.SelectValue == null || this.SelectValue is string)
2017-01-07 21:54:51 +08:00
{
2017-03-05 16:18:49 +08:00
reval = GetSelectValueByString();
2017-01-07 21:54:51 +08:00
}
2017-03-05 16:18:49 +08:00
else
{
reval = GetSelectValueByExpression();
}
2017-04-25 01:04:55 +08:00
if (this.SelectType == ResolveExpressType.SelectMultiple)
{
this.SelectCacheKey = this.SelectCacheKey + string.Join("-", this._JoinQueryInfos.Select(it => it.TableName));
2017-03-05 16:18:49 +08:00
}
return reval;
}
}
public virtual string GetSelectValueByExpression()
{
var expression = this.SelectValue as Expression;
2017-04-25 01:04:55 +08:00
var reval = GetExpressionValue(expression, this.SelectType).GetResultString();
2017-03-05 16:18:49 +08:00
this.SelectCacheKey = reval;
return reval;
}
public virtual string GetSelectValueByString()
{
string reval;
if (this.SelectValue.IsNullOrEmpty())
{
string pre = null;
2017-03-08 14:12:14 +08:00
if (this.JoinQueryInfos.IsValuable() && this.JoinQueryInfos.Any(it => TableShortName.IsValuable()))
2017-03-05 16:18:49 +08:00
{
2017-03-08 14:12:14 +08:00
pre = Builder.GetTranslationColumnName(TableShortName) + ".";
2017-03-05 16:18:49 +08:00
}
2017-09-06 16:37:25 +08:00
reval = string.Join(",", this.Context.EntityMaintenance.GetEntityInfo(this.EntityType).Columns.Where(it => !it.IsIgnore).Select(it => pre + Builder.GetTranslationColumnName(it.EntityName, it.PropertyName)));
2017-01-07 21:54:51 +08:00
}
2017-03-05 16:18:49 +08:00
else
{
reval = this.SelectValue.ObjToString();
2017-03-05 17:15:36 +08:00
this.SelectCacheKey = reval;
2017-03-05 16:18:49 +08:00
}
return reval;
2017-01-07 21:54:51 +08:00
}
public virtual string GetWhereValueString
{
get
{
if (this.WhereInfos == null) return null;
else
{
2017-08-25 22:22:12 +08:00
return string.Join(UtilConstants.Space, this.WhereInfos);
2017-01-07 21:54:51 +08:00
}
}
}
public virtual string GetJoinValueString
{
get
{
if (this.JoinQueryInfos.IsNullOrEmpty()) return null;
2017-03-05 16:18:49 +08:00
else
{
2017-08-25 22:22:12 +08:00
return string.Join(UtilConstants.Space, this.JoinQueryInfos.Select(it => this.ToJoinString(it)));
2017-01-07 21:54:51 +08:00
}
}
}
2017-04-25 01:04:55 +08:00
public virtual string GetTableNameString
2017-01-07 21:54:51 +08:00
{
get
{
2017-04-26 02:42:26 +08:00
var result = Builder.GetTranslationTableName(EntityName);
2017-08-25 22:22:12 +08:00
result += UtilConstants.Space;
2017-04-25 01:04:55 +08:00
if (this.TableShortName.IsValuable())
{
2017-08-25 22:22:12 +08:00
result += (TableShortName + UtilConstants.Space);
2017-04-25 01:04:55 +08:00
}
2017-09-08 14:02:17 +08:00
if (this.TableWithString.IsValuable())
{
result += TableWithString + UtilConstants.Space;
}
2017-04-26 02:14:09 +08:00
if (!this.IsSingle())
{
2017-08-25 22:22:12 +08:00
result += GetJoinValueString + UtilConstants.Space;
2017-04-26 02:14:09 +08:00
}
2017-06-18 07:16:50 +08:00
if (this.EasyJoinInfos.IsValuable())
{
2017-07-06 01:27:05 +08:00
2017-06-18 07:16:50 +08:00
if (this.TableWithString.IsValuable())
{
2017-07-08 01:22:14 +08:00
result += "," + string.Join(",", this.EasyJoinInfos.Select(it => string.Format("{0} {1} {2} ", GetTableName(it.Value), it.Key, TableWithString)));
2017-06-18 07:16:50 +08:00
}
else
{
2017-07-06 01:27:05 +08:00
result += "," + string.Join(",", this.EasyJoinInfos.Select(it => string.Format("{0} {1} ", GetTableName(it.Value), it.Key)));
2017-06-18 07:16:50 +08:00
}
}
2017-04-25 01:04:55 +08:00
return result;
2017-01-07 21:54:51 +08:00
}
}
2017-04-26 02:14:09 +08:00
public virtual string GetOrderByString
{
get
{
2017-06-18 06:49:51 +08:00
if (this.OrderByValue == null) return null;
2017-09-12 14:02:12 +08:00
if (IsCount&&this.PartitionByValue.IsNullOrEmpty()) return null;
2017-05-27 17:36:50 +08:00
else
2017-06-18 06:49:51 +08:00
{
2017-07-08 01:22:14 +08:00
return this.OrderByValue;
2017-06-18 06:49:51 +08:00
}
2017-04-26 02:14:09 +08:00
}
}
public virtual string GetGroupByString
{
get
{
2017-07-28 10:18:34 +08:00
if (this.GroupByValue == null) return null;
if (this.GroupByValue.Last() != ' ' )
{
2017-08-25 22:22:12 +08:00
return this.GroupByValue + UtilConstants.Space;
2017-07-28 10:18:34 +08:00
}
2017-04-26 02:14:09 +08:00
return this.GroupByValue;
}
}
2017-04-25 01:04:55 +08:00
#endregion
2017-07-06 01:27:05 +08:00
private string GetTableName(string entityName)
{
2017-09-06 16:37:25 +08:00
var result = this.Context.EntityMaintenance.GetTableName(entityName);
2017-07-06 01:27:05 +08:00
return this.Builder.GetTranslationTableName(result);
}
2017-01-07 21:54:51 +08:00
}
}