fix: hc900_map_master UNIQUE 인덱스 변경 + FF/Stream 컬럼 마이그레이션
- hc900_map_master: UNIQUE(tagname) → UNIQUE(controller_id, tagname) - 동일 태그명이 여러 컨트롤러에 존재 가능 (peer comms) - ff_column_config: ALTER TABLE ADD COLUMN IF NOT EXISTS 10개 누락 컬럼 (feed_tag, pressure_tag, level_tags, feed_filter_tau_sec 등) - ff_stream_config: stream_key → key RENAME COLUMN + 12개 컬럼 추가 (flow_tag, role, target_coeff, theta_up_sec, theta_dn_sec, tau_sec, sp_min, sp_max, rate_up_per_min, rate_dn_per_min, reflux_from_product, grade) - EF Core HasIndex(tagname).IsUnique() → HasIndex(controller_id, tagname).IsUnique() - GetSubArea/UpdateSubArea/DeletePoint: ToLowerInvariant 제거 → OrdinalIgnoreCase 비교로 대체
This commit is contained in:
@@ -44,7 +44,7 @@ public class Hc900DbContext : DbContext
|
||||
modelBuilder.Entity<Hc900MapEntry>(e =>
|
||||
{
|
||||
e.HasKey(x => x.Id);
|
||||
e.HasIndex(x => x.TagName).IsUnique();
|
||||
e.HasIndex(x => new { x.ControllerId, x.TagName }).IsUnique();
|
||||
e.HasIndex(x => x.Hc900Tag);
|
||||
});
|
||||
|
||||
@@ -461,6 +461,30 @@ public class Hc900DbService : IExperionDbService
|
||||
await _ctx.Database.ExecuteSqlRawAsync(
|
||||
"ALTER TABLE hc900_map_master ADD COLUMN IF NOT EXISTS controller_id TEXT NOT NULL DEFAULT 'HC1'");
|
||||
|
||||
// hc900_map_master: tagname is unique PER controller, not globally — the same
|
||||
// SignalTag name can exist on several controllers (peer comms). Replace the old
|
||||
// UNIQUE(tagname) with UNIQUE(controller_id, tagname).
|
||||
await _ctx.Database.ExecuteSqlRawAsync("""
|
||||
DO $$
|
||||
BEGIN
|
||||
IF EXISTS (
|
||||
SELECT 1 FROM pg_constraint
|
||||
WHERE conrelid = 'hc900_map_master'::regclass
|
||||
AND conname = 'hc900_map_master_tagname_key'
|
||||
) THEN
|
||||
ALTER TABLE hc900_map_master DROP CONSTRAINT hc900_map_master_tagname_key;
|
||||
END IF;
|
||||
IF NOT EXISTS (
|
||||
SELECT 1 FROM pg_indexes
|
||||
WHERE tablename = 'hc900_map_master'
|
||||
AND indexname = 'ux_hc900_map_ctrl_tag'
|
||||
) THEN
|
||||
CREATE UNIQUE INDEX ux_hc900_map_ctrl_tag
|
||||
ON hc900_map_master(controller_id, tagname);
|
||||
END IF;
|
||||
END $$;
|
||||
""");
|
||||
|
||||
// realtime_table: UNIQUE(controller_id, tagname) for ON CONFLICT upsert
|
||||
await _ctx.Database.ExecuteSqlRawAsync("""
|
||||
DO $$
|
||||
@@ -1155,6 +1179,36 @@ public class Hc900DbService : IExperionDbService
|
||||
ALTER TABLE ff_column_config ADD COLUMN IF NOT EXISTS delta_p_tag TEXT;
|
||||
ALTER TABLE ff_column_config ADD COLUMN IF NOT EXISTS delta_p_flood_limit DOUBLE PRECISION NOT NULL DEFAULT 1e9;
|
||||
ALTER TABLE ff_column_config ADD COLUMN IF NOT EXISTS temp_high_limit DOUBLE PRECISION NOT NULL DEFAULT 1e9;
|
||||
-- migration: missing columns from the original CREATE TABLE (schema was json-based)
|
||||
ALTER TABLE ff_column_config ADD COLUMN IF NOT EXISTS feed_tag TEXT NOT NULL DEFAULT '';
|
||||
ALTER TABLE ff_column_config ADD COLUMN IF NOT EXISTS pressure_tag TEXT;
|
||||
ALTER TABLE ff_column_config ADD COLUMN IF NOT EXISTS level_tags TEXT;
|
||||
ALTER TABLE ff_column_config ADD COLUMN IF NOT EXISTS feed_filter_tau_sec DOUBLE PRECISION NOT NULL DEFAULT 300;
|
||||
ALTER TABLE ff_column_config ADD COLUMN IF NOT EXISTS feed_move_thr_per_min DOUBLE PRECISION NOT NULL DEFAULT 0;
|
||||
ALTER TABLE ff_column_config ADD COLUMN IF NOT EXISTS press_filter_tau_sec DOUBLE PRECISION NOT NULL DEFAULT 60;
|
||||
ALTER TABLE ff_column_config ADD COLUMN IF NOT EXISTS pressure_band DOUBLE PRECISION NOT NULL DEFAULT 1e9;
|
||||
ALTER TABLE ff_column_config ADD COLUMN IF NOT EXISTS settle_sec DOUBLE PRECISION NOT NULL DEFAULT 0;
|
||||
ALTER TABLE ff_column_config ADD COLUMN IF NOT EXISTS stale_sec DOUBLE PRECISION NOT NULL DEFAULT 120;
|
||||
ALTER TABLE ff_column_config ADD COLUMN IF NOT EXISTS product_key TEXT NOT NULL DEFAULT 'P';
|
||||
DO $$
|
||||
BEGIN
|
||||
IF EXISTS (SELECT 1 FROM information_schema.columns WHERE table_schema='hc900' AND table_name='ff_stream_config' AND column_name='stream_key')
|
||||
AND NOT EXISTS (SELECT 1 FROM information_schema.columns WHERE table_schema='hc900' AND table_name='ff_stream_config' AND column_name='key') THEN
|
||||
ALTER TABLE hc900.ff_stream_config RENAME COLUMN stream_key TO key;
|
||||
END IF;
|
||||
END $$;
|
||||
ALTER TABLE ff_stream_config ADD COLUMN IF NOT EXISTS flow_tag TEXT NOT NULL DEFAULT '';
|
||||
ALTER TABLE ff_stream_config ADD COLUMN IF NOT EXISTS role TEXT NOT NULL DEFAULT 'Monitor';
|
||||
ALTER TABLE ff_stream_config ADD COLUMN IF NOT EXISTS target_coeff DOUBLE PRECISION NOT NULL DEFAULT 0;
|
||||
ALTER TABLE ff_stream_config ADD COLUMN IF NOT EXISTS theta_up_sec DOUBLE PRECISION NOT NULL DEFAULT 0;
|
||||
ALTER TABLE ff_stream_config ADD COLUMN IF NOT EXISTS theta_dn_sec DOUBLE PRECISION NOT NULL DEFAULT 0;
|
||||
ALTER TABLE ff_stream_config ADD COLUMN IF NOT EXISTS tau_sec DOUBLE PRECISION NOT NULL DEFAULT 0;
|
||||
ALTER TABLE ff_stream_config ADD COLUMN IF NOT EXISTS sp_min DOUBLE PRECISION NOT NULL DEFAULT 0;
|
||||
ALTER TABLE ff_stream_config ADD COLUMN IF NOT EXISTS sp_max DOUBLE PRECISION NOT NULL DEFAULT 1e9;
|
||||
ALTER TABLE ff_stream_config ADD COLUMN IF NOT EXISTS rate_up_per_min DOUBLE PRECISION NOT NULL DEFAULT 1e9;
|
||||
ALTER TABLE ff_stream_config ADD COLUMN IF NOT EXISTS rate_dn_per_min DOUBLE PRECISION NOT NULL DEFAULT 1e9;
|
||||
ALTER TABLE ff_stream_config ADD COLUMN IF NOT EXISTS reflux_from_product BOOLEAN NOT NULL DEFAULT FALSE;
|
||||
ALTER TABLE ff_stream_config ADD COLUMN IF NOT EXISTS grade TEXT NOT NULL DEFAULT 'A';
|
||||
""");
|
||||
|
||||
// ── FF operator action audit log ────────────────────────────────
|
||||
@@ -1414,9 +1468,8 @@ public class Hc900DbService : IExperionDbService
|
||||
var point = await _ctx.RealtimePoints.FindAsync(id);
|
||||
if (point == null) return new PointDeleteResult { Deleted = false };
|
||||
|
||||
var tagName = point.TagName; // 예: "fi-6101.pv"
|
||||
var baseTag = (tagName.Contains('.') ? tagName[..tagName.IndexOf('.')] : tagName)
|
||||
.ToLowerInvariant(); // "fi-6101"
|
||||
var tagName = point.TagName; // 예: "FICQ-6101.pv"
|
||||
var baseTag = tagName.Contains('.') ? tagName[..tagName.IndexOf('.')] : tagName;
|
||||
|
||||
_ctx.RealtimePoints.Remove(point);
|
||||
await _ctx.SaveChangesAsync();
|
||||
@@ -1924,9 +1977,9 @@ public class Hc900DbService : IExperionDbService
|
||||
|
||||
public async Task<string?> GetSubAreaByTagNameAsync(string tagName)
|
||||
{
|
||||
var baseTag = (tagName.Contains('.') ? tagName[..tagName.LastIndexOf('.')] : tagName).ToLowerInvariant();
|
||||
var baseTag = tagName.Contains('.') ? tagName[..tagName.LastIndexOf('.')] : tagName;
|
||||
return await _ctx.TagMetadata
|
||||
.Where(m => m.BaseTag == baseTag && m.Attribute == "sub_area")
|
||||
.Where(m => m.BaseTag.Equals(baseTag, StringComparison.OrdinalIgnoreCase) && m.Attribute == "sub_area")
|
||||
.Select(m => m.Value)
|
||||
.FirstOrDefaultAsync();
|
||||
}
|
||||
@@ -1991,7 +2044,6 @@ public class Hc900DbService : IExperionDbService
|
||||
|
||||
public async Task<bool> UpdateSubAreaAsync(string baseTag, string? subArea)
|
||||
{
|
||||
baseTag = baseTag.ToLowerInvariant();
|
||||
if (string.IsNullOrWhiteSpace(subArea))
|
||||
{
|
||||
var deleted = await _ctx.Database.ExecuteSqlRawAsync(
|
||||
|
||||
Reference in New Issue
Block a user