erp-platform/api/src/Erp.Platform.Domain/Queries/SelectQueryManager.cs

820 lines
32 KiB
C#
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

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