Skip to content

Commit 3120c2b

Browse files
author
Mohsen Esmailpour
committed
Implement SqlServer query builder.
1 parent 9127ebf commit 3120c2b

File tree

17 files changed

+520
-392
lines changed

17 files changed

+520
-392
lines changed
Lines changed: 30 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -1,34 +1,34 @@
1-
using Serilog.Ui.Core.Models;
1+
using Serilog.Ui.Core.Attributes;
2+
using Serilog.Ui.Core.Models;
3+
using System.Reflection;
24
using static Serilog.Ui.Core.Models.SearchOptions;
35

46
namespace Serilog.Ui.Core.QueryBuilder.Sql;
57

68
/// <summary>
79
/// Abstract class that provides methods to build SQL queries for fetching and counting logs.
810
/// </summary>
9-
public abstract class SqlQueryBuilder
11+
public abstract class SqlQueryBuilder<TModel> where TModel : LogModel
1012
{
1113
/// <summary>
1214
/// Builds a SQL query to fetch logs from the specified table.
1315
/// </summary>
14-
/// <typeparam name="T">The type of the log model.</typeparam>
1516
/// <param name="columns">The column names used in the sink for logging.</param>
1617
/// <param name="schema">The schema of the table.</param>
1718
/// <param name="tableName">The name of the table.</param>
1819
/// <param name="query">The query parameters for fetching logs.</param>
1920
/// <returns>A SQL query string to fetch logs.</returns>
20-
public abstract string BuildFetchLogsQuery<T>(SinkColumnNames columns, string schema, string tableName, FetchLogsQuery query) where T : LogModel;
21+
public abstract string BuildFetchLogsQuery(SinkColumnNames columns, string schema, string tableName, FetchLogsQuery query);
2122

2223
/// <summary>
2324
/// Builds a SQL query to count logs in the specified table.
2425
/// </summary>
25-
/// <typeparam name="T">The type of the log model.</typeparam>
2626
/// <param name="columns">The column names used in the sink for logging.</param>
2727
/// <param name="schema">The schema of the table.</param>
2828
/// <param name="tableName">The name of the table.</param>
2929
/// <param name="query">The query parameters for counting logs.</param>
3030
/// <returns>A SQL query string to count logs.</returns>
31-
public abstract string BuildCountLogsQuery<T>(SinkColumnNames columns, string schema, string tableName, FetchLogsQuery query) where T : LogModel;
31+
public abstract string BuildCountLogsQuery(SinkColumnNames columns, string schema, string tableName, FetchLogsQuery query);
3232

3333
/// <summary>
3434
/// Generates a SQL sort clause based on the specified sort property and direction.
@@ -37,16 +37,31 @@ public abstract class SqlQueryBuilder
3737
/// <param name="sortOn">The property to sort on.</param>
3838
/// <param name="sortBy">The direction to sort by.</param>
3939
/// <returns>A SQL sort clause string.</returns>
40-
protected static string GenerateSortClause(SinkColumnNames columns, SortProperty sortOn, SortDirection sortBy)
40+
protected abstract string GenerateSortClause(SinkColumnNames columns, SortProperty sortOn, SortDirection sortBy);
41+
42+
/// <summary>
43+
/// Generates a SQL sort clause based on the specified sort property and direction.
44+
/// </summary>
45+
/// <param name="columns">The column names used in the sink for logging.</param>
46+
/// <param name="sortOn">The property to sort on.</param>
47+
/// <returns>A SQL sort clause string.</returns>
48+
protected static string GetSortColumnName(SinkColumnNames columns, SortProperty sortOn) => sortOn switch
49+
{
50+
SortProperty.Timestamp => columns.Timestamp,
51+
SortProperty.Level => columns.Level,
52+
SortProperty.Message => columns.Message,
53+
_ => columns.Timestamp
54+
};
55+
56+
/// <summary>
57+
/// Determines whether to add the exception column to the WHERE clause based on the presence of the RemovedColumnAttribute.
58+
/// </summary>
59+
/// <returns>True if the exception column should be added to the WHERE clause; otherwise, false.</returns>
60+
protected static bool AddExceptionToWhereClause()
4161
{
42-
var sortPropertyName = sortOn switch
43-
{
44-
SortProperty.Timestamp => columns.Timestamp,
45-
SortProperty.Level => columns.Level,
46-
SortProperty.Message => columns.Message,
47-
_ => columns.Timestamp
48-
};
62+
PropertyInfo? exceptionProperty = typeof(TModel).GetProperty("Exception");
63+
RemovedColumnAttribute? att = exceptionProperty?.GetCustomAttribute<RemovedColumnAttribute>();
4964

50-
return $"\"{sortPropertyName}\" {sortBy.ToString().ToUpper()}";
65+
return att is null;
5166
}
5267
}
Lines changed: 52 additions & 52 deletions
Original file line numberDiff line numberDiff line change
@@ -1,64 +1,64 @@
1-
using System;
2-
using Dapper;
1+
using Dapper;
32
using Microsoft.Extensions.DependencyInjection;
43
using Serilog.Ui.Core;
54
using Serilog.Ui.Core.Interfaces;
65
using Serilog.Ui.Core.Models.Options;
6+
using System;
77

8-
namespace Serilog.Ui.MsSqlServerProvider.Extensions
9-
{
10-
/// <summary>
11-
/// SQL Server data provider specific extension methods for <see cref="ISerilogUiOptionsBuilder"/>.
12-
/// </summary>
13-
public static class SerilogUiOptionBuilderExtensions
14-
{
15-
/// <summary>Configures the SerilogUi to connect to a SQL Server database.</summary>
16-
/// <param name="optionsBuilder"> The options builder. </param>
17-
/// <param name="setupOptions">The Ms Sql options action.</param>
18-
/// <param name="dateTimeCustomParsing">
19-
/// Delegate to customize the DateTime parsing.
20-
/// It throws <see cref="InvalidOperationException" /> if the return DateTime isn't UTC kind.
21-
/// </param>
22-
public static ISerilogUiOptionsBuilder UseSqlServer(
23-
this ISerilogUiOptionsBuilder optionsBuilder,
24-
Action<RelationalDbOptions> setupOptions,
25-
Func<string, DateTime>? dateTimeCustomParsing = null
26-
) => optionsBuilder.UseSqlServer<SqlServerLogModel>(setupOptions, dateTimeCustomParsing);
27-
28-
/// <summary>Configures the SerilogUi to connect to a SQL Server database.</summary>
29-
/// <typeparam name="T">The log model, containing any additional columns. It must inherit <see cref="SqlServerLogModel"/>.</typeparam>
30-
/// <param name="optionsBuilder"> The options builder. </param>
31-
/// <param name="setupOptions">The Ms Sql options action.</param>
32-
/// <param name="dateTimeCustomParsing">
33-
/// Delegate to customize the DateTime parsing.
34-
/// It throws <see cref="InvalidOperationException" /> if the return DateTime isn't UTC kind.
35-
/// </param>
36-
public static ISerilogUiOptionsBuilder UseSqlServer<T>(
37-
this ISerilogUiOptionsBuilder optionsBuilder,
38-
Action<RelationalDbOptions> setupOptions,
39-
Func<string, DateTime>? dateTimeCustomParsing = null
40-
) where T : SqlServerLogModel
41-
{
42-
var dbOptions = new RelationalDbOptions("dbo");
43-
setupOptions(dbOptions);
44-
dbOptions.Validate();
45-
46-
var providerName = dbOptions.GetProviderName(SqlServerDataProvider.MsSqlProviderName);
8+
namespace Serilog.Ui.MsSqlServerProvider.Extensions;
479

48-
optionsBuilder.RegisterExceptionAsStringForProviderKey(providerName);
49-
SqlMapper.AddTypeHandler(new DapperDateTimeHandler(dateTimeCustomParsing));
10+
/// <summary>
11+
/// SQL Server data provider specific extension methods for <see cref="ISerilogUiOptionsBuilder"/>.
12+
/// </summary>
13+
public static class SerilogUiOptionBuilderExtensions
14+
{
15+
/// <summary>Configures the SerilogUi to connect to a SQL Server database.</summary>
16+
/// <param name="optionsBuilder"> The options builder. </param>
17+
/// <param name="setupOptions">The Ms Sql options action.</param>
18+
/// <param name="dateTimeCustomParsing">
19+
/// Delegate to customize the DateTime parsing.
20+
/// It throws <see cref="InvalidOperationException" /> if the return DateTime isn't UTC kind.
21+
/// </param>
22+
public static ISerilogUiOptionsBuilder UseSqlServer(
23+
this ISerilogUiOptionsBuilder optionsBuilder,
24+
Action<RelationalDbOptions> setupOptions,
25+
Func<string, DateTime>? dateTimeCustomParsing = null
26+
) => optionsBuilder.UseSqlServer<SqlServerLogModel>(setupOptions, dateTimeCustomParsing);
5027

51-
var customModel = typeof(T) != typeof(SqlServerLogModel);
52-
if (customModel)
53-
{
54-
optionsBuilder.RegisterColumnsInfo<T>(providerName);
55-
optionsBuilder.Services.AddScoped<IDataProvider>(_ => new SqlServerDataProvider<T>(dbOptions));
28+
/// <summary>Configures the SerilogUi to connect to a SQL Server database.</summary>
29+
/// <typeparam name="T">The log model, containing any additional columns. It must inherit <see cref="SqlServerLogModel"/>.</typeparam>
30+
/// <param name="optionsBuilder"> The options builder. </param>
31+
/// <param name="setupOptions">The Ms Sql options action.</param>
32+
/// <param name="dateTimeCustomParsing">
33+
/// Delegate to customize the DateTime parsing.
34+
/// It throws <see cref="InvalidOperationException" /> if the return DateTime isn't UTC kind.
35+
/// </param>
36+
public static ISerilogUiOptionsBuilder UseSqlServer<T>(
37+
this ISerilogUiOptionsBuilder optionsBuilder,
38+
Action<RelationalDbOptions> setupOptions,
39+
Func<string, DateTime>? dateTimeCustomParsing = null
40+
) where T : SqlServerLogModel
41+
{
42+
SqlServerDbOptions dbOptions = new("dbo");
43+
setupOptions(dbOptions);
44+
dbOptions.Validate();
5645

57-
return optionsBuilder;
58-
}
46+
string providerName = dbOptions.GetProviderName(SqlServerDataProvider.MsSqlProviderName);
47+
optionsBuilder.RegisterExceptionAsStringForProviderKey(providerName);
48+
SqlMapper.AddTypeHandler(new DapperDateTimeHandler(dateTimeCustomParsing));
5949

60-
optionsBuilder.Services.AddScoped<IDataProvider>(_ => new SqlServerDataProvider(dbOptions));
61-
return optionsBuilder;
50+
bool customModel = typeof(T) != typeof(SqlServerLogModel);
51+
if (customModel)
52+
{
53+
optionsBuilder.RegisterColumnsInfo<T>(providerName);
54+
optionsBuilder.Services.AddScoped<IDataProvider>(_ => new SqlServerDataProvider<T>(dbOptions, new SqlServerQueryBuilder<T>()));
6255
}
56+
else
57+
{
58+
optionsBuilder.Services.AddScoped<IDataProvider>(_ =>
59+
new SqlServerDataProvider(dbOptions, new SqlServerQueryBuilder<SqlServerLogModel>()));
60+
}
61+
62+
return optionsBuilder;
6363
}
6464
}
Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
using Serilog.Ui.Core.Models.Options;
2+
using Serilog.Ui.Core.QueryBuilder.Sql;
3+
using Serilog.Ui.MsSqlServerProvider.Models;
4+
5+
namespace Serilog.Ui.MsSqlServerProvider.Extensions;
6+
7+
public class SqlServerDbOptions(string defaultSchemaName) : RelationalDbOptions(defaultSchemaName)
8+
{
9+
internal SinkColumnNames ColumnNames { get; } = new SqlServerSinkColumnNames();
10+
}
Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
using Serilog.Ui.Core.QueryBuilder.Sql;
2+
3+
namespace Serilog.Ui.MsSqlServerProvider.Models;
4+
5+
internal class SqlServerSinkColumnNames : SinkColumnNames
6+
{
7+
public SqlServerSinkColumnNames()
8+
{
9+
Exception = "Exception";
10+
Level = "Level";
11+
LogEventSerialized = "Properties";
12+
Message = "Message";
13+
MessageTemplate = "";
14+
Timestamp = "TimeStamp";
15+
}
16+
}

src/Serilog.Ui.MsSqlServerProvider/Serilog.Ui.MsSqlServerProvider.csproj

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -13,10 +13,11 @@
1313

1414
<ItemGroup>
1515
<PackageReference Include="Dapper" Version="2.1.35" />
16-
<PackageReference Include="Microsoft.Data.SqlClient" Version="5.2.1"/>
16+
<PackageReference Include="Microsoft.Data.SqlClient" Version="5.2.1" />
1717
</ItemGroup>
1818

1919
<ItemGroup>
2020
<ProjectReference Include="..\Serilog.Ui.Core\Serilog.Ui.Core.csproj" PrivateAssets="All" />
21+
<InternalsVisibleTo Include="MsSql.Tests" />
2122
</ItemGroup>
2223
</Project>

0 commit comments

Comments
 (0)