"SELECT address, duid, valid_lifetime, "
"expire, subnet_id, pref_lifetime, "
"lease_type, iaid, prefix_len "
- "FROM lease6 WHERE address = ?");
+ "FROM lease6 "
+ "WHERE address = ?");
prepareStatement(GET_LEASE6_DUID_IAID,
"SELECT address, duid, valid_lifetime, "
"expire, subnet_id, pref_lifetime, "
"lease_type, iaid, prefix_len "
- "FROM lease6 WHERE duid = ? AND iaid = ?");
+ "FROM lease6 "
+ "WHERE duid = ? AND iaid = ?");
+ prepareStatement(GET_LEASE6_DUID_IAID_SUBID,
+ "SELECT address, duid, valid_lifetime, "
+ "expire, subnet_id, pref_lifetime, "
+ "lease_type, iaid, prefix_len "
+ "FROM lease6 "
+ "WHERE duid = ? AND iaid = ? AND subnet_id = ?");
prepareStatement(GET_VERSION,
"SELECT version, minor FROM schema_version");
prepareStatement(INSERT_LEASE6,
"INSERT INTO lease6(address, duid, valid_lifetime, "
"expire, subnet_id, pref_lifetime, "
"lease_type, iaid, prefix_len) "
- "VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?)");
+ "VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?)");
prepareStatement(UPDATE_LEASE6,
"UPDATE lease6 SET address = ?, duid = ?, "
"valid_lifetime = ?, expire = ?, subnet_id = ?, "
"pref_lifetime = ?, lease_type = ?, iaid = ?, "
- "prefix_len = ? WHERE address = ?");
+ "prefix_len = ? "
+ "WHERE address = ?");
}
bool
}
Lease6Ptr
-MySqlLeaseMgr::getLease6(const DUID& /* duid */, uint32_t /* iaid */,
- SubnetID /* subnet_id */) const {
- isc_throw(NotImplemented, "MySqlLeaseMgr::getLease4(const DUID&, SubnetID) "
- "not implemented yet");
- return (Lease6Ptr());
+MySqlLeaseMgr::getLease6(const DUID& duid, uint32_t iaid,
+ SubnetID subnet_id) const {
+ // Set up the WHERE clause value
+ MYSQL_BIND inbind[3];
+ memset(inbind, 0, sizeof(inbind));
+
+ // DUID. The complex casting is needed to obtain the "const" vector of
+ // uint8_t from the DUID, point to the start of it (discarding the
+ // "const"ness) and finally casing it to "char*" for the MySQL buffer
+ // element.
+ const vector<uint8_t>& duid_vector = duid.getDuid();
+ unsigned long duid_length = duid_vector.size();
+ inbind[0].buffer_type = MYSQL_TYPE_BLOB;
+ inbind[0].buffer = reinterpret_cast<char*>(
+ const_cast<uint8_t*>(&duid_vector[0]));
+ inbind[0].buffer_length = duid_length;
+ inbind[0].length = &duid_length;
+
+ // IAID
+ inbind[1].buffer_type = MYSQL_TYPE_LONG;
+ inbind[1].buffer = reinterpret_cast<char*>(&iaid);
+ inbind[1].is_unsigned = static_cast<my_bool>(1);
+
+ // Subnet ID
+ inbind[2].buffer_type = MYSQL_TYPE_LONG;
+ inbind[2].buffer = reinterpret_cast<char*>(&subnet_id);
+ inbind[2].is_unsigned = static_cast<my_bool>(1);
+
+ // Bind the input parameters to the statement
+ int status = mysql_stmt_bind_param(statements_[GET_LEASE6_DUID_IAID_SUBID], inbind);
+ checkError(status, GET_LEASE6_DUID_IAID_SUBID, "unable to bind WHERE clause parameter");
+
+ // Set up the SELECT clause
+ MySqlLease6Exchange exchange;
+ std::vector<MYSQL_BIND> outbind;
+ exchange.createBindForReceive(outbind);
+
+ // Bind the output parameters to the statement
+ status = mysql_stmt_bind_result(statements_[GET_LEASE6_DUID_IAID_SUBID], &outbind[0]);
+ checkError(status, GET_LEASE6_DUID_IAID_SUBID, "unable to bind SELECT clause parameters");
+
+ // Execute the query.
+ status = mysql_stmt_execute(statements_[GET_LEASE6_DUID_IAID_SUBID]);
+ checkError(status, GET_LEASE6_DUID_IAID_SUBID, "unable to execute");
+
+ Lease6Ptr result;
+ status = mysql_stmt_fetch(statements_[GET_LEASE6_DUID_IAID_SUBID]);
+ if (status == 0) {
+ try {
+ result = exchange.getLeaseData();
+
+ // TODO: check for more than one row returned. At present, just ignore
+ // the excess and take the first.
+
+ } catch (const isc::BadValue& ex) {
+ // Free up result set.
+
+ (void) mysql_stmt_free_result(statements_[GET_LEASE6_DUID_IAID_SUBID]);
+ // Lease type is returned, to rethrow the exception with a bit
+ // more data.
+ isc_throw(BadValue, ex.what() << ". Statement is <" <<
+ text_statements_[GET_LEASE6_DUID_IAID_SUBID] << ">");
+ }
+
+ // As the address is the primary key in the table, we can't return
+ // two rows, so we don't bother checking whether multiple rows have
+ // been returned.
+
+ } else if (status == 1) {
+ checkError(status, GET_LEASE6_DUID_IAID_SUBID, "unable to fetch results");
+
+ } else {
+ // @TODO Handle truncation
+ // We are ignoring truncation for now, so the only other result is
+ // no data was found. In that case, we return a null Lease6 structure.
+ // This has already been set, so the action is a no-op.
+ }
+
+ // Free data structures associated with information returned.
+ (void) mysql_stmt_free_result(statements_[GET_LEASE6_DUID_IAID_SUBID]);
+ return (result);
}
void
detailCompareLease6(leases[2], l_returned);
}
-
// @brief Check GetLease6 methods - Access by DUID/IAID
//
// Adds leases to the database and checks that they can be accessed via
EXPECT_EQ(L1_ADDRESS, addresses[0]);
EXPECT_EQ(L4_ADDRESS, addresses[1]);
EXPECT_EQ(L5_ADDRESS, addresses[2]);
+
+ // Check that nothing is returned when either the IAID or DUID match
+ // nothing.
+ returned = lmptr_->getLease6(*leases[1]->duid_, leases[1]->iaid_ + 1);
+ EXPECT_EQ(0, returned.size());
+
+ // Alter the leases[1] DUID to match nothing in the database.
+ vector<uint8_t> duid_vector = leases[1]->duid_->getDuid();
+ ++duid_vector[0];
+ DUID new_duid(duid_vector);
+ returned = lmptr_->getLease6(new_duid, leases[1]->iaid_);
+ EXPECT_EQ(0, returned.size());
+}
+
+
+
+// @brief Check GetLease6 methods - Access by DUID/IAID/SubnetID
+//
+// Adds leases to the database and checks that they can be accessed via
+// a combination of DIUID and IAID.
+TEST_F(MySqlLeaseMgrTest, GetLease6Extended2) {
+ // Get the leases to be used for the test.
+ vector<Lease6Ptr> leases = createLeases6();
+ EXPECT_LE(6, leases.size()); // Expect to access leases 0 through 5
+
+ // Add them to the database
+ for (int i = 0; i < leases.size(); ++i) {
+ EXPECT_TRUE(lmptr_->addLease(leases[i]));
+ }
+
+ // Get the leases matching the DUID and IAID of lease[1].
+ Lease6Ptr returned = lmptr_->getLease6(*leases[1]->duid_,
+ leases[1]->iaid_,
+ leases[1]->subnet_id_);
+ ASSERT_TRUE(returned);
+ EXPECT_TRUE(*returned == *leases[1]);
+
+ // Modify each of the three parameters (DUID, IAID, Subnet ID) and
+ // check that nothing is returned.
+ returned = lmptr_->getLease6(*leases[1]->duid_, leases[1]->iaid_ + 1,
+ leases[1]->subnet_id_);
+ EXPECT_FALSE(returned);
+
+ returned = lmptr_->getLease6(*leases[1]->duid_, leases[1]->iaid_,
+ leases[1]->subnet_id_ + 1);
+ EXPECT_FALSE(returned);
+
+ // Alter the leases[1] DUID to match nothing in the database.
+ vector<uint8_t> duid_vector = leases[1]->duid_->getDuid();
+ ++duid_vector[0];
+ DUID new_duid(duid_vector);
+ returned = lmptr_->getLease6(new_duid, leases[1]->iaid_,
+ leases[1]->subnet_id_);
+ EXPECT_FALSE(returned);
}