Commit 0ece8832 authored by Jelte Jansen's avatar Jelte Jansen
Browse files

[2541] addZone in SQLite3Accessor

parent 00554310
......@@ -78,7 +78,8 @@ enum StatementID {
ADD_NSEC3_RECORD = 19,
DEL_ZONE_NSEC3_RECORDS = 20,
DEL_NSEC3_RECORD = 21,
NUM_STATEMENTS = 22
ADD_ZONE = 22,
NUM_STATEMENTS = 23
};
const char* const text_statements[NUM_STATEMENTS] = {
......@@ -161,7 +162,10 @@ const char* const text_statements[NUM_STATEMENTS] = {
"DELETE FROM nsec3 WHERE zone_id=?1",
// DEL_NSEC3_RECORD: delete specified NSEC3-related records
"DELETE FROM nsec3 WHERE zone_id=?1 AND hash=?2 "
"AND rdtype=?3 AND rdata=?4"
"AND rdtype=?3 AND rdata=?4",
// ADD_ZONE: add a zone to the zones table
"INSERT INTO zones (name, rdclass) VALUES (?1, ?2)" // ADD_ZONE
};
struct SQLite3Parameters {
......@@ -612,6 +616,33 @@ SQLite3Accessor::getZone(const std::string& name) const {
return (std::pair<bool, int>(false, 0));
}
int
SQLite3Accessor::addZone(const std::string& zone_name) {
// Transaction should have been started by the caller
if (!dbparameters_->in_transaction) {
isc_throw(DataSourceError, "performing addZone on SQLite3 "
"data source without transaction");
}
// First check if the zone exists, if it does, do nothing and
// return false
std::pair<bool, int> getzone_result = getZone(zone_name);
if (getzone_result.first) {
return (getzone_result.second);
}
StatementProcessor proc(*dbparameters_, ADD_ZONE, "add zone");
proc.bindText(1, zone_name.c_str(), SQLITE_TRANSIENT);
proc.bindText(2, class_.c_str(), SQLITE_TRANSIENT);
proc.exec();
// There are tricks to getting this in one go, but it is safer
// to do a new lookup
getzone_result = getZone(zone_name);
assert(getzone_result.first);
return (getzone_result.second);
}
namespace {
// Conversion to plain char
......
......@@ -131,6 +131,31 @@ public:
*/
virtual std::pair<bool, int> getZone(const std::string& name) const;
/**
* \brief Add a zone
*
* This implements the addZone from DatabaseAccessor and adds an (empty)
* zone into the zones table. If the zone exists already, nothing is done,
* and the id of the existing zone is returned. Otherwise, the zone is
* created, and its id is returned (unless it raises an exception).
*
* The class of the newly created zone is the class passed at construction
* time of the accessor.
*
* Because this method performs a lookup and probably an assert, it
* requires a transaction has been started (with \c beginTransaction)
* by the caller.
*
* \exception DataSourceError if no transaction is active, or if there
* is an SQLite3 error when performing the
* queries.
*
* \param zone_name The origin name of the zone to add
* \return the id of the zone (either an existing one if the zone exists
* already, or the id of the newly created zone).
*/
virtual int addZone(const std::string& zone_name);
/** \brief Look up all resource records for a name
*
* This implements the getRecords() method from DatabaseAccessor
......
......@@ -667,6 +667,42 @@ TEST_F(SQLite3Create, creationtest) {
ASSERT_TRUE(isReadable(SQLITE_NEW_DBFILE));
}
// Test addZone works. This is done on the 'createtest' fixture so we
// can easily be sure it does not exist yet.
TEST_F(SQLite3Create, addZone) {
// Need shared_ptr for the getAllRecords at the end of the test
boost::shared_ptr<SQLite3Accessor> accessor(
new SQLite3Accessor(SQLITE_NEW_DBFILE, "IN"));
const std::string zone_name("example.com");
const std::pair<bool, int> zone_info(accessor->getZone(zone_name));
ASSERT_FALSE(zone_info.first);
// Calling addZone without transaction should fail
ASSERT_THROW(accessor->addZone(zone_name), DataSourceError);
// Add the zone. Since it does not exist yet, it should return true
accessor->startTransaction();
const int new_zone_id = accessor->addZone(zone_name);
accessor->commit();
// Calling addZone again should return the same zone id
accessor->startTransaction();
ASSERT_EQ(new_zone_id, accessor->addZone(zone_name));
accessor->rollback();
// Check that it exists now, but has no records at this point
const std::pair<bool, int> zone_info2(accessor->getZone(zone_name));
ASSERT_TRUE(zone_info2.first);
ASSERT_EQ(new_zone_id, zone_info2.second);
DatabaseAccessor::IteratorContextPtr context =
accessor->getAllRecords(zone_info2.second);
string data[DatabaseAccessor::COLUMN_COUNT];
ASSERT_NE(DatabaseAccessor::IteratorContextPtr(), context);
EXPECT_FALSE(context->getNext(data));
}
TEST_F(SQLite3Create, emptytest) {
ASSERT_FALSE(isReadable(SQLITE_NEW_DBFILE));
......
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment