Commit 61feac83 authored by Stephen Morris's avatar Stephen Morris
Browse files

[1330] First test (index not in table) now passing

parent 01b4b95b
......@@ -52,7 +52,10 @@ enum StatementID {
DEL_RECORD = 8,
ITERATE = 9,
FIND_PREVIOUS = 10,
NUM_STATEMENTS = 11
LOW_DIFF_ID = 11,
HIGH_DIFF_ID = 12,
DIFFS = 13,
NUM_STATEMENTS = 14
};
const char* const text_statements[NUM_STATEMENTS] = {
......@@ -60,28 +63,39 @@ const char* const text_statements[NUM_STATEMENTS] = {
// specifically chosen to match the enum values in RecordColumns
"SELECT id FROM zones WHERE name=?1 AND rdclass = ?2", // ZONE
"SELECT rdtype, ttl, sigtype, rdata FROM records " // ANY
"WHERE zone_id=?1 AND name=?2",
"WHERE zone_id=?1 AND name=?2",
"SELECT rdtype, ttl, sigtype, rdata " // ANY_SUB
"FROM records WHERE zone_id=?1 AND name LIKE (\"%.\" || ?2)",
"FROM records WHERE zone_id=?1 AND name LIKE (\"%.\" || ?2)",
"BEGIN", // BEGIN
"COMMIT", // COMMIT
"ROLLBACK", // ROLLBACK
"DELETE FROM records WHERE zone_id=?1", // DEL_ZONE_RECORDS
"INSERT INTO records " // ADD_RECORD
"(zone_id, name, rname, ttl, rdtype, sigtype, rdata) "
"VALUES (?1, ?2, ?3, ?4, ?5, ?6, ?7)",
"(zone_id, name, rname, ttl, rdtype, sigtype, rdata) "
"VALUES (?1, ?2, ?3, ?4, ?5, ?6, ?7)",
"DELETE FROM records WHERE zone_id=?1 AND name=?2 " // DEL_RECORD
"AND rdtype=?3 AND rdata=?4",
"AND rdtype=?3 AND rdata=?4",
"SELECT rdtype, ttl, sigtype, rdata, name FROM records " // ITERATE
"WHERE zone_id = ?1 ORDER BY rname, rdtype",
"WHERE zone_id = ?1 ORDER BY rname, rdtype",
/*
* This one looks for previous name with NSEC record. It is done by
* using the reversed name. The NSEC is checked because we need to
* skip glue data, which don't have the NSEC.
*/
"SELECT name FROM records " // FIND_PREVIOUS
"WHERE zone_id=?1 AND rdtype = 'NSEC' AND "
"rname < $2 ORDER BY rname DESC LIMIT 1"
"WHERE zone_id=?1 AND rdtype = 'NSEC' AND "
"rname < $2 ORDER BY rname DESC LIMIT 1",
// Two statements to select the lowest ID and highest ID in a set of
// differences.
"SELECT id FROM diffs " // LOW_DIFF_ID
"WHERE zone_id=?1 AND version=?2 and OPERATION=0 "
"ORDER BY id ASC LIMIT 1",
"SELECT id FROM diffs " // LOW_DIFF_ID
"WHERE zone_id=?1 AND version=?2 and OPERATION=1 "
"ORDER BY id DESC LIMIT 1",
"SELECT name, rrtype, ttl, rdata FROM diffs " // DIFFS
"WHERE zone_id=?1 AND id>=?2 and id<=?3"
};
struct SQLite3Parameters {
......@@ -194,18 +208,26 @@ const char* const SCHEMA_LIST[] = {
"dnssec BOOLEAN NOT NULL DEFAULT 0)",
"CREATE INDEX zones_byname ON zones (name)",
"CREATE TABLE records (id INTEGER PRIMARY KEY, "
"zone_id INTEGER NOT NULL, name STRING NOT NULL COLLATE NOCASE, "
"rname STRING NOT NULL COLLATE NOCASE, ttl INTEGER NOT NULL, "
"rdtype STRING NOT NULL COLLATE NOCASE, sigtype STRING COLLATE NOCASE, "
"rdata STRING NOT NULL)",
"zone_id INTEGER NOT NULL, name STRING NOT NULL COLLATE NOCASE, "
"rname STRING NOT NULL COLLATE NOCASE, ttl INTEGER NOT NULL, "
"rdtype STRING NOT NULL COLLATE NOCASE, sigtype STRING COLLATE NOCASE, "
"rdata STRING NOT NULL)",
"CREATE INDEX records_byname ON records (name)",
"CREATE INDEX records_byrname ON records (rname)",
"CREATE TABLE nsec3 (id INTEGER PRIMARY KEY, zone_id INTEGER NOT NULL, "
"hash STRING NOT NULL COLLATE NOCASE, "
"owner STRING NOT NULL COLLATE NOCASE, "
"ttl INTEGER NOT NULL, rdtype STRING NOT NULL COLLATE NOCASE, "
"rdata STRING NOT NULL)",
"hash STRING NOT NULL COLLATE NOCASE, "
"owner STRING NOT NULL COLLATE NOCASE, "
"ttl INTEGER NOT NULL, rdtype STRING NOT NULL COLLATE NOCASE, "
"rdata STRING NOT NULL)",
"CREATE INDEX nsec3_byhash ON nsec3 (hash)",
"CREATE TABLE diffs (id INTEGER PRIMARY KEY AUTOINCREMENT,"
"zone_id INTEGER NOT NULL, "
"version INTEGER NOT NULL, "
"operation INTEGER NOT NULL, "
"name STRING NOT NULL COLLATE NOCASE, "
"rrtype STRING NOT NULL COLLATE NOCASE, "
"ttl INTEGER NOT NULL, "
"rdata STRING NOT NULL)",
NULL
};
......@@ -551,9 +573,13 @@ class SQLite3Accessor::DiffContext : public DatabaseAccessor::IteratorContext {
public:
// Construct an iterator for difference records.
DiffContext(const boost::shared_ptr<const SQLite3Accessor>&, int,
uint32_t, uint32_t)
DiffContext(const boost::shared_ptr<const SQLite3Accessor>& accessor,
int id, int start, int end) :
accessor_(accessor)
{
int low_id = findIndex(LOW_DIFF_ID, id, start);
int high_id = findIndex(HIGH_DIFF_ID, id, end);
std::cout << "Low index is " << low_id << ", high index is " << high_id << "\n";
}
virtual ~DiffContext() {}
......@@ -563,6 +589,99 @@ public:
return (false);
}
private:
/// \brief Clear Statement Bindings
///
/// Clears the bindings of variables in a prepared statement and resets
/// them to null.
///
/// \param stindex Index of prepared statement to which to bind
void clearBindings(int stindex) {
if (sqlite3_clear_bindings(accessor_->dbparameters_->statements_[stindex])
!= SQLITE_OK) {
isc_throw(SQLite3Error, "Could not clear SQL statement bindings in '" <<
text_statements[stindex] << "': " <<
sqlite3_errmsg(accessor_->dbparameters_->db_));
}
}
/// \brief Bind Int
///
/// Binds an integer to a specific variable in a prepared statement.
///
/// \param stindex Index of prepared statement to which to bind
/// \param varindex Index of variable to which to bind
/// \param value Value of variable to bind
/// \exception SQLite3Error on an error
void bindInt(int stindex, int varindex, int value) {
if (sqlite3_bind_int(accessor_->dbparameters_->statements_[stindex],
varindex, value) != SQLITE_OK) {
isc_throw(SQLite3Error, "Could not bind value to parameter " <<
varindex << " in statement '" <<
text_statements[stindex] << "': " <<
sqlite3_errmsg(accessor_->dbparameters_->db_));
}
}
/// \brief Find index
///
/// Executes the prepared statement locating the high or low index in
/// the diffs table and returns that index.
///
/// \param stmt_id Index of the prepared statement to execute
/// \param zone_id ID of the zone for which the index is being sought
/// \param serial Zone serial number for which an index is being sought.
///
/// \return int ID of the row in the difss table corresponding to the
/// statement.
///
/// \exception NoSuchSerial Serial number not found
int findIndex(StatementID stindex, int zone_id, uint32_t serial) {
// Set up the statement
clearBindings(stindex);
bindInt(stindex, 1, zone_id);
bindInt(stindex, 2, serial);
// Get a pointer to the statement for brevity (does not transfer resources)
sqlite3_stmt* stmt = accessor_->dbparameters_->statements_[stindex];
// Execute the data. Should be just one result
int rc = sqlite3_step(stmt);
int result = -1;
if (rc == SQLITE_ROW) {
// Got some data, extract the value
result = sqlite3_column_int(stmt, 1);
int rc = sqlite3_step(stmt);
if (rc == SQLITE_DONE) {
// That was the only data, OK to return. Tidy up as we go,
// ignoring any error return.
rc = sqlite3_reset(stmt);
} else if (rc == SQLITE_ROW) {
isc_throw(DataSourceError, "request to return one value from "
"diffs table for serial " << serial << " (zone ID " <<
zone_id << ") returned multiple values");
}
} else if (rc == SQLITE_DONE) {
// No data in the table for this zone and version. Note that.
isc_throw(NoSuchSerial, "no data on serial number " << serial <<
" for zone ID " << zone_id);
}
if (rc != SQLITE_OK) {
isc_throw(DataSourceError, "could not get data from diffs table: " <<
sqlite3_errmsg(accessor_->dbparameters_->db_));
}
return (result);
}
boost::shared_ptr<const SQLite3Accessor> accessor_; // Accessor object
};
// ... and return the iterator
......
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