]> git.ipfire.org Git - thirdparty/kea.git/commitdiff
[313-return-a-list-of-all-reservations-by-subnet-id] Addressed more comments
authorFrancis Dupont <fdupont@isc.org>
Wed, 23 Jan 2019 15:07:45 +0000 (16:07 +0100)
committerFrancis Dupont <fdupont@isc.org>
Tue, 29 Jan 2019 09:49:05 +0000 (04:49 -0500)
doc/guide/hooks.xml
src/lib/dhcpsrv/cql_host_data_source.cc
src/lib/dhcpsrv/cql_host_data_source.h
src/lib/dhcpsrv/mysql_host_data_source.cc
src/lib/dhcpsrv/pgsql_host_data_source.cc
src/lib/dhcpsrv/testutils/generic_host_data_source_unittest.h

index c3e340cfe1499e36836b21b84498737443bbeec9..8aa341a7d08b8521838812be87dea49a0bcaf834 100644 (file)
@@ -1663,7 +1663,48 @@ An example result returned when the query was malformed:<screen>
           retrieved by using subnet-id value of zero (0).
           </para>
 
-          <!-- Add example? -->
+         <para>For instance for retrieving host reservations for the
+          subnet 1:
+<screen>
+{
+    "command": "reservation-get-all",
+    "arguments": {
+        <userinput>"subnet-id": 1</userinput>
+     }
+}
+</screen> returns found some IPv4 hosts:
+<screen>
+{
+    "arguments": {
+        "hosts": [
+            {
+                "boot-file-name": "bootfile.efi",
+                "client-classes": [ ],
+                "hostname": "somehost.example.org",
+                "hw-address": "01:02:03:04:05:06",
+                "ip-address": "192.0.2.100",
+                "next-server": "192.0.0.2",
+                "option-data": [ ],
+                "server-hostname": "server-hostname.example.org"
+            },
+            ...
+            {
+                "boot-file-name": "bootfile.efi",
+                "client-classes": [ ],
+                "hostname": "otherhost.example.org",
+                "hw-address": "01:02:03:04:05:ff",
+                "ip-address": "192.0.2.200",
+                "next-server": "192.0.0.2",
+                "option-data": [ ],
+                "server-hostname": "server-hostname.example.org"
+            }
+        ]
+    },
+    "result": 0,
+    "text": "72 IPv4 host(s) found."
+}
+</screen>
+         </para>
 
           <para>The response returned by <command>reservation-get-all</command>
           can be very long. The DHCP server does not handle DHCP
@@ -1690,14 +1731,83 @@ An example result returned when the query was malformed:<screen>
           uses to chain page queries.
           </para>
 
-          <!-- Add example -->
-
           <para>The first page is queried without source-index and from,
           for next pages source-index and from should be set using
           the preceeding result source-index and next. After the last page
           the returned list is empty, count is 0 and result 3 is returned.
           </para>
 
+         <para>For instance for retrieving host reservations for the
+         subnet 1 requesting the first page can be done by:
+<screen>
+{
+    "command": "reservation-get-page",
+    "arguments": {
+        <userinput>"subnet-id": 1,
+       "limit": 10</userinput>
+     }
+}
+</screen> leaving source-index and from to their zero default values.
+          </para>
+
+          <para>Some hosts are returned with informations to get the next page:
+<screen>
+{
+    "arguments": {
+        "count": 72,
+        "hosts": [
+            {
+                "boot-file-name": "bootfile.efi",
+                "client-classes": [ ],
+                "hostname": "somehost.example.org",
+                "hw-address": "01:02:03:04:05:06",
+                "ip-address": "192.0.2.100",
+                "next-server": "192.0.0.2",
+                "option-data": [ ],
+                "server-hostname": "server-hostname.example.org"
+            },
+            ...
+            {
+                "boot-file-name": "bootfile.efi",
+                "client-classes": [ ],
+                "hostname": "otherhost.example.org",
+                "hw-address": "01:02:03:04:05:ff",
+                "ip-address": "192.0.2.200",
+                "next-server": "192.0.0.2",
+                "option-data": [ ],
+                "server-hostname": "server-hostname.example.org"
+            }
+        ],
+        "next": 1234567,
+        "source-index": 0
+    },
+    "result": 0,
+    "text": "72 IPv4 host(s) found."
+}
+</screen> To get the next page this can be sent:
+<screen>
+{
+    "command": "reservation-get-page",
+    "arguments": {
+        <userinput>"subnet-id": 1,
+        "source-index": 1,
+        "from": 1234567,
+       "limit": 10</userinput>
+     }
+}
+</screen> responses after the last page look like:
+<screen>
+{
+    "arguments": {
+        "count": 0,
+        "hosts": [ ],
+        "source-index": 2,
+    },
+    "result": 3,
+    "0 IPv4 host(s) found."
+}
+</screen></para>
+
           <para>This command is more complex than
           <command>reservation-get-all</command>, but lets users
           retrieve larger host reservations lists by smaller
index 308fd1cc85c8034358508af2f04f4a1ab61a955a..a94121e437084798d9165fbcfb5a8fbb569237c4 100644 (file)
@@ -321,26 +321,6 @@ public:
     // associated with a host using subnet identifier.
     static constexpr StatementTag GET_HOST_BY_IPV6_SUBNET_ID =
         "GET_HOST_BY_IPV6_SUBNET_ID";
-
-    // Retrieves host information along with the IPv4 options associated
-    // with it using a subnet identifier. First page.
-    static constexpr StatementTag GET_HOST_BY_IPV4_SUBNET_ID_LIMIT =
-        "GET_HOST_BY_IPV4_SUBNET_ID_LIMIT";
-
-    // Retrieves host information along with the IPv4 options associated
-    // with it using a subnet identifier. Next page.
-    static constexpr StatementTag GET_HOST_BY_IPV4_SUBNET_ID_PAGE =
-        "GET_HOST_BY_IPV4_SUBNET_ID_PAGE";
-
-    // Retrieves host information along with the IPv6 options associated
-    // with it using a subnet identifier. First page.
-    static constexpr StatementTag GET_HOST_BY_IPV6_SUBNET_ID_LIMIT =
-        "GET_HOST_BY_IPV6_SUBNET_ID_LIMIT";
-
-    // Retrieves host information along with the IPv6 options associated
-    // with it using a subnet identifier. Next page.
-    static constexpr StatementTag GET_HOST_BY_IPV6_SUBNET_ID_PAGE =
-        "GET_HOST_BY_IPV6_SUBNET_ID_PAGE";
     /// @}
 
     /// @brief Cassandra statements
@@ -452,10 +432,6 @@ constexpr StatementTag CqlHostExchange::GET_HOST_BY_IPV6_SUBNET_ID_AND_ADDRESS;
 constexpr StatementTag CqlHostExchange::DELETE_HOST;
 constexpr StatementTag CqlHostExchange::GET_HOST_BY_IPV4_SUBNET_ID;
 constexpr StatementTag CqlHostExchange::GET_HOST_BY_IPV6_SUBNET_ID;
-constexpr StatementTag CqlHostExchange::GET_HOST_BY_IPV4_SUBNET_ID_LIMIT;
-constexpr StatementTag CqlHostExchange::GET_HOST_BY_IPV4_SUBNET_ID_PAGE;
-constexpr StatementTag CqlHostExchange::GET_HOST_BY_IPV6_SUBNET_ID_LIMIT;
-constexpr StatementTag CqlHostExchange::GET_HOST_BY_IPV6_SUBNET_ID_PAGE;
 
 StatementMap CqlHostExchange::tagged_statements_ = {
     {INSERT_HOST,
@@ -870,154 +846,6 @@ StatementMap CqlHostExchange::tagged_statements_ = {
       "FROM host_reservations "
       "WHERE host_ipv6_subnet_id = ? "
       "ALLOW FILTERING "
-     }},
-
-    {GET_HOST_BY_IPV4_SUBNET_ID_LIMIT,
-     {GET_HOST_BY_IPV4_SUBNET_ID_LIMIT,
-      "SELECT "
-      "id, "
-      "host_identifier, "
-      "host_identifier_type, "
-      "host_ipv4_subnet_id, "
-      "host_ipv6_subnet_id, "
-      "host_ipv4_address, "
-      "host_ipv4_next_server, "
-      "host_ipv4_server_hostname, "
-      "host_ipv4_boot_file_name, "
-      "auth_key, "
-      "hostname, "
-      "user_context, "
-      "host_ipv4_client_classes, "
-      "host_ipv6_client_classes, "
-      "reserved_ipv6_prefix_address, "
-      "reserved_ipv6_prefix_length, "
-      "reserved_ipv6_prefix_address_type, "
-      "iaid, "
-      "option_universe, "
-      "option_code, "
-      "option_value, "
-      "option_formatted_value, "
-      "option_space, "
-      "option_is_persistent, "
-      "option_client_class, "
-      "option_subnet_id, "
-      "option_user_context, "
-      "option_scope_id "
-      "FROM host_reservations "
-      "WHERE host_ipv4_subnet_id = ? "
-      "LIMIT ? "
-      "ALLOW FILTERING "
-     }},
-
-    {GET_HOST_BY_IPV4_SUBNET_ID_PAGE,
-     {GET_HOST_BY_IPV4_SUBNET_ID_PAGE,
-      "SELECT "
-      "id, "
-      "host_identifier, "
-      "host_identifier_type, "
-      "host_ipv4_subnet_id, "
-      "host_ipv6_subnet_id, "
-      "host_ipv4_address, "
-      "host_ipv4_next_server, "
-      "host_ipv4_server_hostname, "
-      "host_ipv4_boot_file_name, "
-      "auth_key, "
-      "hostname, "
-      "user_context, "
-      "host_ipv4_client_classes, "
-      "host_ipv6_client_classes, "
-      "reserved_ipv6_prefix_address, "
-      "reserved_ipv6_prefix_length, "
-      "reserved_ipv6_prefix_address_type, "
-      "iaid, "
-      "option_universe, "
-      "option_code, "
-      "option_value, "
-      "option_formatted_value, "
-      "option_space, "
-      "option_is_persistent, "
-      "option_client_class, "
-      "option_subnet_id, "
-      "option_user_context, "
-      "option_scope_id "
-      "FROM host_reservations "
-      "WHERE host_ipv4_subnet_id = ? AND TOKEN(id) > TOKEN(?) "
-      "LIMIT ? "
-      "ALLOW FILTERING "
-     }},
-
-    {GET_HOST_BY_IPV6_SUBNET_ID_LIMIT,
-     {GET_HOST_BY_IPV6_SUBNET_ID_LIMIT,
-      "SELECT "
-      "id, "
-      "host_identifier, "
-      "host_identifier_type, "
-      "host_ipv4_subnet_id, "
-      "host_ipv6_subnet_id, "
-      "host_ipv4_address, "
-      "host_ipv4_next_server, "
-      "host_ipv4_server_hostname, "
-      "host_ipv4_boot_file_name, "
-      "auth_key, "
-      "hostname, "
-      "user_context, "
-      "host_ipv4_client_classes, "
-      "host_ipv6_client_classes, "
-      "reserved_ipv6_prefix_address, "
-      "reserved_ipv6_prefix_length, "
-      "reserved_ipv6_prefix_address_type, "
-      "iaid, "
-      "option_universe, "
-      "option_code, "
-      "option_value, "
-      "option_formatted_value, "
-      "option_space, "
-      "option_is_persistent, "
-      "option_client_class, "
-      "option_subnet_id, "
-      "option_user_context, "
-      "option_scope_id "
-      "FROM host_reservations "
-      "WHERE host_ipv6_subnet_id = ? "
-      "LIMIT ? "
-      "ALLOW FILTERING "
-     }},
-
-    {GET_HOST_BY_IPV6_SUBNET_ID_PAGE,
-     {GET_HOST_BY_IPV6_SUBNET_ID_PAGE,
-      "SELECT "
-      "id, "
-      "host_identifier, "
-      "host_identifier_type, "
-      "host_ipv4_subnet_id, "
-      "host_ipv6_subnet_id, "
-      "host_ipv4_address, "
-      "host_ipv4_next_server, "
-      "host_ipv4_server_hostname, "
-      "host_ipv4_boot_file_name, "
-      "auth_key, "
-      "hostname, "
-      "user_context, "
-      "host_ipv4_client_classes, "
-      "host_ipv6_client_classes, "
-      "reserved_ipv6_prefix_address, "
-      "reserved_ipv6_prefix_length, "
-      "reserved_ipv6_prefix_address_type, "
-      "iaid, "
-      "option_universe, "
-      "option_code, "
-      "option_value, "
-      "option_formatted_value, "
-      "option_space, "
-      "option_is_persistent, "
-      "option_client_class, "
-      "option_subnet_id, "
-      "option_user_context, "
-      "option_scope_id "
-      "FROM host_reservations "
-      "WHERE host_ipv6_subnet_id = ? AND TOKEN(id) > TOKEN(?) "
-      "LIMIT ? "
-      "ALLOW FILTERING "
      }}
 };
 
@@ -1700,6 +1528,9 @@ public:
 
     /// @brief Implementation of @ref CqlHostDataSource::getPage4()
     ///
+    /// Not implemented.
+    /// @todo: implement it.
+    ///
     /// See @ref CqlHostDataSource::getPage4() for parameter details.
     ///
     /// @param subnet_id identifier of the subnet to which hosts belong
@@ -1713,6 +1544,9 @@ public:
 
     /// @brief Implementation of @ref CqlHostDataSource::getPage6()
     ///
+    /// Not implemented.
+    /// @todo: implement it.
+    ///
     /// See @ref CqlHostDataSource::getPage6() for parameter details.
     ///
     /// @param subnet_id identifier of the subnet to which hosts belong
@@ -2143,71 +1977,29 @@ CqlHostDataSourceImpl::getAll6(const SubnetID& subnet_id) const {
     return (result);
 }
 
-ConstHostCollection
-CqlHostDataSourceImpl::getPage4(const SubnetID& subnet_id,
-                                uint64_t lower_host_id,
-                                const HostPageSize& page_size) const {
-    // Convert to CQL data types.
-    cass_int32_t host_ipv4_subnet_id = static_cast<cass_int32_t>(subnet_id);
-
-    // Bind to array.
-    AnyArray where_values;
-    where_values.add(&host_ipv4_subnet_id);
+// There are some problems implementing this for Cassandra.
+// Attempts show the per page ordering does not work and
+// it is not possible to order by TOKEN(host_id).
+// If the issue solved by paging is the Kea API overhead then
+// a solution is to get and cache all reservations and to handle
+// paging at the API level.
 
-    cass_int64_t id = static_cast<cass_int64_t>(lower_host_id);
-    if (id) {
-        where_values.add(&id);
-    }
-
-    cass_int32_t page_size_data =
-        static_cast<cass_int32_t>(page_size.page_size_);
-    where_values.add(&page_size_data);
-
-    // Run statement.
-    ConstHostCollection result =
-        getHostCollection(id == 0 ?
-                          CqlHostExchange::GET_HOST_BY_IPV4_SUBNET_ID_LIMIT :
-                          CqlHostExchange::GET_HOST_BY_IPV4_SUBNET_ID_PAGE,
-                          where_values);
-
-    // Note the result is not ordered (or ordered following TOKEN).
-
-    return (result);
+ConstHostCollection
+CqlHostDataSourceImpl::getPage4(const SubnetID& /*subnet_id*/,
+                                uint64_t /*lower_host_id*/,
+                                const HostPageSize& /*page_size*/) const {
+    isc_throw(NotImplemented,
+              "reservation-get-page is not supported by Cassandra");
 }
 
 ConstHostCollection
-CqlHostDataSourceImpl::getPage6(const SubnetID& subnet_id,
-                                uint64_t lower_host_id,
-                                const HostPageSize& page_size) const {
-    // Convert to CQL data types.
-    cass_int32_t host_ipv6_subnet_id = static_cast<cass_int32_t>(subnet_id);
-
-    // Bind to array.
-    AnyArray where_values;
-    where_values.add(&host_ipv6_subnet_id);
-
-    cass_int64_t id = static_cast<cass_int64_t>(lower_host_id);
-    if (id) {
-        where_values.add(&id);
-    }
-
-    cass_int32_t page_size_data =
-        static_cast<cass_int32_t>(page_size.page_size_);
-    where_values.add(&page_size_data);
-
-    // Run statement.
-    ConstHostCollection result =
-        getHostCollection(id == 0 ?
-                          CqlHostExchange::GET_HOST_BY_IPV6_SUBNET_ID_LIMIT :
-                          CqlHostExchange::GET_HOST_BY_IPV6_SUBNET_ID_PAGE,
-                          where_values);
-
-    // Note the result is not ordered (or ordered following TOKEN).
-
-    return (result);
+CqlHostDataSourceImpl::getPage6(const SubnetID& /*subnet_id*/,
+                                uint64_t /*lower_host_id*/,
+                                const HostPageSize& /*page_size*/) const {
+    isc_throw(NotImplemented,
+              "reservation-get-page is not supported by Cassandra");
 }
 
-
 ConstHostCollection
 CqlHostDataSourceImpl::getAll4(const asiolink::IOAddress& address) const {
     // Convert to CQL data types.
index d5dc7137366fb675609d25740bb40f9f3986bb02..c9f5a18512963ab66840d7980ecc895b472c967b 100644 (file)
@@ -192,8 +192,7 @@ public:
 
     /// @brief Returns range of hosts in a DHCPv4 subnet.
     ///
-    /// This method returns a page of @c Host objects which represent
-    /// reservations in a specified subnet.
+    /// Not implemented.
     ///
     /// @param subnet_id Subnet identifier.
     /// @param source_index Index of the source (unused).
@@ -210,8 +209,7 @@ public:
 
     /// @brief Returns range of hosts in a DHCPv6 subnet.
     ///
-    /// This method returns a page of @c Host objects which represent
-    /// reservations in a specified subnet.
+    /// Not implemented.
     ///
     /// @param subnet_id Subnet identifier.
     /// @param source_index Index of the source (unused).
index 3a57cbb3a4f0c01dcf97d00cd813ad9a6eda60f7..4e6c25bb28da2028389863aa7fc968ba479692b9 100644 (file)
@@ -2325,17 +2325,23 @@ TaggedStatementArray tagged_statements = { {
             "persistent, user_context, dhcp_client_class, dhcp6_subnet_id, host_id, scope_id) "
          " VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, 3)"},
 
+    // Delete a single IPv4 reservation by subnet id and reserved address.
     {MySqlHostDataSourceImpl::DEL_HOST_ADDR4,
      "DELETE FROM hosts WHERE dhcp4_subnet_id = ? AND ipv4_address = ?"},
 
+    // Delete a single IPv4 reservation by subnet id and identifier.
     {MySqlHostDataSourceImpl::DEL_HOST_SUBID4_ID,
      "DELETE FROM hosts WHERE dhcp4_subnet_id = ? AND dhcp_identifier_type=? "
      "AND dhcp_identifier = ?"},
 
+    // Delete a single IPv6 reservation by subnet id and identifier.
     {MySqlHostDataSourceImpl::DEL_HOST_SUBID6_ID,
      "DELETE FROM hosts WHERE dhcp6_subnet_id = ? AND dhcp_identifier_type=? "
      "AND dhcp_identifier = ?"},
 
+    // Retrieves host information along with the DHCPv4 options associated with
+    // it. Left joining the dhcp4_options table results in multiple rows being
+    // returned for the same host. Hosts are retrieved by IPv4 subnet id.
     {MySqlHostDataSourceImpl::GET_HOST_SUBID4,
             "SELECT h.host_id, h.dhcp_identifier, h.dhcp_identifier_type, "
                 "h.dhcp4_subnet_id, h.dhcp6_subnet_id, h.ipv4_address, h.hostname, "
@@ -2350,6 +2356,10 @@ TaggedStatementArray tagged_statements = { {
             "WHERE h.dhcp4_subnet_id = ? "
             "ORDER BY h.host_id, o.option_id"},
 
+    // Retrieves host information, IPv6 reservations and DHCPv6 options
+    // associated with a host. The number of rows returned is a multiplication
+    // of number of IPv6 reservations and DHCPv6 options. Hosts are retrieved
+    // by IPv6 subnet id.
     {MySqlHostDataSourceImpl::GET_HOST_SUBID6,
             "SELECT h.host_id, h.dhcp_identifier, "
                 "h.dhcp_identifier_type, h.dhcp4_subnet_id, "
@@ -2370,6 +2380,11 @@ TaggedStatementArray tagged_statements = { {
             "WHERE h.dhcp6_subnet_id = ? "
             "ORDER BY h.host_id, o.option_id, r.reservation_id"},
 
+    // Retrieves host information along with the DHCPv4 options associated with
+    // it. Left joining the dhcp4_options table results in multiple rows being
+    // returned for the same host. Hosts are retrieved by IPv4 subnet id
+    // and with a host id greater than the start one.
+    // The number of hosts returned is lower or equal to the limit.
     {MySqlHostDataSourceImpl::GET_HOST_SUBID4_PAGE,
             "SELECT h.host_id, h.dhcp_identifier, h.dhcp_identifier_type, "
                 "h.dhcp4_subnet_id, h.dhcp6_subnet_id, h.ipv4_address, h.hostname, "
@@ -2378,13 +2393,19 @@ TaggedStatementArray tagged_statements = { {
                 "h.dhcp4_boot_file_name, h.auth_key, "
                 "o.option_id, o.code, o.value, o.formatted_value, o.space, "
                 "o.persistent, o.user_context "
-            "FROM hosts AS h "
+            "FROM ( SELECT * FROM hosts AS h "
+                       "WHERE h.dhcp4_subnet_id = ? AND h.host_id > ? "
+                       "ORDER BY h.host_id "
+                       "LIMIT ? ) AS h "
             "LEFT JOIN dhcp4_options AS o "
                 "ON h.host_id = o.host_id "
-            "WHERE h.dhcp4_subnet_id = ? AND h.host_id > ? "
-            "ORDER BY h.host_id, o.option_id "
-            "LIMIT ?"},
+            "ORDER BY h.host_id, o.option_id"},
 
+    // Retrieves host information, IPv6 reservations and DHCPv6 options
+    // associated with a host. The number of rows returned is a multiplication
+    // of number of IPv6 reservations and DHCPv6 options. Hosts are retrieved
+    // by IPv6 subnet id and with a host id greater than the start one.
+    // The number of hosts returned is lower or equal to the limit.
     {MySqlHostDataSourceImpl::GET_HOST_SUBID6_PAGE,
             "SELECT h.host_id, h.dhcp_identifier, "
                 "h.dhcp_identifier_type, h.dhcp4_subnet_id, "
@@ -2397,14 +2418,15 @@ TaggedStatementArray tagged_statements = { {
                 "o.persistent, o.user_context, "
                 "r.reservation_id, r.address, r.prefix_len, r.type, "
                 "r.dhcp6_iaid "
-            "FROM hosts AS h "
+            "FROM ( SELECT * FROM hosts AS h "
+                       "WHERE h.dhcp6_subnet_id = ? AND h.host_id > ? "
+                       "ORDER BY h.host_id "
+                       "LIMIT ? ) AS h "
             "LEFT JOIN dhcp6_options AS o "
                 "ON h.host_id = o.host_id "
             "LEFT JOIN ipv6_reservations AS r "
                 "ON h.host_id = r.host_id "
-            "WHERE h.dhcp6_subnet_id = ? AND h.host_id > ? "
-            "ORDER BY h.host_id, o.option_id, r.reservation_id "
-            "LIMIT ?"}
+            "ORDER BY h.host_id, o.option_id, r.reservation_id"}
     }
 };
 
index f92142398edb69e375dae23a24899aa0093de72d..d6a9d229242c2da338289c0529e8d4c0c5c7cf1f 100644 (file)
@@ -1784,11 +1784,12 @@ TaggedStatementArray tagged_statements = { {
      "  h.dhcp4_boot_file_name, h.auth_key, "
      "  o.option_id, o.code, o.value, o.formatted_value, o.space, "
      "  o.persistent, o.user_context "
-     "FROM hosts AS h "
+     "FROM ( SELECT * FROM hosts AS h "
+     "       WHERE h.dhcp4_subnet_id = $1 AND h.host_id > $2 "
+     "       ORDER BY h.host_id "
+     "       LIMIT $3 ) AS h "
      "LEFT JOIN dhcp4_options AS o ON h.host_id = o.host_id "
-     "WHERE h.dhcp4_subnet_id = $1 AND h.host_id > $2 "
-     "ORDER BY h.host_id, o.option_id "
-     "LIMIT $3"
+     "ORDER BY h.host_id, o.option_id"
     },
 
     // PgSqlHostDataSourceImpl::GET_HOST_SUBID6_PAGE
@@ -1810,12 +1811,13 @@ TaggedStatementArray tagged_statements = { {
      "  o.option_id, o.code, o.value, o.formatted_value, o.space, "
      "  o.persistent, o.user_context, "
      "  r.reservation_id, r.address, r.prefix_len, r.type, r.dhcp6_iaid "
-     "FROM hosts AS h "
+     "FROM ( SELECT * FROM hosts AS h "
+     "       WHERE h.dhcp6_subnet_id = $1 AND h.host_id > $2 "
+     "       ORDER BY h.host_id "
+     "       LIMIT $3 ) AS h "
      "LEFT JOIN dhcp6_options AS o ON h.host_id = o.host_id "
      "LEFT JOIN ipv6_reservations AS r ON h.host_id = r.host_id "
-     "WHERE h.dhcp6_subnet_id = $1 AND h.host_id > $2 "
-     "ORDER BY h.host_id, o.option_id, r.reservation_id "
-     "LIMIT $3"
+     "ORDER BY h.host_id, o.option_id, r.reservation_id"
     }
 }
 };
index 8661dfae38b82ceefb75f8c6f69109991e1f1b3f..4954876e05182d8ad7bf3e1bc6a65097ede0466a 100644 (file)
@@ -206,6 +206,22 @@ public:
     /// @param id Identifier type (hwaddr or duid).
     void testGetPage6(const Host::IdentifierType& id);
 
+    /// @brief Test that Verifies that pages of complex host reservations
+    /// are not truncated, i.e. the limit applies on the number of hosts
+    /// and not on the number of rows.
+    ///
+    /// Uses gtest macros to report failures.
+    /// @param id Identifier type (hwaddr or duid).
+    // void testGetPageLimit4(const Host::IdentifierType& id);
+
+    /// @brief Test that Verifies that pages of complex host reservations
+    /// are not truncated, i.e. the limit applies on the number of hosts
+    /// and not on the number of rows.
+    ///
+    /// Uses gtest macros to report failures.
+    /// @param id Identifier type (hwaddr or duid).
+    // void testGetPageLimit6(const Host::IdentifierType& id);
+
     /// @brief Test inserts several hosts with unique IPv4 address and
     ///        checks that they can be retrieved properly.
     ///