|
- using System.Data;
- using System.Data.OleDb;
- using System.Runtime.Versioning;
-
- namespace Campaign_Tracker.Server.LegacyData.Schema;
-
- [SupportedOSPlatform("windows")]
- public sealed class OleDbLegacySchemaInspector : ILegacySchemaInspector
- {
- private readonly string _connectionString;
-
- public OleDbLegacySchemaInspector(string connectionString)
- {
- if (string.IsNullOrWhiteSpace(connectionString))
- {
- throw new ArgumentException("Legacy database connection string is required.", nameof(connectionString));
- }
-
- _connectionString = connectionString;
- }
-
- public async Task<IReadOnlyList<LegacyTableDefinition>> GetCurrentSchemaAsync(
- CancellationToken cancellationToken = default)
- {
- await using var connection = new OleDbConnection(_connectionString);
- await connection.OpenAsync(cancellationToken);
-
- var schema = connection.GetOleDbSchemaTable(OleDbSchemaGuid.Columns, null)
- ?? throw new InvalidOperationException("OleDb provider did not return column schema metadata.");
-
- var tables = schema.Rows
- .Cast<DataRow>()
- .GroupBy(row => GetRequiredString(row, "TABLE_NAME"), StringComparer.OrdinalIgnoreCase)
- .OrderBy(group => group.Key, StringComparer.OrdinalIgnoreCase)
- .Select(group => new LegacyTableDefinition(
- group.Key,
- group
- .OrderBy(row => GetOrdinal(row))
- .Select(row => new LegacyColumnDefinition(
- GetRequiredString(row, "COLUMN_NAME"),
- GetRequiredInt(row, "DATA_TYPE"),
- GetNullableInt(row, "CHARACTER_MAXIMUM_LENGTH"),
- GetNullableBool(row, "IS_NULLABLE") ?? true)
- {
- Constraints = GetColumnConstraints(row),
- })
- .ToArray()))
- .ToArray();
-
- return tables;
- }
-
- private static int GetOrdinal(DataRow row) =>
- GetNullableInt(row, "ORDINAL_POSITION") ?? int.MaxValue;
-
- private static IReadOnlyList<string> GetColumnConstraints(DataRow row)
- {
- var constraints = new List<string>();
- return constraints;
- }
-
- private static string GetRequiredString(DataRow row, string columnName)
- {
- var value = row.Table.Columns.Contains(columnName) ? row[columnName] : null;
- var text = value is null or DBNull ? null : Convert.ToString(value);
- return string.IsNullOrWhiteSpace(text)
- ? throw new InvalidOperationException($"OleDb schema row is missing required field {columnName}.")
- : text;
- }
-
- private static int GetRequiredInt(DataRow row, string columnName) =>
- GetNullableInt(row, columnName)
- ?? throw new InvalidOperationException($"OleDb schema row is missing required field {columnName}.");
-
- private static int? GetNullableInt(DataRow row, string columnName)
- {
- if (!row.Table.Columns.Contains(columnName) || row[columnName] is DBNull)
- {
- return null;
- }
-
- return Convert.ToInt32(row[columnName]);
- }
-
- private static bool? GetNullableBool(DataRow row, string columnName)
- {
- if (!row.Table.Columns.Contains(columnName) || row[columnName] is DBNull)
- {
- return null;
- }
-
- var value = row[columnName];
- if (value is bool flag)
- {
- return flag;
- }
-
- var text = Convert.ToString(value);
- if (string.Equals(text, "YES", StringComparison.OrdinalIgnoreCase) ||
- string.Equals(text, "TRUE", StringComparison.OrdinalIgnoreCase))
- {
- return true;
- }
-
- if (string.Equals(text, "NO", StringComparison.OrdinalIgnoreCase) ||
- string.Equals(text, "FALSE", StringComparison.OrdinalIgnoreCase))
- {
- return false;
- }
-
- return null;
- }
- }
|