|
|
@@ -0,0 +1,2103 @@
|
|
|
+--
|
|
|
+-- PostgreSQL database dump
|
|
|
+--
|
|
|
+
|
|
|
+\restrict fMX8pe7fyPeennYB6eeK17lVC7rkBp0LxzYWCFMQgMflMYdB3BYjGmqxfiz2Aj2
|
|
|
+
|
|
|
+-- Dumped from database version 18.0
|
|
|
+-- Dumped by pg_dump version 18.4
|
|
|
+
|
|
|
+-- Started on 2026-06-30 18:28:52 MSK
|
|
|
+
|
|
|
+SET statement_timeout = 0;
|
|
|
+SET lock_timeout = 0;
|
|
|
+SET idle_in_transaction_session_timeout = 0;
|
|
|
+SET transaction_timeout = 0;
|
|
|
+SET client_encoding = 'UTF8';
|
|
|
+SET standard_conforming_strings = on;
|
|
|
+SELECT pg_catalog.set_config('search_path', '', false);
|
|
|
+SET check_function_bodies = false;
|
|
|
+SET xmloption = content;
|
|
|
+SET client_min_messages = warning;
|
|
|
+SET row_security = off;
|
|
|
+
|
|
|
+--
|
|
|
+-- TOC entry 16 (class 2615 OID 442818)
|
|
|
+-- Name: dyachkov_ya; Type: SCHEMA; Schema: -; Owner: dyachkov_ya
|
|
|
+--
|
|
|
+
|
|
|
+CREATE SCHEMA dyachkov_ya;
|
|
|
+
|
|
|
+
|
|
|
+ALTER SCHEMA dyachkov_ya OWNER TO dyachkov_ya;
|
|
|
+
|
|
|
+--
|
|
|
+-- TOC entry 1403 (class 1255 OID 443423)
|
|
|
+-- Name: add_user_with_phones(character varying, character varying, integer, integer, integer, character varying, real, integer, character varying, character varying); Type: PROCEDURE; Schema: dyachkov_ya; Owner: dyachkov_ya
|
|
|
+--
|
|
|
+
|
|
|
+CREATE PROCEDURE dyachkov_ya.add_user_with_phones(IN p_lastname character varying, IN p_name character varying, IN p_year_b integer, IN p_groups integer, IN p_age integer, IN p_category character varying DEFAULT NULL::character varying, IN p_debt real DEFAULT 0, IN p_level integer DEFAULT 1, IN p_home_phone character varying DEFAULT NULL::character varying, IN p_mobile_phone character varying DEFAULT NULL::character varying)
|
|
|
+ LANGUAGE plpgsql
|
|
|
+ AS $$
|
|
|
+DECLARE
|
|
|
+ v_has_phone BOOLEAN;
|
|
|
+BEGIN
|
|
|
+ BEGIN
|
|
|
+ -- Проверка наличия хотя бы одного телефона
|
|
|
+ v_has_phone := (p_home_phone IS NOT NULL AND p_home_phone != '') OR
|
|
|
+ (p_mobile_phone IS NOT NULL AND p_mobile_phone != '');
|
|
|
+
|
|
|
+ IF NOT v_has_phone THEN
|
|
|
+ RAISE EXCEPTION 'Необходимо указать хотя бы один телефон (домашний или мобильный) для связи с читателем';
|
|
|
+ END IF;
|
|
|
+
|
|
|
+ -- Вставка пользователя
|
|
|
+ INSERT INTO users (lastname, name, year_b, groups, age, category, debt, level, home_phone, mobile_phone)
|
|
|
+ VALUES (p_lastname, p_name, p_year_b, p_groups, p_age, p_category, p_debt, p_level, p_home_phone, p_mobile_phone);
|
|
|
+
|
|
|
+ COMMIT;
|
|
|
+ RAISE NOTICE 'Пользователь "% %" успешно добавлен', p_lastname, p_name;
|
|
|
+ RAISE NOTICE 'Телефоны: дом.%, моб.%',
|
|
|
+ COALESCE(p_home_phone, 'не указан'),
|
|
|
+ COALESCE(p_mobile_phone, 'не указан');
|
|
|
+
|
|
|
+ EXCEPTION
|
|
|
+ WHEN OTHERS THEN
|
|
|
+ ROLLBACK;
|
|
|
+ RAISE NOTICE 'ОШИБКА: %', SQLERRM;
|
|
|
+ END;
|
|
|
+END;
|
|
|
+$$;
|
|
|
+
|
|
|
+
|
|
|
+ALTER PROCEDURE dyachkov_ya.add_user_with_phones(IN p_lastname character varying, IN p_name character varying, IN p_year_b integer, IN p_groups integer, IN p_age integer, IN p_category character varying, IN p_debt real, IN p_level integer, IN p_home_phone character varying, IN p_mobile_phone character varying) OWNER TO dyachkov_ya;
|
|
|
+
|
|
|
+--
|
|
|
+-- TOC entry 1404 (class 1255 OID 443424)
|
|
|
+-- Name: authenticate_user(character varying, text); Type: FUNCTION; Schema: dyachkov_ya; Owner: dyachkov_ya
|
|
|
+--
|
|
|
+
|
|
|
+CREATE FUNCTION dyachkov_ya.authenticate_user(p_username character varying, p_password text) RETURNS TABLE(user_id integer, username character varying, decrypted_name text, role_name character varying, is_authenticated boolean)
|
|
|
+ LANGUAGE plpgsql
|
|
|
+ AS $$
|
|
|
+DECLARE
|
|
|
+ v_user_record RECORD;
|
|
|
+ v_decrypted_name TEXT;
|
|
|
+BEGIN
|
|
|
+ -- Поиск пользователя
|
|
|
+ SELECT u.id, u.username, u.encrypted_name, u.password_hash, r.role_name
|
|
|
+ INTO v_user_record
|
|
|
+ FROM system_users u
|
|
|
+ JOIN roles r ON u.role_id = r.id
|
|
|
+ WHERE u.username = p_username AND u.is_active = TRUE;
|
|
|
+
|
|
|
+ IF v_user_record.id IS NULL THEN
|
|
|
+ RETURN QUERY SELECT NULL::INTEGER, NULL::VARCHAR, NULL::TEXT, NULL::VARCHAR, FALSE::BOOLEAN;
|
|
|
+ RETURN;
|
|
|
+ END IF;
|
|
|
+
|
|
|
+ -- Проверка пароля
|
|
|
+ IF v_user_record.password_hash = crypt(p_password, v_user_record.password_hash) THEN
|
|
|
+ -- Расшифровываем имя
|
|
|
+ BEGIN
|
|
|
+ v_decrypted_name := convert_from(decrypt(decode(v_user_record.encrypted_name, 'base64'), 'master_key', 'aes'), 'UTF8');
|
|
|
+ EXCEPTION WHEN OTHERS THEN
|
|
|
+ v_decrypted_name := '[Ошибка расшифровки]';
|
|
|
+ END;
|
|
|
+
|
|
|
+ RETURN QUERY SELECT
|
|
|
+ v_user_record.id,
|
|
|
+ v_user_record.username,
|
|
|
+ v_decrypted_name,
|
|
|
+ v_user_record.role_name,
|
|
|
+ TRUE::BOOLEAN;
|
|
|
+ ELSE
|
|
|
+ RETURN QUERY SELECT NULL::INTEGER, NULL::VARCHAR, NULL::TEXT, NULL::VARCHAR, FALSE::BOOLEAN;
|
|
|
+ END IF;
|
|
|
+END;
|
|
|
+$$;
|
|
|
+
|
|
|
+
|
|
|
+ALTER FUNCTION dyachkov_ya.authenticate_user(p_username character varying, p_password text) OWNER TO dyachkov_ya;
|
|
|
+
|
|
|
+--
|
|
|
+-- TOC entry 1405 (class 1255 OID 443425)
|
|
|
+-- Name: autonomous_log(integer, real, real); Type: FUNCTION; Schema: dyachkov_ya; Owner: dyachkov_ya
|
|
|
+--
|
|
|
+
|
|
|
+CREATE FUNCTION dyachkov_ya.autonomous_log(p_book_bshifr integer, p_old_price real, p_new_price real) RETURNS void
|
|
|
+ LANGUAGE plpgsql
|
|
|
+ AS $$
|
|
|
+BEGIN
|
|
|
+ -- Имитация автономной транзакции
|
|
|
+ BEGIN
|
|
|
+ INSERT INTO logs (bk, cena_old, cena_new)
|
|
|
+ VALUES (p_book_bshifr, p_old_price, p_new_price);
|
|
|
+
|
|
|
+ -- Фиксируем лог независимо от основной транзакции
|
|
|
+ COMMIT;
|
|
|
+ RAISE NOTICE 'Лог сохранен автономно: книга bshifr=%, цена %.2f -> %.2f',
|
|
|
+ p_book_bshifr, p_old_price, p_new_price;
|
|
|
+ EXCEPTION
|
|
|
+ WHEN OTHERS THEN
|
|
|
+ RAISE NOTICE 'Не удалось сохранить лог: %', SQLERRM;
|
|
|
+ END;
|
|
|
+END;
|
|
|
+$$;
|
|
|
+
|
|
|
+
|
|
|
+ALTER FUNCTION dyachkov_ya.autonomous_log(p_book_bshifr integer, p_old_price real, p_new_price real) OWNER TO dyachkov_ya;
|
|
|
+
|
|
|
+--
|
|
|
+-- TOC entry 1406 (class 1255 OID 443426)
|
|
|
+-- Name: check_ticket_constraints(); Type: FUNCTION; Schema: dyachkov_ya; Owner: dyachkov_ya
|
|
|
+--
|
|
|
+
|
|
|
+CREATE FUNCTION dyachkov_ya.check_ticket_constraints() RETURNS trigger
|
|
|
+ LANGUAGE plpgsql
|
|
|
+ AS $$
|
|
|
+DECLARE
|
|
|
+user_exists BOOLEAN;
|
|
|
+book_exists BOOLEAN;
|
|
|
+BEGIN
|
|
|
+SELECT EXISTS (SELECT 1 FROM users WHERE id = NEW.user_id)
|
|
|
+INTO user_exists;
|
|
|
+IF NOT user_exists THEN
|
|
|
+RAISE EXCEPTION 'Ошибка: Пользователь с ID % не существует в таблице users. Запись в ticket не может быть добавлена.', NEW.user_id;
|
|
|
+END IF;
|
|
|
+SELECT EXISTS (SELECT 1 FROM book WHERE bshifr = NEW.book_id)
|
|
|
+INTO book_exists;
|
|
|
+IF NOT book_exists THEN
|
|
|
+RAISE EXCEPTION 'Ошибка: Книга с шифром % не существует в таблице book. Запись в ticket не может быть добавлена.', NEW.book_id;
|
|
|
+END IF;
|
|
|
+IF NEW.date_return IS NOT NULL AND NEW.date_of_issue IS NOT NULL THEN
|
|
|
+IF NEW.date_return < NEW.date_of_issue THEN
|
|
|
+RAISE EXCEPTION 'Ошибка: Дата возврата (%) не может быть раньше даты выдачи (%).', NEW.date_return, NEW.date_of_issue;
|
|
|
+END IF;
|
|
|
+END IF;
|
|
|
+RETURN NEW;
|
|
|
+END;
|
|
|
+$$;
|
|
|
+
|
|
|
+
|
|
|
+ALTER FUNCTION dyachkov_ya.check_ticket_constraints() OWNER TO dyachkov_ya;
|
|
|
+
|
|
|
+--
|
|
|
+-- TOC entry 1407 (class 1255 OID 443427)
|
|
|
+-- Name: check_user_access(character varying, character varying); Type: FUNCTION; Schema: dyachkov_ya; Owner: dyachkov_ya
|
|
|
+--
|
|
|
+
|
|
|
+CREATE FUNCTION dyachkov_ya.check_user_access(p_username character varying, p_required_role character varying) RETURNS boolean
|
|
|
+ LANGUAGE plpgsql
|
|
|
+ AS $$
|
|
|
+DECLARE
|
|
|
+ v_user_role VARCHAR(50);
|
|
|
+ v_has_access BOOLEAN := FALSE;
|
|
|
+BEGIN
|
|
|
+ -- Начинаем транзакцию
|
|
|
+ BEGIN
|
|
|
+ SELECT r.role_name INTO v_user_role
|
|
|
+ FROM system_users u
|
|
|
+ JOIN roles r ON u.role_id = r.id
|
|
|
+ WHERE u.username = p_username AND u.is_active = TRUE;
|
|
|
+
|
|
|
+ -- Проверка роли (admin имеет полный доступ)
|
|
|
+ IF v_user_role = 'admin' OR v_user_role = p_required_role THEN
|
|
|
+ v_has_access := TRUE;
|
|
|
+ END IF;
|
|
|
+
|
|
|
+ -- Логируем попытку доступа (в реальной системе)
|
|
|
+ INSERT INTO access_log (username, access_time, has_access, required_role)
|
|
|
+ VALUES (p_username, CURRENT_TIMESTAMP, v_has_access, p_required_role);
|
|
|
+
|
|
|
+ COMMIT;
|
|
|
+ EXCEPTION WHEN OTHERS THEN
|
|
|
+ ROLLBACK;
|
|
|
+ RAISE NOTICE 'Ошибка при проверке доступа: %', SQLERRM;
|
|
|
+ v_has_access := FALSE;
|
|
|
+ END;
|
|
|
+
|
|
|
+ RETURN v_has_access;
|
|
|
+END;
|
|
|
+$$;
|
|
|
+
|
|
|
+
|
|
|
+ALTER FUNCTION dyachkov_ya.check_user_access(p_username character varying, p_required_role character varying) OWNER TO dyachkov_ya;
|
|
|
+
|
|
|
+--
|
|
|
+-- TOC entry 1408 (class 1255 OID 443428)
|
|
|
+-- Name: check_user_by_email(text); Type: FUNCTION; Schema: dyachkov_ya; Owner: dyachkov_ya
|
|
|
+--
|
|
|
+
|
|
|
+CREATE FUNCTION dyachkov_ya.check_user_by_email(p_email text) RETURNS integer
|
|
|
+ LANGUAGE plpgsql
|
|
|
+ AS $$
|
|
|
+DECLARE
|
|
|
+ user_exists INTEGER;
|
|
|
+ decrypted_email TEXT;
|
|
|
+ user_record RECORD;
|
|
|
+BEGIN
|
|
|
+ user_exists := 0;
|
|
|
+
|
|
|
+ -- Проходим по всем пользователям и расшифровываем email для сравнения
|
|
|
+ FOR user_record IN SELECT id, email FROM users LOOP
|
|
|
+ IF user_record.email IS NOT NULL THEN
|
|
|
+ BEGIN
|
|
|
+ decrypted_email := decrypt_email(user_record.email);
|
|
|
+ IF decrypted_email = p_email THEN
|
|
|
+ user_exists := 1;
|
|
|
+ EXIT;
|
|
|
+ END IF;
|
|
|
+ EXCEPTION WHEN OTHERS THEN
|
|
|
+ -- Пропускаем ошибки дешифрования
|
|
|
+ CONTINUE;
|
|
|
+ END;
|
|
|
+ END IF;
|
|
|
+ END LOOP;
|
|
|
+
|
|
|
+ RETURN user_exists;
|
|
|
+END;
|
|
|
+$$;
|
|
|
+
|
|
|
+
|
|
|
+ALTER FUNCTION dyachkov_ya.check_user_by_email(p_email text) OWNER TO dyachkov_ya;
|
|
|
+
|
|
|
+--
|
|
|
+-- TOC entry 1409 (class 1255 OID 443429)
|
|
|
+-- Name: clean_string(text); Type: FUNCTION; Schema: dyachkov_ya; Owner: dyachkov_ya
|
|
|
+--
|
|
|
+
|
|
|
+CREATE FUNCTION dyachkov_ya.clean_string(input text) RETURNS text
|
|
|
+ LANGUAGE plpgsql
|
|
|
+ AS $$
|
|
|
+BEGIN
|
|
|
+ IF input IS NULL THEN
|
|
|
+ RETURN NULL;
|
|
|
+ END IF;
|
|
|
+ -- Удаление лишних пробелов, замена нескольких пробелов на один
|
|
|
+ RETURN TRIM(REGEXP_REPLACE(input, '\s+', ' ', 'g'));
|
|
|
+END;
|
|
|
+$$;
|
|
|
+
|
|
|
+
|
|
|
+ALTER FUNCTION dyachkov_ya.clean_string(input text) OWNER TO dyachkov_ya;
|
|
|
+
|
|
|
+--
|
|
|
+-- TOC entry 1410 (class 1255 OID 443430)
|
|
|
+-- Name: count_books_by_user(character varying, character varying); Type: FUNCTION; Schema: dyachkov_ya; Owner: dyachkov_ya
|
|
|
+--
|
|
|
+
|
|
|
+CREATE FUNCTION dyachkov_ya.count_books_by_user(p_lastname character varying, p_name character varying) RETURNS integer
|
|
|
+ LANGUAGE plpgsql
|
|
|
+ AS $$
|
|
|
+DECLARE
|
|
|
+books_count INTEGER := 0;
|
|
|
+BEGIN
|
|
|
+IF p_lastname IS NULL OR p_name IS NULL THEN
|
|
|
+RAISE EXCEPTION 'Фамилия и имя пользователя не могут быть NULL.';
|
|
|
+END IF;
|
|
|
+SELECT COUNT(t.id)
|
|
|
+INTO books_count
|
|
|
+FROM ticket t
|
|
|
+JOIN users u ON t.user_id = u.id
|
|
|
+WHERE u.lastname = p_lastname AND u.name = p_name;
|
|
|
+RETURN books_count;
|
|
|
+END;
|
|
|
+$$;
|
|
|
+
|
|
|
+
|
|
|
+ALTER FUNCTION dyachkov_ya.count_books_by_user(p_lastname character varying, p_name character varying) OWNER TO dyachkov_ya;
|
|
|
+
|
|
|
+--
|
|
|
+-- TOC entry 1411 (class 1255 OID 443431)
|
|
|
+-- Name: count_unique_readers_in_month(integer); Type: FUNCTION; Schema: dyachkov_ya; Owner: dyachkov_ya
|
|
|
+--
|
|
|
+
|
|
|
+CREATE FUNCTION dyachkov_ya.count_unique_readers_in_month(p_month integer) RETURNS bigint
|
|
|
+ LANGUAGE plpgsql
|
|
|
+ AS $$
|
|
|
+DECLARE
|
|
|
+readers_count BIGINT := 0;
|
|
|
+BEGIN
|
|
|
+IF p_month IS NULL OR p_month < 1 OR p_month > 12 THEN
|
|
|
+RAISE EXCEPTION 'Номер месяца должен быть от 1 до 12.';
|
|
|
+END IF;
|
|
|
+SELECT COUNT(DISTINCT t.user_id)
|
|
|
+INTO readers_count
|
|
|
+FROM ticket t
|
|
|
+WHERE EXTRACT(MONTH FROM t.date_of_issue) = p_month; -- EXTRACT(MONTH FROM ...) извлекает номер месяца из даты
|
|
|
+RETURN readers_count;
|
|
|
+END;
|
|
|
+$$;
|
|
|
+
|
|
|
+
|
|
|
+ALTER FUNCTION dyachkov_ya.count_unique_readers_in_month(p_month integer) OWNER TO dyachkov_ya;
|
|
|
+
|
|
|
+--
|
|
|
+-- TOC entry 1412 (class 1255 OID 443432)
|
|
|
+-- Name: days_since_issue(integer); Type: FUNCTION; Schema: dyachkov_ya; Owner: dyachkov_ya
|
|
|
+--
|
|
|
+
|
|
|
+CREATE FUNCTION dyachkov_ya.days_since_issue(p_ticket_id integer) RETURNS integer
|
|
|
+ LANGUAGE plpgsql
|
|
|
+ AS $$
|
|
|
+DECLARE
|
|
|
+issue_date DATE;
|
|
|
+days_elapsed INTEGER;
|
|
|
+BEGIN
|
|
|
+SELECT date_of_issue
|
|
|
+INTO issue_date
|
|
|
+FROM ticket
|
|
|
+WHERE id = p_ticket_id;
|
|
|
+IF NOT FOUND THEN
|
|
|
+RAISE EXCEPTION 'Билет с ID % не найден.', p_ticket_id;
|
|
|
+END IF;
|
|
|
+days_elapsed := Kol_Dney(issue_date, CURRENT_DATE::date);
|
|
|
+RETURN days_elapsed;
|
|
|
+END;
|
|
|
+$$;
|
|
|
+
|
|
|
+
|
|
|
+ALTER FUNCTION dyachkov_ya.days_since_issue(p_ticket_id integer) OWNER TO dyachkov_ya;
|
|
|
+
|
|
|
+--
|
|
|
+-- TOC entry 1413 (class 1255 OID 443433)
|
|
|
+-- Name: decrypt_data(text, text); Type: FUNCTION; Schema: dyachkov_ya; Owner: dyachkov_ya
|
|
|
+--
|
|
|
+
|
|
|
+CREATE FUNCTION dyachkov_ya.decrypt_data(p_encrypted text, p_key text DEFAULT 'default_key'::text) RETURNS text
|
|
|
+ LANGUAGE plpgsql
|
|
|
+ AS $$
|
|
|
+DECLARE
|
|
|
+ result TEXT;
|
|
|
+BEGIN
|
|
|
+ result := convert_from(decrypt(decode(p_encrypted, 'hex'), p_key, 'aes'), 'UTF8');
|
|
|
+ RETURN result;
|
|
|
+EXCEPTION WHEN OTHERS THEN
|
|
|
+ RETURN 'Ошибка дешифрования';
|
|
|
+END;
|
|
|
+$$;
|
|
|
+
|
|
|
+
|
|
|
+ALTER FUNCTION dyachkov_ya.decrypt_data(p_encrypted text, p_key text) OWNER TO dyachkov_ya;
|
|
|
+
|
|
|
+--
|
|
|
+-- TOC entry 1414 (class 1255 OID 443435)
|
|
|
+-- Name: decrypt_email(text); Type: FUNCTION; Schema: dyachkov_ya; Owner: dyachkov_ya
|
|
|
+--
|
|
|
+
|
|
|
+CREATE FUNCTION dyachkov_ya.decrypt_email(encrypted_email text) RETURNS text
|
|
|
+ LANGUAGE plpgsql
|
|
|
+ AS $$
|
|
|
+DECLARE
|
|
|
+ decrypted_email TEXT;
|
|
|
+BEGIN
|
|
|
+ IF encrypted_email IS NULL THEN
|
|
|
+ RETURN NULL;
|
|
|
+ END IF;
|
|
|
+
|
|
|
+ BEGIN
|
|
|
+ decrypted_email := convert_from(decrypt(decode(encrypted_email, 'base64'), 'my_secret_key', 'aes'), 'UTF8');
|
|
|
+ RETURN decrypted_email;
|
|
|
+ EXCEPTION WHEN OTHERS THEN
|
|
|
+ RETURN encrypted_email; -- Если не зашифровано, возвращаем как есть
|
|
|
+ END;
|
|
|
+END;
|
|
|
+$$;
|
|
|
+
|
|
|
+
|
|
|
+ALTER FUNCTION dyachkov_ya.decrypt_email(encrypted_email text) OWNER TO dyachkov_ya;
|
|
|
+
|
|
|
+--
|
|
|
+-- TOC entry 1415 (class 1255 OID 443436)
|
|
|
+-- Name: delete_book(integer); Type: PROCEDURE; Schema: dyachkov_ya; Owner: dyachkov_ya
|
|
|
+--
|
|
|
+
|
|
|
+CREATE PROCEDURE dyachkov_ya.delete_book(IN p_bshifr integer)
|
|
|
+ LANGUAGE plpgsql
|
|
|
+ AS $$
|
|
|
+DECLARE
|
|
|
+ v_title VARCHAR(25);
|
|
|
+ v_vidano BOOLEAN;
|
|
|
+BEGIN
|
|
|
+ BEGIN
|
|
|
+ -- Получаем информацию о книге
|
|
|
+ SELECT title, vidano INTO v_title, v_vidano
|
|
|
+ FROM book WHERE bshifr = p_bshifr;
|
|
|
+
|
|
|
+ IF NOT FOUND THEN
|
|
|
+ RAISE EXCEPTION 'Книга с bshifr=% не найдена', p_bshifr;
|
|
|
+ END IF;
|
|
|
+
|
|
|
+ -- Проверка: если книга на руках - запрещаем удаление
|
|
|
+ IF v_vidano = TRUE THEN
|
|
|
+ RAISE EXCEPTION 'Невозможно удалить книгу "%" - экземпляр находится на руках у читателя', v_title;
|
|
|
+ END IF;
|
|
|
+
|
|
|
+ -- Удаляем книгу
|
|
|
+ DELETE FROM book WHERE bshifr = p_bshifr;
|
|
|
+
|
|
|
+ COMMIT;
|
|
|
+ RAISE NOTICE 'Книга "% (bshifr=%) успешно удалена', v_title, p_bshifr;
|
|
|
+
|
|
|
+ EXCEPTION
|
|
|
+ WHEN OTHERS THEN
|
|
|
+ ROLLBACK;
|
|
|
+ RAISE NOTICE 'ОШИБКА: %', SQLERRM;
|
|
|
+ END;
|
|
|
+END;
|
|
|
+$$;
|
|
|
+
|
|
|
+
|
|
|
+ALTER PROCEDURE dyachkov_ya.delete_book(IN p_bshifr integer) OWNER TO dyachkov_ya;
|
|
|
+
|
|
|
+--
|
|
|
+-- TOC entry 1416 (class 1255 OID 443437)
|
|
|
+-- Name: delete_reader(integer); Type: PROCEDURE; Schema: dyachkov_ya; Owner: dyachkov_ya
|
|
|
+--
|
|
|
+
|
|
|
+CREATE PROCEDURE dyachkov_ya.delete_reader(IN p_user_id integer)
|
|
|
+ LANGUAGE plpgsql
|
|
|
+ AS $$
|
|
|
+DECLARE
|
|
|
+ v_books_count INTEGER;
|
|
|
+ v_username VARCHAR(50);
|
|
|
+ v_books_list TEXT;
|
|
|
+BEGIN
|
|
|
+ BEGIN
|
|
|
+ -- Получаем имя пользователя
|
|
|
+ SELECT lastname || ' ' || name INTO v_username
|
|
|
+ FROM users WHERE id = p_user_id;
|
|
|
+
|
|
|
+ IF NOT FOUND THEN
|
|
|
+ RAISE EXCEPTION 'Пользователь с ID % не найден', p_user_id;
|
|
|
+ END IF;
|
|
|
+
|
|
|
+ -- Подсчет книг на руках
|
|
|
+ SELECT COUNT(*) INTO v_books_count
|
|
|
+ FROM ticket
|
|
|
+ WHERE user_id = p_user_id
|
|
|
+ AND (date_of_return IS NULL OR date_of_return > CURRENT_DATE);
|
|
|
+
|
|
|
+ -- Если есть книги - формируем список и выдаем ошибку
|
|
|
+ IF v_books_count > 0 THEN
|
|
|
+ SELECT STRING_AGG(b.title, ', ') INTO v_books_list
|
|
|
+ FROM ticket t
|
|
|
+ JOIN book b ON t.book_id = b.bshifr
|
|
|
+ WHERE t.user_id = p_user_id
|
|
|
+ AND (t.date_of_return IS NULL OR t.date_of_return > CURRENT_DATE);
|
|
|
+
|
|
|
+ RAISE EXCEPTION 'Невозможно удалить читателя "%". У него на руках % книг: %',
|
|
|
+ v_username, v_books_count, v_books_list;
|
|
|
+ END IF;
|
|
|
+
|
|
|
+ -- Удаляем пользователя
|
|
|
+ DELETE FROM users WHERE id = p_user_id;
|
|
|
+
|
|
|
+ COMMIT;
|
|
|
+ RAISE NOTICE 'Читатель "% (ID: %) успешно удален', v_username, p_user_id;
|
|
|
+
|
|
|
+ EXCEPTION
|
|
|
+ WHEN OTHERS THEN
|
|
|
+ ROLLBACK;
|
|
|
+ RAISE NOTICE 'ОШИБКА: %', SQLERRM;
|
|
|
+ END;
|
|
|
+END;
|
|
|
+$$;
|
|
|
+
|
|
|
+
|
|
|
+ALTER PROCEDURE dyachkov_ya.delete_reader(IN p_user_id integer) OWNER TO dyachkov_ya;
|
|
|
+
|
|
|
+--
|
|
|
+-- TOC entry 1417 (class 1255 OID 443438)
|
|
|
+-- Name: encrypt_data(text, text); Type: FUNCTION; Schema: dyachkov_ya; Owner: dyachkov_ya
|
|
|
+--
|
|
|
+
|
|
|
+CREATE FUNCTION dyachkov_ya.encrypt_data(p_data text, p_key text DEFAULT 'default_key'::text) RETURNS text
|
|
|
+ LANGUAGE plpgsql
|
|
|
+ AS $$
|
|
|
+BEGIN
|
|
|
+ RETURN encode(encrypt(p_data::bytea, p_key, 'aes'), 'hex');
|
|
|
+END;
|
|
|
+$$;
|
|
|
+
|
|
|
+
|
|
|
+ALTER FUNCTION dyachkov_ya.encrypt_data(p_data text, p_key text) OWNER TO dyachkov_ya;
|
|
|
+
|
|
|
+--
|
|
|
+-- TOC entry 1418 (class 1255 OID 443439)
|
|
|
+-- Name: encrypt_email(); Type: FUNCTION; Schema: dyachkov_ya; Owner: dyachkov_ya
|
|
|
+--
|
|
|
+
|
|
|
+CREATE FUNCTION dyachkov_ya.encrypt_email() RETURNS trigger
|
|
|
+ LANGUAGE plpgsql
|
|
|
+ AS $$
|
|
|
+BEGIN
|
|
|
+ IF NEW.email IS NOT NULL AND NEW.email != '' THEN
|
|
|
+ -- Используем симметричное шифрование с ключом 'secret_key'
|
|
|
+ NEW.email := encode(encrypt(NEW.email::bytea, 'my_secret_key', 'aes'), 'base64');
|
|
|
+ END IF;
|
|
|
+ RETURN NEW;
|
|
|
+END;
|
|
|
+$$;
|
|
|
+
|
|
|
+
|
|
|
+ALTER FUNCTION dyachkov_ya.encrypt_email() OWNER TO dyachkov_ya;
|
|
|
+
|
|
|
+--
|
|
|
+-- TOC entry 1419 (class 1255 OID 443440)
|
|
|
+-- Name: generate_random_id_for_usernew(); Type: FUNCTION; Schema: dyachkov_ya; Owner: dyachkov_ya
|
|
|
+--
|
|
|
+
|
|
|
+CREATE FUNCTION dyachkov_ya.generate_random_id_for_usernew() RETURNS trigger
|
|
|
+ LANGUAGE plpgsql
|
|
|
+ AS $$
|
|
|
+DECLARE
|
|
|
+ new_id INTEGER;
|
|
|
+ is_unique BOOLEAN := FALSE;
|
|
|
+ max_attempts INTEGER := 100; -- Количество попыток генерации ID
|
|
|
+ current_attempt INTEGER := 0;
|
|
|
+BEGIN
|
|
|
+ -- Если ID уже предоставлен (НЕ NULL), оставляем его.
|
|
|
+ IF NEW.id IS NOT NULL THEN
|
|
|
+ RETURN NEW;
|
|
|
+ END IF;
|
|
|
+
|
|
|
+ -- Генерируем новый ID, пока он не станет уникальным.
|
|
|
+ WHILE NOT is_unique LOOP
|
|
|
+ -- Генерируем случайное число (диапазон 1 - 1000000).
|
|
|
+ new_id := floor(random() * 1000000 + 1);
|
|
|
+
|
|
|
+ -- Проверяем уникальность ID.
|
|
|
+ IF NOT EXISTS (SELECT 1 FROM usernew WHERE id = new_id) THEN
|
|
|
+ is_unique := TRUE;
|
|
|
+ END IF;
|
|
|
+
|
|
|
+ current_attempt := current_attempt + 1;
|
|
|
+ -- Защита от бесконечного цикла.
|
|
|
+ IF current_attempt > max_attempts THEN
|
|
|
+ RAISE EXCEPTION 'Не удалось сгенерировать уникальный ID для usernew после % попыток.', max_attempts;
|
|
|
+ END IF;
|
|
|
+ END LOOP;
|
|
|
+
|
|
|
+ -- Присваиваем сгенерированный ID.
|
|
|
+ NEW.id := new_id;
|
|
|
+
|
|
|
+ RETURN NEW;
|
|
|
+END;
|
|
|
+$$;
|
|
|
+
|
|
|
+
|
|
|
+ALTER FUNCTION dyachkov_ya.generate_random_id_for_usernew() OWNER TO dyachkov_ya;
|
|
|
+
|
|
|
+--
|
|
|
+-- TOC entry 1420 (class 1255 OID 443441)
|
|
|
+-- Name: generate_sentence_from_dict(integer, text); Type: FUNCTION; Schema: dyachkov_ya; Owner: dyachkov_ya
|
|
|
+--
|
|
|
+
|
|
|
+CREATE FUNCTION dyachkov_ya.generate_sentence_from_dict(p_word_count integer, p_separator text DEFAULT ' '::text) RETURNS text
|
|
|
+ LANGUAGE plpgsql
|
|
|
+ AS $$
|
|
|
+DECLARE
|
|
|
+ v_words TEXT[];
|
|
|
+ v_sentence TEXT := '';
|
|
|
+ v_capitalized_word TEXT;
|
|
|
+ i INTEGER;
|
|
|
+BEGIN
|
|
|
+ -- Получаем случайные слова
|
|
|
+ v_words := get_random_words(p_word_count);
|
|
|
+
|
|
|
+ -- Формируем предложение
|
|
|
+ FOR i IN 1..array_length(v_words, 1) LOOP
|
|
|
+ IF i = 1 THEN
|
|
|
+ -- Первое слово с заглавной буквы
|
|
|
+ v_sentence := v_sentence || initcap(v_words[i]);
|
|
|
+ ELSE
|
|
|
+ v_sentence := v_sentence || p_separator || lower(v_words[i]);
|
|
|
+ END IF;
|
|
|
+ END LOOP;
|
|
|
+
|
|
|
+ -- Добавляем точку в конце
|
|
|
+ v_sentence := v_sentence || '.';
|
|
|
+
|
|
|
+ RETURN v_sentence;
|
|
|
+END;
|
|
|
+$$;
|
|
|
+
|
|
|
+
|
|
|
+ALTER FUNCTION dyachkov_ya.generate_sentence_from_dict(p_word_count integer, p_separator text) OWNER TO dyachkov_ya;
|
|
|
+
|
|
|
+--
|
|
|
+-- TOC entry 1421 (class 1255 OID 443442)
|
|
|
+-- Name: generate_uuid_and_time(); Type: FUNCTION; Schema: dyachkov_ya; Owner: dyachkov_ya
|
|
|
+--
|
|
|
+
|
|
|
+CREATE FUNCTION dyachkov_ya.generate_uuid_and_time() RETURNS trigger
|
|
|
+ LANGUAGE plpgsql
|
|
|
+ AS $$
|
|
|
+BEGIN
|
|
|
+ IF NEW.uuid IS NULL THEN
|
|
|
+ NEW.uuid := gen_random_uuid();
|
|
|
+ END IF;
|
|
|
+ NEW.time_created := CURRENT_TIMESTAMP;
|
|
|
+ RETURN NEW;
|
|
|
+END;
|
|
|
+$$;
|
|
|
+
|
|
|
+
|
|
|
+ALTER FUNCTION dyachkov_ya.generate_uuid_and_time() OWNER TO dyachkov_ya;
|
|
|
+
|
|
|
+--
|
|
|
+-- TOC entry 1849 (class 1255 OID 444742)
|
|
|
+-- Name: get_exhibit_count_by_author(integer); Type: FUNCTION; Schema: dyachkov_ya; Owner: dyachkov_ya
|
|
|
+--
|
|
|
+
|
|
|
+CREATE FUNCTION dyachkov_ya.get_exhibit_count_by_author(author_id integer) RETURNS integer
|
|
|
+ LANGUAGE plpgsql
|
|
|
+ AS $$
|
|
|
+DECLARE
|
|
|
+ exhibit_count INTEGER;
|
|
|
+BEGIN
|
|
|
+ SELECT COUNT(*) INTO exhibit_count
|
|
|
+ FROM Exhibit
|
|
|
+ WHERE id_creator = author_id;
|
|
|
+
|
|
|
+ RETURN exhibit_count;
|
|
|
+END;
|
|
|
+$$;
|
|
|
+
|
|
|
+
|
|
|
+ALTER FUNCTION dyachkov_ya.get_exhibit_count_by_author(author_id integer) OWNER TO dyachkov_ya;
|
|
|
+
|
|
|
+--
|
|
|
+-- TOC entry 1422 (class 1255 OID 443443)
|
|
|
+-- Name: get_most_expensive_book_by_author(character varying); Type: FUNCTION; Schema: dyachkov_ya; Owner: dyachkov_ya
|
|
|
+--
|
|
|
+
|
|
|
+CREATE FUNCTION dyachkov_ya.get_most_expensive_book_by_author(p_author_lastname character varying) RETURNS character varying
|
|
|
+ LANGUAGE plpgsql
|
|
|
+ AS $$
|
|
|
+DECLARE
|
|
|
+book_title_result VARCHAR(255);
|
|
|
+BEGIN
|
|
|
+IF p_author_lastname IS NULL THEN
|
|
|
+RAISE EXCEPTION 'Фамилия автора не может быть NULL.';
|
|
|
+END IF;
|
|
|
+SELECT b.title
|
|
|
+INTO book_title_result
|
|
|
+FROM book b
|
|
|
+JOIN author a ON b.id_author = a.id
|
|
|
+WHERE a.lastname = p_author_lastname
|
|
|
+ORDER BY b.price DESC
|
|
|
+LIMIT 1;
|
|
|
+IF NOT FOUND THEN
|
|
|
+RAISE NOTICE 'Автор "%" не найден или у него нет книг в базе.', p_author_lastname;
|
|
|
+RETURN NULL; -- Возвращаем NULL, если ничего не найдено.
|
|
|
+END IF;
|
|
|
+RETURN book_title_result;
|
|
|
+END;
|
|
|
+$$;
|
|
|
+
|
|
|
+
|
|
|
+ALTER FUNCTION dyachkov_ya.get_most_expensive_book_by_author(p_author_lastname character varying) OWNER TO dyachkov_ya;
|
|
|
+
|
|
|
+--
|
|
|
+-- TOC entry 1423 (class 1255 OID 443444)
|
|
|
+-- Name: get_random_sentence(integer); Type: FUNCTION; Schema: dyachkov_ya; Owner: dyachkov_ya
|
|
|
+--
|
|
|
+
|
|
|
+CREATE FUNCTION dyachkov_ya.get_random_sentence(word_count integer DEFAULT 5) RETURNS text
|
|
|
+ LANGUAGE plpgsql
|
|
|
+ AS $$
|
|
|
+DECLARE
|
|
|
+ words TEXT[];
|
|
|
+ sentence TEXT := '';
|
|
|
+ i INTEGER;
|
|
|
+BEGIN
|
|
|
+ words := get_random_words(word_count);
|
|
|
+
|
|
|
+ FOR i IN 1..array_length(words, 1) LOOP
|
|
|
+ IF i > 1 THEN
|
|
|
+ sentence := sentence || ' ';
|
|
|
+ END IF;
|
|
|
+ sentence := sentence || words[i];
|
|
|
+ END LOOP;
|
|
|
+
|
|
|
+ RETURN sentence || '.';
|
|
|
+END;
|
|
|
+$$;
|
|
|
+
|
|
|
+
|
|
|
+ALTER FUNCTION dyachkov_ya.get_random_sentence(word_count integer) OWNER TO dyachkov_ya;
|
|
|
+
|
|
|
+--
|
|
|
+-- TOC entry 1424 (class 1255 OID 443445)
|
|
|
+-- Name: get_random_words(integer); Type: FUNCTION; Schema: dyachkov_ya; Owner: dyachkov_ya
|
|
|
+--
|
|
|
+
|
|
|
+CREATE FUNCTION dyachkov_ya.get_random_words(word_count integer DEFAULT 1) RETURNS text[]
|
|
|
+ LANGUAGE plpgsql
|
|
|
+ AS $$
|
|
|
+DECLARE
|
|
|
+ words_array TEXT[];
|
|
|
+ result_array TEXT[] := '{}';
|
|
|
+ i INTEGER;
|
|
|
+ random_index INTEGER;
|
|
|
+BEGIN
|
|
|
+ -- Пытаемся прочитать файл со словами
|
|
|
+ BEGIN
|
|
|
+ SELECT string_to_array(pg_read_file('/usr/share/dict/words', 0, 1000000), E'\n') INTO words_array;
|
|
|
+ EXCEPTION WHEN OTHERS THEN
|
|
|
+ -- Если файл не доступен, используем встроенный словарь
|
|
|
+ words_array := ARRAY['apple', 'table', 'chair', 'house', 'computer', 'program', 'database', 'security', 'encryption', 'hash'];
|
|
|
+ END;
|
|
|
+
|
|
|
+ -- Проверяем, что массив не пустой
|
|
|
+ IF array_length(words_array, 1) IS NULL THEN
|
|
|
+ words_array := ARRAY['apple', 'table', 'chair', 'house', 'computer'];
|
|
|
+ END IF;
|
|
|
+
|
|
|
+ -- Выбираем случайные слова
|
|
|
+ FOR i IN 1..word_count LOOP
|
|
|
+ random_index := 1 + floor(random() * array_length(words_array, 1))::INTEGER;
|
|
|
+ result_array := array_append(result_array, words_array[random_index]);
|
|
|
+ END LOOP;
|
|
|
+
|
|
|
+ RETURN result_array;
|
|
|
+END;
|
|
|
+$$;
|
|
|
+
|
|
|
+
|
|
|
+ALTER FUNCTION dyachkov_ya.get_random_words(word_count integer) OWNER TO dyachkov_ya;
|
|
|
+
|
|
|
+--
|
|
|
+-- TOC entry 1425 (class 1255 OID 443446)
|
|
|
+-- Name: get_ticket_details_refcursor(integer); Type: FUNCTION; Schema: dyachkov_ya; Owner: dyachkov_ya
|
|
|
+--
|
|
|
+
|
|
|
+CREATE FUNCTION dyachkov_ya.get_ticket_details_refcursor(p_ticket_id integer) RETURNS refcursor
|
|
|
+ LANGUAGE plpgsql
|
|
|
+ AS $$
|
|
|
+DECLARE
|
|
|
+ticket_cur REFCURSOR;
|
|
|
+BEGIN
|
|
|
+IF p_ticket_id IS NULL THEN
|
|
|
+RAISE EXCEPTION 'ID билета не может быть NULL.';
|
|
|
+END IF;
|
|
|
+OPEN ticket_cur FOR
|
|
|
+SELECT
|
|
|
+u.lastname AS user_lastname,
|
|
|
+b.title AS book_title,
|
|
|
+t.date_of_issue AS ticket_date
|
|
|
+FROM ticket t
|
|
|
+JOIN users u ON t.user_id = u.id
|
|
|
+JOIN book b ON t.book_id = b.bshifr
|
|
|
+WHERE t.id = p_ticket_id;
|
|
|
+RETURN ticket_cur;
|
|
|
+END;
|
|
|
+$$;
|
|
|
+
|
|
|
+
|
|
|
+ALTER FUNCTION dyachkov_ya.get_ticket_details_refcursor(p_ticket_id integer) OWNER TO dyachkov_ya;
|
|
|
+
|
|
|
+--
|
|
|
+-- TOC entry 1838 (class 1255 OID 444504)
|
|
|
+-- Name: getaverageratingforexhibit(integer); Type: FUNCTION; Schema: dyachkov_ya; Owner: dyachkov_ya
|
|
|
+--
|
|
|
+
|
|
|
+CREATE FUNCTION dyachkov_ya.getaverageratingforexhibit(exhibit_id integer) RETURNS numeric
|
|
|
+ LANGUAGE plpgsql
|
|
|
+ AS $$
|
|
|
+DECLARE
|
|
|
+ avg_rating DECIMAL(3,2);
|
|
|
+BEGIN
|
|
|
+ SELECT AVG(exhibit_rating) INTO avg_rating
|
|
|
+ FROM Viewing
|
|
|
+ WHERE id_exhibit = exhibit_id;
|
|
|
+
|
|
|
+ RETURN COALESCE(avg_rating, 0);
|
|
|
+END;
|
|
|
+$$;
|
|
|
+
|
|
|
+
|
|
|
+ALTER FUNCTION dyachkov_ya.getaverageratingforexhibit(exhibit_id integer) OWNER TO dyachkov_ya;
|
|
|
+
|
|
|
+--
|
|
|
+-- TOC entry 1836 (class 1255 OID 444502)
|
|
|
+-- Name: getexhibitcountbyauthor(integer); Type: FUNCTION; Schema: dyachkov_ya; Owner: dyachkov_ya
|
|
|
+--
|
|
|
+
|
|
|
+CREATE FUNCTION dyachkov_ya.getexhibitcountbyauthor(author_id integer) RETURNS integer
|
|
|
+ LANGUAGE plpgsql
|
|
|
+ AS $$
|
|
|
+DECLARE
|
|
|
+ exhibit_count INT;
|
|
|
+BEGIN
|
|
|
+ SELECT COUNT(*) INTO exhibit_count
|
|
|
+ FROM Exhibit
|
|
|
+ WHERE id_creator = author_id;
|
|
|
+
|
|
|
+ RETURN exhibit_count;
|
|
|
+END;
|
|
|
+$$;
|
|
|
+
|
|
|
+
|
|
|
+ALTER FUNCTION dyachkov_ya.getexhibitcountbyauthor(author_id integer) OWNER TO dyachkov_ya;
|
|
|
+
|
|
|
+--
|
|
|
+-- TOC entry 1837 (class 1255 OID 444503)
|
|
|
+-- Name: getexhibitsbyauthor(integer); Type: FUNCTION; Schema: dyachkov_ya; Owner: dyachkov_ya
|
|
|
+--
|
|
|
+
|
|
|
+CREATE FUNCTION dyachkov_ya.getexhibitsbyauthor(author_id integer) RETURNS TABLE(id_exhibit integer, type character varying, creation_date date, copy_price numeric, creation_cost numeric)
|
|
|
+ LANGUAGE plpgsql
|
|
|
+ AS $$
|
|
|
+BEGIN
|
|
|
+ RETURN QUERY
|
|
|
+ SELECT e.id_exhibit, e.type, e.creation_date, e.copy_price, e.creation_cost
|
|
|
+ FROM Exhibit e
|
|
|
+ WHERE e.id_creator = author_id;
|
|
|
+END;
|
|
|
+$$;
|
|
|
+
|
|
|
+
|
|
|
+ALTER FUNCTION dyachkov_ya.getexhibitsbyauthor(author_id integer) OWNER TO dyachkov_ya;
|
|
|
+
|
|
|
+--
|
|
|
+-- TOC entry 1840 (class 1255 OID 444506)
|
|
|
+-- Name: getmuseumtotalvalue(integer); Type: FUNCTION; Schema: dyachkov_ya; Owner: dyachkov_ya
|
|
|
+--
|
|
|
+
|
|
|
+CREATE FUNCTION dyachkov_ya.getmuseumtotalvalue(museum_id integer) RETURNS numeric
|
|
|
+ LANGUAGE plpgsql
|
|
|
+ AS $$
|
|
|
+DECLARE
|
|
|
+ total_value DECIMAL(15,2);
|
|
|
+BEGIN
|
|
|
+ SELECT SUM(e.copy_price) INTO total_value
|
|
|
+ FROM Exhibit e
|
|
|
+ WHERE e.id_museum = museum_id;
|
|
|
+
|
|
|
+ RETURN COALESCE(total_value, 0);
|
|
|
+END;
|
|
|
+$$;
|
|
|
+
|
|
|
+
|
|
|
+ALTER FUNCTION dyachkov_ya.getmuseumtotalvalue(museum_id integer) OWNER TO dyachkov_ya;
|
|
|
+
|
|
|
+--
|
|
|
+-- TOC entry 1839 (class 1255 OID 444505)
|
|
|
+-- Name: gettop5expensiveexhibits(); Type: FUNCTION; Schema: dyachkov_ya; Owner: dyachkov_ya
|
|
|
+--
|
|
|
+
|
|
|
+CREATE FUNCTION dyachkov_ya.gettop5expensiveexhibits() RETURNS TABLE(id_exhibit integer, type character varying, copy_price numeric, author_name character varying)
|
|
|
+ LANGUAGE plpgsql
|
|
|
+ AS $$
|
|
|
+BEGIN
|
|
|
+ RETURN QUERY
|
|
|
+ SELECT e.id_exhibit, e.type, e.copy_price, c.full_name
|
|
|
+ FROM Exhibit e
|
|
|
+ JOIN Creator c ON e.id_creator = c.id_creator
|
|
|
+ ORDER BY e.copy_price DESC
|
|
|
+ LIMIT 5;
|
|
|
+END;
|
|
|
+$$;
|
|
|
+
|
|
|
+
|
|
|
+ALTER FUNCTION dyachkov_ya.gettop5expensiveexhibits() OWNER TO dyachkov_ya;
|
|
|
+
|
|
|
+--
|
|
|
+-- TOC entry 1426 (class 1255 OID 443447)
|
|
|
+-- Name: hash_password(text, text); Type: FUNCTION; Schema: dyachkov_ya; Owner: dyachkov_ya
|
|
|
+--
|
|
|
+
|
|
|
+CREATE FUNCTION dyachkov_ya.hash_password(p_password text, p_salt text DEFAULT NULL::text) RETURNS text
|
|
|
+ LANGUAGE plpgsql
|
|
|
+ AS $$
|
|
|
+DECLARE
|
|
|
+ salt TEXT;
|
|
|
+ hashed_password TEXT;
|
|
|
+BEGIN
|
|
|
+ -- Генерируем соль, если не передана
|
|
|
+ IF p_salt IS NULL THEN
|
|
|
+ salt := gen_salt('bf'); -- Blowfish алгоритм
|
|
|
+ ELSE
|
|
|
+ salt := p_salt;
|
|
|
+ END IF;
|
|
|
+
|
|
|
+ -- Создаём хэш пароля
|
|
|
+ hashed_password := crypt(p_password, salt);
|
|
|
+ RETURN hashed_password;
|
|
|
+END;
|
|
|
+$$;
|
|
|
+
|
|
|
+
|
|
|
+ALTER FUNCTION dyachkov_ya.hash_password(p_password text, p_salt text) OWNER TO dyachkov_ya;
|
|
|
+
|
|
|
+--
|
|
|
+-- TOC entry 1427 (class 1255 OID 443448)
|
|
|
+-- Name: increase_price_by_cursor(); Type: PROCEDURE; Schema: dyachkov_ya; Owner: dyachkov_ya
|
|
|
+--
|
|
|
+
|
|
|
+CREATE PROCEDURE dyachkov_ya.increase_price_by_cursor()
|
|
|
+ LANGUAGE plpgsql
|
|
|
+ AS $$
|
|
|
+DECLARE
|
|
|
+ v_book RECORD;
|
|
|
+ v_new_price REAL;
|
|
|
+ v_increase REAL := 20; -- 20%
|
|
|
+ v_max_price REAL := 10000;
|
|
|
+ v_processed INTEGER := 0;
|
|
|
+ v_updated INTEGER := 0;
|
|
|
+BEGIN
|
|
|
+ -- Курсор для книг авторов, родившихся менее 1950 года
|
|
|
+ FOR v_book IN
|
|
|
+ SELECT b.bshifr, b.title, b.price, a.lastname, a.name, a.year_b
|
|
|
+ FROM book b
|
|
|
+ JOIN author a ON b.id_author = a.id
|
|
|
+ WHERE a.year_b < 1950
|
|
|
+ LOOP
|
|
|
+ -- Создаем точку сохранения для каждой книги
|
|
|
+ PERFORM 1;
|
|
|
+
|
|
|
+ BEGIN
|
|
|
+ -- Вычисляем новую цену (+20%)
|
|
|
+ v_new_price := v_book.price * (1 + v_increase / 100);
|
|
|
+
|
|
|
+ RAISE NOTICE 'Книга: "%", Автор: % % (род. %), Цена: % -> %',
|
|
|
+ v_book.title, v_book.lastname, v_book.name,
|
|
|
+ v_book.year_b, v_book.price, v_new_price;
|
|
|
+
|
|
|
+ -- Проверка: не превышает ли новая цена 10000
|
|
|
+ IF v_new_price <= v_max_price THEN
|
|
|
+ UPDATE book SET price = v_new_price WHERE bshifr = v_book.bshifr;
|
|
|
+ v_updated := v_updated + 1;
|
|
|
+ RAISE NOTICE ' -> ЦЕНА УВЕЛИЧЕНА';
|
|
|
+ ELSE
|
|
|
+ -- Цена не изменяется, просто пропускаем
|
|
|
+ RAISE NOTICE ' -> ЦЕНА НЕ ИЗМЕНЕНА (%.2f превысила бы лимит %.0f)', v_new_price, v_max_price;
|
|
|
+ END IF;
|
|
|
+
|
|
|
+ v_processed := v_processed + 1;
|
|
|
+
|
|
|
+ EXCEPTION
|
|
|
+ WHEN OTHERS THEN
|
|
|
+ -- При ошибке просто пропускаем книгу
|
|
|
+ RAISE NOTICE ' -> ОШИБКА при обработке книги "%": %', v_book.title, SQLERRM;
|
|
|
+ END;
|
|
|
+ END LOOP;
|
|
|
+
|
|
|
+ RAISE NOTICE '=========================================';
|
|
|
+ RAISE NOTICE 'Обработано книг: %, Обновлено: %', v_processed, v_updated;
|
|
|
+ RAISE NOTICE '=========================================';
|
|
|
+END;
|
|
|
+$$;
|
|
|
+
|
|
|
+
|
|
|
+ALTER PROCEDURE dyachkov_ya.increase_price_by_cursor() OWNER TO dyachkov_ya;
|
|
|
+
|
|
|
+--
|
|
|
+-- TOC entry 1428 (class 1255 OID 443449)
|
|
|
+-- Name: issue_book(integer, integer, date); Type: PROCEDURE; Schema: dyachkov_ya; Owner: dyachkov_ya
|
|
|
+--
|
|
|
+
|
|
|
+CREATE PROCEDURE dyachkov_ya.issue_book(IN p_user_id integer, IN p_book_bshifr integer, IN p_date_issue date)
|
|
|
+ LANGUAGE plpgsql
|
|
|
+ AS $$
|
|
|
+DECLARE
|
|
|
+ v_books_count INTEGER;
|
|
|
+ v_title VARCHAR(25);
|
|
|
+ v_username VARCHAR(50);
|
|
|
+ v_available BOOLEAN;
|
|
|
+BEGIN
|
|
|
+ BEGIN
|
|
|
+ -- Получаем имя пользователя
|
|
|
+ SELECT lastname || ' ' || name INTO v_username
|
|
|
+ FROM users WHERE id = p_user_id;
|
|
|
+
|
|
|
+ IF NOT FOUND THEN
|
|
|
+ RAISE EXCEPTION 'Пользователь с ID % не найден', p_user_id;
|
|
|
+ END IF;
|
|
|
+
|
|
|
+ -- Получаем информацию о книге
|
|
|
+ SELECT title, vidano INTO v_title, v_available
|
|
|
+ FROM book WHERE bshifr = p_book_bshifr;
|
|
|
+
|
|
|
+ IF NOT FOUND THEN
|
|
|
+ RAISE EXCEPTION 'Книга с bshifr=% не найдена', p_book_bshifr;
|
|
|
+ END IF;
|
|
|
+
|
|
|
+ -- Проверка доступности книги
|
|
|
+ IF v_available = TRUE THEN
|
|
|
+ RAISE EXCEPTION 'Книга "%" уже выдана другому читателю', v_title;
|
|
|
+ END IF;
|
|
|
+
|
|
|
+ -- Подсчет книг на руках у читателя
|
|
|
+ SELECT COUNT(*) INTO v_books_count
|
|
|
+ FROM ticket
|
|
|
+ WHERE user_id = p_user_id
|
|
|
+ AND (date_of_return IS NULL OR date_of_return > CURRENT_DATE);
|
|
|
+
|
|
|
+ RAISE NOTICE 'У читателя "%" на руках % книг', v_username, v_books_count;
|
|
|
+
|
|
|
+ -- Проверка лимита (не более 3)
|
|
|
+ IF v_books_count >= 3 THEN
|
|
|
+ RAISE EXCEPTION 'Читатель "%" уже имеет % книг на руках (максимум 3)',
|
|
|
+ v_username, v_books_count;
|
|
|
+ END IF;
|
|
|
+
|
|
|
+ -- Выдача книги
|
|
|
+ INSERT INTO ticket (user_id, book_id, date_of_issue, date_of_return)
|
|
|
+ VALUES (p_user_id, p_book_bshifr, p_date_issue, NULL);
|
|
|
+
|
|
|
+ UPDATE book SET vidano = TRUE WHERE bshifr = p_book_bshifr;
|
|
|
+
|
|
|
+ COMMIT;
|
|
|
+ RAISE NOTICE 'Книга "%" выдана читателю "%"', v_title, v_username;
|
|
|
+
|
|
|
+ EXCEPTION
|
|
|
+ WHEN OTHERS THEN
|
|
|
+ ROLLBACK;
|
|
|
+ RAISE NOTICE 'ОШИБКА: %', SQLERRM;
|
|
|
+ END;
|
|
|
+END;
|
|
|
+$$;
|
|
|
+
|
|
|
+
|
|
|
+ALTER PROCEDURE dyachkov_ya.issue_book(IN p_user_id integer, IN p_book_bshifr integer, IN p_date_issue date) OWNER TO dyachkov_ya;
|
|
|
+
|
|
|
+--
|
|
|
+-- TOC entry 1429 (class 1255 OID 443450)
|
|
|
+-- Name: kol_dney(date, date); Type: FUNCTION; Schema: dyachkov_ya; Owner: dyachkov_ya
|
|
|
+--
|
|
|
+
|
|
|
+CREATE FUNCTION dyachkov_ya.kol_dney(date1 date, date2 date) RETURNS integer
|
|
|
+ LANGUAGE plpgsql
|
|
|
+ AS $$
|
|
|
+DECLARE
|
|
|
+ num_days INTEGER;
|
|
|
+BEGIN
|
|
|
+ IF date1 IS NULL OR date2 IS NULL THEN
|
|
|
+ RAISE EXCEPTION 'Даты не могут быть NULL.';
|
|
|
+ END IF;
|
|
|
+
|
|
|
+ -- В PostgreSQL разница между двумя DATE автоматически возвращает количество дней.
|
|
|
+ num_days := date2 - date1;
|
|
|
+
|
|
|
+ RETURN num_days; -- Возвращаем разницу в днях
|
|
|
+END;
|
|
|
+$$;
|
|
|
+
|
|
|
+
|
|
|
+ALTER FUNCTION dyachkov_ya.kol_dney(date1 date, date2 date) OWNER TO dyachkov_ya;
|
|
|
+
|
|
|
+--
|
|
|
+-- TOC entry 1430 (class 1255 OID 443451)
|
|
|
+-- Name: month_name_by_number(integer); Type: FUNCTION; Schema: dyachkov_ya; Owner: dyachkov_ya
|
|
|
+--
|
|
|
+
|
|
|
+CREATE FUNCTION dyachkov_ya.month_name_by_number(month_num integer) RETURNS character varying
|
|
|
+ LANGUAGE plpgsql
|
|
|
+ AS $$
|
|
|
+BEGIN
|
|
|
+IF month_num IS NULL OR month_num < 1 OR month_num > 12 THEN
|
|
|
+RAISE EXCEPTION 'Номер месяца должен быть от 1 до 12.';
|
|
|
+END IF;
|
|
|
+RETURN CASE month_num
|
|
|
+WHEN 1 THEN 'Январь'
|
|
|
+WHEN 2 THEN 'Февраль'
|
|
|
+WHEN 3 THEN 'Март'
|
|
|
+WHEN 4 THEN 'Апрель'
|
|
|
+WHEN 5 THEN 'Май'
|
|
|
+WHEN 6 THEN 'Июнь'
|
|
|
+WHEN 7 THEN 'Июль'
|
|
|
+WHEN 8 THEN 'Август'
|
|
|
+WHEN 9 THEN 'Сентябрь'
|
|
|
+WHEN 10 THEN 'Октябрь'
|
|
|
+WHEN 11 THEN 'Ноябрь'
|
|
|
+WHEN 12 THEN 'Декабрь'
|
|
|
+ELSE 'Неизвестный месяц'
|
|
|
+END;
|
|
|
+END;
|
|
|
+$$;
|
|
|
+
|
|
|
+
|
|
|
+ALTER FUNCTION dyachkov_ya.month_name_by_number(month_num integer) OWNER TO dyachkov_ya;
|
|
|
+
|
|
|
+--
|
|
|
+-- TOC entry 1431 (class 1255 OID 443452)
|
|
|
+-- Name: multi_hash(text, integer); Type: FUNCTION; Schema: dyachkov_ya; Owner: dyachkov_ya
|
|
|
+--
|
|
|
+
|
|
|
+CREATE FUNCTION dyachkov_ya.multi_hash(p_value text, p_iterations integer DEFAULT 1) RETURNS text
|
|
|
+ LANGUAGE plpgsql
|
|
|
+ AS $$
|
|
|
+DECLARE
|
|
|
+ hashed_value TEXT;
|
|
|
+ i INTEGER;
|
|
|
+BEGIN
|
|
|
+ IF p_value IS NULL THEN
|
|
|
+ RETURN NULL;
|
|
|
+ END IF;
|
|
|
+
|
|
|
+ hashed_value := p_value;
|
|
|
+
|
|
|
+ FOR i IN 1..p_iterations LOOP
|
|
|
+ hashed_value := encode(digest(hashed_value, 'sha256'), 'hex');
|
|
|
+ END LOOP;
|
|
|
+
|
|
|
+ RETURN hashed_value;
|
|
|
+END;
|
|
|
+$$;
|
|
|
+
|
|
|
+
|
|
|
+ALTER FUNCTION dyachkov_ya.multi_hash(p_value text, p_iterations integer) OWNER TO dyachkov_ya;
|
|
|
+
|
|
|
+--
|
|
|
+-- TOC entry 1432 (class 1255 OID 443453)
|
|
|
+-- Name: normalize_region(text); Type: FUNCTION; Schema: dyachkov_ya; Owner: dyachkov_ya
|
|
|
+--
|
|
|
+
|
|
|
+CREATE FUNCTION dyachkov_ya.normalize_region(region_name text) RETURNS text
|
|
|
+ LANGUAGE plpgsql
|
|
|
+ AS $$
|
|
|
+BEGIN
|
|
|
+ RETURN CASE
|
|
|
+ WHEN region_name ILIKE '%Санкт-Петербург%' OR region_name ILIKE '%СПб%' THEN 'Санкт-Петербург'
|
|
|
+ WHEN region_name ILIKE '%Ленинградская%' THEN 'Ленинградская область'
|
|
|
+ WHEN region_name ILIKE '%Новгород%' THEN 'Новгородская область'
|
|
|
+ ELSE clean_string(region_name)
|
|
|
+ END;
|
|
|
+END;
|
|
|
+$$;
|
|
|
+
|
|
|
+
|
|
|
+ALTER FUNCTION dyachkov_ya.normalize_region(region_name text) OWNER TO dyachkov_ya;
|
|
|
+
|
|
|
+--
|
|
|
+-- TOC entry 1433 (class 1255 OID 443454)
|
|
|
+-- Name: nvl(anyelement, anyelement); Type: FUNCTION; Schema: dyachkov_ya; Owner: dyachkov_ya
|
|
|
+--
|
|
|
+
|
|
|
+CREATE FUNCTION dyachkov_ya.nvl(input_value anyelement, default_value anyelement) RETURNS anyelement
|
|
|
+ LANGUAGE plpgsql
|
|
|
+ AS $$
|
|
|
+BEGIN
|
|
|
+ RETURN COALESCE(input_value, default_value);
|
|
|
+END;
|
|
|
+$$;
|
|
|
+
|
|
|
+
|
|
|
+ALTER FUNCTION dyachkov_ya.nvl(input_value anyelement, default_value anyelement) OWNER TO dyachkov_ya;
|
|
|
+
|
|
|
+--
|
|
|
+-- TOC entry 1434 (class 1255 OID 443455)
|
|
|
+-- Name: parse_salary(text); Type: FUNCTION; Schema: dyachkov_ya; Owner: dyachkov_ya
|
|
|
+--
|
|
|
+
|
|
|
+CREATE FUNCTION dyachkov_ya.parse_salary(salary_text text) RETURNS TABLE(min_salary numeric, max_salary numeric)
|
|
|
+ LANGUAGE plpgsql
|
|
|
+ AS $$
|
|
|
+DECLARE
|
|
|
+ numbers NUMERIC[];
|
|
|
+BEGIN
|
|
|
+ IF salary_text IS NULL THEN
|
|
|
+ min_salary := NULL;
|
|
|
+ max_salary := NULL;
|
|
|
+ RETURN NEXT;
|
|
|
+ RETURN;
|
|
|
+ END IF;
|
|
|
+
|
|
|
+ -- Извлечение чисел из строки
|
|
|
+ SELECT ARRAY(
|
|
|
+ SELECT REGEXP_MATCHES(salary_text, '(\d+[.,]?\d*)', 'g')
|
|
|
+ ) INTO numbers;
|
|
|
+
|
|
|
+ IF array_length(numbers, 1) >= 1 THEN
|
|
|
+ min_salary := numbers[1]::NUMERIC;
|
|
|
+ IF array_length(numbers, 1) >= 2 THEN
|
|
|
+ max_salary := numbers[2]::NUMERIC;
|
|
|
+ ELSE
|
|
|
+ max_salary := min_salary;
|
|
|
+ END IF;
|
|
|
+ ELSE
|
|
|
+ min_salary := NULL;
|
|
|
+ max_salary := NULL;
|
|
|
+ END IF;
|
|
|
+
|
|
|
+ RETURN NEXT;
|
|
|
+END;
|
|
|
+$$;
|
|
|
+
|
|
|
+
|
|
|
+ALTER FUNCTION dyachkov_ya.parse_salary(salary_text text) OWNER TO dyachkov_ya;
|
|
|
+
|
|
|
+--
|
|
|
+-- TOC entry 1435 (class 1255 OID 443456)
|
|
|
+-- Name: proizv(integer); Type: FUNCTION; Schema: dyachkov_ya; Owner: dyachkov_ya
|
|
|
+--
|
|
|
+
|
|
|
+CREATE FUNCTION dyachkov_ya.proizv(n integer) RETURNS bigint
|
|
|
+ LANGUAGE plpgsql
|
|
|
+ AS $$
|
|
|
+DECLARE
|
|
|
+ i INTEGER;
|
|
|
+ total_product BIGINT := 1; -- Инициализируем произведение единицей
|
|
|
+BEGIN
|
|
|
+ IF n IS NULL OR n <= 0 THEN
|
|
|
+ RAISE EXCEPTION 'Параметр n должен быть положительным целым числом.';
|
|
|
+ END IF;
|
|
|
+
|
|
|
+ -- Цикл от 1 до n
|
|
|
+ FOR i IN 1..n LOOP
|
|
|
+ total_product := total_product * i; -- Умножаем текущее число на произведение
|
|
|
+ END LOOP;
|
|
|
+
|
|
|
+ RETURN total_product; -- Возвращаем вычисленное произведение
|
|
|
+END;
|
|
|
+$$;
|
|
|
+
|
|
|
+
|
|
|
+ALTER FUNCTION dyachkov_ya.proizv(n integer) OWNER TO dyachkov_ya;
|
|
|
+
|
|
|
+--
|
|
|
+-- TOC entry 1436 (class 1255 OID 443457)
|
|
|
+-- Name: proverka(integer, integer, date, date); Type: PROCEDURE; Schema: dyachkov_ya; Owner: dyachkov_ya
|
|
|
+--
|
|
|
+
|
|
|
+CREATE PROCEDURE dyachkov_ya.proverka(IN kodu integer, IN kodb integer, IN dvid date, IN dvoz date)
|
|
|
+ LANGUAGE plpgsql
|
|
|
+ AS $$
|
|
|
+DECLARE
|
|
|
+ rez VARCHAR(10) := 'ОК';
|
|
|
+ pr INTEGER;
|
|
|
+ v_last_id INTEGER;
|
|
|
+BEGIN
|
|
|
+ -- Начинаем транзакцию
|
|
|
+ BEGIN
|
|
|
+ -- Ввод записи в таблицу ticket (она же bilet)
|
|
|
+ INSERT INTO ticket (user_id, book_id, date_of_issue, date_of_return)
|
|
|
+ VALUES (kodU, kodB, dVid, dVoz)
|
|
|
+ RETURNING id INTO v_last_id;
|
|
|
+
|
|
|
+ RAISE NOTICE 'Вставлена запись с ID: %', v_last_id;
|
|
|
+
|
|
|
+ -- Вычисляем разницу между датой возврата и датой выдачи
|
|
|
+ SELECT (date_of_return - date_of_issue) INTO pr
|
|
|
+ FROM ticket WHERE id = v_last_id;
|
|
|
+
|
|
|
+ RAISE NOTICE 'Разница между датами: % дней', pr;
|
|
|
+
|
|
|
+ -- Проверка: если разница > 0, то фиксируем, иначе откатываем
|
|
|
+ IF pr > 0 THEN
|
|
|
+ COMMIT;
|
|
|
+ rez := 'ОК';
|
|
|
+ RAISE NOTICE 'Дата возврата корректна. Транзакция зафиксирована.';
|
|
|
+ ELSE
|
|
|
+ ROLLBACK;
|
|
|
+ rez := 'No';
|
|
|
+ RAISE NOTICE 'ОШИБКА: дата возврата (%) меньше или равна дате выдачи (%)', dVoz, dVid;
|
|
|
+ RAISE NOTICE 'Транзакция откачена.';
|
|
|
+ END IF;
|
|
|
+
|
|
|
+ -- Выводим значение переменной rez
|
|
|
+ RAISE NOTICE 'Результат: %', rez;
|
|
|
+
|
|
|
+ EXCEPTION
|
|
|
+ WHEN OTHERS THEN
|
|
|
+ ROLLBACK;
|
|
|
+ rez := 'Error';
|
|
|
+ RAISE NOTICE 'Ошибка при выполнении: %', SQLERRM;
|
|
|
+ END;
|
|
|
+END;
|
|
|
+$$;
|
|
|
+
|
|
|
+
|
|
|
+ALTER PROCEDURE dyachkov_ya.proverka(IN kodu integer, IN kodb integer, IN dvid date, IN dvoz date) OWNER TO dyachkov_ya;
|
|
|
+
|
|
|
+--
|
|
|
+-- TOC entry 1437 (class 1255 OID 443458)
|
|
|
+-- Name: register_user(character varying, text, text, character varying); Type: FUNCTION; Schema: dyachkov_ya; Owner: dyachkov_ya
|
|
|
+--
|
|
|
+
|
|
|
+CREATE FUNCTION dyachkov_ya.register_user(p_username character varying, p_name text, p_password text, p_role_name character varying DEFAULT 'user'::character varying) RETURNS integer
|
|
|
+ LANGUAGE plpgsql
|
|
|
+ AS $$
|
|
|
+DECLARE
|
|
|
+ v_salt TEXT;
|
|
|
+ v_role_id INTEGER;
|
|
|
+ v_encrypted_name TEXT;
|
|
|
+ v_user_id INTEGER;
|
|
|
+BEGIN
|
|
|
+ -- Получаем ID роли
|
|
|
+ SELECT id INTO v_role_id FROM roles WHERE role_name = p_role_name;
|
|
|
+ IF v_role_id IS NULL THEN
|
|
|
+ RAISE EXCEPTION 'Роль "%" не существует', p_role_name;
|
|
|
+ END IF;
|
|
|
+
|
|
|
+ -- Генерируем соль
|
|
|
+ v_salt := gen_salt('bf');
|
|
|
+
|
|
|
+ -- Шифруем имя пользователя (используем AES)
|
|
|
+ v_encrypted_name := encode(encrypt(p_name::bytea, 'master_key', 'aes'), 'base64');
|
|
|
+
|
|
|
+ -- Вставляем пользователя
|
|
|
+ INSERT INTO system_users (username, encrypted_name, password_hash, salt, role_id)
|
|
|
+ VALUES (p_username, v_encrypted_name, crypt(p_password, v_salt), v_salt, v_role_id)
|
|
|
+ RETURNING id INTO v_user_id;
|
|
|
+
|
|
|
+ RETURN v_user_id;
|
|
|
+EXCEPTION WHEN unique_violation THEN
|
|
|
+ RAISE EXCEPTION 'Пользователь с именем "%" уже существует', p_username;
|
|
|
+END;
|
|
|
+$$;
|
|
|
+
|
|
|
+
|
|
|
+ALTER FUNCTION dyachkov_ya.register_user(p_username character varying, p_name text, p_password text, p_role_name character varying) OWNER TO dyachkov_ya;
|
|
|
+
|
|
|
+--
|
|
|
+-- TOC entry 1438 (class 1255 OID 443459)
|
|
|
+-- Name: summa(integer); Type: FUNCTION; Schema: dyachkov_ya; Owner: dyachkov_ya
|
|
|
+--
|
|
|
+
|
|
|
+CREATE FUNCTION dyachkov_ya.summa(n integer) RETURNS bigint
|
|
|
+ LANGUAGE plpgsql
|
|
|
+ AS $$
|
|
|
+DECLARE
|
|
|
+ i INTEGER;
|
|
|
+ total_sum BIGINT := 0; -- Инициализируем сумму нулем
|
|
|
+BEGIN
|
|
|
+ IF n IS NULL OR n <= 0 THEN
|
|
|
+ RAISE EXCEPTION 'Параметр n должен быть положительным целым числом.';
|
|
|
+ END IF;
|
|
|
+
|
|
|
+ -- Цикл от 1 до n
|
|
|
+ FOR i IN 1..n LOOP
|
|
|
+ total_sum := total_sum + i; -- Добавляем текущее число к сумме
|
|
|
+ END LOOP;
|
|
|
+
|
|
|
+ RETURN total_sum; -- Возвращаем вычисленную сумму
|
|
|
+END;
|
|
|
+$$;
|
|
|
+
|
|
|
+
|
|
|
+ALTER FUNCTION dyachkov_ya.summa(n integer) OWNER TO dyachkov_ya;
|
|
|
+
|
|
|
+--
|
|
|
+-- TOC entry 1439 (class 1255 OID 443460)
|
|
|
+-- Name: tek_vr(integer); Type: PROCEDURE; Schema: dyachkov_ya; Owner: dyachkov_ya
|
|
|
+--
|
|
|
+
|
|
|
+CREATE PROCEDURE dyachkov_ya.tek_vr(IN n integer)
|
|
|
+ LANGUAGE plpgsql
|
|
|
+ AS $$
|
|
|
+DECLARE
|
|
|
+ i INTEGER;
|
|
|
+BEGIN
|
|
|
+ IF n IS NULL OR n <= 0 THEN
|
|
|
+ RAISE EXCEPTION 'Параметр N должен быть положительным числом.';
|
|
|
+ END IF;
|
|
|
+
|
|
|
+ RAISE NOTICE '--- Вывод текущего времени % раз ---', n;
|
|
|
+
|
|
|
+ FOR i IN 1..n LOOP
|
|
|
+ -- NOW() возвращает текущую дату и время
|
|
|
+ RAISE NOTICE 'Итерация %: Текущее время: %', i, NOW();
|
|
|
+ END LOOP;
|
|
|
+END;
|
|
|
+$$;
|
|
|
+
|
|
|
+
|
|
|
+ALTER PROCEDURE dyachkov_ya.tek_vr(IN n integer) OWNER TO dyachkov_ya;
|
|
|
+
|
|
|
+--
|
|
|
+-- TOC entry 1440 (class 1255 OID 443461)
|
|
|
+-- Name: ticket_insert_trigger(); Type: FUNCTION; Schema: dyachkov_ya; Owner: dyachkov_ya
|
|
|
+--
|
|
|
+
|
|
|
+CREATE FUNCTION dyachkov_ya.ticket_insert_trigger() RETURNS trigger
|
|
|
+ LANGUAGE plpgsql
|
|
|
+ AS $$
|
|
|
+BEGIN
|
|
|
+IF ( NEW.date_of_issue >= DATE '2024-01-01' AND NEW.date_of_issue < DATE '2024-02-01' ) THEN INSERT INTO ticket2024m1 VALUES (NEW.*);
|
|
|
+ELSIF ( NEW.date_of_issue >= DATE '2024-02-01' AND NEW.date_of_issue < DATE '2024-03-01' ) THEN INSERT INTO ticket2024m2 VALUES (NEW.*);
|
|
|
+ELSIF ( NEW.date_of_issue >= DATE '2024-03-01' AND NEW.date_of_issue < DATE '2024-04-01' ) THEN INSERT INTO ticket2024m3 VALUES (NEW.*);
|
|
|
+ELSIF ( NEW.date_of_issue >= DATE '2024-04-01' AND NEW.date_of_issue < DATE '2024-05-01' ) THEN INSERT INTO ticket2024m4 VALUES (NEW.*);
|
|
|
+ELSIF ( NEW.date_of_issue >= DATE '2024-05-01' AND NEW.date_of_issue < DATE '2024-06-01' ) THEN INSERT INTO ticket2024m5 VALUES (NEW.*);
|
|
|
+ELSIF ( NEW.date_of_issue >= DATE '2024-06-01' AND NEW.date_of_issue < DATE '2024-07-01' ) THEN INSERT INTO ticket2024m6 VALUES (NEW.*);
|
|
|
+ELSIF ( NEW.date_of_issue >= DATE '2024-07-01' AND NEW.date_of_issue < DATE '2024-08-01' ) THEN INSERT INTO ticket2024m7 VALUES (NEW.*);
|
|
|
+ELSIF ( NEW.date_of_issue >= DATE '2024-08-01' AND NEW.date_of_issue < DATE '2024-09-01' ) THEN INSERT INTO ticket2024m8 VALUES (NEW.*);
|
|
|
+ELSIF ( NEW.date_of_issue >= DATE '2024-09-01' AND NEW.date_of_issue < DATE '2024-10-01' ) THEN INSERT INTO ticket2024m9 VALUES (NEW.*);
|
|
|
+ELSIF ( NEW.date_of_issue >= DATE '2024-10-01' AND NEW.date_of_issue < DATE '2024-11-01' ) THEN INSERT INTO ticket2024m10 VALUES (NEW.*);
|
|
|
+ELSIF ( NEW.date_of_issue >= DATE '2024-11-01' AND NEW.date_of_issue < DATE '2024-12-01' ) THEN INSERT INTO ticket2024m11 VALUES (NEW.*);
|
|
|
+ELSIF ( NEW.date_of_issue >= DATE '2024-12-01' AND NEW.date_of_issue < DATE '2025-01-01' ) THEN INSERT INTO ticket2024m12 VALUES (NEW.*);
|
|
|
+ELSE RAISE EXCEPTION 'Date out of range for all partitions';
|
|
|
+END IF;
|
|
|
+RETURN NULL;
|
|
|
+END;
|
|
|
+$$;
|
|
|
+
|
|
|
+
|
|
|
+ALTER FUNCTION dyachkov_ya.ticket_insert_trigger() OWNER TO dyachkov_ya;
|
|
|
+
|
|
|
+--
|
|
|
+-- TOC entry 1441 (class 1255 OID 443462)
|
|
|
+-- Name: track_price_change(); Type: FUNCTION; Schema: dyachkov_ya; Owner: dyachkov_ya
|
|
|
+--
|
|
|
+
|
|
|
+CREATE FUNCTION dyachkov_ya.track_price_change() RETURNS trigger
|
|
|
+ LANGUAGE plpgsql
|
|
|
+ AS $$
|
|
|
+BEGIN
|
|
|
+ -- Если цена изменилась и новая цена > 1000 рублей
|
|
|
+ IF OLD.price IS DISTINCT FROM NEW.price AND NEW.price > 1000 THEN
|
|
|
+ -- Автономное логирование (сохранится даже при ROLLBACK)
|
|
|
+ PERFORM autonomous_log(NEW.bshifr, OLD.price, NEW.price);
|
|
|
+
|
|
|
+ RAISE NOTICE 'Зафиксирована попытка изменения цены книги bshifr=%: % -> %',
|
|
|
+ NEW.bshifr, OLD.price, NEW.price;
|
|
|
+ END IF;
|
|
|
+
|
|
|
+ RETURN NEW;
|
|
|
+END;
|
|
|
+$$;
|
|
|
+
|
|
|
+
|
|
|
+ALTER FUNCTION dyachkov_ya.track_price_change() OWNER TO dyachkov_ya;
|
|
|
+
|
|
|
+--
|
|
|
+-- TOC entry 1841 (class 1255 OID 444522)
|
|
|
+-- Name: update_museum_profit(); Type: FUNCTION; Schema: dyachkov_ya; Owner: dyachkov_ya
|
|
|
+--
|
|
|
+
|
|
|
+CREATE FUNCTION dyachkov_ya.update_museum_profit() RETURNS trigger
|
|
|
+ LANGUAGE plpgsql
|
|
|
+ AS $$
|
|
|
+BEGIN
|
|
|
+ -- Обновляем прибыль музея при добавлении нового экспоната
|
|
|
+ UPDATE Museum
|
|
|
+ SET profit = profit + (NEW.copy_price - NEW.creation_cost)
|
|
|
+ WHERE id_museum = NEW.id_museum;
|
|
|
+
|
|
|
+ RETURN NEW;
|
|
|
+END;
|
|
|
+$$;
|
|
|
+
|
|
|
+
|
|
|
+ALTER FUNCTION dyachkov_ya.update_museum_profit() OWNER TO dyachkov_ya;
|
|
|
+
|
|
|
+SET default_tablespace = '';
|
|
|
+
|
|
|
+SET default_table_access_method = heap;
|
|
|
+
|
|
|
+--
|
|
|
+-- TOC entry 720 (class 1259 OID 450407)
|
|
|
+-- Name: auditlog; Type: TABLE; Schema: dyachkov_ya; Owner: dyachkov_ya
|
|
|
+--
|
|
|
+
|
|
|
+CREATE TABLE dyachkov_ya.auditlog (
|
|
|
+ id_log integer NOT NULL,
|
|
|
+ id_user integer,
|
|
|
+ action character varying(255),
|
|
|
+ table_name character varying(100),
|
|
|
+ record_id integer,
|
|
|
+ action_time timestamp without time zone DEFAULT CURRENT_TIMESTAMP,
|
|
|
+ ip_address character varying(45),
|
|
|
+ details text
|
|
|
+);
|
|
|
+
|
|
|
+
|
|
|
+ALTER TABLE dyachkov_ya.auditlog OWNER TO dyachkov_ya;
|
|
|
+
|
|
|
+--
|
|
|
+-- TOC entry 719 (class 1259 OID 450406)
|
|
|
+-- Name: auditlog_id_log_seq; Type: SEQUENCE; Schema: dyachkov_ya; Owner: dyachkov_ya
|
|
|
+--
|
|
|
+
|
|
|
+CREATE SEQUENCE dyachkov_ya.auditlog_id_log_seq
|
|
|
+ AS integer
|
|
|
+ START WITH 1
|
|
|
+ INCREMENT BY 1
|
|
|
+ NO MINVALUE
|
|
|
+ NO MAXVALUE
|
|
|
+ CACHE 1;
|
|
|
+
|
|
|
+
|
|
|
+ALTER SEQUENCE dyachkov_ya.auditlog_id_log_seq OWNER TO dyachkov_ya;
|
|
|
+
|
|
|
+--
|
|
|
+-- TOC entry 6622 (class 0 OID 0)
|
|
|
+-- Dependencies: 719
|
|
|
+-- Name: auditlog_id_log_seq; Type: SEQUENCE OWNED BY; Schema: dyachkov_ya; Owner: dyachkov_ya
|
|
|
+--
|
|
|
+
|
|
|
+ALTER SEQUENCE dyachkov_ya.auditlog_id_log_seq OWNED BY dyachkov_ya.auditlog.id_log;
|
|
|
+
|
|
|
+
|
|
|
+--
|
|
|
+-- TOC entry 325 (class 1259 OID 444440)
|
|
|
+-- Name: creator; Type: TABLE; Schema: dyachkov_ya; Owner: dyachkov_ya
|
|
|
+--
|
|
|
+
|
|
|
+CREATE TABLE dyachkov_ya.creator (
|
|
|
+ id_creator integer NOT NULL,
|
|
|
+ full_name character varying(100) NOT NULL,
|
|
|
+ royalty numeric(10,2),
|
|
|
+ phone character varying(20),
|
|
|
+ address character varying(200)
|
|
|
+);
|
|
|
+
|
|
|
+
|
|
|
+ALTER TABLE dyachkov_ya.creator OWNER TO dyachkov_ya;
|
|
|
+
|
|
|
+--
|
|
|
+-- TOC entry 327 (class 1259 OID 444460)
|
|
|
+-- Name: exhibit; Type: TABLE; Schema: dyachkov_ya; Owner: dyachkov_ya
|
|
|
+--
|
|
|
+
|
|
|
+CREATE TABLE dyachkov_ya.exhibit (
|
|
|
+ id_exhibit integer NOT NULL,
|
|
|
+ type character varying(50),
|
|
|
+ creation_date date,
|
|
|
+ copy_price numeric(10,2),
|
|
|
+ creation_cost numeric(10,2),
|
|
|
+ id_creator integer,
|
|
|
+ id_museum integer
|
|
|
+);
|
|
|
+
|
|
|
+
|
|
|
+ALTER TABLE dyachkov_ya.exhibit OWNER TO dyachkov_ya;
|
|
|
+
|
|
|
+--
|
|
|
+-- TOC entry 324 (class 1259 OID 444434)
|
|
|
+-- Name: museum; Type: TABLE; Schema: dyachkov_ya; Owner: dyachkov_ya
|
|
|
+--
|
|
|
+
|
|
|
+CREATE TABLE dyachkov_ya.museum (
|
|
|
+ id_museum integer NOT NULL,
|
|
|
+ area numeric(10,2),
|
|
|
+ profit numeric(12,2),
|
|
|
+ phone character varying(20),
|
|
|
+ address character varying(200)
|
|
|
+);
|
|
|
+
|
|
|
+
|
|
|
+ALTER TABLE dyachkov_ya.museum OWNER TO dyachkov_ya;
|
|
|
+
|
|
|
+--
|
|
|
+-- TOC entry 716 (class 1259 OID 450373)
|
|
|
+-- Name: roles; Type: TABLE; Schema: dyachkov_ya; Owner: dyachkov_ya
|
|
|
+--
|
|
|
+
|
|
|
+CREATE TABLE dyachkov_ya.roles (
|
|
|
+ id_role integer NOT NULL,
|
|
|
+ role_name character varying(50) NOT NULL,
|
|
|
+ description text
|
|
|
+);
|
|
|
+
|
|
|
+
|
|
|
+ALTER TABLE dyachkov_ya.roles OWNER TO dyachkov_ya;
|
|
|
+
|
|
|
+--
|
|
|
+-- TOC entry 715 (class 1259 OID 450372)
|
|
|
+-- Name: roles_id_role_seq; Type: SEQUENCE; Schema: dyachkov_ya; Owner: dyachkov_ya
|
|
|
+--
|
|
|
+
|
|
|
+CREATE SEQUENCE dyachkov_ya.roles_id_role_seq
|
|
|
+ AS integer
|
|
|
+ START WITH 1
|
|
|
+ INCREMENT BY 1
|
|
|
+ NO MINVALUE
|
|
|
+ NO MAXVALUE
|
|
|
+ CACHE 1;
|
|
|
+
|
|
|
+
|
|
|
+ALTER SEQUENCE dyachkov_ya.roles_id_role_seq OWNER TO dyachkov_ya;
|
|
|
+
|
|
|
+--
|
|
|
+-- TOC entry 6623 (class 0 OID 0)
|
|
|
+-- Dependencies: 715
|
|
|
+-- Name: roles_id_role_seq; Type: SEQUENCE OWNED BY; Schema: dyachkov_ya; Owner: dyachkov_ya
|
|
|
+--
|
|
|
+
|
|
|
+ALTER SEQUENCE dyachkov_ya.roles_id_role_seq OWNED BY dyachkov_ya.roles.id_role;
|
|
|
+
|
|
|
+
|
|
|
+--
|
|
|
+-- TOC entry 718 (class 1259 OID 450386)
|
|
|
+-- Name: users; Type: TABLE; Schema: dyachkov_ya; Owner: dyachkov_ya
|
|
|
+--
|
|
|
+
|
|
|
+CREATE TABLE dyachkov_ya.users (
|
|
|
+ id_user integer NOT NULL,
|
|
|
+ username character varying(50) NOT NULL,
|
|
|
+ password_hash character varying(255) NOT NULL,
|
|
|
+ salt character varying(100) NOT NULL,
|
|
|
+ id_role integer NOT NULL,
|
|
|
+ created_at timestamp without time zone DEFAULT CURRENT_TIMESTAMP,
|
|
|
+ last_login timestamp without time zone,
|
|
|
+ is_active boolean DEFAULT true
|
|
|
+);
|
|
|
+
|
|
|
+
|
|
|
+ALTER TABLE dyachkov_ya.users OWNER TO dyachkov_ya;
|
|
|
+
|
|
|
+--
|
|
|
+-- TOC entry 717 (class 1259 OID 450385)
|
|
|
+-- Name: users_id_user_seq; Type: SEQUENCE; Schema: dyachkov_ya; Owner: dyachkov_ya
|
|
|
+--
|
|
|
+
|
|
|
+CREATE SEQUENCE dyachkov_ya.users_id_user_seq
|
|
|
+ AS integer
|
|
|
+ START WITH 1
|
|
|
+ INCREMENT BY 1
|
|
|
+ NO MINVALUE
|
|
|
+ NO MAXVALUE
|
|
|
+ CACHE 1;
|
|
|
+
|
|
|
+
|
|
|
+ALTER SEQUENCE dyachkov_ya.users_id_user_seq OWNER TO dyachkov_ya;
|
|
|
+
|
|
|
+--
|
|
|
+-- TOC entry 6624 (class 0 OID 0)
|
|
|
+-- Dependencies: 717
|
|
|
+-- Name: users_id_user_seq; Type: SEQUENCE OWNED BY; Schema: dyachkov_ya; Owner: dyachkov_ya
|
|
|
+--
|
|
|
+
|
|
|
+ALTER SEQUENCE dyachkov_ya.users_id_user_seq OWNED BY dyachkov_ya.users.id_user;
|
|
|
+
|
|
|
+
|
|
|
+--
|
|
|
+-- TOC entry 328 (class 1259 OID 444476)
|
|
|
+-- Name: viewing; Type: TABLE; Schema: dyachkov_ya; Owner: dyachkov_ya
|
|
|
+--
|
|
|
+
|
|
|
+CREATE TABLE dyachkov_ya.viewing (
|
|
|
+ id_ticket integer NOT NULL,
|
|
|
+ id_exhibit integer NOT NULL,
|
|
|
+ exhibit_rating integer,
|
|
|
+ CONSTRAINT viewing_exhibit_rating_check CHECK (((exhibit_rating >= 1) AND (exhibit_rating <= 5)))
|
|
|
+);
|
|
|
+
|
|
|
+
|
|
|
+ALTER TABLE dyachkov_ya.viewing OWNER TO dyachkov_ya;
|
|
|
+
|
|
|
+--
|
|
|
+-- TOC entry 330 (class 1259 OID 444512)
|
|
|
+-- Name: v_exhibit_popularity; Type: VIEW; Schema: dyachkov_ya; Owner: dyachkov_ya
|
|
|
+--
|
|
|
+
|
|
|
+CREATE VIEW dyachkov_ya.v_exhibit_popularity AS
|
|
|
+ SELECT e.id_exhibit,
|
|
|
+ e.type,
|
|
|
+ count(v.id_ticket) AS views_count,
|
|
|
+ avg(v.exhibit_rating) AS average_rating
|
|
|
+ FROM (dyachkov_ya.exhibit e
|
|
|
+ LEFT JOIN dyachkov_ya.viewing v ON ((e.id_exhibit = v.id_exhibit)))
|
|
|
+ GROUP BY e.id_exhibit, e.type
|
|
|
+ ORDER BY (avg(v.exhibit_rating)) DESC;
|
|
|
+
|
|
|
+
|
|
|
+ALTER VIEW dyachkov_ya.v_exhibit_popularity OWNER TO dyachkov_ya;
|
|
|
+
|
|
|
+--
|
|
|
+-- TOC entry 329 (class 1259 OID 444507)
|
|
|
+-- Name: v_exhibits_with_authors; Type: VIEW; Schema: dyachkov_ya; Owner: dyachkov_ya
|
|
|
+--
|
|
|
+
|
|
|
+CREATE VIEW dyachkov_ya.v_exhibits_with_authors AS
|
|
|
+ SELECT e.id_exhibit,
|
|
|
+ e.type,
|
|
|
+ e.creation_date,
|
|
|
+ e.copy_price,
|
|
|
+ e.creation_cost,
|
|
|
+ c.full_name AS author_name,
|
|
|
+ m.address AS museum_location
|
|
|
+ FROM ((dyachkov_ya.exhibit e
|
|
|
+ LEFT JOIN dyachkov_ya.creator c ON ((e.id_creator = c.id_creator)))
|
|
|
+ LEFT JOIN dyachkov_ya.museum m ON ((e.id_museum = m.id_museum)));
|
|
|
+
|
|
|
+
|
|
|
+ALTER VIEW dyachkov_ya.v_exhibits_with_authors OWNER TO dyachkov_ya;
|
|
|
+
|
|
|
+--
|
|
|
+-- TOC entry 326 (class 1259 OID 444447)
|
|
|
+-- Name: visitor; Type: TABLE; Schema: dyachkov_ya; Owner: dyachkov_ya
|
|
|
+--
|
|
|
+
|
|
|
+CREATE TABLE dyachkov_ya.visitor (
|
|
|
+ id_ticket integer NOT NULL,
|
|
|
+ full_name character varying(100) NOT NULL,
|
|
|
+ phone character varying(20),
|
|
|
+ visit_date date,
|
|
|
+ museum_rating integer,
|
|
|
+ id_museum integer,
|
|
|
+ CONSTRAINT visitor_museum_rating_check CHECK (((museum_rating >= 1) AND (museum_rating <= 5)))
|
|
|
+);
|
|
|
+
|
|
|
+
|
|
|
+ALTER TABLE dyachkov_ya.visitor OWNER TO dyachkov_ya;
|
|
|
+
|
|
|
+--
|
|
|
+-- TOC entry 331 (class 1259 OID 444517)
|
|
|
+-- Name: v_museum_statistics; Type: VIEW; Schema: dyachkov_ya; Owner: dyachkov_ya
|
|
|
+--
|
|
|
+
|
|
|
+CREATE VIEW dyachkov_ya.v_museum_statistics AS
|
|
|
+ SELECT m.id_museum,
|
|
|
+ m.address,
|
|
|
+ count(DISTINCT e.id_exhibit) AS exhibits_count,
|
|
|
+ count(DISTINCT v.id_ticket) AS visitors_count,
|
|
|
+ sum(e.copy_price) AS total_exhibits_value
|
|
|
+ FROM ((dyachkov_ya.museum m
|
|
|
+ LEFT JOIN dyachkov_ya.exhibit e ON ((m.id_museum = e.id_museum)))
|
|
|
+ LEFT JOIN dyachkov_ya.visitor v ON ((m.id_museum = v.id_museum)))
|
|
|
+ GROUP BY m.id_museum, m.address;
|
|
|
+
|
|
|
+
|
|
|
+ALTER VIEW dyachkov_ya.v_museum_statistics OWNER TO dyachkov_ya;
|
|
|
+
|
|
|
+--
|
|
|
+-- TOC entry 6329 (class 2604 OID 450410)
|
|
|
+-- Name: auditlog id_log; Type: DEFAULT; Schema: dyachkov_ya; Owner: dyachkov_ya
|
|
|
+--
|
|
|
+
|
|
|
+ALTER TABLE ONLY dyachkov_ya.auditlog ALTER COLUMN id_log SET DEFAULT nextval('dyachkov_ya.auditlog_id_log_seq'::regclass);
|
|
|
+
|
|
|
+
|
|
|
+--
|
|
|
+-- TOC entry 6325 (class 2604 OID 450376)
|
|
|
+-- Name: roles id_role; Type: DEFAULT; Schema: dyachkov_ya; Owner: dyachkov_ya
|
|
|
+--
|
|
|
+
|
|
|
+ALTER TABLE ONLY dyachkov_ya.roles ALTER COLUMN id_role SET DEFAULT nextval('dyachkov_ya.roles_id_role_seq'::regclass);
|
|
|
+
|
|
|
+
|
|
|
+--
|
|
|
+-- TOC entry 6326 (class 2604 OID 450389)
|
|
|
+-- Name: users id_user; Type: DEFAULT; Schema: dyachkov_ya; Owner: dyachkov_ya
|
|
|
+--
|
|
|
+
|
|
|
+ALTER TABLE ONLY dyachkov_ya.users ALTER COLUMN id_user SET DEFAULT nextval('dyachkov_ya.users_id_user_seq'::regclass);
|
|
|
+
|
|
|
+
|
|
|
+--
|
|
|
+-- TOC entry 6616 (class 0 OID 450407)
|
|
|
+-- Dependencies: 720
|
|
|
+-- Data for Name: auditlog; Type: TABLE DATA; Schema: dyachkov_ya; Owner: dyachkov_ya
|
|
|
+--
|
|
|
+
|
|
|
+COPY dyachkov_ya.auditlog (id_log, id_user, action, table_name, record_id, action_time, ip_address, details) FROM stdin;
|
|
|
+\.
|
|
|
+
|
|
|
+
|
|
|
+--
|
|
|
+-- TOC entry 6607 (class 0 OID 444440)
|
|
|
+-- Dependencies: 325
|
|
|
+-- Data for Name: creator; Type: TABLE DATA; Schema: dyachkov_ya; Owner: dyachkov_ya
|
|
|
+--
|
|
|
+
|
|
|
+COPY dyachkov_ya.creator (id_creator, full_name, royalty, phone, address) FROM stdin;
|
|
|
+1 Иван Иванов 10000.00 +7-111-1111111 ул. Пушкина, 1
|
|
|
+2 Мария Петрова 15000.00 +7-222-2222222 ул. Лермонтова, 2
|
|
|
+3 Алексей Сидоров 12000.00 +7-333-3333333 ул. Гоголя, 3
|
|
|
+4 Елена Васильева 18000.00 +7-444-4444444 ул. Толстого, 4
|
|
|
+\.
|
|
|
+
|
|
|
+
|
|
|
+--
|
|
|
+-- TOC entry 6609 (class 0 OID 444460)
|
|
|
+-- Dependencies: 327
|
|
|
+-- Data for Name: exhibit; Type: TABLE DATA; Schema: dyachkov_ya; Owner: dyachkov_ya
|
|
|
+--
|
|
|
+
|
|
|
+COPY dyachkov_ya.exhibit (id_exhibit, type, creation_date, copy_price, creation_cost, id_creator, id_museum) FROM stdin;
|
|
|
+101 Живопись 2020-01-15 200000.00 50000.00 1 1
|
|
|
+102 Скульптура 2019-10-20 150000.00 40000.00 2 1
|
|
|
+103 Графика 2021-05-10 80000.00 20000.00 1 2
|
|
|
+104 Живопись 2018-07-22 250000.00 60000.00 3 1
|
|
|
+105 Фотография 2022-03-15 50000.00 10000.00 2 2
|
|
|
+106 Скульптура 2020-11-30 120000.00 35000.00 4 3
|
|
|
+107 Икона 2017-09-05 300000.00 80000.00 1 1
|
|
|
+108 Графика 2019-12-18 50000.00 15000.00 3 3
|
|
|
+\.
|
|
|
+
|
|
|
+
|
|
|
+--
|
|
|
+-- TOC entry 6606 (class 0 OID 444434)
|
|
|
+-- Dependencies: 324
|
|
|
+-- Data for Name: museum; Type: TABLE DATA; Schema: dyachkov_ya; Owner: dyachkov_ya
|
|
|
+--
|
|
|
+
|
|
|
+COPY dyachkov_ya.museum (id_museum, area, profit, phone, address) FROM stdin;
|
|
|
+1 1200.50 500000.00 +7-123-4567890 ул. Тверская, 5, Москва
|
|
|
+3 1500.00 750000.00 +7-555-1234567 ул. Ленина, 15, Екатеринбург
|
|
|
+2 800.00 400000.00 +7-987-6543210 пр. Невский, 10, Санкт-Петербург
|
|
|
+\.
|
|
|
+
|
|
|
+
|
|
|
+--
|
|
|
+-- TOC entry 6612 (class 0 OID 450373)
|
|
|
+-- Dependencies: 716
|
|
|
+-- Data for Name: roles; Type: TABLE DATA; Schema: dyachkov_ya; Owner: dyachkov_ya
|
|
|
+--
|
|
|
+
|
|
|
+COPY dyachkov_ya.roles (id_role, role_name, description) FROM stdin;
|
|
|
+1 Admin Полный доступ ко всем функциям
|
|
|
+2 Curator Управление экспонатами и авторами
|
|
|
+3 Cashier Работа с посетителями
|
|
|
+4 Guest Только просмотр
|
|
|
+\.
|
|
|
+
|
|
|
+
|
|
|
+--
|
|
|
+-- TOC entry 6614 (class 0 OID 450386)
|
|
|
+-- Dependencies: 718
|
|
|
+-- Data for Name: users; Type: TABLE DATA; Schema: dyachkov_ya; Owner: dyachkov_ya
|
|
|
+--
|
|
|
+
|
|
|
+COPY dyachkov_ya.users (id_user, username, password_hash, salt, id_role, created_at, last_login, is_active) FROM stdin;
|
|
|
+9 curator 1bc936e86f9f3f3082b9e81e5489639dda3661522011f0586d74630d30aa9c2f wkcZ1ZKs7I9Fkrhs4V6P6uM0kx0IYbY8aRyYfa06+mE= 2 2026-06-01 16:30:13.375361 \N t
|
|
|
+10 cashier 7f3c6eac18259fab2b0916dcd958ecbd6c5a7e1e11823fd64d23388852c57445 Yomt7dErmMWuTyE/Ut3HMN1gzzXuF9y0YFL8yVVObOU= 3 2026-06-01 16:30:13.402044 \N t
|
|
|
+11 guest c09bbc66d7d00cbd91441685c4f0a23811d59d2d57754fc0b82f7271df245428 dAO2P8AgdohaItFZI4JpZ8PH/JH/AXbXJELFl4DPEmY= 4 2026-06-01 16:30:13.433068 \N t
|
|
|
+8 admin 119e41ff69e6c9fd2133b72169dd666a9caf9d24765483274de2730f00d85f5a WLdeT8d1JEiq//inGEmb83MFydypm84/dldG8Bg366k= 1 2026-06-01 16:30:13.324373 2026-06-29 00:42:40.906973 t
|
|
|
+\.
|
|
|
+
|
|
|
+
|
|
|
+--
|
|
|
+-- TOC entry 6610 (class 0 OID 444476)
|
|
|
+-- Dependencies: 328
|
|
|
+-- Data for Name: viewing; Type: TABLE DATA; Schema: dyachkov_ya; Owner: dyachkov_ya
|
|
|
+--
|
|
|
+
|
|
|
+COPY dyachkov_ya.viewing (id_ticket, id_exhibit, exhibit_rating) FROM stdin;
|
|
|
+1001 101 5
|
|
|
+1001 102 4
|
|
|
+1001 103 5
|
|
|
+1002 103 4
|
|
|
+1002 105 5
|
|
|
+1003 101 5
|
|
|
+1003 104 4
|
|
|
+1003 107 5
|
|
|
+1004 106 3
|
|
|
+1004 108 4
|
|
|
+1005 103 5
|
|
|
+1005 105 4
|
|
|
+1006 101 5
|
|
|
+1006 102 5
|
|
|
+1006 104 4
|
|
|
+\.
|
|
|
+
|
|
|
+
|
|
|
+--
|
|
|
+-- TOC entry 6608 (class 0 OID 444447)
|
|
|
+-- Dependencies: 326
|
|
|
+-- Data for Name: visitor; Type: TABLE DATA; Schema: dyachkov_ya; Owner: dyachkov_ya
|
|
|
+--
|
|
|
+
|
|
|
+COPY dyachkov_ya.visitor (id_ticket, full_name, phone, visit_date, museum_rating, id_museum) FROM stdin;
|
|
|
+1001 Петр Сидоров +7-123-4567890 2023-06-01 5 1
|
|
|
+1002 Анна Ким +7-234-5678901 2023-06-02 4 2
|
|
|
+1003 Олег Иванов +7-345-6789012 2023-06-03 5 1
|
|
|
+1004 Наталья Смирнова +7-456-7890123 2023-06-04 3 3
|
|
|
+1005 Дмитрий Петров +7-567-8901234 2023-06-05 4 2
|
|
|
+1006 Екатерина Кузнецова +7-678-9012345 2023-06-06 5 1
|
|
|
+\.
|
|
|
+
|
|
|
+
|
|
|
+--
|
|
|
+-- TOC entry 6625 (class 0 OID 0)
|
|
|
+-- Dependencies: 719
|
|
|
+-- Name: auditlog_id_log_seq; Type: SEQUENCE SET; Schema: dyachkov_ya; Owner: dyachkov_ya
|
|
|
+--
|
|
|
+
|
|
|
+SELECT pg_catalog.setval('dyachkov_ya.auditlog_id_log_seq', 1, false);
|
|
|
+
|
|
|
+
|
|
|
+--
|
|
|
+-- TOC entry 6626 (class 0 OID 0)
|
|
|
+-- Dependencies: 715
|
|
|
+-- Name: roles_id_role_seq; Type: SEQUENCE SET; Schema: dyachkov_ya; Owner: dyachkov_ya
|
|
|
+--
|
|
|
+
|
|
|
+SELECT pg_catalog.setval('dyachkov_ya.roles_id_role_seq', 9, true);
|
|
|
+
|
|
|
+
|
|
|
+--
|
|
|
+-- TOC entry 6627 (class 0 OID 0)
|
|
|
+-- Dependencies: 717
|
|
|
+-- Name: users_id_user_seq; Type: SEQUENCE SET; Schema: dyachkov_ya; Owner: dyachkov_ya
|
|
|
+--
|
|
|
+
|
|
|
+SELECT pg_catalog.setval('dyachkov_ya.users_id_user_seq', 11, true);
|
|
|
+
|
|
|
+
|
|
|
+--
|
|
|
+-- TOC entry 6352 (class 2606 OID 450416)
|
|
|
+-- Name: auditlog auditlog_pkey; Type: CONSTRAINT; Schema: dyachkov_ya; Owner: dyachkov_ya
|
|
|
+--
|
|
|
+
|
|
|
+ALTER TABLE ONLY dyachkov_ya.auditlog
|
|
|
+ ADD CONSTRAINT auditlog_pkey PRIMARY KEY (id_log);
|
|
|
+
|
|
|
+
|
|
|
+--
|
|
|
+-- TOC entry 6336 (class 2606 OID 444446)
|
|
|
+-- Name: creator creator_pkey; Type: CONSTRAINT; Schema: dyachkov_ya; Owner: dyachkov_ya
|
|
|
+--
|
|
|
+
|
|
|
+ALTER TABLE ONLY dyachkov_ya.creator
|
|
|
+ ADD CONSTRAINT creator_pkey PRIMARY KEY (id_creator);
|
|
|
+
|
|
|
+
|
|
|
+--
|
|
|
+-- TOC entry 6340 (class 2606 OID 444465)
|
|
|
+-- Name: exhibit exhibit_pkey; Type: CONSTRAINT; Schema: dyachkov_ya; Owner: dyachkov_ya
|
|
|
+--
|
|
|
+
|
|
|
+ALTER TABLE ONLY dyachkov_ya.exhibit
|
|
|
+ ADD CONSTRAINT exhibit_pkey PRIMARY KEY (id_exhibit);
|
|
|
+
|
|
|
+
|
|
|
+--
|
|
|
+-- TOC entry 6334 (class 2606 OID 444439)
|
|
|
+-- Name: museum museum_pkey; Type: CONSTRAINT; Schema: dyachkov_ya; Owner: dyachkov_ya
|
|
|
+--
|
|
|
+
|
|
|
+ALTER TABLE ONLY dyachkov_ya.museum
|
|
|
+ ADD CONSTRAINT museum_pkey PRIMARY KEY (id_museum);
|
|
|
+
|
|
|
+
|
|
|
+--
|
|
|
+-- TOC entry 6344 (class 2606 OID 450382)
|
|
|
+-- Name: roles roles_pkey; Type: CONSTRAINT; Schema: dyachkov_ya; Owner: dyachkov_ya
|
|
|
+--
|
|
|
+
|
|
|
+ALTER TABLE ONLY dyachkov_ya.roles
|
|
|
+ ADD CONSTRAINT roles_pkey PRIMARY KEY (id_role);
|
|
|
+
|
|
|
+
|
|
|
+--
|
|
|
+-- TOC entry 6346 (class 2606 OID 450384)
|
|
|
+-- Name: roles roles_role_name_key; Type: CONSTRAINT; Schema: dyachkov_ya; Owner: dyachkov_ya
|
|
|
+--
|
|
|
+
|
|
|
+ALTER TABLE ONLY dyachkov_ya.roles
|
|
|
+ ADD CONSTRAINT roles_role_name_key UNIQUE (role_name);
|
|
|
+
|
|
|
+
|
|
|
+--
|
|
|
+-- TOC entry 6348 (class 2606 OID 450398)
|
|
|
+-- Name: users users_pkey; Type: CONSTRAINT; Schema: dyachkov_ya; Owner: dyachkov_ya
|
|
|
+--
|
|
|
+
|
|
|
+ALTER TABLE ONLY dyachkov_ya.users
|
|
|
+ ADD CONSTRAINT users_pkey PRIMARY KEY (id_user);
|
|
|
+
|
|
|
+
|
|
|
+--
|
|
|
+-- TOC entry 6350 (class 2606 OID 450400)
|
|
|
+-- Name: users users_username_key; Type: CONSTRAINT; Schema: dyachkov_ya; Owner: dyachkov_ya
|
|
|
+--
|
|
|
+
|
|
|
+ALTER TABLE ONLY dyachkov_ya.users
|
|
|
+ ADD CONSTRAINT users_username_key UNIQUE (username);
|
|
|
+
|
|
|
+
|
|
|
+--
|
|
|
+-- TOC entry 6342 (class 2606 OID 444485)
|
|
|
+-- Name: viewing viewing_pkey; Type: CONSTRAINT; Schema: dyachkov_ya; Owner: dyachkov_ya
|
|
|
+--
|
|
|
+
|
|
|
+ALTER TABLE ONLY dyachkov_ya.viewing
|
|
|
+ ADD CONSTRAINT viewing_pkey PRIMARY KEY (id_ticket, id_exhibit);
|
|
|
+
|
|
|
+
|
|
|
+--
|
|
|
+-- TOC entry 6338 (class 2606 OID 444454)
|
|
|
+-- Name: visitor visitor_pkey; Type: CONSTRAINT; Schema: dyachkov_ya; Owner: dyachkov_ya
|
|
|
+--
|
|
|
+
|
|
|
+ALTER TABLE ONLY dyachkov_ya.visitor
|
|
|
+ ADD CONSTRAINT visitor_pkey PRIMARY KEY (id_ticket);
|
|
|
+
|
|
|
+
|
|
|
+--
|
|
|
+-- TOC entry 6360 (class 2620 OID 444523)
|
|
|
+-- Name: exhibit after_exhibit_insert; Type: TRIGGER; Schema: dyachkov_ya; Owner: dyachkov_ya
|
|
|
+--
|
|
|
+
|
|
|
+CREATE TRIGGER after_exhibit_insert AFTER INSERT ON dyachkov_ya.exhibit FOR EACH ROW EXECUTE FUNCTION dyachkov_ya.update_museum_profit();
|
|
|
+
|
|
|
+
|
|
|
+--
|
|
|
+-- TOC entry 6359 (class 2606 OID 450417)
|
|
|
+-- Name: auditlog auditlog_id_user_fkey; Type: FK CONSTRAINT; Schema: dyachkov_ya; Owner: dyachkov_ya
|
|
|
+--
|
|
|
+
|
|
|
+ALTER TABLE ONLY dyachkov_ya.auditlog
|
|
|
+ ADD CONSTRAINT auditlog_id_user_fkey FOREIGN KEY (id_user) REFERENCES dyachkov_ya.users(id_user);
|
|
|
+
|
|
|
+
|
|
|
+--
|
|
|
+-- TOC entry 6354 (class 2606 OID 444466)
|
|
|
+-- Name: exhibit exhibit_id_creator_fkey; Type: FK CONSTRAINT; Schema: dyachkov_ya; Owner: dyachkov_ya
|
|
|
+--
|
|
|
+
|
|
|
+ALTER TABLE ONLY dyachkov_ya.exhibit
|
|
|
+ ADD CONSTRAINT exhibit_id_creator_fkey FOREIGN KEY (id_creator) REFERENCES dyachkov_ya.creator(id_creator);
|
|
|
+
|
|
|
+
|
|
|
+--
|
|
|
+-- TOC entry 6355 (class 2606 OID 444471)
|
|
|
+-- Name: exhibit exhibit_id_museum_fkey; Type: FK CONSTRAINT; Schema: dyachkov_ya; Owner: dyachkov_ya
|
|
|
+--
|
|
|
+
|
|
|
+ALTER TABLE ONLY dyachkov_ya.exhibit
|
|
|
+ ADD CONSTRAINT exhibit_id_museum_fkey FOREIGN KEY (id_museum) REFERENCES dyachkov_ya.museum(id_museum);
|
|
|
+
|
|
|
+
|
|
|
+--
|
|
|
+-- TOC entry 6358 (class 2606 OID 450401)
|
|
|
+-- Name: users users_id_role_fkey; Type: FK CONSTRAINT; Schema: dyachkov_ya; Owner: dyachkov_ya
|
|
|
+--
|
|
|
+
|
|
|
+ALTER TABLE ONLY dyachkov_ya.users
|
|
|
+ ADD CONSTRAINT users_id_role_fkey FOREIGN KEY (id_role) REFERENCES dyachkov_ya.roles(id_role);
|
|
|
+
|
|
|
+
|
|
|
+--
|
|
|
+-- TOC entry 6356 (class 2606 OID 444491)
|
|
|
+-- Name: viewing viewing_id_exhibit_fkey; Type: FK CONSTRAINT; Schema: dyachkov_ya; Owner: dyachkov_ya
|
|
|
+--
|
|
|
+
|
|
|
+ALTER TABLE ONLY dyachkov_ya.viewing
|
|
|
+ ADD CONSTRAINT viewing_id_exhibit_fkey FOREIGN KEY (id_exhibit) REFERENCES dyachkov_ya.exhibit(id_exhibit);
|
|
|
+
|
|
|
+
|
|
|
+--
|
|
|
+-- TOC entry 6357 (class 2606 OID 444486)
|
|
|
+-- Name: viewing viewing_id_ticket_fkey; Type: FK CONSTRAINT; Schema: dyachkov_ya; Owner: dyachkov_ya
|
|
|
+--
|
|
|
+
|
|
|
+ALTER TABLE ONLY dyachkov_ya.viewing
|
|
|
+ ADD CONSTRAINT viewing_id_ticket_fkey FOREIGN KEY (id_ticket) REFERENCES dyachkov_ya.visitor(id_ticket);
|
|
|
+
|
|
|
+
|
|
|
+--
|
|
|
+-- TOC entry 6353 (class 2606 OID 444455)
|
|
|
+-- Name: visitor visitor_id_museum_fkey; Type: FK CONSTRAINT; Schema: dyachkov_ya; Owner: dyachkov_ya
|
|
|
+--
|
|
|
+
|
|
|
+ALTER TABLE ONLY dyachkov_ya.visitor
|
|
|
+ ADD CONSTRAINT visitor_id_museum_fkey FOREIGN KEY (id_museum) REFERENCES dyachkov_ya.museum(id_museum);
|
|
|
+
|
|
|
+
|
|
|
+-- Completed on 2026-06-30 18:28:57 MSK
|
|
|
+
|
|
|
+--
|
|
|
+-- PostgreSQL database dump complete
|
|
|
+--
|
|
|
+
|
|
|
+\unrestrict fMX8pe7fyPeennYB6eeK17lVC7rkBp0LxzYWCFMQgMflMYdB3BYjGmqxfiz2Aj2
|
|
|
+
|