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

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

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

Рисунок 25 – Добавим спецификацию для велосипеда Победа в виде 45

Шестигранников

Рисунок 26 – Результат

21

Рисунок 27 – Проверка спецификации

Рисунок 28 – Спецификация верна

22

Выводы.

В данной работе была разработан проект каркаса для работы со спецификациями. Реализация произведена в базе данных PostgreSQL.

Проведено тестирование, показывающее корректную работу реализованных функций для работы с данными. Кроме того, был реализован пользовательский интерфейс для взаимодействия человека с базой данных.

Проведены тесты работы приложения и была установлена его корректная работа. Полный код программы можно посмотреть в приложении А. Методы классов технической программы представлены в приложении Б.

23

ПРИЛОЖЕНИЕ А

---НОВАЯ ТАБЛИЦА----

create table Spec_Product --Таблица позиций спецификатора

(

id_variation serial not null primary key,-- id пары главного продукта и используемого

id_mainProduct integer not null, -- id главного продукта id_useProduct integer not null, --id составного продукта positionInSP integer not null, -- Номер позиции

countInSP integer not null, -- Количество используемого продукта в главном

flag integer not null,-- Флаг базы

CONSTRAINT id_mainProduct FOREIGN KEY (id_mainProduct) REFERENCES Product (id_product) MATCH SIMPLE

ON UPDATE NO ACTION

ON DELETE CASCADE

)

create unique index union_MainAndUse on Spec_Product(id_mainProduct, id_useProduct); --Создадим индекс для уникальности пар (главный продукт, составной продукт)

ALTER TABLE Spec_Product ADD CONSTRAINT id_useProduct FOREIGN KEY (id_useProduct)

REFERENCES public.Product (id_product) MATCH SIMPLE

ON UPDATE NO ACTION

ON DELETE cascade

---ФУНКЦИИ-----

-- Добавление элементов в таблицу SP

/*функция: Дообавляет новую позицию в спецификатор и поверяет не создано ли циклов. Если циклы есть, то изменения откатываются вход: id_mainProductN - ид. продукта главного

id_useProductN - ид. используемого продукта countInSPN -количество используемого продукта flagN - флаг базы

эффекты:

24

1.Если продукта главного или используемого не существует, то будет выведена ошибка.

2.Если при поощи новой позиции был создан цикл, то изменения не будут внесены.

3.Позиция пары будет вычислена автоматически

*/

CREATE OR REPLACE function add_posSP ( id_mainProductN integer, id_useProductN integer,

countInSPN integer,

flagN integer) RETURNS VOID as $$

declare ind_mp int default 0; declare ind_up int default 0; declare posNew int default 0; begin

select id_product from product where id_mainProductN = id_product into ind_mp;

select id_product from product where id_useProductN = id_product into ind_up;

if (ind_mp is not null) then if ind_up is not null then

select max(positioninsp)+1 from spec_product where id_mainProductN = id_mainproduct into posNew;

if posNew is null then posNew:= 1;

end if;

INSERT INTO spec_product(id_mainproduct, id_useproduct,positioninsp,countinsp,flag) VALUES (id_mainProductN, id_useProductN,posNew,countInSPN,flagN);

if check_loop(id_mainProductN) is not null then delete from spec_product where id_mainproduct =

id_mainProductN and id_useproduct = id_useProductN;

raise exception 'You have created the loop. Db

was not updated.';

end if;

else

25

raise exception 'This using product is not existing. Db was not updated.';

end if; else

raise exception 'This main product is not existing. Db was not updated.';

end if;

end $$ LANGUAGE plpgsql;

--Удаление Позиции в спецификаторе

/*функция: Удаляет ппозицию в спецификаторе, если заявленный идентификато пары существует

вход: spIdToDelete - id_variation пары, которую нужно удалить эффекты:

1. Если id пары нет, то будет выведено сообщение об ошибке.

*/

CREATE OR REPLACE function delete_sp ( spIdToDelete integer) RETURNS VOID

as $$ begin

if(select id_variation from spec_product where spIdToDelete = id_variation limit 1) is not null then

DELETE FROM spec_product WHERE spIdToDelete = id_variation;

else

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

updated.'; end if;

end $$ LANGUAGE plpgsql;

/*функция: Проверяет наличие циклов и возвращает либо 0, либо число отличное от 0

вход: spIdToCheck - id новой позиции, которая проверяется на создание цикла

выход: id_useproduct - либо id продукта которрый стоит перед заданным в цикле,либо null - если цикла нет

26

*/

CREATE OR REPLACE function check_loop (

spIdToCheck integer) RETURNS table (id_useproduct int) LANGUAGE plpgsql as $func$

begin

RETURN QUERY

with recursive graph(id_mainproduct, id_useproduct, path) as ( select sp.id_mainproduct, sp.id_useproduct, CAST

(sp.id_useproduct AS TEXT) as PATH

from spec_product as sp where sp.id_mainproduct = spIdToCheck union all

select spec_product.id_mainproduct, spec_product.id_useproduct, CAST ( graph.PATH ||' = > '|| spec_product.id_useproduct AS TEXT)

from spec_product inner join graph on graph.id_useproduct = spec_product.id_mainproduct

where spec_product.id_mainproduct <> spIdToCheck

)

select graph.id_useproduct from graph where graph.id_useproduct = spIdToCheck limit 1;

end $func$;

--

/*функция: Выводит все позиции используемых продуктов для заданного и считает количество каждого из них

вход: spIdToCheck - идентификатор того продукта, для которого необходио составить список выход: Таблица с количеством продукта и его идентификатором

*/

CREATE OR REPLACE function func_count (

spIdToCheck integer) RETURNS table (countProd bigint,id_useproduct

int)

LANGUAGE plpgsql as $func$ begin

RETURN QUERY

27

with recursive graph(id_mainproduct, id_useproduct, path) as ( select sp.id_mainproduct, sp.id_useproduct, CAST

(sp.id_useproduct AS TEXT) as PATH

from spec_product as sp where sp.id_mainproduct = spIdToCheck union all

select spec_product.id_mainproduct, spec_product.id_useproduct, CAST ( graph.PATH ||' = > '|| spec_product.id_useproduct AS TEXT)

from spec_product inner join graph on graph.id_useproduct = spec_product.id_mainproduct

)

select func_price(t1.id, spIdToCheck), id from (select distinct graph.id_useproduct as id from graph) as t1;

end $func$;

select * from func_price(9,1);

/*функция: Высчитывает количество для заданного продукта вход: spIdToCheck - идентификатор того продукта, для которого расчитывается количество выход: Количество продукта

*/

CREATE OR REPLACE function func_price (

spIdToCheck integer, MainIdProd integer) RETURNS table (countprod bigint)

LANGUAGE plpgsql as $func$ begin

RETURN QUERY

with recursive graph(id_mainproductt, id_useproduct, path, countp) as (

select sp.id_mainproduct, sp.id_useproduct, CAST ( sp.id_useproduct|| ' = > ' || sp.id_mainproduct AS TEXT) as path, sp.countinsp

from spec_product as sp where sp.id_useproduct = spIdToCheck union all

28

select spec_product.id_mainproduct, spec_product.id_useproduct, CAST ( graph.PATH ||' = > '|| spec_product.id_mainproduct AS TEXT), spec_product.countinsp*graph.countp

from spec_product inner join graph on graph.id_mainproductt = spec_product.id_useproduct

)

select sum (t2.countp) from (select id_mainproductt, countp from graph where id_mainproductt = MainIdProd) as t2;

end $func$;

/*функция: На основании ранее перечисленных функций объединяет таблицы и выводит позиции для главного продуктав понятном виде

вход: idProd - идентификатор того продукта, для которого выводится список с количеством выход: Таблица с классом продукта, его названием, количеством и единицой измерения

*/

CREATE OR REPLACE function func_output (

idProd integer) RETURNS table (countProduct bigint, nameProduct text, nameClass text, nameUom text)

LANGUAGE plpgsql as $func$ begin

RETURN QUERY

select t2.countprod, t2.name_product, t2.name_class, uom.name_uom

from(

select t1.countprod, t1.name_product, pc.name_class, pc.id_uom from

(select countprod, name_product, id_class from func_count(idProd) as f left join product as p on p.id_product = f.id_useproduct) as t1

left join product_class pc on pc.id_class = t1.id_class) as

t2

left join unit_of_measure uom on uom.id_uom = t2.id_uom;

end $func$;

29

---------------------------------------------Заполнение таблиц -------

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

select add_class('Велосипед',null,1); select add_class('Горный',1,1); select add_class('Спортивный',1,1); select add_class('Прогулочный',1,1);

select add_class('Колёса', null, 1); select add_class('БольшиеКолёса', 5, 1); select add_class('МаленькиеКолёса', 5, 1); select add_class('СредниеКолёса', 5, 1);

select add_class('Руль', null, 1); select add_class('ТипА_Р', 9, 1); select add_class('ТипБ_Р', 9, 1); select add_class('ТипС_Р', 9, 1);

select add_class('Болты', null, 1); select add_class('ТипА_Б', 13, 1); select add_class('ТипБ_Б', 13, 1); select add_class('ТипС_Б', 13, 1);

select add_class('Крылья', null, 1); select add_class('Резиновые', 17, 1); select add_class('Железные', 17, 1);

select add_class('Спицы', null, 1); select add_class('ТипА_С', 20, 1); select add_class('ТипБ_С', 20, 1); select add_class('ТипС_С', 20, 1);

select add_class('Металл', null, 1); select add_class('ТипА_М', 24, 1); select add_class('ТипБ_М', 24, 1); select add_class('ТипС_М', 24, 1);

30