%PDF- %PDF-
| Direktori : /proc/self/root/backups/router/usr/local/share/kea/scripts/pgsql/ |
| Current File : //proc/self/root/backups/router/usr/local/share/kea/scripts/pgsql/upgrade_009_to_010.sh |
#!/bin/sh
# Copyright (C) 2022-2024 Internet Systems Consortium, Inc. ("ISC")
#
# This Source Code Form is subject to the terms of the Mozilla Public
# License, v. 2.0. If a copy of the MPL was not distributed with this
# file, You can obtain one at http://mozilla.org/MPL/2.0/.
# Exit with error if commands exit with non-zero and if undefined variables are
# used.
set -eu
# shellcheck disable=SC2034
# SC2034: ... appears unused. Verify use (or export if used externally).
prefix="/usr/local"
# Include utilities based on location of this script. Check for sources first,
# so that the unexpected situations with weird paths fall on the default
# case of installed.
script_path=$(cd "$(dirname "${0}")" && pwd)
if test "${script_path}" = "/usr/obj/usr/ports/net/kea/work/kea-2.6.1/src/share/database/scripts/pgsql"; then
# shellcheck source=./src/bin/admin/admin-utils.sh.in
. "/usr/obj/usr/ports/net/kea/work/kea-2.6.1/src/bin/admin/admin-utils.sh"
else
# shellcheck source=./src/bin/admin/admin-utils.sh.in
. "${prefix}/share/kea/scripts/admin-utils.sh"
fi
VERSION=$(pgsql_version "$@")
if [ "$VERSION" != "9.0" ]; then
printf 'This script upgrades 9.0 to 10.0. '
printf 'Reported version is %s. Skipping upgrade.\n' "${VERSION}"
exit 0
fi
psql "$@" >/dev/null <<EOF
START TRANSACTION;
-- This line starts the schema upgrade to version 10.0.
-- It adds corrections for client classes for CB
-- Replace setClientClass4Order():
-- 1. l_depend_on_known_indirectly needs to be BOOL
-- 2. follow_class_index needs to be BIGINT
-- -----------------------------------------------------------------------
-- Stored procedure positioning an inserted or updated client class
-- within the class hierarchy, depending on the value of the
-- new_follow_class_name parameter.
--
-- Parameters:
-- - id id of the positioned class,
-- - new_follow_class_name name of the class after which this class should be
-- positioned within the class hierarchy.
-- - old_follow_class_name previous name of the class after which this
-- class was positioned within the class hierarchy.
-- -----------------------------------------------------------------------
CREATE OR REPLACE FUNCTION setClientClass4Order(id BIGINT,
new_follow_class_name VARCHAR(128),
old_follow_class_name VARCHAR(128))
RETURNS VOID
LANGUAGE plpgsql
AS \$\$
DECLARE
-- Used to fetch class's current value for depend_on_known_indirectly
l_depend_on_known_indirectly BOOL := false;
-- Optionally set if the follow_class_name column value is specified.
follow_class_index BIGINT;
BEGIN
-- Fetch the class's current value of depend_on_known_indirectly.
SELECT depend_on_known_indirectly INTO l_depend_on_known_indirectly
FROM dhcp4_client_class_order WHERE id = class_id;
-- Save it to the current session for use elsewhere during this transaction.
-- Note this does not work prior to Postgres 9.2 unless the variables are
-- defined in postgresql.conf. I think for now we put up with CB not supported
-- prior to 9.2 or we tell people how to edit the conf file.
PERFORM set_session_value('kea.depend_on_known_indirectly', l_depend_on_known_indirectly);
-- Bail if the class is updated without re-positioning.
IF(
l_depend_on_known_indirectly IS NOT NULL AND
((new_follow_class_name IS NULL AND old_follow_class_name IS NULL) OR
(new_follow_class_name = old_follow_class_name))
) THEN
-- The depend_on_known_indirectly is set to 0 because this procedure is invoked
-- whenever the dhcp4_client_class record is updated. Such update may include
-- test expression changes impacting the dependency on KNOWN/UNKNOWN classes.
-- This value will be later adjusted when dependencies are inserted.
-- TKM should we update the session value also or is it moot?
UPDATE dhcp4_client_class_order SET depend_on_known_indirectly = false
WHERE class_id = id;
RETURN;
END IF;
IF new_follow_class_name IS NOT NULL THEN
-- Get the position of the class after which the new class should be added.
SELECT o.order_index INTO follow_class_index
FROM dhcp4_client_class AS c
INNER JOIN dhcp4_client_class_order AS o
ON c.id = o.class_id
WHERE c.name = new_follow_class_name;
IF follow_class_index IS NULL THEN
-- The class with a name specified with new_follow_class_name does
-- not exist.
RAISE EXCEPTION 'Class %s does not exist.', new_follow_class_name
USING ERRCODE = 'sql_routine_exception';
END IF;
-- We need to place the new class at the position of follow_class_index + 1.
-- There may be a class at this position already.
IF EXISTS(SELECT * FROM dhcp4_client_class_order WHERE order_index = follow_class_index + 1) THEN
-- There is a class at this position already. Let's move all classes
-- starting from this position by one to create a spot for the new
-- class.
UPDATE dhcp4_client_class_order
SET order_index = order_index + 1
WHERE order_index >= follow_class_index + 1;
-- TKM postgresql doesn't like order by here, does it matter?
-- ORDER BY order_index DESC;
END IF;
ELSE
-- A caller did not specify the new_follow_class_name value. Let's append the
-- new class at the end of the hierarchy.
SELECT MAX(order_index) INTO follow_class_index FROM dhcp4_client_class_order;
IF follow_class_index IS NULL THEN
-- Apparently, there are no classes. Let's start from 0.
follow_class_index = 0;
END IF;
END IF;
-- Check if moving the class doesn't break dependent classes.
IF EXISTS(
SELECT 1 FROM dhcp4_client_class_dependency AS d
INNER JOIN dhcp4_client_class_order AS o
ON d.class_id = o.class_id
WHERE d.dependency_id = id AND o.order_index < follow_class_index + 1
LIMIT 1
) THEN
RAISE EXCEPTION 'Unable to move class with id %s because it would break its dependencies', id
USING ERRCODE = 'sql_routine_exception';
END IF;
-- The depend_on_known_indirectly is set to 0 because this procedure is invoked
-- whenever the dhcp4_client_class record is updated. Such update may include
-- test expression changes impacting the dependency on KNOWN/UNKNOWN classes.
-- This value will be later adjusted when dependencies are inserted.
-- TKM - note that ON CONFLICT requires PostgreSQL 9.5 or later.
UPDATE dhcp4_client_class_order
SET order_index = follow_class_index + 1,
depend_on_known_indirectly = l_depend_on_known_indirectly
WHERE class_id = id;
IF FOUND THEN
RETURN;
END IF;
INSERT INTO dhcp4_client_class_order(class_id, order_index, depend_on_known_indirectly)
VALUES (id, follow_class_index + 1, false);
RETURN;
END;\$\$;
-- Replace setClientClass6Order():
-- 1. l_depend_on_known_indirectly needs to be BOOL
-- 2. follow_class_index needs to be BIGINT
-- -----------------------------------------------------------------------
-- Stored procedure positioning an inserted or updated client class
-- within the class hierarchy, depending on the value of the
-- new_follow_class_name parameter.
--
-- Parameters:
-- - id id of the positioned class,
-- - new_follow_class_name name of the class after which this class should be
-- positioned within the class hierarchy.
-- - old_follow_class_name previous name of the class after which this
-- class was positioned within the class hierarchy.
-- -----------------------------------------------------------------------
CREATE OR REPLACE FUNCTION setClientClass6Order(id BIGINT,
new_follow_class_name VARCHAR(128),
old_follow_class_name VARCHAR(128))
RETURNS VOID
LANGUAGE plpgsql
AS \$\$
DECLARE
-- Used to fetch class's current value for depend_on_known_indirectly
l_depend_on_known_indirectly BOOL := false;
-- Optionally set if the follow_class_name column value is specified.
follow_class_index BIGINT;
BEGIN
-- Fetch the class's current value of depend_on_known_indirectly.
SELECT depend_on_known_indirectly INTO l_depend_on_known_indirectly
FROM dhcp6_client_class_order WHERE id = class_id;
-- Save it to the current session for use elsewhere during this transaction.
-- Note this does not work prior to Postgres 9.2 unless the variables are
-- defined in postgresql.conf. I think for now we put up with CB not supported
-- prior to 9.2 or we tell people how to edit the conf file.
PERFORM set_session_value('kea.depend_on_known_indirectly', l_depend_on_known_indirectly);
-- Bail if the class is updated without re-positioning.
IF(
l_depend_on_known_indirectly IS NOT NULL AND
((new_follow_class_name IS NULL AND old_follow_class_name IS NULL) OR
(new_follow_class_name = old_follow_class_name))
) THEN
-- The depend_on_known_indirectly is set to 0 because this procedure is invoked
-- whenever the dhcp6_client_class record is updated. Such update may include
-- test expression changes impacting the dependency on KNOWN/UNKNOWN classes.
-- This value will be later adjusted when dependencies are inserted.
-- TKM should we update the session value also or is it moot?
UPDATE dhcp6_client_class_order SET depend_on_known_indirectly = false
WHERE class_id = id;
RETURN;
END IF;
IF new_follow_class_name IS NOT NULL THEN
-- Get the position of the class after which the new class should be added.
SELECT o.order_index INTO follow_class_index
FROM dhcp6_client_class AS c
INNER JOIN dhcp6_client_class_order AS o
ON c.id = o.class_id
WHERE c.name = new_follow_class_name;
IF follow_class_index IS NULL THEN
-- The class with a name specified with new_follow_class_name does
-- not exist.
RAISE EXCEPTION 'Class %s does not exist.', new_follow_class_name
USING ERRCODE = 'sql_routine_exception';
END IF;
-- We need to place the new class at the position of follow_class_index + 1.
-- There may be a class at this position already.
IF EXISTS(SELECT * FROM dhcp6_client_class_order WHERE order_index = follow_class_index + 1) THEN
-- There is a class at this position already. Let's move all classes
-- starting from this position by one to create a spot for the new
-- class.
UPDATE dhcp6_client_class_order
SET order_index = order_index + 1
WHERE order_index >= follow_class_index + 1;
-- TKM postgresql doesn't like order by here, does it matter?
-- ORDER BY order_index DESC;
END IF;
ELSE
-- A caller did not specify the new_follow_class_name value. Let's append the
-- new class at the end of the hierarchy.
SELECT MAX(order_index) INTO follow_class_index FROM dhcp6_client_class_order;
IF follow_class_index IS NULL THEN
-- Apparently, there are no classes. Let's start from 0.
follow_class_index = 0;
END IF;
END IF;
-- Check if moving the class doesn't break dependent classes.
IF EXISTS(
SELECT 1 FROM dhcp6_client_class_dependency AS d
INNER JOIN dhcp6_client_class_order AS o
ON d.class_id = o.class_id
WHERE d.dependency_id = id AND o.order_index < follow_class_index + 1
LIMIT 1
) THEN
RAISE EXCEPTION 'Unable to move class with id %s because it would break its dependencies', id
USING ERRCODE = 'sql_routine_exception';
END IF;
-- The depend_on_known_indirectly is set to 0 because this procedure is invoked
-- whenever the dhcp6_client_class record is updated. Such update may include
-- test expression changes impacting the dependency on KNOWN/UNKNOWN classes.
-- This value will be later adjusted when dependencies are inserted.
-- TKM - note that ON CONFLICT requires PostgreSQL 9.5 or later.
UPDATE dhcp6_client_class_order
SET order_index = follow_class_index + 1,
depend_on_known_indirectly = l_depend_on_known_indirectly
WHERE class_id = id;
IF FOUND THEN
RETURN;
END IF;
INSERT INTO dhcp6_client_class_order(class_id, order_index, depend_on_known_indirectly)
VALUES (id, follow_class_index + 1, false);
RETURN;
END;\$\$;
-- Change primary key to composite, dependency table can have multiple rows
-- per class id.
ALTER TABLE dhcp4_client_class_dependency DROP CONSTRAINT dhcp4_client_class_dependency_pkey;
ALTER TABLE dhcp4_client_class_dependency ADD PRIMARY KEY(class_id, dependency_id);
ALTER TABLE dhcp6_client_class_dependency DROP CONSTRAINT dhcp6_client_class_dependency_pkey;
ALTER TABLE dhcp6_client_class_dependency ADD PRIMARY KEY(class_id, dependency_id);
-- Replace triggers that verify class dependency.
-- Because they are BEFORE INSERT triggers they need to return NEW not NULL.
-- -----------------------------------------------------------------------
-- Trigger verifying if class dependency is met. It includes checking
-- if referenced classes exist, are associated with the same server
-- or all servers, and are defined before the class specified with
-- class_id.
-- -----------------------------------------------------------------------
CREATE OR REPLACE FUNCTION func_dhcp4_client_class_check_dependency_BINS()
RETURNS trigger AS \$dhcp4_client_class_check_dependency_BINS\$
BEGIN
PERFORM checkDHCPv4ClientClassDependency(NEW.class_id, NEW.dependency_id);
RETURN NEW;
END;
\$dhcp4_client_class_check_dependency_BINS\$
LANGUAGE plpgsql;
-- -----------------------------------------------------------------------
-- Trigger verifying if class dependency is met. It includes checking
-- if referenced classes exist, are associated with the same server
-- or all servers, and are defined before the class specified with
-- class_id.
-- -----------------------------------------------------------------------
CREATE OR REPLACE FUNCTION func_dhcp6_client_class_check_dependency_BINS()
RETURNS trigger AS \$dhcp6_client_class_check_dependency_BINS\$
BEGIN
PERFORM checkDHCPv6ClientClassDependency(NEW.class_id, NEW.dependency_id);
RETURN NEW;
END;
\$dhcp6_client_class_check_dependency_BINS\$
LANGUAGE plpgsql;
-- Update the schema version number.
UPDATE schema_version
SET version = '10', minor = '0';
-- This line concludes the schema upgrade to version 10.0.
-- Commit the script transaction.
COMMIT;
EOF