Browse Source

[master] Merge branch 'trac3382'

Fixed Conflicts in:
	src/bin/d2/tests/nc_test_utils.cc
	src/lib/dns/tests/labelsequence_unittest.cc
Thomas Markwalder 11 years ago
parent
commit
7b5cd680f7

+ 2 - 1
configure.ac

@@ -942,7 +942,8 @@ if test "$PG_CONFIG" != "" ; then
 
 
     PGSQL_CPPFLAGS=`$PG_CONFIG --cppflags`
     PGSQL_CPPFLAGS=`$PG_CONFIG --cppflags`
     PGSQL_INCLUDEDIR=`$PG_CONFIG --includedir`
     PGSQL_INCLUDEDIR=`$PG_CONFIG --includedir`
-    PGSQL_CPPFLAGS="$PGSQL_CPPFLAGS -I$PGSQL_INCLUDEDIR"
+    PGSQL_INCLUDEDIR_SERVER=`$PG_CONFIG --includedir-server`
+    PGSQL_CPPFLAGS="$PGSQL_CPPFLAGS -I$PGSQL_INCLUDEDIR -I$PGSQL_INCLUDEDIR_SERVER"
     PGSQL_LIBS=`$PG_CONFIG --libdir`
     PGSQL_LIBS=`$PG_CONFIG --libdir`
     PGSQL_LIBS="-L$PGSQL_LIBS -lpq"
     PGSQL_LIBS="-L$PGSQL_LIBS -lpq"
     PGSQL_VERSION=`$PG_CONFIG --version`
     PGSQL_VERSION=`$PG_CONFIG --version`

+ 24 - 8
src/lib/dhcpsrv/database_backends.dox

@@ -22,16 +22,22 @@
   the abstract isc::dhcp::LeaseMgr class.  This provides methods to
   the abstract isc::dhcp::LeaseMgr class.  This provides methods to
   create, retrieve, modify and delete leases in the database.
   create, retrieve, modify and delete leases in the database.
 
 
-  There are currently two available Lease Managers, MySQL and Memfile:
+  There are currently three available Lease Managers, Memfile, MySQL and
+  PostgreSQL:
+
+  - Memfile is an in-memory lease database which can be configured to persist
+  its content to disk in a flat-file.  Support for the Memfile database
+  backend is built into Kea DHCP.
 
 
   - The MySQL lease manager uses the freely available MySQL as its backend
   - The MySQL lease manager uses the freely available MySQL as its backend
-  database.  This is not included in BIND 10 DHCP by default:
+  database.  This is not included in Kea DHCP by default:
   the \--with-dhcp-mysql switch must be supplied to "configure" for support
   the \--with-dhcp-mysql switch must be supplied to "configure" for support
   to be compiled into the software.
   to be compiled into the software.
-  - Memfile is an in-memory lease database, with (currently) nothing being
-  written to persistent storage.  The long-term plans for the backend do
-  include the ability to store this on disk, but it is currently a
-  low-priority item.
+
+  - The PostgreSQL lease manager uses the freely available PostgreSQL as its
+  backend database.  This is not included in Kea DHCP by default:
+  the \--with-dhcp-pgsql switch must be supplied to "configure" for
+  support to be compiled into the software.
 
 
   @section dhcpdb-instantiation Instantiation of Lease Managers
   @section dhcpdb-instantiation Instantiation of Lease Managers
 
 
@@ -74,6 +80,16 @@
   - <b>user</b> - database user ID under which the database is accessed.  If not
   - <b>user</b> - database user ID under which the database is accessed.  If not
     specified, no user ID is used - the database is assumed to be open.
     specified, no user ID is used - the database is assumed to be open.
 
 
+  @subsection dhcpdb-keywords-pgsql PostgreSQL connection string keywords
+
+  - <b>host</b> - host on which the selected database is running.  If not
+  supplied, "localhost" is assumed.
+  - <b>name</b> - name of the PostgreSQL database to access.  There is no
+  default - this must always be supplied.
+  - <b>password</b> - password for the selected user ID (see below).  If not
+  specified, no password is used.
+  - <b>user</b> - database user ID under which the database is accessed.  If not
+    specified, no user ID is used - the database is assumed to be open.
 
 
   @section dhcp-backend-unittest Running Unit Tests
   @section dhcp-backend-unittest Running Unit Tests
 
 
@@ -81,7 +97,7 @@
   certain database-specific pre-requisites for successfully running the unit
   certain database-specific pre-requisites for successfully running the unit
   tests.  These are listed in the following sections.
   tests.  These are listed in the following sections.
 
 
-  @subsection dhcp-mysql-unittest MySQL
+  @subsection dhcp-mysql-unittest MySQL Unit Tests
 
 
   A database called <i>keatest</i> must be created. A database user, also called
   A database called <i>keatest</i> must be created. A database user, also called
   <i>keatest</i> (and with a password <i>keatest</i>) must also be created and
   <i>keatest</i> (and with a password <i>keatest</i>) must also be created and
@@ -122,7 +138,7 @@
   that BIND 10 has been build with the \--with-dhcp-mysql switch (see the installation
   that BIND 10 has been build with the \--with-dhcp-mysql switch (see the installation
   section in the <a href="http://bind10.isc.org/docs/bind10-guide.html">BIND 10 Guide</a>).
   section in the <a href="http://bind10.isc.org/docs/bind10-guide.html">BIND 10 Guide</a>).
 
 
- @subsection dhcp-pgsql-unittest PostgreSQL unit-tests
+ @subsection dhcp-pgsql-unittest PostgreSQL Unit Tests
 
 
   Conceptually, the steps required to run PostgreSQL unit-tests are the same as
   Conceptually, the steps required to run PostgreSQL unit-tests are the same as
   in MySQL. First, a database called <i>keatest</i> must be created. A database
   in MySQL. First, a database called <i>keatest</i> must be created. A database

+ 2 - 0
src/lib/dhcpsrv/lease_mgr.cc

@@ -32,6 +32,8 @@ using namespace std;
 namespace isc {
 namespace isc {
 namespace dhcp {
 namespace dhcp {
 
 
+const time_t LeaseMgr::MAX_DB_TIME = 2147483647;
+
 std::string LeaseMgr::getParameter(const std::string& name) const {
 std::string LeaseMgr::getParameter(const std::string& name) const {
     ParameterMap::const_iterator param = parameters_.find(name);
     ParameterMap::const_iterator param = parameters_.find(name);
     if (param == parameters_.end()) {
     if (param == parameters_.end()) {

+ 4 - 0
src/lib/dhcpsrv/lease_mgr.h

@@ -122,6 +122,10 @@ public:
 /// see the documentation of those classes for details.
 /// see the documentation of those classes for details.
 class LeaseMgr {
 class LeaseMgr {
 public:
 public:
+    /// @brief Defines maximum value for time that can be reliably stored.
+    // If I'm still alive I'll be too old to care. You fix it.
+    static const time_t MAX_DB_TIME;
+
     /// Database configuration parameter map
     /// Database configuration parameter map
     typedef std::map<std::string, std::string> ParameterMap;
     typedef std::map<std::string, std::string> ParameterMap;
 
 

File diff suppressed because it is too large
+ 853 - 531
src/lib/dhcpsrv/pgsql_lease_mgr.cc


+ 108 - 89
src/lib/dhcpsrv/pgsql_lease_mgr.h

@@ -27,43 +27,84 @@
 namespace isc {
 namespace isc {
 namespace dhcp {
 namespace dhcp {
 
 
-/// @brief An auxiliary structure for marshalling data for compiled statements
+/// @brief Structure used to bind C++ input values to dynamic SQL parameters
+/// The structure contains three vectors which store the input values,
+/// data lengths, and formats.  These vectors are passed directly into the
+/// PostgreSQL execute call.
 ///
 ///
-/// It represents a single field used in a query (e.g. one field used in WHERE
-/// or UPDATE clauses).
-struct PgSqlParam {
-    std::string value; ///< The actual value represented as text
-    bool isbinary;     ///< Boolean flag that indicates if data is binary
-    int binarylen;     ///< Specified binary length
-
-    /// @brief Constructor for text parameters
-    ///
-    /// Constructs a text (i.e. non-binary) instance given a string value.
-    /// @param val string containing the text value of the parameter.  The
-    /// default is an empty string which serves as the default or empty
-    /// parameter constructor.
-    PgSqlParam (const std::string& val = "")
-        : value(val), isbinary(false), binarylen(0) {
+/// Note that the data values are stored as pointers. These pointers need to
+/// valid for the duration of the PostgreSQL statement execution.  In other
+/// words populating them with pointers to values that go out of scope before
+/// statement is executed is a bad idea.
+struct PsqlBindArray {
+    /// @brief Vector of pointers to the data values.
+    std::vector<const char *> values_;
+    /// @brief Vector of data lengths for each value.
+    std::vector<int> lengths_;
+    /// @brief Vector of "format" for each value. A value of 0 means the
+    /// value is text, 1 means the value is binary.
+    std::vector<int> formats_;
+
+    /// @brief Format value for text data.
+    static const int TEXT_FMT;
+    /// @brief Format value for binary data.
+    static const int BINARY_FMT;
+
+    /// @brief Constant string passed to DB for boolean true values.
+    static const char* TRUE_STR;
+    /// @brief Constant string passed to DB for boolean false values.
+    static const char* FALSE_STR;
+
+    /// @brief Fetches the number of entries in the array.
+    /// @return Returns size_t containing the number of entries.
+    size_t size() {
+        return (values_.size());
     }
     }
 
 
-    /// @brief Constructor for binary data parameters
-    ///
-    /// Constructs a binary data instance given a vector of binary data.
-    /// @param data vector of binary data from which to set the parameter's
-    /// value.
-    PgSqlParam (const std::vector<uint8_t>& data)
-      : value(data.begin(), data.end()), isbinary(true),
-          binarylen(data.size()) {
+    /// @brief Indicates it the array is empty.
+    /// @return Returns true if there are no entries in the array, false
+    /// otherwise.
+    bool empty() {
+
+        return (values_.empty());
     }
     }
-};
 
 
-/// @brief Defines all parameters for binding a compiled statement
-typedef std::vector<PgSqlParam> BindParams;
+    /// @brief Adds a char array to bind array based
+    ///
+    /// Adds a TEXT_FMT value to the end of the bind array, using the given
+    /// char* as the data source. Note that value is expected to be NULL
+    /// terminated.
+    ///
+    /// @param value char array containing the null-terminated text to add.
+    void add(const char* value);
+
+    /// @brief Adds an string value to the bind array
+    ///
+    /// Adds a TEXT formatted value to the end of the bind array using the
+    /// given string as the data source.
+    ///
+    /// @param value std::string containing the value to add.
+    void add(const std::string& value);
+
+    /// @brief Adds a binary value to the bind array.
+    ///
+    /// Adds a BINARY_FMT value to the end of the bind array using the
+    /// given vector as the data source.
+    ///
+    /// @param value vector of binary bytes.
+    void add(const std::vector<uint8_t>& data);
 
 
-/// @brief Describes a single compiled statement
-struct PgSqlStatementBind {
-    const char* stmt_name; ///< Name of the compiled statement
-    int stmt_nbparams; ///< Number of statement parameters
+    /// @brief Adds a boolean value to the bind array.
+    ///
+    /// Converts the given boolean value to its corresponding to PostgreSQL
+    /// string value and adds it as a TEXT_FMT value to the bind array.
+    ///
+    /// @param value bool value to add.
+    void add(const bool& value);
+
+    /// @brief Dumps the contents of the array to a string.
+    /// @return std::string containing the dump
+    std::string toText();
 };
 };
 
 
 // Forward definitions (needed for shared_ptr definitions)
 // Forward definitions (needed for shared_ptr definitions)
@@ -145,9 +186,6 @@ public:
     ///
     ///
     /// @return smart pointer to the lease (or NULL if a lease is not found)
     /// @return smart pointer to the lease (or NULL if a lease is not found)
     ///
     ///
-    /// @throw isc::dhcp::DataTruncation Data was truncated on retrieval to
-    ///        fit into the space allocated for the result.  This indicates a
-    ///        programming error.
     /// @throw isc::dhcp::DbOperationError An operation on the open database has
     /// @throw isc::dhcp::DbOperationError An operation on the open database has
     ///        failed.
     ///        failed.
     virtual Lease4Ptr getLease4(const isc::asiolink::IOAddress& addr) const;
     virtual Lease4Ptr getLease4(const isc::asiolink::IOAddress& addr) const;
@@ -163,9 +201,6 @@ public:
     ///
     ///
     /// @return lease collection
     /// @return lease collection
     ///
     ///
-    /// @throw isc::dhcp::DataTruncation Data was truncated on retrieval to
-    ///        fit into the space allocated for the result.  This indicates a
-    ///        programming error.
     /// @throw isc::dhcp::DbOperationError An operation on the open database has
     /// @throw isc::dhcp::DbOperationError An operation on the open database has
     ///        failed.
     ///        failed.
     virtual Lease4Collection getLease4(const isc::dhcp::HWAddr& hwaddr) const;
     virtual Lease4Collection getLease4(const isc::dhcp::HWAddr& hwaddr) const;
@@ -181,9 +216,6 @@ public:
     ///
     ///
     /// @return a pointer to the lease (or NULL if a lease is not found)
     /// @return a pointer to the lease (or NULL if a lease is not found)
     ///
     ///
-    /// @throw isc::dhcp::DataTruncation Data was truncated on retrieval to
-    ///        fit into the space allocated for the result.  This indicates a
-    ///        programming error.
     /// @throw isc::dhcp::DbOperationError An operation on the open database has
     /// @throw isc::dhcp::DbOperationError An operation on the open database has
     ///        failed.
     ///        failed.
     virtual Lease4Ptr getLease4(const isc::dhcp::HWAddr& hwaddr,
     virtual Lease4Ptr getLease4(const isc::dhcp::HWAddr& hwaddr,
@@ -200,9 +232,6 @@ public:
     ///
     ///
     /// @return lease collection
     /// @return lease collection
     ///
     ///
-    /// @throw isc::dhcp::DataTruncation Data was truncated on retrieval to
-    ///        fit into the space allocated for the result.  This indicates a
-    ///        programming error.
     /// @throw isc::dhcp::DbOperationError An operation on the open database has
     /// @throw isc::dhcp::DbOperationError An operation on the open database has
     ///        failed.
     ///        failed.
     virtual Lease4Collection getLease4(const ClientId& clientid) const;
     virtual Lease4Collection getLease4(const ClientId& clientid) const;
@@ -216,7 +245,7 @@ public:
     ///
     ///
     /// @return A pointer to the lease or NULL if the lease is not found.
     /// @return A pointer to the lease or NULL if the lease is not found.
     /// @throw isc::NotImplemented On every call as this function is currently
     /// @throw isc::NotImplemented On every call as this function is currently
-    /// not implemented for the MySQL backend.
+    /// not implemented for the PostgreSQL backend.
     virtual Lease4Ptr getLease4(const ClientId& client_id, const HWAddr& hwaddr,
     virtual Lease4Ptr getLease4(const ClientId& client_id, const HWAddr& hwaddr,
                                 SubnetID subnet_id) const;
                                 SubnetID subnet_id) const;
 
 
@@ -359,23 +388,31 @@ public:
 
 
     /// @brief Commit Transactions
     /// @brief Commit Transactions
     ///
     ///
-    /// Commits all pending database operations.  On databases that don't
-    /// support transactions, this is a no-op.
+    /// Commits all pending database operations.
     ///
     ///
     /// @throw DbOperationError Iif the commit failed.
     /// @throw DbOperationError Iif the commit failed.
     virtual void commit();
     virtual void commit();
 
 
     /// @brief Rollback Transactions
     /// @brief Rollback Transactions
     ///
     ///
-    /// Rolls back all pending database operations.  On databases that don't
-    /// support transactions, this is a no-op.
+    /// Rolls back all pending database operations.
     ///
     ///
     /// @throw DbOperationError If the rollback failed.
     /// @throw DbOperationError If the rollback failed.
     virtual void rollback();
     virtual void rollback();
 
 
+    /// @brief Checks a result set's SQL state against an error state.
+    ///
+    /// @param r result set to check
+    /// @param error_state error state to compare against
+    ///
+    /// @return True if the result set's SQL state equals the error_state,
+    /// false otherwise.
+    bool compareError(PGresult*& r, const char* error_state);
+
     /// @brief Statement Tags
     /// @brief Statement Tags
     ///
     ///
-    /// The contents of the enum are indexes into the list of compiled SQL statements
+    /// The contents of the enum are indexes into the list of compiled SQL
+    /// statements
     enum StatementIndex {
     enum StatementIndex {
         DELETE_LEASE4,              // Delete from lease4 by address
         DELETE_LEASE4,              // Delete from lease4 by address
         DELETE_LEASE6,              // Delete from lease6 by address
         DELETE_LEASE6,              // Delete from lease6 by address
@@ -423,8 +460,8 @@ private:
     /// of the addLease method.  It binds the contents of the lease object to
     /// of the addLease method.  It binds the contents of the lease object to
     /// the prepared statement and adds it to the database.
     /// the prepared statement and adds it to the database.
     ///
     ///
-    /// @param stindex Index of statemnent being executed
-    /// @param bind MYSQL_BIND array that has been created for the type
+    /// @param stindex Index of statement being executed
+    /// @param bind_array array that has been created for the type
     ///        of lease in question.
     ///        of lease in question.
     ///
     ///
     /// @return true if the lease was added, false if it was not added because
     /// @return true if the lease was added, false if it was not added because
@@ -432,7 +469,7 @@ private:
     ///
     ///
     /// @throw isc::dhcp::DbOperationError An operation on the open database has
     /// @throw isc::dhcp::DbOperationError An operation on the open database has
     ///        failed.
     ///        failed.
-    bool addLeaseCommon(StatementIndex stindex, BindParams& params);
+    bool addLeaseCommon(StatementIndex stindex, PsqlBindArray& bind_array);
 
 
     /// @brief Get Lease Collection Common Code
     /// @brief Get Lease Collection Common Code
     ///
     ///
@@ -440,7 +477,7 @@ private:
     /// from the database.
     /// from the database.
     ///
     ///
     /// @param stindex Index of statement being executed
     /// @param stindex Index of statement being executed
-    /// @param params PostgreSQL parameters for the query
+    /// @param bind_array array containing the where clause input parameters
     /// @param exchange Exchange object to use
     /// @param exchange Exchange object to use
     /// @param result Returned collection of Leases Note that any leases in
     /// @param result Returned collection of Leases Note that any leases in
     ///        the collection when this method is called are not erased: the
     ///        the collection when this method is called are not erased: the
@@ -455,7 +492,7 @@ private:
     /// @throw isc::dhcp::MultipleRecords Multiple records were retrieved
     /// @throw isc::dhcp::MultipleRecords Multiple records were retrieved
     ///        from the database where only one was expected.
     ///        from the database where only one was expected.
     template <typename Exchange, typename LeaseCollection>
     template <typename Exchange, typename LeaseCollection>
-    void getLeaseCollection(StatementIndex stindex, BindParams& params,
+    void getLeaseCollection(StatementIndex stindex, PsqlBindArray& bind_array,
                             Exchange& exchange, LeaseCollection& result,
                             Exchange& exchange, LeaseCollection& result,
                             bool single = false) const;
                             bool single = false) const;
 
 
@@ -465,7 +502,7 @@ private:
     /// the get lease collection common code.
     /// the get lease collection common code.
     ///
     ///
     /// @param stindex Index of statement being executed
     /// @param stindex Index of statement being executed
-    /// @param params PostgreSQL parameters for the query
+    /// @param bind_array array containing the where clause input parameters
     /// @param lease LeaseCollection object returned.  Note that any leases in
     /// @param lease LeaseCollection object returned.  Note that any leases in
     ///        the collection when this method is called are not erased: the
     ///        the collection when this method is called are not erased: the
     ///        new data is appended to the end.
     ///        new data is appended to the end.
@@ -475,9 +512,9 @@ private:
     ///        failed.
     ///        failed.
     /// @throw isc::dhcp::MultipleRecords Multiple records were retrieved
     /// @throw isc::dhcp::MultipleRecords Multiple records were retrieved
     ///        from the database where only one was expected.
     ///        from the database where only one was expected.
-    void getLeaseCollection(StatementIndex stindex, BindParams& params,
+    void getLeaseCollection(StatementIndex stindex, PsqlBindArray& bind_array,
                             Lease4Collection& result) const {
                             Lease4Collection& result) const {
-        getLeaseCollection(stindex, params, exchange4_, result);
+        getLeaseCollection(stindex, bind_array, exchange4_, result);
     }
     }
 
 
     /// @brief Get Lease6 Collection
     /// @brief Get Lease6 Collection
@@ -486,7 +523,7 @@ private:
     /// the get lease collection common code.
     /// the get lease collection common code.
     ///
     ///
     /// @param stindex Index of statement being executed
     /// @param stindex Index of statement being executed
-    /// @param params PostgreSQL parameters for the query
+    /// @param bind_array array containing input parameters for the query
     /// @param lease LeaseCollection object returned.  Note that any existing
     /// @param lease LeaseCollection object returned.  Note that any existing
     ///        data in the collection is erased first.
     ///        data in the collection is erased first.
     ///
     ///
@@ -495,9 +532,9 @@ private:
     ///        failed.
     ///        failed.
     /// @throw isc::dhcp::MultipleRecords Multiple records were retrieved
     /// @throw isc::dhcp::MultipleRecords Multiple records were retrieved
     ///        from the database where only one was expected.
     ///        from the database where only one was expected.
-    void getLeaseCollection(StatementIndex stindex, BindParams& params,
+    void getLeaseCollection(StatementIndex stindex, PsqlBindArray& bind_array,
                             Lease6Collection& result) const {
                             Lease6Collection& result) const {
-        getLeaseCollection(stindex, params, exchange6_, result);
+        getLeaseCollection(stindex, bind_array, exchange6_, result);
     }
     }
 
 
     /// @brief Checks result of the r object
     /// @brief Checks result of the r object
@@ -509,20 +546,7 @@ private:
     /// @param index will be used to print out compiled statement name
     /// @param index will be used to print out compiled statement name
     ///
     ///
     /// @throw isc::dhcp::DbOperationError Detailed PostgreSQL failure
     /// @throw isc::dhcp::DbOperationError Detailed PostgreSQL failure
-    inline void checkStatementError(PGresult* r, StatementIndex index) const;
-
-    /// @brief Converts query parameters to format accepted by PostgreSQL
-    ///
-    /// Converts parameters stored in params into 3 vectors: out_params,
-    /// out_lengths and out_formats.
-    /// @param params input parameters
-    /// @param out_values [out] values of specified parameters
-    /// @param out_lengths [out] lengths of specified values
-    /// @param out_formats [out] specifies format (text (0) or binary (1))
-    inline void convertToQuery(const BindParams& params,
-                               std::vector<const char *>& out_values,
-                               std::vector<int>& out_lengths,
-                               std::vector<int>& out_formats) const;
+    void checkStatementError(PGresult*& r, StatementIndex index) const;
 
 
     /// @brief Get Lease4 Common Code
     /// @brief Get Lease4 Common Code
     ///
     ///
@@ -531,9 +555,9 @@ private:
     /// but retrieveing only a single lease.
     /// but retrieveing only a single lease.
     ///
     ///
     /// @param stindex Index of statement being executed
     /// @param stindex Index of statement being executed
-    /// @param BindParams PostgreSQL array for input parameters
+    /// @param bind_array array containing input parameters for the query
     /// @param lease Lease4 object returned
     /// @param lease Lease4 object returned
-    void getLease(StatementIndex stindex, BindParams& params,
+    void getLease(StatementIndex stindex, PsqlBindArray& bind_array,
                   Lease4Ptr& result) const;
                   Lease4Ptr& result) const;
 
 
     /// @brief Get Lease6 Common Code
     /// @brief Get Lease6 Common Code
@@ -543,9 +567,9 @@ private:
     /// but retrieveing only a single lease.
     /// but retrieveing only a single lease.
     ///
     ///
     /// @param stindex Index of statement being executed
     /// @param stindex Index of statement being executed
-    /// @param BindParams PostgreSQL array for input parameters
+    /// @param bind_array array containing input parameters for the query
     /// @param lease Lease6 object returned
     /// @param lease Lease6 object returned
-    void getLease(StatementIndex stindex, BindParams& params,
+    void getLease(StatementIndex stindex, PsqlBindArray& bind_array,
                   Lease6Ptr& result) const;
                   Lease6Ptr& result) const;
 
 
 
 
@@ -556,9 +580,8 @@ private:
     /// were affected.
     /// were affected.
     ///
     ///
     /// @param stindex Index of prepared statement to be executed
     /// @param stindex Index of prepared statement to be executed
-    /// @param BindParams Array of PostgreSQL objects representing the parameters.
-    ///        (Note that the number is determined by the number of parameters
-    ///        in the statement.)
+    /// @param bind_array array containing lease values and where clause
+    /// parameters for the update.
     /// @param lease Pointer to the lease object whose record is being updated.
     /// @param lease Pointer to the lease object whose record is being updated.
     ///
     ///
     /// @throw NoSuchLease Could not update a lease because no lease matches
     /// @throw NoSuchLease Could not update a lease because no lease matches
@@ -566,7 +589,7 @@ private:
     /// @throw isc::dhcp::DbOperationError An operation on the open database has
     /// @throw isc::dhcp::DbOperationError An operation on the open database has
     ///        failed.
     ///        failed.
     template <typename LeasePtr>
     template <typename LeasePtr>
-    void updateLeaseCommon(StatementIndex stindex, BindParams& params,
+    void updateLeaseCommon(StatementIndex stindex, PsqlBindArray& bind_array,
                            const LeasePtr& lease);
                            const LeasePtr& lease);
 
 
     /// @brief Delete lease common code
     /// @brief Delete lease common code
@@ -576,16 +599,15 @@ private:
     /// see how many rows were deleted.
     /// see how many rows were deleted.
     ///
     ///
     /// @param stindex Index of prepared statement to be executed
     /// @param stindex Index of prepared statement to be executed
-    /// @param BindParams Array of PostgreSQL objects representing the parameters.
-    ///        (Note that the number is determined by the number of parameters
-    ///        in the statement.)
+    /// @param bind_array array containing lease values and where clause
+    /// parameters for the delete
     ///
     ///
     /// @return true if one or more rows were deleted, false if none were
     /// @return true if one or more rows were deleted, false if none were
     ///         deleted.
     ///         deleted.
     ///
     ///
     /// @throw isc::dhcp::DbOperationError An operation on the open database has
     /// @throw isc::dhcp::DbOperationError An operation on the open database has
     ///        failed.
     ///        failed.
-    bool deleteLeaseCommon(StatementIndex stindex, BindParams& params);
+    bool deleteLeaseCommon(StatementIndex stindex, PsqlBindArray& bind_array);
 
 
     /// The exchange objects are used for transfer of data to/from the database.
     /// The exchange objects are used for transfer of data to/from the database.
     /// They are pointed-to objects as the contents may change in "const" calls,
     /// They are pointed-to objects as the contents may change in "const" calls,
@@ -594,9 +616,6 @@ private:
     boost::scoped_ptr<PgSqlLease4Exchange> exchange4_; ///< Exchange object
     boost::scoped_ptr<PgSqlLease4Exchange> exchange4_; ///< Exchange object
     boost::scoped_ptr<PgSqlLease6Exchange> exchange6_; ///< Exchange object
     boost::scoped_ptr<PgSqlLease6Exchange> exchange6_; ///< Exchange object
 
 
-    /// A vector of compiled SQL statements
-    std::vector<PgSqlStatementBind> statements_;
-
     /// PostgreSQL connection handle
     /// PostgreSQL connection handle
     PGconn* conn_;
     PGconn* conn_;
 };
 };

+ 58 - 0
src/lib/dhcpsrv/tests/generic_lease_mgr_unittest.cc

@@ -683,6 +683,29 @@ GenericLeaseMgrTest::testAddGetDelete6(bool check_t1_t2) {
 }
 }
 
 
 void
 void
+GenericLeaseMgrTest::testMaxDate4() {
+    // Get the leases to be used for the test.
+    vector<Lease4Ptr> leases = createLeases4();
+    Lease4Ptr lease = leases[1];
+
+    // Set valid_lft_ to 1 day, cllt_ to max time. This should make expire
+    // time too large to store.
+    lease->valid_lft_ = 24*60*60;
+    lease->cltt_ = LeaseMgr::MAX_DB_TIME;
+
+    // Insert should throw.
+    ASSERT_THROW(lmptr_->addLease(leases[1]), DbOperationError);
+
+    // Set valid_lft_ to 0, which should make expire time small enough to
+    // store and try again.
+    lease->valid_lft_ = 0;
+    EXPECT_TRUE(lmptr_->addLease(leases[1]));
+    Lease4Ptr l_returned = lmptr_->getLease4(ioaddress4_[1]);
+    ASSERT_TRUE(l_returned);
+    detailCompareLease(leases[1], l_returned);
+}
+
+void
 GenericLeaseMgrTest::testBasicLease4() {
 GenericLeaseMgrTest::testBasicLease4() {
     // Get the leases to be used for the test.
     // Get the leases to be used for the test.
     vector<Lease4Ptr> leases = createLeases4();
     vector<Lease4Ptr> leases = createLeases4();
@@ -829,6 +852,29 @@ GenericLeaseMgrTest::testBasicLease6() {
 }
 }
 
 
 void
 void
+GenericLeaseMgrTest::testMaxDate6() {
+    // Get the leases to be used for the test.
+    vector<Lease6Ptr> leases = createLeases6();
+    Lease6Ptr lease = leases[1];
+
+    // Set valid_lft_ to 1 day, cllt_ to max time. This should make expire
+    // time too large to store.
+    lease->valid_lft_ = 24*60*60;
+    lease->cltt_ = LeaseMgr::MAX_DB_TIME;
+
+    // Insert should throw.
+    ASSERT_THROW(lmptr_->addLease(leases[1]), DbOperationError);
+
+    // Set valid_lft_ to 0, which should make expire time small enough to
+    // store and try again.
+    lease->valid_lft_ = 0;
+    EXPECT_TRUE(lmptr_->addLease(leases[1]));
+    Lease6Ptr l_returned = lmptr_->getLease6(leasetype6_[1], ioaddress6_[1]);
+    ASSERT_TRUE(l_returned);
+    detailCompareLease(leases[1], l_returned);
+}
+
+void
 GenericLeaseMgrTest::testLease4InvalidHostname() {
 GenericLeaseMgrTest::testLease4InvalidHostname() {
     // Get the leases to be used for the test.
     // Get the leases to be used for the test.
     vector<Lease4Ptr> leases = createLeases4();
     vector<Lease4Ptr> leases = createLeases4();
@@ -1506,6 +1552,18 @@ GenericLeaseMgrTest::testRecreateLease6() {
     detailCompareLease(lease, l_returned);
     detailCompareLease(lease, l_returned);
 }
 }
 
 
+void
+GenericLeaseMgrTest::testNullDuid() {
+    // Create leases, although we need only one.
+    vector<Lease6Ptr> leases = createLeases6();
+
+    // Set DUID to empty pointer.
+    leases[1]->duid_.reset();
+
+    // Insert should throw.
+    ASSERT_THROW(lmptr_->addLease(leases[1]), DbOperationError);
+}
+
 
 
 }; // namespace test
 }; // namespace test
 }; // namespace dhcp
 }; // namespace dhcp

+ 10 - 0
src/lib/dhcpsrv/tests/generic_lease_mgr_unittest.h

@@ -105,6 +105,9 @@ public:
     /// @brief checks that addLease, getLease4(addr) and deleteLease() works
     /// @brief checks that addLease, getLease4(addr) and deleteLease() works
     void testBasicLease4();
     void testBasicLease4();
 
 
+    /// @brief checks that invalid dates are safely handled.
+    void testMaxDate4();
+
     /// @brief Test lease retrieval using client id.
     /// @brief Test lease retrieval using client id.
     void testGetLease4ClientId();
     void testGetLease4ClientId();
 
 
@@ -180,6 +183,10 @@ public:
     /// IPv6 address) works.
     /// IPv6 address) works.
     void testBasicLease6();
     void testBasicLease6();
 
 
+    /// @brief checks that invalid dates are safely handled.
+    void testMaxDate6();
+
+
     /// @brief Test that IPv6 lease can be added, retrieved and deleted.
     /// @brief Test that IPv6 lease can be added, retrieved and deleted.
     ///
     ///
     /// This method checks basic IPv6 lease operations. There's check_t1_t2
     /// This method checks basic IPv6 lease operations. There's check_t1_t2
@@ -245,6 +252,9 @@ public:
     /// persistent storage has been updated as expected.
     /// persistent storage has been updated as expected.
     void testRecreateLease6();
     void testRecreateLease6();
 
 
+    /// @brief Verifies that a null DUID is not allowed.
+    void testNullDuid();
+
     /// @brief String forms of IPv4 addresses
     /// @brief String forms of IPv4 addresses
     std::vector<std::string>  straddress4_;
     std::vector<std::string>  straddress4_;
 
 

+ 10 - 0
src/lib/dhcpsrv/tests/memfile_lease_mgr_unittest.cc

@@ -411,4 +411,14 @@ TEST_F(MemfileLeaseMgrTest, testRecreateLease6) {
 // testGetLease4HWAddrSubnetIdSize() - memfile just keeps Lease structure
 // testGetLease4HWAddrSubnetIdSize() - memfile just keeps Lease structure
 //     and does not do any checks of HWAddr content
 //     and does not do any checks of HWAddr content
 
 
+/// @brief Checks that null DUID is not allowed.
+/// Test is disabled as Memfile does not currently defend against a null DUID.
+TEST_F(MemfileLeaseMgrTest, DISABLED_nullDuid) {
+    // Create leases, although we need only one.
+    vector<Lease6Ptr> leases = createLeases6();
+
+    leases[1]->duid_.reset();
+    ASSERT_THROW(lmptr_->addLease(leases[1]), DbOperationError);
+}
+
 }; // end of anonymous namespace
 }; // end of anonymous namespace

+ 16 - 0
src/lib/dhcpsrv/tests/mysql_lease_mgr_unittest.cc

@@ -333,6 +333,11 @@ TEST_F(MySqlLeaseMgrTest, basicLease4) {
     testBasicLease4();
     testBasicLease4();
 }
 }
 
 
+/// @brief Check that Lease4 code safely handles invalid dates.
+TEST_F(MySqlLeaseMgrTest, maxDate4) {
+    testMaxDate4();
+}
+
 /// @brief Lease4 update tests
 /// @brief Lease4 update tests
 ///
 ///
 /// Checks that we are able to update a lease in the database.
 /// Checks that we are able to update a lease in the database.
@@ -437,6 +442,11 @@ TEST_F(MySqlLeaseMgrTest, basicLease6) {
     testBasicLease6();
     testBasicLease6();
 }
 }
 
 
+/// @brief Check that Lease6 code safely handles invalid dates.
+TEST_F(MySqlLeaseMgrTest, maxDate6) {
+    testMaxDate6();
+}
+
 /// @brief Verify that too long hostname for Lease6 is not accepted.
 /// @brief Verify that too long hostname for Lease6 is not accepted.
 ///
 ///
 /// Checks that the it is not possible to create a lease when the hostname
 /// Checks that the it is not possible to create a lease when the hostname
@@ -506,4 +516,10 @@ TEST_F(MySqlLeaseMgrTest, testRecreateLease6) {
     testRecreateLease6();
     testRecreateLease6();
 }
 }
 
 
+/// @brief Checks that null DUID is not allowed.
+/// Test is disabled as MySqlLeaseMgr does not currently defend against a null DUID.
+TEST_F(MySqlLeaseMgrTest, DISABLED_nullDuid) {
+    testNullDuid();
+}
+
 }; // Of anonymous namespace
 }; // Of anonymous namespace

+ 18 - 6
src/lib/dhcpsrv/tests/pgsql_lease_mgr_unittest.cc

@@ -110,14 +110,13 @@ validConnectionString() {
 // tests will (should) fall over.
 // tests will (should) fall over.
 void destroySchema() {
 void destroySchema() {
     // Open database
     // Open database
-    PGconn * conn = 0;
+    PGconn* conn = 0;
     conn = PQconnectdb("host = 'localhost' user = 'keatest'"
     conn = PQconnectdb("host = 'localhost' user = 'keatest'"
                        " password = 'keatest' dbname = 'keatest'");
                        " password = 'keatest' dbname = 'keatest'");
 
 
-    PGresult * r;
     // Get rid of everything in it.
     // Get rid of everything in it.
     for (int i = 0; destroy_statement[i] != NULL; ++i) {
     for (int i = 0; destroy_statement[i] != NULL; ++i) {
-        r = PQexec(conn, destroy_statement[i]);
+        PGresult* r = PQexec(conn, destroy_statement[i]);
         PQclear(r);
         PQclear(r);
     }
     }
 
 
@@ -132,14 +131,13 @@ void destroySchema() {
 // will fall over.
 // will fall over.
 void createSchema() {
 void createSchema() {
     // Open database
     // Open database
-    PGconn * conn = 0;
+    PGconn* conn = 0;
     conn = PQconnectdb("host = 'localhost' user = 'keatest'"
     conn = PQconnectdb("host = 'localhost' user = 'keatest'"
                        " password = 'keatest' dbname = 'keatest'");
                        " password = 'keatest' dbname = 'keatest'");
 
 
-    PGresult * r;
     // Get rid of everything in it.
     // Get rid of everything in it.
     for (int i = 0; create_statement[i] != NULL; ++i) {
     for (int i = 0; create_statement[i] != NULL; ++i) {
-        r = PQexec(conn, create_statement[i]);
+        PGresult* r = PQexec(conn, create_statement[i]);
         PQclear(r);
         PQclear(r);
     }
     }
 
 
@@ -301,6 +299,11 @@ TEST_F(PgSqlLeaseMgrTest, basicLease4) {
     testBasicLease4();
     testBasicLease4();
 }
 }
 
 
+/// @brief Check that Lease4 code safely handles invalid dates.
+TEST_F(PgSqlLeaseMgrTest, maxDate4) {
+    testMaxDate4();
+}
+
 /// @brief Lease4 update tests
 /// @brief Lease4 update tests
 ///
 ///
 /// Checks that we are able to update a lease in the database.
 /// Checks that we are able to update a lease in the database.
@@ -405,6 +408,11 @@ TEST_F(PgSqlLeaseMgrTest, basicLease6) {
     testBasicLease6();
     testBasicLease6();
 }
 }
 
 
+/// @brief Check that Lease6 code safely handles invalid dates.
+TEST_F(PgSqlLeaseMgrTest, maxDate6) {
+    testMaxDate6();
+}
+
 /// @brief Verify that too long hostname for Lease6 is not accepted.
 /// @brief Verify that too long hostname for Lease6 is not accepted.
 ///
 ///
 /// Checks that the it is not possible to create a lease when the hostname
 /// Checks that the it is not possible to create a lease when the hostname
@@ -456,4 +464,8 @@ TEST_F(PgSqlLeaseMgrTest, updateLease6) {
     testUpdateLease6();
     testUpdateLease6();
 }
 }
 
 
+TEST_F(PgSqlLeaseMgrTest, nullDuid) {
+    testNullDuid();
+}
+
 };
 };