Skip to content

Commit

Permalink
dbcopy: escape data object
Browse files Browse the repository at this point in the history
  • Loading branch information
franku committed Jan 31, 2020
1 parent 39cbae2 commit c12a7c8
Show file tree
Hide file tree
Showing 7 changed files with 56 additions and 12 deletions.
4 changes: 4 additions & 0 deletions core/src/cats/bdb_postgresql.h
Expand Up @@ -46,6 +46,10 @@ class BareosDbPostgresql : public BareosDbPrivateInterface {
const char* old,
int len) override;
char* EscapeObject(JobControlRecord* jcr, char* old, int len) override;
unsigned char* EscapeObject(const unsigned char* old,
std::size_t old_len,
std::size_t& new_len) override;
void FreeEscapedObjectMemory(unsigned char* obj) override;
void UnescapeObject(JobControlRecord* jcr,
char* from,
int32_t expected_len,
Expand Down
8 changes: 8 additions & 0 deletions core/src/cats/cats.h
Expand Up @@ -1031,6 +1031,14 @@ class BareosDb : public BareosDbQueryEnum {
const char* old,
int len);
virtual char* EscapeObject(JobControlRecord* jcr, char* old, int len);
virtual unsigned char* EscapeObject(const unsigned char* old,
std::size_t old_len,
std::size_t& new_len)
{
return nullptr;
}
virtual void FreeEscapedObjectMemory(unsigned char* obj) {}

virtual void UnescapeObject(JobControlRecord* jcr,
char* from,
int32_t expected_len,
Expand Down
13 changes: 13 additions & 0 deletions core/src/cats/postgresql.cc
Expand Up @@ -400,6 +400,19 @@ char* BareosDbPostgresql::EscapeObject(JobControlRecord* jcr,
return (char*)esc_obj;
}

unsigned char* BareosDbPostgresql::EscapeObject(const unsigned char* old,
std::size_t old_len,
std::size_t& new_len)
{
return PQescapeByteaConn(db_handle_, old, old_len, std::addressof(new_len));
}

void BareosDbPostgresql::FreeEscapedObjectMemory(unsigned char* obj)
{
PQfreemem(obj);
}


/**
* Unescape binary object so that PostgreSQL is happy
*
Expand Down
22 changes: 18 additions & 4 deletions core/src/dird/dbcopy/column_description.cc
Expand Up @@ -46,12 +46,12 @@ ColumnDescription::ColumnDescription(const char* column_name_in,
}
}

static void no_conversion(FieldData& fd)
static void no_conversion(BareosDb* db, FieldData& fd)
{
fd.data_pointer = fd.data_pointer ? fd.data_pointer : "";
}

static void timestamp_conversion_postgresql(FieldData& fd)
static void timestamp_conversion_postgresql(BareosDb* db, FieldData& fd)
{
static const char* dummy_timepoint = "1970-01-01 00:00:00";
if (!fd.data_pointer) {
Expand All @@ -63,11 +63,14 @@ static void timestamp_conversion_postgresql(FieldData& fd)
}
}

static void string_conversion_postgresql(FieldData& fd)
static void string_conversion_postgresql(BareosDb* db, FieldData& fd)
{
if (fd.data_pointer) {
std::size_t len{strlen(fd.data_pointer)};
fd.converted_data.resize(len * 2 + 1);
#if 1
db->EscapeString(nullptr, fd.converted_data.data(), fd.data_pointer, len);
#else
char* n = fd.converted_data.data();
const char* o = fd.data_pointer;
Expand All @@ -89,12 +92,23 @@ static void string_conversion_postgresql(FieldData& fd)
}
}
*n = 0;
#endif
fd.data_pointer = fd.converted_data.data();
} else {
fd.data_pointer = "";
}
}

static void bytea_conversion_postgresql(BareosDb* db, FieldData& fd)
{
std::size_t new_len{};
auto old = reinterpret_cast<const unsigned char*>(fd.data_pointer);
auto obj = db->EscapeObject(old, strlen(fd.data_pointer), new_len);
fd.converted_data.resize(new_len + 1);
memcpy(fd.converted_data.data(), obj, new_len + 1);
db->FreeEscapedObjectMemory(obj);
}

const DataTypeConverterMap ColumnDescriptionMysql::db_import_converter_map{
{"bigint", no_conversion}, {"binary", no_conversion},
{"blob", no_conversion}, {"char", no_conversion},
Expand All @@ -121,7 +135,7 @@ ColumnDescriptionMysql::ColumnDescriptionMysql(const char* column_name_in,

const DataTypeConverterMap ColumnDescriptionPostgresql::db_export_converter_map{
{"bigint", no_conversion},
{"bytea", string_conversion_postgresql},
{"bytea", bytea_conversion_postgresql},
{"character", string_conversion_postgresql},
{"integer", no_conversion},
{"numeric", no_conversion},
Expand Down
9 changes: 6 additions & 3 deletions core/src/dird/dbcopy/column_description.h
Expand Up @@ -27,6 +27,7 @@
#include <string>

class FieldData;
class BareosDb;

class ColumnDescription {
public:
Expand All @@ -38,12 +39,14 @@ class ColumnDescription {
std::string column_name;
std::string data_type;
std::size_t character_maximum_length{};
std::function<void(FieldData&)> db_export_converter{};
std::function<void(FieldData&)> db_import_converter{};

using ConverterCallback = std::function<void(BareosDb*, FieldData&)>;
ConverterCallback db_export_converter{};
ConverterCallback db_import_converter{};
};

using DataTypeConverterMap =
std::map<std::string, std::function<void(FieldData&)>>;
std::map<std::string, ColumnDescription::ConverterCallback>;

class ColumnDescriptionMysql : public ColumnDescription {
public:
Expand Down
2 changes: 1 addition & 1 deletion core/src/dird/dbcopy/database_export_postgresql.cc
Expand Up @@ -84,7 +84,7 @@ void DatabaseExportPostgresql::CopyRow(RowData& origin_data)

if (i < origin_data.row.size()) {
query_values += "'";
column_description->db_export_converter(origin_data.row[i]);
column_description->db_export_converter(db_, origin_data.row[i]);
query_values += origin_data.row[i].data_pointer;
query_values += "',";
} else {
Expand Down
10 changes: 6 additions & 4 deletions core/src/dird/dbcopy/database_import_mysql.cc
Expand Up @@ -69,15 +69,17 @@ struct ResultHandlerContext {
ResultHandlerContext(
const DatabaseColumnDescriptions::VectorOfColumnDescriptions& c,
RowData& d,
DatabaseExport& e)
: column_descriptions(c), row_data(d), exporter(e)
DatabaseExport& e,
BareosDb* db_in)
: column_descriptions(c), row_data(d), exporter(e), db(db_in)
{
}
const DatabaseColumnDescriptions::VectorOfColumnDescriptions&
column_descriptions;
RowData& row_data;
DatabaseExport& exporter;
uint64_t counter{};
BareosDb* db;
};

void DatabaseImportMysql::RunQuerySelectAllRows(
Expand Down Expand Up @@ -107,7 +109,7 @@ void DatabaseImportMysql::RunQuerySelectAllRows(
}

RowData row_data(t.column_descriptions, t.table_name);
ResultHandlerContext ctx(t.column_descriptions, row_data, exporter);
ResultHandlerContext ctx(t.column_descriptions, row_data, exporter, db_);

if (!db_->SqlQuery(query.c_str(), ResultHandler, &ctx)) {
std::cout << "Could not import table: " << t.table_name << std::endl;
Expand Down Expand Up @@ -154,7 +156,7 @@ void DatabaseImportMysql::FillRowWithDatabaseResult(ResultHandlerContext* r,
for (int i = 0; i < fields; i++) {
RowData& row_data = r->row_data;
row_data.row[i].data_pointer = row[i];
r->column_descriptions[i]->db_import_converter(row_data.row[i]);
r->column_descriptions[i]->db_import_converter(r->db, row_data.row[i]);
}
}

Expand Down

0 comments on commit c12a7c8

Please sign in to comment.