using Datamodels.DatabaseModels; using System; using System.Collections.Generic; using System.Threading.Tasks; using Microsoft.Extensions.Logging; using Repositories.Interfaces; using Datamodels.BusinessModels; using Datamodels.SearchModels; using Newtonsoft.Json; using System.Linq; using System.Linq.Expressions; using SearchApi.Exceptions; using Datamodels.Enums; namespace SearchApi.SearchLogic { public class SearchLogic : ISearchLogic { private readonly ILogger _logger; private readonly IFwMariaSearchRepo _searchRepo; private List _tableNames = new List(); private List _joinConditions = new List(); private List _fieldNames = new List(); private List _whereConditions = new List(); private List _sortFields = new List(); public SearchLogic(ILogger logger, IFwMariaSearchRepo searchRepo) { _logger = logger; _searchRepo = searchRepo; } public async Task>> GetAllAddresses() { var result = await _searchRepo.GetAllAddresses(); return result; } public async Task> GetFilteredData(FilterModel filter, long skip = 0, long take = -1) { var result = new DataResult(); result.Data = new ResultModel(); result.Data.SearchModel = filter; var sql = await Task.Run(() => { return AssembleSqlQuery(filter); } ); return result; } // Extract Table private void GetTables(FilterModel filter) { bool hasTableList = filter.TableDescriptions.Count > 0; _tableNames = new List(); foreach(var table in filter.TableDescriptions) { if (hasTableList && string.IsNullOrEmpty(table.TableAlias)) { throw new TableAliasMissingException($"No Alias defined for Table {table.TableName}"); } _tableNames.Add($"{table.TableName} {(string.IsNullOrEmpty(table.TableAlias) ? string.Empty : table.TableAlias)}"); } } // Extract Fieldlist private void GetFields(FilterModel filter) { var tables = filter.TableDescriptions; foreach (var table in tables) { bool hasMultipleFields = table.Fields.Count > 0; foreach (var field in table.Fields) { if (hasMultipleFields && string.IsNullOrEmpty(field.FieldAlias)) { throw new FieldAliasMissingException($"No Alias defined for Field {field.FieldName} in Table {table.TableName}"); } _fieldNames.Add($"{table.TableAlias}.{field.FieldName} {field.FieldAlias}"); } } } // Extract Join Path if more than one table private void GetTableJoinConditions(FilterModel filter) { } // Extract Where Conditions // ToDo: wenn es mehrere Values gibt, werden die generell mit OR verknüpft? Oder nehmen wir lieber AND? private void GetWhereConditions(string tableName, FieldModel field) { if (field.SearchDescriptions.Count > 0) { foreach (var condition in field.SearchDescriptions) { var op = Operator(condition.SearchData.PhraseOperator); if (op != "NOTHING") { var usedField = $"{tableName}.{field.FieldName}{op}{condition.SearchData.Values[0]}"; _whereConditions.Add(usedField); } else { if (condition.SearchData.PhraseOperator == PhraseOperators.Contains) { var usedField = $"{tableName}.{field.FieldName} like '%{condition.SearchData.Values[0]}%'"; _whereConditions.Add(usedField); } if (condition.SearchData.PhraseOperator == PhraseOperators.StartsWith) { var usedField = $"{tableName}.{field.FieldName} like '%{condition.SearchData.Values[0]}'"; _whereConditions.Add(usedField); } if (condition.SearchData.PhraseOperator == PhraseOperators.EndsWith) { var usedField = $"{tableName}.{field.FieldName} like '{condition.SearchData.Values[0]} + %'"; _whereConditions.Add(usedField); } } } } } public string Operator(PhraseOperators ops) { switch (ops) { case PhraseOperators.Equal: return "="; case PhraseOperators.NotEqual: return "!="; case PhraseOperators.GreaterThan: return ">"; case PhraseOperators.GreaterThanOrEqual: return ">="; case PhraseOperators.LowerThan: return "<"; case PhraseOperators.LowerThanOrEqual: return "<="; default: return "NOTHING"; } } // Extract Sort Items private void GetSortFields(FilterModel filter) { } // Assemble SQL Query private string AssembleSqlQuery(FilterModel filter) { GetTables(filter); GetFields(filter); var result = BuildSql(); return result; } //Build SQL String itself private string BuildSql() { var sql = "SELECT "; foreach (var field in _fieldNames) { sql += field.ToUpper(); if (_fieldNames.IndexOf(field) < _fieldNames.Count - 1) sql += ","; } sql += " FROM "; foreach (var table in _tableNames) { sql += table.ToUpper(); if (_tableNames.IndexOf(table) < _tableNames.Count - 1) { sql += ","; } } return sql; } } }