Browse Source

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

Stephen Morris 13 years ago
parent
commit
61feac8366

+ 138 - 19
src/lib/datasrc/sqlite3_accessor.cc

@@ -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

BIN
src/lib/datasrc/tests/testdata/brokendb.sqlite3


BIN
src/lib/datasrc/tests/testdata/example.org.sqlite3


BIN
src/lib/datasrc/tests/testdata/example2.com.sqlite3


BIN
src/lib/datasrc/tests/testdata/rwtest.sqlite3


BIN
src/lib/datasrc/tests/testdata/test-root.sqlite3


BIN
src/lib/datasrc/tests/testdata/test.sqlite3