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_ZONE = 22,
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));
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);
// There are tricks to getting this in one go, but it is safer
// to do a new lookup
getzone_result = getZone(zone_name);
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) {
// 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("");
const std::pair<bool, int> zone_info(accessor->getZone(zone_name));
// 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
const int new_zone_id = accessor->addZone(zone_name);
// Calling addZone again should return the same zone id
ASSERT_EQ(new_zone_id, accessor->addZone(zone_name));
// Check that it exists now, but has no records at this point
const std::pair<bool, int> zone_info2(accessor->getZone(zone_name));
ASSERT_EQ(new_zone_id, zone_info2.second);
DatabaseAccessor::IteratorContextPtr context =
string data[DatabaseAccessor::COLUMN_COUNT];
ASSERT_NE(DatabaseAccessor::IteratorContextPtr(), context);
TEST_F(SQLite3Create, emptytest) {
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