@jungjaehoon/mama-core 1.4.2 → 1.5.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/db/migrations/026-create-canonical-entity-tables.sql +99 -0
- package/db/migrations/027-create-entity-review-support.sql +44 -0
- package/db/migrations/028-create-entity-audit-tables.sql +45 -0
- package/db/migrations/029-extend-entity-observations-observation-type.sql +60 -0
- package/db/migrations/030-case-first-memory-substrate.sql +901 -0
- package/db/migrations/031-wiki-page-index-provenance-columns.sql +2 -0
- package/dist/canonicalize.d.ts +38 -0
- package/dist/canonicalize.js +106 -0
- package/dist/cases/case-links.d.ts +116 -0
- package/dist/cases/case-links.js +794 -0
- package/dist/cases/composition-overrides.d.ts +90 -0
- package/dist/cases/composition-overrides.js +724 -0
- package/dist/cases/corrections.d.ts +156 -0
- package/dist/cases/corrections.js +1045 -0
- package/dist/cases/freshness.d.ts +57 -0
- package/dist/cases/freshness.js +283 -0
- package/dist/cases/live-state.d.ts +48 -0
- package/dist/cases/live-state.js +256 -0
- package/dist/cases/membership-explain.d.ts +56 -0
- package/dist/cases/membership-explain.js +140 -0
- package/dist/cases/membership-matcher.d.ts +23 -0
- package/dist/cases/membership-matcher.js +193 -0
- package/dist/cases/merge-split.d.ts +61 -0
- package/dist/cases/merge-split.js +368 -0
- package/dist/cases/role-inference.d.ts +10 -0
- package/dist/cases/role-inference.js +85 -0
- package/dist/cases/search-rollup.d.ts +23 -0
- package/dist/cases/search-rollup.js +225 -0
- package/dist/cases/sqlite-transaction.d.ts +10 -0
- package/dist/cases/sqlite-transaction.js +62 -0
- package/dist/cases/store.d.ts +74 -0
- package/dist/cases/store.js +816 -0
- package/dist/cases/target-ref.d.ts +25 -0
- package/dist/cases/target-ref.js +22 -0
- package/dist/cases/timeline-range.d.ts +6 -0
- package/dist/cases/timeline-range.js +322 -0
- package/dist/cases/tombstone-sweeper.d.ts +13 -0
- package/dist/cases/tombstone-sweeper.js +128 -0
- package/dist/cases/types.d.ts +244 -0
- package/dist/cases/types.js +47 -0
- package/dist/cases/wiki-page-index.d.ts +50 -0
- package/dist/cases/wiki-page-index.js +350 -0
- package/dist/connectors/event-index.d.ts +44 -0
- package/dist/connectors/event-index.js +366 -0
- package/dist/connectors/types.d.ts +69 -0
- package/dist/connectors/types.js +3 -0
- package/dist/db-manager.d.ts +4 -0
- package/dist/db-manager.js +10 -3
- package/dist/decision-formatter.d.ts +2 -0
- package/dist/decision-formatter.js +11 -8
- package/dist/embedding-server/mobile/daemon.d.ts +1 -0
- package/dist/embedding-server/mobile/daemon.js +11 -1
- package/dist/entities/audit-metrics.d.ts +73 -0
- package/dist/entities/audit-metrics.js +128 -0
- package/dist/entities/candidate-generator.d.ts +9 -0
- package/dist/entities/candidate-generator.js +436 -0
- package/dist/entities/entity-impact.d.ts +41 -0
- package/dist/entities/entity-impact.js +140 -0
- package/dist/entities/entity-linked-decision-counts.d.ts +2 -0
- package/dist/entities/entity-linked-decision-counts.js +29 -0
- package/dist/entities/entity-list.d.ts +23 -0
- package/dist/entities/entity-list.js +99 -0
- package/dist/entities/entity-orphan-list.d.ts +26 -0
- package/dist/entities/entity-orphan-list.js +91 -0
- package/dist/entities/entity-search.d.ts +21 -0
- package/dist/entities/entity-search.js +150 -0
- package/dist/entities/errors.d.ts +65 -0
- package/dist/entities/errors.js +124 -0
- package/dist/entities/exact-merge-backfill.d.ts +11 -0
- package/dist/entities/exact-merge-backfill.js +161 -0
- package/dist/entities/lineage-backfill.d.ts +12 -0
- package/dist/entities/lineage-backfill.js +101 -0
- package/dist/entities/lineage-store.d.ts +51 -0
- package/dist/entities/lineage-store.js +308 -0
- package/dist/entities/normalization.d.ts +14 -0
- package/dist/entities/normalization.js +63 -0
- package/dist/entities/policy-store.d.ts +17 -0
- package/dist/entities/policy-store.js +263 -0
- package/dist/entities/policy-types.d.ts +72 -0
- package/dist/entities/policy-types.js +59 -0
- package/dist/entities/projection.d.ts +8 -0
- package/dist/entities/projection.js +82 -0
- package/dist/entities/provenance-query.d.ts +33 -0
- package/dist/entities/provenance-query.js +167 -0
- package/dist/entities/read-identity.d.ts +31 -0
- package/dist/entities/read-identity.js +264 -0
- package/dist/entities/recall-bridge.d.ts +5 -0
- package/dist/entities/recall-bridge.js +171 -0
- package/dist/entities/resolution-engine.d.ts +15 -0
- package/dist/entities/resolution-engine.js +69 -0
- package/dist/entities/rollback-preview.d.ts +39 -0
- package/dist/entities/rollback-preview.js +235 -0
- package/dist/entities/source-locator.d.ts +3 -0
- package/dist/entities/source-locator.js +32 -0
- package/dist/entities/store.d.ts +75 -0
- package/dist/entities/store.js +465 -0
- package/dist/entities/types.d.ts +162 -0
- package/dist/entities/types.js +30 -0
- package/dist/index.d.ts +47 -2
- package/dist/index.js +66 -25
- package/dist/mama-api.d.ts +22 -1
- package/dist/mama-api.js +272 -64
- package/dist/memory/api.d.ts +28 -1
- package/dist/memory/api.js +293 -31
- package/dist/memory/types.d.ts +11 -2
- package/dist/search/feedback-store.d.ts +59 -0
- package/dist/search/feedback-store.js +211 -0
- package/dist/search/question-type.d.ts +5 -0
- package/dist/search/question-type.js +41 -0
- package/dist/search/ranker-features.d.ts +23 -0
- package/dist/search/ranker-features.js +104 -0
- package/dist/search/ranker-rescore.d.ts +31 -0
- package/dist/search/ranker-rescore.js +226 -0
- package/dist/search/ranker-trainer.d.ts +94 -0
- package/dist/search/ranker-trainer.js +860 -0
- package/dist/test-utils.d.ts +14 -0
- package/dist/test-utils.js +52 -0
- package/package.json +21 -3
|
@@ -0,0 +1,99 @@
|
|
|
1
|
+
CREATE TABLE IF NOT EXISTS entity_nodes (
|
|
2
|
+
id TEXT PRIMARY KEY,
|
|
3
|
+
kind TEXT NOT NULL CHECK (kind IN ('project', 'person', 'organization', 'work_item')),
|
|
4
|
+
preferred_label TEXT NOT NULL,
|
|
5
|
+
status TEXT NOT NULL DEFAULT 'active' CHECK (status IN ('active', 'merged', 'archived')),
|
|
6
|
+
scope_kind TEXT CHECK (scope_kind IN ('project', 'channel', 'user', 'global')),
|
|
7
|
+
scope_id TEXT,
|
|
8
|
+
merged_into TEXT,
|
|
9
|
+
created_at INTEGER NOT NULL DEFAULT (unixepoch() * 1000),
|
|
10
|
+
updated_at INTEGER NOT NULL DEFAULT (unixepoch() * 1000),
|
|
11
|
+
FOREIGN KEY (merged_into) REFERENCES entity_nodes(id),
|
|
12
|
+
CHECK ((scope_kind = 'global' AND scope_id IS NULL) OR (scope_kind != 'global'))
|
|
13
|
+
);
|
|
14
|
+
|
|
15
|
+
CREATE TABLE IF NOT EXISTS entity_aliases (
|
|
16
|
+
id TEXT PRIMARY KEY,
|
|
17
|
+
entity_id TEXT NOT NULL,
|
|
18
|
+
label TEXT NOT NULL,
|
|
19
|
+
normalized_label TEXT NOT NULL,
|
|
20
|
+
lang TEXT,
|
|
21
|
+
script TEXT,
|
|
22
|
+
label_type TEXT NOT NULL CHECK (label_type IN ('pref', 'alt', 'hidden', 'source_native')),
|
|
23
|
+
source_type TEXT NOT NULL,
|
|
24
|
+
source_ref TEXT,
|
|
25
|
+
confidence REAL,
|
|
26
|
+
status TEXT NOT NULL DEFAULT 'active' CHECK (status IN ('active', 'suppressed')),
|
|
27
|
+
created_at INTEGER NOT NULL DEFAULT (unixepoch() * 1000),
|
|
28
|
+
FOREIGN KEY (entity_id) REFERENCES entity_nodes(id) ON DELETE CASCADE
|
|
29
|
+
);
|
|
30
|
+
|
|
31
|
+
CREATE TABLE IF NOT EXISTS entity_observations (
|
|
32
|
+
id TEXT PRIMARY KEY,
|
|
33
|
+
entity_kind_hint TEXT CHECK (entity_kind_hint IN ('project', 'person', 'organization', 'work_item')),
|
|
34
|
+
surface_form TEXT NOT NULL,
|
|
35
|
+
normalized_form TEXT NOT NULL,
|
|
36
|
+
lang TEXT,
|
|
37
|
+
script TEXT,
|
|
38
|
+
context_summary TEXT,
|
|
39
|
+
related_surface_forms TEXT NOT NULL DEFAULT '[]',
|
|
40
|
+
timestamp_observed INTEGER,
|
|
41
|
+
scope_kind TEXT CHECK (scope_kind IN ('project', 'channel', 'user', 'global')),
|
|
42
|
+
scope_id TEXT,
|
|
43
|
+
extractor_version TEXT NOT NULL,
|
|
44
|
+
embedding_model_version TEXT,
|
|
45
|
+
source_connector TEXT NOT NULL,
|
|
46
|
+
source_raw_db_ref TEXT,
|
|
47
|
+
source_raw_record_id TEXT NOT NULL,
|
|
48
|
+
created_at INTEGER NOT NULL DEFAULT (unixepoch() * 1000),
|
|
49
|
+
CHECK ((scope_kind = 'global' AND scope_id IS NULL) OR (scope_kind != 'global'))
|
|
50
|
+
);
|
|
51
|
+
|
|
52
|
+
CREATE TABLE IF NOT EXISTS entity_links (
|
|
53
|
+
id TEXT PRIMARY KEY,
|
|
54
|
+
from_entity_id TEXT NOT NULL,
|
|
55
|
+
to_entity_id TEXT NOT NULL,
|
|
56
|
+
relation_type TEXT NOT NULL,
|
|
57
|
+
confidence REAL NOT NULL DEFAULT 0.5,
|
|
58
|
+
source_basis TEXT NOT NULL,
|
|
59
|
+
created_at INTEGER NOT NULL DEFAULT (unixepoch() * 1000),
|
|
60
|
+
updated_at INTEGER NOT NULL DEFAULT (unixepoch() * 1000),
|
|
61
|
+
FOREIGN KEY (from_entity_id) REFERENCES entity_nodes(id) ON DELETE CASCADE,
|
|
62
|
+
FOREIGN KEY (to_entity_id) REFERENCES entity_nodes(id) ON DELETE CASCADE
|
|
63
|
+
);
|
|
64
|
+
|
|
65
|
+
CREATE TABLE IF NOT EXISTS entity_timeline_events (
|
|
66
|
+
id TEXT PRIMARY KEY,
|
|
67
|
+
entity_id TEXT NOT NULL,
|
|
68
|
+
event_type TEXT NOT NULL,
|
|
69
|
+
valid_from INTEGER,
|
|
70
|
+
valid_to INTEGER,
|
|
71
|
+
observed_at INTEGER,
|
|
72
|
+
source_ref TEXT,
|
|
73
|
+
summary TEXT NOT NULL,
|
|
74
|
+
details TEXT,
|
|
75
|
+
created_at INTEGER NOT NULL DEFAULT (unixepoch() * 1000),
|
|
76
|
+
FOREIGN KEY (entity_id) REFERENCES entity_nodes(id) ON DELETE CASCADE
|
|
77
|
+
);
|
|
78
|
+
|
|
79
|
+
CREATE INDEX IF NOT EXISTS idx_entity_nodes_kind ON entity_nodes(kind);
|
|
80
|
+
CREATE INDEX IF NOT EXISTS idx_entity_nodes_preferred_label ON entity_nodes(preferred_label);
|
|
81
|
+
CREATE INDEX IF NOT EXISTS idx_entity_nodes_scope ON entity_nodes(scope_kind, scope_id);
|
|
82
|
+
|
|
83
|
+
CREATE INDEX IF NOT EXISTS idx_entity_aliases_entity_id ON entity_aliases(entity_id);
|
|
84
|
+
CREATE INDEX IF NOT EXISTS idx_entity_aliases_normalized_label ON entity_aliases(normalized_label);
|
|
85
|
+
|
|
86
|
+
CREATE INDEX IF NOT EXISTS idx_entity_observations_normalized_label ON entity_observations(normalized_form);
|
|
87
|
+
CREATE INDEX IF NOT EXISTS idx_entity_observations_observed_at ON entity_observations(timestamp_observed);
|
|
88
|
+
CREATE INDEX IF NOT EXISTS idx_entity_observations_scope ON entity_observations(scope_kind, scope_id);
|
|
89
|
+
CREATE UNIQUE INDEX IF NOT EXISTS idx_entity_observations_source_record
|
|
90
|
+
ON entity_observations(source_connector, source_raw_record_id);
|
|
91
|
+
|
|
92
|
+
CREATE INDEX IF NOT EXISTS idx_entity_links_from ON entity_links(from_entity_id);
|
|
93
|
+
CREATE INDEX IF NOT EXISTS idx_entity_links_to ON entity_links(to_entity_id);
|
|
94
|
+
|
|
95
|
+
CREATE INDEX IF NOT EXISTS idx_entity_timeline_events_entity_id ON entity_timeline_events(entity_id);
|
|
96
|
+
CREATE INDEX IF NOT EXISTS idx_entity_timeline_events_observed_at ON entity_timeline_events(observed_at);
|
|
97
|
+
|
|
98
|
+
INSERT OR IGNORE INTO schema_version (version, description)
|
|
99
|
+
VALUES (26, 'Create canonical entity core tables');
|
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
CREATE TABLE IF NOT EXISTS entity_resolution_candidates (
|
|
2
|
+
id TEXT PRIMARY KEY,
|
|
3
|
+
candidate_kind TEXT NOT NULL CHECK (candidate_kind IN ('alias_to_entity', 'entity_to_entity', 'cluster')),
|
|
4
|
+
left_ref TEXT NOT NULL,
|
|
5
|
+
right_ref TEXT NOT NULL,
|
|
6
|
+
status TEXT NOT NULL CHECK (status IN ('pending', 'auto_merged', 'approved', 'rejected', 'deferred')),
|
|
7
|
+
score_total REAL NOT NULL DEFAULT 0,
|
|
8
|
+
score_structural REAL NOT NULL DEFAULT 0,
|
|
9
|
+
score_string REAL NOT NULL DEFAULT 0,
|
|
10
|
+
score_context REAL NOT NULL DEFAULT 0,
|
|
11
|
+
score_graph REAL NOT NULL DEFAULT 0,
|
|
12
|
+
score_embedding REAL NOT NULL DEFAULT 0,
|
|
13
|
+
rule_trace TEXT,
|
|
14
|
+
extractor_version TEXT NOT NULL,
|
|
15
|
+
embedding_model_version TEXT,
|
|
16
|
+
created_at INTEGER NOT NULL DEFAULT (unixepoch() * 1000),
|
|
17
|
+
updated_at INTEGER NOT NULL DEFAULT (unixepoch() * 1000)
|
|
18
|
+
);
|
|
19
|
+
|
|
20
|
+
CREATE TABLE IF NOT EXISTS entity_merge_actions (
|
|
21
|
+
id TEXT PRIMARY KEY,
|
|
22
|
+
action_type TEXT NOT NULL CHECK (action_type IN ('merge', 'reject', 'defer', 'split')),
|
|
23
|
+
source_entity_id TEXT,
|
|
24
|
+
target_entity_id TEXT,
|
|
25
|
+
candidate_id TEXT,
|
|
26
|
+
actor_type TEXT NOT NULL CHECK (actor_type IN ('system', 'user', 'agent')),
|
|
27
|
+
actor_id TEXT,
|
|
28
|
+
reason TEXT NOT NULL,
|
|
29
|
+
evidence_json TEXT NOT NULL,
|
|
30
|
+
created_at INTEGER NOT NULL DEFAULT (unixepoch() * 1000),
|
|
31
|
+
FOREIGN KEY (source_entity_id) REFERENCES entity_nodes(id) ON DELETE SET NULL,
|
|
32
|
+
FOREIGN KEY (target_entity_id) REFERENCES entity_nodes(id) ON DELETE SET NULL,
|
|
33
|
+
FOREIGN KEY (candidate_id) REFERENCES entity_resolution_candidates(id) ON DELETE SET NULL
|
|
34
|
+
);
|
|
35
|
+
|
|
36
|
+
CREATE INDEX IF NOT EXISTS idx_entity_candidates_status_score
|
|
37
|
+
ON entity_resolution_candidates(status, score_total DESC, created_at DESC);
|
|
38
|
+
CREATE INDEX IF NOT EXISTS idx_entity_merge_actions_candidate_id
|
|
39
|
+
ON entity_merge_actions(candidate_id);
|
|
40
|
+
CREATE INDEX IF NOT EXISTS idx_entity_merge_actions_source_target
|
|
41
|
+
ON entity_merge_actions(source_entity_id, target_entity_id);
|
|
42
|
+
|
|
43
|
+
INSERT OR IGNORE INTO schema_version (version, description)
|
|
44
|
+
VALUES (27, 'Create canonical entity review support tables');
|
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
CREATE TABLE IF NOT EXISTS entity_audit_runs (
|
|
2
|
+
id TEXT PRIMARY KEY,
|
|
3
|
+
status TEXT NOT NULL CHECK (status IN ('running', 'complete', 'failed', 'timeout')),
|
|
4
|
+
baseline_run_id TEXT,
|
|
5
|
+
classification TEXT CHECK (classification IN ('improved', 'stable', 'regressed', 'inconclusive')),
|
|
6
|
+
metric_summary_json TEXT,
|
|
7
|
+
reason TEXT,
|
|
8
|
+
created_at INTEGER NOT NULL DEFAULT (unixepoch() * 1000),
|
|
9
|
+
completed_at INTEGER,
|
|
10
|
+
FOREIGN KEY (baseline_run_id) REFERENCES entity_audit_runs(id) ON DELETE SET NULL
|
|
11
|
+
);
|
|
12
|
+
|
|
13
|
+
CREATE UNIQUE INDEX IF NOT EXISTS entity_audit_runs_single_running
|
|
14
|
+
ON entity_audit_runs(status)
|
|
15
|
+
WHERE status = 'running';
|
|
16
|
+
|
|
17
|
+
CREATE INDEX IF NOT EXISTS idx_entity_audit_runs_created_at
|
|
18
|
+
ON entity_audit_runs(created_at DESC);
|
|
19
|
+
|
|
20
|
+
CREATE TABLE IF NOT EXISTS entity_audit_metrics (
|
|
21
|
+
run_id TEXT NOT NULL,
|
|
22
|
+
metric_name TEXT NOT NULL,
|
|
23
|
+
metric_value REAL NOT NULL,
|
|
24
|
+
metric_meta_json TEXT,
|
|
25
|
+
created_at INTEGER NOT NULL DEFAULT (unixepoch() * 1000),
|
|
26
|
+
PRIMARY KEY (run_id, metric_name),
|
|
27
|
+
FOREIGN KEY (run_id) REFERENCES entity_audit_runs(id) ON DELETE CASCADE
|
|
28
|
+
);
|
|
29
|
+
|
|
30
|
+
CREATE TABLE IF NOT EXISTS entity_audit_findings (
|
|
31
|
+
id TEXT PRIMARY KEY,
|
|
32
|
+
run_id TEXT NOT NULL,
|
|
33
|
+
finding_kind TEXT NOT NULL,
|
|
34
|
+
severity TEXT NOT NULL CHECK (severity IN ('info', 'warn', 'critical')),
|
|
35
|
+
summary TEXT NOT NULL,
|
|
36
|
+
details_json TEXT,
|
|
37
|
+
created_at INTEGER NOT NULL DEFAULT (unixepoch() * 1000),
|
|
38
|
+
FOREIGN KEY (run_id) REFERENCES entity_audit_runs(id) ON DELETE CASCADE
|
|
39
|
+
);
|
|
40
|
+
|
|
41
|
+
CREATE INDEX IF NOT EXISTS idx_entity_audit_findings_run_id
|
|
42
|
+
ON entity_audit_findings(run_id);
|
|
43
|
+
|
|
44
|
+
INSERT OR IGNORE INTO schema_version (version, description)
|
|
45
|
+
VALUES (28, 'Create entity benchmark and audit run storage');
|
|
@@ -0,0 +1,60 @@
|
|
|
1
|
+
ALTER TABLE entity_observations
|
|
2
|
+
ADD COLUMN observation_type TEXT NOT NULL DEFAULT 'generic'
|
|
3
|
+
CHECK (observation_type IN ('generic', 'author', 'channel'));
|
|
4
|
+
|
|
5
|
+
UPDATE entity_observations
|
|
6
|
+
SET source_raw_db_ref = ''
|
|
7
|
+
WHERE source_raw_db_ref IS NULL;
|
|
8
|
+
|
|
9
|
+
DROP INDEX IF EXISTS idx_entity_observations_source_record;
|
|
10
|
+
|
|
11
|
+
CREATE UNIQUE INDEX IF NOT EXISTS idx_entity_observations_source_record
|
|
12
|
+
ON entity_observations(
|
|
13
|
+
source_connector,
|
|
14
|
+
source_raw_db_ref,
|
|
15
|
+
source_raw_record_id,
|
|
16
|
+
observation_type
|
|
17
|
+
);
|
|
18
|
+
|
|
19
|
+
CREATE TRIGGER IF NOT EXISTS trg_entity_nodes_scope_guard_insert
|
|
20
|
+
BEFORE INSERT ON entity_nodes
|
|
21
|
+
WHEN (
|
|
22
|
+
(NEW.scope_kind = 'global' AND NEW.scope_id IS NOT NULL)
|
|
23
|
+
OR (NEW.scope_kind IS NOT NULL AND NEW.scope_kind != 'global' AND NEW.scope_id IS NULL)
|
|
24
|
+
)
|
|
25
|
+
BEGIN
|
|
26
|
+
SELECT RAISE(ABORT, 'entity_nodes scope_id invalid for scope_kind');
|
|
27
|
+
END;
|
|
28
|
+
|
|
29
|
+
CREATE TRIGGER IF NOT EXISTS trg_entity_nodes_scope_guard_update
|
|
30
|
+
BEFORE UPDATE ON entity_nodes
|
|
31
|
+
WHEN (
|
|
32
|
+
(NEW.scope_kind = 'global' AND NEW.scope_id IS NOT NULL)
|
|
33
|
+
OR (NEW.scope_kind IS NOT NULL AND NEW.scope_kind != 'global' AND NEW.scope_id IS NULL)
|
|
34
|
+
)
|
|
35
|
+
BEGIN
|
|
36
|
+
SELECT RAISE(ABORT, 'entity_nodes scope_id invalid for scope_kind');
|
|
37
|
+
END;
|
|
38
|
+
|
|
39
|
+
CREATE TRIGGER IF NOT EXISTS trg_entity_observations_scope_guard_insert
|
|
40
|
+
BEFORE INSERT ON entity_observations
|
|
41
|
+
WHEN (
|
|
42
|
+
(NEW.scope_kind = 'global' AND NEW.scope_id IS NOT NULL)
|
|
43
|
+
OR (NEW.scope_kind IS NOT NULL AND NEW.scope_kind != 'global' AND NEW.scope_id IS NULL)
|
|
44
|
+
)
|
|
45
|
+
BEGIN
|
|
46
|
+
SELECT RAISE(ABORT, 'entity_observations scope_id invalid for scope_kind');
|
|
47
|
+
END;
|
|
48
|
+
|
|
49
|
+
CREATE TRIGGER IF NOT EXISTS trg_entity_observations_scope_guard_update
|
|
50
|
+
BEFORE UPDATE ON entity_observations
|
|
51
|
+
WHEN (
|
|
52
|
+
(NEW.scope_kind = 'global' AND NEW.scope_id IS NOT NULL)
|
|
53
|
+
OR (NEW.scope_kind IS NOT NULL AND NEW.scope_kind != 'global' AND NEW.scope_id IS NULL)
|
|
54
|
+
)
|
|
55
|
+
BEGIN
|
|
56
|
+
SELECT RAISE(ABORT, 'entity_observations scope_id invalid for scope_kind');
|
|
57
|
+
END;
|
|
58
|
+
|
|
59
|
+
INSERT OR IGNORE INTO schema_version (version, description)
|
|
60
|
+
VALUES (29, 'Extend entity observations with observation type and scope guards');
|