From 4d2b87dbfb8c34f39a294fb470884dc5feb29b05 Mon Sep 17 00:00:00 2001 From: Michael Davis <michael.davis@cern.ch> Date: Tue, 21 May 2019 16:39:19 +0200 Subject: [PATCH] [catalogue] Postgres escapes ByteA type before insertion into DB Binary blobs containing zeros are now handled correctly. --- catalogue/CatalogueTest.cpp | 2 +- catalogue/PostgresCatalogue.cpp | 2 +- rdbms/Conn.hpp | 9 +++++++++ rdbms/wrapper/PostgresColumn.cpp | 17 +++++++++++++++++ rdbms/wrapper/PostgresColumn.hpp | 11 +++++++++++ rdbms/wrapper/PostgresConn.hpp | 3 ++- 6 files changed, 41 insertions(+), 3 deletions(-) diff --git a/catalogue/CatalogueTest.cpp b/catalogue/CatalogueTest.cpp index bd1607cd5f..50bb22beab 100644 --- a/catalogue/CatalogueTest.cpp +++ b/catalogue/CatalogueTest.cpp @@ -3465,7 +3465,7 @@ TEST_P(cta_catalogue_CatalogueTest, createTape_1_tape_with_write_log_1_tape_with file1Written.diskFileOwnerUid = PUBLIC_DISK_USER; file1Written.diskFileGid = PUBLIC_DISK_GROUP; file1Written.size = fileSize; - file1Written.checksumBlob.insert(checksum::ADLER32, "1234"); + file1Written.checksumBlob.insert(checksum::ADLER32, 0x1000); // tests checksum with embedded zeros file1Written.storageClassName = storageClass.name; file1Written.vid = vid1; file1Written.fSeq = 1; diff --git a/catalogue/PostgresCatalogue.cpp b/catalogue/PostgresCatalogue.cpp index e3793c1a2f..dc5a8ded68 100644 --- a/catalogue/PostgresCatalogue.cpp +++ b/catalogue/PostgresCatalogue.cpp @@ -491,7 +491,7 @@ void PostgresCatalogue::idempotentBatchInsertArchiveFiles(rdbms::Conn &conn, archiveFileBatch.diskFileUser.setFieldValue(i, event.diskFileOwnerUid); archiveFileBatch.diskFileGroup.setFieldValue(i, event.diskFileGid); archiveFileBatch.size.setFieldValue(i, event.size); - archiveFileBatch.checksumBlob.setFieldValue(i, event.checksumBlob.serialize()); + archiveFileBatch.checksumBlob.setFieldByteA(conn, i, event.checksumBlob.serialize()); archiveFileBatch.storageClassName.setFieldValue(i, event.storageClassName); archiveFileBatch.creationTime.setFieldValue(i, now); archiveFileBatch.reconciliationTime.setFieldValue(i, now); diff --git a/rdbms/Conn.hpp b/rdbms/Conn.hpp index b9849a9b45..4d3f6b140c 100644 --- a/rdbms/Conn.hpp +++ b/rdbms/Conn.hpp @@ -209,6 +209,15 @@ public: */ std::list<std::string> getTriggerNames(); + /** + * Get a pointer to the connection wrapper implementation + * + * Required for Postgres PQescapeByteaConn() + */ + wrapper::ConnWrapper *getConnWrapperPtr() { + return m_connAndStmts->conn.get(); + } + private: /** diff --git a/rdbms/wrapper/PostgresColumn.cpp b/rdbms/wrapper/PostgresColumn.cpp index 90636678b2..7e58d0032e 100644 --- a/rdbms/wrapper/PostgresColumn.cpp +++ b/rdbms/wrapper/PostgresColumn.cpp @@ -18,6 +18,7 @@ #include "common/exception/Exception.hpp" #include "rdbms/wrapper/PostgresColumn.hpp" +#include "rdbms/wrapper/PostgresConn.hpp" namespace cta { namespace rdbms { @@ -46,6 +47,22 @@ size_t PostgresColumn::getNbRows() const { return m_nbRows; } +//------------------------------------------------------------------------------ +// setFieldByteA +//------------------------------------------------------------------------------ +void PostgresColumn::setFieldByteA(rdbms::Conn &conn, const size_t index, const std::string &value) { + auto pgconn_ptr = dynamic_cast<PostgresConn*>(conn.getConnWrapperPtr()); + auto pgconn = pgconn_ptr->get(); + + size_t escaped_length; + auto escapedByteA = PQescapeByteaConn(pgconn, reinterpret_cast<const unsigned char*>(value.c_str()), + value.length(), &escaped_length); + std::string escapedStr(reinterpret_cast<const char*>(escapedByteA), escaped_length); + PQfreemem(escapedByteA); + + copyStrIntoField(index, escapedStr); +} + //------------------------------------------------------------------------------ // getValue //------------------------------------------------------------------------------ diff --git a/rdbms/wrapper/PostgresColumn.hpp b/rdbms/wrapper/PostgresColumn.hpp index 741f9d4348..64f1679d16 100644 --- a/rdbms/wrapper/PostgresColumn.hpp +++ b/rdbms/wrapper/PostgresColumn.hpp @@ -22,6 +22,8 @@ #include <string.h> #include <typeinfo> #include <vector> +#include <libpq-fe.h> +#include <rdbms/Conn.hpp> namespace cta { namespace rdbms { @@ -73,6 +75,15 @@ public: setFieldValue(index, value, std::is_integral<T>()); } + /** + * Sets the BYTEA field at the specified index to the value of a byte array + * + * @param conn The connection to the Postgres database + * @param index The index of the field + * @param value The value of the field expressed as a byte array + */ + void setFieldByteA(rdbms::Conn &conn, const size_t index, const std::string &value); + private: /** diff --git a/rdbms/wrapper/PostgresConn.hpp b/rdbms/wrapper/PostgresConn.hpp index 53ef5facb6..ce67db9c29 100644 --- a/rdbms/wrapper/PostgresConn.hpp +++ b/rdbms/wrapper/PostgresConn.hpp @@ -33,6 +33,7 @@ namespace wrapper { class PostgresStmt; class PostgresRset; +class PostgresColumn; class PostgresConn: public ConnWrapper { public: @@ -42,7 +43,7 @@ public: */ friend PostgresStmt; friend PostgresRset; - + friend PostgresColumn; /** * Constructor. -- GitLab