%PDF- %PDF-
| Direktori : /proc/self/root/backups/router/usr/local/share/kea/scripts/mysql/ |
| Current File : //proc/self/root/backups/router/usr/local/share/kea/scripts/mysql/upgrade_013_to_014.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/mysql"; 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
# Check version.
version=$(mysql_version "${@}")
if test "${version}" != "13.0"; then
printf 'This script upgrades 13.0 to 14.0. '
printf 'Reported version is %s. Skipping upgrade.\n' "${version}"
exit 0
fi
# Get the schema name from database argument. We need this to
# query information_schema for the right database.
for arg in "${@}"
do
if ! printf '%s' "${arg}" | grep -Eq -- '^--'
then
schema="$arg"
break
fi
done
# Make sure we have the schema.
if [ -z "$schema" ]
then
printf "Could not find database schema name in cmd line args: %s\n" "${*}"
exit 255
fi
mysql "$@" <<EOF
-- This line starts the schema upgrade to version 14.0.
-- Modify shared-network-name foreign key constraint on dhcp4_subnet to not perform
-- the update when the network is deleted the cascaded update will not execute
-- dhcp4_subnet update trigger leaving the updated subnets without audit_entries.
ALTER TABLE dhcp4_subnet
DROP FOREIGN KEY fk_dhcp4_subnet_shared_network;
ALTER TABLE dhcp4_subnet
ADD CONSTRAINT fk_dhcp4_subnet_shared_network FOREIGN KEY (shared_network_name)
REFERENCES dhcp4_shared_network (name)
ON DELETE NO ACTION ON UPDATE NO ACTION;
-- Modify BEFORE delete trigger on dhcp4_shared_network to explicitly
-- update dhcp4_subnets. This ensures there are audit entries for updated
-- subnets.
DROP TRIGGER dhcp4_shared_network_BDEL;
DELIMITER $$
CREATE TRIGGER dhcp4_shared_network_BDEL BEFORE DELETE ON dhcp4_shared_network
FOR EACH ROW
BEGIN
CALL createAuditEntryDHCP4('dhcp4_shared_network', OLD.id, "delete");
-- In MySQL Foreign key constraint triggered updates will not cascade, so we explicitly
-- update subnets first which should ensure they get audit entries.
UPDATE dhcp4_subnet SET shared_network_name = NULL WHERE shared_network_name = OLD.name;
DELETE FROM dhcp4_options WHERE shared_network_name = OLD.name;
END $$
DELIMITER ;
-- Modify shared-network-name foreign key constraint on dhcp6_subnet to not perform
-- the update when the network is deleted the cascaded update will not execute
-- dhcp6_subnet update trigger leaving the updated subnets without audit_entries.
ALTER TABLE dhcp6_subnet
DROP FOREIGN KEY fk_dhcp6_subnet_shared_network;
ALTER TABLE dhcp6_subnet
ADD CONSTRAINT fk_dhcp6_subnet_shared_network FOREIGN KEY (shared_network_name)
REFERENCES dhcp6_shared_network (name)
ON DELETE NO ACTION ON UPDATE NO ACTION;
-- Modify BEFORE delete trigger on dhcp6_shared_network to explicitly
-- update dhcp6_subnets. This ensures there are audit entries for updated
-- subnets.
DROP TRIGGER dhcp6_shared_network_BDEL;
DELIMITER $$
CREATE TRIGGER dhcp6_shared_network_BDEL BEFORE DELETE ON dhcp6_shared_network
FOR EACH ROW
BEGIN
CALL createAuditEntryDHCP6('dhcp6_shared_network', OLD.id, "delete");
-- In MySQL Foreign key constraint triggered updates will not cascade, so we explicitly
-- update subnets first which should ensure they get audit entries.
UPDATE dhcp6_subnet SET shared_network_name = NULL WHERE shared_network_name = OLD.name;
DELETE FROM dhcp6_options WHERE shared_network_name = OLD.name;
END $$
DELIMITER ;
-- Add user_context column to client class tables.
ALTER TABLE dhcp4_client_class ADD COLUMN user_context LONGTEXT NULL;
ALTER TABLE dhcp6_client_class ADD COLUMN user_context LONGTEXT NULL;
-- Schema changes related to lease limiting start here. --
-- Recreate the triggers that update the leaseX_stat tables as stored procedures. --
DROP PROCEDURE IF EXISTS lease4_AINS_lease4_stat;
DELIMITER $$
CREATE PROCEDURE lease4_AINS_lease4_stat(IN new_state TINYINT,
IN new_subnet_id INT UNSIGNED)
BEGIN
IF new_state = 0 OR new_state = 1 THEN
-- Update the state count if it exists.
UPDATE lease4_stat SET leases = leases + 1
WHERE subnet_id = new_subnet_id AND state = new_state;
-- Insert the state count record if it does not exist.
IF ROW_COUNT() <= 0 THEN
INSERT INTO lease4_stat VALUES (new_subnet_id, new_state, 1);
END IF;
END IF;
END $$
DELIMITER ;
DROP PROCEDURE IF EXISTS lease4_AUPD_lease4_stat;
DELIMITER $$
CREATE PROCEDURE lease4_AUPD_lease4_stat(IN old_state TINYINT,
IN old_subnet_id INT UNSIGNED,
IN new_state TINYINT,
IN new_subnet_id INT UNSIGNED)
BEGIN
IF old_subnet_id != new_subnet_id OR old_state != new_state THEN
IF old_state = 0 OR old_state = 1 THEN
-- Decrement the old state count if record exists.
UPDATE lease4_stat
SET leases = IF(leases > 0, leases - 1, 0)
WHERE subnet_id = old_subnet_id AND state = old_state;
END IF;
IF new_state = 0 OR new_state = 1 THEN
-- Increment the new state count if record exists.
UPDATE lease4_stat SET leases = leases + 1
WHERE subnet_id = new_subnet_id AND state = new_state;
-- Insert new state record if it does not exist.
IF ROW_COUNT() <= 0 THEN
INSERT INTO lease4_stat VALUES (new_subnet_id, new_state, 1);
END IF;
END IF;
END IF;
END $$
DELIMITER ;
DROP PROCEDURE IF EXISTS lease4_ADEL_lease4_stat;
DELIMITER $$
CREATE PROCEDURE lease4_ADEL_lease4_stat(IN old_state TINYINT,
IN old_subnet_id INT UNSIGNED)
BEGIN
IF old_state = 0 OR old_state = 1 THEN
-- Decrement the state count if record exists.
UPDATE lease4_stat
SET leases = IF(leases > 0, leases - 1, 0)
WHERE subnet_id = old_subnet_id AND old_state = state;
END IF;
END $$
DELIMITER ;
DROP PROCEDURE IF EXISTS lease6_AINS_lease6_stat;
DELIMITER $$
CREATE PROCEDURE lease6_AINS_lease6_stat(IN new_state TINYINT,
IN new_subnet_id INT UNSIGNED,
IN new_lease_type TINYINT)
BEGIN
IF new_state = 0 OR new_state = 1 THEN
-- Update the state count if it exists.
UPDATE lease6_stat SET leases = leases + 1
WHERE subnet_id = new_subnet_id AND lease_type = new_lease_type
AND state = new_state;
-- Insert the state count record if it does not exist.
IF ROW_COUNT() <= 0 THEN
INSERT INTO lease6_stat VALUES (new_subnet_id, new_lease_type, new_state, 1);
END IF;
END IF;
END $$
DELIMITER ;
DROP PROCEDURE IF EXISTS lease6_AUPD_lease6_stat;
DELIMITER $$
CREATE PROCEDURE lease6_AUPD_lease6_stat(IN old_state TINYINT,
IN old_subnet_id INT UNSIGNED,
IN old_lease_type TINYINT,
IN new_state TINYINT,
IN new_subnet_id INT UNSIGNED,
IN new_lease_type TINYINT)
BEGIN
IF old_subnet_id != new_subnet_id OR
old_lease_type != new_lease_type OR
old_state != new_state THEN
IF old_state = 0 OR old_state = 1 THEN
-- Decrement the old state count if record exists.
UPDATE lease6_stat
SET leases = IF(leases > 0, leases - 1, 0)
WHERE subnet_id = old_subnet_id AND lease_type = old_lease_type
AND state = old_state;
END IF;
IF new_state = 0 OR new_state = 1 THEN
-- Increment the new state count if record exists
UPDATE lease6_stat SET leases = leases + 1
WHERE subnet_id = new_subnet_id AND lease_type = new_lease_type
AND state = new_state;
-- Insert new state record if it does not exist
IF ROW_COUNT() <= 0 THEN
INSERT INTO lease6_stat
VALUES (new_subnet_id, new_lease_type, new_state, 1);
END IF;
END IF;
END IF;
END $$
DELIMITER ;
DROP PROCEDURE IF EXISTS lease6_ADEL_lease6_stat;
DELIMITER $$
CREATE PROCEDURE lease6_ADEL_lease6_stat(IN old_state TINYINT,
IN old_subnet_id INT UNSIGNED,
IN old_lease_type TINYINT)
BEGIN
IF old_state = 0 OR old_state = 1 THEN
-- Decrement the state count if record exists
UPDATE lease6_stat
SET leases = IF(leases > 0, leases - 1, 0)
WHERE subnet_id = old_subnet_id AND lease_type = old_lease_type
AND state = old_state;
END IF;
END $$
DELIMITER ;
-- Create tables that contain the number of active leases. --
DROP TABLE IF EXISTS lease4_stat_by_client_class;
CREATE TABLE lease4_stat_by_client_class (
client_class VARCHAR(128) NOT NULL PRIMARY KEY,
leases BIGINT UNSIGNED NOT NULL
) ENGINE = InnoDB;
DROP TABLE IF EXISTS lease6_stat_by_client_class;
CREATE TABLE lease6_stat_by_client_class (
client_class VARCHAR(128) NOT NULL,
lease_type TINYINT NOT NULL,
leases BIGINT UNSIGNED NOT NULL,
PRIMARY KEY (client_class, lease_type),
CONSTRAINT fk_lease6_stat_by_client_class_lease_type FOREIGN KEY (lease_type)
REFERENCES lease6_types (lease_type)
) ENGINE = InnoDB;
-- Create procedures to be called for each row in after-event triggers for
-- INSERT, UPDATE and DELETE on lease tables.
DROP PROCEDURE IF EXISTS lease4_AINS_lease4_stat_by_client_class;
DELIMITER $$
CREATE PROCEDURE lease4_AINS_lease4_stat_by_client_class(IN new_state TINYINT,
IN new_user_context TEXT)
BEGIN
-- Declarations
DECLARE client_classes TEXT;
DECLARE class VARCHAR(255);
DECLARE length INT;
DECLARE i INT;
-- Ignore ERROR 3141 (22032) at line 1: Invalid JSON text in argument 1 to
-- function json_extract: "The document is empty." at position 0.
-- Ignore ERROR 4037 (HY000): Unexpected end of JSON text in argument 1 to function 'json_extract'
-- These situations are handled with a propagating NULL result from JSON_EXTRACT.
DECLARE CONTINUE HANDLER FOR 3141 BEGIN END;
DECLARE CONTINUE HANDLER FOR 4037 BEGIN END;
-- Only state 0 is needed for lease limiting.
IF new_state = 0 THEN
-- Dive into client classes.
SET client_classes = JSON_EXTRACT(new_user_context, '$."ISC"."client-classes"');
SET length = JSON_LENGTH(client_classes);
-- Iterate through all the client classes and increment the lease count for each.
SET i = 0;
label: WHILE i < length DO
SET class = JSON_UNQUOTE(JSON_EXTRACT(client_classes, CONCAT('\$[', i, ']')));
-- Upsert to increment the lease count.
UPDATE lease4_stat_by_client_class SET leases = leases + 1
WHERE client_class = class;
IF ROW_COUNT() = 0 THEN
INSERT INTO lease4_stat_by_client_class VALUES (class, 1);
END IF;
SET i = i + 1;
END WHILE label;
END IF;
END $$
DELIMITER ;
DROP PROCEDURE IF EXISTS lease4_AUPD_lease4_stat_by_client_class;
DELIMITER $$
CREATE PROCEDURE lease4_AUPD_lease4_stat_by_client_class(IN old_state TINYINT,
IN old_user_context TEXT,
IN new_state TINYINT,
IN new_user_context TEXT)
BEGIN
-- Declarations
DECLARE old_client_classes TEXT;
DECLARE new_client_classes TEXT;
DECLARE class VARCHAR(255);
DECLARE length INT;
DECLARE i INT;
SET old_client_classes = JSON_EXTRACT(old_user_context, '$."ISC"."client-classes"');
SET new_client_classes = JSON_EXTRACT(new_user_context, '$."ISC"."client-classes"');
IF old_state != new_state OR old_client_classes != new_client_classes THEN
-- Check if it's moving away from a counted state.
IF old_state = 0 THEN
-- Dive into client classes.
SET length = JSON_LENGTH(old_client_classes);
SET i = 0;
label: WHILE i < length DO
SET class = JSON_UNQUOTE(JSON_EXTRACT(old_client_classes, CONCAT('\$[', i, ']')));
-- Decrement the lease count if the record exists.
UPDATE lease4_stat_by_client_class SET leases = IF(leases > 0, leases - 1, 0)
WHERE client_class = class;
SET i = i + 1;
END WHILE label;
END IF;
-- Check if it's moving into a counted state.
IF new_state = 0 THEN
-- Dive into client classes.
SET length = JSON_LENGTH(new_client_classes);
SET i = 0;
label: WHILE i < length DO
SET class = JSON_UNQUOTE(JSON_EXTRACT(new_client_classes, CONCAT('\$[', i, ']')));
-- Upsert to increment the lease count.
UPDATE lease4_stat_by_client_class SET leases = leases + 1
WHERE client_class = class;
IF ROW_COUNT() <= 0 THEN
INSERT INTO lease4_stat_by_client_class VALUES (class, 1);
END IF;
SET i = i + 1;
END WHILE label;
END IF;
END IF;
END $$
DELIMITER ;
DROP PROCEDURE IF EXISTS lease4_ADEL_lease4_stat_by_client_class;
DELIMITER $$
CREATE PROCEDURE lease4_ADEL_lease4_stat_by_client_class(IN old_state TINYINT,
IN old_user_context TEXT)
BEGIN
-- Declarations
DECLARE client_classes TEXT;
DECLARE class VARCHAR(255);
DECLARE length INT;
DECLARE i INT;
-- Ignore ERROR 3141 (22032) at line 1: Invalid JSON text in argument 1 to
-- function json_extract: "The document is empty." at position 0.
-- Ignore ERROR 4037 (HY000): Unexpected end of JSON text in argument 1 to function 'json_extract'
-- These situations are handled with a propagating NULL result from JSON_EXTRACT.
DECLARE CONTINUE HANDLER FOR 3141 BEGIN END;
DECLARE CONTINUE HANDLER FOR 4037 BEGIN END;
-- Only state 0 is accounted for in lease limiting.
IF old_state = 0 THEN
-- Dive into client classes.
SET client_classes = JSON_EXTRACT(old_user_context, '$."ISC"."client-classes"');
SET length = JSON_LENGTH(client_classes);
SET i = 0;
label: WHILE i < length DO
SET class = JSON_UNQUOTE(JSON_EXTRACT(client_classes, CONCAT('\$[', i, ']')));
-- Decrement the lease count if the record exists.
UPDATE lease4_stat_by_client_class SET leases = IF(leases > 0, leases - 1, 0)
WHERE client_class = class;
SET i = i + 1;
END WHILE label;
END IF;
END $$
DELIMITER ;
DROP PROCEDURE IF EXISTS lease6_AINS_lease6_stat_by_client_class;
DELIMITER $$
CREATE PROCEDURE lease6_AINS_lease6_stat_by_client_class(IN new_state TINYINT,
IN new_user_context TEXT,
IN new_lease_type TINYINT)
BEGIN
-- Declarations
DECLARE client_classes TEXT;
DECLARE class VARCHAR(255);
DECLARE length INT;
DECLARE i INT;
-- Ignore ERROR 3141 (22032) at line 1: Invalid JSON text in argument 1 to
-- function json_extract: "The document is empty." at position 0.
-- Ignore ERROR 4037 (HY000): Unexpected end of JSON text in argument 1 to function 'json_extract'
-- These situations are handled with a propagating NULL result from JSON_EXTRACT.
DECLARE CONTINUE HANDLER FOR 3141 BEGIN END;
DECLARE CONTINUE HANDLER FOR 4037 BEGIN END;
-- Only state 0 is needed for lease limiting.
IF new_state = 0 THEN
-- Dive into client classes.
SET client_classes = JSON_EXTRACT(new_user_context, '$."ISC"."client-classes"');
SET length = JSON_LENGTH(client_classes);
SET i = 0;
label: WHILE i < length DO
SET class = JSON_UNQUOTE(JSON_EXTRACT(client_classes, CONCAT('\$[', i, ']')));
-- Upsert to increment the lease count.
UPDATE lease6_stat_by_client_class SET leases = leases + 1
WHERE client_class = class AND lease_type = new_lease_type;
IF ROW_COUNT() <= 0 THEN
INSERT INTO lease6_stat_by_client_class VALUES (class, new_lease_type, 1);
END IF;
SET i = i + 1;
END WHILE label;
END IF;
END $$
DELIMITER ;
DROP PROCEDURE IF EXISTS lease6_AUPD_lease6_stat_by_client_class;
DELIMITER $$
CREATE PROCEDURE lease6_AUPD_lease6_stat_by_client_class(IN old_state TINYINT,
IN old_user_context TEXT,
IN old_lease_type TINYINT,
IN new_state TINYINT,
IN new_user_context TEXT,
IN new_lease_type TINYINT)
BEGIN
-- Declarations
DECLARE old_client_classes TEXT;
DECLARE new_client_classes TEXT;
DECLARE class VARCHAR(255);
DECLARE length INT;
DECLARE i INT;
SET old_client_classes = JSON_EXTRACT(old_user_context, '$."ISC"."client-classes"');
SET new_client_classes = JSON_EXTRACT(new_user_context, '$."ISC"."client-classes"');
IF old_state != new_state OR old_client_classes != new_client_classes OR old_lease_type != new_lease_type THEN
-- Check if it's moving away from a counted state.
IF old_state = 0 THEN
-- Dive into client classes.
SET length = JSON_LENGTH(old_client_classes);
SET i = 0;
label: WHILE i < length DO
SET class = JSON_UNQUOTE(JSON_EXTRACT(old_client_classes, CONCAT('\$[', i, ']')));
-- Decrement the lease count if the record exists.
UPDATE lease6_stat_by_client_class SET leases = IF(leases > 0, leases - 1, 0)
WHERE client_class = class AND lease_type = old_lease_type;
SET i = i + 1;
END WHILE label;
END IF;
-- Check if it's moving into a counted state.
IF new_state = 0 THEN
-- Dive into client classes.
SET length = JSON_LENGTH(new_client_classes);
SET i = 0;
label: WHILE i < length DO
SET class = JSON_UNQUOTE(JSON_EXTRACT(new_client_classes, CONCAT('\$[', i, ']')));
-- Upsert to increment the lease count.
UPDATE lease6_stat_by_client_class SET leases = leases + 1
WHERE client_class = class AND lease_type = new_lease_type;
IF ROW_COUNT() <= 0 THEN
INSERT INTO lease6_stat_by_client_class VALUES (class, new_lease_type, 1);
END IF;
SET i = i + 1;
END WHILE label;
END IF;
END IF;
END $$
DELIMITER ;
DROP PROCEDURE IF EXISTS lease6_ADEL_lease6_stat_by_client_class;
DELIMITER $$
CREATE PROCEDURE lease6_ADEL_lease6_stat_by_client_class(IN old_state TINYINT,
IN old_user_context TEXT,
IN old_lease_type TINYINT)
BEGIN
-- Declarations
DECLARE client_classes TEXT;
DECLARE class VARCHAR(255);
DECLARE length INT;
DECLARE i INT;
-- Ignore ERROR 3141 (22032) at line 1: Invalid JSON text in argument 1 to
-- function json_extract: "The document is empty." at position 0.
-- Ignore ERROR 4037 (HY000): Unexpected end of JSON text in argument 1 to function 'json_extract'
-- These situations are handled with a propagating NULL result from JSON_EXTRACT.
DECLARE CONTINUE HANDLER FOR 3141 BEGIN END;
DECLARE CONTINUE HANDLER FOR 4037 BEGIN END;
-- Only state 0 is accounted for in lease limiting. But check both states to be consistent with lease6_stat.
IF old_state = 0 THEN
-- Dive into client classes.
SET client_classes = JSON_EXTRACT(old_user_context, '$."ISC"."client-classes"');
SET length = JSON_LENGTH(client_classes);
SET i = 0;
label: WHILE i < length DO
SET class = JSON_UNQUOTE(JSON_EXTRACT(client_classes, CONCAT('\$[', i, ']')));
-- Decrement the lease count if the record exists.
UPDATE lease6_stat_by_client_class SET leases = IF(leases > 0, leases - 1, 0)
WHERE client_class = class AND lease_type = old_lease_type;
SET i = i + 1;
END WHILE label;
END IF;
END $$
DELIMITER ;
-- Recreate the after-event triggers for INSERT, UPDATE and DELETE on lease tables to call the --
-- stored procedures above in pairs of two: for client classes and for subnets. --
-- Function that establishes whether JSON functions are supported.
-- They should be provided with MySQL>= 5.7, MariaDB >= 10.2.3.
DROP FUNCTION IF EXISTS isJsonSupported;
DELIMITER $$
CREATE FUNCTION isJsonSupported()
RETURNS BOOL
DETERMINISTIC
BEGIN
DECLARE dummy BOOL;
DECLARE CONTINUE HANDLER FOR SQLEXCEPTION
RETURN false;
SELECT JSON_EXTRACT('{ "foo-bar": 1 }', '$."foo-bar"') INTO dummy;
RETURN true;
END $$
DELIMITER ;
DROP TRIGGER IF EXISTS stat_lease4_insert;
DROP TRIGGER IF EXISTS lease4_AINS;
DELIMITER $$
CREATE TRIGGER lease4_AINS AFTER INSERT ON lease4 FOR EACH ROW
BEGIN
CALL lease4_AINS_lease4_stat(NEW.state, NEW.subnet_id);
IF @json_supported IS NULL THEN
SELECT isJsonSupported() INTO @json_supported;
END IF;
IF @json_supported = 1 THEN
CALL lease4_AINS_lease4_stat_by_client_class(NEW.state, NEW.user_context);
END IF;
END $$
DELIMITER ;
DROP TRIGGER IF EXISTS stat_lease4_update;
DROP TRIGGER IF EXISTS lease4_AUPD;
DELIMITER $$
CREATE TRIGGER lease4_AUPD AFTER UPDATE ON lease4 FOR EACH ROW
BEGIN
CALL lease4_AUPD_lease4_stat(OLD.state, OLD.subnet_id, NEW.state, NEW.subnet_id);
IF @json_supported IS NULL THEN
SELECT isJsonSupported() INTO @json_supported;
END IF;
IF @json_supported = 1 THEN
CALL lease4_AUPD_lease4_stat_by_client_class(OLD.state, OLD.user_context, NEW.state, NEW.user_context);
END IF;
END $$
DELIMITER ;
DROP TRIGGER IF EXISTS stat_lease4_delete;
DROP TRIGGER IF EXISTS lease4_ADEL;
DELIMITER $$
CREATE TRIGGER lease4_ADEL AFTER DELETE ON lease4 FOR EACH ROW
BEGIN
CALL lease4_ADEL_lease4_stat(OLD.state, OLD.subnet_id);
IF @json_supported IS NULL THEN
SELECT isJsonSupported() INTO @json_supported;
END IF;
IF @json_supported = 1 THEN
CALL lease4_ADEL_lease4_stat_by_client_class(OLD.state, OLD.user_context);
END IF;
END $$
DELIMITER ;
DROP TRIGGER IF EXISTS stat_lease6_insert;
DROP TRIGGER IF EXISTS lease6_AINS;
DELIMITER $$
CREATE TRIGGER lease6_AINS AFTER INSERT ON lease6 FOR EACH ROW
BEGIN
CALL lease6_AINS_lease6_stat(NEW.state, NEW.subnet_id, NEW.lease_type);
IF @json_supported IS NULL THEN
SELECT isJsonSupported() INTO @json_supported;
END IF;
IF @json_supported = 1 THEN
CALL lease6_AINS_lease6_stat_by_client_class(NEW.state, NEW.user_context, NEW.lease_type);
END IF;
END $$
DELIMITER ;
DROP TRIGGER IF EXISTS stat_lease6_update;
DROP TRIGGER IF EXISTS lease6_AUPD;
DELIMITER $$
CREATE TRIGGER lease6_AUPD AFTER UPDATE ON lease6 FOR EACH ROW
BEGIN
CALL lease6_AUPD_lease6_stat(OLD.state, OLD.subnet_id, OLD.lease_type, NEW.state, NEW.subnet_id, NEW.lease_type);
IF @json_supported IS NULL THEN
SELECT isJsonSupported() INTO @json_supported;
END IF;
IF @json_supported = 1 THEN
CALL lease6_AUPD_lease6_stat_by_client_class(OLD.state, OLD.user_context, OLD.lease_type, NEW.state, NEW.user_context, NEW.lease_type);
END IF;
END $$
DELIMITER ;
DROP TRIGGER IF EXISTS stat_lease6_delete;
DROP TRIGGER IF EXISTS lease6_ADEL;
DELIMITER $$
CREATE TRIGGER lease6_ADEL AFTER DELETE ON lease6 FOR EACH ROW
BEGIN
CALL lease6_ADEL_lease6_stat(OLD.state, OLD.subnet_id, OLD.lease_type);
IF @json_supported IS NULL THEN
SELECT isJsonSupported() INTO @json_supported;
END IF;
IF @json_supported = 1 THEN
CALL lease6_ADEL_lease6_stat_by_client_class(OLD.state, OLD.user_context, OLD.lease_type);
END IF;
END $$
DELIMITER ;
-- Create functions that check if the lease limits set in the given user context are exceeded.
-- They return a string describing a limit that is being exceeded, or an empty
-- string if no limits are exceeded. The following format for is assumed for user_context
-- (not all nodes are mandatory and values are given only as examples):
-- { "ISC": { "limits": { "client-classes": [ { "name": "foo", "address-limit": 2, "prefix-limit": 1 } ],
-- "subnet": { "id": 1, "address-limit": 2, "prefix-limit": 1 } } } }
DROP FUNCTION IF EXISTS checkLease4Limits;
DELIMITER $$
CREATE FUNCTION checkLease4Limits(user_context TEXT)
RETURNS TEXT
READS SQL DATA
BEGIN
-- Declarations
DECLARE json_element TEXT;
DECLARE length INT;
DECLARE class TEXT;
DECLARE name VARCHAR(255);
DECLARE i INT;
DECLARE lease_limit INT;
DECLARE lease_count INT;
-- Dive into client class limits.
SET json_element = JSON_EXTRACT(user_context, '$."ISC"."limits"."client-classes"');
SET length = JSON_LENGTH(json_element);
SET i = 0;
label: WHILE i < length DO
-- Get the lease limit for this client class.
SET class = JSON_EXTRACT(json_element, CONCAT('\$[', i, ']'));
SET name = JSON_UNQUOTE(JSON_EXTRACT(class, '$.name'));
SET lease_limit = JSON_EXTRACT(class, '$."address-limit"');
IF lease_limit IS NOT NULL THEN
-- Get the lease count for this client class.
SET lease_count = (SELECT leases FROM lease4_stat_by_client_class WHERE client_class = name);
IF lease_count IS NULL THEN
SET lease_count = 0;
END IF;
-- Compare. Return immediately if the limit is exceeded.
IF lease_limit <= lease_count THEN
RETURN CONCAT('address limit ', lease_limit, ' for client class "', name, '", current lease count ', lease_count);
END IF;
END IF;
SET i = i + 1;
END WHILE label;
-- Dive into subnet limits. Reuse i as subnet ID.
SET json_element = JSON_EXTRACT(user_context, '$.ISC.limits.subnet');
SET i = JSON_EXTRACT(json_element, '$.id');
SET lease_limit = JSON_EXTRACT(json_element, '$."address-limit"');
IF lease_limit IS NOT NULL THEN
-- Get the lease count for this client class.
SET lease_count = (SELECT leases FROM lease4_stat WHERE subnet_id = i AND state = 0);
IF lease_count IS NULL THEN
SET lease_count = 0;
END IF;
-- Compare. Return immediately if the limit is exceeded.
IF lease_limit <= lease_count THEN
RETURN CONCAT('address limit ', lease_limit, ' for subnet ID ', i, ', current lease count ', lease_count);
END IF;
END IF;
RETURN '';
END $$
DELIMITER ;
DROP FUNCTION IF EXISTS checkLease6Limits;
DELIMITER $$
CREATE FUNCTION checkLease6Limits(user_context TEXT)
RETURNS TEXT
READS SQL DATA
BEGIN
-- Declarations
DECLARE json_element TEXT;
DECLARE length INT;
DECLARE class TEXT;
DECLARE name VARCHAR(255);
DECLARE i INT;
DECLARE lease_limit INT;
DECLARE lease_count INT;
-- Dive into client class limits.
SET json_element = JSON_EXTRACT(user_context, '$."ISC"."limits"."client-classes"');
SET length = JSON_LENGTH(json_element);
SET i = 0;
label: WHILE i < length DO
-- Get the lease limit for this client class.
SET class = JSON_EXTRACT(json_element, CONCAT('\$[', i, ']'));
SET name = JSON_UNQUOTE(JSON_EXTRACT(class, '$.name'));
SET lease_limit = JSON_EXTRACT(class, '$."address-limit"');
IF lease_limit IS NOT NULL THEN
-- Get the address count for this client class.
SET lease_count = (SELECT leases FROM lease6_stat_by_client_class WHERE client_class = name AND lease_type = 0);
IF lease_count IS NULL THEN
SET lease_count = 0;
END IF;
-- Compare. Return immediately if the limit is exceeded.
IF lease_limit <= lease_count THEN
RETURN CONCAT('address limit ', lease_limit, ' for client class "', name, '", current lease count ', lease_count);
END IF;
END IF;
SET lease_limit = JSON_EXTRACT(class, '$."prefix-limit"');
IF lease_limit IS NOT NULL THEN
-- Get the prefix count for this client class.
SET lease_count = (SELECT leases FROM lease6_stat_by_client_class WHERE client_class = name AND lease_type = 2);
IF lease_count IS NULL THEN
SET lease_count = 0;
END IF;
-- Compare. Return immediately if the limit is exceeded.
IF lease_limit <= lease_count THEN
RETURN CONCAT('prefix limit ', lease_limit, ' for client class "', name, '", current lease count ', lease_count);
END IF;
END IF;
SET i = i + 1;
END WHILE label;
-- Dive into subnet limits. Reuse i as subnet ID.
SET json_element = JSON_EXTRACT(user_context, '$.ISC.limits.subnet');
SET i = JSON_EXTRACT(json_element, '$.id');
SET lease_limit = JSON_EXTRACT(json_element, '$."address-limit"');
IF lease_limit IS NOT NULL THEN
-- Get the lease count for this client class.
SET lease_count = (SELECT leases FROM lease6_stat WHERE subnet_id = i AND lease_type = 0 AND state = 0);
IF lease_count IS NULL THEN
SET lease_count = 0;
END IF;
-- Compare. Return immediately if the limit is exceeded.
IF lease_limit <= lease_count THEN
RETURN CONCAT('address limit ', lease_limit, ' for subnet ID ', i, ', current lease count ', lease_count);
END IF;
END IF;
SET lease_limit = JSON_EXTRACT(json_element, '$."prefix-limit"');
IF lease_limit IS NOT NULL THEN
-- Get the lease count for this client class.
SET lease_count = (SELECT leases FROM lease6_stat WHERE subnet_id = i AND lease_type = 2 AND state = 0);
IF lease_count IS NULL THEN
SET lease_count = 0;
END IF;
-- Compare. Return immediately if the limit is exceeded.
IF lease_limit <= lease_count THEN
RETURN CONCAT('prefix limit ', lease_limit, ' for subnet ID ', i, ', current lease count ', lease_count);
END IF;
END IF;
RETURN '';
END $$
DELIMITER ;
-- Update the schema version number.
UPDATE schema_version
SET version = '14', minor = '0';
-- This line concludes the schema upgrade to version 14.0.
EOF