Files
scylladb/schema.hh
Pekka Enberg 28b03772f2 Add schema::set_comment() member function
Needed by the cf_prop_defs class to modify a schema object in the
apply_to_cf_metadata() function.

Signed-off-by: Pekka Enberg <penberg@cloudius-systems.com>
2015-03-24 15:04:17 +02:00

205 lines
7.5 KiB
C++

/*
* Copyright (C) 2015 Cloudius Systems, Ltd.
*/
#pragma once
#include <unordered_map>
#include <boost/range/iterator_range.hpp>
#include <boost/range/join.hpp>
#include <boost/range/algorithm/transform.hpp>
#include "cql3/column_specification.hh"
#include "core/shared_ptr.hh"
#include "types.hh"
#include "tuple.hh"
#include "gc_clock.hh"
#include "unimplemented.hh"
using column_id = uint32_t;
class column_definition final {
public:
template<typename ColumnRange>
static std::vector<const column_definition*> vectorize(ColumnRange&& columns) {
std::vector<const column_definition*> r;
boost::transform(std::forward<ColumnRange>(columns), std::back_inserter(r), [] (auto& def) { return &def; });
return r;
}
private:
bytes _name;
public:
enum class column_kind { PARTITION, CLUSTERING, REGULAR, STATIC };
column_definition(bytes name, data_type type, column_id id, column_kind kind);
data_type type;
// Unique within (kind, schema instance).
// schema::position() and component_index() depend on the fact that for PK columns this is
// equivalent to component index.
column_id id;
column_kind kind;
::shared_ptr<cql3::column_specification> column_specification;
bool is_static() const { return kind == column_kind::STATIC; }
bool is_regular() const { return kind == column_kind::REGULAR; }
bool is_partition_key() const { return kind == column_kind::PARTITION; }
bool is_clustering_key() const { return kind == column_kind::CLUSTERING; }
bool is_primary_key() const { return kind == column_kind::PARTITION || kind == column_kind::CLUSTERING; }
bool is_atomic() const { return !type->is_multi_cell(); }
bool is_compact_value() const;
const sstring& name_as_text() const;
const bytes& name() const;
friend std::ostream& operator<<(std::ostream& os, const column_definition& cd) {
return os << cd.name_as_text();
}
uint32_t component_index() const {
assert(is_primary_key());
return id;
}
};
struct thrift_schema {
shared_ptr<abstract_type> partition_key_type;
};
// Schema fields which can be safely default-copied
// FIXME: encapsulate public fields so that we can make this a private inner structure of schema
class raw_schema {
protected:
std::vector<column_definition> _partition_key;
std::vector<column_definition> _clustering_key;
std::vector<column_definition> _regular_columns; // sorted by name
std::vector<column_definition> _static_columns; // sorted by name, present only when there's any clustering column
sstring _comment;
public:
gc_clock::duration default_time_to_live = gc_clock::duration::zero();
sstring ks_name;
sstring cf_name;
lw_shared_ptr<tuple_type<>> partition_key_type;
lw_shared_ptr<tuple_type<>> clustering_key_type;
lw_shared_ptr<tuple_prefix> clustering_key_prefix_type;
data_type regular_column_name_type;
thrift_schema thrift;
};
/*
* Keep this effectively immutable.
*/
class schema final : public raw_schema {
private:
std::unordered_map<bytes, const column_definition*> _columns_by_name;
std::map<bytes, const column_definition*, serialized_compare> _regular_columns_by_name;
public:
struct column {
bytes name;
data_type type;
struct name_compare {
shared_ptr<abstract_type> type;
name_compare(shared_ptr<abstract_type> type) : type(type) {}
bool operator()(const column& cd1, const column& cd2) const {
return type->less(cd1.name, cd2.name);
}
};
};
private:
void build_columns(const std::vector<column>& columns, column_definition::column_kind kind, std::vector<column_definition>& dst);
::shared_ptr<cql3::column_specification> make_column_specification(const column_definition& def);
void rehash_columns();
public:
schema(sstring ks_name, sstring cf_name,
std::vector<column> partition_key,
std::vector<column> clustering_key,
std::vector<column> regular_columns,
std::vector<column> static_columns,
shared_ptr<abstract_type> regular_column_name_type,
sstring comment = {});
schema(const schema&);
void set_comment(const sstring& comment) {
_comment = comment;
}
bool is_dense() const {
return false;
}
bool is_counter() const {
return false;
}
const column_definition* get_column_definition(const bytes& name);
auto regular_begin() {
return _regular_columns.begin();
}
auto regular_end() {
return _regular_columns.end();
}
auto regular_lower_bound(const bytes& name) {
// TODO: use regular_columns and a version of std::lower_bound() with heterogeneous comparator
auto i = _regular_columns_by_name.lower_bound(name);
if (i == _regular_columns_by_name.end()) {
return regular_end();
} else {
return _regular_columns.begin() + i->second->id;
}
}
auto regular_upper_bound(const bytes& name) {
// TODO: use regular_columns and a version of std::upper_bound() with heterogeneous comparator
auto i = _regular_columns_by_name.upper_bound(name);
if (i == _regular_columns_by_name.end()) {
return regular_end();
} else {
return _regular_columns.begin() + i->second->id;
}
}
data_type column_name_type(const column_definition& def) {
return def.kind == column_definition::column_kind::REGULAR ? regular_column_name_type : utf8_type;
}
column_definition& regular_column_at(column_id id) {
return _regular_columns[id];
}
column_definition& static_column_at(column_id id) {
return _static_columns[id];
}
bool is_last_partition_key(const column_definition& def) {
return &_partition_key[_partition_key.size() - 1] == &def;
}
bool has_collections() {
warn(unimplemented::cause::COLLECTIONS);
return false; // FIXME
}
bool has_static_columns() {
return !_static_columns.empty();
}
size_t partition_key_size() const { return _partition_key.size(); }
size_t clustering_key_size() const { return _clustering_key.size(); }
size_t static_columns_count() const { return _static_columns.size(); }
size_t regular_columns_count() const { return _regular_columns.size(); }
// Returns a range of column definitions
auto partition_key_columns() const {
return boost::make_iterator_range(_partition_key.begin(), _partition_key.end());
}
// Returns a range of column definitions
auto clustering_key_columns() const {
return boost::make_iterator_range(_clustering_key.begin(), _clustering_key.end());
}
// Returns a range of column definitions
auto static_columns() const {
return boost::make_iterator_range(_static_columns.begin(), _static_columns.end());
}
// Returns a range of column definitions
auto regular_columns() const {
return boost::make_iterator_range(_regular_columns.begin(), _regular_columns.end());
}
// Returns a range of column definitions
auto all_columns_in_select_order() const {
return boost::join(partition_key_columns(),
boost::join(clustering_key_columns(),
boost::join(static_columns(), regular_columns())));
}
uint32_t position(const column_definition& column) const {
if (column.is_primary_key()) {
return column.id;
}
return _clustering_key.size();
}
};
using schema_ptr = lw_shared_ptr<schema>;