|
Bogdan Timofte
authored
2 weeks ago
|
1
|
-- autoSMART Database Schema v2.0 — Normalizare SMART parameters din JSONB
|
|
|
2
|
-- Version: 2.0
|
|
|
3
|
-- Description: Replaces blob-based JSONB storage with structured EAV model
|
|
|
4
|
-- Date: 2026-05-20
|
|
|
5
|
-- This schema REPLACES smart_readings with smart_collection_events + smart_param_values
|
|
|
6
|
-- Backward compat: v_smart_readings_compat view emulates old schema
|
|
|
7
|
|
|
|
8
|
-- ============================================================================
|
|
|
9
|
-- EXTENSIONS
|
|
|
10
|
-- ============================================================================
|
|
|
11
|
|
|
|
12
|
CREATE EXTENSION IF NOT EXISTS "uuid-ossp";
|
|
|
13
|
CREATE EXTENSION IF NOT EXISTS "btree_gin";
|
|
|
14
|
|
|
|
15
|
-- ============================================================================
|
|
|
16
|
-- TIMESTAMP TRIGGER (reusable)
|
|
|
17
|
-- ============================================================================
|
|
|
18
|
|
|
|
19
|
CREATE OR REPLACE FUNCTION update_timestamp() RETURNS TRIGGER AS $$
|
|
|
20
|
BEGIN
|
|
|
21
|
NEW.updated_at = NOW();
|
|
|
22
|
RETURN NEW;
|
|
|
23
|
END;
|
|
|
24
|
$$ LANGUAGE plpgsql;
|
|
|
25
|
|
|
|
26
|
-- ============================================================================
|
|
|
27
|
-- SMART PARAMETER CATALOG — Registru parametri cu auto-discovery
|
|
|
28
|
-- ============================================================================
|
|
|
29
|
|
|
|
30
|
CREATE TABLE smart_param_catalog (
|
|
|
31
|
id SERIAL PRIMARY KEY,
|
|
|
32
|
param_name VARCHAR(100) NOT NULL,
|
|
|
33
|
param_id_ata INTEGER,
|
|
|
34
|
device_type VARCHAR(20) DEFAULT 'any',
|
|
|
35
|
unit VARCHAR(20),
|
|
|
36
|
description TEXT,
|
|
|
37
|
warning_threshold NUMERIC,
|
|
|
38
|
critical_threshold NUMERIC,
|
|
|
39
|
health_weight NUMERIC DEFAULT 1.0,
|
|
|
40
|
is_critical BOOLEAN DEFAULT false,
|
|
|
41
|
lower_is_better BOOLEAN DEFAULT true,
|
|
|
42
|
track_raw_value BOOLEAN DEFAULT true,
|
|
|
43
|
track_normalized BOOLEAN DEFAULT false,
|
|
|
44
|
first_seen TIMESTAMPTZ DEFAULT NOW(),
|
|
|
45
|
created_at TIMESTAMPTZ DEFAULT NOW(),
|
|
|
46
|
updated_at TIMESTAMPTZ DEFAULT NOW(),
|
|
|
47
|
|
|
|
48
|
CONSTRAINT uq_param_name UNIQUE (param_name)
|
|
|
49
|
);
|
|
|
50
|
|
|
|
51
|
CREATE INDEX idx_param_catalog_name ON smart_param_catalog(param_name);
|
|
|
52
|
CREATE INDEX idx_param_catalog_critical ON smart_param_catalog(is_critical) WHERE is_critical = true;
|
|
|
53
|
|
|
|
54
|
CREATE TRIGGER update_param_catalog_timestamp
|
|
|
55
|
BEFORE UPDATE ON smart_param_catalog
|
|
|
56
|
FOR EACH ROW EXECUTE FUNCTION update_timestamp();
|
|
|
57
|
|
|
|
58
|
-- ============================================================================
|
|
|
59
|
-- SMART COLLECTION EVENTS — Metadate per-colectare (înlocuiește smart_readings)
|
|
|
60
|
-- ============================================================================
|
|
|
61
|
|
|
|
62
|
CREATE TABLE smart_collection_events (
|
|
|
63
|
id BIGSERIAL PRIMARY KEY,
|
|
|
64
|
hdd_id INTEGER NOT NULL REFERENCES hdd_inventory(id),
|
|
|
65
|
serial_number VARCHAR(100) NOT NULL,
|
|
|
66
|
node_id VARCHAR(50) NOT NULL,
|
|
|
67
|
collected_at TIMESTAMPTZ NOT NULL DEFAULT NOW(),
|
|
|
68
|
collection_ok BOOLEAN DEFAULT true,
|
|
|
69
|
temperature SMALLINT,
|
|
|
70
|
checksum VARCHAR(64),
|
|
|
71
|
param_count SMALLINT,
|
|
|
72
|
notes TEXT
|
|
|
73
|
);
|
|
|
74
|
|
|
|
75
|
CREATE INDEX idx_sce_hdd_id_time ON smart_collection_events(hdd_id, collected_at DESC);
|
|
|
76
|
CREATE INDEX idx_sce_serial ON smart_collection_events(serial_number);
|
|
|
77
|
CREATE INDEX idx_sce_node_time ON smart_collection_events(node_id, collected_at DESC);
|
|
|
78
|
CREATE INDEX idx_sce_collected_at ON smart_collection_events(collected_at DESC);
|
|
|
79
|
CREATE INDEX idx_sce_checksum ON smart_collection_events(checksum) WHERE checksum IS NOT NULL;
|
|
|
80
|
|
|
|
81
|
-- ============================================================================
|
|
|
82
|
-- SMART PARAM VALUES — Tabel EAV partiționat lunar
|
|
|
83
|
-- ============================================================================
|
|
|
84
|
|
|
|
85
|
CREATE TABLE smart_param_values (
|
|
|
86
|
id BIGSERIAL,
|
|
|
87
|
event_id BIGINT NOT NULL,
|
|
|
88
|
hdd_id INTEGER NOT NULL,
|
|
|
89
|
param_id INTEGER NOT NULL REFERENCES smart_param_catalog(id),
|
|
|
90
|
collected_at TIMESTAMPTZ NOT NULL,
|
|
|
91
|
raw_value BIGINT,
|
|
|
92
|
normalized_value SMALLINT,
|
|
|
93
|
worst_value SMALLINT,
|
|
|
94
|
threshold_value SMALLINT,
|
|
|
95
|
when_failed VARCHAR(20),
|
|
|
96
|
|
|
|
97
|
PRIMARY KEY (collected_at, id)
|
|
|
98
|
) PARTITION BY RANGE (collected_at);
|
|
|
99
|
|
|
|
100
|
-- Creare partiții pentru perioada viitoare (2025-2027)
|
|
|
101
|
CREATE TABLE smart_param_values_2025_01 PARTITION OF smart_param_values
|
|
|
102
|
FOR VALUES FROM ('2025-01-01') TO ('2025-02-01');
|
|
|
103
|
CREATE TABLE smart_param_values_2025_02 PARTITION OF smart_param_values
|
|
|
104
|
FOR VALUES FROM ('2025-02-01') TO ('2025-03-01');
|
|
|
105
|
CREATE TABLE smart_param_values_2025_03 PARTITION OF smart_param_values
|
|
|
106
|
FOR VALUES FROM ('2025-03-01') TO ('2025-04-01');
|
|
|
107
|
CREATE TABLE smart_param_values_2025_04 PARTITION OF smart_param_values
|
|
|
108
|
FOR VALUES FROM ('2025-04-01') TO ('2025-05-01');
|
|
|
109
|
CREATE TABLE smart_param_values_2025_05 PARTITION OF smart_param_values
|
|
|
110
|
FOR VALUES FROM ('2025-05-01') TO ('2025-06-01');
|
|
|
111
|
CREATE TABLE smart_param_values_2025_06 PARTITION OF smart_param_values
|
|
|
112
|
FOR VALUES FROM ('2025-06-01') TO ('2025-07-01');
|
|
|
113
|
CREATE TABLE smart_param_values_2025_07 PARTITION OF smart_param_values
|
|
|
114
|
FOR VALUES FROM ('2025-07-01') TO ('2025-08-01');
|
|
|
115
|
CREATE TABLE smart_param_values_2025_08 PARTITION OF smart_param_values
|
|
|
116
|
FOR VALUES FROM ('2025-08-01') TO ('2025-09-01');
|
|
|
117
|
CREATE TABLE smart_param_values_2025_09 PARTITION OF smart_param_values
|
|
|
118
|
FOR VALUES FROM ('2025-09-01') TO ('2025-10-01');
|
|
|
119
|
CREATE TABLE smart_param_values_2025_10 PARTITION OF smart_param_values
|
|
|
120
|
FOR VALUES FROM ('2025-10-01') TO ('2025-11-01');
|
|
|
121
|
CREATE TABLE smart_param_values_2025_11 PARTITION OF smart_param_values
|
|
|
122
|
FOR VALUES FROM ('2025-11-01') TO ('2025-12-01');
|
|
|
123
|
CREATE TABLE smart_param_values_2025_12 PARTITION OF smart_param_values
|
|
|
124
|
FOR VALUES FROM ('2025-12-01') TO ('2026-01-01');
|
|
|
125
|
CREATE TABLE smart_param_values_2026_01 PARTITION OF smart_param_values
|
|
|
126
|
FOR VALUES FROM ('2026-01-01') TO ('2026-02-01');
|
|
|
127
|
CREATE TABLE smart_param_values_2026_02 PARTITION OF smart_param_values
|
|
|
128
|
FOR VALUES FROM ('2026-02-01') TO ('2026-03-01');
|
|
|
129
|
CREATE TABLE smart_param_values_2026_03 PARTITION OF smart_param_values
|
|
|
130
|
FOR VALUES FROM ('2026-03-01') TO ('2026-04-01');
|
|
|
131
|
CREATE TABLE smart_param_values_2026_04 PARTITION OF smart_param_values
|
|
|
132
|
FOR VALUES FROM ('2026-04-01') TO ('2026-05-01');
|
|
|
133
|
CREATE TABLE smart_param_values_2026_05 PARTITION OF smart_param_values
|
|
|
134
|
FOR VALUES FROM ('2026-05-01') TO ('2026-06-01');
|
|
|
135
|
CREATE TABLE smart_param_values_2026_06 PARTITION OF smart_param_values
|
|
|
136
|
FOR VALUES FROM ('2026-06-01') TO ('2026-07-01');
|
|
|
137
|
CREATE TABLE smart_param_values_2026_07 PARTITION OF smart_param_values
|
|
|
138
|
FOR VALUES FROM ('2026-07-01') TO ('2026-08-01');
|
|
|
139
|
CREATE TABLE smart_param_values_2026_08 PARTITION OF smart_param_values
|
|
|
140
|
FOR VALUES FROM ('2026-08-01') TO ('2026-09-01');
|
|
|
141
|
CREATE TABLE smart_param_values_2026_09 PARTITION OF smart_param_values
|
|
|
142
|
FOR VALUES FROM ('2026-09-01') TO ('2026-10-01');
|
|
|
143
|
CREATE TABLE smart_param_values_2026_10 PARTITION OF smart_param_values
|
|
|
144
|
FOR VALUES FROM ('2026-10-01') TO ('2026-11-01');
|
|
|
145
|
CREATE TABLE smart_param_values_2026_11 PARTITION OF smart_param_values
|
|
|
146
|
FOR VALUES FROM ('2026-11-01') TO ('2026-12-01');
|
|
|
147
|
CREATE TABLE smart_param_values_2026_12 PARTITION OF smart_param_values
|
|
|
148
|
FOR VALUES FROM ('2026-12-01') TO ('2027-01-01');
|
|
|
149
|
|
|
|
150
|
-- Partiție default pentru date neprevăzute
|
|
|
151
|
CREATE TABLE smart_param_values_default PARTITION OF smart_param_values DEFAULT;
|
|
|
152
|
|
|
|
153
|
-- Indexuri pe partiții
|
|
|
154
|
CREATE INDEX idx_spv_hdd_param_time ON smart_param_values(hdd_id, param_id, collected_at DESC);
|
|
|
155
|
CREATE INDEX idx_spv_event_id ON smart_param_values(event_id);
|
|
|
156
|
CREATE INDEX idx_spv_param_time ON smart_param_values(param_id, collected_at DESC);
|
|
|
157
|
CREATE INDEX idx_spv_critical_values ON smart_param_values(hdd_id, collected_at DESC)
|
|
|
158
|
WHERE raw_value > 0;
|
|
|
159
|
|
|
|
160
|
-- ============================================================================
|
|
|
161
|
-- VIEWS
|
|
|
162
|
-- ============================================================================
|
|
|
163
|
|
|
|
164
|
-- View 1: Ultimele valori per disc per parametru
|
|
|
165
|
CREATE VIEW v_latest_param_values AS
|
|
|
166
|
SELECT DISTINCT ON (spv.hdd_id, spv.param_id)
|
|
|
167
|
spv.hdd_id,
|
|
|
168
|
spv.param_id,
|
|
|
169
|
spc.param_name,
|
|
|
170
|
spc.unit,
|
|
|
171
|
spc.is_critical,
|
|
|
172
|
spv.raw_value,
|
|
|
173
|
spv.normalized_value,
|
|
|
174
|
spv.collected_at,
|
|
|
175
|
hi.serial_number,
|
|
|
176
|
hi.model_name,
|
|
|
177
|
hi.current_node_id
|
|
|
178
|
FROM smart_param_values spv
|
|
|
179
|
JOIN smart_param_catalog spc ON spv.param_id = spc.id
|
|
|
180
|
JOIN hdd_inventory hi ON spv.hdd_id = hi.id
|
|
|
181
|
WHERE hi.status = 'active'
|
|
|
182
|
ORDER BY spv.hdd_id, spv.param_id, spv.collected_at DESC;
|
|
|
183
|
|
|
|
184
|
-- View 2: Starea curentă a fiecărui disc
|
|
|
185
|
CREATE VIEW v_drive_health_summary AS
|
|
|
186
|
SELECT
|
|
|
187
|
hi.id AS hdd_id,
|
|
|
188
|
hi.serial_number,
|
|
|
189
|
hi.model_name,
|
|
|
190
|
hi.manufacturer,
|
|
|
191
|
hi.current_node_id,
|
|
|
192
|
hi.current_device_path,
|
|
|
193
|
hi.status,
|
|
|
194
|
hi.size_gb,
|
|
|
195
|
sce_last.collected_at AS last_collection,
|
|
|
196
|
sce_last.temperature AS last_temperature,
|
|
|
197
|
sce_last.collection_ok AS last_collection_ok,
|
|
|
198
|
EXTRACT(EPOCH FROM (NOW() - sce_last.collected_at)) / 3600 AS hours_since_collection,
|
|
|
199
|
critical_counts.params_above_zero AS critical_params_triggered,
|
|
|
200
|
pred.risk_level,
|
|
|
201
|
pred.failure_probability,
|
|
|
202
|
pred.predicted_failure_date
|
|
|
203
|
FROM hdd_inventory hi
|
|
|
204
|
LEFT JOIN LATERAL (
|
|
|
205
|
SELECT collected_at, temperature, collection_ok
|
|
|
206
|
FROM smart_collection_events
|
|
|
207
|
WHERE hdd_id = hi.id
|
|
|
208
|
ORDER BY collected_at DESC
|
|
|
209
|
LIMIT 1
|
|
|
210
|
) sce_last ON true
|
|
|
211
|
LEFT JOIN LATERAL (
|
|
|
212
|
SELECT COUNT(*) AS params_above_zero
|
|
|
213
|
FROM smart_param_values spv
|
|
|
214
|
JOIN smart_param_catalog spc ON spv.param_id = spc.id
|
|
|
215
|
WHERE spv.hdd_id = hi.id
|
|
|
216
|
AND spc.is_critical = true
|
|
|
217
|
AND spv.raw_value > 0
|
|
|
218
|
AND spv.collected_at >= COALESCE((
|
|
|
219
|
SELECT collected_at FROM smart_collection_events
|
|
|
220
|
WHERE hdd_id = hi.id ORDER BY collected_at DESC LIMIT 1
|
|
|
221
|
), NOW()) - INTERVAL '5 minutes'
|
|
|
222
|
) critical_counts ON true
|
|
|
223
|
LEFT JOIN LATERAL (
|
|
|
224
|
SELECT risk_level, failure_probability, predicted_failure_date
|
|
|
225
|
FROM predictions
|
|
|
226
|
WHERE hdd_id = hi.id
|
|
|
227
|
ORDER BY timestamp DESC
|
|
|
228
|
LIMIT 1
|
|
|
229
|
) pred ON true
|
|
|
230
|
WHERE hi.status = 'active';
|
|
|
231
|
|
|
|
232
|
-- View 3: Trending parametru specific
|
|
|
233
|
CREATE VIEW v_param_trend AS
|
|
|
234
|
SELECT
|
|
|
235
|
hi.serial_number,
|
|
|
236
|
hi.model_name,
|
|
|
237
|
hi.current_node_id,
|
|
|
238
|
spc.param_name,
|
|
|
239
|
spc.unit,
|
|
|
240
|
spc.is_critical,
|
|
|
241
|
spc.warning_threshold,
|
|
|
242
|
spc.critical_threshold,
|
|
|
243
|
spv.raw_value,
|
|
|
244
|
spv.normalized_value,
|
|
|
245
|
spv.collected_at,
|
|
|
246
|
sce.node_id AS collected_on_node,
|
|
|
247
|
sce.temperature AS drive_temp_at_collection
|
|
|
248
|
FROM smart_param_values spv
|
|
|
249
|
JOIN smart_collection_events sce ON spv.event_id = sce.id
|
|
|
250
|
JOIN smart_param_catalog spc ON spv.param_id = spc.id
|
|
|
251
|
JOIN hdd_inventory hi ON spv.hdd_id = hi.id;
|
|
|
252
|
|
|
|
253
|
-- View 4: Cluster overview
|
|
|
254
|
CREATE VIEW v_cluster_overview AS
|
|
|
255
|
SELECT
|
|
|
256
|
hi.current_node_id AS node,
|
|
|
257
|
COUNT(*) AS total_drives,
|
|
|
258
|
COUNT(*) FILTER (WHERE dhs.last_collection > NOW() - INTERVAL '1 hour') AS drives_recently_collected,
|
|
|
259
|
COUNT(*) FILTER (WHERE dhs.critical_params_triggered > 0) AS drives_with_critical_params,
|
|
|
260
|
COUNT(*) FILTER (WHERE dhs.risk_level IN ('high', 'critical')) AS drives_high_risk,
|
|
|
261
|
MAX(dhs.last_collection) AS latest_collection,
|
|
|
262
|
MIN(dhs.last_collection) AS oldest_collection
|
|
|
263
|
FROM hdd_inventory hi
|
|
|
264
|
JOIN v_drive_health_summary dhs ON hi.id = dhs.hdd_id
|
|
|
265
|
WHERE hi.status = 'active'
|
|
|
266
|
GROUP BY hi.current_node_id;
|
|
|
267
|
|
|
|
268
|
-- View 5: Compatibilitate cu codul existent (emulează smart_readings)
|
|
|
269
|
CREATE VIEW v_smart_readings_compat AS
|
|
|
270
|
SELECT
|
|
|
271
|
sce.id,
|
|
|
272
|
sce.hdd_id,
|
|
|
273
|
sce.serial_number,
|
|
|
274
|
sce.collected_at AS timestamp,
|
|
|
275
|
sce.temperature,
|
|
|
276
|
sce.node_id,
|
|
|
277
|
sce.collection_ok,
|
|
|
278
|
jsonb_object_agg(
|
|
|
279
|
COALESCE(spc.param_name, ''),
|
|
|
280
|
spv.raw_value
|
|
|
281
|
) FILTER (WHERE spc.param_name IS NOT NULL) AS parameters_json
|
|
|
282
|
FROM smart_collection_events sce
|
|
|
283
|
LEFT JOIN smart_param_values spv ON spv.event_id = sce.id
|
|
|
284
|
LEFT JOIN smart_param_catalog spc ON spv.param_id = spc.id
|
|
|
285
|
GROUP BY sce.id, sce.hdd_id, sce.serial_number, sce.collected_at, sce.temperature, sce.node_id, sce.collection_ok;
|
|
|
286
|
|
|
|
287
|
-- ============================================================================
|
|
|
288
|
-- FUNCTIONS
|
|
|
289
|
-- ============================================================================
|
|
|
290
|
|
|
|
291
|
-- Upsert parametru în catalog (auto-discovery)
|
|
|
292
|
CREATE OR REPLACE FUNCTION upsert_param_catalog(
|
|
|
293
|
p_param_name VARCHAR(100),
|
|
|
294
|
p_param_id_ata INTEGER DEFAULT NULL,
|
|
|
295
|
p_unit VARCHAR(20) DEFAULT 'count'
|
|
|
296
|
) RETURNS INTEGER AS $$
|
|
|
297
|
DECLARE
|
|
|
298
|
v_id INTEGER;
|
|
|
299
|
BEGIN
|
|
|
300
|
INSERT INTO smart_param_catalog (param_name, param_id_ata, unit, first_seen)
|
|
|
301
|
VALUES (p_param_name, p_param_id_ata, p_unit, NOW())
|
|
|
302
|
ON CONFLICT (param_name) DO UPDATE
|
|
|
303
|
SET param_id_ata = COALESCE(EXCLUDED.param_id_ata, smart_param_catalog.param_id_ata),
|
|
|
304
|
updated_at = NOW()
|
|
|
305
|
RETURNING id INTO v_id;
|
|
|
306
|
RETURN v_id;
|
|
|
307
|
END;
|
|
|
308
|
$$ LANGUAGE plpgsql;
|
|
|
309
|
|
|
|
310
|
-- Inserare atomică event + valori (înlocuiește logica de collection)
|
|
|
311
|
CREATE OR REPLACE FUNCTION insert_collection_event(
|
|
|
312
|
p_hdd_id INTEGER,
|
|
|
313
|
p_serial VARCHAR(100),
|
|
|
314
|
p_node_id VARCHAR(50),
|
|
|
315
|
p_collected_at TIMESTAMPTZ,
|
|
|
316
|
p_temperature SMALLINT,
|
|
|
317
|
p_collection_ok BOOLEAN,
|
|
|
318
|
p_checksum VARCHAR(64),
|
|
|
319
|
p_params JSONB
|
|
|
320
|
) RETURNS BIGINT AS $$
|
|
|
321
|
DECLARE
|
|
|
322
|
v_event_id BIGINT;
|
|
|
323
|
v_param_id INTEGER;
|
|
|
324
|
v_param RECORD;
|
|
|
325
|
v_count SMALLINT := 0;
|
|
|
326
|
BEGIN
|
|
|
327
|
INSERT INTO smart_collection_events
|
|
|
328
|
(hdd_id, serial_number, node_id, collected_at,
|
|
|
329
|
collection_ok, temperature, checksum, param_count)
|
|
|
330
|
VALUES
|
|
|
331
|
(p_hdd_id, p_serial, p_node_id, p_collected_at,
|
|
|
332
|
p_collection_ok, p_temperature, p_checksum, 0)
|
|
|
333
|
RETURNING id INTO v_event_id;
|
|
|
334
|
|
|
|
335
|
FOR v_param IN SELECT * FROM jsonb_each(p_params)
|
|
|
336
|
LOOP
|
|
|
337
|
v_param_id := upsert_param_catalog(
|
|
|
338
|
v_param.key,
|
|
|
339
|
(v_param.value->>'id')::INTEGER,
|
|
|
340
|
'count'
|
|
|
341
|
);
|
|
|
342
|
|
|
|
343
|
INSERT INTO smart_param_values
|
|
|
344
|
(event_id, hdd_id, param_id, collected_at,
|
|
|
345
|
raw_value, normalized_value, worst_value, threshold_value, when_failed)
|
|
|
346
|
VALUES
|
|
|
347
|
(v_event_id, p_hdd_id, v_param_id, p_collected_at,
|
|
|
348
|
(v_param.value->>'raw_value')::BIGINT,
|
|
|
349
|
(v_param.value->>'value')::SMALLINT,
|
|
|
350
|
(v_param.value->>'worst')::SMALLINT,
|
|
|
351
|
(v_param.value->>'thresh')::SMALLINT,
|
|
|
352
|
v_param.value->>'when_failed');
|
|
|
353
|
|
|
|
354
|
v_count := v_count + 1;
|
|
|
355
|
END LOOP;
|
|
|
356
|
|
|
|
357
|
UPDATE smart_collection_events SET param_count = v_count WHERE id = v_event_id;
|
|
|
358
|
|
|
|
359
|
RETURN v_event_id;
|
|
|
360
|
END;
|
|
|
361
|
$$ LANGUAGE plpgsql;
|
|
|
362
|
|
|
|
363
|
-- Creare partiție lunară (cu idempotență)
|
|
|
364
|
CREATE OR REPLACE FUNCTION create_monthly_partition(p_year INTEGER, p_month INTEGER)
|
|
|
365
|
RETURNS VOID AS $$
|
|
|
366
|
DECLARE
|
|
|
367
|
v_table_name TEXT;
|
|
|
368
|
v_start_date DATE;
|
|
|
369
|
v_end_date DATE;
|
|
|
370
|
BEGIN
|
|
|
371
|
v_table_name := format('smart_param_values_%s_%s',
|
|
|
372
|
p_year, lpad(p_month::TEXT, 2, '0'));
|
|
|
373
|
v_start_date := make_date(p_year, p_month, 1);
|
|
|
374
|
v_end_date := v_start_date + INTERVAL '1 month';
|
|
|
375
|
|
|
|
376
|
IF NOT EXISTS (
|
|
|
377
|
SELECT 1 FROM information_schema.tables
|
|
|
378
|
WHERE table_name = v_table_name AND table_schema = 'public'
|
|
|
379
|
) THEN
|
|
|
380
|
EXECUTE format(
|
|
|
381
|
'CREATE TABLE %I PARTITION OF smart_param_values
|
|
|
382
|
FOR VALUES FROM (%L) TO (%L)',
|
|
|
383
|
v_table_name, v_start_date, v_end_date
|
|
|
384
|
);
|
|
|
385
|
RAISE NOTICE 'Created partition: %', v_table_name;
|
|
|
386
|
END IF;
|
|
|
387
|
END;
|
|
|
388
|
$$ LANGUAGE plpgsql;
|
|
|
389
|
|
|
Bogdan Timofte
authored
2 weeks ago
|
390
|
-- On-demand data deletion: delete all data for a specific HDD (by serial_number)
|
|
|
391
|
-- RETENTION POLICY: On-demand only (no automatic cleanup)
|
|
|
392
|
-- Called from frontend when user requests to remove a drive from monitoring
|
|
|
393
|
CREATE OR REPLACE FUNCTION delete_hdd_data_by_serial(
|
|
|
394
|
p_serial_number VARCHAR(100),
|
|
|
395
|
p_keep_catalog BOOLEAN DEFAULT true
|
|
|
396
|
) RETURNS TABLE(
|
|
|
397
|
deleted_values BIGINT,
|
|
|
398
|
deleted_events BIGINT,
|
|
|
399
|
deleted_catalog INTEGER
|
|
|
400
|
) AS $$
|
|
Bogdan Timofte
authored
2 weeks ago
|
401
|
DECLARE
|
|
Bogdan Timofte
authored
2 weeks ago
|
402
|
v_hdd_id INTEGER;
|
|
|
403
|
v_deleted_values BIGINT := 0;
|
|
|
404
|
v_deleted_events BIGINT := 0;
|
|
|
405
|
v_deleted_catalog INTEGER := 0;
|
|
Bogdan Timofte
authored
2 weeks ago
|
406
|
BEGIN
|
|
Bogdan Timofte
authored
2 weeks ago
|
407
|
-- Get HDD ID for this serial
|
|
|
408
|
SELECT id INTO v_hdd_id FROM hdd_inventory WHERE serial_number = p_serial_number;
|
|
Bogdan Timofte
authored
2 weeks ago
|
409
|
|
|
Bogdan Timofte
authored
2 weeks ago
|
410
|
IF v_hdd_id IS NULL THEN
|
|
|
411
|
RAISE NOTICE 'Serial % not found in inventory', p_serial_number;
|
|
|
412
|
RETURN QUERY SELECT 0::BIGINT, 0::BIGINT, 0::INTEGER;
|
|
|
413
|
RETURN;
|
|
|
414
|
END IF;
|
|
|
415
|
|
|
|
416
|
-- Delete from smart_param_values (cascade via event_id FK)
|
|
|
417
|
DELETE FROM smart_param_values spv
|
|
|
418
|
WHERE event_id IN (
|
|
|
419
|
SELECT id FROM smart_collection_events
|
|
|
420
|
WHERE hdd_id = v_hdd_id
|
|
|
421
|
);
|
|
|
422
|
GET DIAGNOSTICS v_deleted_values = ROW_COUNT;
|
|
Bogdan Timofte
authored
2 weeks ago
|
423
|
|
|
Bogdan Timofte
authored
2 weeks ago
|
424
|
-- Delete from smart_collection_events
|
|
Bogdan Timofte
authored
2 weeks ago
|
425
|
DELETE FROM smart_collection_events
|
|
Bogdan Timofte
authored
2 weeks ago
|
426
|
WHERE hdd_id = v_hdd_id OR serial_number = p_serial_number;
|
|
|
427
|
GET DIAGNOSTICS v_deleted_events = ROW_COUNT;
|
|
|
428
|
|
|
|
429
|
-- Optionally delete from hdd_inventory and catalog
|
|
|
430
|
IF NOT p_keep_catalog THEN
|
|
|
431
|
DELETE FROM smart_param_catalog spc
|
|
|
432
|
WHERE NOT EXISTS (
|
|
|
433
|
SELECT 1 FROM smart_param_values
|
|
|
434
|
WHERE param_id = spc.id
|
|
|
435
|
);
|
|
|
436
|
GET DIAGNOSTICS v_deleted_catalog = ROW_COUNT;
|
|
|
437
|
|
|
|
438
|
DELETE FROM hdd_inventory WHERE id = v_hdd_id;
|
|
|
439
|
END IF;
|
|
|
440
|
|
|
|
441
|
RAISE NOTICE 'Deleted % param values, % events for serial %',
|
|
|
442
|
v_deleted_values, v_deleted_events, p_serial_number;
|
|
Bogdan Timofte
authored
2 weeks ago
|
443
|
|
|
Bogdan Timofte
authored
2 weeks ago
|
444
|
RETURN QUERY SELECT v_deleted_values, v_deleted_events, v_deleted_catalog;
|
|
Bogdan Timofte
authored
2 weeks ago
|
445
|
END;
|
|
|
446
|
$$ LANGUAGE plpgsql;
|
|
|
447
|
|
|
|
448
|
-- ============================================================================
|
|
|
449
|
-- PERMISSIONS
|
|
|
450
|
-- ============================================================================
|
|
|
451
|
|
|
|
452
|
GRANT ALL PRIVILEGES ON ALL TABLES IN SCHEMA public TO autosmart;
|
|
|
453
|
GRANT ALL PRIVILEGES ON ALL SEQUENCES IN SCHEMA public TO autosmart;
|
|
|
454
|
GRANT EXECUTE ON ALL FUNCTIONS IN SCHEMA public TO autosmart;
|
|
|
455
|
|
|
|
456
|
-- Specific grants for collections
|
|
|
457
|
GRANT SELECT, INSERT, UPDATE, DELETE ON TABLE smart_param_catalog TO autosmart;
|
|
|
458
|
GRANT SELECT, INSERT, UPDATE, DELETE ON TABLE smart_collection_events TO autosmart;
|
|
|
459
|
GRANT SELECT, INSERT, UPDATE, DELETE ON TABLE smart_param_values TO autosmart;
|
|
|
460
|
GRANT SELECT ON ALL TABLES IN SCHEMA public TO autosmart;
|
|
|
461
|
|
|
|
462
|
-- ============================================================================
|
|
|
463
|
-- FINAL MESSAGE
|
|
|
464
|
-- ============================================================================
|
|
|
465
|
|
|
|
466
|
DO $$
|
|
|
467
|
BEGIN
|
|
|
468
|
RAISE NOTICE '✅ autoSMART Schema v2.0 deployed successfully!';
|
|
|
469
|
RAISE NOTICE 'New tables: smart_param_catalog, smart_collection_events, smart_param_values (partitioned)';
|
|
|
470
|
RAISE NOTICE 'Views: v_latest_param_values, v_drive_health_summary, v_param_trend, v_cluster_overview, v_smart_readings_compat';
|
|
Bogdan Timofte
authored
2 weeks ago
|
471
|
RAISE NOTICE 'Functions: upsert_param_catalog, insert_collection_event, create_monthly_partition, delete_hdd_data_by_serial';
|
|
Bogdan Timofte
authored
2 weeks ago
|
472
|
RAISE NOTICE 'Next step: Run sql/migrate-v1-to-v2.sql to migrate existing data';
|
|
|
473
|
END $$;
|