mirror of
https://gitlab.isc.org/isc-projects/kea
synced 2025-09-03 07:25:18 +00:00
[1899] Break up UNION SQL query into two and merge manually
Also drop unnecessary columns and ORDER BYs.
This commit is contained in:
@@ -63,19 +63,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] = {
|
||||
@@ -95,19 +96,19 @@ 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. As there is
|
||||
// only one RR per-owner per-zone, there's no need to order these
|
||||
// for the sake of any post-processing.
|
||||
"SELECT rdtype, ttl, \"NSEC3\", rdata, owner FROM nsec3 "
|
||||
"WHERE zone_id = ?1",
|
||||
/*
|
||||
* 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
|
||||
@@ -637,11 +638,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);
|
||||
}
|
||||
|
||||
@@ -660,6 +671,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
|
||||
@@ -693,29 +707,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);
|
||||
@@ -761,13 +781,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_;
|
||||
};
|
||||
|
||||
|
Reference in New Issue
Block a user