summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDaniel Burrows <dburrows@debian.org>2009-07-30 08:16:01 -0700
committerDaniel Burrows <dburrows@debian.org>2009-07-30 08:16:01 -0700
commit9c3497575ee632fd9ed57c92924ca42706490591 (patch)
tree5756ca45e8e0fbc403cf8a30e74dc15f30bead68
parent31658b7927c97228bd902dd3817743ed3f7c7195 (diff)
downloadaptitude-9c3497575ee632fd9ed57c92924ca42706490591.tar.gz
Wrap sqlite3_blob_read and sqlite3_blob_write.
-rw-r--r--src/generic/util/sqlite.cc25
-rw-r--r--src/generic/util/sqlite.h30
-rw-r--r--tests/test_sqlite.cc60
3 files changed, 115 insertions, 0 deletions
diff --git a/src/generic/util/sqlite.cc b/src/generic/util/sqlite.cc
index e4cbff37..0d138ae2 100644
--- a/src/generic/util/sqlite.cc
+++ b/src/generic/util/sqlite.cc
@@ -413,5 +413,30 @@ namespace aptitude
sqlite3_blob_close(handle);
parent.active_blobs.erase(this);
}
+
+ int blob::size()
+ {
+ return sqlite3_blob_bytes(handle);
+ }
+
+ void blob::read(int offset, void *out, int length)
+ {
+ const int result = sqlite3_blob_read(handle, out, length, offset);
+ if(result != SQLITE_OK)
+ {
+ std::string msg(parent.get_error());
+ throw exception(msg, result);
+ }
+ }
+
+ void blob::write(int offset, const void *out, int length)
+ {
+ const int result = sqlite3_blob_write(handle, out, length, offset);
+ if(result != SQLITE_OK)
+ {
+ std::string msg(parent.get_error());
+ throw exception(msg, result);
+ }
+ }
}
}
diff --git a/src/generic/util/sqlite.h b/src/generic/util/sqlite.h
index 884385d8..abe640f6 100644
--- a/src/generic/util/sqlite.h
+++ b/src/generic/util/sqlite.h
@@ -490,6 +490,36 @@ namespace aptitude
sqlite3_int64 row,
bool readWrite = true);
+ /** \brief Retrieve the size of the BLOB in bytes. */
+ int size();
+
+ /** \brief Read some data from the BLOB.
+ *
+ * \param offset The byte offset at which to start reading.
+ * \param out The memory location at which to begin storing
+ * the data that was read.
+ * \param length The number of bytes of data to read.
+ *
+ * If there are fewer than "length" bytes following "offset" in
+ * the BLOB, this operation throws an exception. If the BLOB's
+ * row has been modified, this operation throws an exception
+ * with the error code SQLITE_ABORT.
+ */
+ void read(int offset, void *out, int length);
+
+ /** \brief Write some data into the BLOB.
+ *
+ * \param offset The byte offset at which to start writing.
+ * \param in The data to write into the BLOB.
+ * \param length The number of bytes of data to write.
+ *
+ * If there are fewer than "length" bytes following "offset" in
+ * the BLOB, this operation throws an exception. If the BLOB's
+ * row has been modified, this operation throws an exception
+ * with the error code SQLITE_ABORT.
+ */
+ void write(int offset, const void *in, int length);
+
~blob();
};
}
diff --git a/tests/test_sqlite.cc b/tests/test_sqlite.cc
index 1ff034bf..2a7e174f 100644
--- a/tests/test_sqlite.cc
+++ b/tests/test_sqlite.cc
@@ -429,3 +429,63 @@ BOOST_FIXTURE_TEST_CASE(testOpenBlob, test_blob_fixture)
100),
exception);
}
+
+BOOST_FIXTURE_TEST_CASE(testBlobSize, test_blob_fixture)
+{
+ boost::shared_ptr<blob> b = blob::open(*tmpdb,
+ "main",
+ "test",
+ "C",
+ blob_rowid);
+
+ BOOST_CHECK_EQUAL(b->size(), 2);
+}
+
+BOOST_FIXTURE_TEST_CASE(testBlobRead, test_blob_fixture)
+{
+ boost::shared_ptr<blob> b = blob::open(*tmpdb,
+ "main",
+ "test",
+ "C",
+ blob_rowid);
+
+ char contents[3];
+ const char expected[] = { 0x54, 0x12 };
+ b->read(0, contents, 2);
+ BOOST_CHECK_EQUAL_COLLECTIONS(contents, contents + 2,
+ expected, expected + 2);
+ b->read(0, contents, 2);
+ BOOST_CHECK_EQUAL_COLLECTIONS(contents, contents + 2,
+ expected, expected + 2);
+
+ BOOST_CHECK_THROW(b->read(0, contents, 3), exception);
+}
+
+BOOST_FIXTURE_TEST_CASE(testBlobWrite, test_blob_fixture)
+{
+ const char data[2] = { 0x54, 0x11 };
+ {
+ boost::shared_ptr<blob> b = blob::open(*tmpdb,
+ "main",
+ "test",
+ "C",
+ blob_rowid);
+
+ b->write(1, data + 1, 1);
+ BOOST_CHECK_THROW(b->write(1, data, 2), exception);
+ }
+
+ boost::shared_ptr<statement> stmt =
+ statement::prepare(*tmpdb, "select C from test where rowid = ?");
+ stmt->bind_int64(1, blob_rowid);
+ BOOST_REQUIRE(stmt->step());
+
+ int len = -1;
+ const void *val = stmt->get_blob(0, len);
+ BOOST_CHECK_EQUAL(len, sizeof(data));
+ BOOST_CHECK_EQUAL_COLLECTIONS(data, data + sizeof(data),
+ reinterpret_cast<const char *>(val),
+ reinterpret_cast<const char *>(val) + len);
+
+ BOOST_CHECK(!stmt->step());
+}