Commit daedcaea authored by Mukund Sivaraman's avatar Mukund Sivaraman
Browse files

Merge branch 'trac1899_2'

parents 432064bc f5bd1368
......@@ -193,10 +193,17 @@ UPGRADES = [
"ALTER TABLE schema_version " +
"ADD COLUMN minor INTEGER NOT NULL DEFAULT 0"
]
},
{'from': (2, 0), 'to': (2, 1),
'statements': [
"CREATE INDEX nsec3_byhash_and_rdtype ON nsec3 " +
"(hash, rdtype)"
]
}
# To extend this, leave the above statements in place and add another
# dictionary to the list. The "from" version should be (2, 0), the "to"
# dictionary to the list. The "from" version should be (2, 1), the "to"
# version whatever the version the update is to, and the SQL statements are
# the statements required to perform the upgrade. This way, the upgrade
# program will be able to upgrade both a V1.0 and a V2.0 database.
......
......@@ -165,7 +165,7 @@ upgrade_ok_test() {
if [ $? -eq 0 ]
then
# Compare schema with the reference
get_schema $testdata/v2_0.sqlite3
get_schema $testdata/v2_1.sqlite3
expected_schema=$db_schema
get_schema $tempfile
actual_schema=$db_schema
......@@ -177,7 +177,7 @@ upgrade_ok_test() {
fi
# Check the version is set correctly
check_version $tempfile "V2.0"
check_version $tempfile "V2.1"
# Check that a backup was made
check_backup $1 $2
......@@ -449,7 +449,7 @@ copy_file $testdata/old_v1.sqlite3 $tempfile
Yes
.
passzero $?
check_version $tempfile "V2.0"
check_version $tempfile "V2.1"
rm -f $tempfile $backupfile
echo "13.4 Interactive prompt - no"
......
......@@ -10,3 +10,4 @@ EXTRA_DIST += old_v1.sqlite3
EXTRA_DIST += README
EXTRA_DIST += too_many_version.sqlite3
EXTRA_DIST += v2_0.sqlite3
EXTRA_DIST += v2_1.sqlite3
......@@ -44,7 +44,7 @@ namespace {
// program may not be taking advantage of features (possibly performance
// improvements) added to the database.
const int SQLITE_SCHEMA_MAJOR_VERSION = 2;
const int SQLITE_SCHEMA_MINOR_VERSION = 0;
const int SQLITE_SCHEMA_MINOR_VERSION = 1;
}
namespace isc {
......@@ -65,19 +65,20 @@ enum StatementID {
DEL_ZONE_RECORDS = 6,
ADD_RECORD = 7,
DEL_RECORD = 8,
ITERATE = 9,
FIND_PREVIOUS = 10,
ADD_RECORD_DIFF = 11,
LOW_DIFF_ID = 12,
HIGH_DIFF_ID = 13,
DIFF_RECS = 14,
NSEC3 = 15,
NSEC3_PREVIOUS = 16,
NSEC3_LAST = 17,
ADD_NSEC3_RECORD = 18,
DEL_ZONE_NSEC3_RECORDS = 19,
DEL_NSEC3_RECORD = 20,
NUM_STATEMENTS = 21
ITERATE_RECORDS = 9,
ITERATE_NSEC3 = 10,
FIND_PREVIOUS = 11,
ADD_RECORD_DIFF = 12,
LOW_DIFF_ID = 13,
HIGH_DIFF_ID = 14,
DIFF_RECS = 15,
NSEC3 = 16,
NSEC3_PREVIOUS = 17,
NSEC3_LAST = 18,
ADD_NSEC3_RECORD = 19,
DEL_ZONE_NSEC3_RECORDS = 20,
DEL_NSEC3_RECORD = 21,
NUM_STATEMENTS = 22
};
const char* const text_statements[NUM_STATEMENTS] = {
......@@ -102,19 +103,17 @@ const char* const text_statements[NUM_STATEMENTS] = {
"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",
// The following iterates the whole zone. As the NSEC3 records
// (and corresponding RRSIGs) live in separate table, we need to
// take both of them. As the RRSIGs are for NSEC3s in the other
// table, we can easily hardcode the sigtype.
//
// The extra column is so we can order it by rname. This is to
// preserve the previous order, mostly for tests.
// TODO: Is it possible to get rid of the ordering?
"SELECT rdtype, ttl, sigtype, rdata, name, rname FROM records " // ITERATE
"WHERE zone_id = ?1 "
"UNION "
"SELECT rdtype, ttl, \"NSEC3\", rdata, owner, owner FROM nsec3 "
"WHERE zone_id = ?1 ORDER by rname, rdtype",
// ITERATE_RECORDS:
// The following iterates the whole zone in the records table.
"SELECT rdtype, ttl, sigtype, rdata, name FROM records "
"WHERE zone_id = ?1 ORDER BY rname, rdtype",
// ITERATE_NSEC3:
// The following iterates the whole zone in the nsec3 table. As the
// RRSIGs are for NSEC3s, we can hardcode the sigtype.
"SELECT rdtype, ttl, \"NSEC3\", rdata, owner FROM nsec3 "
"WHERE zone_id = ?1 ORDER BY hash, 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
......@@ -332,7 +331,7 @@ public:
const char* const SCHEMA_LIST[] = {
"CREATE TABLE schema_version (version INTEGER NOT NULL, "
"minor INTEGER NOT NULL DEFAULT 0)",
"INSERT INTO schema_version VALUES (2, 0)",
"INSERT INTO schema_version VALUES (2, 1)",
"CREATE TABLE zones (id INTEGER PRIMARY KEY, "
"name TEXT NOT NULL COLLATE NOCASE, "
"rdclass TEXT NOT NULL COLLATE NOCASE DEFAULT 'IN', "
......@@ -358,6 +357,7 @@ const char* const SCHEMA_LIST[] = {
"ttl INTEGER NOT NULL, rdtype TEXT NOT NULL COLLATE NOCASE, "
"rdata TEXT NOT NULL)",
"CREATE INDEX nsec3_byhash ON nsec3 (hash)",
"CREATE INDEX nsec3_byhash_and_rdtype ON nsec3 (hash, rdtype)",
"CREATE TABLE diffs (id INTEGER PRIMARY KEY, "
"zone_id INTEGER NOT NULL, "
"version INTEGER NOT NULL, "
......@@ -642,11 +642,21 @@ public:
iterator_type_(ITT_ALL),
accessor_(accessor),
statement_(NULL),
statement2_(NULL),
rc_(SQLITE_OK),
rc2_(SQLITE_OK),
name_("")
{
// We create the statement now and then just keep getting data from it
// We create the statements now and then just keep getting data
// from them.
statement_ = prepare(accessor->dbparameters_->db_,
text_statements[ITERATE]);
text_statements[ITERATE_NSEC3]);
bindZoneId(id);
std::swap(statement_, statement2_);
statement_ = prepare(accessor->dbparameters_->db_,
text_statements[ITERATE_RECORDS]);
bindZoneId(id);
}
......@@ -665,6 +675,9 @@ public:
iterator_type_(qtype == QT_NSEC3 ? ITT_NSEC3 : ITT_NAME),
accessor_(accessor),
statement_(NULL),
statement2_(NULL),
rc_(SQLITE_OK),
rc2_(SQLITE_OK),
name_(name)
{
// Choose the statement text depending on the query type, and
......@@ -703,29 +716,35 @@ public:
// If there's another row, get it
// If finalize has been called (e.g. when previous getNext() got
// SQLITE_DONE), directly return false
if (statement_ == NULL) {
return false;
}
const int rc(sqlite3_step(statement_));
if (rc == SQLITE_ROW) {
// For both types, we copy the first four columns
copyColumn(data, TYPE_COLUMN);
copyColumn(data, TTL_COLUMN);
// The NSEC3 lookup does not provide the SIGTYPE, it is not
// necessary and not contained in the table.
if (iterator_type_ != ITT_NSEC3) {
copyColumn(data, SIGTYPE_COLUMN);
while (statement_ != NULL) {
rc_ = sqlite3_step(statement_);
if (rc_ == SQLITE_ROW) {
// For both types, we copy the first four columns
copyColumn(data, TYPE_COLUMN);
copyColumn(data, TTL_COLUMN);
// The NSEC3 lookup does not provide the SIGTYPE, it is not
// necessary and not contained in the table.
if (iterator_type_ != ITT_NSEC3) {
copyColumn(data, SIGTYPE_COLUMN);
}
copyColumn(data, RDATA_COLUMN);
// Only copy Name if we are iterating over every record
if (iterator_type_ == ITT_ALL) {
copyColumn(data, NAME_COLUMN);
}
return (true);
} else if (rc_ != SQLITE_DONE) {
isc_throw(DataSourceError,
"Unexpected failure in sqlite3_step: " <<
sqlite3_errmsg(accessor_->dbparameters_->db_));
}
copyColumn(data, RDATA_COLUMN);
// Only copy Name if we are iterating over every record
if (iterator_type_ == ITT_ALL) {
copyColumn(data, NAME_COLUMN);
// We are done with statement_. If statement2_ has not been
// used yet, try that one now.
if ((statement2_ == NULL) || (rc2_ != SQLITE_OK)) {
break;
}
return (true);
} else if (rc != SQLITE_DONE) {
isc_throw(DataSourceError,
"Unexpected failure in sqlite3_step: " <<
sqlite3_errmsg(accessor_->dbparameters_->db_));
std::swap(statement_, statement2_);
std::swap(rc_, rc2_);
}
finalize();
return (false);
......@@ -771,13 +790,22 @@ private:
}
void finalize() {
sqlite3_finalize(statement_);
statement_ = NULL;
if (statement_ != NULL) {
sqlite3_finalize(statement_);
statement_ = NULL;
}
if (statement2_ != NULL) {
sqlite3_finalize(statement2_);
statement2_ = NULL;
}
}
const IteratorType iterator_type_;
boost::shared_ptr<const SQLite3Accessor> accessor_;
sqlite3_stmt* statement_;
sqlite3_stmt* statement2_;
int rc_;
int rc2_;
const std::string name_;
};
......
......@@ -191,6 +191,11 @@ TEST_F(SQLite3AccessorTest, iterator) {
checkRR(context, "sub.example.org.", "3600", "NS", "ns.sub.example.org.");
checkRR(context, "ns.sub.example.org.", "3600", "A", "192.0.2.101");
checkRR(context, "www.example.org.", "3600", "A", "192.0.2.1");
checkRR(context, "ns3.example.org.", "3600", "NSEC3",
"1 1 12 aabbccdd 2T7B4G4VSA5SMI47K61MV5BV1A22BOJR A RRSIG");
checkRR(context, "ns3.example.org.", "3600", "RRSIG",
"NSEC3 5 3 3600 20000101000000 20000201000000 "
"12345 ns3.example.org. FAKEFAKEFAKE");
// Check there's no other
EXPECT_FALSE(context->getNext(data));
......
......@@ -25,7 +25,7 @@ RR_RDATA_INDEX = 7
# Current major and minor versions of schema
SCHEMA_MAJOR_VERSION = 2
SCHEMA_MINOR_VERSION = 0
SCHEMA_MINOR_VERSION = 1
class Sqlite3DSError(Exception):
""" Define exceptions."""
......@@ -81,6 +81,7 @@ def create(cur):
rdtype TEXT NOT NULL COLLATE NOCASE,
rdata TEXT NOT NULL)""")
cur.execute("CREATE INDEX nsec3_byhash ON nsec3 (hash)")
cur.execute("CREATE INDEX nsec3_byhash_and_rdtype ON nsec3 (hash, rdtype)")
cur.execute("""CREATE TABLE diffs (id INTEGER PRIMARY KEY,
zone_id INTEGER NOT NULL,
version INTEGER NOT NULL,
......
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