From: Thomas Markwalder Date: Thu, 17 Feb 2022 21:05:25 +0000 (-0500) Subject: [#95] Fix time handling and make installable X-Git-Tag: Kea-2.1.3~5 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=c164541e3ac7deba104b3c1926c22a0bb0857268;p=thirdparty%2Fkea.git [#95] Fix time handling and make installable src/hooks/dhcp/pgsql_cb/pgsql_query_macros_dhcp.h Use gmt_epoch() to fetch timestamps src/lib/pgsql/pgsql_exchange.* PsqlBindArray::addTimestamp() PsqlBindArray::addTimestamp() - use convertLocaltoDatabaseTime() PgSqlExchange::convertLocalToDatabaseTime() - new function for converting local times src/lib/pgsql/tests/pgsql_basics.* Add LOCALTIME_COL column src/lib/pgsql/tests/pgsql_exchange_unittest.cc Update unit tests src/share/database/scripts/pgsql/dhcpdb_create.pgsql src/share/database/scripts/pgsql/upgrade_008_to_009.sh.in src/share/database/scripts/pgsql/dhcpdb_drop.pgsql Add gmt_epoch() function src/share/database/scripts/pgsql/wipe_data.sh.in Fix order of tables --- diff --git a/src/hooks/dhcp/pgsql_cb/pgsql_query_macros_dhcp.h b/src/hooks/dhcp/pgsql_cb/pgsql_query_macros_dhcp.h index b28b9f52cd..5222dcb6b3 100644 --- a/src/hooks/dhcp/pgsql_cb/pgsql_query_macros_dhcp.h +++ b/src/hooks/dhcp/pgsql_cb/pgsql_query_macros_dhcp.h @@ -32,7 +32,7 @@ namespace { " g.name," \ " g.value," \ " g.parameter_type," \ - " extract(epoch from g.modification_ts)::bigint as modification_ts, " \ + " gmt_epoch(g.modification_ts) as modification_ts, " \ " s.tag " \ "FROM " #table_prefix "_global_parameter AS g " \ "INNER JOIN " #table_prefix "_global_parameter_server AS a " \ @@ -56,7 +56,7 @@ namespace { " s.client_class," \ " s.interface," \ " s.match_client_id," \ - " extract(epoch from s.modification_ts)::bigint as modification_ts, " \ + " gmt_epoch(s.modification_ts) as modification_ts, " \ " s.next_server," \ " s.rebind_timer," \ " s.relay," \ @@ -71,7 +71,7 @@ namespace { " p.start_address," \ " p.end_address," \ " p.subnet_id," \ - " extract(epoch from p.modification_ts)::bigint as modification_ts, " \ + " gmt_epoch(p.modification_ts) as modification_ts, " \ " x.option_id," \ " x.code," \ " x.value," \ @@ -83,7 +83,7 @@ namespace { " x.user_context," \ " x.shared_network_name," \ " x.pool_id," \ - " extract(epoch from x.modification_ts)::bigint as modification_ts, " \ + " gmt_epoch(x.modification_ts) as modification_ts, " \ " o.option_id," \ " o.code," \ " o.value," \ @@ -95,7 +95,7 @@ namespace { " o.user_context," \ " o.shared_network_name," \ " o.pool_id," \ - " extract(epoch from o.modification_ts)::bigint as modification_ts, " \ + " gmt_epoch(o.modification_ts) as modification_ts, " \ " s.calculate_tee_times," \ " s.t1_percent," \ " s.t2_percent," \ @@ -157,7 +157,7 @@ namespace { " s.subnet_prefix," \ " s.client_class," \ " s.interface," \ - " extract(epoch from s.modification_ts)::bigint as modification_ts, " \ + " gmt_epoch(s.modification_ts) as modification_ts, " \ " s.preferred_lifetime," \ " s.rapid_commit," \ " s.rebind_timer," \ @@ -172,13 +172,13 @@ namespace { " p.start_address," \ " p.end_address," \ " p.subnet_id," \ - " extract(epoch from p.modification_ts)::bigint as modification_ts, " \ + " gmt_epoch(p.modification_ts) as modification_ts, " \ " d.id," \ " d.prefix," \ " d.prefix_length," \ " d.delegated_prefix_length," \ " d.subnet_id," \ - " extract(epoch from d.modification_ts)::bigint as modification_ts, " \ + " gmt_epoch(d.modification_ts) as modification_ts, " \ " x.option_id," \ " x.code," \ " x.value," \ @@ -190,7 +190,7 @@ namespace { " x.user_context," \ " x.shared_network_name," \ " x.pool_id," \ - " extract(epoch from x.modification_ts)::bigint as modification_ts, " \ + " gmt_epoch(x.modification_ts) as modification_ts, " \ " x.pd_pool_id," \ " y.option_id," \ " y.code," \ @@ -203,7 +203,7 @@ namespace { " y.user_context," \ " y.shared_network_name," \ " y.pool_id," \ - " extract(epoch from y.modification_ts)::bigint as modification_ts, " \ + " gmt_epoch(y.modification_ts) as modification_ts, " \ " y.pd_pool_id," \ " o.option_id," \ " o.code," \ @@ -216,7 +216,7 @@ namespace { " o.user_context," \ " o.shared_network_name," \ " o.pool_id," \ - " extract(epoch from o.modification_ts)::bigint as modification_ts, " \ + " gmt_epoch(o.modification_ts) as modification_ts, " \ " o.pd_pool_id, " \ " s.calculate_tee_times," \ " s.t1_percent," \ @@ -291,7 +291,7 @@ namespace { " p.client_class," \ " p.require_client_classes," \ " p.user_context," \ - " extract(epoch from p.modification_ts)::bigint as modification_ts, " \ + " gmt_epoch(p.modification_ts) as modification_ts, " \ " x.option_id," \ " x.code," \ " x.value," \ @@ -303,7 +303,7 @@ namespace { " x.user_context," \ " x.shared_network_name," \ " x.pool_id," \ - " extract(epoch from x.modification_ts)::bigint as modification_ts " \ + " gmt_epoch(x.modification_ts) as modification_ts " \ "FROM dhcp4_pool AS p " \ server_join \ "LEFT JOIN dhcp4_options AS x ON x.scope_id = 5 AND p.id = x.pool_id " \ @@ -331,7 +331,7 @@ namespace { " p.client_class," \ " p.require_client_classes," \ " p.user_context," \ - " extract(epoch from p.modification_ts)::bigint as modification_ts, " \ + " gmt_epoch(p.modification_ts) as modification_ts, " \ " x.option_id," \ " x.code," \ " x.value," \ @@ -343,7 +343,7 @@ namespace { " x.user_context," \ " x.shared_network_name," \ " x.pool_id," \ - " extract(epoch from x.modification_ts)::bigint as modification_ts, " \ + " gmt_epoch(x.modification_ts) as modification_ts, " \ " x.pd_pool_id " \ "FROM dhcp6_pool AS p " \ server_join \ @@ -375,7 +375,7 @@ namespace { " p.client_class," \ " p.require_client_classes," \ " p.user_context," \ - " extract(epoch from p.modification_ts)::bigint as modification_ts, " \ + " gmt_epoch(p.modification_ts) as modification_ts, " \ " x.option_id," \ " x.code," \ " x.value," \ @@ -387,7 +387,7 @@ namespace { " x.user_context," \ " x.shared_network_name," \ " x.pool_id," \ - " extract(epoch from x.modification_ts)::bigint as modification_ts, " \ + " gmt_epoch(x.modification_ts) as modification_ts, " \ " x.pd_pool_id " \ "FROM dhcp6_pd_pool AS p " \ server_join \ @@ -414,7 +414,7 @@ namespace { " n.client_class," \ " n.interface," \ " n.match_client_id," \ - " extract(epoch from n.modification_ts)::bigint as modification_ts, " \ + " gmt_epoch(n.modification_ts) as modification_ts, " \ " n.rebind_timer," \ " n.relay," \ " n.renew_timer," \ @@ -433,7 +433,7 @@ namespace { " o.user_context," \ " o.shared_network_name," \ " o.pool_id," \ - " extract(epoch from o.modification_ts)::bigint as modification_ts, " \ + " gmt_epoch(o.modification_ts) as modification_ts, " \ " n.calculate_tee_times," \ " n.t1_percent," \ " n.t2_percent," \ @@ -493,7 +493,7 @@ namespace { " n.name," \ " n.client_class," \ " n.interface," \ - " extract(epoch from n.modification_ts)::bigint as modification_ts, " \ + " gmt_epoch(n.modification_ts) as modification_ts, " \ " n.preferred_lifetime," \ " n.rapid_commit," \ " n.rebind_timer," \ @@ -514,7 +514,7 @@ namespace { " o.user_context," \ " o.shared_network_name," \ " o.pool_id," \ - " extract(epoch from o.modification_ts)::bigint as modification_ts, " \ + " gmt_epoch(o.modification_ts) as modification_ts, " \ " o.pd_pool_id, " \ " n.calculate_tee_times," \ " n.t1_percent," \ @@ -575,7 +575,7 @@ namespace { " d.name," \ " d.space," \ " d.type," \ - " extract(epoch from d.modification_ts)::bigint as modification_ts, " \ + " gmt_epoch(d.modification_ts) as modification_ts, " \ " d.is_array," \ " d.encapsulate," \ " d.record_types," \ @@ -604,7 +604,7 @@ namespace { " o.user_context," \ " o.shared_network_name," \ " o.pool_id," \ - " extract(epoch from o.modification_ts)::bigint as modification_ts, " \ + " gmt_epoch(o.modification_ts) as modification_ts, " \ " s.tag " \ pd_pool_id \ "FROM " #table_prefix "_options AS o " \ @@ -628,7 +628,7 @@ namespace { " a.object_type," \ " a.object_id," \ " a.modification_type," \ - " extract(epoch from r.modification_ts)::bigint as modification_ts, " \ + " gmt_epoch(r.modification_ts) as modification_ts, " \ " r.id, " \ " r.log_message " \ "FROM " #table_prefix "_audit AS a " \ @@ -646,7 +646,7 @@ namespace { " s.id," \ " s.tag," \ " s.description," \ - " extract(epoch from s.modification_ts)::bigint as modification_ts " \ + " gmt_epoch(s.modification_ts) as modification_ts " \ "FROM " #table_prefix "_server AS s " \ "WHERE s.id > 1 " \ __VA_ARGS__ \ @@ -672,13 +672,13 @@ namespace { " c.max_valid_lifetime," \ " c.depend_on_known_directly," \ " o.depend_on_known_indirectly, " \ - " extract(epoch from c.modification_ts)::bigint as modification_ts, " \ + " gmt_epoch(c.modification_ts) as modification_ts, " \ " d.id," \ " d.code," \ " d.name," \ " d.space," \ " d.type," \ - " extract(epoch from d.modification_ts)::bigint as modification_ts, " \ + " gmt_epoch(d.modification_ts) as modification_ts, " \ " d.is_array," \ " d.encapsulate," \ " d.record_types," \ @@ -694,7 +694,7 @@ namespace { " x.user_context," \ " x.shared_network_name," \ " x.pool_id," \ - " extract(epoch from x.modification_ts)::bigint as modification_ts, " \ + " gmt_epoch(x.modification_ts) as modification_ts, " \ " s.tag " \ "FROM dhcp4_client_class AS c " \ "INNER JOIN dhcp4_client_class_order AS o " \ @@ -735,13 +735,13 @@ namespace { " c.max_valid_lifetime," \ " c.depend_on_known_directly," \ " o.depend_on_known_indirectly, " \ - " extract(epoch from c.modification_ts)::bigint as modification_ts, " \ + " gmt_epoch(c.modification_ts) as modification_ts, " \ " d.id," \ " d.code," \ " d.name," \ " d.space," \ " d.type," \ - " extract(epoch from d.modification_ts)::bigint as modification_ts, " \ + " gmt_epoch(d.modification_ts) as modification_ts, " \ " d.is_array," \ " d.encapsulate," \ " d.record_types," \ @@ -757,7 +757,7 @@ namespace { " x.user_context," \ " x.shared_network_name," \ " x.pool_id," \ - " extract(epoch from x.modification_ts)::bigint as modification_ts, " \ + " gmt_epoch(x.modification_ts) as modification_ts, " \ " s.tag, " \ " c.preferred_lifetime," \ " c.min_preferred_lifetime, " \ diff --git a/src/lib/pgsql/pgsql_exchange.cc b/src/lib/pgsql/pgsql_exchange.cc index 3451b3a070..a646c46fb1 100644 --- a/src/lib/pgsql/pgsql_exchange.cc +++ b/src/lib/pgsql/pgsql_exchange.cc @@ -247,14 +247,14 @@ PsqlBindArray::addTimestamp(const boost::posix_time::ptime& timestamp) { } // Converts to timestamp to local date/time string. - addTempString(PgSqlExchange::convertToDatabaseTime(input_time)); + addTempString(PgSqlExchange::convertLocalToDatabaseTime(input_time)); } void PsqlBindArray::addTimestamp() { time_t now; time(&now); - addTempString(PgSqlExchange::convertToDatabaseTime(now)); + addTempString(PgSqlExchange::convertLocalToDatabaseTime(now)); } void @@ -331,13 +331,30 @@ std::string PgSqlExchange::convertToDatabaseTime(const time_t input_time) { struct tm tinfo; char buffer[20]; + localtime_r(&input_time, &tinfo); + + // PostgreSQL will assume the value is already in local time since we + // do not specify timezone in the string. + strftime(buffer, sizeof(buffer), "%Y-%m-%d %H:%M:%S", &tinfo); + return (std::string(buffer)); +} + +std::string +PgSqlExchange::convertLocalToDatabaseTime(const time_t input_time) { + struct tm tinfo; + char buffer[20]; + + // We use gmtime_r to avoid adjustment as time_t is already local. + gmtime_r(&input_time, &tinfo); + // PostgreSQL will assume the value is already in local time since we // do not specify timezone in the string. strftime(buffer, sizeof(buffer), "%Y-%m-%d %H:%M:%S", &tinfo); return (std::string(buffer)); } + std::string PgSqlExchange::convertToDatabaseTime(const time_t cltt, const uint32_t valid_lifetime) { diff --git a/src/lib/pgsql/pgsql_exchange.h b/src/lib/pgsql/pgsql_exchange.h index 4221463a78..48dfaf9371 100644 --- a/src/lib/pgsql/pgsql_exchange.h +++ b/src/lib/pgsql/pgsql_exchange.h @@ -522,12 +522,18 @@ public: /// @brief Destructor virtual ~PgSqlExchange() {} - /// @brief Converts time_t value to a text representation in local time. + /// @brief Converts UTC time_t value to a text representation in local time. /// /// @param input_time A time_t value representing time. /// @return std::string containing stringified time. static std::string convertToDatabaseTime(const time_t input_time); + /// @brief Converts local time_t value to a text representation in local time. + /// + /// @param input_time A time_t value representing time. + /// @return std::string containing stringified time. + static std::string convertLocalToDatabaseTime(const time_t input_time); + /// @brief Converts lease expiration time to a text representation in /// local time. /// diff --git a/src/lib/pgsql/tests/pgsql_basics.cc b/src/lib/pgsql/tests/pgsql_basics.cc index c12326945b..e6d061a336 100644 --- a/src/lib/pgsql/tests/pgsql_basics.cc +++ b/src/lib/pgsql/tests/pgsql_basics.cc @@ -48,6 +48,7 @@ PgSqlBasicsTest::PgSqlBasicsTest() : expected_col_names_(NUM_BASIC_COLS) { expected_col_names_[MIN_INT_COL] = "min_int_col"; expected_col_names_[MAX_INT_COL] = "max_int_col"; expected_col_names_[INET6_COL] = "inet6_col"; + expected_col_names_[LOCALTIME_COL] = "localtime_col"; destroySchema(); createSchema(); @@ -86,7 +87,8 @@ PgSqlBasicsTest::createSchema() { " json_col JSON," " min_int_col INT, " " max_int_col INT, " - " inet6_col INET " + " inet6_col INET, " + " localtime_col TIMESTAMP WITH TIME ZONE " "); "; PgSqlResult r(PQexec(*conn_, sql)); @@ -136,7 +138,8 @@ PgSqlBasicsTest::fetchRows(PgSqlResultPtr& r, int exp_rows, int line) { " int_col, text_col," " extract(epoch from timestamp_col)::bigint as timestamp_col," " varchar_col, inet4_col, float_col, json_col," - " min_int_col, max_int_col, inet6_col" + " min_int_col, max_int_col, inet6_col," + " (extract(epoch from localtime_col) + extract(timezone from localtime_col))::bigint as localtime_col" " FROM basics"; runSql(r, sql, PGRES_TUPLES_OK, line); diff --git a/src/lib/pgsql/tests/pgsql_basics.h b/src/lib/pgsql/tests/pgsql_basics.h index 3165208e6e..b46f55d44b 100644 --- a/src/lib/pgsql/tests/pgsql_basics.h +++ b/src/lib/pgsql/tests/pgsql_basics.h @@ -49,7 +49,7 @@ public: SMALLINT_COL, INT_COL, TEXT_COL, - TIMESTAMP_COL, + TIMESTAMP_COL, // Used when epoch coming back is GMT (e.g. lease mgr) VARCHAR_COL, INET4_COL, FLOAT_COL, @@ -57,6 +57,7 @@ public: MIN_INT_COL, MAX_INT_COL, INET6_COL, + LOCALTIME_COL, // Used when epoch coming back is LOCAL (e.g. CB) NUM_BASIC_COLS }; diff --git a/src/lib/pgsql/tests/pgsql_exchange_unittest.cc b/src/lib/pgsql/tests/pgsql_exchange_unittest.cc index 54f5d180c9..724c68f852 100644 --- a/src/lib/pgsql/tests/pgsql_exchange_unittest.cc +++ b/src/lib/pgsql/tests/pgsql_exchange_unittest.cc @@ -969,7 +969,7 @@ TEST_F(PgSqlBasicsTest, ptimeTimestamp) { // Create a prepared statement for inserting a TIMESTAMP PgSqlTaggedStatement statement[] = { { 1, { OID_TIMESTAMP }, "timestamp_insert", - "INSERT INTO BASICS (timestamp_col) values ($1)" } + "INSERT INTO BASICS (localtime_col) values ($1)" } }; ASSERT_NO_THROW(conn_->prepareStatement(statement[0])); @@ -986,7 +986,6 @@ TEST_F(PgSqlBasicsTest, ptimeTimestamp) { // Now add reasonable day, US National Ice Cream day. ptime nice_day(date(2021, Jul, 18), duration); bind_array->addTimestamp(nice_day); - std::cout << "bind array: " << bind_array->toText() << std::endl; PgSqlResultPtr r; RUN_PREP(r, statement[0], bind_array, PGRES_COMMAND_OK); @@ -995,11 +994,11 @@ TEST_F(PgSqlBasicsTest, ptimeTimestamp) { FETCH_ROWS(r, 1); // Timestamp column should not be null. - ASSERT_FALSE(PgSqlExchange::isColumnNull(*r, 0, TIMESTAMP_COL)); + ASSERT_FALSE(PgSqlExchange::isColumnNull(*r, 0, LOCALTIME_COL)); // Convert fetched value into a ptime. ptime fetched_time; - ASSERT_NO_THROW_LOG(PgSqlExchange::getColumnValue(*r, 0, TIMESTAMP_COL, + ASSERT_NO_THROW_LOG(PgSqlExchange::getColumnValue(*r, 0, LOCALTIME_COL, fetched_time)); ASSERT_EQ(fetched_time, nice_day); @@ -1430,7 +1429,7 @@ TEST_F(PgSqlBasicsTest, resultRowWorker) { " smallint_col, " " int_col, " " text_col, " - " timestamp_col, " + " localtime_col, " " varchar_col, " " inet4_col, " " float_col, " @@ -1514,7 +1513,7 @@ TEST_F(PgSqlBasicsTest, resultRowWorker) { EXPECT_EQ(exp_smallint, worker->getSmallInt(SMALLINT_COL)); EXPECT_EQ(exp_int, worker->getInt(INT_COL)); EXPECT_EQ(exp_text, worker->getString(TEXT_COL)); - EXPECT_EQ(exp_timestamp, worker->getTimestamp(TIMESTAMP_COL)); + EXPECT_EQ(exp_timestamp, worker->getTimestamp(LOCALTIME_COL)); EXPECT_EQ(exp_varchar, worker->getString(VARCHAR_COL)); EXPECT_EQ(exp_inet4, worker->getInet4(INET4_COL)); EXPECT_EQ(exp_double, worker->getDouble(FLOAT_COL)); diff --git a/src/share/database/scripts/pgsql/dhcpdb_create.pgsql b/src/share/database/scripts/pgsql/dhcpdb_create.pgsql index c8d18f680c..ecf417d587 100644 --- a/src/share/database/scripts/pgsql/dhcpdb_create.pgsql +++ b/src/share/database/scripts/pgsql/dhcpdb_create.pgsql @@ -4492,6 +4492,24 @@ BEGIN RETURN; END;$$; +-- Returns the epoch GMT time in second from a timestamp with time zone +-- +-- param input_ts timestamp value to convert +-- return a BIGINT containing the number of seconds since the epoch in GMT. +CREATE OR REPLACE FUNCTION gmt_epoch(input_ts TIMESTAMP WITH TIME ZONE) +RETURNS BIGINT +AS $$ +DECLARE + gmt_epoch BIGINT; +BEGIN + select extract(epoch from input_ts) + extract(timezone from input_ts) into gmt_epoch; + RETURN gmt_epoch; + EXCEPTION + WHEN OTHERS THEN + RAISE EXCEPTION 'gmt_epoch(%) : failed, sqlstate: %', input_ts, sqlstate; +END;$$ +LANGUAGE plpgsql; + -- Update the schema version number. UPDATE schema_version SET version = '9', minor = '0'; diff --git a/src/share/database/scripts/pgsql/dhcpdb_drop.pgsql b/src/share/database/scripts/pgsql/dhcpdb_drop.pgsql index 843166b1a8..c4247437c2 100644 --- a/src/share/database/scripts/pgsql/dhcpdb_drop.pgsql +++ b/src/share/database/scripts/pgsql/dhcpdb_drop.pgsql @@ -175,3 +175,5 @@ DROP FUNCTION IF EXISTS set_session_value(name text, value BOOLEAN); DROP FUNCTION IF EXISTS lease4Upload(); DROP FUNCTION IF EXISTS lease6Upload(); + +DROP FUNCTION IF EXISTS gmt_epoch(input_time TIMESTAMP WITH TIME ZONE); diff --git a/src/share/database/scripts/pgsql/upgrade_008_to_009.sh.in b/src/share/database/scripts/pgsql/upgrade_008_to_009.sh.in index 04cc8d4414..656f664d5d 100644 --- a/src/share/database/scripts/pgsql/upgrade_008_to_009.sh.in +++ b/src/share/database/scripts/pgsql/upgrade_008_to_009.sh.in @@ -264,6 +264,24 @@ BEGIN RETURN; END;\$\$; +-- Returns the epoch GMT time in second from a timestamp with time zone +-- +-- param input_ts timestamp value to convert +-- return a BIGINT containing the number of seconds since the epoch in GMT. +CREATE OR REPLACE FUNCTION gmt_epoch(input_ts TIMESTAMP WITH TIME ZONE) +RETURNS BIGINT +AS \$\$ +DECLARE + gmt_epoch BIGINT; +BEGIN + select extract(epoch from input_ts) + extract(timezone from input_ts) into gmt_epoch; + RETURN gmt_epoch; + EXCEPTION + WHEN OTHERS THEN + RAISE EXCEPTION 'gmt_epoch(%) : failed, sqlstate: %', input_ts, sqlstate; +END;\$\$ +LANGUAGE plpgsql; + -- Update the schema version number. UPDATE schema_version SET version = '9', minor = '0'; diff --git a/src/share/database/scripts/pgsql/wipe_data.sh.in b/src/share/database/scripts/pgsql/wipe_data.sh.in index b1a0e03f0f..154ddb0aa0 100644 --- a/src/share/database/scripts/pgsql/wipe_data.sh.in +++ b/src/share/database/scripts/pgsql/wipe_data.sh.in @@ -83,11 +83,15 @@ DELETE FROM dhcp4_option_def_server; DELETE FROM dhcp4_options; DELETE FROM dhcp4_options_server; DELETE FROM dhcp4_pool; -DELETE FROM dhcp4_server WHERE tag != 'all'; -- preserve the special tag DELETE FROM dhcp4_shared_network; -DELETE FROM dhcp4_shared_network_server; DELETE FROM dhcp4_subnet; DELETE FROM dhcp4_subnet_server; +DELETE FROM dhcp4_shared_network_server; +DELETE FROM dhcp4_client_class_order; +DELETE FROM dhcp4_client_class_dependency; +DELETE FROM dhcp4_client_class_server; +DELETE FROM dhcp4_client_class; +DELETE FROM dhcp4_server WHERE tag != 'all'; -- preserve the special tag DELETE FROM dhcp6_audit; DELETE FROM dhcp6_audit_revision; @@ -99,9 +103,13 @@ DELETE FROM dhcp6_options; DELETE FROM dhcp6_options_server; DELETE FROM dhcp6_pool; DELETE FROM dhcp6_pd_pool; -DELETE FROM dhcp6_server WHERE tag != 'all'; -- preserve the special tag DELETE FROM dhcp6_shared_network; DELETE FROM dhcp6_subnet; +DELETE FROM dhcp6_client_class_order; +DELETE FROM dhcp6_client_class_dependency; +DELETE FROM dhcp6_client_class_server; +DELETE FROM dhcp6_client_class; +DELETE FROM dhcp6_server WHERE tag != 'all'; -- preserve the special tag COMMIT; EOF