2
* Copyright (c) 2011, 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
20
#include "tut_stdafx.h"
22
#include "wb_helpers.h"
23
#include "workbench/wb_history_tree.h"
24
#include "grtdb/db_object_helpers.h"
25
#include "grt_test_utility.h"
27
#include "mysql_table_editor.h"
32
BEGIN_TEST_DATA_CLASS(wb_undo_editors)
39
db_mgmt_RdbmsRef _rdbms;
41
size_t last_undo_stack_height;
42
size_t last_redo_stack_height;
44
TEST_DATA_CONSTRUCTOR(wb_undo_editors)
46
wbui = wb.wb->get_ui();
47
um = wb.wb->get_grt()->get_undo_manager();
48
overview = wbui->get_physical_overview();
50
wbui->set_active_form(overview);
52
last_undo_stack_height= 0;
53
last_redo_stack_height= 0;
56
#include "wb_undo_methods.h"
61
// For undo tests we use a single document loaded at the beginning of the group
62
// Each test must do the test and undo everything so that the state of the document
63
// never actually changes.
64
// At the end of the test group, the document is compared to the saved one to check
65
// for unexpected changes (ie, anything but stuff like timestamps)
68
TEST_MODULE(wb_undo_editors, "undo tests for editors in Workbench");
74
bool flag= wb.wb->open_document("data/workbench/undo_test_model2.mwb");
75
ensure("open_document", flag);
77
ensure_equals("schemas", wb.get_catalog()->schemata().count(), 1U);
79
schema = wb.get_catalog()->schemata()[0];
81
_rdbms = db_mgmt_RdbmsRef::cast_from(wb.grt->unserialize("../../modules/db.mysql/res/mysql_rdbms_info.xml"));
83
// make sure the loaded model contains expected number of things
84
ensure_equals("tables", schema->tables().count(), 2U);
85
ensure_equals("tables", schema->tables()[0]->columns()->count(), 2U);
87
ensure_equals("undo stack is empty", um->get_undo_stack().size(), 0U);
93
ensure_equals("tables", schema->tables()[0]->columns()->count(), 2U);
96
wb.get_pview()->unselectAll();
98
other.wb->open_document("data/workbench/undo_test_model2.mwb");
100
// check if the document matches the one originally loaded
101
grt_ensure_equals("compare model",
103
other.wb->get_root());
107
//----------------------------------------------------------------------------------------
108
TEST_FUNCTION(2) // General
110
db_mysql_TableRef table(db_mysql_TableRef::cast_from(schema->tables()[0]));
111
const std::string old_name = table->name();
112
std::auto_ptr<MySQLTableEditorBE> be(new MySQLTableEditorBE(wb.wb->get_grt_manager(), table, _rdbms));
115
be->set_name("new_name");
116
check_only_one_undo_added();
117
ensure("Table name set to new value", table->name() == "new_name");
119
ensure("Table name change undo failed", table->name() == old_name);
122
be->set_comment("comment");
123
check_only_one_undo_added();
124
ensure("Table comment set to new value", be->get_comment() == "comment");
126
ensure("Table comment undo failed", be->get_comment() == "test_table_comment");
129
//------------------------------------------------------------------------------
130
TEST_FUNCTION(3) // Table (general)
132
db_mysql_TableRef table(db_mysql_TableRef::cast_from(schema->tables()[0]));
133
std::auto_ptr<MySQLTableEditorBE> be(new MySQLTableEditorBE(wb.wb->get_grt_manager(), table, _rdbms));
136
std::string old_value = be->get_table_option_by_name("CHARACTER SET - COLLATE");
137
std::vector<std::string> collations(be->get_charset_collation_list());
138
if ( collations.size() > 2 )
140
int new_coll_idx = collations.size() / 2;
141
if ( collations[new_coll_idx] != old_value )
143
be->set_table_option_by_name("CHARACTER SET - COLLATE", collations[new_coll_idx]);
144
check_only_one_undo_added();
145
ensure("Table collation change failed", old_value != be->get_table_option_by_name("CHARACTER SET - COLLATE"));
147
ensure("Table collation change undo failed", old_value == be->get_table_option_by_name("CHARACTER SET - COLLATE"));
150
ensure("can not test collation", false);
153
ensure("can not test collation. list empty", false);
156
old_value = be->get_table_option_by_name("ENGINE");
157
std::vector<std::string> engines(be->get_engines_list());
158
if ( engines.size() > 2 )
160
int new_eng_idx = engines.size() / 2;
161
if ( engines[new_eng_idx] != old_value )
163
be->set_table_option_by_name("ENGINE", engines[new_eng_idx]);
164
check_only_one_undo_added();
165
ensure("Table engine change failed", old_value != be->get_table_option_by_name("ENGINE"));
167
ensure("Table engine change undo failed", old_value == be->get_table_option_by_name("ENGINE"));
170
ensure("can not test engine change", false);
173
ensure("can not test engine change. list empty", false);
176
//------------------------------------------------------------------------------
177
TEST_FUNCTION(4) // Table (add column)
179
db_mysql_TableRef table(db_mysql_TableRef::cast_from(schema->tables()[0]));
180
std::auto_ptr<MySQLTableEditorBE> be(new MySQLTableEditorBE(wb.wb->get_grt_manager(), table, _rdbms));
183
const size_t existing_cols_nr = table->columns().count();
184
ensure("Table has extra columns before test", existing_cols_nr == 2);
185
be->add_column("test_column");
186
check_only_one_undo_added();
187
ensure("Column was not added", table->columns()[existing_cols_nr]->name() == "test_column");
189
ensure("Table has extra columns after undo", table->columns().count() == existing_cols_nr);
191
ensure("Column was not added after redo", table->columns()[existing_cols_nr]->name() == "test_column");
195
//------------------------------------------------------------------------------
196
TEST_FUNCTION(5) // Table (rename column)
198
db_mysql_TableRef table(db_mysql_TableRef::cast_from(schema->tables()[0]));
199
std::auto_ptr<MySQLTableEditorBE> be(new MySQLTableEditorBE(wb.wb->get_grt_manager(), table, _rdbms));
201
const std::string old_name = table->columns()[0]->name();
203
bec::TableColumnsListBE* cols = be->get_columns();
204
cols->set_field(bec::NodeId(0), MySQLTableColumnsListBE::Name, std::string("abyrvalg"));
205
check_only_one_undo_added();
206
ensure("Column was not renamed", table->columns()[0]->name() == "abyrvalg");
208
ensure("Column name change undo failed", table->columns()[0]->name() == old_name);
211
//------------------------------------------------------------------------------
212
TEST_FUNCTION(6) // Table (Column type change)
214
db_mysql_TableRef table(db_mysql_TableRef::cast_from(schema->tables()[0]));
215
std::auto_ptr<MySQLTableEditorBE> be(new MySQLTableEditorBE(wb.wb->get_grt_manager(), table, _rdbms));
217
bec::TableColumnsListBE* cols = be->get_columns();
221
const std::string old_value = table->columns()[0]->formattedType();
223
// change type via BE, adding undo action
224
cols->set_field(bec::NodeId(0), MySQLTableColumnsListBE::Type, std::string("FLOAT"));
225
check_only_one_undo_added();
226
ensure("Column type was not set to FLOAT", table->columns()[0]->formattedType() == "FLOAT");
227
// Store new value to check redo later
228
const std::string new_value = table->columns()[0]->formattedType();
231
// verify that type was reverted to original
232
ensure("Column type change undo failed", table->columns()[0]->formattedType() == old_value);
235
ensure("Column type was not reset to " + old_value + " after redo", table->columns()[0]->formattedType() == new_value);
237
// revert all and do a last check
239
ensure("Column type change undo after redo failed", table->columns()[0]->formattedType() == old_value);
242
//------------------------------------------------------------------------------
243
TEST_FUNCTION(7) // Table (Column flag change)
245
db_mysql_TableRef table(db_mysql_TableRef::cast_from(schema->tables()[0]));
246
std::auto_ptr<MySQLTableEditorBE> be(new MySQLTableEditorBE(wb.wb->get_grt_manager(), table, _rdbms));
248
bec::TableColumnsListBE* cols = be->get_columns();
251
int flag = cols->get_column_flag(bec::NodeId(0), "PRIMARY KEY");
252
cols->set_column_flag(bec::NodeId(0), "PRIMARY KEY", !flag);
253
check_only_one_undo_added();
254
ensure("Column flag was not changed", flag != cols->get_column_flag(bec::NodeId(0), "PRIMARY KEY"));
257
ensure("Column flag change undo failed", flag == cols->get_column_flag(bec::NodeId(0), "PRIMARY KEY"));
260
//------------------------------------------------------------------------------
261
TEST_FUNCTION(8) // Table (column NN change)
263
db_mysql_TableRef table(db_mysql_TableRef::cast_from(schema->tables()[0]));
264
std::auto_ptr<MySQLTableEditorBE> be(new MySQLTableEditorBE(wb.wb->get_grt_manager(), table, _rdbms));
266
bec::TableColumnsListBE* cols = be->get_columns();
268
// Change NN, get original flag and revert it
270
cols->get_field(bec::NodeId(0), MySQLTableColumnsListBE::IsNotNull, nn);
271
cols->set_field(bec::NodeId(0), MySQLTableColumnsListBE::IsNotNull, !nn);
272
check_only_one_undo_added();
274
// get value and check that it was changed, they should match
276
cols->get_field(bec::NodeId(0), MySQLTableColumnsListBE::IsNotNull, nn2);
277
ensure("NN was not set", nn2 == !nn);
280
cols->get_field(bec::NodeId(0), MySQLTableColumnsListBE::IsNotNull, nn2);
281
ensure("NN was not set back on undo", nn2 == nn);
284
//------------------------------------------------------------------------------
285
TEST_FUNCTION(9) // Table (column default change)
287
db_mysql_TableRef table(db_mysql_TableRef::cast_from(schema->tables()[0]));
288
std::auto_ptr<MySQLTableEditorBE> be(new MySQLTableEditorBE(wb.wb->get_grt_manager(), table, _rdbms));
290
bec::TableColumnsListBE* cols = be->get_columns();
294
cols->get_field(bec::NodeId(0), MySQLTableColumnsListBE::Default, value);
295
cols->set_field(bec::NodeId(0), MySQLTableColumnsListBE::Default, "2");
296
check_only_one_undo_added();
300
cols->get_field(bec::NodeId(0), MySQLTableColumnsListBE::Default, value2);
301
ensure("Default value undo failed", value == value2);
304
//------------------------------------------------------------------------------
305
TEST_FUNCTION(10) // Table (column remove)
307
db_mysql_TableRef table(db_mysql_TableRef::cast_from(schema->tables()[0]));
308
std::auto_ptr<MySQLTableEditorBE> be(new MySQLTableEditorBE(wb.wb->get_grt_manager(), table, _rdbms));
310
const size_t ncols = table->columns().count();
311
ensure_equals("tables", ncols, 2U);
313
be->remove_column(bec::NodeId(1));
314
check_only_one_undo_added();
315
// In file we had 2 columns and one index(PRIMARY KEY). We removed column on which PK was.
317
ensure("Table column remove undo failed", table->columns().count() == ncols);
320
//------------------------------------------------------------------------------
321
TEST_FUNCTION(11) // Table (index add)
323
db_mysql_TableRef table(db_mysql_TableRef::cast_from(schema->tables()[0]));
324
std::auto_ptr<MySQLTableEditorBE> be(new MySQLTableEditorBE(wb.wb->get_grt_manager(), table, _rdbms));
326
const size_t nidx = table->indices().count();
328
be->add_index("idx");
329
check_only_one_undo_added();
330
ensure("Index was not added", table->indices()[nidx]->name() == "idx");
332
ensure("Index add undo failed", table->indices().count() == nidx);
334
ensure("Index add redo failed", table->indices()[nidx]->name() == "idx");
336
ensure("Index add undo2 failed", table->indices().count() == nidx);
339
//------------------------------------------------------------------------------
340
TEST_FUNCTION(12) // Table (index rename)
342
db_mysql_TableRef table(db_mysql_TableRef::cast_from(schema->tables()[0]));
343
std::auto_ptr<MySQLTableEditorBE> be(new MySQLTableEditorBE(wb.wb->get_grt_manager(), table, _rdbms));
345
const size_t nidx = table->indices().count();
346
be->add_index("idx");
347
check_only_one_undo_added();
350
MySQLTableIndexListBE* indices = be->get_indexes();
351
indices->set_field(bec::NodeId(nidx), bec::IndexListBE::Name, "idx_new");
352
check_only_one_undo_added();
354
ensure("Index rename undo failed", table->indices()[nidx]->name() == "idx");
356
check_undo(); // undo index addition
359
//------------------------------------------------------------------------------
360
TEST_FUNCTION(13) // Table (index remove)
362
db_mysql_TableRef table(db_mysql_TableRef::cast_from(schema->tables()[0]));
363
std::auto_ptr<MySQLTableEditorBE> be(new MySQLTableEditorBE(wb.wb->get_grt_manager(), table, _rdbms));
365
const size_t nidx = table->indices().count();
366
be->add_index("idx");
367
check_only_one_undo_added();
370
be->remove_index(bec::NodeId(nidx));
371
check_only_one_undo_added();
373
ensure("Index removal undo failed", table->indices().count() == nidx+1);
378
//------------------------------------------------------------------------------
379
TEST_FUNCTION(14) // Table (index type change)
381
db_mysql_TableRef table(db_mysql_TableRef::cast_from(schema->tables()[0]));
382
std::auto_ptr<MySQLTableEditorBE> be(new MySQLTableEditorBE(wb.wb->get_grt_manager(), table, _rdbms));
384
const size_t nidx = table->indices().count();
385
be->add_index("idx");
386
check_only_one_undo_added();
388
MySQLTableIndexListBE *indices = be->get_indexes();
390
indices->select_index(bec::NodeId(nidx));
392
indices->set_field(bec::NodeId(nidx), bec::IndexListBE::Type, "FULLTEXT");
393
check_only_one_undo_added();
395
ensure("Index type change undo failed", table->indices()[nidx]->indexType() == "INDEX");
400
//------------------------------------------------------------------------------
401
TEST_FUNCTION(15) // Table (index storage change)
403
db_mysql_TableRef table(db_mysql_TableRef::cast_from(schema->tables()[0]));
404
std::auto_ptr<MySQLTableEditorBE> be(new MySQLTableEditorBE(wb.wb->get_grt_manager(), table, _rdbms));
406
const size_t nidx = table->indices().count();
407
be->add_index("idx");
408
check_only_one_undo_added();
410
MySQLTableIndexListBE *indices = be->get_indexes();
412
indices->select_index(bec::NodeId(nidx));
414
// Change Storage Type
415
indices->set_field(bec::NodeId(nidx), MySQLTableIndexListBE::StorageType, "RTREE");
416
check_only_one_undo_added();
418
ensure("Index storage type change undo failed", table->indices()[nidx]->indexKind() == "");
423
//------------------------------------------------------------------------------
424
TEST_FUNCTION(16) // Table (index column add)
426
db_mysql_TableRef table(db_mysql_TableRef::cast_from(schema->tables()[0]));
427
std::auto_ptr<MySQLTableEditorBE> be(new MySQLTableEditorBE(wb.wb->get_grt_manager(), table, _rdbms));
429
const size_t nidx = table->indices().count();
430
be->add_index("idx");
431
check_only_one_undo_added();
433
MySQLTableIndexListBE *indices = be->get_indexes();
434
indices->select_index(bec::NodeId(nidx));
436
bec::IndexColumnsListBE *icols = indices->get_columns();
437
icols->set_column_enabled(bec::NodeId(icols->count() - 1), true);
438
check_only_one_undo_added();
440
ensure("Undo adding column to index failed", 0 == icols->get_column_enabled(bec::NodeId(bec::NodeId(table->columns().count() - 1))));
452
//------------------------------------------------------------------------------
453
TEST_FUNCTION(17) // Table (fk add)
455
db_mysql_TableRef table(db_mysql_TableRef::cast_from(schema->tables()[0]));
456
std::auto_ptr<MySQLTableEditorBE> be(new MySQLTableEditorBE(wb.wb->get_grt_manager(), table, _rdbms));
457
const size_t nfks = table->foreignKeys().count();
460
check_only_one_undo_added();
461
ensure("FK was not added", table->foreignKeys()[nfks]->name() == "fk1");
464
ensure("adding FK redo failed", table->foreignKeys()[nfks]->name() == "fk1");
468
//------------------------------------------------------------------------------
469
TEST_FUNCTION(18) // Table (fk remove)
471
db_mysql_TableRef table(db_mysql_TableRef::cast_from(schema->tables()[0]));
472
std::auto_ptr<MySQLTableEditorBE> be(new MySQLTableEditorBE(wb.wb->get_grt_manager(), table, _rdbms));
473
const size_t nfks = table->foreignKeys().count();
476
check_only_one_undo_added();
478
be->remove_fk(bec::NodeId(nfks));
479
check_only_one_undo_added();
480
ensure("FK was not removed", nfks == table->foreignKeys().count());
482
ensure("FK remove undo failed", nfks+1 != table->foreignKeys().count());
487
//------------------------------------------------------------------------------
488
TEST_FUNCTION(19) // Table (fk rename)
490
db_mysql_TableRef table(db_mysql_TableRef::cast_from(schema->tables()[0]));
491
std::auto_ptr<MySQLTableEditorBE> be(new MySQLTableEditorBE(wb.wb->get_grt_manager(), table, _rdbms));
492
const size_t nfks = table->foreignKeys().count();
493
bec::FKConstraintListBE* fks = be->get_fks();
496
check_only_one_undo_added();
498
fks->set_field(bec::NodeId(nfks), bec::FKConstraintListBE::Name, "fk_new");
499
check_only_one_undo_added();
501
ensure("Index rename undo failed", table->foreignKeys()[nfks]->name() == "fk1");
509
//------------------------------------------------------------------------------
510
TEST_FUNCTION(20) // Table (fk set ref table)
512
db_mysql_TableRef table(db_mysql_TableRef::cast_from(schema->tables()[0]));
513
std::auto_ptr<MySQLTableEditorBE> be(new MySQLTableEditorBE(wb.wb->get_grt_manager(), table, _rdbms));
514
const size_t nfks = table->foreignKeys().count();
515
bec::FKConstraintListBE* fks = be->get_fks();
518
check_only_one_undo_added();
519
fks->select_fk(bec::NodeId(nfks));
521
fks->set_field(bec::NodeId(nfks), bec::FKConstraintListBE::RefTable, "table2");
522
check_only_one_undo_added();
523
ensure("FK ref table was not set", fks->get_selected_fk()->referencedTable()->name() == "table2");
529
//------------------------------------------------------------------------------
530
TEST_FUNCTION(21) // Table (fk set ref column)
532
db_mysql_TableRef table(db_mysql_TableRef::cast_from(schema->tables()[0]));
533
db_mysql_TableRef table2(db_mysql_TableRef::cast_from(schema->tables()[1]));
534
std::auto_ptr<MySQLTableEditorBE> be(new MySQLTableEditorBE(wb.wb->get_grt_manager(), table, _rdbms));
535
const size_t nfks = table->foreignKeys().count();
536
bec::FKConstraintListBE* fks = be->get_fks();
539
check_only_one_undo_added();
540
fks->select_fk(bec::NodeId(nfks));
542
fks->set_field(bec::NodeId(nfks), bec::FKConstraintListBE::RefTable, "table2");
543
check_only_one_undo_added();
544
ensure("FK ref table was not set", fks->get_selected_fk()->referencedTable()->name() == "table2");
546
bec::FKConstraintColumnsListBE* fkcols = fks->get_columns();
547
fkcols->set_field(bec::NodeId(0), bec::FKConstraintColumnsListBE::Enabled, 1);
548
check_only_one_undo_added();
549
fkcols->set_field(bec::NodeId(0), bec::FKConstraintColumnsListBE::RefColumn, table2->columns()[table2->columns()->count() - 1]->name());
550
check_only_one_undo_added();
552
// TODO: Change On Update
553
// TODO: Change On Delete
556
check_undo();//set column
557
check_undo();//set ref column
559
check_undo();//set ref table
561
check_undo();//add fk
564
//------------------------------------------------------------------------------
565
TEST_FUNCTION(22) // Table (Triggers)
567
db_mysql_TableRef table(db_mysql_TableRef::cast_from(schema->tables()[0]));
568
std::auto_ptr<MySQLTableEditorBE> be(new MySQLTableEditorBE(wb.wb->get_grt_manager(), table, _rdbms));
570
const std::string trig_sql = be->get_all_triggers_sql();
571
be->set_triggers_sql("create trigger tr1 before insert on table1 for each row set new.idtable1 = 1", true);//dunno if this should be true or fasle
572
check_only_one_undo_added();
573
ensure("Triggers sql was not set", be->get_all_triggers_sql() == "create trigger tr1 before insert on table1 for each row set new.idtable1 = 1");
575
ensure("Triggers sql undo failed", be->get_all_triggers_sql() == trig_sql);
580
TEST_FUNCTION(36) // Table (inserts)
582
ensure("not implemented", false);
586
TEST_FUNCTION(37) // Table (partitioning)
588
ensure("not implemented", false);
592
TEST_FUNCTION(38) // Table (options)
594
ensure("not implemented", false);
598
TEST_FUNCTION(40) // View
600
ensure("not implemented", false);
604
TEST_FUNCTION(45) // Routine
606
ensure("not implemented", false);
609
TEST_FUNCTION(50) // RoutineGroup
611
ensure("not implemented", false);
614
TEST_FUNCTION(55) // Schema
616
ensure("not implemented", false);
619
TEST_FUNCTION(60) // Relationship
621
ensure("not implemented", false);
624
TEST_FUNCTION(61) // Image
626
ensure("not implemented", false);
629
TEST_FUNCTION(62) // Note
631
ensure("not implemented", false);
634
TEST_FUNCTION(63) // Stored Script
636
ensure("not implemented", false);
639
TEST_FUNCTION(64) // Stored Note
641
ensure("not implemented", false);