in modules/db.mysql/src/db_mysql_diffsqlgen.cpp [766:1085]
void DiffSQLGeneratorBE::generate_alter_stmt(db_mysql_TableRef table, const grt::DiffChange *diffchange,
AlterTableFlags alter_table_flags) {
if (table->isStub())
return;
const grt::ChangeSet *cs = diffchange->subchanges();
if ((alter_table_flags & EverythingButForeignKeys)) {
// process table triggers
for (grt::ChangeSet::const_iterator e = cs->end(), it = cs->begin(); it != e; it++) {
const grt::ObjectAttrModifiedChange *attr_change = static_cast<const grt::ObjectAttrModifiedChange *>(it->get());
if (attr_change->get_attr_name().compare("triggers") == 0) {
const grt::MultiChange *list_change = static_cast<const grt::MultiChange *>(attr_change->get_subchange().get());
const grt::ChangeSet *triggers_cs = list_change->subchanges();
for (grt::ChangeSet::const_iterator e2 = triggers_cs->end(), jt = triggers_cs->begin(); jt != e2; jt++) {
const grt::DiffChange *trigger_change = jt->get();
switch (trigger_change->get_change_type()) {
case grt::ListItemAdded: {
db_mysql_TriggerRef trigger(db_mysql_TriggerRef::cast_from(
static_cast<const grt::ListItemAddedChange *>(trigger_change)->get_value()));
generate_create_stmt(trigger, true);
} break;
case grt::ListItemRemoved: {
db_mysql_TriggerRef trigger(db_mysql_TriggerRef::cast_from(
static_cast<const grt::ListItemRemovedChange *>(trigger_change)->get_value()));
generate_drop_stmt(trigger, true);
} break;
case grt::ListItemModified: {
db_mysql_TriggerRef old_trigger = db_mysql_TriggerRef::cast_from(
grt::ValueRef(static_cast<const grt::ListItemModifiedChange *>(trigger_change)->get_old_value()));
db_mysql_TriggerRef new_trigger = db_mysql_TriggerRef::cast_from(
grt::ValueRef(static_cast<const grt::ListItemModifiedChange *>(trigger_change)->get_new_value()));
generate_drop_stmt(old_trigger, true);
generate_create_stmt(new_trigger, true);
} break;
case grt::ListItemOrderChanged: {
const grt::ListItemOrderChange *order_change =
dynamic_cast<const grt::ListItemOrderChange *>(trigger_change);
if (order_change) // && order_change->get_subchange())
{
// const grt::ListItemModifiedChange *change = dynamic_cast<const
// grt::ListItemModifiedChange *>(order_change->get_subchange().get());
// if (change)
{
generate_drop_stmt(db_mysql_TriggerRef::cast_from(order_change->get_old_value()), true);
generate_create_stmt(db_mysql_TriggerRef::cast_from(order_change->get_new_value()), true);
}
}
}
default:
break;
}
}
}
}
}
const std::string table_name_for_filter(get_old_object_name_for_key(table, _case_sensitive));
if (_use_filtered_lists && (_filtered_tables.find(table_name_for_filter) == _filtered_tables.end()))
return;
bool partitions_processed = false;
cs = diffchange->subchanges();
// check whether all changes detected for this table are dummy changes (index reorders or fk reorders)
bool dummy_changes_only = true;
for (grt::ChangeSet::const_iterator e = cs->end(), it = cs->begin(); it != e; it++) {
const grt::ObjectAttrModifiedChange *attr_change = dynamic_cast<const grt::ObjectAttrModifiedChange *>(it->get());
if (attr_change->get_attr_name().compare("indices") == 0 ||
attr_change->get_attr_name().compare("foreignKeys") == 0) {
const grt::MultiChange *list_change = dynamic_cast<const grt::MultiChange *>(attr_change->get_subchange().get());
// ignore changes if they're only reorderings (with no subchanges)
if (list_change && list_change->subchanges()) {
const grt::ListItemOrderChange *order_change = NULL;
if (list_change->subchanges()->changes.size() == 1)
order_change = dynamic_cast<const grt::ListItemOrderChange *>(list_change->subchanges()->begin()->get());
if (!order_change || order_change->get_subchange()) {
dummy_changes_only = false;
break;
}
}
} else
dummy_changes_only = false;
}
if (dummy_changes_only)
return;
callback->alter_table_props_begin(table);
for (grt::ChangeSet::const_iterator e = cs->end(), it = cs->begin(); it != e; it++) {
const grt::ObjectAttrModifiedChange *attr_change = static_cast<const grt::ObjectAttrModifiedChange *>(it->get());
if (!(alter_table_flags & OnlyForeignKeys) && attr_change->get_attr_name().compare("foreignKeys") == 0)
continue;
else if (!(alter_table_flags & EverythingButForeignKeys) &&
attr_change->get_attr_name().compare("foreignKeys") != 0)
continue;
if (attr_change->get_attr_name().compare("name") == 0) {
const grt::SimpleValueChange *change =
static_cast<const grt::SimpleValueChange *>(attr_change->get_subchange().get());
grt::StringRef str = grt::StringRef::cast_from(change->get_new_value());
callback->alter_table_name(table, str);
}
if (attr_change->get_attr_name().compare("columns") == 0) {
const grt::MultiChange *list_change = static_cast<const grt::MultiChange *>(attr_change->get_subchange().get());
generate_alter(table->columns(), list_change);
} else if (attr_change->get_attr_name().compare("indices") == 0) {
const grt::MultiChange *list_change = static_cast<const grt::MultiChange *>(attr_change->get_subchange().get());
// ignore changes if they're only reorderings
if (list_change && list_change->subchanges()) {
const grt::ListItemOrderChange *order_change = NULL;
if (list_change->subchanges()->changes.size() == 1)
order_change = dynamic_cast<const grt::ListItemOrderChange *>(list_change->subchanges()->begin()->get());
if (!order_change || order_change->get_subchange()) {
callback->alter_table_indexes_begin(table);
generate_alter(table->indices(), list_change);
callback->alter_table_indexes_end(table);
}
}
} else if (attr_change->get_attr_name().compare("foreignKeys") == 0) {
const grt::MultiChange *list_change = static_cast<const grt::MultiChange *>(attr_change->get_subchange().get());
// ignore changes if they're only reorderings
if (list_change && list_change->subchanges()) {
const grt::ListItemOrderChange *order_change = NULL;
if (list_change->subchanges()->changes.size() == 1)
order_change = dynamic_cast<const grt::ListItemOrderChange *>(list_change->subchanges()->begin()->get());
if (!order_change || order_change->get_subchange()) {
callback->alter_table_fks_begin(table);
generate_alter(table->foreignKeys(), list_change);
callback->alter_table_fks_end(table);
}
}
} else if (attr_change->get_attr_name().compare("tableEngine") == 0) {
const grt::SimpleValueChange *change =
static_cast<const grt::SimpleValueChange *>(attr_change->get_subchange().get());
grt::StringRef str = grt::StringRef::cast_from(change->get_new_value());
if (!str.empty())
callback->alter_table_engine(table, str);
} else if (attr_change->get_attr_name().compare("nextAutoInc") == 0) {
const grt::SimpleValueChange *change =
static_cast<const grt::SimpleValueChange *>(attr_change->get_subchange().get());
grt::StringRef str = grt::StringRef::cast_from(change->get_new_value());
callback->alter_table_next_auto_inc(table, str);
} else if (attr_change->get_attr_name().compare("password") == 0) {
const grt::SimpleValueChange *change =
static_cast<const grt::SimpleValueChange *>(attr_change->get_subchange().get());
grt::StringRef str = grt::StringRef::cast_from(change->get_new_value());
callback->alter_table_password(table, str);
} else if (attr_change->get_attr_name().compare("delayKeyWrite") == 0) {
const grt::SimpleValueChange *change =
static_cast<const grt::SimpleValueChange *>(attr_change->get_subchange().get());
grt::IntegerRef n = grt::IntegerRef::cast_from(change->get_new_value());
callback->alter_table_delay_key_write(table, n);
} else if (attr_change->get_attr_name().compare("defaultCharacterSetName") == 0) {
const grt::SimpleValueChange *change =
static_cast<const grt::SimpleValueChange *>(attr_change->get_subchange().get());
grt::StringRef str = grt::StringRef::cast_from(change->get_new_value());
callback->alter_table_charset(table, str);
} else if (attr_change->get_attr_name().compare("defaultCollationName") == 0) {
const grt::SimpleValueChange *change =
static_cast<const grt::SimpleValueChange *>(attr_change->get_subchange().get());
grt::StringRef str = grt::StringRef::cast_from(change->get_new_value());
callback->alter_table_collate(table, str);
} else if (attr_change->get_attr_name().compare("mergeUnion") == 0) {
const grt::SimpleValueChange *change =
static_cast<const grt::SimpleValueChange *>(attr_change->get_subchange().get());
grt::StringRef str = grt::StringRef::cast_from(change->get_new_value());
callback->alter_table_merge_union(table, str);
} else if (attr_change->get_attr_name().compare("mergeInsert") == 0) {
const grt::SimpleValueChange *change =
static_cast<const grt::SimpleValueChange *>(attr_change->get_subchange().get());
grt::StringRef str = grt::StringRef::cast_from(change->get_new_value());
callback->alter_table_merge_insert(table, str);
}
// ALTER TABLE silently ignores these attributes
#if 0
else if(attr_change->get_attr_name().compare("tableDataDir") == 0)
{
const grt::SimpleValueChange *change= static_cast<const grt::SimpleValueChange *>(attr_change->get_subchange().get());
grt::StringRef str= grt::StringRef::cast_from(change->get_new_value());
alter_sql.append("DATA DIRECTORY = '").append(str.c_str()).append("' ");
}
else if(attr_change->get_attr_name().compare("tableIndexDir") == 0)
{
const grt::SimpleValueChange *change= static_cast<const grt::SimpleValueChange *>(attr_change->get_subchange().get());
grt::StringRef str= grt::StringRef::cast_from(change->get_new_value());
alter_sql.append("INDEX DIRECTORY = '").append(str.c_str()).append("' ");
}
#endif
else if (attr_change->get_attr_name().compare("packKeys") == 0) {
const grt::SimpleValueChange *change =
static_cast<const grt::SimpleValueChange *>(attr_change->get_subchange().get());
grt::StringRef str = grt::StringRef::cast_from(change->get_new_value());
callback->alter_table_pack_keys(table, str);
} else if (attr_change->get_attr_name().compare("checksum") == 0) {
const grt::SimpleValueChange *change =
static_cast<const grt::SimpleValueChange *>(attr_change->get_subchange().get());
grt::IntegerRef n = grt::IntegerRef::cast_from(change->get_new_value());
callback->alter_table_checksum(table, n);
} else if (attr_change->get_attr_name().compare("comment") == 0) {
const grt::SimpleValueChange *change =
static_cast<const grt::SimpleValueChange *>(attr_change->get_subchange().get());
grt::StringRef str = grt::StringRef::cast_from(change->get_new_value());
callback->alter_table_comment(table, str);
} else if (attr_change->get_attr_name().compare("rowFormat") == 0) {
const grt::SimpleValueChange *change =
static_cast<const grt::SimpleValueChange *>(attr_change->get_subchange().get());
grt::StringRef str = grt::StringRef::cast_from(change->get_new_value());
callback->alter_table_row_format(table, str);
} else if (attr_change->get_attr_name().compare("keyBlockSize") == 0) {
const grt::SimpleValueChange *change =
static_cast<const grt::SimpleValueChange *>(attr_change->get_subchange().get());
grt::StringRef str = grt::StringRef::cast_from(change->get_new_value());
callback->alter_table_key_block_size(table, str);
} else if (attr_change->get_attr_name().compare("avgRowLength") == 0) {
const grt::SimpleValueChange *change =
static_cast<const grt::SimpleValueChange *>(attr_change->get_subchange().get());
grt::StringRef str = grt::StringRef::cast_from(change->get_new_value());
callback->alter_table_avg_row_length(table, str);
} else if (attr_change->get_attr_name().compare("minRows") == 0) {
const grt::SimpleValueChange *change =
static_cast<const grt::SimpleValueChange *>(attr_change->get_subchange().get());
grt::StringRef str = grt::StringRef::cast_from(change->get_new_value());
callback->alter_table_min_rows(table, str);
} else if (attr_change->get_attr_name().compare("maxRows") == 0) {
const grt::SimpleValueChange *change =
static_cast<const grt::SimpleValueChange *>(attr_change->get_subchange().get());
grt::StringRef str = grt::StringRef::cast_from(change->get_new_value());
callback->alter_table_max_rows(table, str);
}
// to be added later, probably needs support for CREATE/ALTER SERVER
#if 0
else if(attr_change->get_attr_name().compare("connection") == 0)
{
}
#endif
else if (attr_change->get_attr_name().compare("connectionString") == 0) {
const grt::SimpleValueChange *change =
static_cast<const grt::SimpleValueChange *>(attr_change->get_subchange().get());
grt::StringRef str = grt::StringRef::cast_from(change->get_new_value());
callback->alter_table_connection_string(table, str);
} else if (!partitions_processed && ((attr_change->get_attr_name().compare("partitionType") == 0) ||
(attr_change->get_attr_name().compare("partitionExpression") == 0) ||
(attr_change->get_attr_name().compare("subpartitionType") == 0) ||
(attr_change->get_attr_name().compare("subpartitionExpression") == 0) ||
(attr_change->get_attr_name().compare("subpartitionCount") == 0))) {
generate_set_partitioning(table, diffchange);
partitions_processed = true;
}
}
if (alter_table_flags & EverythingButForeignKeys) {
bool is_range = (strcmp(table->partitionType().c_str(), "RANGE") == 0);
// partitioning options that dont require PARTITION BY clause
for (grt::ChangeSet::const_iterator e = cs->end(), it = cs->begin(); (it != e) && !partitions_processed; it++) {
const grt::ObjectAttrModifiedChange *attr_change = static_cast<const grt::ObjectAttrModifiedChange *>(it->get());
if (attr_change->get_attr_name().compare("partitionCount") == 0) {
const grt::SimpleValueChange *change =
static_cast<const grt::SimpleValueChange *>(attr_change->get_subchange().get());
grt::IntegerRef old_count = grt::IntegerRef::cast_from(change->get_old_value());
// std::string part_count_sql(generate_change_partition_count(table, new_count));
//// partition count alone can be changed only for HASH/KEY partitions
//// generate_change_partition_count() will return empty string otherwise
//// for RANGE/LIST we ignore change of this attribute and rely solely on
//// partition definitions change
std::string part_type(table->partitionType().c_str());
if ((part_type.find("HASH") != std::string::npos) || (part_type.find("KEY") != std::string::npos)) {
callback->alter_table_partition_count(table, old_count);
partitions_processed = true;
}
} else if (attr_change->get_attr_name().compare("partitionDefinitions") == 0) {
const grt::MultiChange *list_change = static_cast<const grt::MultiChange *>(attr_change->get_subchange().get());
const grt::ChangeSet *part_cs = list_change->subchanges();
for (grt::ChangeSet::const_iterator e2 = part_cs->end(), jt = part_cs->begin(); jt != e2; jt++) {
const grt::DiffChange *part_change = jt->get();
switch (part_change->get_change_type()) {
case grt::ListItemAdded: {
db_mysql_PartitionDefinitionRef part(db_mysql_PartitionDefinitionRef::cast_from(
static_cast<const grt::ListItemAddedChange *>(part_change)->get_value()));
callback->alter_table_add_partition(part, is_range);
} break;
case grt::ListItemRemoved: {
db_mysql_PartitionDefinitionRef part = db_mysql_PartitionDefinitionRef::cast_from(
static_cast<const grt::ListItemRemovedChange *>(part_change)->get_value());
callback->alter_table_drop_partition(part->name().c_str());
} break;
case grt::ListItemModified: {
db_mysql_PartitionDefinitionRef old_part(db_mysql_PartitionDefinitionRef::cast_from(
static_cast<const grt::ListItemModifiedChange *>(part_change)->get_old_value()));
db_mysql_PartitionDefinitionRef new_part(db_mysql_PartitionDefinitionRef::cast_from(
static_cast<const grt::ListItemModifiedChange *>(part_change)->get_new_value()));
callback->alter_table_reorganize_partition(old_part, new_part, is_range);
} break;
default:
break;
}
partitions_processed = true;
}
}
}
}
callback->alter_table_props_end(table);
}