BusinessMgr 3.0.1.6

This commit is contained in:
Andy Howard
2025-05-05 16:00:50 +01:00
parent f4f50fc258
commit 2559b9dae3
22 changed files with 92 additions and 81 deletions
+60 -54
View File
@@ -15,6 +15,7 @@ namespace Sarand.Net.Standard.Base.Dbas
LeftOuter,
RightOuter,
FullOuter,
OuterApply,
Cross,
}
public enum DbOrderByNullMode
@@ -87,6 +88,7 @@ namespace Sarand.Net.Standard.Base.Dbas
case DbJoinType.LeftOuter: return (DbGlobalDbms.Type == DbmsType.Sage ? "LEFT JOIN" : "LEFT OUTER JOIN");
case DbJoinType.RightOuter: return (DbGlobalDbms.Type == DbmsType.Sage ? "RIGHT JOIN" : "RIGHT OUTER JOIN");
case DbJoinType.FullOuter: return (DbGlobalDbms.Type == DbmsType.Sage ? "FULL JOIN" : "FULL OUTER JOIN");
case DbJoinType.OuterApply: return ("OUTER APPLY");
case DbJoinType.Cross: return "CROSS JOIN";
case DbJoinType.Inner:
default: return "INNER JOIN";
@@ -134,10 +136,11 @@ namespace Sarand.Net.Standard.Base.Dbas
foreach (var subJoin in SubJoins)
{
// Add another bracket in front of the table:
joinTable = "(" + joinTable;
joinTable = $"({joinTable}";
// Add the sub join.
subJoinData += subJoin.BuildJoin("") + ")";
subJoinData += $"{subJoin.BuildJoin("")})";
}
//---------------------------------------------------------------
// Build this join's list of filter conditions.
// Take care not to add too many embedded brackets - confuses Access etc.
// [Original version: lFilter.Concat (" AND ", "(", ")", true, true)].
@@ -149,36 +152,39 @@ namespace Sarand.Net.Standard.Base.Dbas
if (filterClause.IsEmpty()) continue;
// Embed the clause in brackets if it contains at least one 'OR' operator.
if (filterClause.IndexOf(" OR ", StringComparison.OrdinalIgnoreCase) >= 0)
filterClause = "(" + filterClause + ")";
filterClause = $"({filterClause})";
filter += (!filter.IsEmpty() ? " AND " : "") + filterClause;
}
// Surround the entire filter in brackets (if not already done).
if (filter.FindMatchingBrace(0) != filter.Length)
filter = "(" + filter + ")";
if (!StringUtil.IsBlank(filter) && filter.FindMatchingBrace(0) != filter.Length)
filter = $"({filter})";
//---------------------------------------------------------------
// Build the join.
if (enclosedJoin.IsEmpty() && subJoinData.IsEmpty())
{
//-----------------------------------------------------------
// Simple join syntax.
// <Join-Type> <Join-Table> ON <Join-Filter>
joinData = joinType + " " + joinTable + " ON " + filter;
//-----------------------------------------------------------
joinData = $"{joinType} {joinTable}";
}
else
{
//-----------------------------------------------------------
// More complex join syntax - nested joins.
// <Join-Type> (<Join-Table> <NestedJoin>) ON <Join-Filter>
//-----------------------------------------------------------
// Bracket the table, enclosing any enclosed or subordinate joins.
joinData = joinType + " (" + joinTable;
joinData = $"{joinType} ({joinTable}";
if (!subJoinData.IsEmpty())
joinData += " " + subJoinData;
joinData += $" {subJoinData}";
if (!enclosedJoin.IsEmpty())
joinData += " " + enclosedJoin;
joinData += ") ON " + filter;
//-----------------------------------------------------------
joinData += $" {enclosedJoin}";
joinData += ")";
}
//---------------------------------------------------------------
// Add the join filter.
if (Type != DbJoinType.OuterApply)
joinData += $" ON {filter}";
else if (!StringUtil.IsBlank(filter))
SaLogger.Warn($"{SysUtil.Fn} Filter found on 'Outer Apply' join: '{filter}'.");
//---------------------------------------------------------------
return joinData;
}
@@ -187,13 +193,13 @@ namespace Sarand.Net.Standard.Base.Dbas
public void Dump()
{
SaLogger.Debug($"{SysUtil.Fn}");
SaLogger.Debug("\tType = " + GetJoinType(Type));
SaLogger.Debug("\tTable = " + Table.Concat(" AS "));
SaLogger.Debug("\tFilters = " + Filters.Concat("", "\t\t", "\n"));
SaLogger.Debug($"\tType = {GetJoinType(Type)}");
SaLogger.Debug($"\tTable = {Table.Concat(" AS ")}");
SaLogger.Debug($"\tFilters = {Filters.Concat("", "\t\t", "\n")}");
if (SubJoins.Count > 0)
{
}
SaLogger.Debug("\tJoin = " + BuildJoin(""));
SaLogger.Debug($"\tJoin = {BuildJoin("")}");
}
//-------------------------------------------------------------------
@@ -229,8 +235,8 @@ namespace Sarand.Net.Standard.Base.Dbas
foreach (var join in joins)
{
// Add the next join in the list.
if (++joinCount > 1 && !joinData.IsEmpty()) joinData = "(" + joinData + ")";
joinData = joinData + " " + join.BuildJoin("");
if (++joinCount > 1 && !joinData.IsEmpty()) joinData = $"({joinData})";
joinData = $"{joinData} {join.BuildJoin("")}";
joinData.Trim();
}
}
@@ -247,7 +253,7 @@ namespace Sarand.Net.Standard.Base.Dbas
joinData = join.BuildJoin(joinData);
joinData.Trim();
}
joinData = primaryTable + " " + joinData;
joinData = $"{primaryTable} {joinData}";
}
}
return joinData;
@@ -342,14 +348,14 @@ namespace Sarand.Net.Standard.Base.Dbas
if (!rawValue.IsEmpty() || !ignoreBlanks)
{
if (stringData)
value = "'" + FormatForCondition(value) + "'";
value = $"'{FormatForCondition(value)}'";
else value.Trim(); // Non string data can be cleansed.
values.Add(value);
}
}
values.RemoveDuplicatesCI();
if (values.Count > 0)
result = "(" + values.Concat(",") + ")";
result = $"({values.Concat(",")})";
return result;
}
@@ -412,7 +418,7 @@ namespace Sarand.Net.Standard.Base.Dbas
{
// Surround the expression in brackets if not present.
if (expression.Left(1) != "(")
expression = "(" + expression + ")";
expression = $"({expression})";
// Logic to include or exclude null values.
if (excludeNulls)
{
@@ -443,7 +449,7 @@ namespace Sarand.Net.Standard.Base.Dbas
{
// Surround the expression in brackets if not present.
if (expression.Left(1) != "(")
expression = "(" + expression + ")";
expression = $"({expression})";
// Logic to promote null values to start of sequence or demote null values to the end of the sequence.
String nullsClause = String.Empty;
if (nullMode == DbOrderByNullMode.PromoteNulls || nullMode == DbOrderByNullMode.DatePromoteNulls)
@@ -452,15 +458,15 @@ namespace Sarand.Net.Standard.Base.Dbas
{
// Treat NULLs before other values.
List<String> nullsFilters = new List<String>();
nullsFilters.Add(expression + " IS NULL");
nullsFilters.Add($"{expression} IS NULL");
if (treatZeroAsNull)
nullsFilters.Add(expression + "=0");
nullsFilters.Add($"{expression}=0");
if (nullMode == DbOrderByNullMode.DatePromoteNulls)
nullsFilters.Add(expression + "<=" + FormatDateForCondition(NullDate));
nullsClause = "(CASE WHEN " + nullsFilters.Concat(" OR ", "(", ")") + " THEN 0 ELSE 1 END)";
nullsFilters.Add($"{expression}<={FormatDateForCondition(NullDate)}");
nullsClause = $"(CASE WHEN {nullsFilters.Concat(" OR ", "(", ")")} THEN 0 ELSE 1 END)";
}
else
nullsClause = expression + " IS NULL";
nullsClause = $"{expression} IS NULL";
}
else if (nullMode == DbOrderByNullMode.DemoteNulls || nullMode == DbOrderByNullMode.DateDemoteNulls)
{
@@ -472,15 +478,15 @@ namespace Sarand.Net.Standard.Base.Dbas
if (treatZeroAsNull)
nullsFilters.Add(expression + "=0");
if (nullMode == DbOrderByNullMode.DateDemoteNulls)
nullsFilters.Add(expression + "<=" + FormatDateForCondition(NullDate));
nullsClause = "(CASE WHEN " + nullsFilters.Concat(" OR ", "(", ")") + " THEN 1 ELSE 0 END)";
nullsFilters.Add($"{expression}<={FormatDateForCondition(NullDate)}");
nullsClause = $"(CASE WHEN {nullsFilters.Concat(" OR ", "(", ")")} THEN 1 ELSE 0 END)";
}
else
nullsClause = expression + " IS NOT NULL";
nullsClause = $"{expression} IS NOT NULL";
}
if (!nullsClause.IsEmpty()) orderBy.Add(nullsClause);
// Main clause for this expression.
orderBy.Add(expression + " " + (ascending ? "ASC" : "DESC"));
orderBy.Add($"{expression} {(ascending ? "ASC" : "DESC")}");
}
return orderBy;
}
@@ -617,7 +623,7 @@ namespace Sarand.Net.Standard.Base.Dbas
}
if (interval.IsEmpty()) return "''";
}
return "DateDiff(" + interval + "," + column1 + "," + column2 + ")";
return $"DateDiff({interval},{column1},{column2})";
}
//-------------------------------------------------------------------
@@ -643,7 +649,7 @@ namespace Sarand.Net.Standard.Base.Dbas
#if DEBUG
else
{
SaLogger.Debug("BuildBitMappedFilter - Invalid bit (" + bit + ").");
SaLogger.Debug($"BuildBitMappedFilter - Invalid bit ({bit}).");
}
#endif
}
@@ -662,7 +668,7 @@ namespace Sarand.Net.Standard.Base.Dbas
if (!clause.IsEmpty())
{
if (DbGlobalDbms.Type == DbmsType.MsSql)
clause = "(" + clause + " <> 0)";
clause = $"({clause} <> 0)";
}
return clause;
}
@@ -708,23 +714,23 @@ namespace Sarand.Net.Standard.Base.Dbas
//---------------------------------------------------------------------
// Start with the column names.
String query = "SELECT ";
if (DistinctRows) query += "DISTINCT ";
if (RowLimit > 0) query += "TOP " + RowLimit.ToString() + " ";
if (Columns.Count < 1) query += "* ";
else query += Columns.Concat(" AS ", false).Concat(",");
String query = "SELECT";
if (DistinctRows) query += " DISTINCT";
if (RowLimit > 0) query += $" TOP {RowLimit.ToString()}";
if (Columns.Count < 1) query += " *";
else query += $" {Columns.Concat(" AS ", false).Concat(",")}";
//---------------------------------------------------------------------
// Add the tables and joins.
String tableAliasOperator = DbGlobalDbms.Type == DbmsType.Sage ? " " : " AS ";
if (Tables.Count > 1 || Joins.Count < 1)
{
query += " FROM " + Tables.Concat(tableAliasOperator, false).Concat(",") + " " + Joins.BuildJoins("");
query += $" FROM {Tables.Concat(tableAliasOperator, false).Concat(",")} {Joins.BuildJoins("")}";
}
else if (Tables.Count == 1)
{
// Table name is bracketed with multiple joins...
query += " FROM " + Joins.BuildJoins(Tables.Concat(tableAliasOperator, false)[0]);
// Single Table name is bracketed with multiple joins.
query += $" FROM {Joins.BuildJoins(Tables.Concat(tableAliasOperator, false)[0])}";
}
query.TrimEnd(' ');
@@ -732,24 +738,24 @@ namespace Sarand.Net.Standard.Base.Dbas
// Filters.
String filter = Filters.Concat(" AND ", "(", ")", true, true);
// Jan2019 Not required: if (Filters.Count > 1) filter = "(" + filter + ")";
if (!filter.IsEmpty()) query += " WHERE " + filter;
if (!filter.IsEmpty()) query += $" WHERE {filter}";
// Groupings.
String groupByData = GroupBy.Concat(",", "", "", true, true);
if (!groupByData.IsEmpty()) query += " GROUP BY " + groupByData;
String groupByClause = GroupBy.Concat(",", "", "", true, true);
if (!groupByClause.IsEmpty()) query += $" GROUP BY {groupByClause}";
// Sort sequence.
String orderByData = OrderBy.Concat(",", "", "", true, true);
if (!orderByData.IsEmpty()) query += " ORDER BY " + orderByData;
String orderByClause = OrderBy.Concat(",", "", "", true, true);
if (!orderByClause.IsEmpty()) query += $" ORDER BY {orderByClause}";
// Paging.
if (paging != null && paging.Paged)
{
// Must have an 'Order By' clause to use 'Offset ... Fetch Next ...'
if (orderByData.IsEmpty())
if (orderByClause.IsEmpty())
throw new NotSupportedException("Query paging requires sort order to be specified");
if (DbGlobalDbms.Type == DbmsType.MsSql)
query += " OFFSET " + ((paging.PageNo - 1) * paging.PageLength) + " ROWS FETCH NEXT " + paging.PageLength + " ROWS ONLY";
query += $" OFFSET {((paging.PageNo - 1) * paging.PageLength)} ROWS FETCH NEXT {paging.PageLength} ROWS ONLY";
else throw new NotSupportedException($"Query paging not supported for {DbGlobalDbms.Type}");
}
@@ -757,7 +763,7 @@ namespace Sarand.Net.Standard.Base.Dbas
#if DEBUG
bool bDisplayDebugMsg = false;
if (bDisplayDebugMsg)
SaLogger.Debug("Query: " + query);
SaLogger.Debug($"Query: {query}");
#endif
//---------------------------------------------------------------------