Commit d23cde8c authored by Jelte Jansen's avatar Jelte Jansen
Browse files

[trac1062] initial addition of searchForRecords and getNextRecord

parent 885d7987
......@@ -71,6 +71,29 @@ public:
* an opaque handle.
*/
virtual std::pair<bool, int> getZone(const isc::dns::Name& name) const = 0;
/**
* \brief Starts a new search for records of the given name in the given zone
*
* \param zone_id The zone to search in, as returned by getZone()
* \param name The name of the records to find
*/
virtual void searchForRecords(int zone_id, const std::string& name) const = 0;
/**
* \brief Retrieves the next record from the search started with searchForRecords()
*
* Returns a boolean specifying whether or not there was more data to read.
* In the case of a database error, a DatasourceError is thrown.
*
* \exception DatasourceError if there was an error reading from the database
*
* \param columns This vector will be cleared, and the fields of the record will
* be appended here as strings (in the order rdtype, ttl, sigtype,
* and rdata). If there was no data, the vector is untouched.
* \return true if there was a next record, false if there was not
*/
virtual bool getNextRecord(std::vector<std::string>& columns) const = 0;
};
/**
......
......@@ -24,19 +24,20 @@ namespace datasrc {
struct SQLite3Parameters {
SQLite3Parameters() :
db_(NULL), version_(-1),
q_zone_(NULL) /*, q_record_(NULL), q_addrs_(NULL), q_referral_(NULL),
q_any_(NULL), q_count_(NULL), q_previous_(NULL), q_nsec3_(NULL),
q_zone_(NULL), q_any_(NULL)
/*q_record_(NULL), q_addrs_(NULL), q_referral_(NULL),
q_count_(NULL), q_previous_(NULL), q_nsec3_(NULL),
q_prevnsec3_(NULL) */
{}
sqlite3* db_;
int version_;
sqlite3_stmt* q_zone_;
sqlite3_stmt* q_any_;
/*
TODO: Yet unneeded statements
sqlite3_stmt* q_record_;
sqlite3_stmt* q_addrs_;
sqlite3_stmt* q_referral_;
sqlite3_stmt* q_any_;
sqlite3_stmt* q_count_;
sqlite3_stmt* q_previous_;
sqlite3_stmt* q_nsec3_;
......@@ -69,6 +70,9 @@ public:
if (params_.q_zone_ != NULL) {
sqlite3_finalize(params_.q_zone_);
}
if (params_.q_any_ != NULL) {
sqlite3_finalize(params_.q_any_);
}
/*
if (params_.q_record_ != NULL) {
sqlite3_finalize(params_.q_record_);
......@@ -79,9 +83,6 @@ public:
if (params_.q_referral_ != NULL) {
sqlite3_finalize(params_.q_referral_);
}
if (params_.q_any_ != NULL) {
sqlite3_finalize(params_.q_any_);
}
if (params_.q_count_ != NULL) {
sqlite3_finalize(params_.q_count_);
}
......@@ -132,6 +133,9 @@ const char* const SCHEMA_LIST[] = {
const char* const q_zone_str = "SELECT id FROM zones WHERE name=?1 AND rdclass = ?2";
const char* const q_any_str = "SELECT rdtype, ttl, sigtype, rdata "
"FROM records WHERE zone_id=?1 AND name=?2";
/* TODO: Prune the statements, not everything will be needed maybe?
const char* const q_record_str = "SELECT rdtype, ttl, sigtype, rdata "
"FROM records WHERE zone_id=?1 AND name=?2 AND "
......@@ -148,9 +152,6 @@ const char* const q_referral_str = "SELECT rdtype, ttl, sigtype, rdata FROM "
"(rdtype='NS' OR sigtype='NS' OR rdtype='DS' OR sigtype='DS' OR "
"rdtype='DNAME' OR sigtype='DNAME')";
const char* const q_any_str = "SELECT rdtype, ttl, sigtype, rdata "
"FROM records WHERE zone_id=?1 AND name=?2";
const char* const q_count_str = "SELECT COUNT(*) FROM records "
"WHERE zone_id=?1 AND rname LIKE (?2 || '%');";
......@@ -200,11 +201,11 @@ checkAndSetupSchema(Initializer* initializer) {
}
initializer->params_.q_zone_ = prepare(db, q_zone_str);
initializer->params_.q_any_ = prepare(db, q_any_str);
/* TODO: Yet unneeded statements
initializer->params_.q_record_ = prepare(db, q_record_str);
initializer->params_.q_addrs_ = prepare(db, q_addrs_str);
initializer->params_.q_referral_ = prepare(db, q_referral_str);
initializer->params_.q_any_ = prepare(db, q_any_str);
initializer->params_.q_count_ = prepare(db, q_count_str);
initializer->params_.q_previous_ = prepare(db, q_previous_str);
initializer->params_.q_nsec3_ = prepare(db, q_nsec3_str);
......@@ -252,6 +253,9 @@ SQLite3Connection::close(void) {
sqlite3_finalize(dbparameters_->q_zone_);
dbparameters_->q_zone_ = NULL;
sqlite3_finalize(dbparameters_->q_any_);
dbparameters_->q_any_ = NULL;
/* TODO: Once they are needed or not, uncomment or drop
sqlite3_finalize(dbparameters->q_record_);
dbparameters->q_record_ = NULL;
......@@ -262,9 +266,6 @@ SQLite3Connection::close(void) {
sqlite3_finalize(dbparameters->q_referral_);
dbparameters->q_referral_ = NULL;
sqlite3_finalize(dbparameters->q_any_);
dbparameters->q_any_ = NULL;
sqlite3_finalize(dbparameters->q_count_);
dbparameters->q_count_ = NULL;
......@@ -318,5 +319,51 @@ SQLite3Connection::getZone(const isc::dns::Name& name) const {
return (result);
}
void
SQLite3Connection::searchForRecords(int zone_id, const std::string& name) const {
sqlite3_reset(dbparameters_->q_any_);
sqlite3_clear_bindings(dbparameters_->q_any_);
sqlite3_bind_int(dbparameters_->q_any_, 1, zone_id);
// use transient since name is a ref and may disappear
sqlite3_bind_text(dbparameters_->q_any_, 2, name.c_str(), -1,
SQLITE_TRANSIENT);
};
namespace {
const char*
convertToPlainChar(const unsigned char* ucp) {
if (ucp == NULL) {
return ("");
}
const void* p = ucp;
return (static_cast<const char*>(p));
}
}
bool
SQLite3Connection::getNextRecord(std::vector<std::string>& columns) const {
sqlite3_stmt* current_stmt = dbparameters_->q_any_;
const int rc = sqlite3_step(current_stmt);
if (rc == SQLITE_ROW) {
columns.clear();
for (int column = 0; column < 4; ++column) {
columns.push_back(convertToPlainChar(sqlite3_column_text(
current_stmt, column)));
}
return true;
} else if (rc == SQLITE_DONE) {
// reached the end of matching rows
sqlite3_reset(current_stmt);
sqlite3_clear_bindings(current_stmt);
return false;
}
sqlite3_reset(current_stmt);
isc_throw(DataSourceError, "Unexpected failure in sqlite3_step");
// Compilers might not realize isc_throw always throws
return false;
}
}
}
......@@ -88,6 +88,8 @@ public:
* element and the zone id in the second if it was.
*/
virtual std::pair<bool, int> getZone(const isc::dns::Name& name) const;
virtual void searchForRecords(int zone_id, const std::string& name) const;
virtual bool getNextRecord(std::vector<std::string>& columns) const;
private:
/// \brief Private database data
SQLite3Parameters* dbparameters_;
......
......@@ -39,6 +39,8 @@ public:
return (std::pair<bool, int>(false, 0));
}
}
virtual void searchForRecords(int, const std::string&) const {};
virtual bool getNextRecord(std::vector<std::string>&) const { return false; };
};
class DatabaseClientTest : public ::testing::Test {
......
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