~ubuntu-branches/ubuntu/quantal/mysql-workbench/quantal

« back to all changes in this revision

Viewing changes to modules/db.mysql/src/db_mysql_diffsqlgen.cpp

  • Committer: Package Import Robot
  • Author(s): Dmitry Smirnov
  • Date: 2012-03-01 21:57:30 UTC
  • Revision ID: package-import@ubuntu.com-20120301215730-o7y8av8y38n162ro
Tags: upstream-5.2.38+dfsg
ImportĀ upstreamĀ versionĀ 5.2.38+dfsg

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/* 
 
2
 * Copyright (c) 2009, 2012, Oracle and/or its affiliates. All rights reserved.
 
3
 *
 
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
 
7
 * License.
 
8
 * 
 
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.
 
13
 * 
 
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
 
17
 * 02110-1301  USA
 
18
 */
 
19
 
 
20
#include "stdafx.h"
 
21
 
 
22
#include "db_mysql_diffsqlgen.h"
 
23
 
 
24
#include "diffchange.h"
 
25
#include "grtdiff.h"
 
26
#include "changeobjects.h"
 
27
#include "changelistobjects.h"
 
28
 
 
29
#include "db_mysql_diffsqlgen_grant.h"
 
30
 
 
31
#include "grt/common.h"
 
32
 
 
33
#include <algorithm>
 
34
#include <ctype.h>
 
35
 
 
36
#include "module_db_mysql.h"
 
37
 
 
38
void DiffSQLGeneratorBE::remember(const GrtNamedObjectRef &obj, const std::string &sql)
 
39
{
 
40
  if(target_list.is_valid())
 
41
  {
 
42
    target_list.insert(grt::StringRef(sql));
 
43
    if(target_object_list.is_valid())
 
44
      target_object_list.insert(obj);
 
45
  }
 
46
  else
 
47
  {
 
48
    target_map.set(get_full_object_name_for_key(obj,_case_sensitive), grt::StringRef(sql));
 
49
  }
 
50
}
 
51
 
 
52
void DiffSQLGeneratorBE::remember_alter(const GrtNamedObjectRef &obj, const std::string &sql)
 
53
{
 
54
  if(target_list.is_valid())
 
55
  {
 
56
    target_list.insert(grt::StringRef(sql));
 
57
    if(target_object_list.is_valid())
 
58
      target_object_list.insert(obj);
 
59
    return;
 
60
  }
 
61
 
 
62
  std::string key= get_full_object_name_for_key(obj,_case_sensitive);
 
63
 
 
64
  if(target_map.has_key(key))
 
65
  {
 
66
    grt::ValueRef value= target_map.get(key);
 
67
    if(grt::StringRef::can_wrap(value))
 
68
    {
 
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);
 
73
    }
 
74
    else if(grt::StringListRef::can_wrap(value))
 
75
    {
 
76
      grt::StringListRef::cast_from(value).insert(grt::StringRef(sql));
 
77
    }
 
78
    else
 
79
    {
 
80
      // a bug
 
81
      assert(0);
 
82
    }
 
83
  }
 
84
  else
 
85
  {
 
86
    target_map.set(key, grt::StringRef(sql));
 
87
  }
 
88
}
 
89
 
 
90
 
 
91
struct Part_sort_pred {
 
92
  bool operator() (const std::pair<int, grt::ValueRef>& v1, const std::pair<int, grt::ValueRef>& v2)
 
93
  {
 
94
    return v1 < v2;
 
95
  }
 
96
};
 
97
 
 
98
void DiffSQLGeneratorBE::generate_set_partitioning(db_mysql_TableRef table, 
 
99
                                                   const grt::DiffChange *table_diffchange)
 
100
{
 
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());
 
106
  int part_count= 0;
 
107
 
 
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++)
 
111
  {
 
112
    const grt::ObjectAttrModifiedChange *attr_change= static_cast<const grt::ObjectAttrModifiedChange *>(it->get());
 
113
 
 
114
    if(attr_change->get_attr_name().compare("partitionType") == 0)
 
115
    {
 
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()));
 
119
      part_type_set= true;
 
120
    }
 
121
    else if(attr_change->get_attr_name().compare("partitionExpression") == 0)
 
122
    {
 
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()));
 
126
      part_expr_set= true;
 
127
    }
 
128
    else if(attr_change->get_attr_name().compare("subpartitionType") == 0)
 
129
    {
 
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;
 
134
    }
 
135
    else if(attr_change->get_attr_name().compare("subpartitionExpression") == 0)
 
136
    {
 
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;
 
141
    }
 
142
    else if(attr_change->get_attr_name().compare("partitionCount") == 0)
 
143
    {
 
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;
 
148
    }
 
149
    else if(attr_change->get_attr_name().compare("partitionDefinitions") == 0)
 
150
    {
 
151
      const grt::MultiChange *change= 
 
152
        static_cast<const grt::MultiChange *>(attr_change->get_subchange());
 
153
      const grt::ChangeSet *part_defs_cs= change->subchanges();
 
154
 
 
155
      // needs to be sorted by LESS THAN value
 
156
      std::vector<std::pair<int, grt::ValueRef> > partition_vector;
 
157
 
 
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++)
 
160
      {
 
161
        grt::ValueRef part_def_grt_value;
 
162
 
 
163
        const boost::shared_ptr<grt::DiffChange> part_def_change= *part_defs_it;
 
164
        if(part_def_change->get_change_type() == grt::ListItemAdded)
 
165
        {
 
166
          const grt::ListItemAddedChange *added_change= 
 
167
              static_cast<const grt::ListItemAddedChange *>(part_def_change.get());
 
168
 
 
169
          part_def_grt_value= added_change->get_value();
 
170
        }
 
171
        else if(part_def_change->get_change_type() == grt::ListItemModified)
 
172
        {
 
173
          const grt::ListItemModifiedChange *modified_change= 
 
174
            static_cast<const grt::ListItemModifiedChange  *>(part_def_change.get());
 
175
 
 
176
          part_def_grt_value= modified_change->get_new_value();
 
177
        }
 
178
 
 
179
        db_mysql_PartitionDefinitionRef part_def_value(db_mysql_PartitionDefinitionRef::cast_from(part_def_grt_value));
 
180
 
 
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));
 
184
      }
 
185
 
 
186
 
 
187
      std::sort(partition_vector.begin(), partition_vector.end());
 
188
 
 
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++)
 
191
      {
 
192
        part_defs.insert(db_mysql_PartitionDefinitionRef::cast_from(pv_it->second));
 
193
      }
 
194
 
 
195
      part_defs_set= true;
 
196
    }
 
197
  }
 
198
 
 
199
  if(!part_type_set)
 
200
    part_type.assign(table->partitionType().c_str());
 
201
    
 
202
  if(!part_expr_set)
 
203
    part_expr.assign(table->partitionExpression().c_str());
 
204
 
 
205
  if(!subpart_type_set)
 
206
    subpart_type.assign(table->subpartitionType().c_str());
 
207
 
 
208
  if(!subpart_expr_set)
 
209
    subpart_expr.assign(table->subpartitionExpression().c_str());
 
210
 
 
211
  if(!part_count_set)
 
212
    part_count= table->partitionCount();
 
213
 
 
214
  if(!part_defs_set)
 
215
    part_defs= table->partitionDefinitions();
 
216
 
 
217
  callback->alter_table_generate_partitioning(table, part_type, part_expr, part_count, 
 
218
                        subpart_type, subpart_expr, part_defs);
 
219
}
 
220
 
 
221
void DiffSQLGeneratorBE::generate_create_partitioning(db_mysql_TableRef table)
 
222
{
 
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()
 
230
    );
 
231
}
 
232
 
 
233
void DiffSQLGeneratorBE::generate_create_stmt(db_mysql_TableRef table)
 
234
{
 
235
  if (table->isStub())
 
236
    return;
 
237
 
 
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;
 
243
 
 
244
  if(process_table)
 
245
  {
 
246
    callback->create_table_props_begin(table);
 
247
 
 
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
 
250
 
 
251
    callback->create_table_columns_begin(table);
 
252
 
 
253
    grt::ListRef<db_mysql_Column> columns= table->columns();
 
254
    for(size_t columns_count= columns.count(), i= 0; i < columns_count; i++)
 
255
    {
 
256
      db_mysql_ColumnRef column= columns.get(i);
 
257
      callback->create_table_column(column);
 
258
    }
 
259
 
 
260
    callback->create_table_columns_end(table);
 
261
 
 
262
    // indices processing
 
263
 
 
264
    callback->create_table_indexes_begin(table);
 
265
 
 
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++)
 
270
    {
 
271
      fk_indexes.insert(table->foreignKeys()[i]->index());
 
272
      (table->foreignKeys()[i]->modelOnly()?fk_skip_indexes:fk_create_indexes).insert(table->foreignKeys()[i]->index());
 
273
    }
 
274
 
 
275
    grt::ListRef<db_mysql_Index> indices= table->indices();
 
276
    for(size_t index_count= indices.count(), i= 0; i < index_count; i++)
 
277
    {
 
278
      db_mysql_IndexRef index= indices.get(i);
 
279
 
 
280
      if (index->isPrimary())
 
281
      {
 
282
        callback->create_table_index(index, false);
 
283
        continue;      
 
284
      }
 
285
      
 
286
      if (_skip_fk_indexes && (stricmp(index->indexType().c_str(), "FOREIGN") == 0
 
287
                                 || fk_indexes.find(index) != fk_indexes.end()))
 
288
        continue;
 
289
 
 
290
      if ((fk_skip_indexes.find(index) != fk_skip_indexes.end())&&(fk_create_indexes.find(index) == fk_create_indexes.end()))
 
291
        continue;
 
292
      callback->create_table_index(index, _gen_create_index);
 
293
    }
 
294
 
 
295
    callback->create_table_indexes_end(table);
 
296
 
 
297
    callback->create_table_fks_begin(table);
 
298
 
 
299
    if (!_skip_foreign_keys)
 
300
    {
 
301
 
 
302
      grt::ListRef<db_mysql_ForeignKey> fks= table->foreignKeys();
 
303
      for(size_t fk_count= fks.count(), i= 0; i < fk_count; i++)
 
304
      {
 
305
        db_mysql_ForeignKeyRef fk= fks.get(i);
 
306
        if (fk.is_valid() && fk->referencedTable().is_valid())
 
307
        {
 
308
          if (fk->modelOnly() || fk->referencedTable()->modelOnly())
 
309
            continue;
 
310
 
 
311
          callback->create_table_fk(fk);
 
312
        }
 
313
      }
 
314
 
 
315
    }
 
316
    callback->create_table_fks_end(table);
 
317
 
 
318
    // TODO: [TABLESPACE tablespace_name STORAGE DISK]
 
319
 
 
320
    if(strlen(table->tableEngine().c_str()))
 
321
      callback->create_table_engine(table->tableEngine());
 
322
 
 
323
    if(strlen(table->nextAutoInc().c_str()))
 
324
      callback->create_table_next_auto_inc(table->nextAutoInc());
 
325
 
 
326
    if(strlen(table->avgRowLength().c_str()))
 
327
      callback->create_table_avg_row_length(table->avgRowLength());
 
328
 
 
329
    if(strlen(table->defaultCharacterSetName().c_str()))
 
330
      callback->create_table_charset(table->defaultCharacterSetName());
 
331
 
 
332
    if(table->checksum() != 0)
 
333
      callback->create_table_checksum(table->checksum());
 
334
 
 
335
    if(strlen(table->defaultCollationName().c_str()))
 
336
      callback->create_table_collate(table->defaultCollationName());
 
337
 
 
338
    if(strlen(table->comment().c_str()))
 
339
      callback->create_table_comment(table->comment());
 
340
    
 
341
    // CONNECTION [=] 'connect_string'
 
342
 
 
343
    if(strlen(table->tableDataDir().c_str()))
 
344
      callback->create_table_data_dir(table->tableDataDir());
 
345
 
 
346
    if(table->delayKeyWrite() != 0)
 
347
      callback->create_table_delay_key_write(table->delayKeyWrite());
 
348
 
 
349
    if(strlen(table->tableIndexDir().c_str()))
 
350
      callback->create_table_index_dir(table->tableIndexDir());
 
351
 
 
352
    if(strlen(table->mergeInsert().c_str()))
 
353
      callback->create_table_merge_insert(table->mergeInsert());
 
354
 
 
355
    // KEY_BLOCK_SIZE [=] value
 
356
 
 
357
    if(strlen(table->maxRows().c_str()))
 
358
      callback->create_table_max_rows(table->maxRows());
 
359
 
 
360
    if(strlen(table->minRows().c_str()))
 
361
      callback->create_table_min_rows(table->minRows());
 
362
 
 
363
    if(strlen(table->packKeys().c_str()))
 
364
      callback->create_table_pack_keys(table->packKeys());
 
365
 
 
366
    if(strlen(table->password().c_str()))
 
367
      callback->create_table_password(table->password());
 
368
 
 
369
    if(strlen(table->rowFormat().c_str()))
 
370
      callback->create_table_row_format(table->rowFormat());
 
371
 
 
372
    if(strlen(table->mergeUnion().c_str()))
 
373
      callback->create_table_merge_union(table->mergeUnion());
 
374
 
 
375
    if(table->partitionType().is_valid() && strlen(table->partitionType().c_str())
 
376
    && table->partitionExpression().is_valid() /*&& strlen(table->partitionExpression().c_str())*/)
 
377
    {
 
378
      generate_create_partitioning(table);
 
379
    }
 
380
 
 
381
    callback->create_table_props_end(table);
 
382
  } // process_table
 
383
 
 
384
  grt::ListRef<db_mysql_Trigger> triggers= table->triggers();
 
385
  for(size_t c= triggers.count(), i= 0; i < c; i++)
 
386
  {
 
387
    db_mysql_TriggerRef trigger= triggers.get(i);
 
388
    generate_create_stmt(trigger);
 
389
  }
 
390
}
 
391
 
 
392
void DiffSQLGeneratorBE::generate_create_stmt(db_mysql_ViewRef view)
 
393
{
 
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())
 
397
      return;
 
398
 
 
399
  callback->create_view(view);
 
400
}
 
401
 
 
402
void DiffSQLGeneratorBE::generate_create_stmt(db_mysql_RoutineRef routine, bool for_alter)
 
403
{
 
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())
 
407
      return;
 
408
 
 
409
  callback->create_routine(routine, for_alter);
 
410
}
 
411
 
 
412
void DiffSQLGeneratorBE::generate_create_stmt(db_mysql_TriggerRef trigger, bool for_alter)
 
413
{
 
414
  std::string trigger_name_for_filter(get_old_object_name_for_key(trigger, _case_sensitive));
 
415
 
 
416
  if(_use_filtered_lists)
 
417
    if(_filtered_triggers.find(trigger_name_for_filter) == _filtered_triggers.end())
 
418
      return;
 
419
 
 
420
  callback->create_trigger(trigger, for_alter);
 
421
}
 
422
 
 
423
void DiffSQLGeneratorBE::generate_create_stmt(db_mysql_SchemaRef schema)
 
424
{
 
425
  std::string schema_name_for_filter(get_old_object_name_for_key(schema, _case_sensitive));
 
426
 
 
427
  if(_use_filtered_lists)
 
428
    if(_filtered_schemata.find(schema_name_for_filter) == _filtered_schemata.end())
 
429
      return;
 
430
 
 
431
  callback->create_schema(schema);
 
432
 
 
433
  grt::ListRef<db_mysql_Table> tables= schema->tables();
 
434
  for(size_t count= tables.count(), i= 0; i < count; i++)
 
435
  {
 
436
    db_mysql_TableRef table= tables.get(i);
 
437
    generate_create_stmt(table);
 
438
  }
 
439
 
 
440
  grt::ListRef<db_mysql_View> views= schema->views();
 
441
  for(size_t count= views.count(), i= 0; i < count; i++)
 
442
  {
 
443
    db_mysql_ViewRef view= views.get(i);
 
444
    generate_create_stmt(view);
 
445
  }
 
446
 
 
447
  grt::ListRef<db_mysql_Routine> routines= schema->routines();
 
448
  for(size_t count= routines.count(), i= 0; i < count; i++)
 
449
  {
 
450
    db_mysql_RoutineRef routine= routines.get(i);
 
451
    generate_create_stmt(routine);
 
452
  }
 
453
}
 
454
 
 
455
void DiffSQLGeneratorBE::generate_create_stmt(db_UserRef user)
 
456
{
 
457
  std::string user_name_for_filter(get_old_object_name_for_key(user, _case_sensitive));
 
458
 
 
459
  if(_use_filtered_lists)
 
460
    if(_filtered_users.find(user_name_for_filter) == _filtered_users.end())
 
461
      return;
 
462
 
 
463
  callback->create_user(user);
 
464
}
 
465
 
 
466
void DiffSQLGeneratorBE::generate_create_stmt(db_mysql_CatalogRef catalog)
 
467
{
 
468
  grt::ListRef<db_mysql_Schema> schemata= catalog->schemata();
 
469
  for(size_t count= schemata.count(), i= 0; i < count; i++)
 
470
  {
 
471
    db_mysql_SchemaRef schema= schemata.get(i);
 
472
    generate_create_stmt(schema);
 
473
  }
 
474
 
 
475
  for(size_t count= catalog->users().count(), i= 0; i < count; i++)
 
476
  {
 
477
    db_UserRef user= catalog->users().get(i);
 
478
    generate_create_stmt(user);
 
479
  }
 
480
}
 
481
 
 
482
void DiffSQLGeneratorBE::generate_drop_stmt(db_mysql_TableRef table)
 
483
{
 
484
  if (table->isStub())
 
485
    return;
 
486
 
 
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())
 
490
      return;
 
491
 
 
492
  callback->drop_table(table);
 
493
 
 
494
  grt::ListRef<db_mysql_Trigger> triggers= table->triggers();
 
495
  for(size_t c= triggers.count(), i= 0; i < c; i++)
 
496
  {
 
497
    db_mysql_TriggerRef trigger= triggers.get(i);
 
498
    generate_drop_stmt(trigger);
 
499
  }
 
500
}
 
501
 
 
502
void DiffSQLGeneratorBE::generate_drop_stmt(db_mysql_TriggerRef trigger, bool for_alter)
 
503
{
 
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())
 
507
      return;
 
508
 
 
509
  callback->drop_trigger(trigger, for_alter);
 
510
}
 
511
 
 
512
void DiffSQLGeneratorBE::generate_drop_stmt(db_mysql_ViewRef view) 
 
513
 
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()) 
 
517
      return; 
 
518
 
 
519
  callback->drop_view(view); 
 
520
 
521
 
 
522
void DiffSQLGeneratorBE::generate_drop_stmt(db_mysql_RoutineRef routine, bool for_alter) 
 
523
 
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()) 
 
527
      return; 
 
528
 
 
529
  callback->drop_routine(routine, for_alter); 
 
530
 
531
 
 
532
void DiffSQLGeneratorBE::generate_drop_stmt(db_UserRef user)
 
533
{
 
534
  callback->drop_user(user);
 
535
}
 
536
 
 
537
void DiffSQLGeneratorBE::generate_drop_stmt(db_mysql_SchemaRef schema)
 
538
{
 
539
  callback->drop_schema(schema);
 
540
 
 
541
  grt::ListRef<db_mysql_Table> tables= schema->tables();
 
542
  for(size_t count= tables.count(), i= 0; i < count; i++)
 
543
  {
 
544
    db_mysql_TableRef table= tables.get(i);
 
545
    generate_drop_stmt(table);
 
546
  }
 
547
 
 
548
  grt::ListRef<db_mysql_View> views= schema->views();
 
549
  for(size_t count= views.count(), i= 0; i < count; i++)
 
550
  {
 
551
    db_mysql_ViewRef view= views.get(i);
 
552
    generate_drop_stmt(view);
 
553
  }
 
554
 
 
555
  grt::ListRef<db_mysql_Routine> routines= schema->routines();
 
556
  for(size_t count= routines.count(), i= 0; i < count; i++)
 
557
  {
 
558
    db_mysql_RoutineRef routine= routines.get(i);
 
559
    generate_drop_stmt(routine);
 
560
  }
 
561
}
 
562
 
 
563
void DiffSQLGeneratorBE::generate_drop_stmt(db_mysql_CatalogRef catalog)
 
564
{
 
565
  grt::ListRef<db_mysql_Schema> schemata= catalog->schemata();
 
566
  for(size_t count= schemata.count(), i= 0; i < count; i++)
 
567
  {
 
568
    db_mysql_SchemaRef schema= schemata.get(i);
 
569
    generate_drop_stmt(schema);
 
570
  }
 
571
 
 
572
  for(size_t count= catalog->users().count(), i= 0; i < count; i++)
 
573
  {
 
574
    db_UserRef user= catalog->users().get(i);
 
575
    generate_drop_stmt(user);
 
576
  }
 
577
}
 
578
 
 
579
void DiffSQLGeneratorBE::generate_alter(grt::ListRef<db_mysql_Column> columns, const grt::MultiChange *diffchange)
 
580
{
 
581
  const grt::ChangeSet *columns_cs= diffchange->subchanges();
 
582
 
 
583
  if(columns.count() == 0)
 
584
    return;
 
585
 
 
586
  db_mysql_TableRef table= db_mysql_TableRef::cast_from(columns.get(0)->owner());
 
587
 
 
588
  callback->alter_table_columns_begin(table);
 
589
 
 
590
  Column_rename_map column_rename_map;
 
591
 
 
592
  // build a map of column renames
 
593
  for(grt::ChangeSet::const_iterator e= columns_cs->end(), it= columns_cs->begin(); it != e; it++)
 
594
  {
 
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++)
 
597
    {
 
598
      const boost::shared_ptr<grt::DiffChange> column_change= *it;
 
599
 
 
600
      if(column_change->get_change_type() == grt::ListItemModified)
 
601
      {
 
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());
 
606
      }
 
607
      else if(column_change->get_change_type() == grt::ListItemOrderChanged)
 
608
      {
 
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());
 
614
      }
 
615
    }
 
616
  }
 
617
 
 
618
  // process DROP COLUMN
 
619
  for(grt::ChangeSet::const_iterator e= columns_cs->end(), it= columns_cs->begin(); it != e; it++)
 
620
  {
 
621
    const boost::shared_ptr<grt::DiffChange> column_change= *it;
 
622
    if(column_change->get_change_type() != grt::ListItemRemoved)
 
623
      continue;
 
624
 
 
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()));
 
627
  }
 
628
 
 
629
  // process ADD COLUMN
 
630
  for(grt::ChangeSet::const_iterator e= columns_cs->end(), it= columns_cs->begin(); it != e; it++)
 
631
  {
 
632
    const boost::shared_ptr<grt::DiffChange> column_change= *it;
 
633
    if(column_change->get_change_type() != grt::ListItemAdded)
 
634
      continue;
 
635
 
 
636
    const grt::ListItemAddedChange *added_change= static_cast<const grt::ListItemAddedChange *>(column_change.get());
 
637
 
 
638
    callback->alter_table_add_column(
 
639
      table, 
 
640
      column_rename_map,
 
641
      db_mysql_ColumnRef::cast_from(grt::ValueRef(added_change->get_value())),
 
642
      db_mysql_ColumnRef::cast_from(added_change->get_prev_item()));
 
643
  }
 
644
 
 
645
  std::set<grt::ValueRef> processed_items;
 
646
 
 
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++)
 
649
  {
 
650
    const boost::shared_ptr<grt::DiffChange> column_change= *it;
 
651
 
 
652
    if(column_change->get_change_type() != grt::ListItemOrderChanged)
 
653
      continue;
 
654
 
 
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(
 
659
      table,
 
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()),
 
664
      false,
 
665
      column_rename_map
 
666
    );
 
667
  }
 
668
 
 
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++)
 
671
  {
 
672
    const boost::shared_ptr<grt::DiffChange> column_change= *it;
 
673
 
 
674
    if(column_change->get_change_type() != grt::ListItemModified)
 
675
      continue;
 
676
  
 
677
    const grt::ListItemModifiedChange *modified_change= static_cast<const grt::ListItemModifiedChange *>(column_change.get());
 
678
 
 
679
    callback->alter_table_change_column(
 
680
      table,
 
681
      db_mysql_ColumnRef::cast_from(grt::ValueRef(modified_change->get_new_value())),
 
682
      db_mysql_ColumnRef(),
 
683
      db_mysql_ColumnRef(),
 
684
      true,
 
685
      column_rename_map
 
686
    );
 
687
  }
 
688
 
 
689
  callback->alter_table_columns_end(table);
 
690
}
 
691
 
 
692
void DiffSQLGeneratorBE::generate_alter(grt::ListRef<db_mysql_Index> indices, const grt::MultiChange *diffchange)
 
693
{
 
694
  const grt::ChangeSet *indices_cs= diffchange->subchanges();
 
695
 
 
696
  for(grt::ChangeSet::const_iterator e= indices_cs->end(), it= indices_cs->begin(); it != e; it++)
 
697
  {
 
698
    const boost::shared_ptr<grt::DiffChange> index_change= *it;
 
699
    
 
700
    switch(index_change->get_change_type())
 
701
    {
 
702
    case grt::ListItemAdded:  // ADD INDEX
 
703
      {
 
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()));
 
706
      }
 
707
      break;
 
708
    case grt::ListItemRemoved:  // DROP INDEX
 
709
      {
 
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()));
 
712
      }
 
713
      break;
 
714
    case grt::ListItemOrderChanged: // DROP/ADD INDEX
 
715
      {
 
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())
 
719
          break;
 
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()));
 
722
      }
 
723
      break;
 
724
 
 
725
    case grt::ListItemModified: 
 
726
      {
 
727
        const grt::ListItemModifiedChange *modified_change= static_cast<const grt::ListItemModifiedChange *>(index_change.get());
 
728
 
 
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()));
 
731
      }
 
732
      break;
 
733
      default: break;
 
734
    }
 
735
  }
 
736
}
 
737
 
 
738
void DiffSQLGeneratorBE::generate_alter_drop(
 
739
  grt::ListRef<db_mysql_ForeignKey> fks, const grt::MultiChange *diffchange)
 
740
{
 
741
/*
 
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 
 
744
  statements.
 
745
*/
 
746
 
 
747
  const grt::ChangeSet *fks_cs= diffchange->subchanges();
 
748
 
 
749
  for(grt::ChangeSet::const_iterator e= fks_cs->end(), it= fks_cs->begin(); it != e; it++)
 
750
  {
 
751
    const boost::shared_ptr<grt::DiffChange> fk_change= *it;
 
752
    
 
753
    db_mysql_ForeignKeyRef fk1;
 
754
    switch(fk_change->get_change_type())
 
755
    {
 
756
    case grt::ListItemRemoved:  // DROP FK
 
757
      {
 
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());
 
760
      }
 
761
      break;
 
762
    case grt::ListItemModified: 
 
763
      {
 
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());
 
766
      }
 
767
      break;
 
768
    default:
 
769
      break;
 
770
    }
 
771
    if (fk1.is_valid() && (fk1->modelOnly() || !fk1->referencedTable().is_valid() || fk1->referencedTable()->modelOnly()))
 
772
      continue;
 
773
 
 
774
    switch(fk_change->get_change_type())
 
775
    {
 
776
    case grt::ListItemRemoved:  // DROP FK
 
777
      {
 
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()));
 
780
      }
 
781
      break;
 
782
    case grt::ListItemModified: 
 
783
      {
 
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()));
 
786
      }
 
787
      break;
 
788
      default: break;
 
789
    }
 
790
  }
 
791
}
 
792
 
 
793
void DiffSQLGeneratorBE::generate_alter(
 
794
  grt::ListRef<db_mysql_ForeignKey> fks, const grt::MultiChange *diffchange)
 
795
{
 
796
/*
 
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 
 
799
  statements.
 
800
*/
 
801
 
 
802
  const grt::ChangeSet *fks_cs= diffchange->subchanges();
 
803
 
 
804
  for(grt::ChangeSet::const_iterator e= fks_cs->end(), it= fks_cs->begin(); it != e; it++)
 
805
  {
 
806
    const boost::shared_ptr<grt::DiffChange> fk_change= *it;
 
807
    
 
808
    db_mysql_ForeignKeyRef fk1, fk2;
 
809
    switch(fk_change->get_change_type())
 
810
    {
 
811
    case grt::ListItemAdded:  // ADD FK
 
812
      {
 
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());
 
815
      }
 
816
      break;
 
817
    case grt::ListItemRemoved:  // DROP FK
 
818
      {
 
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());
 
821
      }
 
822
      break;
 
823
    case grt::ListItemOrderChanged: // DROP/ADD FK
 
824
      {
 
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());
 
828
      }
 
829
      break;
 
830
    case grt::ListItemModified: 
 
831
      {
 
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());
 
835
      }
 
836
      break;
 
837
    default:
 
838
      break;
 
839
    }
 
840
    if (fk1.is_valid() && (fk1->modelOnly() || !fk1->referencedTable().is_valid() || fk1->referencedTable()->modelOnly()))
 
841
      continue;
 
842
    if (fk2.is_valid() && (fk2->modelOnly() || !fk2->referencedTable().is_valid() || fk2->referencedTable()->modelOnly()))
 
843
      continue;
 
844
 
 
845
    switch(fk_change->get_change_type())
 
846
    {
 
847
    case grt::ListItemAdded:  // ADD FK
 
848
      {
 
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()));
 
851
      }
 
852
      break;
 
853
    case grt::ListItemRemoved:  // DROP FK
 
854
/*      {
 
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()));
 
857
      }*/
 
858
      break;
 
859
    case grt::ListItemOrderChanged: // DROP/ADD FK
 
860
      {
 
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()));
 
864
      }
 
865
      break;
 
866
 
 
867
    case grt::ListItemModified: 
 
868
      {
 
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()));
 
872
      }
 
873
      break;
 
874
      default: break;
 
875
    }
 
876
  }
 
877
}
 
878
 
 
879
void DiffSQLGeneratorBE::generate_alter_stmt_drops(db_mysql_TableRef table, const grt::DiffChange *diffchange)
 
880
{
 
881
  if (table->isStub())
 
882
    return;
 
883
 
 
884
  bool process_table= true;
 
885
 
 
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;
 
890
  if(!process_table)
 
891
    return;
 
892
  const grt::ChangeSet* cs= diffchange->subchanges();
 
893
 
 
894
  callback->alter_table_props_begin(table);
 
895
 
 
896
  for(grt::ChangeSet::const_iterator e= cs->end(), it= cs->begin(); it != e; it++)
 
897
  {
 
898
    const grt::ObjectAttrModifiedChange *attr_change= 
 
899
        static_cast<const grt::ObjectAttrModifiedChange *>(it->get());
 
900
 
 
901
    if(attr_change->get_attr_name().compare("foreignKeys") == 0)
 
902
    {
 
903
      const grt::MultiChange *list_change= 
 
904
        static_cast<const grt::MultiChange *>(attr_change->get_subchange());
 
905
 
 
906
      callback->alter_table_fks_begin(table);
 
907
      generate_alter_drop(table->foreignKeys(), list_change);
 
908
      callback->alter_table_fks_end(table);
 
909
    }
 
910
  }
 
911
 
 
912
  callback->alter_table_props_end(table);
 
913
 
 
914
}
 
915
 
 
916
void DiffSQLGeneratorBE::generate_alter_stmt(db_mysql_TableRef table, const grt::DiffChange *diffchange)
 
917
{
 
918
  if (table->isStub())
 
919
    return;
 
920
 
 
921
  bool process_table= true;
 
922
 
 
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;
 
927
 
 
928
  // process table triggers
 
929
  const grt::ChangeSet *cs= diffchange->subchanges();
 
930
 
 
931
  for(grt::ChangeSet::const_iterator e= cs->end(), it= cs->begin(); it != e; it++)
 
932
  {
 
933
    const grt::ObjectAttrModifiedChange *attr_change= 
 
934
      static_cast<const grt::ObjectAttrModifiedChange *>(it->get());
 
935
 
 
936
    if(attr_change->get_attr_name().compare("triggers") == 0)
 
937
    {
 
938
      const grt::MultiChange *list_change= 
 
939
        static_cast<const grt::MultiChange *>(attr_change->get_subchange());
 
940
      
 
941
      const grt::ChangeSet *triggers_cs= list_change->subchanges();
 
942
      
 
943
      for(grt::ChangeSet::const_iterator e2= triggers_cs->end(), jt= triggers_cs->begin(); jt != e2; jt++)
 
944
      {
 
945
        const grt::DiffChange *trigger_change= jt->get();
 
946
 
 
947
        switch(trigger_change->get_change_type())
 
948
        {
 
949
        case grt::ListItemAdded:
 
950
          {
 
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);
 
954
          }
 
955
          break;
 
956
        case grt::ListItemRemoved:
 
957
          {
 
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);
 
961
          }
 
962
          break;
 
963
        case grt::ListItemModified:
 
964
          {
 
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()));
 
971
 
 
972
            generate_drop_stmt(old_trigger);
 
973
            generate_create_stmt(new_trigger);
 
974
          }
 
975
          break;
 
976
        // list item position change is not relevant        
 
977
          default: break;
 
978
        }
 
979
      }
 
980
    }
 
981
  }
 
982
 
 
983
  if(!process_table)
 
984
    return;
 
985
 
 
986
  bool partitions_processed= false;
 
987
  cs= diffchange->subchanges();
 
988
 
 
989
  callback->alter_table_props_begin(table);
 
990
 
 
991
  for(grt::ChangeSet::const_iterator e= cs->end(), it= cs->begin(); it != e; it++)
 
992
  {
 
993
    const grt::ObjectAttrModifiedChange *attr_change= 
 
994
        static_cast<const grt::ObjectAttrModifiedChange *>(it->get());
 
995
 
 
996
    if(attr_change->get_attr_name().compare("name") == 0)
 
997
    {
 
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);
 
1002
    }
 
1003
    if(attr_change->get_attr_name().compare("columns") == 0)
 
1004
    {
 
1005
      const grt::MultiChange *list_change= 
 
1006
        static_cast<const grt::MultiChange *>(attr_change->get_subchange());
 
1007
      generate_alter(table->columns(), list_change);
 
1008
    }
 
1009
    else if(attr_change->get_attr_name().compare("indices") == 0)
 
1010
    {
 
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);
 
1016
    }
 
1017
    else if(attr_change->get_attr_name().compare("foreignKeys") == 0)
 
1018
    {
 
1019
      const grt::MultiChange *list_change= 
 
1020
        static_cast<const grt::MultiChange *>(attr_change->get_subchange());
 
1021
      
 
1022
      callback->alter_table_fks_begin(table);
 
1023
      generate_alter(table->foreignKeys(), list_change);
 
1024
      callback->alter_table_fks_end(table);
 
1025
    }
 
1026
    else if(attr_change->get_attr_name().compare("tableEngine") == 0)
 
1027
    {
 
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);
 
1032
    }
 
1033
    else if(attr_change->get_attr_name().compare("nextAutoInc") == 0)
 
1034
    {
 
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);
 
1039
    }
 
1040
    else if(attr_change->get_attr_name().compare("password") == 0)
 
1041
    {
 
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);
 
1046
    }
 
1047
    else if(attr_change->get_attr_name().compare("delayKeyWrite") == 0)
 
1048
    {
 
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);
 
1053
    }
 
1054
    else if(attr_change->get_attr_name().compare("defaultCharacterSetName") == 0)
 
1055
    {
 
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);
 
1060
    }
 
1061
    else if(attr_change->get_attr_name().compare("defaultCollationName") == 0)
 
1062
    {
 
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);
 
1067
    }
 
1068
    else if(attr_change->get_attr_name().compare("mergeUnion") == 0)
 
1069
    {
 
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);
 
1074
    }
 
1075
    else if(attr_change->get_attr_name().compare("mergeInsert") == 0)
 
1076
    {
 
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);
 
1081
    }
 
1082
    // ALTER TABLE silently ignores these attributes
 
1083
#if 0
 
1084
    else if(attr_change->get_attr_name().compare("tableDataDir") == 0)
 
1085
    {
 
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("' ");
 
1089
    }
 
1090
    else if(attr_change->get_attr_name().compare("tableIndexDir") == 0)
 
1091
    {
 
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("' ");
 
1095
    }
 
1096
#endif
 
1097
    else if(attr_change->get_attr_name().compare("packKeys") == 0)
 
1098
    {
 
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);
 
1103
    }
 
1104
    else if(attr_change->get_attr_name().compare("checksum") == 0)
 
1105
    {
 
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);
 
1110
    }
 
1111
    else if(attr_change->get_attr_name().compare("comment") == 0)
 
1112
    {
 
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);
 
1117
    }
 
1118
    else if(attr_change->get_attr_name().compare("rowFormat") == 0)
 
1119
    {
 
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);
 
1123
    }
 
1124
    else if(attr_change->get_attr_name().compare("avgRowLength") == 0)
 
1125
    {
 
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);
 
1130
    }
 
1131
    else if(attr_change->get_attr_name().compare("minRows") == 0)
 
1132
    {
 
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);
 
1137
    }
 
1138
    else if(attr_change->get_attr_name().compare("maxRows") == 0)
 
1139
    {
 
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);
 
1144
    }
 
1145
    // to be added later, probably needs support for CREATE/ALTER SERVER
 
1146
#if 0
 
1147
    else if(attr_change->get_attr_name().compare("connection") == 0)
 
1148
    {
 
1149
    }
 
1150
#endif
 
1151
    else if(attr_change->get_attr_name().compare("connectionString") == 0)
 
1152
    {
 
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);
 
1157
    }
 
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))
 
1163
    {
 
1164
      if(partitions_processed)
 
1165
        continue;
 
1166
 
 
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());
 
1171
 
 
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);
 
1176
 
 
1177
      partitions_processed= true;
 
1178
    }
 
1179
    else
 
1180
    {
 
1181
      continue; // avoid setting comma, see below
 
1182
    }
 
1183
  }
 
1184
 
 
1185
  bool is_range= (strcmp(table->partitionType().c_str(), "RANGE") == 0);
 
1186
 
 
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++)
 
1190
  {
 
1191
    const grt::ObjectAttrModifiedChange *attr_change= 
 
1192
      static_cast<const grt::ObjectAttrModifiedChange *>(it->get());
 
1193
 
 
1194
    if(attr_change->get_attr_name().compare("partitionCount") == 0)
 
1195
    {
 
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());
 
1199
      
 
1200
      //std::string part_count_sql(generate_change_partition_count(table, new_count));
 
1201
 
 
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())
 
1207
      //{
 
1208
      //  alter_sql.append(comma).append(part_count_sql);
 
1209
      //  partitions_processed= true;
 
1210
      //}
 
1211
 
 
1212
      std::string part_type(table->partitionType().c_str());
 
1213
 
 
1214
      if((part_type.find("HASH") != std::string::npos)
 
1215
          || (part_type.find("KEY") != std::string::npos))
 
1216
      {
 
1217
        callback->alter_table_partition_count(table, new_count);
 
1218
        partitions_processed= true;
 
1219
      }
 
1220
    }
 
1221
    else if(attr_change->get_attr_name().compare("partitionDefinitions") == 0)
 
1222
    {
 
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++)
 
1226
      {
 
1227
        const grt::DiffChange *part_change= jt->get();
 
1228
        switch(part_change->get_change_type())
 
1229
        {
 
1230
        case grt::ListItemAdded:
 
1231
          {
 
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);
 
1235
          }
 
1236
          break;
 
1237
        case grt::ListItemRemoved:
 
1238
          {
 
1239
            db_mysql_PartitionDefinitionRef part= db_mysql_PartitionDefinitionRef::cast_from(
 
1240
              static_cast<const grt::ListItemRemovedChange *>(part_change)->get_value());
 
1241
 
 
1242
            callback->alter_table_drop_partition(part->name().c_str());
 
1243
          }
 
1244
          break;
 
1245
        case grt::ListItemModified:
 
1246
          {
 
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()));
 
1251
 
 
1252
            callback->alter_table_reorganize_partition(old_part, new_part, is_range);
 
1253
          }
 
1254
          break;
 
1255
          default: break;
 
1256
        }
 
1257
 
 
1258
        partitions_processed= true;
 
1259
      }
 
1260
    }
 
1261
  }
 
1262
 
 
1263
  callback->alter_table_props_end(table);
 
1264
}
 
1265
 
 
1266
void DiffSQLGeneratorBE::generate_alter_stmt(db_mysql_ViewRef old_view, db_mysql_ViewRef new_view, const grt::DiffChange *diffchange)
 
1267
{
 
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())
 
1271
      return;
 
1272
 
 
1273
  generate_create_stmt(new_view);
 
1274
 
 
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);
 
1277
}
 
1278
 
 
1279
void DiffSQLGeneratorBE::generate_routine_alter_stmt(db_mysql_RoutineRef old_routine, db_mysql_RoutineRef new_routine, const grt::DiffChange *diffchange)
 
1280
{
 
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())
 
1284
      return;
 
1285
 
 
1286
  generate_drop_stmt(old_routine);
 
1287
 
 
1288
  generate_create_stmt(new_routine); 
 
1289
}
 
1290
 
 
1291
void DiffSQLGeneratorBE::generate_alter_stmt(db_mysql_SchemaRef schema, const grt::DiffChange *diffchange)
 
1292
{
 
1293
  bool process_alter_schema= true;
 
1294
  std::string schema_name_for_filter(get_old_object_name_for_key(schema, _case_sensitive));
 
1295
 
 
1296
  if(_use_filtered_lists)
 
1297
    if(_filtered_schemata.find(schema_name_for_filter) == _filtered_schemata.end())
 
1298
      process_alter_schema= false;
 
1299
 
 
1300
  std::string alter_sql;
 
1301
  const grt::ChangeSet *cs= diffchange->subchanges();
 
1302
 
 
1303
  callback->alter_schema_props_begin(schema);
 
1304
 
 
1305
  if(process_alter_schema)
 
1306
  {
 
1307
    for(grt::ChangeSet::const_iterator e= cs->end(), it= cs->begin(); it != e; it++)
 
1308
    {
 
1309
      const grt::ObjectAttrModifiedChange *attr_change= static_cast<const grt::ObjectAttrModifiedChange *>(it->get());
 
1310
 
 
1311
      if(attr_change->get_attr_name().compare("name") == 0)
 
1312
      {
 
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);
 
1317
      }
 
1318
      if(attr_change->get_attr_name().compare("defaultCharacterSetName") == 0)
 
1319
      {
 
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));
 
1322
      }
 
1323
      else if(attr_change->get_attr_name().compare("defaultCollationName") == 0)
 
1324
      {
 
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));
 
1327
      }
 
1328
    }
 
1329
  }
 
1330
 
 
1331
  callback->alter_schema_props_end(schema);
 
1332
 
 
1333
  for(grt::ChangeSet::const_iterator e= cs->end(), it= cs->begin(); it != e; it++)
 
1334
  {
 
1335
    const grt::ObjectAttrModifiedChange *attr_change= static_cast<const grt::ObjectAttrModifiedChange *>(it->get());
 
1336
    if(attr_change->get_attr_name().compare("tables") == 0)
 
1337
    {
 
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++)
 
1341
      {
 
1342
        const grt::DiffChange *table_change= jt->get();
 
1343
        if (table_change->get_change_type() == grt::ListItemModified)
 
1344
        {
 
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)
 
1349
        {
 
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());
 
1355
            if(mc)
 
1356
              generate_alter_stmt_drops(db_mysql_TableRef::cast_from(mc->get_new_value()), mc->subchanges()->begin()->get());
 
1357
        }
 
1358
      }
 
1359
    }
 
1360
  }
 
1361
 
 
1362
 
 
1363
  for(grt::ChangeSet::const_iterator e= cs->end(), it= cs->begin(); it != e; it++)
 
1364
  {
 
1365
    const grt::ObjectAttrModifiedChange *attr_change= static_cast<const grt::ObjectAttrModifiedChange *>(it->get());
 
1366
    if(attr_change->get_attr_name().compare("tables") == 0)
 
1367
    {
 
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++)
 
1371
      {
 
1372
        const grt::DiffChange *table_change= jt->get();
 
1373
        switch(table_change->get_change_type())
 
1374
        {
 
1375
        case grt::ListItemAdded:
 
1376
          generate_create_stmt(
 
1377
            db_mysql_TableRef::cast_from(static_cast<const grt::ListItemAddedChange *>(table_change)->get_value()));
 
1378
          break;
 
1379
        case grt::ListItemRemoved:
 
1380
          generate_drop_stmt(db_mysql_TableRef::cast_from(
 
1381
            static_cast<const grt::ListItemRemovedChange *>(table_change)->get_value()));
 
1382
          break;
 
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());
 
1387
          break;
 
1388
        case grt::ListItemOrderChanged:
 
1389
          {
 
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());
 
1395
            if(mc)
 
1396
                generate_alter_stmt(db_mysql_TableRef::cast_from(mc->get_new_value()), mc->subchanges()->begin()->get());
 
1397
          }
 
1398
          break;
 
1399
          default: 
 
1400
            break;
 
1401
        }
 
1402
      }
 
1403
    }
 
1404
    else if(attr_change->get_attr_name().compare("views") == 0)
 
1405
    {
 
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++)
 
1409
      {
 
1410
        const grt::DiffChange *view_change= jt->get();
 
1411
        switch(view_change->get_change_type())
 
1412
        {
 
1413
        case grt::ListItemAdded:
 
1414
          {
 
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);
 
1418
          }
 
1419
          break;
 
1420
        case grt::ListItemRemoved:
 
1421
          {
 
1422
            generate_drop_stmt(db_mysql_ViewRef::cast_from(static_cast<const grt::ListItemRemovedChange *>(view_change)->get_value()));
 
1423
          }
 
1424
          break;
 
1425
        case grt::ListItemModified:
 
1426
          {
 
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);
 
1432
          }
 
1433
          break;
 
1434
        // list item position change is not relevant        
 
1435
          default: break;
 
1436
        }
 
1437
      }
 
1438
    }
 
1439
    else if(attr_change->get_attr_name().compare("routines") == 0)
 
1440
    {
 
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++)
 
1444
      {
 
1445
        const grt::DiffChange *routine_change= jt->get();
 
1446
        switch(routine_change->get_change_type())
 
1447
        {
 
1448
        case grt::ListItemAdded:
 
1449
          {
 
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);
 
1453
          }
 
1454
          break;
 
1455
        case grt::ListItemRemoved:
 
1456
          {
 
1457
            generate_drop_stmt(db_mysql_RoutineRef::cast_from(static_cast<const grt::ListItemRemovedChange *>(routine_change)->get_value()));
 
1458
          }
 
1459
          break;
 
1460
        case grt::ListItemModified:
 
1461
          {
 
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);
 
1467
          }
 
1468
          break;
 
1469
        case grt::ListItemOrderChanged:
 
1470
        // list item position change is not relevant but may hold diff inside
 
1471
            {
 
1472
            if (!static_cast<const grt::ListItemOrderChange *>(routine_change)->get_subchange())
 
1473
                break;
 
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);
 
1479
            }
 
1480
            break;
 
1481
          default: break;        
 
1482
        }
 
1483
      }
 
1484
    }
 
1485
  }
 
1486
}
 
1487
 
 
1488
 
 
1489
void DiffSQLGeneratorBE::generate_alter_stmt(db_mysql_CatalogRef catalog, const grt::DiffChange *diffchange)
 
1490
{
 
1491
  // process changes in schemata
 
1492
  for(grt::ChangeSet::const_iterator e= diffchange->subchanges()->end(),
 
1493
    it= diffchange->subchanges()->begin(); it != e; it++)
 
1494
  {
 
1495
    const grt::DiffChange *subchange= it->get();
 
1496
    if(subchange->get_change_type() == grt::ObjectAttrModified)
 
1497
    {
 
1498
      const grt::ObjectAttrModifiedChange *objattrchange= 
 
1499
        static_cast<const grt::ObjectAttrModifiedChange *>(subchange);
 
1500
 
 
1501
      if(objattrchange->get_attr_name().compare("schemata") == 0)
 
1502
      {
 
1503
        const grt::DiffChange *objattr_subchange= objattrchange->get_subchange();
 
1504
        if(objattr_subchange->get_change_type() == grt::ListModified)
 
1505
        {
 
1506
          const grt::MultiChange *schemata_list_change=
 
1507
            static_cast<const grt::MultiChange *>(objattr_subchange);
 
1508
 
 
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++)
 
1511
          {
 
1512
            const grt::DiffChange *schema_subchange= schemata_it->get();
 
1513
            switch(schema_subchange->get_change_type())
 
1514
            {
 
1515
            case grt::ListItemAdded:
 
1516
              generate_create_stmt(
 
1517
                db_mysql_SchemaRef::cast_from(static_cast<const grt::ListItemAddedChange *>(schema_subchange)->get_value()));
 
1518
              break;
 
1519
            case grt::ListItemRemoved:
 
1520
              generate_drop_stmt(db_mysql_SchemaRef::cast_from(
 
1521
                static_cast<const grt::ListItemRemovedChange *>(schema_subchange)->get_value()));
 
1522
              break;
 
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());
 
1526
              break;
 
1527
            case grt::ListItemOrderChanged:
 
1528
              {
 
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());
 
1534
                if(mc)
 
1535
                  generate_alter_stmt(db_mysql_SchemaRef::cast_from(
 
1536
                    mc->get_new_value()), mc->subchanges()->begin()->get());
 
1537
              }
 
1538
              break;
 
1539
              default: 
 
1540
                break;
 
1541
            }
 
1542
          }
 
1543
        }
 
1544
      }
 
1545
    }
 
1546
  }
 
1547
}
 
1548
 
 
1549
static void fill_set_from_list(grt::StringListRef string_list, std::set<std::string>& string_set)
 
1550
{
 
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()));
 
1553
}
 
1554
 
 
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)
 
1557
{
 
1558
  if(options.is_valid())
 
1559
  {
 
1560
 
 
1561
    if(options.has_key("SkipForeignKeys"))
 
1562
    {
 
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"))
 
1567
    {
 
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);
 
1571
    }
 
1572
    if(options.has_key("UseFilteredLists"))
 
1573
    {
 
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);
 
1577
    }
 
1578
        cb->set_short_names(false);
 
1579
    if(options.has_key("UseShortNames"))
 
1580
    {
 
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);
 
1584
    }
 
1585
    if(options.has_key("GenerateUse"))
 
1586
    {
 
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);
 
1590
    }
 
1591
    if(options.has_key("GenerateCreateIndex"))
 
1592
    {
 
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);
 
1596
    }
 
1597
 
 
1598
    if(options.has_key("UserFilterList"))
 
1599
    {
 
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);
 
1603
    }
 
1604
 
 
1605
    if(options.has_key("SchemaFilterList"))
 
1606
    {
 
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);
 
1610
    }
 
1611
 
 
1612
    if(options.has_key("TableFilterList"))
 
1613
    {
 
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);
 
1617
    }
 
1618
 
 
1619
    if(options.has_key("ViewFilterList"))
 
1620
    {
 
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);
 
1624
    }
 
1625
 
 
1626
    if(options.has_key("RoutineFilterList"))
 
1627
    {
 
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);
 
1631
    }
 
1632
 
 
1633
    if(options.has_key("TriggerFilterList"))
 
1634
    {
 
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);
 
1638
    }
 
1639
  }
 
1640
}
 
1641
 
 
1642
void DiffSQLGeneratorBE::process_diff_change(grt::ValueRef org_object, grt::DiffChange *diff, grt::DictRef map)
 
1643
{
 
1644
  this->target_list= grt::StringListRef();
 
1645
  this->target_map= map;
 
1646
 
 
1647
  do_process_diff_change(org_object, diff);
 
1648
}
 
1649
 
 
1650
void DiffSQLGeneratorBE::process_diff_change(grt::ValueRef org_object, 
 
1651
                                             grt::DiffChange *diff, 
 
1652
                                             grt::StringListRef list, 
 
1653
                                             grt::ListRef<GrtNamedObject> objlist)
 
1654
{
 
1655
  this->target_map= grt::DictRef();
 
1656
  this->target_list= list;
 
1657
  this->target_object_list= objlist;
 
1658
 
 
1659
  do_process_diff_change(org_object, diff);
 
1660
}
 
1661
 
 
1662
void DiffSQLGeneratorBE::do_process_diff_change(grt::ValueRef org_object, grt::DiffChange *diff)
 
1663
{
 
1664
  switch(diff->get_change_type())
 
1665
  {
 
1666
  //case SimpleValue:
 
1667
  case grt::ValueAdded:
 
1668
    generate_create_stmt(db_mysql_CatalogRef::cast_from(dynamic_cast<grt::ValueAddedChange*>(diff)->get_value()));
 
1669
    break;
 
1670
  case grt::DictItemAdded:
 
1671
    break;
 
1672
  case grt::ListItemAdded:
 
1673
    generate_create_stmt(db_mysql_CatalogRef::cast_from(dynamic_cast<grt::ListItemAddedChange*>(diff)->get_value()));
 
1674
    break;
 
1675
 
 
1676
  case grt::ValueRemoved:
 
1677
  case grt::ListItemRemoved:
 
1678
  case grt::DictItemRemoved:
 
1679
    generate_drop_stmt(db_mysql_CatalogRef::cast_from(org_object));
 
1680
    break;
 
1681
 
 
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);
 
1690
    break;
 
1691
  
 
1692
  default:
 
1693
    break;
 
1694
  }
 
1695
}