From 05f7a6d63e04c34810c8e1c8337fe9bdb4fc11f4 Mon Sep 17 00:00:00 2001 From: Duarte Nunes Date: Tue, 31 May 2016 16:16:08 +0200 Subject: [PATCH] thrift: Add basic support for dynamic CF In thrift, a static column family is one where all columns are defined upon schema creation. It maps to a CQL table with a singular partition key and a set of regular columns. On the other hand, a dynamic column family is one which allows column to be dynamically added by insertion requests. It maps to a CQL table with a partition key and a clustering key, which will hold the names of the dynamic columns, and a regular column, which will how the respective values. If the thrift comparator type is composite, then there will be a clustering column for each of the composite's components. There can also be mixed column families; supporting those is future work. Signed-off-by: Duarte Nunes --- thrift/handler.cc | 41 ++++++++++++++++++++++++++++++++++++----- 1 file changed, 36 insertions(+), 5 deletions(-) diff --git a/thrift/handler.cc b/thrift/handler.cc index 7fee01bbc4..aaee2bf0e5 100644 --- a/thrift/handler.cc +++ b/thrift/handler.cc @@ -33,6 +33,7 @@ #include "utils/UUID_gen.hh" #include #include +#include "db/marshal/type_parser.hh" #include "service/migration_manager.hh" #include "utils/class_registrator.hh" #include "noexcept_traits.hh" @@ -498,12 +499,24 @@ public: std::vector regular_columns; // FIXME: get this from comparator auto column_name_type = utf8_type; - // FIXME: look at key_alias and key_validator first + // FIXME: look at key_alias and key_validation_class first partition_key.push_back({"key", bytes_type}); - // FIXME: guess clustering keys - for (const ColumnDef& col_def : cf_def.column_metadata) { - // FIXME: look at all fields, not just name - regular_columns.push_back({to_bytes(col_def.name), bytes_type}); + if (cf_def.column_metadata.empty()) { + // Dynamic CF + auto ck_types = get_types(cf_def.comparator_type); + for (uint32_t i = 0; i < ck_types.size(); ++i) { + clustering_key.push_back({"column" + (i + 1), std::move(ck_types[i])}); + } + auto&& vtype = cf_def.__isset.default_validation_class + ? db::marshal::type_parser::parse(sstring_view(cf_def.default_validation_class)) + : utf8_type; + regular_columns.push_back({"value", std::move(vtype)}); + } else { + // Static CF + for (const ColumnDef& col_def : cf_def.column_metadata) { + // FIXME: look at all fields, not just name + regular_columns.push_back({to_bytes(col_def.name), bytes_type}); + } } auto id = utils::UUID_gen::get_time_UUID(); auto s = make_lw_shared(schema(id, ks_def.name, cf_def.name, @@ -620,6 +633,20 @@ private: type += ")"; return type; } + static std::vector get_types(const std::string& thrift_type) { + static const char composite_type[] = "CompositeType"; + std::vector ret; + auto t = sstring_view(thrift_type); + auto composite_idx = t.find(composite_type); + if (composite_idx == sstring_view::npos) { + ret.emplace_back(db::marshal::type_parser::parse(t)); + } else { + t.remove_prefix(composite_idx + sizeof(composite_type) - 1); + auto types = db::marshal::type_parser(t).get_type_parameters(false); + std::move(types.begin(), types.end(), std::back_inserter(ret)); + } + return ret; + } static KsDef get_keyspace_definition(const keyspace& ks) { auto&& meta = ks.metadata(); KsDef def; @@ -674,6 +701,10 @@ private: } return partition_key::from_single_value(*s, std::move(k)); } + static bool is_dynamic(const schema& s) { + // FIXME: what about CFs created from CQL? + return s.clustering_key_size() > 0; + } }; class handler_factory : public CassandraCobSvIfFactory {