@@ -165,6 +165,309 @@ ADD CONSTRAINT system_inventory_id
165165 FOREIGN KEY (rh_account_id, system_id)
166166 REFERENCES system_inventory (rh_account_id, id);
167167
168+ -- UPDATE FUNCTIONS
169+ CREATE OR REPLACE FUNCTION on_system_update ()
170+ -- this trigger updates advisory_account_data when server changes its stale flag
171+ RETURNS TRIGGER
172+ AS
173+ $system_update$
174+ DECLARE
175+ was_counted BOOLEAN ;
176+ should_count BOOLEAN ;
177+ change INT ;
178+ BEGIN
179+ -- Ignore not yet evaluated systems
180+ IF TG_OP != ' UPDATE' OR NOT EXISTS (
181+ SELECT 1
182+ FROM system_patch
183+ WHERE system_id = NEW .id
184+ AND rh_account_id = NEW .rh_account_id
185+ AND last_evaluation IS NOT NULL
186+ ) THEN
187+ RETURN NEW;
188+ END IF;
189+
190+ was_counted := OLD .stale = FALSE;
191+ should_count := NEW .stale = FALSE;
192+
193+ -- Determine what change we are performing
194+ IF was_counted and NOT should_count THEN
195+ change := - 1 ;
196+ ELSIF NOT was_counted AND should_count THEN
197+ change := 1 ;
198+ ELSE
199+ -- No change
200+ RETURN NEW;
201+ END IF;
202+
203+ -- insert/update advisories linked to the server
204+ INSERT
205+ INTO advisory_account_data (advisory_id, rh_account_id, systems_installable, systems_applicable)
206+ SELECT sa .advisory_id , NEW .rh_account_id ,
207+ case when sa .status_id = 0 then change else 0 end as systems_installable,
208+ change as systems_applicable
209+ FROM system_advisories sa
210+ WHERE sa .system_id = NEW .id AND sa .rh_account_id = NEW .rh_account_id
211+ ORDER BY sa .advisory_id
212+ ON CONFLICT (advisory_id, rh_account_id) DO UPDATE
213+ SET systems_installable = advisory_account_data .systems_installable + EXCLUDED .systems_installable ,
214+ systems_applicable = advisory_account_data .systems_applicable + EXCLUDED .systems_applicable ;
215+ RETURN NEW;
216+ END;
217+ $system_update$ LANGUAGE plpgsql;
218+
219+ CREATE OR REPLACE FUNCTION refresh_advisory_caches_multi (advisory_ids_in INTEGER [] DEFAULT NULL ,
220+ rh_account_id_in INTEGER DEFAULT NULL )
221+ RETURNS VOID AS
222+ $refresh_advisory$
223+ BEGIN
224+ -- Lock rows
225+ PERFORM aad .rh_account_id , aad .advisory_id
226+ FROM advisory_account_data aad
227+ WHERE (aad .advisory_id = ANY (advisory_ids_in) OR advisory_ids_in IS NULL )
228+ AND (aad .rh_account_id = rh_account_id_in OR rh_account_id_in IS NULL )
229+ FOR UPDATE OF aad;
230+
231+ WITH current_counts AS (
232+ SELECT sa .advisory_id , sa .rh_account_id ,
233+ count (sa.* ) filter (where sa .status_id = 0 ) as systems_installable,
234+ count (sa.* ) as systems_applicable
235+ FROM system_advisories sa
236+ JOIN system_inventory si
237+ ON sa .rh_account_id = si .rh_account_id AND sa .system_id = si .id
238+ JOIN system_patch sp
239+ ON si .id = sp .system_id AND sp .rh_account_id = si .rh_account_id
240+ WHERE sp .last_evaluation IS NOT NULL
241+ AND si .stale = FALSE
242+ AND (sa .advisory_id = ANY (advisory_ids_in) OR advisory_ids_in IS NULL )
243+ AND (si .rh_account_id = rh_account_id_in OR rh_account_id_in IS NULL )
244+ GROUP BY sa .advisory_id , sa .rh_account_id
245+ ),
246+ upserted AS (
247+ INSERT INTO advisory_account_data (advisory_id, rh_account_id, systems_installable, systems_applicable)
248+ SELECT advisory_id, rh_account_id, systems_installable, systems_applicable
249+ FROM current_counts
250+ ON CONFLICT (advisory_id, rh_account_id) DO UPDATE SET
251+ systems_installable = EXCLUDED .systems_installable ,
252+ systems_applicable = EXCLUDED .systems_applicable
253+ )
254+ DELETE FROM advisory_account_data
255+ WHERE (advisory_id, rh_account_id) NOT IN (SELECT advisory_id, rh_account_id FROM current_counts)
256+ AND (advisory_id = ANY (advisory_ids_in) OR advisory_ids_in IS NULL )
257+ AND (rh_account_id = rh_account_id_in OR rh_account_id_in IS NULL );
258+ END;
259+ $refresh_advisory$ language plpgsql;
260+
261+ CREATE OR REPLACE FUNCTION refresh_system_caches (system_id_in BIGINT DEFAULT NULL ,
262+ rh_account_id_in INTEGER DEFAULT NULL )
263+ RETURNS INTEGER AS
264+ $refresh_system$
265+ DECLARE
266+ COUNT INTEGER ;
267+ BEGIN
268+ WITH system_advisories_count AS (
269+ SELECT si .rh_account_id , si .id ,
270+ COUNT (advisory_id) FILTER (WHERE sa .status_id = 0 ) as installable_total,
271+ COUNT (advisory_id) FILTER (WHERE am .advisory_type_id = 1 AND sa .status_id = 0 ) AS installable_enhancement,
272+ COUNT (advisory_id) FILTER (WHERE am .advisory_type_id = 2 AND sa .status_id = 0 ) AS installable_bugfix,
273+ COUNT (advisory_id) FILTER (WHERE am .advisory_type_id = 3 AND sa .status_id = 0 ) as installable_security,
274+ COUNT (advisory_id) as applicable_total,
275+ COUNT (advisory_id) FILTER (WHERE am .advisory_type_id = 1 ) AS applicable_enhancement,
276+ COUNT (advisory_id) FILTER (WHERE am .advisory_type_id = 2 ) AS applicable_bugfix,
277+ COUNT (advisory_id) FILTER (WHERE am .advisory_type_id = 3 ) as applicable_security
278+ FROM system_inventory si -- this table ensures even systems without any system_advisories are in results
279+ LEFT JOIN system_advisories sa
280+ ON si .rh_account_id = sa .rh_account_id AND si .id = sa .system_id
281+ LEFT JOIN advisory_metadata am
282+ ON sa .advisory_id = am .id
283+ WHERE (si .id = system_id_in OR system_id_in IS NULL )
284+ AND (si .rh_account_id = rh_account_id_in OR rh_account_id_in IS NULL )
285+ GROUP BY si .rh_account_id , si .id
286+ ORDER BY si .rh_account_id , si .id
287+ )
288+ UPDATE system_patch sp
289+ SET installable_advisory_count_cache = sc .installable_total ,
290+ installable_advisory_enh_count_cache = sc .installable_enhancement ,
291+ installable_advisory_bug_count_cache = sc .installable_bugfix ,
292+ installable_advisory_sec_count_cache = sc .installable_security ,
293+ applicable_advisory_count_cache = sc .applicable_total ,
294+ applicable_advisory_enh_count_cache = sc .applicable_enhancement ,
295+ applicable_advisory_bug_count_cache = sc .applicable_bugfix ,
296+ applicable_advisory_sec_count_cache = sc .applicable_security
297+ FROM system_advisories_count sc
298+ WHERE sp .rh_account_id = sc .rh_account_id AND sp .system_id = sc .id
299+ AND (sp .system_id = system_id_in OR system_id_in IS NULL )
300+ AND (sp .rh_account_id = rh_account_id_in OR rh_account_id_in IS NULL );
301+
302+ GET DIAGNOSTICS COUNT = ROW_COUNT;
303+ RETURN COUNT;
304+ END;
305+ $refresh_system$ LANGUAGE plpgsql;
306+
307+ CREATE OR REPLACE FUNCTION refresh_system_cached_counts (inventory_id_in varchar )
308+ RETURNS void AS
309+ $refresh_system_cached_counts$
310+ DECLARE
311+ system_id int ;
312+ BEGIN
313+
314+ SELECT id FROM system_inventory WHERE inventory_id = inventory_id_in INTO system_id;
315+
316+ PERFORM refresh_system_caches(system_id, NULL );
317+ END;
318+ $refresh_system_cached_counts$
319+ LANGUAGE ' plpgsql' ;
320+
321+ CREATE OR REPLACE FUNCTION delete_system (inventory_id_in uuid)
322+ RETURNS TABLE
323+ (
324+ deleted_inventory_id uuid
325+ )
326+ AS
327+ $delete_system$
328+ DECLARE
329+ v_system_id INT ;
330+ v_account_id INT ;
331+ BEGIN
332+ -- opt out to refresh cache and then delete
333+ SELECT id, rh_account_id
334+ FROM system_inventory
335+ WHERE inventory_id = inventory_id_in
336+ LIMIT 1
337+ FOR UPDATE OF system_inventory
338+ INTO v_system_id, v_account_id;
339+
340+ IF v_system_id IS NULL OR v_account_id IS NULL THEN
341+ RAISE NOTICE ' Not found' ;
342+ RETURN;
343+ END IF;
344+
345+ UPDATE system_inventory
346+ SET stale = true
347+ WHERE rh_account_id = v_account_id
348+ AND id = v_system_id;
349+
350+ DELETE
351+ FROM system_advisories
352+ WHERE rh_account_id = v_account_id
353+ AND system_id = v_system_id;
354+
355+ DELETE
356+ FROM system_repo
357+ WHERE rh_account_id = v_account_id
358+ AND system_id = v_system_id;
359+
360+ DELETE
361+ FROM system_package2
362+ WHERE rh_account_id = v_account_id
363+ AND system_id = v_system_id;
364+
365+ DELETE
366+ FROM system_patch
367+ WHERE rh_account_id = v_account_id
368+ AND system_id = v_system_id;
369+
370+ RETURN QUERY DELETE FROM system_inventory
371+ WHERE rh_account_id = v_account_id AND
372+ id = v_system_id
373+ RETURNING inventory_id;
374+ END;
375+ $delete_system$ LANGUAGE ' plpgsql' ;
376+
377+ CREATE OR REPLACE FUNCTION delete_systems (inventory_ids UUID[])
378+ RETURNS INTEGER
379+ AS
380+ $$
381+ DECLARE
382+ tmp_cnt INTEGER ;
383+ BEGIN
384+
385+ WITH systems as (
386+ SELECT rh_account_id, id
387+ FROM system_inventory
388+ WHERE inventory_id = ANY (inventory_ids)
389+ ORDER BY rh_account_id, id FOR UPDATE OF system_inventory),
390+ marked as (
391+ UPDATE system_inventory sp
392+ SET stale = true
393+ WHERE (rh_account_id, id) in (select rh_account_id, id from systems)
394+ ),
395+ advisories as (
396+ DELETE
397+ FROM system_advisories
398+ WHERE (rh_account_id, system_id) in (select rh_account_id, id from systems)
399+ ),
400+ repos as (
401+ DELETE
402+ FROM system_repo
403+ WHERE (rh_account_id, system_id) in (select rh_account_id, id from systems)
404+ ),
405+ packages2 as (
406+ DELETE
407+ FROM system_package2
408+ WHERE (rh_account_id, system_id) in (select rh_account_id, id from systems)
409+ ),
410+ patch_systems as (
411+ DELETE
412+ FROM system_patch
413+ WHERE (rh_account_id, system_id) in (select rh_account_id, id from systems)
414+ ),
415+ deleted as (
416+ DELETE
417+ FROM system_inventory
418+ WHERE (rh_account_id, id) in (select rh_account_id, id from systems)
419+ RETURNING id
420+ )
421+ SELECT count (* )
422+ FROM deleted
423+ INTO tmp_cnt;
424+
425+ RETURN tmp_cnt;
426+ END
427+ $$ LANGUAGE plpgsql;
428+
429+ CREATE OR REPLACE FUNCTION delete_culled_systems (delete_limit INTEGER )
430+ RETURNS INTEGER
431+ AS
432+ $fun$
433+ DECLARE
434+ ids UUID[];
435+ BEGIN
436+ ids := ARRAY(
437+ SELECT inventory_id
438+ FROM system_inventory
439+ WHERE culled_timestamp < now()
440+ ORDER BY id
441+ LIMIT delete_limit
442+ );
443+ return delete_systems(ids);
444+ END;
445+ $fun$ LANGUAGE plpgsql;
446+
447+ CREATE OR REPLACE FUNCTION mark_stale_systems (mark_limit integer )
448+ RETURNS INTEGER
449+ AS
450+ $fun$
451+ DECLARE
452+ marked integer ;
453+ BEGIN
454+ WITH ids AS (
455+ SELECT rh_account_id, id, stale_warning_timestamp < now() as expired
456+ FROM system_inventory
457+ WHERE stale != (stale_warning_timestamp < now())
458+ ORDER BY rh_account_id, id FOR UPDATE OF system_inventory
459+ LIMIT mark_limit
460+ )
461+ UPDATE system_inventory si
462+ SET stale = ids .expired
463+ FROM ids
464+ WHERE si .rh_account_id = ids .rh_account_id
465+ AND si .id = ids .id ;
466+ GET DIAGNOSTICS marked = ROW_COUNT;
467+ RETURN marked;
468+ END;
469+ $fun$ LANGUAGE plpgsql;
470+
168471
169472
170473-- system_patch
0 commit comments