Browse Source

[1330] Test to check first record returned is OK passes

Added code to handle getting set of records between two indexes.
Stephen Morris 13 years ago
parent
commit
2f51afcbc5

+ 87 - 17
src/lib/datasrc/sqlite3_accessor.cc

@@ -16,7 +16,6 @@
 
 
 #include <string>
 #include <string>
 #include <vector>
 #include <vector>
-#include <iostream>
 
 
 #include <boost/foreach.hpp>
 #include <boost/foreach.hpp>
 
 
@@ -58,7 +57,7 @@ enum StatementID {
     COUNT_DIFF_RECS = 13,
     COUNT_DIFF_RECS = 13,
     LOW_DIFF_ID = 14,
     LOW_DIFF_ID = 14,
     HIGH_DIFF_ID = 15,
     HIGH_DIFF_ID = 15,
-    DIFFS = 16,
+    DIFF_RECS = 16,
     NUM_STATEMENTS = 17
     NUM_STATEMENTS = 17
 };
 };
 
 
@@ -105,7 +104,10 @@ const char* const text_statements[NUM_STATEMENTS] = {
     "SELECT id FROM diffs "     // HIGH_DIFF_ID
     "SELECT id FROM diffs "     // HIGH_DIFF_ID
         "WHERE zone_id=?1 AND version=?2 and OPERATION=1 "
         "WHERE zone_id=?1 AND version=?2 and OPERATION=1 "
         "ORDER BY id DESC LIMIT 1",
         "ORDER BY id DESC LIMIT 1",
-    "SELECT name, rrtype, ttl, rdata FROM diffs "   // DIFFS
+
+    // In the next statement, note the redundant ID.  This is to ensure
+    // that the columns match the column IDs passed to the iterator
+    "SELECT rrtype, ttl, id, rdata, name FROM diffs "   // DIFF_RECS
         "WHERE zone_id=?1 AND id>=?2 and id<=?3"
         "WHERE zone_id=?1 AND id>=?2 and id<=?3"
 };
 };
 
 
@@ -607,26 +609,78 @@ public:
 
 
     /// \brief Constructor
     /// \brief Constructor
     ///
     ///
+    /// Constructs the iterator for the difference sequence.  It is
+    /// passed two parameters, the first and last versions in the difference
+    /// sequence.  Note that because of serial number rollover, it may well
+    /// be that the start serial number is greater than the end one.
+    ///
     /// \param zone_id ID of the zone (in the zone table)
     /// \param zone_id ID of the zone (in the zone table)
+    /// \param start Serial number of first version in difference sequence
+    /// \param end Serial number of last version in difference sequence
+    ///
+    /// \exception any A number of exceptions can be expected
     DiffContext(const boost::shared_ptr<const SQLite3Accessor>& accessor,
     DiffContext(const boost::shared_ptr<const SQLite3Accessor>& accessor,
                 int zone_id, uint32_t start, uint32_t end) :
                 int zone_id, uint32_t start, uint32_t end) :
-        accessor_(accessor)
+        accessor_(accessor),
+        last_status_(SQLITE_ROW)
     {
     {
         try {
         try {
             int low_id = findIndex(LOW_DIFF_ID, zone_id, start);
             int low_id = findIndex(LOW_DIFF_ID, zone_id, start);
             int high_id = findIndex(HIGH_DIFF_ID, zone_id, end);
             int high_id = findIndex(HIGH_DIFF_ID, zone_id, end);
-            std::cout << "Low index is " << low_id << ", high index is " << high_id << "\n";
+
+            // Prepare the statement that will return data values
+            clearBindings(DIFF_RECS);
+            bindInt(DIFF_RECS, 1, zone_id);
+            bindInt(DIFF_RECS, 2, low_id);
+            bindInt(DIFF_RECS, 3, high_id);
+
+            // last_status_ has been initialized to pretend that the last
+            // getNext() returned a record.
+
         } catch (...) {
         } catch (...) {
             accessor_->dbparameters_->finalizeStatements();
             accessor_->dbparameters_->finalizeStatements();
             throw;
             throw;
         }
         }
     }
     }
 
 
-    virtual ~DiffContext() {}
+    /// \brief Destructor
+    virtual ~DiffContext()
+    {}
 
 
-    virtual bool getNext(std::string (&data)[COLUMN_COUNT]) {
-        static_cast<void>(data[0]);
-        return (false);
+    /// \brief Get Next Diff Record
+    ///
+    /// Returns the next difference record in the difference sequence.
+    ///
+    /// \param data Array of std::strings COLUMN_COUNT long.  The results
+    ///        are returned in this.
+    ///
+    /// \return bool true if data is returned, false if not.
+    ///
+    /// \exceptions any Varied
+    bool getNext(std::string (&data)[COLUMN_COUNT]) {
+
+        // Get a pointer to the statement for brevity (does not transfer
+        // resources)
+        sqlite3_stmt* stmt = accessor_->dbparameters_->getStatement(DIFF_RECS);
+
+        // If there is a row to get, get it.
+        if (last_status_ != SQLITE_DONE) {
+            const int rc(sqlite3_step(stmt));
+            if (rc == SQLITE_ROW) {
+                // Copy the data across to the output array
+                copyColumn(DIFF_RECS, data, TYPE_COLUMN);
+                copyColumn(DIFF_RECS, data, TTL_COLUMN);
+                copyColumn(DIFF_RECS, data, NAME_COLUMN);
+                copyColumn(DIFF_RECS, data, RDATA_COLUMN);
+            } else if (rc != SQLITE_DONE) {
+                accessor_->dbparameters_->finalizeStatements();
+                isc_throw(DataSourceError,
+                          "Unexpected failure in sqlite3_step: " <<
+                          sqlite3_errmsg(accessor_->dbparameters_->db_));
+            }
+            last_status_ = rc;
+        }
+        return (last_status_ == SQLITE_ROW);
     }
     }
 
 
 private:
 private:
@@ -727,15 +781,10 @@ private:
     /// \return int ID of the row in the difss table corresponding to the
     /// \return int ID of the row in the difss table corresponding to the
     ///         statement.
     ///         statement.
     ///
     ///
+    /// \exception TooLittleData Internal error, no result returned when one
+    ///            was expected.
     /// \exception NoSuchSerial Serial number not found.
     /// \exception NoSuchSerial Serial number not found.
-    ///
-    /// TODO: NoSuchSerial will be thrown if no records are found.  This is
-    /// most likely due to there being no match for the serial number, but it
-    /// could also be 
-    /// might also occur if there are no difference records for the zone in
-    /// the table.  We can check for this, but only at the cost of
-    /// no difference records in the table.  We can disambiguate these cases,
-    /// but only by 
+    /// \exception NoDiffsData No data for this zone found in diffs table
     int findIndex(StatementID stindex, int zone_id, uint32_t serial) {
     int findIndex(StatementID stindex, int zone_id, uint32_t serial) {
 
 
         // Set up the statement
         // Set up the statement
@@ -772,8 +821,29 @@ private:
         return (result);
         return (result);
     }
     }
 
 
+    /// \brief Copy Column to Output
+    ///
+    /// Copies the textual data in the result set to the specified column
+    /// in the output.
+    ///
+    /// \param stindex Index of prepared statement used to access data
+    /// \param data Array of columns passed to getNext
+    /// \param column Column of output to copy
+    void copyColumn(StatementID stindex, std::string (&data)[COLUMN_COUNT],
+                    int column) {
+
+        // Get a pointer to the statement for brevity (does not transfer
+        // resources)
+        sqlite3_stmt* stmt = accessor_->dbparameters_->getStatement(stindex);
+        data[column] = convertToPlainChar(sqlite3_column_text(stmt,
+                                                              column),
+                                          accessor_->dbparameters_->db_);
+    }
     
     
+    // Attributes
+
     boost::shared_ptr<const SQLite3Accessor> accessor_; // Accessor object
     boost::shared_ptr<const SQLite3Accessor> accessor_; // Accessor object
+    int last_status_;   // Last status received from sqlite3_step
 };
 };
 
 
 // ... and return the iterator
 // ... and return the iterator

+ 3 - 3
src/lib/datasrc/tests/sqlite3_accessor_unittest.cc

@@ -232,7 +232,7 @@ TEST_F(SQLite3AccessorTest, diffIteratorNoRecords) {
     // Check that valid versions - but for the wrong zone which does not hold
     // Check that valid versions - but for the wrong zone which does not hold
     // any records - throws the correct exception.
     // any records - throws the correct exception.
     EXPECT_THROW(accessor->getDiffs(zone_info.second + 42, 1231, 1234),
     EXPECT_THROW(accessor->getDiffs(zone_info.second + 42, 1231, 1234),
-                 NoSuchSerial);
+                 NoDiffRecs);
 
 
 }
 }
 
 
@@ -254,8 +254,8 @@ TEST_F(SQLite3AccessorTest, validSequence) {
     // Check the records
     // Check the records
     EXPECT_TRUE(context->getNext(data));
     EXPECT_TRUE(context->getNext(data));
     EXPECT_EQ("SOA", data[DatabaseAccessor::TYPE_COLUMN]);
     EXPECT_EQ("SOA", data[DatabaseAccessor::TYPE_COLUMN]);
-    EXPECT_EQ("3600", data[DatabaseAccessor::TTL_COLUMN]);
-    EXPECT_EQ("ns1.example.org. admin.example.org. 1230, 3600 1800 2419200 7200",
+    EXPECT_EQ("1800", data[DatabaseAccessor::TTL_COLUMN]);
+    EXPECT_EQ("ns1.example.org. admin.example.org. 1230 3600 1800 2419200 7200",
         data[DatabaseAccessor::RDATA_COLUMN]);
         data[DatabaseAccessor::RDATA_COLUMN]);
     EXPECT_EQ("example.org.", data[DatabaseAccessor::NAME_COLUMN]);
     EXPECT_EQ("example.org.", data[DatabaseAccessor::NAME_COLUMN]);
 }
 }