820 lines
32 KiB
C#
820 lines
32 KiB
C#
using System;
|
||
using System.Collections.Generic;
|
||
using System.Data;
|
||
using System.Linq;
|
||
using System.Text;
|
||
using System.Text.Json;
|
||
using Erp.Platform.Entities;
|
||
using Erp.Platform.Enums;
|
||
using Erp.Platform.Extensions;
|
||
using Erp.Platform.ListForms;
|
||
using Erp.Platform.Localization;
|
||
using Erp.Platform.OrganizationUnits;
|
||
using Microsoft.Extensions.Localization;
|
||
using Volo.Abp.Domain.Repositories;
|
||
using Volo.Abp.ObjectMapping;
|
||
using Volo.Abp.Settings;
|
||
using Volo.Abp.Users;
|
||
|
||
namespace Erp.Platform.Queries;
|
||
|
||
public interface ISelectQueryManager
|
||
{
|
||
List<SelectField> SelectFields { get; }
|
||
string SelectQuery { get; }
|
||
Dictionary<string, object> SelectQueryParameters { get; }
|
||
string TotalCountQuery { get; }
|
||
string GroupQuery { get; }
|
||
string ChartQuery { get; }
|
||
public string DeleteQuery { get; }
|
||
List<(int Index, string Field, string SelectExpr, string Sort, bool IsExpanded, string GroupInterval)> GroupTuples { get; }
|
||
List<(int Index, string Field, string SelectExpr, string SummaryType)> GroupSummaryTuples { get; }
|
||
List<string> SummaryQueries { get; }
|
||
public bool IsAppliedGridFilter { get; }
|
||
public bool IsAppliedServerFilter { get; }
|
||
void PrepareQueries(ListForm listform,
|
||
List<ListFormField> listFormFields,
|
||
DataSourceTypeEnum dataSourceType,
|
||
List<ListFormCustomization> listFormCustomizations = null,
|
||
QueryParameters queryParams = null);
|
||
}
|
||
|
||
public class SelectField
|
||
{
|
||
public SelectField() { }
|
||
public SelectField(ListFormField item, string baseTableName)
|
||
{
|
||
FieldName = item.FieldName;
|
||
|
||
if (!string.IsNullOrEmpty(item.JoinTableJson))
|
||
JoinOptions = JsonSerializer.Deserialize<JoinTable>(item.JoinTableJson);
|
||
|
||
if (JoinOptions != null && !string.IsNullOrWhiteSpace(JoinOptions.TableName))
|
||
{
|
||
if (!string.IsNullOrEmpty(JoinOptions.FieldNameAlias))
|
||
SelectFieldName = $"\"{JoinOptions.TableName}\".\"{JoinOptions.SelectFieldName}\" AS \"{JoinOptions.FieldNameAlias}\"";
|
||
else
|
||
SelectFieldName = $"\"{JoinOptions.TableName}\".\"{JoinOptions.SelectFieldName}\" AS \"{FieldName}\"";
|
||
|
||
JoinSql = $"{JoinOptions.JoinType} \"{JoinOptions.TableName}\" ON \"{JoinOptions.TableName}\".\"{JoinOptions.JoinFieldName}\" = \"{baseTableName}\".\"{JoinOptions.BaseTableJoinFieldName}\"";
|
||
|
||
// JOIN bolumunde birden fazla condition var ise
|
||
if (!string.IsNullOrEmpty(JoinOptions.JoinFieldName2))
|
||
{
|
||
JoinSql += $" {JoinOptions.JoinCondition2} \"{JoinOptions.JoinFieldName2}\" = {JoinOptions.BaseTableJoinFieldName2_OrValue}";
|
||
}
|
||
|
||
IsJoined = true;
|
||
}
|
||
else
|
||
{
|
||
SelectFieldName = $"\"{baseTableName}\".\"{this.FieldName}\" AS \"{FieldName}\"";
|
||
IsJoined = false;
|
||
}
|
||
}
|
||
|
||
public string FieldName { get; set; } // UserName
|
||
public string SelectFieldName { get; set; } // ListForm.UserName as UserName
|
||
public bool IsJoined { get; set; }
|
||
public JoinTable JoinOptions { get; set; }
|
||
public string JoinSql { get; set; }
|
||
}
|
||
|
||
public class SelectQueryManager : PlatformDomainService, ISelectQueryManager
|
||
{
|
||
private string SelectCommand { get; set; }
|
||
private string TableName { get; set; }
|
||
private string From { get { return SelectCommandType == SelectCommandTypeEnum.Query ? $"({SelectCommand})" : SelectCommand; } }
|
||
private SelectCommandTypeEnum SelectCommandType { get; set; }
|
||
private string KeyFieldName { get; set; }
|
||
private List<string> JoinParts { get; set; }
|
||
private List<string> WhereParts { get; set; }
|
||
private List<string> SortParts { get; set; }
|
||
private DataSourceTypeEnum DataSourceType { get; set; }
|
||
|
||
public List<SelectField> SelectFields { get; private set; }
|
||
public string SelectQuery { get; private set; }
|
||
public Dictionary<string, object> SelectQueryParameters { get; private set; }
|
||
public string TotalCountQuery { get; private set; }
|
||
public string GroupQuery { get; private set; }
|
||
public string DeleteQuery { get; private set; }
|
||
public string ChartQuery { get; private set; }
|
||
public List<(int Index, string Field, string SelectExpr, string Sort, bool IsExpanded, string GroupInterval)> GroupTuples { get; private set; } = [];
|
||
public List<(int Index, string Field, string SelectExpr, string SummaryType)> GroupSummaryTuples { get; private set; } = [];
|
||
public List<string> SummaryQueries { get; private set; }
|
||
public bool IsAppliedGridFilter { get; private set; }
|
||
public bool IsAppliedServerFilter { get; private set; }
|
||
public IPlatformOuRepository OuRepository { get; }
|
||
public IRepository<BranchUsers, Guid> BranchUsersRepository { get; }
|
||
public DefaultValueHelper DefaultValueHelper { get; }
|
||
|
||
public SelectQueryManager(
|
||
ISettingProvider settingProvider,
|
||
IStringLocalizer<PlatformResource> localizer,
|
||
ICurrentUser currentUser,
|
||
IObjectMapper objectMapper,
|
||
IListFormAuthorizationManager authManager,
|
||
IPlatformOuRepository ouRepository,
|
||
IRepository<BranchUsers, Guid> branchUsersRepository,
|
||
DefaultValueHelper defaultValueHelper)
|
||
: base(settingProvider, localizer, currentUser, objectMapper, authManager)
|
||
{
|
||
SelectFields = [];
|
||
JoinParts = [];
|
||
WhereParts = [];
|
||
SortParts = [];
|
||
SummaryQueries = [];
|
||
OuRepository = ouRepository;
|
||
BranchUsersRepository = branchUsersRepository;
|
||
DefaultValueHelper = defaultValueHelper;
|
||
}
|
||
|
||
public void PrepareQueries(ListForm listform,
|
||
List<ListFormField> listFormFields,
|
||
DataSourceTypeEnum dataSourceType,
|
||
List<ListFormCustomization> listFormCustomizations = null,
|
||
QueryParameters queryParams = null)
|
||
{
|
||
if (listform == null)
|
||
{
|
||
return;
|
||
}
|
||
|
||
int take = queryParams?.Take > 0
|
||
? queryParams.Take
|
||
: listform.PageSize > 0
|
||
? listform.PageSize
|
||
: PlatformConsts.GridOptions.RowsPerPage;
|
||
int skip = queryParams?.Skip ?? 0;
|
||
|
||
DataSourceType = dataSourceType;
|
||
SelectCommand = DefaultValueHelper.GetDefaultValue(listform.SelectCommand);
|
||
TableName = listform.TableName.IsNullOrEmpty() ? SelectCommand : listform.TableName;
|
||
KeyFieldName = listform.KeyFieldName;
|
||
SelectCommandType = listform.SelectCommandType;
|
||
var KeyField = new SelectField
|
||
{
|
||
FieldName = KeyFieldName,
|
||
SelectFieldName = $"\"{TableName}\".\"{KeyFieldName}\" AS \"{KeyFieldName}\"",
|
||
IsJoined = false
|
||
};
|
||
|
||
SelectFields.AddRange(GetSelectAndJoinFields(listFormFields));
|
||
if (!SelectFields.Any(a => a.FieldName == KeyField.FieldName))
|
||
{
|
||
SelectFields.Add(KeyField);
|
||
}
|
||
|
||
var joinParts = SelectFields.Where(c => !string.IsNullOrEmpty(c.JoinSql)).Select(c => c.JoinSql).Distinct();
|
||
JoinParts.AddRange(joinParts);
|
||
|
||
List<string> whereFields = GetWhereFields(listform, listFormFields, queryParams);
|
||
WhereParts.AddRange(whereFields);
|
||
|
||
List<string> sortFields = GetSortFields(listform, listFormFields, queryParams?.Sort);
|
||
SortParts.AddRange(sortFields);
|
||
|
||
SelectQuery = GetSelectString();
|
||
SetJoinStringFromCustomizations(listFormCustomizations);
|
||
SelectQuery += GetJoinString();
|
||
SetWhereStringFromCustomizations(listFormCustomizations);
|
||
SelectQuery += GetWhereString();
|
||
SelectQuery += GetSortString();
|
||
|
||
// queryParams null ise grid olusturmak icin gelmistir, paging yapma
|
||
if (queryParams != null && queryParams.Take > 0)
|
||
{
|
||
SelectQuery += GetPagingString(take, skip);
|
||
}
|
||
|
||
TotalCountQuery = GetTotalCountQuery();
|
||
GroupQuery = GetGroupQuery(listFormFields, queryParams);
|
||
DeleteQuery = GetDeleteQuery(queryParams);
|
||
ChartQuery = GetChartQuery(listform, queryParams);
|
||
|
||
#region Total Summary Queries
|
||
if (queryParams != null && !queryParams.TotalSummary.IsNullOrWhiteSpace())
|
||
{
|
||
var items = new List<object>();
|
||
var summaries = queryParams.TotalSummary.Split(PlatformConsts.MultiValueDelimiter);
|
||
for (int i = 0; i < summaries.Length; i++)
|
||
{
|
||
var summary = summaries[i].Split(' ');
|
||
var fieldName = summary[0];
|
||
var summmaryType = summary[1]; // asc, desc
|
||
fieldName = ConvertAliasToFieldName(fieldName, listFormFields);
|
||
if (fieldName == "undefined")
|
||
{
|
||
continue;
|
||
}
|
||
SummaryQueries.Add(GetSummaryQuery(fieldName, summmaryType));
|
||
}
|
||
}
|
||
#endregion
|
||
}
|
||
|
||
private List<SelectField> GetSelectAndJoinFields(List<ListFormField> listFormFields)
|
||
{
|
||
List<SelectField> selectFields = [];
|
||
foreach (var itemField in listFormFields.OrderBy(c => c.JoinTableJson))
|
||
{
|
||
if (!itemField.IsActive.HasValue || !itemField.IsActive.Value || itemField.IsDeleted)
|
||
{
|
||
continue;
|
||
}
|
||
|
||
selectFields.Add(new(itemField, TableName));
|
||
}
|
||
|
||
return selectFields;
|
||
}
|
||
|
||
/// <summary> Sadece join li alanlar icin gercek SqlField bigisini verir
|
||
/// </summary>
|
||
/// <param name="filterName"></param>
|
||
/// <param name="listFormFields"></param>
|
||
/// <returns></returns>
|
||
private string ConvertAliasToFieldName(string filterName, List<ListFormField> listFormFields, string groupInterval = null)
|
||
{
|
||
var format = groupInterval switch
|
||
{
|
||
"year" =>
|
||
DataSourceType == DataSourceTypeEnum.Mssql ? "DATEPART(YEAR, {0})" :
|
||
DataSourceType == DataSourceTypeEnum.Postgresql ? "DATE_PART('YEAR', {0})" : "",
|
||
"quarter" =>
|
||
DataSourceType == DataSourceTypeEnum.Mssql ? "DATEPART(QUARTER, {0})" :
|
||
DataSourceType == DataSourceTypeEnum.Postgresql ? "DATE_PART('QUARTER', {0})" : "",
|
||
"month" =>
|
||
DataSourceType == DataSourceTypeEnum.Mssql ? "DATEPART(MONTH, {0})" :
|
||
DataSourceType == DataSourceTypeEnum.Postgresql ? "DATE_PART('MONTH', {0})" : "",
|
||
"day" =>
|
||
DataSourceType == DataSourceTypeEnum.Mssql ? "DATEPART(DAY, {0})" :
|
||
DataSourceType == DataSourceTypeEnum.Postgresql ? "DATE_PART('DAY', {0})" : "",
|
||
"dayOfWeek" =>
|
||
DataSourceType == DataSourceTypeEnum.Mssql ? "DATEPART(DW, {0})" :
|
||
DataSourceType == DataSourceTypeEnum.Postgresql ? "DATE_PART('DOW', {0})" : "",
|
||
_ => "{0}"
|
||
};
|
||
|
||
var field = listFormFields.FirstOrDefault(a => a.FieldName == filterName && !string.IsNullOrWhiteSpace(a.JoinTableJson));
|
||
if (field is not null)
|
||
{
|
||
var jt = JsonSerializer.Deserialize<JoinTable>(field.JoinTableJson);
|
||
if (!jt.TableName.IsNullOrWhiteSpace())
|
||
{
|
||
return string.Format(format, $"\"{jt.TableName}\".\"{jt.SelectFieldName}\"");
|
||
}
|
||
}
|
||
|
||
return string.Format(format, $"\"{TableName}\".\"{filterName}\"");
|
||
}
|
||
|
||
private string GetSelectString()
|
||
{
|
||
return $"SELECT {string.Join(',', SelectFields.Select(c => $"{c.SelectFieldName}"))} FROM \"{From}\" AS \"{TableName}\"";
|
||
}
|
||
|
||
private string SetJoinStringFromCustomizations(List<ListFormCustomization> listFormCustomizations)
|
||
{
|
||
if (listFormCustomizations.IsNullOrEmpty())
|
||
{
|
||
return string.Empty;
|
||
}
|
||
|
||
var customizations = listFormCustomizations
|
||
.Where(a => a.CustomizationType == ListFormCustomizationTypeEnum.ServerJoin)
|
||
.Select(a => a.CustomizationData)
|
||
.ToList();
|
||
|
||
JoinParts.AddRange(customizations);
|
||
|
||
return string.Join(' ', customizations);
|
||
}
|
||
|
||
/// <summary>
|
||
/// WhereParts icerisine ListFormCustomization tanimindan gelen filtreleri ekler
|
||
/// </summary>
|
||
/// <param name="listFormCustomization"></param>
|
||
private void SetWhereStringFromCustomizations(List<ListFormCustomization> listFormCustomizations)
|
||
{
|
||
if (listFormCustomizations.IsNullOrEmpty())
|
||
{
|
||
return;
|
||
}
|
||
|
||
var customizations = listFormCustomizations
|
||
.Where(a => a.CustomizationType == ListFormCustomizationTypeEnum.ServerWhere)
|
||
.Select(a => a.CustomizationData)
|
||
.ToList();
|
||
|
||
foreach (var item in customizations)
|
||
{
|
||
if (WhereParts.Any())
|
||
{
|
||
WhereParts.Add("AND");
|
||
}
|
||
|
||
WhereParts.Add(DefaultValueHelper.GetDefaultValue(item));
|
||
IsAppliedServerFilter = true;
|
||
}
|
||
}
|
||
|
||
private List<string> GetWhereFields(ListForm listform, List<ListFormField> listFormFields, QueryParameters queryParams = null)
|
||
{
|
||
var whereParts = new List<string>();
|
||
|
||
if (!string.IsNullOrEmpty(queryParams?.Filter))
|
||
{
|
||
var filters = queryParams.Filter.Replace('[', '(')
|
||
.Replace(']', ')')
|
||
.Replace("\"\"", "''") // (empty string) "" -> ''
|
||
.Replace("\"", "")
|
||
.Replace(",\"or\",", " or ")
|
||
.Replace(",\"and\",", " and ");
|
||
|
||
var filterItems = filters.Split(",").ToList();
|
||
if (filterItems
|
||
.Where(a => !a.Contains('!') && a != "and" && a != "or")
|
||
.ToList().Count % 3 == 0) //Eğer gelen veri 'and', 'or' veya '!' dışında kalan item adedi 3 ün katıysa
|
||
{
|
||
SelectQueryParameters = new Dictionary<string, object>();
|
||
|
||
var forDeger = 3;
|
||
|
||
for (int i = 0; i < filterItems.Count; i += forDeger)
|
||
{
|
||
if (filterItems[i].Contains('!'))
|
||
{
|
||
forDeger = 1;
|
||
|
||
whereParts.Add(filterItems[i].Replace("!", "NOT"));
|
||
IsAppliedGridFilter = true;
|
||
}
|
||
else if (filterItems[i] == "and" || filterItems[i] == "or")
|
||
{
|
||
forDeger = 1;
|
||
|
||
whereParts.Add(filterItems[i]);
|
||
IsAppliedGridFilter = true;
|
||
}
|
||
else
|
||
{
|
||
forDeger = 3;
|
||
|
||
var fieldName = filterItems[i];
|
||
var op = filterItems[i + 1];
|
||
var fieldValue = filterItems[i + 2];
|
||
|
||
var filter = ParseFilter(fieldName, op, fieldValue, listFormFields, i);
|
||
|
||
if (filter != "")
|
||
{
|
||
whereParts.Add(filter);
|
||
IsAppliedGridFilter = true;
|
||
}
|
||
}
|
||
}
|
||
}
|
||
}
|
||
|
||
if (!listform.DefaultFilter.IsNullOrWhiteSpace())
|
||
{
|
||
if (whereParts.Any())
|
||
{
|
||
whereParts.Add("AND");
|
||
}
|
||
|
||
whereParts.Add(DefaultValueHelper.GetDefaultValue(listform.DefaultFilter));
|
||
IsAppliedServerFilter = true;
|
||
}
|
||
|
||
if (PlatformConsts.IsMultiTenant && listform.IsTenant)
|
||
{
|
||
if (whereParts.Any())
|
||
{
|
||
whereParts.Add("AND");
|
||
}
|
||
|
||
if (CurrentTenant.IsAvailable)
|
||
{
|
||
whereParts.Add($"\"TenantId\" = '{CurrentTenant.Id}'");
|
||
}
|
||
else
|
||
{
|
||
whereParts.Add($"\"TenantId\" IS NULL");
|
||
}
|
||
}
|
||
|
||
if (listform.IsBranch)
|
||
{
|
||
if (whereParts.Any())
|
||
{
|
||
whereParts.Add("AND");
|
||
}
|
||
|
||
var ids = BranchUsersRepository.GetListAsync((a) => a.UserId == CurrentUser.Id.Value).Result;
|
||
if (ids.Count > 0)
|
||
{
|
||
whereParts.Add($"\"BranchId\" IN ({string.Join(",", ids.Select(a => $"'{a.BranchId}'"))})");
|
||
}
|
||
else
|
||
{
|
||
whereParts.Add($"\"BranchId\" = '{Guid.Empty}'");
|
||
}
|
||
}
|
||
|
||
if (listform.IsOrganizationUnit)
|
||
{
|
||
if (whereParts.Any())
|
||
{
|
||
whereParts.Add("AND");
|
||
}
|
||
|
||
var ids = OuRepository.GetOrganizationUnitIdsWithChildren(CurrentUser.Id.Value).Result;
|
||
if (ids.Count > 0)
|
||
{
|
||
whereParts.Add($"\"OrganizationUnitId\" IN ({string.Join(",", ids.Select(a => $"'{a}'"))})");
|
||
}
|
||
else
|
||
{
|
||
whereParts.Add($"\"OrganizationUnitId\" = '{Guid.Empty}'");
|
||
}
|
||
}
|
||
|
||
if (!whereParts.Any())
|
||
{
|
||
whereParts.Add("1 = 1");
|
||
}
|
||
|
||
return whereParts;
|
||
}
|
||
|
||
/// <summary> FieldName operator Id seklinde olan filtreleri ayirir
|
||
/// </summary>
|
||
/// <param name="filter"></param>
|
||
/// <returns></returns>
|
||
private string ParseFilter(
|
||
string fieldName,
|
||
string op,
|
||
string fieldValue,
|
||
List<ListFormField> listFormFields,
|
||
int customKey)
|
||
{
|
||
string sqlPart = string.Empty;
|
||
if (string.IsNullOrWhiteSpace(fieldName) || string.IsNullOrWhiteSpace(op))
|
||
{
|
||
return sqlPart;
|
||
}
|
||
|
||
var fieldDbType = DbType.String;
|
||
var fieldFilter = fieldName.Split('.');
|
||
var filterFieldName = fieldFilter.First().RemoveParentheses();
|
||
var filterGroupInterval = fieldFilter.Length > 1 ? fieldFilter.Last().ToLower() : null;
|
||
var filterParamKey = $"@{filterFieldName}{customKey}";
|
||
var filterParamKeyLower = filterParamKey;
|
||
var filterOperator = op.RemoveParentheses();
|
||
var filterValue = fieldValue.RemoveParentheses();
|
||
|
||
var listFormField = listFormFields.FirstOrDefault(c => c.FieldName == filterFieldName);
|
||
if (listFormField == null)
|
||
{
|
||
fieldDbType = ListFormManager.InferDbTypeFromString(filterValue);
|
||
}
|
||
else
|
||
{
|
||
// filterGroupInterval sayı olduğu için (örn OrderDate.Month), eğer bu gelirse sayıya parse ediyoruz,
|
||
// diğer durumlarda field tipine parse ediyoruz
|
||
fieldDbType = filterGroupInterval switch
|
||
{
|
||
"year" or "quarter" or "month" or "day" or "dayOfWeek" => DbType.Int32,
|
||
_ => listFormField.SourceDbType
|
||
};
|
||
}
|
||
|
||
if (filterValue == "null")
|
||
{
|
||
if (filterOperator == "=") filterOperator = "isblank";
|
||
if (filterOperator == "<>") filterOperator = "isnotblank";
|
||
}
|
||
var lastCharacters = fieldValue.Replace(filterValue, string.Empty); // Sadece parantezleri almak için
|
||
|
||
var filterSqlFieldName = ConvertAliasToFieldName(filterFieldName, listFormFields, filterGroupInterval);
|
||
if (filterOperator == "=" && DataSourceType == DataSourceTypeEnum.Postgresql && (
|
||
fieldDbType == DbType.String ||
|
||
fieldDbType == DbType.AnsiString))
|
||
{
|
||
filterSqlFieldName = $"lower({filterSqlFieldName})";
|
||
filterParamKeyLower = $"lower({filterParamKeyLower})";
|
||
filterValue = filterValue.Replace('I', 'ı');
|
||
}
|
||
filterSqlFieldName = fieldFilter.First().Replace(filterFieldName, filterSqlFieldName);
|
||
|
||
var sqlOperator = "";
|
||
string formatSql = "{0} {1} {2}";
|
||
|
||
string concatOp =
|
||
DataSourceType == DataSourceTypeEnum.Mssql ? "+" :
|
||
DataSourceType == DataSourceTypeEnum.Postgresql ? "||"
|
||
: "";
|
||
string likeOp =
|
||
DataSourceType == DataSourceTypeEnum.Mssql ? "LIKE" :
|
||
DataSourceType == DataSourceTypeEnum.Postgresql ? "ILIKE"
|
||
: "";
|
||
|
||
if (filterOperator == "=") sqlOperator = "=";
|
||
else if (filterOperator == "<>") sqlOperator = "<>";
|
||
else if (filterOperator == "<") sqlOperator = "<";
|
||
else if (filterOperator == "<=") sqlOperator = "<=";
|
||
else if (filterOperator == ">") sqlOperator = ">";
|
||
else if (filterOperator == ">=") sqlOperator = ">=";
|
||
else if (filterOperator == "contains") formatSql = "{0} " + likeOp + " '%' " + concatOp + " {2} " + concatOp + " '%'";
|
||
else if (filterOperator == "notcontains") formatSql = "{0} NOT " + likeOp + " '%' " + concatOp + " {2} " + concatOp + " '%'";
|
||
else if (filterOperator == "startswith") formatSql = "{0} " + likeOp + " {2} " + concatOp + " '%'";
|
||
else if (filterOperator == "endswith") formatSql = "{0} " + likeOp + " '%' " + concatOp + " {2}";
|
||
else if (filterOperator == "isblank") formatSql = "{0} IS NULL";
|
||
else if (filterOperator == "isnotblank") formatSql = "{0} IS NOT NULL";
|
||
|
||
sqlPart = string.Format(formatSql, filterSqlFieldName, sqlOperator, filterParamKeyLower);
|
||
if (lastCharacters.Any())
|
||
{
|
||
sqlPart += lastCharacters;
|
||
}
|
||
|
||
if (formatSql.Contains("{2}"))
|
||
{
|
||
SelectQueryParameters.Add(filterParamKey, QueryHelper.GetFormattedValue(fieldDbType, filterValue));
|
||
}
|
||
return sqlPart;
|
||
}
|
||
|
||
private List<string> GetSortFields(ListForm listform,
|
||
List<ListFormField> listFormFields,
|
||
string sort = null)
|
||
{
|
||
var sortFields = new List<string>();
|
||
if (listform.SortMode == PlatformConsts.GridOptions.SortModeNone)
|
||
{
|
||
sortFields.Add("CURRENT_TIMESTAMP");
|
||
return SortParts;
|
||
}
|
||
|
||
// kullanicinin islemi ile siralama yapiliyor ise
|
||
if (!string.IsNullOrEmpty(sort))
|
||
{
|
||
var sorts = sort.Split(PlatformConsts.MultiValueDelimiter, StringSplitOptions.RemoveEmptyEntries);
|
||
for (int i = 0; i < sorts.Length; i++)
|
||
{
|
||
// sorts[i] su sekilde gelir: "AlanIsmi desc"
|
||
var sortElem = sorts[i].Trim().Split(' ', StringSplitOptions.RemoveEmptyEntries);
|
||
sortElem[0] = $"\"{sortElem[0].Trim()}\""; // Grid uzerinden gelen siralama istegi icin alan ismini koseli parantes icerisine al (Anahtar isimdeki alanlar icin Bug olusmasini onler, ornegin Key isminde bir alana ait siralama istegi gelebilir)
|
||
sortFields.Add(sortElem.JoinAsString(" ")); // Gelen istegi su sekle donusturur: [AlanIsmi] desc
|
||
}
|
||
}
|
||
else // ekran tanimi ile siralama yapiliyor ise
|
||
{
|
||
foreach (var itemField in listFormFields.Where(c => c.SortIndex.HasValue && c.SortIndex > 0).OrderBy(c => c.SortIndex))
|
||
{
|
||
sortFields.Add($"\"{itemField.FieldName}\" {itemField.SortDirection}");
|
||
}
|
||
}
|
||
|
||
// Varsayilan olarak siramalama yok ise siralamayi etkilemeyecek bir alan ekle (paging islemlerinde Order By bolumu istenildigi icin eklendi)
|
||
if (sortFields.Count == 0)
|
||
{
|
||
sortFields.Add("CURRENT_TIMESTAMP");
|
||
}
|
||
|
||
return sortFields;
|
||
}
|
||
|
||
private string GetJoinString()
|
||
{
|
||
return " " + string.Join(' ', JoinParts);
|
||
}
|
||
|
||
private string GetWhereString()
|
||
{
|
||
if (WhereParts.Count == 0)
|
||
return "";
|
||
|
||
return " WHERE " + string.Join(' ', WhereParts);
|
||
}
|
||
|
||
private string GetSortString()
|
||
{
|
||
return " ORDER BY " + string.Join(',', SortParts);
|
||
}
|
||
|
||
private string GetPagingString(int take, int? skip = 0)
|
||
{
|
||
return $" OFFSET {skip} ROWS FETCH NEXT {take} ROWS ONLY";
|
||
}
|
||
|
||
private string GetTotalCountQuery()
|
||
{
|
||
var sql = $"SELECT COUNT(\"{TableName}\".\"{KeyFieldName}\") FROM \"{From}\" AS \"{TableName}\"";
|
||
sql += GetJoinString();
|
||
sql += GetWhereString();
|
||
|
||
return sql;
|
||
}
|
||
|
||
private string GetSummaryQuery(string fieldName, string summaryType)
|
||
{
|
||
var sql = $"SELECT {summaryType}({fieldName}) FROM \"{From}\" AS \"{TableName}\"";
|
||
sql += GetJoinString();
|
||
sql += GetWhereString();
|
||
|
||
return sql;
|
||
}
|
||
|
||
private string GetGroupQuery(List<ListFormField> listFormFields, QueryParameters queryParams = null)
|
||
{
|
||
if (queryParams == null || queryParams.Group.IsNullOrWhiteSpace())
|
||
{
|
||
return null;
|
||
}
|
||
|
||
var validSummaryTypes = new string[] { "sum", "avg", "min", "max", "count" };
|
||
var validSortTypes = new string[] { "asc", "desc" };
|
||
var validGroupIntervals = new string[] { "day", "dayOfWeek", "month", "quarter", "year" };
|
||
|
||
// queryParams.Group veri yapisi:
|
||
// AlanIsmi desc isExpanded groupInterval
|
||
// Örn: group:IsEnabled asc false|TextDate asc false year|TextDate asc false month|CultureName asc false
|
||
// yapilan grup islemlerinde her bir gruplama icin bir ya da birden fazla istek geliyor.
|
||
var groups = queryParams.Group?.Split(PlatformConsts.MultiValueDelimiter);
|
||
foreach (var (group, i) in groups.Select((a, i) => (a, i)))
|
||
{
|
||
var items = group.Trim().Split(' ');
|
||
if (!items.Length.IsBetween(2, 4))
|
||
{
|
||
continue;
|
||
}
|
||
var field = items[0];
|
||
var sort = validSortTypes.Contains(items[1]) ? items[1] : "asc";
|
||
var isExpanded = items.Length > 2 && items[2] == "true";
|
||
var groupInterval = items.Length > 3 ? validGroupIntervals.Contains(items[3]) ? items[3] : null : null;
|
||
var fieldName = ConvertAliasToFieldName(field, listFormFields, groupInterval);// Alias li bir alan ise gercek alani bul
|
||
GroupTuples.Add((i, fieldName, $"Group_{i}", sort, isExpanded, groupInterval));
|
||
}
|
||
|
||
// gruplanan bir alan icin grup satirinda summary bilgisinin gorunmesi icin gerekli veri yapisidir,
|
||
// grup sorgusu ile birlikte calistirilir.
|
||
// Gelen veri yapisi: FieldName SummaryType|FieldName SummaryType
|
||
// Örn: groupSummary:TextCount sum|TextCount count
|
||
// Not: Gelen sira ile ayni sekilde geri dondurulmelidir! GroupSummaryItems bunun icin kullaniliyor
|
||
var groupSummaries = queryParams.GroupSummary?.Split(PlatformConsts.MultiValueDelimiter);
|
||
if (!groupSummaries.IsNullOrEmpty())
|
||
{
|
||
foreach (var (groupSummary, i) in groupSummaries.Select((a, i) => (a, i)))
|
||
{
|
||
var gs = groupSummary.Trim().Split(' ');
|
||
if (gs.Length != 2)
|
||
{
|
||
continue;
|
||
}
|
||
var field = gs[0].ToString();
|
||
var summaryType = gs[1].ToString();
|
||
if (!validSummaryTypes.Contains(summaryType))
|
||
{
|
||
continue;
|
||
}
|
||
var fieldName = ConvertAliasToFieldName(field, listFormFields);// Alias li bir alan ise gercek alani bul
|
||
GroupSummaryTuples.Add((i, fieldName, $"Summary_{i}", summaryType));
|
||
}
|
||
}
|
||
|
||
var sqlSub = new StringBuilder();
|
||
sqlSub.Append("SELECT ");
|
||
sqlSub.Append(string.Join(',', GroupTuples.Select((a) => $"{a.Field} AS \"{a.SelectExpr}\"")));
|
||
sqlSub.Append(string.Join(',', GroupSummaryTuples.Select((a) => $",{a.SummaryType}({a.Field}) AS \"{a.SelectExpr}\"")));
|
||
sqlSub.Append(",COUNT(1) AS \"Summary_Count\"");
|
||
sqlSub.Append($" FROM \"{From}\" AS \"{TableName}\"");
|
||
sqlSub.Append(GetJoinString());
|
||
sqlSub.Append(GetWhereString());
|
||
sqlSub.Append($" GROUP BY {string.Join(',', GroupTuples.Select((a) => a.Field))}");
|
||
sqlSub.Append($" ORDER BY {string.Join(',', GroupTuples.Select((a, i) => $"\"{a.SelectExpr}\" {a.Sort}"))}");
|
||
if (queryParams.Take > 0)
|
||
{
|
||
sqlSub.Append(GetPagingString(queryParams.Take, queryParams.Skip));
|
||
}
|
||
else
|
||
{
|
||
sqlSub.Append(" OFFSET 0 ROWS");
|
||
}
|
||
|
||
var sqlMain = new StringBuilder();
|
||
sqlMain.Append("SELECT ");
|
||
sqlMain.Append(string.Join(',', GroupTuples.Select((a) => $"\"{a.SelectExpr}\"")));
|
||
foreach (var item in GroupTuples.Select((groupTuple, i) => (groupTuple, i)))
|
||
{
|
||
var prevItems = GroupTuples.Take(item.i + 1);
|
||
if (prevItems.Count() == 1)
|
||
{
|
||
sqlMain.Append($",\"{item.groupTuple.SelectExpr}\" AS \"{item.groupTuple.SelectExpr}_Key\"");
|
||
}
|
||
else
|
||
{
|
||
sqlMain.Append($",CONCAT({string.Join(",'" + PlatformConsts.MultiValueDelimiter + "',", prevItems.Select(a => $"\"{a.SelectExpr}\""))}) AS \"{item.groupTuple.SelectExpr}_Key\"");
|
||
}
|
||
}
|
||
sqlMain.Append(", \"Summary_Count\"");
|
||
foreach (var summaryTuple in GroupSummaryTuples)
|
||
{
|
||
var sType = summaryTuple.SummaryType == "count" ? "sum" : summaryTuple.SummaryType;
|
||
var summarySelect = $"{sType}(\"{summaryTuple.SelectExpr}\")";
|
||
sqlMain.Append($",{summarySelect} OVER() AS \"{summaryTuple.SelectExpr}_All\"");
|
||
var partitionBy = new List<string>();
|
||
foreach (var groupTuple in GroupTuples)
|
||
{
|
||
partitionBy.Add($"\"{groupTuple.SelectExpr}\"");
|
||
sqlMain.Append($",{summarySelect} OVER(PARTITION BY {string.Join(',', partitionBy)}) AS \"{summaryTuple.SelectExpr}_{groupTuple.Index}\"");
|
||
}
|
||
partitionBy.Clear();
|
||
}
|
||
// foreach (var summaryTuple in GroupSummaryTuples)
|
||
// {
|
||
// var summarySelect = $"{summaryTuple.SummaryType}({summaryTuple.SelectExpr})";
|
||
// sqlMain.Append($",{summarySelect} OVER() AS {summaryTuple.SelectExpr}_All");
|
||
|
||
// foreach (var item in GroupTuples.Select((tuple, i) => (tuple, i)))
|
||
// {
|
||
// var groupTuple = item.tuple;
|
||
// if (item.i == 0)
|
||
// {
|
||
// sqlMain.Append($",{summaryTuple.SelectExpr} AS {summaryTuple.SelectExpr}_{groupTuple.Index}");
|
||
// }
|
||
// else
|
||
// {
|
||
// sqlMain.Append($",{summarySelect} OVER(PARTITION BY {groupTuple.SelectExpr}) AS {summaryTuple.SelectExpr}_{groupTuple.Index}");
|
||
// }
|
||
// }
|
||
// }
|
||
sqlMain.Append($" FROM ({sqlSub}) AS \"Sub\"");
|
||
sqlMain.Append($" ORDER BY {string.Join(',', GroupTuples.Select((a, i) => $"\"{a.SelectExpr}\" {a.Sort}"))}");
|
||
|
||
return sqlMain.ToString();
|
||
}
|
||
|
||
private string GetDeleteQuery(QueryParameters queryParams = null)
|
||
{
|
||
if (queryParams == null || queryParams.CreateDeleteQuery == false)
|
||
return null;
|
||
|
||
return $"DELETE \"{TableName}\" FROM {SelectCommand} AS \"{TableName}\" {GetWhereString()}";
|
||
}
|
||
|
||
public string GetChartQuery(ListForm listform, QueryParameters queryParams = null)
|
||
{
|
||
if (listform == null || string.IsNullOrWhiteSpace(listform.SeriesJson) || queryParams == null)
|
||
return null;
|
||
|
||
var seriesList = JsonSerializer.Deserialize<List<ChartSeries>>(listform.SeriesJson);
|
||
|
||
if (seriesList == null || seriesList.Count == 0)
|
||
return null;
|
||
|
||
// ArgumentField listesi
|
||
var argumentFields = seriesList.Select(s => s.ArgumentField).Distinct().ToList();
|
||
|
||
// ArgumentField ifadesini oluştur
|
||
string argumentExpression;
|
||
if (argumentFields.Count == 1)
|
||
{
|
||
// Tek ArgumentField
|
||
argumentExpression = $"[{argumentFields.First()}]";
|
||
}
|
||
else
|
||
{
|
||
// Birden fazla → '|' ile birleştir
|
||
argumentExpression = string.Join(" + '|' + ", argumentFields.Select(f => $"[{f}]"));
|
||
}
|
||
|
||
// Select sütunlarını oluştur
|
||
var selectParts = new List<string> { $"{argumentExpression} AS ArgumentField" };
|
||
foreach (var series in seriesList)
|
||
{
|
||
string sqlFunc = series.SummaryType.ToUpper() switch
|
||
{
|
||
"COUNT" => $"COUNT([{series.ValueField}])",
|
||
"SUM" => $"SUM([{series.ValueField}])",
|
||
"AVG" => $"AVG([{series.ValueField}])",
|
||
"MIN" => $"MIN([{series.ValueField}])",
|
||
"MAX" => $"MAX([{series.ValueField}])",
|
||
_ => throw new NotSupportedException($"Unsupported SummaryType: {series.SummaryType}")
|
||
};
|
||
|
||
selectParts.Add($"{sqlFunc} AS [{series.Name}]");
|
||
}
|
||
|
||
// SQL cümlesi
|
||
var sql = $@"
|
||
SELECT {string.Join(", ", selectParts)}
|
||
FROM [{listform.SelectCommand}]
|
||
{GetWhereString()}
|
||
GROUP BY {argumentExpression}";
|
||
|
||
return sql;
|
||
}
|
||
}
|