Skip to content

Commit 16ba70c

Browse files
authored
feat(config/schema): extend schema API with DB and change-tracking metadata (#97)
- Add DbInfo and SourceTableChangeTrackingInfo records under Models/Schema - Add DbInfoQuery and SourceTableChangeTrackingInfoQuery constants in SchemaExtensions - GetJobConfigSchema now returns sourceDbInfo, targetDbInfo, tableSchemas, and sourceTableChangeTrackingInfos - Rename HTTP request parameter reg to req and validate with ThrowIfNull(req) - Add Dapper usage and remove unused usings (System.Net, SqlBulkSyncFunction.Models)
1 parent e7c6171 commit 16ba70c

4 files changed

Lines changed: 123 additions & 7 deletions

File tree

src/SqlBulkSyncFunction/Functions/GetSyncJobConfig.cs

Lines changed: 31 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1,15 +1,14 @@
11
using System;
22
using System.Linq;
3-
using System.Net;
43
using System.Threading.Tasks;
4+
using Dapper;
55
using Microsoft.AspNetCore.Http;
66
using Microsoft.AspNetCore.Mvc;
77
using Microsoft.Azure.Functions.Worker;
88
using Microsoft.Data.SqlClient;
99
using Microsoft.Extensions.Logging;
1010
using Microsoft.Extensions.Options;
1111
using SqlBulkSyncFunction.Helpers;
12-
using SqlBulkSyncFunction.Models;
1312
using SqlBulkSyncFunction.Models.Job;
1413
using SqlBulkSyncFunction.Models.Schema;
1514
using SqlBulkSyncFunction.Services;
@@ -29,9 +28,11 @@ public async Task<IActionResult> ListIds(
2928
AuthorizationLevel.Function,
3029
"get",
3130
Route ="config"
32-
)] HttpRequest reg
31+
)] HttpRequest req
3332
)
3433
{
34+
ArgumentNullException.ThrowIfNull(req);
35+
3536
var idS = syncJobsConfig.Value.Jobs.Keys;
3637
return new OkObjectResult(idS);
3738
}
@@ -42,10 +43,12 @@ public async Task<IActionResult> ListAreas(
4243
AuthorizationLevel.Function,
4344
"get",
4445
Route ="config/{id}"
45-
)] HttpRequest reg,
46+
)] HttpRequest req,
4647
string id
4748
)
4849
{
50+
ArgumentNullException.ThrowIfNull(req);
51+
4952
if (
5053
!string.IsNullOrWhiteSpace(id) &&
5154
syncJobsConfig.Value.Jobs.TryGetValue(id, out var syncJobConfig)
@@ -62,11 +65,13 @@ public async Task<IActionResult> GetJobConfig(
6265
AuthorizationLevel.Function,
6366
"get",
6467
Route ="config/{id}/{area}"
65-
)] HttpRequest reg,
68+
)] HttpRequest req,
6669
string id,
6770
string area
6871
)
6972
{
73+
ArgumentNullException.ThrowIfNull(req);
74+
7075
if (!string.IsNullOrWhiteSpace(area) &&
7176
!string.IsNullOrWhiteSpace(id) &&
7277
syncJobsConfig.Value.Jobs.TryGetValue(id, out var jobConfig) &&
@@ -100,11 +105,13 @@ public async Task<IActionResult> GetJobConfigSchema(
100105
AuthorizationLevel.Function,
101106
"get",
102107
Route ="config/{id}/{area}/schema"
103-
)] HttpRequest reg,
108+
)] HttpRequest req,
104109
string id,
105110
string area
106111
)
107112
{
113+
ArgumentNullException.ThrowIfNull(req);
114+
108115
if (!string.IsNullOrWhiteSpace(area) &&
109116
!string.IsNullOrWhiteSpace(id) &&
110117
syncJobsConfig.Value.Jobs.TryGetValue(id, out var jobConfig) &&
@@ -129,6 +136,15 @@ string area
129136
await sourceConn.OpenAsync();
130137
await targetConn.OpenAsync();
131138

139+
DbInfo
140+
sourceDbInfo = await sourceConn.QueryFirstAsync<DbInfo>(SchemaExtensions.DbInfoQuery),
141+
targetDbInfo = await targetConn.QueryFirstAsync<DbInfo>(SchemaExtensions.DbInfoQuery);
142+
143+
SourceTableChangeTrackingInfo[]
144+
sourceTableChangeTrackingInfos = [.. await sourceConn.QueryAsync<SourceTableChangeTrackingInfo>(SchemaExtensions.SourceTableChangeTrackingInfoQuery)];
145+
146+
147+
132148
var tableSchemas = (
133149
syncJob.Tables ?? []
134150
)
@@ -151,7 +167,15 @@ string area
151167
})
152168
.ToArray();
153169

154-
return new OkObjectResult(tableSchemas);
170+
return new OkObjectResult(
171+
new
172+
{
173+
sourceDbInfo,
174+
targetDbInfo,
175+
tableSchemas,
176+
sourceTableChangeTrackingInfos
177+
}
178+
);
155179
}
156180
return new NotFoundResult();
157181
}

src/SqlBulkSyncFunction/Helpers/SchemaExtensions.cs

Lines changed: 50 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,56 @@ namespace SqlBulkSyncFunction.Helpers;
99

1010
public static class SchemaExtensions
1111
{
12+
/// <summary>
13+
/// Query to retrieve database-level info including change tracking and server metadata.
14+
/// </summary>
15+
public const string DbInfoQuery =
16+
"""
17+
SELECT @@SERVERNAME AS ServerName,
18+
DB_NAME(db.DatabaseId) AS DatabaseName,
19+
CAST(ISNULL(ct.IsChangeTrackingDatabase, 0) as bit) AS IsChangeTrackingDatabase,
20+
CAST(ISNULL(IsAautoCleanupOn, 0) as bit) AS IsAautoCleanupOn,
21+
RetentionPeriod AS RetentionPeriod,
22+
RetentionPeriodUnit AS RetentionPeriodUnit,
23+
@@VERSION AS ServerVersion
24+
FROM (
25+
SELECT DB_ID() AS DatabaseId -- current DB
26+
) db
27+
OUTER APPLY (
28+
SELECT CAST(1 as bit) AS IsChangeTrackingDatabase,
29+
is_auto_cleanup_on AS IsAautoCleanupOn,
30+
retention_period AS RetentionPeriod,
31+
retention_period_units_desc AS RetentionPeriodUnit
32+
FROM sys.change_tracking_databases
33+
WHERE database_id = db.DatabaseId
34+
) ct
35+
""";
36+
37+
/// <summary>
38+
/// Query to retrieve change tracking metadata for all tracked tables in the database.
39+
/// </summary>
40+
public const string SourceTableChangeTrackingInfoQuery =
41+
"""
42+
SELECT
43+
t.object_id AS TableObjectId,
44+
s.name AS SchemaName,
45+
t.name AS TableName,
46+
CAST(ctt.is_track_columns_updated_on as bit) AS TrackColumnsUpdated,
47+
CHANGE_TRACKING_MIN_VALID_VERSION(t.object_id) AS MinValidVersion,
48+
CHANGE_TRACKING_CURRENT_VERSION() AS CurrentDatabaseVersion,
49+
rc.EstimateRowCount AS EstimateRowCount
50+
FROM sys.change_tracking_tables AS ctt
51+
JOIN sys.tables AS t ON t.object_id = ctt.object_id
52+
JOIN sys.schemas AS s ON s.schema_id = t.schema_id
53+
OUTER APPLY (
54+
SELECT SUM(p.row_count) AS EstimateRowCount
55+
FROM sys.dm_db_partition_stats AS p
56+
WHERE p.object_id = t.object_id
57+
AND p.index_id IN (0, 1)
58+
) rc
59+
ORDER BY s.name, t.name;
60+
""";
61+
1262
public static void PersistsSourceTargetVersionState(
1363
this SqlConnection conn,
1464
TableSchema tableSchema
Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
namespace SqlBulkSyncFunction.Models.Schema;
2+
3+
/// <summary>
4+
/// Database-level information including change tracking and server metadata.
5+
/// </summary>
6+
/// <param name="ServerName">Name of the SQL Server instance.</param>
7+
/// <param name="DatabaseName">Name of the database.</param>
8+
/// <param name="IsChangeTrackingDatabase">Whether change tracking is enabled for the database.</param>
9+
/// <param name="IsAautoCleanupOn">Whether change tracking auto-cleanup is enabled.</param>
10+
/// <param name="RetentionPeriod">Change tracking retention period value.</param>
11+
/// <param name="RetentionPeriodUnit">Unit of the retention period (e.g. DAYS).</param>
12+
/// <param name="ServerVersion">SQL Server version string.</param>
13+
public record DbInfo(
14+
string ServerName,
15+
string DatabaseName,
16+
bool IsChangeTrackingDatabase,
17+
bool IsAautoCleanupOn,
18+
int? RetentionPeriod,
19+
string RetentionPeriodUnit,
20+
string ServerVersion
21+
);
Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
namespace SqlBulkSyncFunction.Models.Schema;
2+
3+
/// <summary>
4+
/// Change tracking metadata for a single table in the source database.
5+
/// </summary>
6+
/// <param name="TableObjectId">Object ID of the table.</param>
7+
/// <param name="SchemaName">Schema name of the table.</param>
8+
/// <param name="TableName">Name of the table.</param>
9+
/// <param name="TrackColumnsUpdated">Whether column-level change tracking is enabled.</param>
10+
/// <param name="MinValidVersion">Minimum valid change tracking version for the table.</param>
11+
/// <param name="CurrentDatabaseVersion">Current change tracking version of the database.</param>
12+
/// <param name="EstimateRowCount">Estimated row count for the table.</param>
13+
public record SourceTableChangeTrackingInfo(
14+
int TableObjectId,
15+
string SchemaName,
16+
string TableName,
17+
bool TrackColumnsUpdated,
18+
long MinValidVersion,
19+
long CurrentDatabaseVersion,
20+
long? EstimateRowCount
21+
);

0 commit comments

Comments
 (0)