chore: initial git load of code space
This commit is contained in:
@@ -0,0 +1,146 @@
|
||||
using System.Text;
|
||||
using Strata.SqlTools.Breakdowns.SqlServer;
|
||||
using Strata.SqlTools.SqlBreakdown.Interfaces.QueryEngine;
|
||||
|
||||
namespace Strata.SqlTools.SqlServer.Utilities;
|
||||
|
||||
/// <summary>
|
||||
/// SQL Server-specific paging helper methods for generating paged query results.
|
||||
/// </summary>
|
||||
public static class SqlServerPagingUtils
|
||||
{
|
||||
/// <summary>
|
||||
/// Generates SQL for paged result sets.
|
||||
/// </summary>
|
||||
/// <param name="queryBreakdown">The query breakdown defining the SQL query.</param>
|
||||
/// <param name="pageIndex">The zero-based page index.</param>
|
||||
/// <param name="pageSize">The number of rows per page.</param>
|
||||
/// <param name="rowNumOrderBy">The ORDER BY clause for row numbering.</param>
|
||||
/// <returns>A SQL string that implements paging.</returns>
|
||||
public static string GetPagingSql(IQueryBreakdown queryBreakdown, int pageIndex, int pageSize, string rowNumOrderBy)
|
||||
{
|
||||
bool isPaged = pageIndex != -1;
|
||||
var sb = new StringBuilder();
|
||||
string finalTable = "#FINALTABLE" + Guid.NewGuid().ToString().Replace("-", string.Empty);
|
||||
|
||||
// Write out any setup clauses
|
||||
sb.AppendLine("--create setup clauses");
|
||||
foreach (string setup in queryBreakdown.SetupClauses)
|
||||
{
|
||||
sb.AppendLine(setup);
|
||||
}
|
||||
|
||||
// Get the data
|
||||
sb.AppendLine("--get the data");
|
||||
if (isPaged)
|
||||
{
|
||||
sb.Append($"SELECT Row_Number() Over (Order By {rowNumOrderBy}) as ROWNUM,");
|
||||
sb.AppendLine();
|
||||
sb.Append($"{queryBreakdown.SelectClause} INTO {finalTable} FROM {queryBreakdown.FromClause}");
|
||||
sb.AppendLine();
|
||||
|
||||
if (queryBreakdown.IsUsingWhereClause)
|
||||
{
|
||||
sb.Append($"WHERE {queryBreakdown.WhereClause}");
|
||||
sb.AppendLine();
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
sb.AppendLine("SELECT");
|
||||
sb.Append($"{queryBreakdown.SelectClause} INTO {finalTable} FROM {queryBreakdown.FromClause}");
|
||||
sb.AppendLine();
|
||||
|
||||
if (queryBreakdown.IsUsingWhereClause)
|
||||
{
|
||||
sb.Append($"WHERE {queryBreakdown.WhereClause}");
|
||||
sb.AppendLine();
|
||||
}
|
||||
}
|
||||
|
||||
if (queryBreakdown.IsUsingGroupByClause)
|
||||
{
|
||||
sb.Append(" GROUP BY ");
|
||||
sb.AppendLine();
|
||||
sb.Append($" {queryBreakdown.GroupByClause} ");
|
||||
sb.AppendLine();
|
||||
}
|
||||
|
||||
if (queryBreakdown.IsUsingOrderByClause)
|
||||
{
|
||||
sb.Append($"ORDER BY {queryBreakdown.OrderByClause}");
|
||||
sb.AppendLine();
|
||||
}
|
||||
|
||||
if (isPaged)
|
||||
{
|
||||
sb.Append($"SELECT * FROM {finalTable} WHERE ROWNUM BETWEEN ({pageIndex} * {pageSize} + 1) and ({pageSize} * ({pageIndex} + 1))");
|
||||
sb.AppendLine();
|
||||
}
|
||||
else
|
||||
{
|
||||
sb.Append($"SELECT * FROM {finalTable}");
|
||||
sb.AppendLine();
|
||||
}
|
||||
|
||||
sb.Append($"SELECT COUNT(*) FROM {finalTable}");
|
||||
sb.AppendLine();
|
||||
|
||||
// Drop temp tables
|
||||
sb.AppendLine("--drop temp tables");
|
||||
sb.Append($"drop table {finalTable}");
|
||||
sb.AppendLine();
|
||||
|
||||
// Write out any finish clauses
|
||||
sb.AppendLine("--create finish clauses");
|
||||
foreach (string finish in queryBreakdown.FinishClauses)
|
||||
{
|
||||
sb.AppendLine(finish);
|
||||
}
|
||||
|
||||
return sb.ToString();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Generate SQL to do paging. TotalCount will be returned as first column in the result set.
|
||||
/// Uses Common Table Expression (CTE) for efficient paging with ROW_NUMBER() and COUNT(*) OVER().
|
||||
/// </summary>
|
||||
/// <param name="queryBreakdown">The query breakdown defining the SQL query.</param>
|
||||
/// <param name="start">The starting row number (1-based).</param>
|
||||
/// <param name="limit">The maximum number of rows to return.</param>
|
||||
/// <param name="sort">The ORDER BY expression for sorting.</param>
|
||||
/// <returns>A SQL string that implements paging with total count.</returns>
|
||||
public static string GetPagingSqlByStart(IQueryBreakdown queryBreakdown, int start, int limit, string sort)
|
||||
{
|
||||
const string rowNumAlias = "RowNum";
|
||||
const string totalCountAlias = "TotalCount";
|
||||
|
||||
// Setup innerQuery
|
||||
const string innerQueryAlias = "Query";
|
||||
var innerQuery = (IQueryBreakdown)((ICloneable)queryBreakdown).Clone();
|
||||
|
||||
var innerSelectSb = new StringBuilder();
|
||||
innerSelectSb.Append($"ROW_NUMBER() OVER(ORDER BY {sort}) AS {rowNumAlias}, ");
|
||||
innerSelectSb.AppendLine();
|
||||
innerSelectSb.Append($"COUNT(*) OVER () AS {totalCountAlias}, ");
|
||||
innerSelectSb.AppendLine(((QueryBreakdown)queryBreakdown).SelectClause.Clause);
|
||||
((QueryBreakdown)innerQuery).SelectClause.Clause = innerSelectSb.ToString();
|
||||
|
||||
// Setup pagingQuery
|
||||
var pagingQuery = new QueryBreakdown();
|
||||
pagingQuery.SelectClause.Clause = "*";
|
||||
pagingQuery.FromClause.Clause = innerQueryAlias;
|
||||
pagingQuery.WhereClause.Clause = $"{rowNumAlias} BETWEEN {start} AND ({start} + {limit}) - 1";
|
||||
|
||||
// Setup finalQuery with CTE
|
||||
var sb = new StringBuilder();
|
||||
sb.Append($";WITH {innerQueryAlias} AS ");
|
||||
sb.AppendLine();
|
||||
sb.AppendLine("( ");
|
||||
sb.AppendLine(innerQuery.GetSql());
|
||||
sb.AppendLine(") ");
|
||||
sb.AppendLine(pagingQuery.GetSql(false));
|
||||
|
||||
return sb.ToString();
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user