39 #include <boost/algorithm/string.hpp>
45 #include <sys/types.h>
59 using namespace Property;
62 #define MAX_COLUMN_ID 255
65 const std::string maybe_quote(
const string &name) {
66 auto valid_char = [](
char c) {
return isalnum(c); };
67 if (!isalpha(name[0]) ||
68 find_if_not(name.begin(), name.end(), valid_char) != name.end())
69 return String(
"'") + name +
"'";
92 if (src_ag->options().is_set_replication())
94 if (src_ag->options().is_set_blocksize())
96 if (src_ag->options().is_set_compressor())
98 if (src_ag->options().is_set_bloom_filter())
100 if (src_ag->options().is_set_in_memory())
103 if (src_ag->defaults().is_set_max_versions())
105 if (src_ag->defaults().is_set_ttl())
107 if (src_ag->defaults().is_set_time_order_desc())
109 if (src_ag->defaults().is_set_counter())
115 for (
auto src_cf : src_ag->columns())
138 class XmlParserSchema :
public XmlParser {
140 XmlParserSchema(
Schema *schema,
const char *s,
int len) :
141 XmlParser(s,len,{
"AccessGroup",
"AccessGroupDefaults",
"ColumnFamilyDefaults"}),
144 void start_element(
const XML_Char *name,
const XML_Char **atts)
override {
145 if (m_element_stack.empty()) {
146 for (
int i=0; atts[i] != 0; i+=2) {
147 if (!strcasecmp(atts[i],
"generation"))
148 m_schema->set_generation(content_to_i64(atts[i], atts[i+1]));
149 else if (!strcasecmp(atts[i],
"version"))
150 m_schema->set_version(content_to_i32(atts[i], atts[i+1]));
151 else if (!strcasecmp(atts[i],
"group_commit_interval"))
152 m_schema->set_group_commit_interval(content_to_i32(atts[i], atts[i+1]));
153 else if (!strcasecmp(atts[i],
"compressor"))
154 m_schema->access_group_defaults().set_compressor(atts[i+1]);
157 "Unrecognized attribute (%s) in Schema element", atts[i]);
160 else if (strcasecmp(name,
"Generation") &&
161 strcasecmp(name,
"GroupCommitInterval"))
163 "Unrecognized Schema element (%s)", name);
166 void end_element(
const XML_Char *name,
const string &content)
override {
167 if (!strcasecmp(name,
"Generation"))
168 m_schema->set_generation(content_to_i64(name, content));
169 else if (!strcasecmp(name,
"GroupCommitInterval"))
170 m_schema->set_group_commit_interval(content_to_i32(name, content));
171 else if (!m_element_stack.empty())
173 "Unrecognized Schema element (%s)", name);
176 void sub_parse(
const XML_Char *name,
const char *s,
int len)
override {
177 if (!strcasecmp(name,
"AccessGroup")) {
180 catch (
Exception &) {
delete ag_spec;
throw; }
181 m_schema->add_access_group(ag_spec);
183 else if (!strcasecmp(name,
"AccessGroupDefaults")) {
186 m_schema->set_access_group_defaults(defaults);
188 else if (!strcasecmp(name,
"ColumnFamilyDefaults")) {
191 m_schema->set_column_family_defaults(defaults);
204 XmlParserSchema parser(schema, buf.c_str(), buf.length());
219 for (
auto cf : ag->columns())
220 cf->set_generation(0);
227 if (orig_ag ==
nullptr || ag->clear_generation_if_changed(*orig_ag)) {
247 for (
auto cf : ag->columns()) {
248 if (cf->get_generation() == 0) {
249 if (cf->get_id() == 0)
250 cf->set_id(++max_id);
251 cf->set_generation(generation);
252 ag->set_generation(generation);
258 if (ag->get_generation() == 0)
259 ag->set_generation(generation);
266 string output =
"<Schema";
277 output +=
" <AccessGroupDefaults>\n";
279 output +=
" </AccessGroupDefaults>\n";
281 output +=
" <ColumnFamilyDefaults>\n";
283 output +=
" </ColumnFamilyDefaults>\n";
288 output +=
"</Schema>\n";
293 string output =
"CREATE TABLE ";
294 output += maybe_quote(table_name);
298 for (
auto cf_spec : ag_spec->
columns()) {
299 if (!cf_spec->get_deleted()) {
300 output += cf_spec->render_hql();
307 for (
auto ag_spec : m_access_groups) {
309 output += i == m_access_groups.size() ?
"\n" :
",\n";
331 for (
auto cf : ag->columns())
332 if (cf->get_id() > max)
340 for (
auto cf : ag->columns()) {
341 if (!cf->get_deleted()) {
343 if (cf->get_value_index())
345 if (cf->get_qualifier_index())
361 "Attempt to add access group '%s' which already exists",
364 set<string> column_families;
366 column_families.insert(cf->get_name());
368 size_t column_count {};
370 column_count += ag->
columns().size();
371 for (
auto cf : ag->
columns()) {
372 if (column_families.count(cf->get_name()))
374 "Column family '%s' already defined",
375 cf->get_name().c_str());
381 "Attempt to add > %d column families to table",
385 m_access_groups.push_back(ag);
402 ag_map_iter->second->remove_column(name);
418 old_ag = iter->second;
424 new_ags.resize(distance(new_ags.begin(), it));
435 if (get_deleted || !cf_iter->second->get_deleted())
454 "Source column '%s' of rename does not exist", old_name.c_str());
456 if (old_name != new_name) {
457 cf = cf_map_it->second;
464 "Destination column '%s' of rename already exists",
475 "Column family to drop (%s) does not exist",
483 "Invalid access group '%s' for column family '%s'",
486 auto ag_cfs_it = find(ag_it->second->columns().begin(),
487 ag_it->second->columns().end(), cf);
488 if (ag_cfs_it == ag_it->second->columns().end())
490 "Column family '%s' not found in access group '%s'",
497 "Column family '%s' not found in Schema list of columns",
500 ag_it->second->drop_column(name);
506 size_t column_count {};
507 map<string, string> column_to_ag_map;
514 column_count += ag_spec->
columns().size();
517 "Attempt to add > %d column families to table",
519 for (
auto cf_spec : ag_spec->
columns()) {
520 if (cf_spec->get_access_group().empty())
521 cf_spec->set_access_group(ag_spec->
get_name());
522 auto iter = column_to_ag_map.find(cf_spec->get_name());
523 if (iter != column_to_ag_map.end())
525 "Column '%s' assigned to two access groups (%s & %s)",
526 cf_spec->get_name().c_str(), iter->second.c_str(),
528 column_to_ag_map.insert(make_pair(cf_spec->get_name(), ag_spec->
get_name()));
531 if (cf_spec->get_id()) {
533 if (cf_spec->get_option_counter())
545 HT_THROWF(e.
code(),
"Merging column '%s' options with table defaults: %s",
546 cf_spec->
get_name().c_str(), e.what());
555 HT_THROWF(e.
code(),
"Merging access group '%s' options with table defaults: %s",
556 ag_spec->
get_name().c_str(), e.what());
ColumnFamilyOptions m_cf_defaults
Default column family options.
Retrieves system information (hardware, installation directory, etc)
void set_default_max_versions(int32_t max_versions)
Sets default max versions column family option.
void parse_xml(const char *base, int len)
Parses XML options document.
void set_default_ttl(time_t ttl)
Sets default ttl column family option.
void set_generation(int64_t generation)
Sets generation.
CstrColumnFamilyMap m_column_family_map
std::string String
A String is simply a typedef to std::string.
void validate()
Validates schema and reconstructs data structures.
String format(const char *fmt,...)
Returns a String using printf like format facilities Vanilla snprintf is about 1.5x faster than this...
std::vector< AccessGroupSpec * > AccessGroupSpecs
Vector of AccessGroupSpec pointers.
void set_default_counter(bool value)
Sets default counter column family option.
const std::string render_hql() const
Renders options in HQL format.
void parse_xml(const char *base, int len)
Parses XML options specification.
void set_option_bloom_filter(const std::string &bloomfilter)
Sets bloom filter option.
void rename_column_family(const String &old_name, const String &new_name)
Renames a column family.
void set_option_compressor(const std::string &compressor)
Sets compressor option.
Column family specification.
void set_name(const std::string &name)
Sets column family name.
Specification for column family options.
ColumnFamilySpecs m_column_families
&Column family specifications
std::map< int32_t, ColumnFamilySpec * > m_column_family_id_map
Map of column family specifications (key == ID)
void set_generation(int64_t generation)
Sets generation.
std::map< const char *, AccessGroupSpec *, LtCstr, CstrAlloc > CstrAccessGroupMap
Map of access group specifications.
Specification for access group options.
Represents a set of table parts (sub-tables).
const std::string render_xml(const std::string &line_prefix, bool with_ids=false) const
Renders access group specification in XML format.
AccessGroupSpecs & get_access_groups()
Returns reference to access group vector.
CstrAccessGroupMap m_access_group_map
std::map< const char *, ColumnFamilySpec *, LtCstr, CstrAlloc > CstrColumnFamilyMap
Map of column family specifications (key == name)
void drop_column_family(const String &name)
Drops column family.
File system utility functions.
CharT * dup(const CharT *s)
Duplicate a null terminated string; memory is allocated from the pool.
void parse_xml(const char *base, int len)
Parses XML access group specification.
TableParts get_table_parts()
Gets table parts.
bool access_group_exists(const std::string &name) const
Checks if access group exists.
void merge_options(const ColumnFamilyOptions &other)
Merges options from another ColumnFamilyOptions object.
Definitions for XmlParser.
const std::string & get_name() const
Gets access group name.
const std::string render_xml(const std::string &line_prefix) const
Renders options in XML format.
AccessGroupSpec * get_access_group(const std::string &name)
Gets an access group specification given its name.
Logging routines and macros.
void merge_options(const AccessGroupOptions &options)
Merges options with those from another AccessGroupOptions object.
AccessGroupOptions m_ag_defaults
Default access group options.
STL Strict Weak Ordering for comparing c-style strings.
Compatibility Macros for C/C++.
int32_t m_version
Version number.
const std::string & get_access_group() const
Gets access group name.
int32_t get_id() const
Gets column ID.
const std::string render_hql() const
Renders options in HQL format.
Access group specification.
bool clear_generation_if_changed(Schema &original)
Clears generation if different than original.
static Schema * new_instance(const std::string &buf)
Creates schema object from XML schema string.
const std::string & get_name() const
Gets column family name.
long long int Lld
Shortcut for printf formats.
void add_access_group(AccessGroupSpec *ag)
Adds access group specification.
AccessGroupSpecs m_access_groups
Access group specifications.
bool column_family_exists(int32_t id, bool get_deleted=false) const
Checks if column family exists.
std::vector< bool > m_counter_mask
Bitmask describing which column families are counters.
Base class for XML document parsers.
ColumnFamilySpecs & columns()
Returns reference to column specifications.
void set_option_in_memory(bool value)
Sets in memory option.
#define HT_THROWF(_code_, _fmt_,...)
void merge_table_defaults(ColumnFamilySpec *cf_spec)
Merges default column family options into a column family spec.
void clear_generation()
Clears generation values.
const std::string render_hql(const std::string &table_name)
Renders schema as HQL CREATE TABLE statement.
This is a generic exception class for Hypertable.
AccessGroupSpec * replace_access_group(AccessGroupSpec *new_ag)
Replaces access group specification.
const std::string render_xml(const std::string &line_prefix) const
Renders options in XML format.
PageArenaAllocator< const char * > CstrAlloc
int32_t get_max_column_family_id()
Gets the maximum column family ID.
int32_t m_group_commit_interval
Group commit interval.
Schema()
Default constructor.
void set_default_time_order_desc(bool value)
Sets default time order desc column family option.
int64_t m_generation
Generation.
String extensions and helpers: sets, maps, append operators etc.
void set_option_replication(int16_t replication)
Sets replication option.
void add_column(ColumnFamilySpec *cf)
Adds column family specification.
ColumnFamilySpec * remove_column_family(const std::string &name)
Removes column family.
const std::string render_xml(bool with_ids=false)
Renders schema in XML format.
int code() const
Returns the error code.
void update_generation(int64_t generation)
Updates generation and assigns column family IDs.
void set_option_blocksize(int32_t blocksize)
Sets blocksize option.
const std::string render_hql() const
Renders access group specification in HQL format.