From a3a4bb3da64d9e806a0bb2edd39664c30da6bbbc Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Markus=20M=C3=A4kel=C3=A4?= Date: Mon, 11 Jun 2018 20:28:06 +0300 Subject: [PATCH] MXS-1881: Add TableCreateEvent JSON serialization Serializing the object allows replicated events to be processed even if the CREATE TABLE statement is not in the binary logs. --- server/modules/routing/avrorouter/rpl.cc | 83 ++++++++++++++++++++++++ server/modules/routing/avrorouter/rpl.hh | 28 +++++++- 2 files changed, 110 insertions(+), 1 deletion(-) diff --git a/server/modules/routing/avrorouter/rpl.cc b/server/modules/routing/avrorouter/rpl.cc index 4e297dea4..fbd5102e6 100644 --- a/server/modules/routing/avrorouter/rpl.cc +++ b/server/modules/routing/avrorouter/rpl.cc @@ -15,6 +15,89 @@ #include #include +#include + +json_t* Column::to_json() const +{ + json_t* obj = json_object(); + json_object_set_new(obj, "name", json_string(name.c_str())); + json_object_set_new(obj, "type", json_string(type.c_str())); + json_object_set_new(obj, "length", json_integer(length)); + return obj; +} + +Column Column::from_json(json_t* json) +{ + json_t* name = json_object_get(json, "name"); + json_t* type = json_object_get(json, "type"); + json_t* length = json_object_get(json, "length"); + + if (name && json_is_string(name) && + type && json_is_string(type) && + length && json_is_integer(length)) + { + return Column(json_string_value(name), json_string_value(type), + json_integer_value(length)); + } + + // Invalid JSON, return empty Column + return Column(""); +} + +json_t* TableCreateEvent::to_json() const +{ + json_t* arr = json_array(); + + for (auto it = columns.begin(); it != columns.end(); it++) + { + json_array_append_new(arr, it->to_json()); + } + + json_t* obj = json_object(); + json_object_set_new(obj, "table", json_string(table.c_str())); + json_object_set_new(obj, "database", json_string(database.c_str())); + json_object_set_new(obj, "version", json_integer(version)); + json_object_set_new(obj, "columns", arr); + + return obj; +} + +STableCreateEvent TableCreateEvent::from_json(json_t* obj) +{ + STableCreateEvent rval; + json_t* table = json_object_get(obj, "table"); + json_t* database = json_object_get(obj, "database"); + json_t* version = json_object_get(obj, "version"); + json_t* columns = json_object_get(obj, "columns"); + + if (json_is_string(table) && json_is_string(database) && + json_is_integer(version) && json_is_array(columns)) + { + std::string tbl = json_string_value(table); + std::string db = json_string_value(database); + int ver = json_integer_value(version); + std::vector cols; + size_t i = 0; + json_t* val; + + json_array_foreach(columns, i, val) + { + cols.emplace_back(Column::from_json(val)); + } + + auto is_empty = [](const Column & col) + { + return col.name.empty(); + }; + + if (std::none_of(cols.begin(), cols.end(), is_empty)) + { + rval.reset(new TableCreateEvent(db, tbl, ver, std::move(cols))); + } + } + + return rval; +} Rpl::Rpl(SERVICE* service, SRowEventHandler handler, gtid_pos_t gtid): m_handler(handler), diff --git a/server/modules/routing/avrorouter/rpl.hh b/server/modules/routing/avrorouter/rpl.hh index eecf31500..bb3fce9bd 100644 --- a/server/modules/routing/avrorouter/rpl.hh +++ b/server/modules/routing/avrorouter/rpl.hh @@ -66,8 +66,14 @@ struct Column std::string name; std::string type; int length; + + json_t* to_json() const; + static Column from_json(json_t* json); }; +struct TableCreateEvent; +typedef std::tr1::shared_ptr STableCreateEvent; + /** A CREATE TABLE abstraction */ struct TableCreateEvent { @@ -80,11 +86,32 @@ struct TableCreateEvent { } + /** + * Get the table identifier i.e. `database.table` + * + * @return The table identifier + */ std::string id() const { return database + '.' + table; } + /** + * Convert to JSON + * + * @return JSON representation of this object + */ + json_t* to_json() const; + + /** + * Convert from JSON + * + * @param json JSON to convert from + * + * @return Object representation of JSON if it is valid or empty pointer if invalid. + */ + static STableCreateEvent from_json(json_t* json); + std::vector columns; std::string table; std::string database; @@ -124,7 +151,6 @@ struct TableMapEvent Bytes column_metadata; }; -typedef std::tr1::shared_ptr STableCreateEvent; typedef std::tr1::shared_ptr STableMapEvent; // Containers for the replication events