2
* Copyright (c) 2009, 2012, Oracle and/or its affiliates. All rights reserved.
4
* This program is free software; you can redistribute it and/or
5
* modify it under the terms of the GNU General Public License as
6
* published by the Free Software Foundation; version 2 of the
9
* This program is distributed in the hope that it will be useful,
10
* but WITHOUT ANY WARRANTY; without even the implied warranty of
11
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12
* GNU General Public License for more details.
14
* You should have received a copy of the GNU General Public License
15
* along with this program; if not, write to the Free Software
16
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
22
#include "db_mysql_diffsqlgen.h"
24
#include "diffchange.h"
26
#include "changeobjects.h"
27
#include "changelistobjects.h"
29
#include "db_mysql_diffsqlgen_grant.h"
31
#include "grt/common.h"
36
#include "module_db_mysql.h"
38
void DiffSQLGeneratorBE::remember(const GrtNamedObjectRef &obj, const std::string &sql)
40
if(target_list.is_valid())
42
target_list.insert(grt::StringRef(sql));
43
if(target_object_list.is_valid())
44
target_object_list.insert(obj);
48
target_map.set(get_full_object_name_for_key(obj,_case_sensitive), grt::StringRef(sql));
52
void DiffSQLGeneratorBE::remember_alter(const GrtNamedObjectRef &obj, const std::string &sql)
54
if(target_list.is_valid())
56
target_list.insert(grt::StringRef(sql));
57
if(target_object_list.is_valid())
58
target_object_list.insert(obj);
62
std::string key= get_full_object_name_for_key(obj,_case_sensitive);
64
if(target_map.has_key(key))
66
grt::ValueRef value= target_map.get(key);
67
if(grt::StringRef::can_wrap(value))
69
grt::StringListRef list_value(target_map.get_grt());
70
list_value.insert(grt::StringRef::cast_from(value));
71
list_value.insert(grt::StringRef(sql));
72
target_map.set(key, list_value);
74
else if(grt::StringListRef::can_wrap(value))
76
grt::StringListRef::cast_from(value).insert(grt::StringRef(sql));
86
target_map.set(key, grt::StringRef(sql));
91
struct Part_sort_pred {
92
bool operator() (const std::pair<int, grt::ValueRef>& v1, const std::pair<int, grt::ValueRef>& v2)
98
void DiffSQLGeneratorBE::generate_set_partitioning(db_mysql_TableRef table,
99
const grt::DiffChange *table_diffchange)
101
bool part_type_set= false, part_expr_set= false,
102
subpart_type_set= false, subpart_expr_set= false,
103
part_count_set= false, part_defs_set= false;
104
std::string part_type, part_expr, subpart_type, subpart_expr;
105
grt::ListRef<db_mysql_PartitionDefinition> part_defs(table->get_grt());
108
// gather all relevant attributes from change object
109
const grt::ChangeSet *cs= table_diffchange->subchanges();
110
for(grt::ChangeSet::const_iterator e= cs->end(), it= cs->begin(); it != e; it++)
112
const grt::ObjectAttrModifiedChange *attr_change= static_cast<const grt::ObjectAttrModifiedChange *>(it->get());
114
if(attr_change->get_attr_name().compare("partitionType") == 0)
116
const grt::SimpleValueChange *change=
117
static_cast<const grt::SimpleValueChange *>(attr_change->get_subchange());
118
part_type.assign(grt::StringRef::cast_from(change->get_new_value()));
121
else if(attr_change->get_attr_name().compare("partitionExpression") == 0)
123
const grt::SimpleValueChange *change=
124
static_cast<const grt::SimpleValueChange *>(attr_change->get_subchange());
125
part_expr.assign(grt::StringRef::cast_from(change->get_new_value()));
128
else if(attr_change->get_attr_name().compare("subpartitionType") == 0)
130
const grt::SimpleValueChange *change=
131
static_cast<const grt::SimpleValueChange *>(attr_change->get_subchange());
132
subpart_type.assign(grt::StringRef::cast_from(change->get_new_value()));
133
subpart_type_set= true;
135
else if(attr_change->get_attr_name().compare("subpartitionExpression") == 0)
137
const grt::SimpleValueChange *change=
138
static_cast<const grt::SimpleValueChange *>(attr_change->get_subchange());
139
subpart_expr.assign(grt::StringRef::cast_from(change->get_new_value()));
140
subpart_expr_set= true;
142
else if(attr_change->get_attr_name().compare("partitionCount") == 0)
144
const grt::SimpleValueChange *change=
145
static_cast<const grt::SimpleValueChange *>(attr_change->get_subchange());
146
part_count= grt::IntegerRef::cast_from(change->get_new_value());
147
part_count_set= true;
149
else if(attr_change->get_attr_name().compare("partitionDefinitions") == 0)
151
const grt::MultiChange *change=
152
static_cast<const grt::MultiChange *>(attr_change->get_subchange());
153
const grt::ChangeSet *part_defs_cs= change->subchanges();
155
// needs to be sorted by LESS THAN value
156
std::vector<std::pair<int, grt::ValueRef> > partition_vector;
158
for(grt::ChangeSet::const_iterator part_defs_e= part_defs_cs->end(),
159
part_defs_it= part_defs_cs->begin(); part_defs_it != part_defs_e; part_defs_it++)
161
grt::ValueRef part_def_grt_value;
163
const boost::shared_ptr<grt::DiffChange> part_def_change= *part_defs_it;
164
if(part_def_change->get_change_type() == grt::ListItemAdded)
166
const grt::ListItemAddedChange *added_change=
167
static_cast<const grt::ListItemAddedChange *>(part_def_change.get());
169
part_def_grt_value= added_change->get_value();
171
else if(part_def_change->get_change_type() == grt::ListItemModified)
173
const grt::ListItemModifiedChange *modified_change=
174
static_cast<const grt::ListItemModifiedChange *>(part_def_change.get());
176
part_def_grt_value= modified_change->get_new_value();
179
db_mysql_PartitionDefinitionRef part_def_value(db_mysql_PartitionDefinitionRef::cast_from(part_def_grt_value));
181
if (part_def_value.is_valid())
182
partition_vector.push_back(std::pair<int, grt::ValueRef>(
183
atoi(part_def_value->value().c_str()), part_def_value));
187
std::sort(partition_vector.begin(), partition_vector.end());
189
for(std::vector<std::pair<int, grt::ValueRef> >::const_iterator pv_e= partition_vector.end(),
190
pv_it= partition_vector.begin(); pv_it != pv_e; pv_it++)
192
part_defs.insert(db_mysql_PartitionDefinitionRef::cast_from(pv_it->second));
200
part_type.assign(table->partitionType().c_str());
203
part_expr.assign(table->partitionExpression().c_str());
205
if(!subpart_type_set)
206
subpart_type.assign(table->subpartitionType().c_str());
208
if(!subpart_expr_set)
209
subpart_expr.assign(table->subpartitionExpression().c_str());
212
part_count= table->partitionCount();
215
part_defs= table->partitionDefinitions();
217
callback->alter_table_generate_partitioning(table, part_type, part_expr, part_count,
218
subpart_type, subpart_expr, part_defs);
221
void DiffSQLGeneratorBE::generate_create_partitioning(db_mysql_TableRef table)
223
callback->alter_table_generate_partitioning(table,
224
std::string(table->partitionType().is_valid() ? table->partitionType().c_str() : ""),
225
std::string(table->partitionExpression().is_valid() ? table->partitionExpression().c_str() : ""),
226
table->partitionCount(),
227
std::string(table->subpartitionType().is_valid() ? table->subpartitionType().c_str() : ""),
228
std::string(table->subpartitionExpression().is_valid() ? table->subpartitionExpression().c_str() : ""),
229
table->partitionDefinitions()
233
void DiffSQLGeneratorBE::generate_create_stmt(db_mysql_TableRef table)
238
bool process_table= true;
239
std::string table_name_for_filter(get_old_object_name_for_key(table, _case_sensitive));
240
if(_use_filtered_lists)
241
if(_filtered_tables.find(table_name_for_filter) == _filtered_tables.end())
242
process_table= false;
246
callback->create_table_props_begin(table);
248
// note: for TIMESTAMP columns 'ON UPDATE' are stored in defaultValue field
249
// see http://dev.mysql.com/doc/refman/5.1/en/timestamp.html for more info
251
callback->create_table_columns_begin(table);
253
grt::ListRef<db_mysql_Column> columns= table->columns();
254
for(size_t columns_count= columns.count(), i= 0; i < columns_count; i++)
256
db_mysql_ColumnRef column= columns.get(i);
257
callback->create_table_column(column);
260
callback->create_table_columns_end(table);
262
// indices processing
264
callback->create_table_indexes_begin(table);
266
std::set<db_IndexRef> fk_indexes;
267
std::set<db_IndexRef> fk_create_indexes;
268
std::set<db_IndexRef> fk_skip_indexes;
269
for (size_t fk_count = table->foreignKeys().count(), i= 0; i < fk_count; i++)
271
fk_indexes.insert(table->foreignKeys()[i]->index());
272
(table->foreignKeys()[i]->modelOnly()?fk_skip_indexes:fk_create_indexes).insert(table->foreignKeys()[i]->index());
275
grt::ListRef<db_mysql_Index> indices= table->indices();
276
for(size_t index_count= indices.count(), i= 0; i < index_count; i++)
278
db_mysql_IndexRef index= indices.get(i);
280
if (index->isPrimary())
282
callback->create_table_index(index, false);
286
if (_skip_fk_indexes && (stricmp(index->indexType().c_str(), "FOREIGN") == 0
287
|| fk_indexes.find(index) != fk_indexes.end()))
290
if ((fk_skip_indexes.find(index) != fk_skip_indexes.end())&&(fk_create_indexes.find(index) == fk_create_indexes.end()))
292
callback->create_table_index(index, _gen_create_index);
295
callback->create_table_indexes_end(table);
297
callback->create_table_fks_begin(table);
299
if (!_skip_foreign_keys)
302
grt::ListRef<db_mysql_ForeignKey> fks= table->foreignKeys();
303
for(size_t fk_count= fks.count(), i= 0; i < fk_count; i++)
305
db_mysql_ForeignKeyRef fk= fks.get(i);
306
if (fk.is_valid() && fk->referencedTable().is_valid())
308
if (fk->modelOnly() || fk->referencedTable()->modelOnly())
311
callback->create_table_fk(fk);
316
callback->create_table_fks_end(table);
318
// TODO: [TABLESPACE tablespace_name STORAGE DISK]
320
if(strlen(table->tableEngine().c_str()))
321
callback->create_table_engine(table->tableEngine());
323
if(strlen(table->nextAutoInc().c_str()))
324
callback->create_table_next_auto_inc(table->nextAutoInc());
326
if(strlen(table->avgRowLength().c_str()))
327
callback->create_table_avg_row_length(table->avgRowLength());
329
if(strlen(table->defaultCharacterSetName().c_str()))
330
callback->create_table_charset(table->defaultCharacterSetName());
332
if(table->checksum() != 0)
333
callback->create_table_checksum(table->checksum());
335
if(strlen(table->defaultCollationName().c_str()))
336
callback->create_table_collate(table->defaultCollationName());
338
if(strlen(table->comment().c_str()))
339
callback->create_table_comment(table->comment());
341
// CONNECTION [=] 'connect_string'
343
if(strlen(table->tableDataDir().c_str()))
344
callback->create_table_data_dir(table->tableDataDir());
346
if(table->delayKeyWrite() != 0)
347
callback->create_table_delay_key_write(table->delayKeyWrite());
349
if(strlen(table->tableIndexDir().c_str()))
350
callback->create_table_index_dir(table->tableIndexDir());
352
if(strlen(table->mergeInsert().c_str()))
353
callback->create_table_merge_insert(table->mergeInsert());
355
// KEY_BLOCK_SIZE [=] value
357
if(strlen(table->maxRows().c_str()))
358
callback->create_table_max_rows(table->maxRows());
360
if(strlen(table->minRows().c_str()))
361
callback->create_table_min_rows(table->minRows());
363
if(strlen(table->packKeys().c_str()))
364
callback->create_table_pack_keys(table->packKeys());
366
if(strlen(table->password().c_str()))
367
callback->create_table_password(table->password());
369
if(strlen(table->rowFormat().c_str()))
370
callback->create_table_row_format(table->rowFormat());
372
if(strlen(table->mergeUnion().c_str()))
373
callback->create_table_merge_union(table->mergeUnion());
375
if(table->partitionType().is_valid() && strlen(table->partitionType().c_str())
376
&& table->partitionExpression().is_valid() /*&& strlen(table->partitionExpression().c_str())*/)
378
generate_create_partitioning(table);
381
callback->create_table_props_end(table);
384
grt::ListRef<db_mysql_Trigger> triggers= table->triggers();
385
for(size_t c= triggers.count(), i= 0; i < c; i++)
387
db_mysql_TriggerRef trigger= triggers.get(i);
388
generate_create_stmt(trigger);
392
void DiffSQLGeneratorBE::generate_create_stmt(db_mysql_ViewRef view)
394
std::string view_name_for_filter(get_old_object_name_for_key(view, _case_sensitive));
395
if(_use_filtered_lists)
396
if(_filtered_views.find(view_name_for_filter) == _filtered_views.end())
399
callback->create_view(view);
402
void DiffSQLGeneratorBE::generate_create_stmt(db_mysql_RoutineRef routine, bool for_alter)
404
std::string routine_name_for_filter(get_old_object_name_for_key(routine, _case_sensitive));
405
if(_use_filtered_lists)
406
if(_filtered_routines.find(routine_name_for_filter) == _filtered_routines.end())
409
callback->create_routine(routine, for_alter);
412
void DiffSQLGeneratorBE::generate_create_stmt(db_mysql_TriggerRef trigger, bool for_alter)
414
std::string trigger_name_for_filter(get_old_object_name_for_key(trigger, _case_sensitive));
416
if(_use_filtered_lists)
417
if(_filtered_triggers.find(trigger_name_for_filter) == _filtered_triggers.end())
420
callback->create_trigger(trigger, for_alter);
423
void DiffSQLGeneratorBE::generate_create_stmt(db_mysql_SchemaRef schema)
425
std::string schema_name_for_filter(get_old_object_name_for_key(schema, _case_sensitive));
427
if(_use_filtered_lists)
428
if(_filtered_schemata.find(schema_name_for_filter) == _filtered_schemata.end())
431
callback->create_schema(schema);
433
grt::ListRef<db_mysql_Table> tables= schema->tables();
434
for(size_t count= tables.count(), i= 0; i < count; i++)
436
db_mysql_TableRef table= tables.get(i);
437
generate_create_stmt(table);
440
grt::ListRef<db_mysql_View> views= schema->views();
441
for(size_t count= views.count(), i= 0; i < count; i++)
443
db_mysql_ViewRef view= views.get(i);
444
generate_create_stmt(view);
447
grt::ListRef<db_mysql_Routine> routines= schema->routines();
448
for(size_t count= routines.count(), i= 0; i < count; i++)
450
db_mysql_RoutineRef routine= routines.get(i);
451
generate_create_stmt(routine);
455
void DiffSQLGeneratorBE::generate_create_stmt(db_UserRef user)
457
std::string user_name_for_filter(get_old_object_name_for_key(user, _case_sensitive));
459
if(_use_filtered_lists)
460
if(_filtered_users.find(user_name_for_filter) == _filtered_users.end())
463
callback->create_user(user);
466
void DiffSQLGeneratorBE::generate_create_stmt(db_mysql_CatalogRef catalog)
468
grt::ListRef<db_mysql_Schema> schemata= catalog->schemata();
469
for(size_t count= schemata.count(), i= 0; i < count; i++)
471
db_mysql_SchemaRef schema= schemata.get(i);
472
generate_create_stmt(schema);
475
for(size_t count= catalog->users().count(), i= 0; i < count; i++)
477
db_UserRef user= catalog->users().get(i);
478
generate_create_stmt(user);
482
void DiffSQLGeneratorBE::generate_drop_stmt(db_mysql_TableRef table)
487
std::string table_name_for_filter(get_old_object_name_for_key(table, _case_sensitive));
488
if(_use_filtered_lists)
489
if(_filtered_tables.find(table_name_for_filter) == _filtered_tables.end())
492
callback->drop_table(table);
494
grt::ListRef<db_mysql_Trigger> triggers= table->triggers();
495
for(size_t c= triggers.count(), i= 0; i < c; i++)
497
db_mysql_TriggerRef trigger= triggers.get(i);
498
generate_drop_stmt(trigger);
502
void DiffSQLGeneratorBE::generate_drop_stmt(db_mysql_TriggerRef trigger, bool for_alter)
504
std::string trigger_name_for_filter(get_old_object_name_for_key(trigger, _case_sensitive));
505
if(_use_filtered_lists)
506
if(_filtered_triggers.find(trigger_name_for_filter) == _filtered_triggers.end())
509
callback->drop_trigger(trigger, for_alter);
512
void DiffSQLGeneratorBE::generate_drop_stmt(db_mysql_ViewRef view)
514
std::string view_name_for_filter(get_old_object_name_for_key(view, _case_sensitive));
515
if(_use_filtered_lists)
516
if(_filtered_views.find(view_name_for_filter) == _filtered_views.end())
519
callback->drop_view(view);
522
void DiffSQLGeneratorBE::generate_drop_stmt(db_mysql_RoutineRef routine, bool for_alter)
524
std::string routine_name_for_filter(get_old_object_name_for_key(routine, _case_sensitive));
525
if(_use_filtered_lists)
526
if(_filtered_routines.find(routine_name_for_filter) == _filtered_routines.end())
529
callback->drop_routine(routine, for_alter);
532
void DiffSQLGeneratorBE::generate_drop_stmt(db_UserRef user)
534
callback->drop_user(user);
537
void DiffSQLGeneratorBE::generate_drop_stmt(db_mysql_SchemaRef schema)
539
callback->drop_schema(schema);
541
grt::ListRef<db_mysql_Table> tables= schema->tables();
542
for(size_t count= tables.count(), i= 0; i < count; i++)
544
db_mysql_TableRef table= tables.get(i);
545
generate_drop_stmt(table);
548
grt::ListRef<db_mysql_View> views= schema->views();
549
for(size_t count= views.count(), i= 0; i < count; i++)
551
db_mysql_ViewRef view= views.get(i);
552
generate_drop_stmt(view);
555
grt::ListRef<db_mysql_Routine> routines= schema->routines();
556
for(size_t count= routines.count(), i= 0; i < count; i++)
558
db_mysql_RoutineRef routine= routines.get(i);
559
generate_drop_stmt(routine);
563
void DiffSQLGeneratorBE::generate_drop_stmt(db_mysql_CatalogRef catalog)
565
grt::ListRef<db_mysql_Schema> schemata= catalog->schemata();
566
for(size_t count= schemata.count(), i= 0; i < count; i++)
568
db_mysql_SchemaRef schema= schemata.get(i);
569
generate_drop_stmt(schema);
572
for(size_t count= catalog->users().count(), i= 0; i < count; i++)
574
db_UserRef user= catalog->users().get(i);
575
generate_drop_stmt(user);
579
void DiffSQLGeneratorBE::generate_alter(grt::ListRef<db_mysql_Column> columns, const grt::MultiChange *diffchange)
581
const grt::ChangeSet *columns_cs= diffchange->subchanges();
583
if(columns.count() == 0)
586
db_mysql_TableRef table= db_mysql_TableRef::cast_from(columns.get(0)->owner());
588
callback->alter_table_columns_begin(table);
590
Column_rename_map column_rename_map;
592
// build a map of column renames
593
for(grt::ChangeSet::const_iterator e= columns_cs->end(), it= columns_cs->begin(); it != e; it++)
595
// process CHANGE COLUMN (handles content change only)
596
for(grt::ChangeSet::const_iterator e= columns_cs->end(), it= columns_cs->begin(); it != e; it++)
598
const boost::shared_ptr<grt::DiffChange> column_change= *it;
600
if(column_change->get_change_type() == grt::ListItemModified)
602
const grt::ListItemModifiedChange *modified_change= static_cast<const grt::ListItemModifiedChange *>(column_change.get());
603
db_mysql_ColumnRef column= db_mysql_ColumnRef::cast_from(grt::ValueRef(modified_change->get_new_value()));
604
if(strcmp(column->name().c_str(), column->oldName().c_str()))
605
column_rename_map[std::string(column->oldName().c_str())]= std::string(column->name().c_str());
607
else if(column_change->get_change_type() == grt::ListItemOrderChanged)
609
const grt::ListItemOrderChange *order_change= static_cast<const grt::ListItemOrderChange *>(column_change.get());
610
db_mysql_ColumnRef org_col= db_mysql_ColumnRef::cast_from(grt::ValueRef(order_change->get_old_value()));
611
db_mysql_ColumnRef mod_col= db_mysql_ColumnRef::cast_from(grt::ValueRef(order_change->get_new_value()));
612
if(strcmp(org_col->name().c_str(), mod_col->oldName().c_str()))
613
column_rename_map[std::string(org_col->oldName().c_str())]= std::string(mod_col->name().c_str());
618
// process DROP COLUMN
619
for(grt::ChangeSet::const_iterator e= columns_cs->end(), it= columns_cs->begin(); it != e; it++)
621
const boost::shared_ptr<grt::DiffChange> column_change= *it;
622
if(column_change->get_change_type() != grt::ListItemRemoved)
625
const grt::ListItemRemovedChange *removed_change= static_cast<const grt::ListItemRemovedChange *>(column_change.get());
626
callback->alter_table_drop_column(table, db_mysql_ColumnRef::cast_from(removed_change->get_value()));
629
// process ADD COLUMN
630
for(grt::ChangeSet::const_iterator e= columns_cs->end(), it= columns_cs->begin(); it != e; it++)
632
const boost::shared_ptr<grt::DiffChange> column_change= *it;
633
if(column_change->get_change_type() != grt::ListItemAdded)
636
const grt::ListItemAddedChange *added_change= static_cast<const grt::ListItemAddedChange *>(column_change.get());
638
callback->alter_table_add_column(
641
db_mysql_ColumnRef::cast_from(grt::ValueRef(added_change->get_value())),
642
db_mysql_ColumnRef::cast_from(added_change->get_prev_item()));
645
std::set<grt::ValueRef> processed_items;
647
// process CHANGE COLUMN (handles both position and content change)
648
for(grt::ChangeSet::const_iterator e= columns_cs->end(), it= columns_cs->begin(); it != e; it++)
650
const boost::shared_ptr<grt::DiffChange> column_change= *it;
652
if(column_change->get_change_type() != grt::ListItemOrderChanged)
655
const grt::ListItemOrderChange *order_change=
656
static_cast<const grt::ListItemOrderChange *>(column_change.get());
657
// index_pair.second is the new position
658
callback->alter_table_change_column(
660
db_mysql_ColumnRef::cast_from(grt::ValueRef(order_change->get_old_value())),
661
db_mysql_ColumnRef::cast_from(grt::ValueRef(order_change->get_new_value())),
662
// v == NULL ? db_mysql_ColumnRef() : db_mysql_ColumnRef::cast_from(grt::ValueRef(*v)),
663
db_mysql_ColumnRef::cast_from(order_change->get_prev_item()),
669
// process CHANGE COLUMN (handles content change only)
670
for(grt::ChangeSet::const_iterator e= columns_cs->end(), it= columns_cs->begin(); it != e; it++)
672
const boost::shared_ptr<grt::DiffChange> column_change= *it;
674
if(column_change->get_change_type() != grt::ListItemModified)
677
const grt::ListItemModifiedChange *modified_change= static_cast<const grt::ListItemModifiedChange *>(column_change.get());
679
callback->alter_table_change_column(
681
db_mysql_ColumnRef::cast_from(grt::ValueRef(modified_change->get_new_value())),
682
db_mysql_ColumnRef(),
683
db_mysql_ColumnRef(),
689
callback->alter_table_columns_end(table);
692
void DiffSQLGeneratorBE::generate_alter(grt::ListRef<db_mysql_Index> indices, const grt::MultiChange *diffchange)
694
const grt::ChangeSet *indices_cs= diffchange->subchanges();
696
for(grt::ChangeSet::const_iterator e= indices_cs->end(), it= indices_cs->begin(); it != e; it++)
698
const boost::shared_ptr<grt::DiffChange> index_change= *it;
700
switch(index_change->get_change_type())
702
case grt::ListItemAdded: // ADD INDEX
704
const grt::ListItemAddedChange *added_change= static_cast<const grt::ListItemAddedChange *>(index_change.get());
705
callback->alter_table_add_index(db_mysql_IndexRef::cast_from(added_change->get_value()));
708
case grt::ListItemRemoved: // DROP INDEX
710
const grt::ListItemRemovedChange *removed_change= static_cast<const grt::ListItemRemovedChange *>(index_change.get());
711
callback->alter_table_drop_index(db_mysql_IndexRef::cast_from(removed_change->get_value()));
714
case grt::ListItemOrderChanged: // DROP/ADD INDEX
716
const grt::ListItemOrderChange *order_change= static_cast<const grt::ListItemOrderChange *>(index_change.get());
717
//Only position changed nothing to do
718
if (!order_change->get_subchange())
720
callback->alter_table_drop_index(db_mysql_IndexRef::cast_from(order_change->get_old_value()));
721
callback->alter_table_add_index(db_mysql_IndexRef::cast_from(order_change->get_new_value()));
725
case grt::ListItemModified:
727
const grt::ListItemModifiedChange *modified_change= static_cast<const grt::ListItemModifiedChange *>(index_change.get());
729
callback->alter_table_drop_index(db_mysql_IndexRef::cast_from(modified_change->get_new_value()));
730
callback->alter_table_add_index(db_mysql_IndexRef::cast_from(modified_change->get_new_value()));
738
void DiffSQLGeneratorBE::generate_alter_drop(
739
grt::ListRef<db_mysql_ForeignKey> fks, const grt::MultiChange *diffchange)
742
You cannot add a foreign key and drop a foreign key in separate
743
clauses of a single ALTER TABLE statement. You must use separate
747
const grt::ChangeSet *fks_cs= diffchange->subchanges();
749
for(grt::ChangeSet::const_iterator e= fks_cs->end(), it= fks_cs->begin(); it != e; it++)
751
const boost::shared_ptr<grt::DiffChange> fk_change= *it;
753
db_mysql_ForeignKeyRef fk1;
754
switch(fk_change->get_change_type())
756
case grt::ListItemRemoved: // DROP FK
758
const grt::ListItemRemovedChange *removed_change= static_cast<const grt::ListItemRemovedChange *>(fk_change.get());
759
fk1= db_mysql_ForeignKeyRef::cast_from(removed_change->get_value());
762
case grt::ListItemModified:
764
const grt::ListItemModifiedChange *modified_change= static_cast<const grt::ListItemModifiedChange *>(fk_change.get());
765
fk1= db_mysql_ForeignKeyRef::cast_from(modified_change->get_old_value());
771
if (fk1.is_valid() && (fk1->modelOnly() || !fk1->referencedTable().is_valid() || fk1->referencedTable()->modelOnly()))
774
switch(fk_change->get_change_type())
776
case grt::ListItemRemoved: // DROP FK
778
const grt::ListItemRemovedChange *removed_change= static_cast<const grt::ListItemRemovedChange *>(fk_change.get());
779
callback->alter_table_drop_fk(db_mysql_ForeignKeyRef::cast_from(removed_change->get_value()));
782
case grt::ListItemModified:
784
const grt::ListItemModifiedChange *modified_change= static_cast<const grt::ListItemModifiedChange *>(fk_change.get());
785
callback->alter_table_drop_fk(db_mysql_ForeignKeyRef::cast_from(modified_change->get_old_value()));
793
void DiffSQLGeneratorBE::generate_alter(
794
grt::ListRef<db_mysql_ForeignKey> fks, const grt::MultiChange *diffchange)
797
You cannot add a foreign key and drop a foreign key in separate
798
clauses of a single ALTER TABLE statement. You must use separate
802
const grt::ChangeSet *fks_cs= diffchange->subchanges();
804
for(grt::ChangeSet::const_iterator e= fks_cs->end(), it= fks_cs->begin(); it != e; it++)
806
const boost::shared_ptr<grt::DiffChange> fk_change= *it;
808
db_mysql_ForeignKeyRef fk1, fk2;
809
switch(fk_change->get_change_type())
811
case grt::ListItemAdded: // ADD FK
813
const grt::ListItemAddedChange *added_change= static_cast<const grt::ListItemAddedChange *>(fk_change.get());
814
fk1= db_mysql_ForeignKeyRef::cast_from(added_change->get_value());
817
case grt::ListItemRemoved: // DROP FK
819
const grt::ListItemRemovedChange *removed_change= static_cast<const grt::ListItemRemovedChange *>(fk_change.get());
820
fk1= db_mysql_ForeignKeyRef::cast_from(removed_change->get_value());
823
case grt::ListItemOrderChanged: // DROP/ADD FK
825
const grt::ListItemOrderChange *order_change= static_cast<const grt::ListItemOrderChange *>(fk_change.get());
826
fk1= db_mysql_ForeignKeyRef::cast_from(order_change->get_old_value());
827
fk2= db_mysql_ForeignKeyRef::cast_from(order_change->get_new_value());
830
case grt::ListItemModified:
832
const grt::ListItemModifiedChange *modified_change= static_cast<const grt::ListItemModifiedChange *>(fk_change.get());
833
fk1= db_mysql_ForeignKeyRef::cast_from(modified_change->get_old_value());
834
fk2= db_mysql_ForeignKeyRef::cast_from(modified_change->get_new_value());
840
if (fk1.is_valid() && (fk1->modelOnly() || !fk1->referencedTable().is_valid() || fk1->referencedTable()->modelOnly()))
842
if (fk2.is_valid() && (fk2->modelOnly() || !fk2->referencedTable().is_valid() || fk2->referencedTable()->modelOnly()))
845
switch(fk_change->get_change_type())
847
case grt::ListItemAdded: // ADD FK
849
const grt::ListItemAddedChange *added_change= static_cast<const grt::ListItemAddedChange *>(fk_change.get());
850
callback->alter_table_add_fk(db_mysql_ForeignKeyRef::cast_from(added_change->get_value()));
853
case grt::ListItemRemoved: // DROP FK
855
const grt::ListItemRemovedChange *removed_change= static_cast<const grt::ListItemRemovedChange *>(fk_change);
856
callback->alter_table_drop_fk(db_mysql_ForeignKeyRef::cast_from(removed_change->get_old_value()));
859
case grt::ListItemOrderChanged: // DROP/ADD FK
861
const grt::ListItemOrderChange *order_change= static_cast<const grt::ListItemOrderChange *>(fk_change.get());
862
callback->alter_table_drop_fk(db_mysql_ForeignKeyRef::cast_from(order_change->get_old_value()));
863
callback->alter_table_add_fk(db_mysql_ForeignKeyRef::cast_from(order_change->get_new_value()));
867
case grt::ListItemModified:
869
const grt::ListItemModifiedChange *modified_change= static_cast<const grt::ListItemModifiedChange *>(fk_change.get());
870
// callback->alter_table_drop_fk(db_mysql_ForeignKeyRef::cast_from(modified_change->get_old_value()));
871
callback->alter_table_add_fk(db_mysql_ForeignKeyRef::cast_from(modified_change->get_new_value()));
879
void DiffSQLGeneratorBE::generate_alter_stmt_drops(db_mysql_TableRef table, const grt::DiffChange *diffchange)
884
bool process_table= true;
886
std::string table_name_for_filter(get_old_object_name_for_key(table, _case_sensitive));
887
if(_use_filtered_lists)
888
if(_filtered_tables.find(table_name_for_filter) == _filtered_tables.end())
889
process_table= false;
892
const grt::ChangeSet* cs= diffchange->subchanges();
894
callback->alter_table_props_begin(table);
896
for(grt::ChangeSet::const_iterator e= cs->end(), it= cs->begin(); it != e; it++)
898
const grt::ObjectAttrModifiedChange *attr_change=
899
static_cast<const grt::ObjectAttrModifiedChange *>(it->get());
901
if(attr_change->get_attr_name().compare("foreignKeys") == 0)
903
const grt::MultiChange *list_change=
904
static_cast<const grt::MultiChange *>(attr_change->get_subchange());
906
callback->alter_table_fks_begin(table);
907
generate_alter_drop(table->foreignKeys(), list_change);
908
callback->alter_table_fks_end(table);
912
callback->alter_table_props_end(table);
916
void DiffSQLGeneratorBE::generate_alter_stmt(db_mysql_TableRef table, const grt::DiffChange *diffchange)
921
bool process_table= true;
923
std::string table_name_for_filter(get_old_object_name_for_key(table, _case_sensitive));
924
if(_use_filtered_lists)
925
if(_filtered_tables.find(table_name_for_filter) == _filtered_tables.end())
926
process_table= false;
928
// process table triggers
929
const grt::ChangeSet *cs= diffchange->subchanges();
931
for(grt::ChangeSet::const_iterator e= cs->end(), it= cs->begin(); it != e; it++)
933
const grt::ObjectAttrModifiedChange *attr_change=
934
static_cast<const grt::ObjectAttrModifiedChange *>(it->get());
936
if(attr_change->get_attr_name().compare("triggers") == 0)
938
const grt::MultiChange *list_change=
939
static_cast<const grt::MultiChange *>(attr_change->get_subchange());
941
const grt::ChangeSet *triggers_cs= list_change->subchanges();
943
for(grt::ChangeSet::const_iterator e2= triggers_cs->end(), jt= triggers_cs->begin(); jt != e2; jt++)
945
const grt::DiffChange *trigger_change= jt->get();
947
switch(trigger_change->get_change_type())
949
case grt::ListItemAdded:
951
db_mysql_TriggerRef trigger(db_mysql_TriggerRef::cast_from(
952
static_cast<const grt::ListItemAddedChange *>(trigger_change)->get_value()));
953
generate_create_stmt(trigger, false);
956
case grt::ListItemRemoved:
958
db_mysql_TriggerRef trigger(db_mysql_TriggerRef::cast_from(
959
static_cast<const grt::ListItemRemovedChange *>(trigger_change)->get_value()));
960
generate_drop_stmt(trigger, false);
963
case grt::ListItemModified:
965
db_mysql_TriggerRef old_trigger= db_mysql_TriggerRef::cast_from(
966
grt::ValueRef(static_cast<const grt::ListItemModifiedChange *>
967
(trigger_change)->get_old_value()));
968
db_mysql_TriggerRef new_trigger= db_mysql_TriggerRef::cast_from(
969
grt::ValueRef(static_cast<const grt::ListItemModifiedChange *>
970
(trigger_change)->get_new_value()));
972
generate_drop_stmt(old_trigger);
973
generate_create_stmt(new_trigger);
976
// list item position change is not relevant
986
bool partitions_processed= false;
987
cs= diffchange->subchanges();
989
callback->alter_table_props_begin(table);
991
for(grt::ChangeSet::const_iterator e= cs->end(), it= cs->begin(); it != e; it++)
993
const grt::ObjectAttrModifiedChange *attr_change=
994
static_cast<const grt::ObjectAttrModifiedChange *>(it->get());
996
if(attr_change->get_attr_name().compare("name") == 0)
998
const grt::SimpleValueChange *change=
999
static_cast<const grt::SimpleValueChange *>(attr_change->get_subchange());
1000
grt::StringRef str= grt::StringRef::cast_from(change->get_new_value());
1001
callback->alter_table_name(table, str);
1003
if(attr_change->get_attr_name().compare("columns") == 0)
1005
const grt::MultiChange *list_change=
1006
static_cast<const grt::MultiChange *>(attr_change->get_subchange());
1007
generate_alter(table->columns(), list_change);
1009
else if(attr_change->get_attr_name().compare("indices") == 0)
1011
const grt::MultiChange *list_change=
1012
static_cast<const grt::MultiChange *>(attr_change->get_subchange());
1013
callback->alter_table_indexes_begin(table);
1014
generate_alter(table->indices(), list_change);
1015
callback->alter_table_indexes_end(table);
1017
else if(attr_change->get_attr_name().compare("foreignKeys") == 0)
1019
const grt::MultiChange *list_change=
1020
static_cast<const grt::MultiChange *>(attr_change->get_subchange());
1022
callback->alter_table_fks_begin(table);
1023
generate_alter(table->foreignKeys(), list_change);
1024
callback->alter_table_fks_end(table);
1026
else if(attr_change->get_attr_name().compare("tableEngine") == 0)
1028
const grt::SimpleValueChange *change=
1029
static_cast<const grt::SimpleValueChange *>(attr_change->get_subchange());
1030
grt::StringRef str= grt::StringRef::cast_from(change->get_new_value());
1031
callback->alter_table_engine(table, str);
1033
else if(attr_change->get_attr_name().compare("nextAutoInc") == 0)
1035
const grt::SimpleValueChange *change=
1036
static_cast<const grt::SimpleValueChange *>(attr_change->get_subchange());
1037
grt::StringRef str= grt::StringRef::cast_from(change->get_new_value());
1038
callback->alter_table_next_auto_inc(table, str);
1040
else if(attr_change->get_attr_name().compare("password") == 0)
1042
const grt::SimpleValueChange *change=
1043
static_cast<const grt::SimpleValueChange *>(attr_change->get_subchange());
1044
grt::StringRef str= grt::StringRef::cast_from(change->get_new_value());
1045
callback->alter_table_password(table, str);
1047
else if(attr_change->get_attr_name().compare("delayKeyWrite") == 0)
1049
const grt::SimpleValueChange *change=
1050
static_cast<const grt::SimpleValueChange *>(attr_change->get_subchange());
1051
grt::IntegerRef n= grt::IntegerRef::cast_from(change->get_new_value());
1052
callback->alter_table_delay_key_write(table, n);
1054
else if(attr_change->get_attr_name().compare("defaultCharacterSetName") == 0)
1056
const grt::SimpleValueChange *change=
1057
static_cast<const grt::SimpleValueChange *>(attr_change->get_subchange());
1058
grt::StringRef str= grt::StringRef::cast_from(change->get_new_value());
1059
callback->alter_table_charset(table, str);
1061
else if(attr_change->get_attr_name().compare("defaultCollationName") == 0)
1063
const grt::SimpleValueChange *change=
1064
static_cast<const grt::SimpleValueChange *>(attr_change->get_subchange());
1065
grt::StringRef str= grt::StringRef::cast_from(change->get_new_value());
1066
callback->alter_table_collate(table, str);
1068
else if(attr_change->get_attr_name().compare("mergeUnion") == 0)
1070
const grt::SimpleValueChange *change=
1071
static_cast<const grt::SimpleValueChange *>(attr_change->get_subchange());
1072
grt::StringRef str= grt::StringRef::cast_from(change->get_new_value());
1073
callback->alter_table_merge_union(table, str);
1075
else if(attr_change->get_attr_name().compare("mergeInsert") == 0)
1077
const grt::SimpleValueChange *change=
1078
static_cast<const grt::SimpleValueChange *>(attr_change->get_subchange());
1079
grt::StringRef str= grt::StringRef::cast_from(change->get_new_value());
1080
callback->alter_table_merge_insert(table, str);
1082
// ALTER TABLE silently ignores these attributes
1084
else if(attr_change->get_attr_name().compare("tableDataDir") == 0)
1086
const grt::SimpleValueChange *change= static_cast<const grt::SimpleValueChange *>(attr_change->get_subchange());
1087
grt::StringRef str= grt::StringRef::cast_from(change->get_new_value());
1088
alter_sql.append("DATA DIRECTORY = '").append(str.c_str()).append("' ");
1090
else if(attr_change->get_attr_name().compare("tableIndexDir") == 0)
1092
const grt::SimpleValueChange *change= static_cast<const grt::SimpleValueChange *>(attr_change->get_subchange());
1093
grt::StringRef str= grt::StringRef::cast_from(change->get_new_value());
1094
alter_sql.append("INDEX DIRECTORY = '").append(str.c_str()).append("' ");
1097
else if(attr_change->get_attr_name().compare("packKeys") == 0)
1099
const grt::SimpleValueChange *change=
1100
static_cast<const grt::SimpleValueChange *>(attr_change->get_subchange());
1101
grt::StringRef str= grt::StringRef::cast_from(change->get_new_value());
1102
callback->alter_table_pack_keys(table, str);
1104
else if(attr_change->get_attr_name().compare("checksum") == 0)
1106
const grt::SimpleValueChange *change=
1107
static_cast<const grt::SimpleValueChange *>(attr_change->get_subchange());
1108
grt::IntegerRef n= grt::IntegerRef::cast_from(change->get_new_value());
1109
callback->alter_table_checksum(table, n);
1111
else if(attr_change->get_attr_name().compare("comment") == 0)
1113
const grt::SimpleValueChange *change=
1114
static_cast<const grt::SimpleValueChange *>(attr_change->get_subchange());
1115
grt::StringRef str= grt::StringRef::cast_from(change->get_new_value());
1116
callback->alter_table_comment(table, str);
1118
else if(attr_change->get_attr_name().compare("rowFormat") == 0)
1120
const grt::SimpleValueChange *change= static_cast<const grt::SimpleValueChange *>(attr_change->get_subchange());
1121
grt::StringRef str= grt::StringRef::cast_from(change->get_new_value());
1122
callback->alter_table_row_format(table, str);
1124
else if(attr_change->get_attr_name().compare("avgRowLength") == 0)
1126
const grt::SimpleValueChange *change=
1127
static_cast<const grt::SimpleValueChange *>(attr_change->get_subchange());
1128
grt::StringRef str= grt::StringRef::cast_from(change->get_new_value());
1129
callback->alter_table_avg_row_length(table, str);
1131
else if(attr_change->get_attr_name().compare("minRows") == 0)
1133
const grt::SimpleValueChange *change=
1134
static_cast<const grt::SimpleValueChange *>(attr_change->get_subchange());
1135
grt::StringRef str= grt::StringRef::cast_from(change->get_new_value());
1136
callback->alter_table_min_rows(table, str);
1138
else if(attr_change->get_attr_name().compare("maxRows") == 0)
1140
const grt::SimpleValueChange *change=
1141
static_cast<const grt::SimpleValueChange *>(attr_change->get_subchange());
1142
grt::StringRef str= grt::StringRef::cast_from(change->get_new_value());
1143
callback->alter_table_max_rows(table, str);
1145
// to be added later, probably needs support for CREATE/ALTER SERVER
1147
else if(attr_change->get_attr_name().compare("connection") == 0)
1151
else if(attr_change->get_attr_name().compare("connectionString") == 0)
1153
const grt::SimpleValueChange *change=
1154
static_cast<const grt::SimpleValueChange *>(attr_change->get_subchange());
1155
grt::StringRef str= grt::StringRef::cast_from(change->get_new_value());
1156
callback->alter_table_connection_string(table, str);
1158
else if((attr_change->get_attr_name().compare("partitionType") == 0)
1159
|| (attr_change->get_attr_name().compare("partitionExpression") == 0)
1160
|| (attr_change->get_attr_name().compare("subpartitionType") == 0)
1161
|| (attr_change->get_attr_name().compare("subpartitionExpression") == 0)
1162
|| (attr_change->get_attr_name().compare("subpartitionCount") == 0))
1164
if(partitions_processed)
1167
const grt::SimpleValueChange *change=
1168
static_cast<const grt::SimpleValueChange *>(attr_change->get_subchange());
1169
grt::StringRef new_str= grt::StringRef::cast_from(change->get_new_value());
1170
grt::StringRef old_str= grt::StringRef::cast_from(change->get_old_value());
1172
if ((strlen(new_str.c_str()) == 0) && ((attr_change->get_attr_name().compare("partitionExpression") != 0))) // drop partitioning
1173
callback->alter_table_drop_partitioning(table);
1174
else // add/change partitioning
1175
generate_set_partitioning(table, diffchange);
1177
partitions_processed= true;
1181
continue; // avoid setting comma, see below
1185
bool is_range= (strcmp(table->partitionType().c_str(), "RANGE") == 0);
1187
// partitioning options that dont require PARTITION BY clause
1188
for(grt::ChangeSet::const_iterator e= cs->end(), it= cs->begin();
1189
(it != e) && !partitions_processed; it++)
1191
const grt::ObjectAttrModifiedChange *attr_change=
1192
static_cast<const grt::ObjectAttrModifiedChange *>(it->get());
1194
if(attr_change->get_attr_name().compare("partitionCount") == 0)
1196
const grt::SimpleValueChange *change=
1197
static_cast<const grt::SimpleValueChange *>(attr_change->get_subchange());
1198
grt::IntegerRef new_count= grt::IntegerRef::cast_from(change->get_new_value());
1200
//std::string part_count_sql(generate_change_partition_count(table, new_count));
1202
//// partition count alone can be changed only for HASH/KEY partitions
1203
//// generate_change_partition_count() will return empty string otherwise
1204
//// for RANGE/LIST we ignore change of this attribute and rely solely on
1205
//// partition definitions change
1206
//if(!part_count_sql.empty())
1208
// alter_sql.append(comma).append(part_count_sql);
1209
// partitions_processed= true;
1212
std::string part_type(table->partitionType().c_str());
1214
if((part_type.find("HASH") != std::string::npos)
1215
|| (part_type.find("KEY") != std::string::npos))
1217
callback->alter_table_partition_count(table, new_count);
1218
partitions_processed= true;
1221
else if(attr_change->get_attr_name().compare("partitionDefinitions") == 0)
1223
const grt::MultiChange *list_change= static_cast<const grt::MultiChange *>(attr_change->get_subchange());
1224
const grt::ChangeSet *part_cs= list_change->subchanges();
1225
for(grt::ChangeSet::const_iterator e2= part_cs->end(), jt= part_cs->begin(); jt != e2; jt++)
1227
const grt::DiffChange *part_change= jt->get();
1228
switch(part_change->get_change_type())
1230
case grt::ListItemAdded:
1232
db_mysql_PartitionDefinitionRef part(db_mysql_PartitionDefinitionRef::cast_from(
1233
static_cast<const grt::ListItemAddedChange *>(part_change)->get_value()));
1234
callback->alter_table_add_partition(part, is_range);
1237
case grt::ListItemRemoved:
1239
db_mysql_PartitionDefinitionRef part= db_mysql_PartitionDefinitionRef::cast_from(
1240
static_cast<const grt::ListItemRemovedChange *>(part_change)->get_value());
1242
callback->alter_table_drop_partition(part->name().c_str());
1245
case grt::ListItemModified:
1247
db_mysql_PartitionDefinitionRef old_part(db_mysql_PartitionDefinitionRef::cast_from(
1248
static_cast<const grt::ListItemModifiedChange *>(part_change)->get_old_value()));
1249
db_mysql_PartitionDefinitionRef new_part(db_mysql_PartitionDefinitionRef::cast_from(
1250
static_cast<const grt::ListItemModifiedChange *>(part_change)->get_new_value()));
1252
callback->alter_table_reorganize_partition(old_part, new_part, is_range);
1258
partitions_processed= true;
1263
callback->alter_table_props_end(table);
1266
void DiffSQLGeneratorBE::generate_alter_stmt(db_mysql_ViewRef old_view, db_mysql_ViewRef new_view, const grt::DiffChange *diffchange)
1268
std::string view_name_for_filter(get_old_object_name_for_key(new_view, _case_sensitive));
1269
if(_use_filtered_lists)
1270
if(_filtered_views.find(view_name_for_filter) == _filtered_views.end())
1273
generate_create_stmt(new_view);
1275
if(strcmp(old_view->name().c_str(), new_view->name().c_str())) // name changed - need to drop old view
1276
generate_drop_stmt(old_view);
1279
void DiffSQLGeneratorBE::generate_routine_alter_stmt(db_mysql_RoutineRef old_routine, db_mysql_RoutineRef new_routine, const grt::DiffChange *diffchange)
1281
std::string routine_name_for_filter(get_old_object_name_for_key(new_routine, _case_sensitive));
1282
if(_use_filtered_lists)
1283
if(_filtered_routines.find(routine_name_for_filter) == _filtered_routines.end())
1286
generate_drop_stmt(old_routine);
1288
generate_create_stmt(new_routine);
1291
void DiffSQLGeneratorBE::generate_alter_stmt(db_mysql_SchemaRef schema, const grt::DiffChange *diffchange)
1293
bool process_alter_schema= true;
1294
std::string schema_name_for_filter(get_old_object_name_for_key(schema, _case_sensitive));
1296
if(_use_filtered_lists)
1297
if(_filtered_schemata.find(schema_name_for_filter) == _filtered_schemata.end())
1298
process_alter_schema= false;
1300
std::string alter_sql;
1301
const grt::ChangeSet *cs= diffchange->subchanges();
1303
callback->alter_schema_props_begin(schema);
1305
if(process_alter_schema)
1307
for(grt::ChangeSet::const_iterator e= cs->end(), it= cs->begin(); it != e; it++)
1309
const grt::ObjectAttrModifiedChange *attr_change= static_cast<const grt::ObjectAttrModifiedChange *>(it->get());
1311
if(attr_change->get_attr_name().compare("name") == 0)
1313
const grt::SimpleValueChange *change=
1314
static_cast<const grt::SimpleValueChange *>(attr_change->get_subchange());
1315
grt::StringRef str= grt::StringRef::cast_from(change->get_new_value());
1316
callback->alter_schema_name(schema, str);
1318
if(attr_change->get_attr_name().compare("defaultCharacterSetName") == 0)
1320
grt::ValueRef value= static_cast<const grt::SimpleValueChange *>(attr_change->get_subchange())->get_new_value();
1321
callback->alter_schema_default_charset(schema, grt::StringRef::cast_from(value));
1323
else if(attr_change->get_attr_name().compare("defaultCollationName") == 0)
1325
grt::ValueRef value= static_cast<const grt::SimpleValueChange *>(attr_change->get_subchange())->get_new_value();
1326
callback->alter_schema_default_collate(schema, grt::StringRef::cast_from(value));
1331
callback->alter_schema_props_end(schema);
1333
for(grt::ChangeSet::const_iterator e= cs->end(), it= cs->begin(); it != e; it++)
1335
const grt::ObjectAttrModifiedChange *attr_change= static_cast<const grt::ObjectAttrModifiedChange *>(it->get());
1336
if(attr_change->get_attr_name().compare("tables") == 0)
1338
const grt::MultiChange *list_change= static_cast<const grt::MultiChange *>(attr_change->get_subchange());
1339
const grt::ChangeSet *tables_cs= list_change->subchanges();
1340
for(grt::ChangeSet::const_iterator e2= tables_cs->end(), jt= tables_cs->begin(); jt != e2; jt++)
1342
const grt::DiffChange *table_change= jt->get();
1343
if (table_change->get_change_type() == grt::ListItemModified)
1345
generate_alter_stmt_drops(
1346
db_mysql_TableRef::cast_from(static_cast<const grt::ListItemModifiedChange *>(table_change)->get_new_value()),
1347
table_change->subchanges()->begin()->get());
1348
}else if (table_change->get_change_type() == grt::ListItemOrderChanged)
1350
const grt::ListItemOrderChange *oc=
1351
static_cast<const grt::ListItemOrderChange *>(table_change);
1352
const grt::ListItemModifiedChange *mc= NULL;
1353
if(!oc->subchanges()->empty())
1354
mc= static_cast<const grt::ListItemModifiedChange *>(oc->subchanges()->begin()->get());
1356
generate_alter_stmt_drops(db_mysql_TableRef::cast_from(mc->get_new_value()), mc->subchanges()->begin()->get());
1363
for(grt::ChangeSet::const_iterator e= cs->end(), it= cs->begin(); it != e; it++)
1365
const grt::ObjectAttrModifiedChange *attr_change= static_cast<const grt::ObjectAttrModifiedChange *>(it->get());
1366
if(attr_change->get_attr_name().compare("tables") == 0)
1368
const grt::MultiChange *list_change= static_cast<const grt::MultiChange *>(attr_change->get_subchange());
1369
const grt::ChangeSet *tables_cs= list_change->subchanges();
1370
for(grt::ChangeSet::const_iterator e2= tables_cs->end(), jt= tables_cs->begin(); jt != e2; jt++)
1372
const grt::DiffChange *table_change= jt->get();
1373
switch(table_change->get_change_type())
1375
case grt::ListItemAdded:
1376
generate_create_stmt(
1377
db_mysql_TableRef::cast_from(static_cast<const grt::ListItemAddedChange *>(table_change)->get_value()));
1379
case grt::ListItemRemoved:
1380
generate_drop_stmt(db_mysql_TableRef::cast_from(
1381
static_cast<const grt::ListItemRemovedChange *>(table_change)->get_value()));
1383
case grt::ListItemModified:
1384
generate_alter_stmt(db_mysql_TableRef::cast_from(
1385
static_cast<const grt::ListItemModifiedChange *>(table_change)->get_new_value()),
1386
table_change->subchanges()->begin()->get());
1388
case grt::ListItemOrderChanged:
1390
const grt::ListItemOrderChange *oc=
1391
static_cast<const grt::ListItemOrderChange *>(table_change);
1392
const grt::ListItemModifiedChange *mc= NULL;
1393
if(!oc->subchanges()->empty())
1394
mc= static_cast<const grt::ListItemModifiedChange *>(oc->subchanges()->begin()->get());
1396
generate_alter_stmt(db_mysql_TableRef::cast_from(mc->get_new_value()), mc->subchanges()->begin()->get());
1404
else if(attr_change->get_attr_name().compare("views") == 0)
1406
const grt::MultiChange *list_change= static_cast<const grt::MultiChange *>(attr_change->get_subchange());
1407
const grt::ChangeSet *views_cs= list_change->subchanges();
1408
for(grt::ChangeSet::const_iterator e2= views_cs->end(), jt= views_cs->begin(); jt != e2; jt++)
1410
const grt::DiffChange *view_change= jt->get();
1411
switch(view_change->get_change_type())
1413
case grt::ListItemAdded:
1415
db_mysql_ViewRef new_view= db_mysql_ViewRef::cast_from(
1416
static_cast<const grt::ListItemAddedChange *>(view_change)->get_value());
1417
generate_create_stmt(new_view);
1420
case grt::ListItemRemoved:
1422
generate_drop_stmt(db_mysql_ViewRef::cast_from(static_cast<const grt::ListItemRemovedChange *>(view_change)->get_value()));
1425
case grt::ListItemModified:
1427
db_mysql_ViewRef old_view= db_mysql_ViewRef::cast_from(
1428
grt::ValueRef(static_cast<const grt::ListItemModifiedChange *>(view_change)->get_old_value()));
1429
db_mysql_ViewRef new_view= db_mysql_ViewRef::cast_from(
1430
grt::ValueRef(static_cast<const grt::ListItemModifiedChange *>(view_change)->get_new_value()));
1431
generate_alter_stmt(old_view, new_view, view_change);
1434
// list item position change is not relevant
1439
else if(attr_change->get_attr_name().compare("routines") == 0)
1441
const grt::MultiChange *list_change= static_cast<const grt::MultiChange *>(attr_change->get_subchange());
1442
const grt::ChangeSet *routines_cs= list_change->subchanges();
1443
for(grt::ChangeSet::const_iterator e2= routines_cs->end(), jt= routines_cs->begin(); jt != e2; jt++)
1445
const grt::DiffChange *routine_change= jt->get();
1446
switch(routine_change->get_change_type())
1448
case grt::ListItemAdded:
1450
db_mysql_RoutineRef new_routine= db_mysql_RoutineRef::cast_from(
1451
static_cast<const grt::ListItemAddedChange *>(routine_change)->get_value());
1452
generate_create_stmt(new_routine);
1455
case grt::ListItemRemoved:
1457
generate_drop_stmt(db_mysql_RoutineRef::cast_from(static_cast<const grt::ListItemRemovedChange *>(routine_change)->get_value()));
1460
case grt::ListItemModified:
1462
db_mysql_RoutineRef old_routine= db_mysql_RoutineRef::cast_from(
1463
grt::ValueRef(static_cast<const grt::ListItemModifiedChange *>(routine_change)->get_old_value()));
1464
db_mysql_RoutineRef new_routine= db_mysql_RoutineRef::cast_from(
1465
grt::ValueRef(static_cast<const grt::ListItemModifiedChange *>(routine_change)->get_new_value()));
1466
generate_routine_alter_stmt(old_routine, new_routine, routine_change);
1469
case grt::ListItemOrderChanged:
1470
// list item position change is not relevant but may hold diff inside
1472
if (!static_cast<const grt::ListItemOrderChange *>(routine_change)->get_subchange())
1474
db_mysql_RoutineRef old_routine= db_mysql_RoutineRef::cast_from(
1475
grt::ValueRef(static_cast<const grt::ListItemOrderChange *>(routine_change)->get_subchange()->get_old_value()));
1476
db_mysql_RoutineRef new_routine= db_mysql_RoutineRef::cast_from(
1477
grt::ValueRef(static_cast<const grt::ListItemOrderChange *>(routine_change)->get_subchange()->get_new_value()));
1478
generate_routine_alter_stmt(old_routine, new_routine, routine_change);
1489
void DiffSQLGeneratorBE::generate_alter_stmt(db_mysql_CatalogRef catalog, const grt::DiffChange *diffchange)
1491
// process changes in schemata
1492
for(grt::ChangeSet::const_iterator e= diffchange->subchanges()->end(),
1493
it= diffchange->subchanges()->begin(); it != e; it++)
1495
const grt::DiffChange *subchange= it->get();
1496
if(subchange->get_change_type() == grt::ObjectAttrModified)
1498
const grt::ObjectAttrModifiedChange *objattrchange=
1499
static_cast<const grt::ObjectAttrModifiedChange *>(subchange);
1501
if(objattrchange->get_attr_name().compare("schemata") == 0)
1503
const grt::DiffChange *objattr_subchange= objattrchange->get_subchange();
1504
if(objattr_subchange->get_change_type() == grt::ListModified)
1506
const grt::MultiChange *schemata_list_change=
1507
static_cast<const grt::MultiChange *>(objattr_subchange);
1509
for(grt::ChangeSet::const_iterator schemata_e= schemata_list_change->subchanges()->end(),
1510
schemata_it= schemata_list_change->subchanges()->begin(); schemata_it != schemata_e; schemata_it++)
1512
const grt::DiffChange *schema_subchange= schemata_it->get();
1513
switch(schema_subchange->get_change_type())
1515
case grt::ListItemAdded:
1516
generate_create_stmt(
1517
db_mysql_SchemaRef::cast_from(static_cast<const grt::ListItemAddedChange *>(schema_subchange)->get_value()));
1519
case grt::ListItemRemoved:
1520
generate_drop_stmt(db_mysql_SchemaRef::cast_from(
1521
static_cast<const grt::ListItemRemovedChange *>(schema_subchange)->get_value()));
1523
case grt::ListItemModified:
1524
generate_alter_stmt(db_mysql_SchemaRef::cast_from(
1525
static_cast<const grt::ListItemModifiedChange *>(schema_subchange)->get_new_value()), schema_subchange->subchanges()->begin()->get());
1527
case grt::ListItemOrderChanged:
1529
const grt::ListItemOrderChange *oc=
1530
static_cast<const grt::ListItemOrderChange *>(schema_subchange);
1531
const grt::ListItemModifiedChange *mc= NULL;
1532
if(!oc->subchanges()->empty())
1533
mc= static_cast<const grt::ListItemModifiedChange *>(oc->subchanges()->begin()->get());
1535
generate_alter_stmt(db_mysql_SchemaRef::cast_from(
1536
mc->get_new_value()), mc->subchanges()->begin()->get());
1549
static void fill_set_from_list(grt::StringListRef string_list, std::set<std::string>& string_set)
1551
for(size_t count= string_list.count(), i= 0; i < count; i++)
1552
string_set.insert(std::string(string_list.get(i).c_str()));
1555
DiffSQLGeneratorBE::DiffSQLGeneratorBE(grt::DictRef options, DiffSQLGeneratorBEActionInterface *cb)
1556
: padding(2), callback(cb), _gen_create_index(false), _use_filtered_lists(true), _skip_foreign_keys(false), _skip_fk_indexes(false), _case_sensitive(false)
1558
if(options.is_valid())
1561
if(options.has_key("SkipForeignKeys"))
1563
grt::IntegerRef SkipForeignKeys= grt::IntegerRef::cast_from(options.get("SkipForeignKeys"));
1564
if(SkipForeignKeys.is_valid())
1565
_skip_foreign_keys = (SkipForeignKeys.operator long() != 0);
1566
}if(options.has_key("SkipFKIndexes"))
1568
grt::IntegerRef skip_fk_indexes= grt::IntegerRef::cast_from(options.get("SkipFKIndexes"));
1569
if(skip_fk_indexes.is_valid())
1570
_skip_fk_indexes = (skip_fk_indexes.operator long() != 0);
1572
if(options.has_key("UseFilteredLists"))
1574
grt::IntegerRef use_filtered_lists= grt::IntegerRef::cast_from(options.get("UseFilteredLists"));
1575
if(use_filtered_lists.is_valid())
1576
_use_filtered_lists= (use_filtered_lists.operator long() != 0);
1578
cb->set_short_names(false);
1579
if(options.has_key("UseShortNames"))
1581
grt::IntegerRef use_short_names = grt::IntegerRef::cast_from(options.get("UseShortNames"));
1582
if(use_short_names.is_valid())
1583
cb->set_short_names(use_short_names.operator long() != 0);
1585
if(options.has_key("GenerateUse"))
1587
grt::IntegerRef gen_use = grt::IntegerRef::cast_from(options.get("GenerateUse"));
1588
if(gen_use.is_valid())
1589
cb->set_gen_use(gen_use.operator long() != 0);
1591
if(options.has_key("GenerateCreateIndex"))
1593
grt::IntegerRef gen_index_value= grt::IntegerRef::cast_from(options.get("GenerateCreateIndex"));
1594
if(gen_index_value.is_valid())
1595
_gen_create_index= (gen_index_value.operator long() != 0);
1598
if(options.has_key("UserFilterList"))
1600
grt::StringListRef user_list= grt::StringListRef::cast_from(options.get("UserFilterList"));
1601
if(user_list.is_valid())
1602
fill_set_from_list(user_list, _filtered_users);
1605
if(options.has_key("SchemaFilterList"))
1607
grt::StringListRef schemata_list= grt::StringListRef::cast_from(options.get("SchemaFilterList"));
1608
if(schemata_list.is_valid())
1609
fill_set_from_list(schemata_list, _filtered_schemata);
1612
if(options.has_key("TableFilterList"))
1614
grt::StringListRef tables_list= grt::StringListRef::cast_from(options.get("TableFilterList"));
1615
if(tables_list.is_valid())
1616
fill_set_from_list(tables_list, _filtered_tables);
1619
if(options.has_key("ViewFilterList"))
1621
grt::StringListRef views_list= grt::StringListRef::cast_from(options.get("ViewFilterList"));
1622
if(views_list.is_valid())
1623
fill_set_from_list(views_list, _filtered_views);
1626
if(options.has_key("RoutineFilterList"))
1628
grt::StringListRef routines_list= grt::StringListRef::cast_from(options.get("RoutineFilterList"));
1629
if(routines_list.is_valid())
1630
fill_set_from_list(routines_list, _filtered_routines);
1633
if(options.has_key("TriggerFilterList"))
1635
grt::StringListRef triggers_list= grt::StringListRef::cast_from(options.get("TriggerFilterList"));
1636
if(triggers_list.is_valid())
1637
fill_set_from_list(triggers_list, _filtered_triggers);
1642
void DiffSQLGeneratorBE::process_diff_change(grt::ValueRef org_object, grt::DiffChange *diff, grt::DictRef map)
1644
this->target_list= grt::StringListRef();
1645
this->target_map= map;
1647
do_process_diff_change(org_object, diff);
1650
void DiffSQLGeneratorBE::process_diff_change(grt::ValueRef org_object,
1651
grt::DiffChange *diff,
1652
grt::StringListRef list,
1653
grt::ListRef<GrtNamedObject> objlist)
1655
this->target_map= grt::DictRef();
1656
this->target_list= list;
1657
this->target_object_list= objlist;
1659
do_process_diff_change(org_object, diff);
1662
void DiffSQLGeneratorBE::do_process_diff_change(grt::ValueRef org_object, grt::DiffChange *diff)
1664
switch(diff->get_change_type())
1667
case grt::ValueAdded:
1668
generate_create_stmt(db_mysql_CatalogRef::cast_from(dynamic_cast<grt::ValueAddedChange*>(diff)->get_value()));
1670
case grt::DictItemAdded:
1672
case grt::ListItemAdded:
1673
generate_create_stmt(db_mysql_CatalogRef::cast_from(dynamic_cast<grt::ListItemAddedChange*>(diff)->get_value()));
1676
case grt::ValueRemoved:
1677
case grt::ListItemRemoved:
1678
case grt::DictItemRemoved:
1679
generate_drop_stmt(db_mysql_CatalogRef::cast_from(org_object));
1682
case grt::ObjectModified:
1683
case grt::ObjectAttrModified:
1684
case grt::ListModified:
1685
case grt::ListItemModified:
1686
case grt::ListItemOrderChanged:
1687
case grt::DictModified:
1688
case grt::DictItemModified:
1689
generate_alter_stmt(db_mysql_CatalogRef::cast_from(org_object), diff);