Files
MBN_STOCK_WEBVIEW/tools/MBN_STOCK_WEBVIEW.DbWriteSmoke/ExistingChildRowGuard.cs

99 lines
3.5 KiB
C#

#nullable enable
using System.Data;
using MMoneyCoderSharp.Data;
namespace MBN_STOCK_WEBVIEW.DbWriteSmoke;
/// <summary>
/// The legacy deletion workflows remove child rows by numeric parent key. This
/// read-only guard proves a newly suggested key has no pre-existing orphaned
/// children before a smoke record can adopt that key.
/// </summary>
internal sealed class ExistingChildRowGuard
{
private const string ResultColumn = "ROW_COUNT";
private readonly IDataQueryExecutor _executor;
internal ExistingChildRowGuard(IDataQueryExecutor executor)
{
_executor = executor ?? throw new ArgumentNullException(nameof(executor));
}
internal Task EnsureNamedPlaylistChildrenAbsentAsync(
string programCode,
CancellationToken cancellationToken) =>
EnsureZeroAsync(
DataSourceKind.Oracle,
"DB_WRITE_SMOKE_PLAYLIST_CHILD_PREFLIGHT",
"SELECT TO_CHAR(COUNT(*)) ROW_COUNT FROM PLAY_LIST WHERE PG_CODE = :parent_code",
programCode,
cancellationToken);
internal Task EnsureThemeChildrenAbsentAsync(
ThemeMarket market,
string themeCode,
CancellationToken cancellationToken) =>
market switch
{
ThemeMarket.Krx => EnsureZeroAsync(
DataSourceKind.Oracle,
"DB_WRITE_SMOKE_KRX_THEME_CHILD_PREFLIGHT",
"SELECT TO_CHAR(COUNT(*)) ROW_COUNT FROM SB_ITEM WHERE SB_M_CODE = :parent_code",
themeCode,
cancellationToken),
ThemeMarket.Nxt => EnsureZeroAsync(
DataSourceKind.MariaDb,
"DB_WRITE_SMOKE_NXT_THEME_CHILD_PREFLIGHT",
"SELECT CAST(COUNT(*) AS CHAR) ROW_COUNT FROM SB_ITEM WHERE SB_M_CODE = @parent_code",
themeCode,
cancellationToken),
_ => throw new ArgumentOutOfRangeException(nameof(market))
};
internal Task EnsureExpertChildrenAbsentAsync(
string expertCode,
CancellationToken cancellationToken) =>
EnsureZeroAsync(
DataSourceKind.Oracle,
"DB_WRITE_SMOKE_EXPERT_CHILD_PREFLIGHT",
"SELECT TO_CHAR(COUNT(*)) ROW_COUNT FROM RECOMMEND_LIST WHERE RC_CODE = :parent_code",
expertCode,
cancellationToken);
private async Task EnsureZeroAsync(
DataSourceKind source,
string queryName,
string sql,
string parentCode,
CancellationToken cancellationToken)
{
ArgumentException.ThrowIfNullOrWhiteSpace(parentCode);
var spec = new DataQuerySpec(
sql,
[new DataQueryParameter("parent_code", parentCode, DbType.String)]);
spec.ValidateFor(source);
var table = await _executor.ExecuteAsync(
source,
queryName,
spec,
cancellationToken).ConfigureAwait(false);
if (table is null ||
table.Columns.Count != 1 ||
table.Rows.Count != 1 ||
!string.Equals(
table.Columns[0].ColumnName,
ResultColumn,
StringComparison.Ordinal) ||
table.Columns[0].DataType != typeof(string) ||
table.Rows[0][0] is not string count ||
!string.Equals(count, "0", StringComparison.Ordinal))
{
throw new InvalidOperationException(
"A suggested numeric key has existing child rows or an invalid preflight result.");
}
}
}