Files
Database/INS/INS_PAC.SRC
Jos Groot Lipman 9d5b3ec37b SGGR#82865 Automatische nummering van objecten niet volmaakt
svn path=/Database/trunk/; revision=64142
2024-04-03 10:16:43 +00:00

630 lines
33 KiB
Plaintext

#ifdef INS
/*
* $Revision$
* $Id$
*/
CREATE OR REPLACE PACKAGE ins AS
FUNCTION delete_deelkoppeling( DeelKey IN NUMBER ) RETURN BOOLEAN;
FUNCTION get_description(pentityname IN VARCHAR2, pparentkey IN NUMBER, pprefix IN VARCHAR2) RETURN VARCHAR2;
FUNCTION nextdescription(pprefix IN VARCHAR2, pparentkey IN NUMBER, pseparator IN VARCHAR2 DEFAULT 'default') RETURN VARCHAR2;
PROCEDURE copyInsKenmerken(pdeel_key IN NUMBER, ptosrtdeel_key IN NUMBER);
PROCEDURE altersrtdeel(pdeel_key IN NUMBER, ptosrtdeel_key IN NUMBER);
FUNCTION sprintf (ps IN varchar2, pins_deel_key IN number) RETURN varchar2;
FUNCTION contrsprintf (ps IN varchar2, pins_deelsrtcontr_key IN NUMBER) RETURN varchar2;
FUNCTION nextcyclusdate (p_insdeel IN NUMBER, p_srtcontrole IN NUMBER, p_scenario IN NUMBER, p_steps IN NUMBER DEFAULT 0) RETURN DATE;
FUNCTION nextcyclusdatesteps (p_insdeel IN NUMBER, p_srtcontrole IN NUMBER, p_steps IN NUMBER DEFAULT 1) RETURN NUMBER;
PROCEDURE setinspectstatus (pdlsrtcontrkey IN NUMBER, pstatus IN NUMBER, puserkey IN NUMBER);
FUNCTION state_compare (str1 IN VARCHAR, str2 IN VARCHAR) RETURN NUMBER;
FUNCTION state_diff (str1 IN VARCHAR, str2 IN VARCHAR) RETURN NUMBER;
FUNCTION state_thresholdcompare (pdeel_key IN NUMBER, pdays NUMBER DEFAULT NULL) RETURN NUMBER;
PROCEDURE compress_states (pdodelete IN NUMBER DEFAULT 1);
END ins;
/
CREATE OR REPLACE PACKAGE BODY ins AS
FUNCTION delete_deelkoppeling( DeelKey IN NUMBER )
RETURN BOOLEAN
AS
BEGIN
DELETE FROM ins_deelkoppeling
WHERE ins_deelkoppeling_van_key = DeelKey
OR ins_deelkoppeling_naar_key = DeelKey;
RETURN TRUE;
EXCEPTION
WHEN OTHERS THEN RETURN FALSE;
END;
-- For backwards compatibility only (used in some CUST procedures) DEPRECATED!
FUNCTION get_description( pentityname IN VARCHAR2
, pparentkey IN NUMBER
, pprefix IN VARCHAR2) RETURN VARCHAR2 IS
BEGIN
IF pentityname = 'LPN_INS_DEEL'
THEN
RETURN ins.nextdescription(pprefix, NULL, '');
END IF;
IF pentityname = 'LPN_INS_ONDERDEEL'
THEN
RETURN ins.nextdescription(pprefix, pparentkey, '');
END IF;
RETURN 'unsupported use of ins.get_description';
END;
-- Determine max+1 volgnr for an object (deel or onderdeel) op basis van het format prefix+volgnummer
-- De laagste is 001 maar vervolgens wordt het gevonden aantal cijfers aangehouden, dus prefix0001+1 = prefix0002
-- Zo nodig wordt er een cijfer bij gedaan. De prefix wordt case-insensitive beschouwd.
FUNCTION nextdescription( pprefix IN VARCHAR2
, pparentkey IN NUMBER
, pseparator IN VARCHAR2 DEFAULT 'default') RETURN VARCHAR2 IS
nextvolgnr VARCHAR2(30); -- overdreven
returnstring ins_deel.ins_deel_omschrijving%TYPE;
lprefix VARCHAR2(30); -- overdreven, inclusief evt separator
lseparator VARCHAR2(30); -- ook overdreven
BEGIN
IF pseparator = 'default'
THEN
lseparator := fac.getsetting('ins_nr_separator');
ELSE
lseparator := pseparator;
END IF;
lprefix := pprefix || lseparator;
-- uniqueness is assumed over the entire database
IF pparentkey IS NULL
THEN
SELECT CASE
WHEN COALESCE(MAX(TO_NUMBER(SUBSTR(ins_deel_upper, LENGTH(lprefix) + 1))) + 1, 1) < 1000
THEN COALESCE(LPAD(TO_CHAR(MAX(TO_NUMBER(SUBSTR(ins_deel_upper, LENGTH(lprefix) + 1))) + 1), MAX(LENGTH(ins_deel_upper) - LENGTH(lprefix)), '0'), '001')
ELSE TO_CHAR(MAX(TO_NUMBER(SUBSTR(ins_deel_upper, LENGTH(lprefix) + 1))) + 1)
END nextvolgnr
INTO nextvolgnr
FROM ins_deel
WHERE ins_deel_upper LIKE UPPER(lprefix) || '%'
AND fac.safe_to_integer(SUBSTR(ins_deel_upper, LENGTH(lprefix) + 1)) IS NOT NULL
AND LTRIM(SUBSTR (ins_deel_upper, LENGTH (lprefix) + 1), '0') = TO_CHAR(fac.safe_to_integer ((SUBSTR (ins_deel_upper, LENGTH (lprefix) + 1))))
AND ins_deel_parent_key IS NULL
AND ins_deel_verwijder IS NULL;
ELSIF pparentkey IS NOT NULL
THEN
SELECT CASE
WHEN COALESCE(MAX(TO_NUMBER(SUBSTR(ins_deel_upper, LENGTH(lprefix) + 1))) + 1, 1) < 1000
THEN COALESCE(LPAD(TO_CHAR(MAX(TO_NUMBER(SUBSTR(ins_deel_upper, LENGTH(lprefix) + 1))) + 1), MAX(LENGTH(ins_deel_upper) - LENGTH(lprefix)), '0'), '001')
ELSE TO_CHAR(MAX(TO_NUMBER(SUBSTR(ins_deel_upper, LENGTH(lprefix) + 1))) + 1)
END nextvolgnr
INTO nextvolgnr
FROM ins_deel
WHERE ins_deel_upper LIKE UPPER(lprefix) || '%'
AND fac.safe_to_integer(SUBSTR(ins_deel_upper, LENGTH(lprefix) + 1)) IS NOT NULL
AND ins_deel_parent_key = pparentkey
AND ins_deel_verwijder IS NULL;
END IF;
returnstring := pprefix || lseparator || nextvolgnr;
RETURN returnstring;
END;
PROCEDURE copyInsKenmerken(pdeel_key IN NUMBER, ptosrtdeel_key IN NUMBER)
AS
CURSOR c_kenmerkdeel (pdeel_key IN NUMBER, ptosrtdeel_key IN NUMBER)
IS
SELECT kd1.ins_kenmerkdeel_key, k2.ins_kenmerk_key
FROM ins_kenmerk k1,
ins_kenmerk k2,
ins_kenmerkdeel kd1,
ins_srtdeel sd2,
ins_srtgroep sg2,
ins_srtkenmerk sk
WHERE k1.ins_srtkenmerk_key = k2.ins_srtkenmerk_key
AND k1.ins_kenmerk_key <> k2.ins_kenmerk_key
AND sk.ins_srtkenmerk_key = k1.ins_srtkenmerk_key
AND COALESCE (k1.ins_kenmerk_omschrijving,
sk.ins_srtkenmerk_omschrijving) =
COALESCE (k2.ins_kenmerk_omschrijving,
sk.ins_srtkenmerk_omschrijving)
AND sd2.ins_srtgroep_key = sg2.ins_srtgroep_key
AND k1.ins_kenmerk_niveau = k2.ins_kenmerk_niveau
AND k1.ins_kenmerk_niveau <> 'C'
AND kd1.ins_kenmerk_key = k1.ins_kenmerk_key
AND k2.ins_srtinstallatie_key =
(CASE
WHEN k2.ins_kenmerk_niveau = 'D' THEN sg2.ins_discipline_key
WHEN k2.ins_kenmerk_niveau = 'G' THEN sg2.ins_srtgroep_key
WHEN k2.ins_kenmerk_niveau = 'S' THEN sd2.ins_srtdeel_key
END)
AND kd1.ins_deel_key = pdeel_key
AND sd2.ins_srtdeel_key = ptosrtdeel_key;
CURSOR c_facbijlagen (pdeel_key IN NUMBER, ptosrtdeel_key IN NUMBER)
IS
SELECT fb1.fac_bijlagen_key, k2.ins_kenmerk_key
FROM ins_kenmerk k1,
ins_kenmerk k2,
fac_bijlagen fb1,
ins_srtdeel sd2,
ins_srtgroep sg2,
ins_srtkenmerk sk
WHERE k1.ins_srtkenmerk_key = k2.ins_srtkenmerk_key
AND k1.ins_kenmerk_key <> k2.ins_kenmerk_key
AND sk.ins_srtkenmerk_key = k1.ins_srtkenmerk_key
AND COALESCE (k1.ins_kenmerk_omschrijving,
sk.ins_srtkenmerk_omschrijving) =
COALESCE (k2.ins_kenmerk_omschrijving,
sk.ins_srtkenmerk_omschrijving)
AND sd2.ins_srtgroep_key = sg2.ins_srtgroep_key
AND k1.ins_kenmerk_niveau = k2.ins_kenmerk_niveau
AND k1.ins_kenmerk_niveau <> 'C'
AND fb1.fac_bijlagen_kenmerk_key = k1.ins_kenmerk_key
AND k2.ins_srtinstallatie_key =
(CASE
WHEN k2.ins_kenmerk_niveau = 'D' THEN sg2.ins_discipline_key
WHEN k2.ins_kenmerk_niveau = 'G' THEN sg2.ins_srtgroep_key
WHEN k2.ins_kenmerk_niveau = 'S' THEN sd2.ins_srtdeel_key
END)
AND fb1.fac_bijlagen_refkey = pdeel_key
AND sd2.ins_srtdeel_key = ptosrtdeel_key;
BEGIN
FOR kd_upd IN c_kenmerkdeel (pdeel_key, ptosrtdeel_key)
LOOP
UPDATE ins_kenmerkdeel
SET ins_kenmerk_key = kd_upd.ins_kenmerk_key
WHERE ins_kenmerkdeel_key = kd_upd.ins_kenmerkdeel_key;
END LOOP;
FOR fb_upd IN c_facbijlagen (pdeel_key, ptosrtdeel_key)
LOOP
UPDATE fac_bijlagen
SET fac_bijlagen_kenmerk_key = fb_upd.ins_kenmerk_key
WHERE fac_bijlagen_key = fb_upd.fac_bijlagen_key;
END LOOP;
END;
-- omkatten van het objectsoort van een object. Controleert wat technische voorwaarden qua binding
-- maar kijkt niet naar bv autorisaties. Trackt alleen als er ook echt iets verandert
PROCEDURE altersrtdeel(pdeel_key IN NUMBER, ptosrtdeel_key IN NUMBER)
AS
fromsrtdeel_key ins_deel.ins_srtdeel_key%TYPE;
fromsrtdeelomschrijving ins_srtdeel.ins_srtdeel_omschrijving%TYPE;
frombinding ins_deel.ins_alg_ruimte_type%TYPE;
frombindingval NUMBER;
tobinding ins_srtdeel.ins_srtdeel_binding%TYPE;
tosrtdeelomschrijving ins_srtdeel.ins_srtdeel_omschrijving%TYPE;
BEGIN
SELECT d.ins_srtdeel_key,
d.ins_alg_ruimte_type,
lcl.x ('ins_srtdeel_omschrijving', sd.ins_srtdeel_key, sd.ins_srtdeel_omschrijving)
INTO fromsrtdeel_key, frombinding, fromsrtdeelomschrijving
FROM ins_deel d, ins_srtdeel sd
WHERE d.ins_srtdeel_key = sd.ins_srtdeel_key AND ins_deel_key = pdeel_key;
-- frombinding is one of A(8),P(16),R(1),T(4),W(2)
SELECT DECODE (frombinding, 'R', 1, 'W', 2, 'T', 4, 'A', 8, 'P', 16, 32)
INTO frombindingval
FROM DUAL;
BEGIN
SELECT ins_srtdeel_binding,
lcl.x ('ins_srtdeel_omschrijving', ins_srtdeel_key, ins_srtdeel_omschrijving)
INTO tobinding, tosrtdeelomschrijving
FROM ins_srtdeel
WHERE ins_srtdeel_key = ptosrtdeel_key
AND BITAND (ins_srtdeel_binding, frombindingval) = frombindingval;
IF fromsrtdeel_key <> ptosrtdeel_key
THEN
UPDATE ins_deel
SET ins_srtdeel_key = ptosrtdeel_key
WHERE ins_deel_key = pdeel_key;
-- de redundante ins_deel.ins_discipline_key wordt door de trigger bijgewerkt
copyInsKenmerken(pdeel_key, ptosrtdeel_key);
-- het is nu mogelijk dat er kenmerken (ins_kenmerkdeel) zijn die qua definitie niet horen
-- tot de kenmerken van de nieuwe soort. Ik vind dat niet erg.
-- de tracking zou discipline/srtgroep/srtdeel -> discipline/srtgroep/srtdeel kunnen zijn
-- voor de volledigheid, maar daar mag iemand om gaan vragen, zo essentieel is dat niet
fac.trackaction (
'INSUPD',
pdeel_key,
TO_NUMBER (SYS_CONTEXT ('USERENV', 'CLIENT_IDENTIFIER')),
NULL,
fromsrtdeelomschrijving || lcl.l ('lcl_trackto') || tosrtdeelomschrijving);
END IF;
EXCEPTION
WHEN NO_DATA_FOUND
THEN
DBMS_OUTPUT.put_line ('Cannot alter srtdeel: bindings do not match');
END;
END;
FUNCTION sprintf (ps IN varchar2, pins_deel_key IN number)
RETURN varchar2
IS
lins_deel_omschrijving ins_deel.ins_deel_omschrijving%TYPE;
lins_deel_opmerking ins_deel.ins_deel_opmerking%TYPE;
lins_srtdeel_omschrijving ins_srtdeel.ins_srtdeel_omschrijving%TYPE;
s varchar2 (2048 CHAR);
BEGIN
s := ps;
-- We support substitution of placeholders in the messages
-- ##DESC## = ins_deel_omschrijving (eigenlijk de ID, maar te laat om aan te passen)
-- ##REMARK## = ins_deel_opmerking
-- ##TYPE## = ins_srtdeel_omschrijving
IF INSTR2 (s, '#') > 0
THEN
SELECT ins_deel_omschrijving, ins_deel_opmerking, ins_srtdeel_omschrijving
INTO lins_deel_omschrijving, lins_deel_opmerking, lins_srtdeel_omschrijving
FROM ins_deel id, ins_srtdeel isd
WHERE id.ins_srtdeel_key = isd.ins_srtdeel_key
AND ins_deel_key = pins_deel_key;
s := REPLACE (REPLACE (REPLACE (REPLACE (s, '##DESC##', lins_deel_omschrijving), '##KEY##', TO_CHAR (pins_deel_key)), '##REMARK##', lins_deel_opmerking), '##TYPE##', lins_srtdeel_omschrijving) ;
END IF;
RETURN s;
END;
FUNCTION contrsprintf (ps IN varchar2, pins_deelsrtcontr_key IN number)
RETURN varchar2
IS
s varchar2 (2048 CHAR);
BEGIN
s := ps;
IF INSTR2 (s, '#') > 0
THEN
s := REPLACE (s, '##KEY##', TO_CHAR (pins_deelsrtcontr_key));
END IF;
RETURN s;
END;
-- Berekent de n-de (p_steps) controledatum na p_date.
-- Indien p_steps niet is meegegeven dan wordt de eerstvolgende controledatum na nu teruggegeven.
-- steps = 0, (NULL): 1-ste vandaag of in de toekomst (als meegegeven datum (p_date) de huidige datum is, dan deze weer teruggeven).
-- steps = n: n-volgende vanaf meegegeven datum (p_date). Als deze berekende datum in de toekomst ligt en steps is nog niet null, dan wordt NULL teruggegeven).
-- De einddatum van het object (xcp.ins_srtcontroledl_xcp_eind) wordt niet meegenomen. De volgende inspectiedatum wordt gewoon teruggeven.
FUNCTION nextcyclusdate (p_insdeel IN NUMBER,
p_srtcontrole IN NUMBER,
p_scenario IN NUMBER,
p_steps IN NUMBER DEFAULT 0)
RETURN DATE
IS
inspdate DATE;
BEGIN
SELECT fac.nextcyclusdate (COALESCE ( (SELECT CASE xcp.ins_srtcontrole_mode
WHEN 0
THEN idsc.ins_deelsrtcontrole_datum_org
ELSE idsc.ins_deelsrtcontrole_datum
END ins_deelsrtcontrole_datum
FROM ins_deelsrtcontrole idsc
WHERE idsc.ins_srtcontrole_key = xcp.ins_srtcontrole_key
AND idsc.ins_deelsrtcontrole_status IN (5,6)
AND idsc.ins_scenario_key = 1
AND idsc.ins_deel_key = xcp.ins_deel_key
-- Voor mjob moeten de NIET succesvolle inspecties niet worden meegenomen.
-- Voor periodieke inspectie laten we het vooralsnog hetzelfde.
AND idsc.ins_deelsrtcontrole_key = (SELECT MAX(ins_deelsrtcontrole_key)
FROM (SELECT idsc2.ins_deelsrtcontrole_key
, idsc2.ins_deel_key
, idsc2.ins_srtcontrole_key
, 0 ctr_ismjob
FROM ins_deelsrtcontrole idsc2
WHERE idsc2.ins_deelsrtcontrole_status IN (5,6)
AND idsc2.ins_scenario_key = 1
UNION
SELECT idsc2.ins_deelsrtcontrole_key
, idsc2.ins_deel_key
, idsc2.ins_srtcontrole_key
, 1 ctr_ismjob
FROM ins_deelsrtcontrole idsc2,
ins_controlemode cm
WHERE idsc2.ins_controlemode_key = cm.ins_controlemode_key
AND idsc2.ins_deelsrtcontrole_status IN (5,6)
AND idsc2.ins_scenario_key = 1
AND cm.ins_controlemode_success = 1) aa
WHERE aa.ins_deel_key = xcp.ins_deel_key
AND aa.ins_srtcontrole_key = xcp.ins_srtcontrole_key
AND aa.ctr_ismjob = xcp.ctr_ismjob)),
xcp.ins_srtcontroledl_xcp_startdat,
xcp.ins_deel_aanmaak),
xcp.ins_srtcontrole_mode,
xcp.ins_srtcontrole_eenheid,
xcp.ins_srtcontrole_periode,
xcp.ins_srtcontrole_bits,
p_steps,
xcp.ctr_ismjob
) inspectie_next
INTO inspdate
FROM ins_v_defined_inspect_xcp xcp
WHERE xcp.ins_deel_key = p_insdeel
AND xcp.ins_srtcontrole_key = p_srtcontrole
AND xcp.ins_scenario_key = p_scenario;
RETURN inspdate;
END;
-- De einddatum van het object (xcp.ins_srtcontroledl_xcp_eind) wordt niet meegenomen. De volgende inspectiedatum wordt gewoon teruggeven.
-- Wordt alleen gebruikt voor Active Situatie (AS) soort controle's. Scenario wordt NULL verondersteld.
FUNCTION nextcyclusdatesteps (p_insdeel IN NUMBER,
p_srtcontrole IN NUMBER,
p_steps IN NUMBER DEFAULT 1) -- Standaard beginnen te tellen bij 1.
RETURN NUMBER
IS
lsteps NUMBER;
BEGIN
SELECT fac.nextcyclusdatesteps (COALESCE ( (SELECT COALESCE(idsc.ins_deelsrtcontrole_plandatum, idsc.ins_deelsrtcontrole_datum_org) ins_deelsrtcontrole_datum
FROM ins_deelsrtcontrole idsc
WHERE xcp.ins_srtcontrole_key = idsc.ins_srtcontrole_key
AND idsc.ins_deelsrtcontrole_status IN (5,6)
AND idsc.ins_scenario_key = 1
AND idsc.ins_deel_key = xcp.ins_deel_key
AND idsc.ins_deelsrtcontrole_key = (SELECT MAX(idsc2.ins_deelsrtcontrole_key)
FROM ins_deelsrtcontrole idsc2
WHERE idsc2.ins_deel_key = xcp.ins_deel_key
AND idsc2.ins_srtcontrole_key = xcp.ins_srtcontrole_key
AND idsc2.ins_deelsrtcontrole_status IN (5,6)
AND idsc2.ins_scenario_key = 1)),
xcp.ins_srtcontroledl_xcp_startdat,
ins_deel_aanmaak),
xcp.ins_srtcontrole_mode,
xcp.ins_srtcontrole_eenheid,
xcp.ins_srtcontrole_periode,
xcp.ins_srtcontrole_bits,
p_steps
) inspectie_steps
INTO lsteps
FROM ins_v_defined_inspect_xcp xcp
WHERE xcp.ins_deel_key = p_insdeel
AND xcp.ins_srtcontrole_key = p_srtcontrole
AND xcp.ins_scenario_key = 1;
RETURN lsteps;
END;
-- Geef deelsrtcontrolekey, gewenste status en userkey, en de status wortdt
-- gezet, waarbij zonodig (indien verandering) een trackrecord wordt gemaakt
-- Als de status niet wijzigt, wordt ook geen trackrecord gemaakt
PROCEDURE setinspectstatus (pdlsrtcontrkey IN NUMBER, pstatus IN NUMBER, puserkey IN NUMBER)
AS
currentstatus ins_deelsrtcontrole.ins_deelsrtcontrole_status%TYPE;
newstatus ins_deelsrtcontrole.ins_deelsrtcontrole_status%TYPE;
eventcode fac_srtnotificatie.fac_srtnotificatie_code%TYPE;
BEGIN
SELECT ins_deelsrtcontrole_status
INTO currentstatus
FROM ins_deelsrtcontrole
WHERE ins_deelsrtcontrole_key = pdlsrtcontrkey;
CASE
WHEN pstatus = 0 -- Gepland
THEN
newstatus := pstatus;
WHEN pstatus = 2 -- In behandeling
THEN
newstatus := pstatus;
eventcode := 'INSCBE';
WHEN pstatus = 3 AND currentstatus = 2 -- Ter uitvoering
THEN
newstatus := pstatus;
eventcode := 'INSCTU';
WHEN pstatus = 5 -- Afgemeld
THEN
newstatus := pstatus;
eventcode := 'INSCAF';
WHEN pstatus = 6 -- Verwerkt
THEN
newstatus := pstatus;
eventcode := 'INSCVE';
ELSE
-- Invalid statuschange or no change
newstatus := NULL;
END CASE;
IF newstatus IS NOT NULL
THEN
-- vooralsnog lopen de notificaties 1-op-1 met de tracking
-- noticode := eventcode;
UPDATE ins_deelsrtcontrole
SET ins_deelsrtcontrole_status = newstatus
WHERE ins_deelsrtcontrole_key = pdlsrtcontrkey;
-- We know that trackaction doesnt do tracking if eventcode is null
fac.trackaction (eventcode, pdlsrtcontrkey, puserkey, NULL, NULL);
END IF;
END;
-- Return the numeric difference between the values of str1 and str2 (first minus second)
-- Rerturn NULL if undecided for whatever reason
FUNCTION state_diff (str1 IN VARCHAR, str2 IN VARCHAR)
RETURN NUMBER
AS
nrval1 NUMBER (12, 5);
nrval2 NUMBER (12, 5);
retval NUMBER;
BEGIN
nrval1 := fac.safe_to_number (REPLACE (str1, ',', '.'));
nrval2 := fac.safe_to_number (REPLACE (str2, ',', '.'));
IF nrval1 IS NOT NULL AND nrval2 IS NOT NULL
THEN
retval := (nrval1 - nrval2);
END IF;
RETURN retval;
END;
-- The return value from state_compare is 0 if the two strings are equal,
-- less than 0 if str1 compares less than str2 , and greater than 0
-- if str1 compares greater than str2 (within the first maxlen characters).
FUNCTION state_compare (str1 IN VARCHAR, str2 IN VARCHAR)
RETURN NUMBER
AS
BEGIN
RETURN SIGN (state_diff (str1, str2));
END;
-- Return >0 if the current state of a sensorvalue exceeds the threshold
-- Return NULL if undecided for whatever reason (no value, no threshold, no sensor
-- If pdays is given, the sensorstate must be set within the last pdays days
-- This provides the option of neglecting an irrelevant too old value
FUNCTION state_thresholdcompare (pdeel_key IN NUMBER, pdays NUMBER DEFAULT NULL)
RETURN NUMBER
AS
lstate ins_deel.ins_deel_state%TYPE;
lstatethreshold ins_srtdeel.ins_srtdeel_statethreshold%TYPE;
retval NUMBER;
BEGIN
IF pdeel_key IS NOT NULL
THEN
BEGIN
IF pdays IS NULL
THEN
SELECT ins_deel_state, ins_srtdeel_statethreshold
INTO lstate, lstatethreshold
FROM ins_deel d, ins_srtdeel sd
WHERE d.ins_srtdeel_key = sd.ins_srtdeel_key
AND ins_deel_verwijder IS NULL
AND d.ins_deel_key = pdeel_key;
ELSE
SELECT ins_deel_state, ins_srtdeel_statethreshold
INTO lstate, lstatethreshold
FROM ins_deel d, ins_srtdeel sd
WHERE d.ins_srtdeel_key = sd.ins_srtdeel_key
AND ins_deel_verwijder IS NULL
AND ins_deel_statedate > SYSDATE - pdays
AND d.ins_deel_key = pdeel_key;
END IF;
retval := state_compare (lstate, lstatethreshold);
EXCEPTION
WHEN NO_DATA_FOUND
THEN
retval := NULL; -- dat wassieal maar dan is het maar duidelijk
END;
END IF;
RETURN retval;
END;
-- Archiveer de meetwaarde van discrete sensoren ouder danins_state_history dagen
-- naar een dag-histogram zodat je er nog wel daggemiddelden van hebt maar
-- niet meer de granulaire ballast.
-- parameter pdontdelete is alleen voor testers
PROCEDURE compress_states (pdodelete IN NUMBER DEFAULT 1)
AS
CURSOR c_days (eerste_dag IN DATE, laatste_dag IN DATE)
IS
SELECT DISTINCT TRUNC (h.ins_deel_statedate) uitvoer_dag
FROM ins_deel_state_history h
, ins_deel d
, ins_srtdeel s
WHERE h.ins_deel_key = d.ins_deel_key
AND d.ins_srtdeel_key = s.ins_srtdeel_key
AND BITAND (s.ins_srtdeel_sensortype, 1) = 1
AND h.ins_deel_statedate BETWEEN eerste_dag AND (laatste_dag + 1)
ORDER BY 1;
keep_days NUMBER (3);
first_day_available DATE;
last_day_compressed DATE;
start_day_compress DATE;
end_day_compress DATE;
BEGIN
-- Tot hoeveel dagen terug houden we de ruwe data?
keep_days := TO_NUMBER (fac.getsetting ('ins_state_history'));
-- dbms_output.put_line('today: '||to_char(today,'dd-mm-yyyy'));
-- Vandaag comprimeren mag niet want je weet niet of je alle meetwaarden al hebt.
end_day_compress := TRUNC (SYSDATE) - keep_days;
IF (end_day_compress = TRUNC (SYSDATE))
THEN
end_day_compress := end_day_compress - 1;
END IF;
-- Voor welke dagen moet ins_deel_state_history gecomprimeerd worden?
-- (voor het geval compress_states een aantal dagen niet heeft gewerkt.)
SELECT TRUNC (COALESCE (MIN (ins_deel_statedate), end_day_compress))
INTO first_day_available
FROM ins_deel_state_history;
-- dbms_output.put_line('first_day_available: ' ||to_char(first_day_available,'dd-mm-yyyy'));
SELECT COALESCE (TRUNC (MAX (ins_deel_statedate)), first_day_available)
INTO last_day_compressed
FROM ins_deel_state_history_all;
-- dbms_output.put_line('last_day_compressed: ' ||to_char(last_day_compressed,'dd-mm-yyyy'));
SELECT GREATEST (first_day_available, (last_day_compressed + 1))
INTO start_day_compress
FROM DUAL;
--DBMS_OUTPUT.put_line ('Compress from '|| TO_CHAR (start_day_compress, 'dd-mm-yyyy')||' to '|| TO_CHAR (end_day_compress, 'dd-mm-yyyy'));
FOR r_day IN c_days (start_day_compress, end_day_compress)
LOOP
--DBMS_OUTPUT.put_line ('Compress ' || TO_CHAR (r_day.uitvoer_dag, 'dd-mm-yyyy'));
--
-- Haal de statuswijzigingen per dag. De laatste status loopt tot middernacht.
-- Ook de status van middernacht tot de eerste statuswijziging deze dag moet worden opgehaald.
-- Deze kan meerdere dagen voor deze dag voor het laatst gezet zijn!
INSERT INTO ins_deel_state_history_all (ins_deel_key,
ins_deel_statedate,
ins_deel_state,
ins_deel_statetime)
SELECT x.ins_deel_key,
r_day.uitvoer_dag,
x.status,
ROUND (SUM (x.eindtijd - x.starttijd), 3) totaaltijd
FROM (( SELECT a.ins_deel_state status,
r_day.uitvoer_dag starttijd,
MIN (c.ins_deel_statedate) eindtijd,
a.ins_deel_key
FROM ins_deel_state_history a, ins_deel_state_history c
WHERE a.ins_deel_key = c.ins_deel_key
AND c.ins_deel_statedate BETWEEN r_day.uitvoer_dag
AND r_day.uitvoer_dag + 1
AND a.ins_deel_statedate =
(SELECT MAX (b.ins_deel_statedate)
FROM ins_deel_state_history b
WHERE b.ins_deel_key = a.ins_deel_key
AND b.ins_deel_statedate < r_day.uitvoer_dag)
GROUP BY a.ins_deel_key, a.ins_deel_state)
UNION
( SELECT a.ins_deel_state status,
a.ins_deel_statedate starttijd,
LEAST (MIN (b.ins_deel_statedate), r_day.uitvoer_dag + 1) eindtijd,
a.ins_deel_key
FROM ins_deel_state_history a, ins_deel_state_history b
WHERE a.ins_deel_statedate BETWEEN r_day.uitvoer_dag
AND r_day.uitvoer_dag + 1
AND a.ins_deel_key = b.ins_deel_key
AND a.ins_deel_state <> b.ins_deel_state
AND a.ins_deel_statedate < b.ins_deel_statedate
GROUP BY a.ins_deel_statedate, a.ins_deel_state, a.ins_deel_key)) x
GROUP BY x.ins_deel_key, x.status
ORDER BY 1, 2;
COMMIT;
END LOOP;
IF pdodelete = 1
THEN
-- Verwijder alle records uit ins_deel_state_history ouder dan keep_days dagen.
-- dat is van de discrete sensoren die zojuist gearchiveer zijn,
-- maar dus ook de van de meetwaardesensoren, die willen we niet behouden
-- besloten we vooralsnog. Mocht er data van niet-sensoren staan (illegaal)
-- dan gooien we die niet weg.
DELETE FROM ins_deel_state_history
WHERE ins_deel_statedate <= TRUNC (SYSDATE - keep_days)
AND ins_deel_key IN
(SELECT ins_deel_key
FROM ins_deel d, ins_srtdeel s
WHERE d.ins_srtdeel_key = s.ins_srtdeel_key AND s.ins_srtdeel_sensortype <> 0);
END IF;
END;
END ins;
/
REGISTERRUN('$Id$')
#endif // INS