МиСПрИС_Задание2_4_Петрова_Романова_Заболотников_9373
.pdfDELETE 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