8c6d6aff6a
Moves the database-independent logic of the SQL Server historian backend into a new shared library for the upcoming QuestDB backend (#666): status codes and bits, value/column mapping, StoredSample + quality clamp, the AtTime and aggregate evaluators, BucketPlan, LiveWritePreparer and HistoryUpdatePlanner (both with a resolutionTicks parameter, default 1), tag-name rules, the bootstrap failure cache, health counters, alarm event ids, the event continuation and severity clamp. The SQL Server backend now calls it; its T-SQL, TVP builders, connection, bootstrapper and catalog stay. Tests: StatusCodeOracleTests, ValueWriterPrepareTests, the column half of SampleRowMapperTests and ProcessedReadTests.Every_enum_member_is_either_served_or_refused move to the new Sql.Common.Tests under the same names. SqlServer integration tests get mechanical renames only. Test-name set across the three projects is identical to the baseline (160 tests). Claude-Session: https://claude.ai/code/session_01Ef2ozxS7QPanGT8uoATbTe
33 lines
1.6 KiB
C#
33 lines
1.6 KiB
C#
using ZB.MOM.WW.OtOpcUa.Core.Abstractions;
|
|
|
|
namespace ZB.MOM.WW.OtOpcUa.Driver.Historian.Sql.Common;
|
|
|
|
/// <summary>A stored sample as read back: source time, typed value and stored status.</summary>
|
|
/// <param name="TimeUtc">Source timestamp (UTC).</param>
|
|
/// <param name="Value">Typed value (<see cref="HistorianValue.Empty"/> for an outage marker).</param>
|
|
/// <param name="Status">Stored OPC UA status code.</param>
|
|
public readonly record struct StoredSample(DateTime TimeUtc, HistorianValue Value, uint Status)
|
|
{
|
|
/// <summary>Severity Good or Uncertain, and a value present (an Empty sample is an outage marker).</summary>
|
|
public bool IsUsable => !StatusBits.IsBad(Status) && Value.Kind != HistorianValueKind.Empty;
|
|
|
|
/// <summary>Usable with severity Good.</summary>
|
|
public bool IsGood => IsUsable && StatusBits.IsGood(Status);
|
|
|
|
/// <summary>
|
|
/// Builds a sample from stored columns, applying the quality clamp: an Empty (no-value) row whose stored status
|
|
/// is not Bad is served as <c>BadNoData</c> — defence in depth for rows written before the writer forced every
|
|
/// Empty sample Bad.
|
|
/// </summary>
|
|
/// <param name="timeUtc">Source timestamp (UTC).</param>
|
|
/// <param name="value">Stored value.</param>
|
|
/// <param name="status">Stored status code.</param>
|
|
/// <returns>The sample, clamped.</returns>
|
|
public static StoredSample FromStored(DateTime timeUtc, HistorianValue value, uint status)
|
|
{
|
|
if (value.Kind == HistorianValueKind.Empty && !StatusBits.IsBad(status))
|
|
status = HistorianStatusCodes.BadNoData;
|
|
return new StoredSample(timeUtc, value, status);
|
|
}
|
|
}
|