From: Andrei Pavel Date: Thu, 13 Feb 2025 14:02:04 +0000 (+0200) Subject: [#3763] Add precautionary continue handlers to lease AUPD triggers X-Git-Tag: Kea-2.7.8~4 X-Git-Url: http://git.ipfire.org/?a=commitdiff_plain;h=60f8b468d6510004a5213a48e989e539528f01b4;p=thirdparty%2Fkea.git [#3763] Add precautionary continue handlers to lease AUPD triggers --- diff --git a/configure.ac b/configure.ac index 94fbd535f9..54f3bb36ee 100644 --- a/configure.ac +++ b/configure.ac @@ -1868,6 +1868,8 @@ AC_CONFIG_FILES([src/share/database/scripts/mysql/upgrade_027_to_028.sh], [chmod +x src/share/database/scripts/mysql/upgrade_027_to_028.sh]) AC_CONFIG_FILES([src/share/database/scripts/mysql/upgrade_028_to_029.sh], [chmod +x src/share/database/scripts/mysql/upgrade_028_to_029.sh]) +AC_CONFIG_FILES([src/share/database/scripts/mysql/upgrade_029_to_030.sh], + [chmod +x src/share/database/scripts/mysql/upgrade_029_to_030.sh]) AC_CONFIG_FILES([src/share/database/scripts/mysql/wipe_data.sh], [chmod +x src/share/database/scripts/mysql/wipe_data.sh]) AC_CONFIG_FILES([src/share/database/scripts/pgsql/Makefile]) diff --git a/src/bin/admin/tests/mysql_tests.sh.in b/src/bin/admin/tests/mysql_tests.sh.in index 3c6513da32..faaa11b7a1 100755 --- a/src/bin/admin/tests/mysql_tests.sh.in +++ b/src/bin/admin/tests/mysql_tests.sh.in @@ -157,7 +157,7 @@ mysql_db_version_test() { run_command \ "${kea_admin}" db-version mysql -u "${db_user}" -p "${db_password}" -n "${db_name}" version="${OUTPUT}" - assert_str_eq "29.0" "${version}" "Expected kea-admin to return %s, returned value was %s" + assert_str_eq "30.0" "${version}" "Expected kea-admin to return %s, returned value was %s" # Let's wipe the whole database mysql_wipe @@ -840,106 +840,106 @@ mysql_upgrade_23_to_24_test() { assert_eq 0 "${EXIT_CODE}" "${query}: expected %d, returned %d" assert_str_eq '18' "${OUTPUT}" "${query}: expected output %s, returned %s" - qry="select name from option_def_data_type where id = 0" + query="select name from option_def_data_type where id = 0" run_command \ - mysql_execute "${qry}" - assert_eq 0 "${EXIT_CODE}" "${qry}. (expected status code %d, returned %d)" + mysql_execute "${query}" + assert_eq 0 "${EXIT_CODE}" "${query}. (expected status code %d, returned %d)" assert_str_eq 'empty' "${OUTPUT}" "${query}: expected output %s, returned %s" - qry="select name from option_def_data_type where id = 1" + query="select name from option_def_data_type where id = 1" run_command \ - mysql_execute "${qry}" - assert_eq 0 "${EXIT_CODE}" "${qry}. (expected status code %d, returned %d)" + mysql_execute "${query}" + assert_eq 0 "${EXIT_CODE}" "${query}. (expected status code %d, returned %d)" assert_str_eq 'binary' "${OUTPUT}" "${query}: expected output %s, returned %s" - qry="select name from option_def_data_type where id = 2" + query="select name from option_def_data_type where id = 2" run_command \ - mysql_execute "${qry}" - assert_eq 0 "${EXIT_CODE}" "${qry}. (expected status code %d, returned %d)" + mysql_execute "${query}" + assert_eq 0 "${EXIT_CODE}" "${query}. (expected status code %d, returned %d)" assert_str_eq 'boolean' "${OUTPUT}" "${query}: expected output %s, returned %s" - qry="select name from option_def_data_type where id = 4" + query="select name from option_def_data_type where id = 4" run_command \ - mysql_execute "${qry}" - assert_eq 0 "${EXIT_CODE}" "${qry}. (expected status code %d, returned %d)" + mysql_execute "${query}" + assert_eq 0 "${EXIT_CODE}" "${query}. (expected status code %d, returned %d)" assert_str_eq 'int16' "${OUTPUT}" "${query}: expected output %s, returned %s" - qry="select name from option_def_data_type where id = 5" + query="select name from option_def_data_type where id = 5" run_command \ - mysql_execute "${qry}" - assert_eq 0 "${EXIT_CODE}" "${qry}. (expected status code %d, returned %d)" + mysql_execute "${query}" + assert_eq 0 "${EXIT_CODE}" "${query}. (expected status code %d, returned %d)" assert_str_eq 'int32' "${OUTPUT}" "${query}: expected output %s, returned %s" - qry="select name from option_def_data_type where id = 6" + query="select name from option_def_data_type where id = 6" run_command \ - mysql_execute "${qry}" - assert_eq 0 "${EXIT_CODE}" "${qry}. (expected status code %d, returned %d)" + mysql_execute "${query}" + assert_eq 0 "${EXIT_CODE}" "${query}. (expected status code %d, returned %d)" assert_str_eq 'uint8' "${OUTPUT}" "${query}: expected output %s, returned %s" - qry="select name from option_def_data_type where id = 7" + query="select name from option_def_data_type where id = 7" run_command \ - mysql_execute "${qry}" - assert_eq 0 "${EXIT_CODE}" "${qry}. (expected status code %d, returned %d)" + mysql_execute "${query}" + assert_eq 0 "${EXIT_CODE}" "${query}. (expected status code %d, returned %d)" assert_str_eq 'uint16' "${OUTPUT}" "${query}: expected output %s, returned %s" - qry="select name from option_def_data_type where id = 8" + query="select name from option_def_data_type where id = 8" run_command \ - mysql_execute "${qry}" - assert_eq 0 "${EXIT_CODE}" "${qry}. (expected status code %d, returned %d)" + mysql_execute "${query}" + assert_eq 0 "${EXIT_CODE}" "${query}. (expected status code %d, returned %d)" assert_str_eq 'uint32' "${OUTPUT}" "${query}: expected output %s, returned %s" - qry="select name from option_def_data_type where id = 10" + query="select name from option_def_data_type where id = 10" run_command \ - mysql_execute "${qry}" - assert_eq 0 "${EXIT_CODE}" "${qry}. (expected status code %d, returned %d)" + mysql_execute "${query}" + assert_eq 0 "${EXIT_CODE}" "${query}. (expected status code %d, returned %d)" assert_str_eq 'ipv4-address' "${OUTPUT}" "${query}: expected output %s, returned %s" - qry="select name from option_def_data_type where id = 11" + query="select name from option_def_data_type where id = 11" run_command \ - mysql_execute "${qry}" - assert_eq 0 "${EXIT_CODE}" "${qry}. (expected status code %d, returned %d)" + mysql_execute "${query}" + assert_eq 0 "${EXIT_CODE}" "${query}. (expected status code %d, returned %d)" assert_str_eq 'ipv6-address' "${OUTPUT}" "${query}: expected output %s, returned %s" - qry="select name from option_def_data_type where id = 12" + query="select name from option_def_data_type where id = 12" run_command \ - mysql_execute "${qry}" - assert_eq 0 "${EXIT_CODE}" "${qry}. (expected status code %d, returned %d)" + mysql_execute "${query}" + assert_eq 0 "${EXIT_CODE}" "${query}. (expected status code %d, returned %d)" assert_str_eq 'ipv6-prefix' "${OUTPUT}" "${query}: expected output %s, returned %s" - qry="select name from option_def_data_type where id = 13" + query="select name from option_def_data_type where id = 13" run_command \ - mysql_execute "${qry}" - assert_eq 0 "${EXIT_CODE}" "${qry}. (expected status code %d, returned %d)" + mysql_execute "${query}" + assert_eq 0 "${EXIT_CODE}" "${query}. (expected status code %d, returned %d)" assert_str_eq 'psid' "${OUTPUT}" "${query}: expected output %s, returned %s" - qry="select name from option_def_data_type where id = 14" + query="select name from option_def_data_type where id = 14" run_command \ - mysql_execute "${qry}" - assert_eq 0 "${EXIT_CODE}" "${qry}. (expected status code %d, returned %d)" + mysql_execute "${query}" + assert_eq 0 "${EXIT_CODE}" "${query}. (expected status code %d, returned %d)" assert_str_eq 'string' "${OUTPUT}" "${query}: expected output %s, returned %s" - qry="select name from option_def_data_type where id = 15" + query="select name from option_def_data_type where id = 15" run_command \ - mysql_execute "${qry}" - assert_eq 0 "${EXIT_CODE}" "${qry}. (expected status code %d, returned %d)" + mysql_execute "${query}" + assert_eq 0 "${EXIT_CODE}" "${query}. (expected status code %d, returned %d)" assert_str_eq 'tuple' "${OUTPUT}" "${query}: expected output %s, returned %s" - qry="select name from option_def_data_type where id = 16" + query="select name from option_def_data_type where id = 16" run_command \ - mysql_execute "${qry}" - assert_eq 0 "${EXIT_CODE}" "${qry}. (expected status code %d, returned %d)" + mysql_execute "${query}" + assert_eq 0 "${EXIT_CODE}" "${query}. (expected status code %d, returned %d)" assert_str_eq 'fqdn' "${OUTPUT}" "${query}: expected output %s, returned %s" - qry="select name from option_def_data_type where id = 17" + query="select name from option_def_data_type where id = 17" run_command \ - mysql_execute "${qry}" - assert_eq 0 "${EXIT_CODE}" "${qry}. (expected status code %d, returned %d)" + mysql_execute "${query}" + assert_eq 0 "${EXIT_CODE}" "${query}. (expected status code %d, returned %d)" assert_str_eq 'internal' "${OUTPUT}" "${query}: expected output %s, returned %s" - qry="select name from option_def_data_type where id = 254" + query="select name from option_def_data_type where id = 254" run_command \ - mysql_execute "${qry}" - assert_eq 0 "${EXIT_CODE}" "${qry}. (expected status code %d, returned %d)" + mysql_execute "${query}" + assert_eq 0 "${EXIT_CODE}" "${query}. (expected status code %d, returned %d)" assert_str_eq 'record' "${OUTPUT}" "${query}: expected output %s, returned %s" } @@ -1033,6 +1033,130 @@ mysql_upgrade_28_to_29_test() { assert_str_eq 'registered' "${OUTPUT}" "${qry}: expected output %s, returned %s" } +mysql_upgrade_29_to_30_test() { + # Test the amendment of the lease AUPD triggers used to populate stat_by_client_class tables. + # Blind test to a blind fix. The test probably passes prior to this schema change. + + # Clear leases. + query='DELETE FROM lease4; DELETE FROM lease6;' + run_command \ + mysql_execute "${query}" + assert_eq 0 "${EXIT_CODE}" "${query}: expected %d, returned %d" + assert_str_eq '' "${OUTPUT}" "${query}: expected output %s, returned %s" + + # Insert a null user context. + query="INSERT INTO lease4 VALUES(10,20,30,40,(SELECT FROM_UNIXTIME(1678900000)),50,1,1,'one,example,com',0,NULL,NULL,NULL,0)" + run_command \ + mysql_execute "${query}" + assert_eq 0 "${EXIT_CODE}" "${query}: expected %d, returned %d" + assert_str_eq '' "${OUTPUT}" "${query}: expected output %s, returned %s" + + # Check the user context. + query="SELECT user_context FROM lease4" + run_command \ + mysql_execute "${query}" + assert_eq 0 "${EXIT_CODE}" "${query}: expected %d, returned %d" + assert_str_eq 'NULL' "${OUTPUT}" "${query}: expected output %s, returned %s" + + # Update the user context explcitly to a valid JSON. + query="UPDATE lease4 SET user_context='{}'" + run_command \ + mysql_execute "${query}" + assert_eq 0 "${EXIT_CODE}" "${query}: expected %d, returned %d" + assert_str_eq '' "${OUTPUT}" "${query}: expected output %s, returned %s" + + # Check the user context. + query="SELECT user_context FROM lease4" + run_command \ + mysql_execute "${query}" + assert_eq 0 "${EXIT_CODE}" "${query}: expected %d, returned %d" + assert_str_eq '{}' "${OUTPUT}" "${query}: expected output %s, returned %s" + + # Update the expiry time. + query="UPDATE lease4 SET expire=FROM_UNIXTIME(1789000000)" + run_command \ + mysql_execute "${query}" + assert_eq 0 "${EXIT_CODE}" "${query}: expected %d, returned %d" + assert_str_eq '' "${OUTPUT}" "${query}: expected output %s, returned %s" + + # Check the user context. + query="SELECT user_context FROM lease4" + run_command \ + mysql_execute "${query}" + assert_eq 0 "${EXIT_CODE}" "${query}: expected %d, returned %d" + assert_str_eq '{}' "${OUTPUT}" "${query}: expected output %s, returned %s" + + # Update the user context explcitly to NULL. + query="UPDATE lease4 SET user_context=NULL" + run_command \ + mysql_execute "${query}" + assert_eq 0 "${EXIT_CODE}" "${query}: expected %d, returned %d" + assert_str_eq '' "${OUTPUT}" "${query}: expected output %s, returned %s" + + # Check the user context. + query="SELECT user_context FROM lease4" + run_command \ + mysql_execute "${query}" + assert_eq 0 "${EXIT_CODE}" "${query}: expected %d, returned %d" + assert_str_eq 'NULL' "${OUTPUT}" "${query}: expected output %s, returned %s" + + # Insert a null user context. + query="INSERT INTO lease6 VALUES(inet6_aton('::10'),20,30,(SELECT FROM_UNIXTIME(1678900000)),40,50,1,60,70,1,1,'one,example,com',80,90,16,0,NULL,0)" + run_command \ + mysql_execute "${query}" + assert_eq 0 "${EXIT_CODE}" 'INSERT INTO lease6 failed, expected exit code %d, actual %d' + assert_str_eq '' "${OUTPUT}" + + # Check the user context. + query="SELECT user_context FROM lease6" + run_command \ + mysql_execute "${query}" + assert_eq 0 "${EXIT_CODE}" "${query}: expected %d, returned %d" + assert_str_eq 'NULL' "${OUTPUT}" "${query}: expected output %s, returned %s" + + # Update the user context explcitly to a valid JSON. + query="UPDATE lease6 SET user_context='{}'" + run_command \ + mysql_execute "${query}" + assert_eq 0 "${EXIT_CODE}" "${query}: expected %d, returned %d" + assert_str_eq '' "${OUTPUT}" "${query}: expected output %s, returned %s" + + # Check the user context. + query="SELECT user_context FROM lease6" + run_command \ + mysql_execute "${query}" + assert_eq 0 "${EXIT_CODE}" "${query}: expected %d, returned %d" + assert_str_eq '{}' "${OUTPUT}" "${query}: expected output %s, returned %s" + + # Update the expiry time. + query="UPDATE lease6 SET expire=FROM_UNIXTIME(1789000000)" + run_command \ + mysql_execute "${query}" + assert_eq 0 "${EXIT_CODE}" "${query}: expected %d, returned %d" + assert_str_eq '' "${OUTPUT}" "${query}: expected output %s, returned %s" + + # Check the user context. + query="SELECT user_context FROM lease6" + run_command \ + mysql_execute "${query}" + assert_eq 0 "${EXIT_CODE}" "${query}: expected %d, returned %d" + assert_str_eq '{}' "${OUTPUT}" "${query}: expected output %s, returned %s" + + # Update the user context explcitly to NULL. + query="UPDATE lease6 SET user_context=NULL" + run_command \ + mysql_execute "${query}" + assert_eq 0 "${EXIT_CODE}" "${query}: expected %d, returned %d" + assert_str_eq '' "${OUTPUT}" "${query}: expected output %s, returned %s" + + # Check the user context. + query="SELECT user_context FROM lease6" + run_command \ + mysql_execute "${query}" + assert_eq 0 "${EXIT_CODE}" "${query}: expected %d, returned %d" + assert_str_eq 'NULL' "${OUTPUT}" "${query}: expected output %s, returned %s" +} + mysql_upgrade_test() { test_start "mysql.upgrade" @@ -1054,7 +1178,7 @@ mysql_upgrade_test() { # Verify that the upgraded schema reports the latest version. version=$("${kea_admin}" db-version mysql -u "${db_user}" -p "${db_password}" -n "${db_name}" -d "${db_scripts_dir}") - assert_str_eq "29.0" "${version}" "Expected kea-admin to return %s, returned value was %s" + assert_str_eq "30.0" "${version}" "Expected kea-admin to return %s, returned value was %s" # Let's check that the new tables are indeed there. @@ -1738,6 +1862,9 @@ SET @disable_audit = 0" # Check upgrade from 28.0 to 29.0. mysql_upgrade_28_to_29_test + # Check upgrade from 29.0 to 30.0. + mysql_upgrade_29_to_30_test + # Let's wipe the whole database mysql_wipe diff --git a/src/bin/admin/tests/pgsql_tests.sh.in b/src/bin/admin/tests/pgsql_tests.sh.in index f90638ec0b..c3b9a9a2ce 100755 --- a/src/bin/admin/tests/pgsql_tests.sh.in +++ b/src/bin/admin/tests/pgsql_tests.sh.in @@ -906,10 +906,10 @@ pgsql_upgrade_18_to_19_test() { pgsql_upgrade_19_to_20_test() { # Verify that lease6_by_subnet_id_address index on lease6 is keyed by # attributes number 5 and 1 (i.e. subnet-id and address) - qry="select ix.indkey as keys from pg_class t, pg_class i, pg_index ix \ + query="select ix.indkey as keys from pg_class t, pg_class i, pg_index ix \ where t.oid = ix.indrelid and i.oid = ix.indexrelid and \ i.relname = 'lease6_by_subnet_id_address' and t.relname = 'lease6';" - run_statement "verify lease6_by_subnet_id_address" "$qry" + run_statement "verify lease6_by_subnet_id_address" "${query}" assert_eq 0 "${EXIT_CODE}" "${query}: expected %d, returned %d" assert_str_eq '5 1' "${OUTPUT}" "${query}: expected output %s, returned %s" } @@ -917,10 +917,10 @@ pgsql_upgrade_19_to_20_test() { pgsql_upgrade_20_to_21_test() { # Verify that dhcp4_server_modification_ts index on dhcp4_server is keyed by # attribute number 4, modification_ts - qry="select ix.indkey as keys from pg_class t, pg_class i, pg_index ix \ + query="select ix.indkey as keys from pg_class t, pg_class i, pg_index ix \ where t.oid = ix.indrelid and i.oid = ix.indexrelid and \ i.relname = 'dhcp4_server_modification_ts' and t.relname = 'dhcp4_server';" - run_statement "verify lease6_by_subnet_id_address" "$qry" + run_statement "verify lease6_by_subnet_id_address" "${query}" assert_eq 0 "${EXIT_CODE}" "${query}: expected %d, returned %d" assert_str_eq '4' "${OUTPUT}" "${query}: expected output %s, returned %s" } @@ -940,106 +940,106 @@ pgsql_upgrade_23_to_24_test() { assert_eq 0 "${EXIT_CODE}" "${query}: expected %d, returned %d" assert_str_eq '18' "${OUTPUT}" "${query}: expected output %s, returned %s" - qry="select name from option_def_data_type where id = 0" + query="select name from option_def_data_type where id = 0" run_command \ - pgsql_execute "${qry}" - assert_eq 0 "${EXIT_CODE}" "${qry}. (expected status code %d, returned %d)" + pgsql_execute "${query}" + assert_eq 0 "${EXIT_CODE}" "${query}. (expected status code %d, returned %d)" assert_str_eq 'empty' "${OUTPUT}" "${query}: expected output %s, returned %s" - qry="select name from option_def_data_type where id = 1" + query="select name from option_def_data_type where id = 1" run_command \ - pgsql_execute "${qry}" - assert_eq 0 "${EXIT_CODE}" "${qry}. (expected status code %d, returned %d)" + pgsql_execute "${query}" + assert_eq 0 "${EXIT_CODE}" "${query}. (expected status code %d, returned %d)" assert_str_eq 'binary' "${OUTPUT}" "${query}: expected output %s, returned %s" - qry="select name from option_def_data_type where id = 2" + query="select name from option_def_data_type where id = 2" run_command \ - pgsql_execute "${qry}" - assert_eq 0 "${EXIT_CODE}" "${qry}. (expected status code %d, returned %d)" + pgsql_execute "${query}" + assert_eq 0 "${EXIT_CODE}" "${query}. (expected status code %d, returned %d)" assert_str_eq 'boolean' "${OUTPUT}" "${query}: expected output %s, returned %s" - qry="select name from option_def_data_type where id = 4" + query="select name from option_def_data_type where id = 4" run_command \ - pgsql_execute "${qry}" - assert_eq 0 "${EXIT_CODE}" "${qry}. (expected status code %d, returned %d)" + pgsql_execute "${query}" + assert_eq 0 "${EXIT_CODE}" "${query}. (expected status code %d, returned %d)" assert_str_eq 'int16' "${OUTPUT}" "${query}: expected output %s, returned %s" - qry="select name from option_def_data_type where id = 5" + query="select name from option_def_data_type where id = 5" run_command \ - pgsql_execute "${qry}" - assert_eq 0 "${EXIT_CODE}" "${qry}. (expected status code %d, returned %d)" + pgsql_execute "${query}" + assert_eq 0 "${EXIT_CODE}" "${query}. (expected status code %d, returned %d)" assert_str_eq 'int32' "${OUTPUT}" "${query}: expected output %s, returned %s" - qry="select name from option_def_data_type where id = 6" + query="select name from option_def_data_type where id = 6" run_command \ - pgsql_execute "${qry}" - assert_eq 0 "${EXIT_CODE}" "${qry}. (expected status code %d, returned %d)" + pgsql_execute "${query}" + assert_eq 0 "${EXIT_CODE}" "${query}. (expected status code %d, returned %d)" assert_str_eq 'uint8' "${OUTPUT}" "${query}: expected output %s, returned %s" - qry="select name from option_def_data_type where id = 7" + query="select name from option_def_data_type where id = 7" run_command \ - pgsql_execute "${qry}" - assert_eq 0 "${EXIT_CODE}" "${qry}. (expected status code %d, returned %d)" + pgsql_execute "${query}" + assert_eq 0 "${EXIT_CODE}" "${query}. (expected status code %d, returned %d)" assert_str_eq 'uint16' "${OUTPUT}" "${query}: expected output %s, returned %s" - qry="select name from option_def_data_type where id = 8" + query="select name from option_def_data_type where id = 8" run_command \ - pgsql_execute "${qry}" - assert_eq 0 "${EXIT_CODE}" "${qry}. (expected status code %d, returned %d)" + pgsql_execute "${query}" + assert_eq 0 "${EXIT_CODE}" "${query}. (expected status code %d, returned %d)" assert_str_eq 'uint32' "${OUTPUT}" "${query}: expected output %s, returned %s" - qry="select name from option_def_data_type where id = 10" + query="select name from option_def_data_type where id = 10" run_command \ - pgsql_execute "${qry}" - assert_eq 0 "${EXIT_CODE}" "${qry}. (expected status code %d, returned %d)" + pgsql_execute "${query}" + assert_eq 0 "${EXIT_CODE}" "${query}. (expected status code %d, returned %d)" assert_str_eq 'ipv4-address' "${OUTPUT}" "${query}: expected output %s, returned %s" - qry="select name from option_def_data_type where id = 11" + query="select name from option_def_data_type where id = 11" run_command \ - pgsql_execute "${qry}" - assert_eq 0 "${EXIT_CODE}" "${qry}. (expected status code %d, returned %d)" + pgsql_execute "${query}" + assert_eq 0 "${EXIT_CODE}" "${query}. (expected status code %d, returned %d)" assert_str_eq 'ipv6-address' "${OUTPUT}" "${query}: expected output %s, returned %s" - qry="select name from option_def_data_type where id = 12" + query="select name from option_def_data_type where id = 12" run_command \ - pgsql_execute "${qry}" - assert_eq 0 "${EXIT_CODE}" "${qry}. (expected status code %d, returned %d)" + pgsql_execute "${query}" + assert_eq 0 "${EXIT_CODE}" "${query}. (expected status code %d, returned %d)" assert_str_eq 'ipv6-prefix' "${OUTPUT}" "${query}: expected output %s, returned %s" - qry="select name from option_def_data_type where id = 13" + query="select name from option_def_data_type where id = 13" run_command \ - pgsql_execute "${qry}" - assert_eq 0 "${EXIT_CODE}" "${qry}. (expected status code %d, returned %d)" + pgsql_execute "${query}" + assert_eq 0 "${EXIT_CODE}" "${query}. (expected status code %d, returned %d)" assert_str_eq 'psid' "${OUTPUT}" "${query}: expected output %s, returned %s" - qry="select name from option_def_data_type where id = 14" + query="select name from option_def_data_type where id = 14" run_command \ - pgsql_execute "${qry}" - assert_eq 0 "${EXIT_CODE}" "${qry}. (expected status code %d, returned %d)" + pgsql_execute "${query}" + assert_eq 0 "${EXIT_CODE}" "${query}. (expected status code %d, returned %d)" assert_str_eq 'string' "${OUTPUT}" "${query}: expected output %s, returned %s" - qry="select name from option_def_data_type where id = 15" + query="select name from option_def_data_type where id = 15" run_command \ - pgsql_execute "${qry}" - assert_eq 0 "${EXIT_CODE}" "${qry}. (expected status code %d, returned %d)" + pgsql_execute "${query}" + assert_eq 0 "${EXIT_CODE}" "${query}. (expected status code %d, returned %d)" assert_str_eq 'tuple' "${OUTPUT}" "${query}: expected output %s, returned %s" - qry="select name from option_def_data_type where id = 16" + query="select name from option_def_data_type where id = 16" run_command \ - pgsql_execute "${qry}" - assert_eq 0 "${EXIT_CODE}" "${qry}. (expected status code %d, returned %d)" + pgsql_execute "${query}" + assert_eq 0 "${EXIT_CODE}" "${query}. (expected status code %d, returned %d)" assert_str_eq 'fqdn' "${OUTPUT}" "${query}: expected output %s, returned %s" - qry="select name from option_def_data_type where id = 17" + query="select name from option_def_data_type where id = 17" run_command \ - pgsql_execute "${qry}" - assert_eq 0 "${EXIT_CODE}" "${qry}. (expected status code %d, returned %d)" + pgsql_execute "${query}" + assert_eq 0 "${EXIT_CODE}" "${query}. (expected status code %d, returned %d)" assert_str_eq 'internal' "${OUTPUT}" "${query}: expected output %s, returned %s" - qry="select name from option_def_data_type where id = 254" + query="select name from option_def_data_type where id = 254" run_command \ - pgsql_execute "${qry}" - assert_eq 0 "${EXIT_CODE}" "${qry}. (expected status code %d, returned %d)" + pgsql_execute "${query}" + assert_eq 0 "${EXIT_CODE}" "${query}. (expected status code %d, returned %d)" assert_str_eq 'record' "${OUTPUT}" "${query}: expected output %s, returned %s" } diff --git a/src/lib/mysql/mysql_constants.h b/src/lib/mysql/mysql_constants.h index bb787bbec7..c741819be2 100644 --- a/src/lib/mysql/mysql_constants.h +++ b/src/lib/mysql/mysql_constants.h @@ -52,7 +52,7 @@ const int MLM_MYSQL_FETCH_FAILURE = 0; /// @name Current database schema version values. //@{ -const uint32_t MYSQL_SCHEMA_VERSION_MAJOR = 29; +const uint32_t MYSQL_SCHEMA_VERSION_MAJOR = 30; const uint32_t MYSQL_SCHEMA_VERSION_MINOR = 0; //@} diff --git a/src/share/database/scripts/mysql/.gitignore b/src/share/database/scripts/mysql/.gitignore index b74e05b3df..11f94eb07a 100644 --- a/src/share/database/scripts/mysql/.gitignore +++ b/src/share/database/scripts/mysql/.gitignore @@ -37,4 +37,5 @@ /upgrade_026_to_027.sh /upgrade_027_to_028.sh /upgrade_028_to_029.sh +/upgrade_029_to_030.sh /wipe_data.sh diff --git a/src/share/database/scripts/mysql/Makefile.am b/src/share/database/scripts/mysql/Makefile.am index 38cbe66c66..117d87b122 100644 --- a/src/share/database/scripts/mysql/Makefile.am +++ b/src/share/database/scripts/mysql/Makefile.am @@ -48,6 +48,7 @@ mysql_SCRIPTS += upgrade_025_to_026.sh mysql_SCRIPTS += upgrade_026_to_027.sh mysql_SCRIPTS += upgrade_027_to_028.sh mysql_SCRIPTS += upgrade_028_to_029.sh +mysql_SCRIPTS += upgrade_029_to_030.sh mysql_SCRIPTS += wipe_data.sh DISTCLEANFILES = ${mysql_SCRIPTS} diff --git a/src/share/database/scripts/mysql/dhcpdb_create.mysql b/src/share/database/scripts/mysql/dhcpdb_create.mysql index 0f001bc9b9..a38bb32bd6 100644 --- a/src/share/database/scripts/mysql/dhcpdb_create.mysql +++ b/src/share/database/scripts/mysql/dhcpdb_create.mysql @@ -6297,6 +6297,145 @@ UPDATE schema_version -- This line concludes the schema upgrade to version 29.0. +-- This line starts the schema upgrade to version 30.0. + +-- Add continue handlers to the lease*_AUPD_lease*_stat_by_client_class. +-- The same continue handlers existed in the AINS and ADEL triggers. + +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; + + -- 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; + + 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 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; + + -- 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; + + 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 ; + +-- Update the schema version number. +UPDATE schema_version + SET version = '30', minor = '0'; + +-- This line concludes the schema upgrade to version 30.0. + # Notes: # # Indexes diff --git a/src/share/database/scripts/mysql/meson.build b/src/share/database/scripts/mysql/meson.build index d8cc25d57d..a4298f284b 100644 --- a/src/share/database/scripts/mysql/meson.build +++ b/src/share/database/scripts/mysql/meson.build @@ -66,6 +66,7 @@ upgrade_scripts = [ 'upgrade_026_to_027.sh', 'upgrade_027_to_028.sh', 'upgrade_028_to_029.sh', + 'upgrade_029_to_030.sh', ] list = run_command( GRABBER, diff --git a/src/share/database/scripts/mysql/upgrade_029_to_030.sh.in b/src/share/database/scripts/mysql/upgrade_029_to_030.sh.in new file mode 100755 index 0000000000..e5675cdb18 --- /dev/null +++ b/src/share/database/scripts/mysql/upgrade_029_to_030.sh.in @@ -0,0 +1,196 @@ +#!/bin/sh + +# Copyright (C) 2025 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="@prefix@" + +# 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}" = "@abs_top_builddir@/src/share/database/scripts/mysql"; then + # shellcheck source=./src/bin/admin/admin-utils.sh.in + . "@abs_top_builddir@/src/bin/admin/admin-utils.sh" +else + # shellcheck source=./src/bin/admin/admin-utils.sh.in + . "@datarootdir@/@PACKAGE_NAME@/scripts/admin-utils.sh" +fi + +# Check version. +version=$(mysql_version "${@}") +if test "${version}" != "29.0"; then + printf 'This script upgrades 29.0 to 30.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 "$@" < 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 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; + + -- 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; + + 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 ; + +-- Update the schema version number. +UPDATE schema_version + SET version = '30', minor = '0'; + +-- This line concludes the schema upgrade to version 30.0. + +EOF