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
}
}