Добавил:
Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:

МиСПрИС_Задание2_4_Петрова_Романова_Заболотников_9373

.pdf
Скачиваний:
16
Добавлен:
20.06.2023
Размер:
1.31 Mб
Скачать

DELETE FROM body_func WHERE IdToDelete = id_pair;

else

raise exception 'Pair with this id does not exist. DB wasnt

updated.'; end if;

end $$ LANGUAGE plpgsql;

----------------------------------------------------------------------

Процедуры

----------------------------------------------------------------------

CREATE OR REPLACE function isInSpec(pIdProd integer,pIdPOS integer) returns table(oIdF integer,oRes integer)

as $$

 

DECLARE

vNumD INTEGER;

DECLARE

vResK INTEGER;

DECLARE

vResPred INTEGER;

DECLARE

vIdPred INTEGER;

DECLARE

vPar INTEGER;

DECLARE

vValP INTEGER;

DECLARE

vOper text;

DECLARE

vValConf INTEGER;

DECLARE

vRes INTEGER;

DECLARE

ValueConfig INTEGER;

DECLARE

ValuePredic INTEGER;

DECLARE

ValueConfigStr text;

DECLARE

ValuePredicStr text;

declare f record; declare f2 record;

begin

/*функция: Определяет допустимость включения строки спецификации в вариант исполнения pIdProd

вход:pIdProd - ид.варианта исполнения

pIdPOS - id пары продукт-используемый продукт в спецификации выход: oNumK - номер конъюнкции

oRes - 0 - false 1 - true

эффекты: */ oRes=1;

/*Находим функцию для строки*/

31

select id_function from spec_product where id_pair = pIdPos into oIdF;

if ((oIdF=0)or(oIdF is null)) then --Если нет такой пары или функция

не задана

 

 

 

oRes=1;

 

 

 

oIdF=0;

 

 

 

return next;

 

 

 

else

 

 

 

vResK=0;

 

 

 

for f in select distinct bf.num_dis from

body_func

bf

where

bf.id_func = oIdF --Выбираем нужные дизъюнкции

 

 

 

loop

 

 

 

vNumD = f. num_dis;

 

 

 

if(vResK=0) then

 

 

 

vResK=1;

 

 

 

for f2 in select bf.id_pred from

body_func

bf

where

bf.id_func = oIdF and bf.num_dis = vNumD --Выбираем поочереди предикаты нужные

loop

vIdPred = f2.id_pred; if(vResK=1) then

select id_param ,id_value ,oper from predicat where id_pred = vIdPred into vPar,vValP,vOper; --ид. для значения и параметра предиката

select id_enum_value from prod_param where id_prod = pIdProd and id_param = vPar into vValConf; -- ид. для значения конфигурации

select value from enum_value where id_value = vValP into ValuePredic; --Находим конкретное знаение для предиката

select value from enum_value where id_value = vValConf into ValueConfig; --Находим конкретное знаение для конфигурации

select name_value from enum_value where id_value = vValP into ValuePredicStr; --Находим конкретное текстовое знаение для предиката

select name_value from enum_value where id_value = vValConf into ValueConfigStr; --Находим конкретное знаение текстовое для конфигурации

32

if(vOper ='=') then

if(ValuePredic=ValueConfig or ValuePredicStr = ValueConfigStr) then vRes=1;

else vRes=0; end if;

else

if(vOper ='>') then if(ValuePredic>ValueConfig) then vRes=1; else vRes=0;

end if; else

if(vOper ='<') then if(ValuePredic<ValueConfig) then vRes=1; else vRes=0;

end if; end if;

end if; end if;

if(vRes=0) then vResK=0; end if;

end if;

end loop; end if;

end loop; oRes=vResK; return next;

end if;

end $$ LANGUAGE plpgsql;

CREATE OR REPLACE function FIND_CIRCLE(pIdEl integer, pYesCircle integer) returns table(

oYesCircle integer, oIdEl1 integer, oIdEl2 integer)

as $$

33

declare vInEl integer; declare vY integer; declare vYesCircle integer; declare f1 record;

declare f2 record; begin

/*функция: Проверяет наличие циклов и выводит проверенные пары вершин и индикатор цикла

вход: pIdEl - ид. начальной вершины

pYesCircle - индикатор наличия цикла (при вызове =0)

выход: oYesCircle - индикатор наличия цикла (0 - цикла нет), oIdEl1 - ид. используемого элемента,

oIdEl2 - ид. использующего элемента эффекты:

1. При обнаружении хотя бы одного цикла oYesCircle сохраняет значение

>0 для всех остальных проверок

требования:

1. При начальном вызове установить pYesCircle = 0

*/

if(pYesCircle = 0) then oYesCircle = pYesCircle; vYesCircle=0;

/*Для всех непосредственнх неотмеченных связей элемента pIdEl*/

for f1 in select id_useproduct, flag from spec_product where id_mainproduct = pIdEl and FLAG<>1

loop

vInEl = f1.id_useproduct; vY = f1.flag;

/*Помечаемтекущуюсвязь */

update spec_product set FLAG = 1 where id_mainproduct = pIdEl and id_useproduct = vInEl;

/*Проверяемналичиеобратнойсвязи*/

select count(*) from spec_product where ( id_mainproduct = vInEl and id_useproduct = pIdEl) into vYesCircle;

/*Помечаем обратную связь*/ if(vYesCircle >0) then

oYesCircle=1;

34

update spec_product set FLAG=1 where id_mainproduct = vInEl and id_useproduct = pIdEl;

end if;

/*присваиваем значения выходным параметрам и вывод*/ oIdEl1=vInEl;

oIdEl2=pIdEl; return next;

/*Для всех связей текущего элемента рекурсивно выполняем данную процедуру*/

for f2 in select oYesCircle,oIdEl1,oIdEl2 from FIND_CIRCLE(vInEl,oYesCircle)

loop

vYesCircle = f2.oYesCircle; oIdEl1 = f2.oIdEl1;

oIdEl2 = f2.oIdEl2; return next;

if(vYesCircle=0) then

/*Проверяем связи найденной вершины с исходной (циклы длины > 1)*/ select count(*) from spec_product where

(id_mainproduct = oIdEl1 and id_useproduct = pIdEl) into vYesCircle; if(vYesCircle>0) then

/*Помечаемтекущуюсвязь */

update spec_product set FLAG=1 where id_mainproduct = oIdEl1 and id_useproduct = pIdEl;

oYesCircle=1;

oIdEl2=pIdEl; return next;

end if;

else oYesCircle=1;

end if; end loop;

end loop; end if;

end $$ LANGUAGE plpgsql; /***************************************************************/

35

/***************************************************************/

CREATE OR REPLACE function YES_CIRCLE(pIdEl integer) returns table (oYesCircle integer)

as $$ BEGIN

/*функция:

Проверяет спецификацию на наличие циклов

вход:

 

pIdEl

- Код элемента, для которого ведется расчет

выход:

 

oYesCircle

- 0 - циклов нет, > 0 - циклы есть

*/

update spec_product set FLAG = 0 where FLAG > 0;

select count(*) from FIND_CIRCLE(pIdEl,0) where oYesCircle>0 into oYesCircle;

return next;

END $$ LANGUAGE plpgsql;

CREATE OR REPLACE function READ_SPEC_CONF(pMainEl integer,pIdEl integer,pUr integer)

returns table(oIdEl integer, oName text,

oInEl integer, oInName text,

oQ double precision, oUr integer,

Res integer)

as $$

declare vInEl integer; declare vIdEl integer; declare vUr integer; declare vFConf integer; declare vIdPos integer; declare vConf integer;

36

declare vREl integer;

declare vTypeProd integer; declare vYesPos integer; declare vYesSpec integer;

declare vCircle integer; declare vName text;

declare f record; declare f2 record;

begin /*

функция: Находит спецификацию изделия с учетом значений параметров конфигурации рассчитывая для каждого элемента уровень U

вход: pMainEl - исходный элемент, pIdEl текущий элемент

pU - начальный уровень = 0

выход:oIdEl - текущий элемент oUr - уровень элемента oName - имя изделия oShName - обозначение oInEl - ид. вход. объект oInShName - имя вх. объекта

oInName - обозначение вх. объекта

oRes - 1 - наличие цикла 0 - циклов нет эффекты:

1. При наличии циклов oIdEl=0, oRes=1

требования: привызове pUr=0

Требования:

1. При вызове pMainEl=pIdEl, pUr=0

*/

select name_product,id_variation,id_type_prod from product where id_product = pIdEl into vName,vConf,vTypeProd;

if ((vConf=1) or (vConf=2) or (vConf is null)) then --Будем мвыводить данные для типового продукта, если это вариация

37

vREl=pIdEl;

else vREl=vTypeProd; end if;

select id_pair from spec_product where id_mainproduct = vREl limit(1) into vYesSpec; --Есть ли позиции в спецификации для этого продукта,

выберем их

Res=0;

if vYesSpec is not null then if(pUr=0) then

select count(*) from FIND_CIRCLE(vREl,0) where oYesCircle>0 into Res;

end if; vUr=pUr+1; oUr=vUr; vIdEl=vREl;

if(Res>0) then --Если нашёлся цикл return next;

else

for f in select id_useproduct,q_insp, id_function, id_pair from spec_product where id_mainproduct = vREl --перебираем спецификации для этого продукта

loop

vInEl = f.id_useproduct; oQ = f.q_insp;

vFConf = f.id_function; vIdPos = f.id_pair;

if(vFConf >0) then -- если есть правило

select oRes from isInSpec(pMainEl,vIdPOS) into vYesPos; --поверяем выполняется ли

end if;

if((vFConf is null)or(vFConf>0)and(vYesPos=1))then --

если нет правила или есть правило, и оно выполянется oIdEl=vIdEl;

oName=vName;

oUr=vUr;

select name_product from product where id_product

= vInEl into oInName;

38

oInEl=vInEl; return next;

for f2 in select ss.oIdEl,ss.oName,ss.oInEl,ss.oInName,ss.oQ,ss.oUr from READ_SPEC_CONF(pMainEl,vInEl,vUr) as ss

loop

oIdEl = f2.oIdEl; oName = f2.oName; oInEl = f2.oInEl; oInName = f2.oInName; oQ = f2.oQ;

oUr = f2. oUr; return next;

end loop; end if;

end loop; end if;

end if;

END $$ LANGUAGE plpgsql;

CREATE OR REPLACE function SUM_Q_CONF(pMainEl integer,pIdEl integer,pUr integer,pQ double precision)

returns table(oIdEl integer, oName text,

oInEl integer, oInName text,

oQ double precision, oUr integer,

oRes integer)

as $$

declare vInEl integer; declare vIdEl integer; declare vUr integer; declare vFConf integer; declare vIdPos integer;

39

declare vConf integer; declare vREl integer;

declare vTypeProd integer; declare vYesPos integer; declare vYesSpec integer;

declare vCircle integer; declare vName varchar(200); declare vQ double precision; declare vTQ double precision;

declare f record; declare f2 record; begin

/*

функция: Находит спецификацию изделия с учетом значений параметров конфигурации рассчитывая для каждого элемента уровень U

вход: pMainEl - исходный элемент, pIdEl текущий элемент

pU - начальный уровень = 0

выход:oIdEl - текущий элемент oUr - уровень элемента oName - имя изделия oShName - обозначение oInEl - ид. вход. объект oInShName - имя вх. объекта

oInName - обозначение вх. объекта

oRes - 1 - наличие цикла 0 - циклов нет эффекты:

1. При наличии циклов oIdEl=0, oRes=1

требования: привызове pUr=0

Требования:

1. При вызове pMainEl=pIdEl, pUr=0

*/

--Для введнного продукта сразу найдем имя, конфигурацию и типовой продукт

40