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

« back to all changes in this revision

Viewing changes to modules/wb.mysql.import/src/wb_mysql_import_dbd4.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, 2010, 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
#ifndef _WIN32
 
23
#include <cctype>
 
24
#include <algorithm>
 
25
#include <iostream>
 
26
#include <sstream>
 
27
#include <fstream>
 
28
#endif
 
29
 
 
30
#include <glib/gstdio.h>
 
31
 
 
32
#include "wb_mysql_import_dbd4.h"
 
33
#include "grt/grt_manager.h"
 
34
#include <grtpp_util.h>
 
35
#include "tinyxml.h"
 
36
#include "grtdb/db_object_helpers.h"
 
37
#include "stream_conv.h"
 
38
#include "grtsqlparser/module_utils.h"
 
39
#include "sqlide/table_inserts_loader_be.h"
 
40
#include "grts/structs.workbench.h"
 
41
#include "base/string_utilities.h"
 
42
 
 
43
using namespace base;
 
44
 
 
45
const float XSCALE_FACTOR= 1.0F;
 
46
const float YSCALE_FACTOR= 1.33F;
 
47
const int DEFAULT_MODEL_BASE_WIDTH= 10000;
 
48
const int DEFAULT_MODEL_BASE_HEIGHT= 7000;
 
49
 
 
50
#define NEUTRAL_STATE_KEEPER Neutral_state_keeper _nsk(this);
 
51
 
 
52
typedef std::map<int, model_LayerRef> Layers;
 
53
 
 
54
 
 
55
/*
 
56
*********************************************************************************
 
57
* @brief Converts a DBDesigner4 string to a utf8 string.
 
58
*
 
59
* Performs the following conversion for a string loaded from a DBD4 xml file:
 
60
*  - converts \n to newline
 
61
*  - converts \t to tab
 
62
*  - converts \a to '
 
63
*  - converts \\ to \
 
64
*  - converts \nnn from latin1 to UTF8 character
 
65
*
 
66
*  @param str
 
67
*
 
68
*  @return UTF8 string
 
69
*********************************************************************************
 
70
*/
 
71
static std::string dbd_string_to_utf8(const char *str)
 
72
{
 
73
  if (!str)
 
74
    return "";
 
75
 
 
76
  std::string res;
 
77
  gchar *tmp= (gchar*)g_malloc(strlen(str)*4+1);
 
78
  const char *ptr;
 
79
  gchar *tmpstr;
 
80
 
 
81
  tmpstr= tmp;
 
82
  ptr= str;
 
83
  while (*ptr)
 
84
  {
 
85
    if (*ptr == '\\')
 
86
    {
 
87
      ++ptr;
 
88
      switch (*ptr)
 
89
      {
 
90
      case 0:
 
91
        --ptr;
 
92
        break;
 
93
      case '\\':
 
94
        *tmpstr= '\\';
 
95
        break;
 
96
      case 'n':
 
97
      case 'N':
 
98
        *tmpstr= '\n';
 
99
        break;
 
100
      case 't':
 
101
      case 'T':
 
102
        *tmpstr= '\t';
 
103
        break;
 
104
      case 'r':
 
105
      case 'R':
 
106
        *tmpstr= '\r';
 
107
        break;
 
108
      case 'a':
 
109
      case 'A':
 
110
        *tmpstr= '\'';
 
111
        break;
 
112
      default:
 
113
        if (isdigit(ptr[0]) && isdigit(ptr[1]) && isdigit(ptr[2]))
 
114
        {
 
115
          char num[4];
 
116
          num[0]= ptr[0];
 
117
          num[1]= ptr[1];
 
118
          num[2]= ptr[2];
 
119
          num[3]= 0;
 
120
          *tmpstr= (gchar)atoi(num);
 
121
          ptr+= 2;
 
122
        }
 
123
        else
 
124
          *tmpstr= *ptr;
 
125
        break;
 
126
      }
 
127
    }
 
128
    else
 
129
      *tmpstr= *ptr;
 
130
    ++tmpstr;
 
131
    ++ptr;
 
132
  }
 
133
  *tmpstr= 0;
 
134
 
 
135
  tmpstr= g_convert(tmp, strlen(tmp), "UTF-8", "ISO-8859-1", NULL, NULL, NULL);
 
136
  g_free(tmp);
 
137
  if (!tmpstr)
 
138
    return str;
 
139
  res= tmpstr;
 
140
  g_free(tmpstr);
 
141
  return res;
 
142
}
 
143
 
 
144
 
 
145
struct Rect
 
146
{
 
147
  double left;
 
148
  double top;
 
149
  double width;
 
150
  double height;
 
151
};
 
152
 
 
153
 
 
154
void replace_terminated_symbol(std::string &str, const std::string &term, const std::string &replace_string)
 
155
{
 
156
  char term_prefix= term[0];
 
157
  char term_symbol= term[1];
 
158
  bool terminated= false;
 
159
  for (size_t n= 0; n < str.length(); ++n)
 
160
  {
 
161
    char chr= str[n];
 
162
 
 
163
    if (terminated && chr == term_symbol)
 
164
    {
 
165
      --n;
 
166
      str= str.replace(n, term.length(), replace_string);
 
167
      terminated= false;
 
168
    }
 
169
    else if (chr == term_prefix)
 
170
      terminated= !terminated;
 
171
    else
 
172
      terminated= false;
 
173
  }
 
174
}
 
175
 
 
176
 
 
177
void split_string(const std::string &str, const std::string &delim, std::vector<std::string> &result)
 
178
{
 
179
  std::string::const_iterator i= str.begin();
 
180
 
 
181
  while (true)
 
182
  {
 
183
    std::string::const_iterator i2= search(i, str.end(), delim.begin(), delim.end());
 
184
    size_t substr_length= std::distance(i, i2);
 
185
    if (str.end() == i2 && !substr_length)
 
186
      break;
 
187
    std::string substr;
 
188
    substr.resize(substr_length);
 
189
    std::copy(i, i2, substr.begin());
 
190
    result.push_back(substr);
 
191
    i= i2;
 
192
    if (str.end() != i2)
 
193
      i+= delim.size();
 
194
  }
 
195
}
 
196
 
 
197
 
 
198
void parse_table_options(db_mysql_TableRef &table, const std::string &optionsstr)
 
199
{
 
200
  std::vector<std::string> options;
 
201
  split_string(optionsstr, "\\n", options);
 
202
  for (std::vector<std::string>::iterator i= options.begin(); i != options.end(); ++i)
 
203
  {
 
204
    std::vector<std::string> option_pair;
 
205
    split_string(*i, "=", option_pair);
 
206
    const std::string &option_name= option_pair[0];
 
207
    const char *option_val= option_pair[1].c_str();
 
208
 
 
209
    if (0 == option_name.compare("DelayKeyTblUpdates"))
 
210
      table->delayKeyWrite(atoi(option_val));
 
211
    else if (0 == option_name.compare("PackKeys"))
 
212
      table->packKeys(option_val);
 
213
    else if (0 == option_name.compare("RowChecksum"))
 
214
      table->checksum(atoi(option_val));
 
215
    else if (0 == option_name.compare("RowFormat"))
 
216
    {
 
217
      // ROW_FORMAT [=] {DEFAULT|DYNAMIC|FIXED|COMPRESSED|REDUNDANT|COMPACT}
 
218
      // REDUNDANT and COMPACT values are not supported by DBD4
 
219
      int n= 0;
 
220
      {
 
221
        std::istringstream iss(option_val);
 
222
        iss >> n;
 
223
      }
 
224
      switch (n)
 
225
      {
 
226
      case 1: option_val= "DYNAMIC"; break;
 
227
      case 2: option_val= "FIXED"; break;
 
228
      case 3: option_val= "COMPRESSED"; break;
 
229
      default: option_val= "DEFAULT"; break;
 
230
      }
 
231
      table->rowFormat(option_val);
 
232
    }
 
233
    else if (0 == option_name.compare("AverageRowLength"))
 
234
      table->avgRowLength(option_val);
 
235
    else if (0 == option_name.compare("MaxRowNumber"))
 
236
      table->maxRows(option_val);
 
237
    else if (0 == option_name.compare("MinRowNumber"))
 
238
      table->minRows(option_val);
 
239
    else if (0 == option_name.compare("NextAutoIncVal"))
 
240
      table->nextAutoInc(option_val);
 
241
    else if (0 == option_name.compare("TblPassword"))
 
242
      table->password(option_val);
 
243
    else if (0 == option_name.compare("TblDataDir"))
 
244
      table->tableDataDir(option_val);
 
245
    else if (0 == option_name.compare("TblIndexDir"))
 
246
      table->tableIndexDir(option_val);
 
247
  }
 
248
}
 
249
 
 
250
 
 
251
void add_figure_on_layer(model_LayerRef layer, model_FigureRef figure)
 
252
{
 
253
  figure->visible(1);
 
254
  layer->figures().insert(figure);
 
255
  layer->owner()->figures().insert(figure); // add to view->figures()
 
256
}
 
257
 
 
258
 
 
259
model_LayerRef find_containing_layer(Rect &rect, Layers &layers)
 
260
{
 
261
  for (Layers::iterator i= layers.begin(); i != layers.end(); ++i)
 
262
  {
 
263
    model_LayerRef &layer= i->second;
 
264
    if (rect.left > layer->left()
 
265
      && (rect.left < layer->left() + layer->width())
 
266
      && (rect.top > layer->top())
 
267
      && (rect.top < layer->top() + layer->height())
 
268
      )
 
269
      return layer;
 
270
  }
 
271
  return model_LayerRef();
 
272
}
 
273
 
 
274
 
 
275
static bool calculate_view_size(const app_PageSettingsRef &page, double &width, double &height)
 
276
{
 
277
  if (page->paperType().is_valid())
 
278
  {
 
279
    width= page->paperType()->width();
 
280
    height= page->paperType()->height();
 
281
 
 
282
    width-= page->marginLeft() + page->marginRight();
 
283
    height-= page->marginTop() + page->marginBottom();
 
284
 
 
285
    width*= page->scale();
 
286
    height*= page->scale();
 
287
 
 
288
    if (page->orientation() == "landscape")
 
289
      std::swap(width, height);
 
290
 
 
291
    return true;
 
292
  }
 
293
  else
 
294
  {
 
295
    width= 1000;
 
296
    height= 1000;
 
297
    return false;
 
298
  }
 
299
}
 
300
 
 
301
 
 
302
Wb_mysql_import_DBD4::Wb_mysql_import_DBD4()
 
303
: _grt(NULL)
 
304
{
 
305
  NEUTRAL_STATE_KEEPER
 
306
}
 
307
 
 
308
int Wb_mysql_import_DBD4::import_DBD4(workbench_physical_ModelRef model, const char *file_name, grt::DictRef options)
 
309
{
 
310
  NEUTRAL_STATE_KEEPER
 
311
 
 
312
  overwrite_default_option<IntegerRef>(_gen_fk_names_when_empty, "gen_fk_names_when_empty", options);
 
313
 
 
314
  TiXmlDocument doc(file_name);
 
315
  bool loaded = doc.LoadFile();
 
316
  if (!loaded || !doc.FirstChildElement("DBMODEL"))
 
317
    throw std::runtime_error("Wrong file format.");
 
318
 
 
319
  _grt= model.get_grt();
 
320
  _catalog= db_mysql_CatalogRef::cast_from(model->catalog());
 
321
 
 
322
  _grt->send_info("Started import DBD4 model.");
 
323
 
 
324
  bec::GRTManager *grtm= bec::GRTManager::get_instance_for(_grt);
 
325
 
 
326
  _created_schemata= ListRef<db_mysql_Schema>(_grt);
 
327
  ensure_schema_created(0,
 
328
    (0 < _catalog->schemata().count()) ? _catalog->schemata().get(0)->name().c_str() : "mydb");
 
329
 
 
330
  const TiXmlElement *dbmodel_el= doc.FirstChildElement("DBMODEL");
 
331
  if (dbmodel_el)
 
332
  {
 
333
    int id= 0;
 
334
 
 
335
    DictRef wb_options= DictRef::cast_from(_grt->get("/wb/options/options"));
 
336
    std::string table_figure_color= wb_options.get_string(std::string(workbench_physical_TableFigure::static_class_name()).append(":Color"));
 
337
    std::string note_figure_color=  wb_options.get_string(std::string(workbench_model_NoteFigure::static_class_name()).append(":Color"));
 
338
    std::string image_color_color= wb_options.get_string(std::string(workbench_model_ImageFigure::static_class_name()).append(":Color"));
 
339
 
 
340
    // view initialization
 
341
    workbench_physical_DiagramRef view;
 
342
    {
 
343
      workbench_WorkbenchRef wb(workbench_WorkbenchRef::cast_from(model->owner()->owner()));
 
344
      double viewWidth;
 
345
      double viewHeight;
 
346
 
 
347
      view= workbench_physical_DiagramRef::cast_from(model->addNewDiagram(0));
 
348
 
 
349
      calculate_view_size(wb->doc()->pageSettings(), viewWidth, viewHeight);
 
350
 
 
351
      const TiXmlElement *settings_el= dbmodel_el->FirstChildElement("SETTINGS");
 
352
      if (settings_el)
 
353
      {
 
354
        const TiXmlElement *global_settings_el= settings_el->FirstChildElement("GLOBALSETTINGS");
 
355
        if (global_settings_el)
 
356
        {
 
357
          int w= 0;
 
358
          int h= 0;
 
359
          global_settings_el->QueryIntAttribute("CanvasWidth", &w);
 
360
          global_settings_el->QueryIntAttribute("CanvasHeight", &h);
 
361
 
 
362
          if (!w) w = DEFAULT_MODEL_BASE_WIDTH;
 
363
          if (!h) h = DEFAULT_MODEL_BASE_HEIGHT;
 
364
 
 
365
          // align with page size (view size should be a whole number of pages)
 
366
          div_t divres= div((int)(w * XSCALE_FACTOR), (int)viewWidth);
 
367
          viewWidth= divres.quot * viewWidth + (divres.rem ? viewWidth : 0);
 
368
          divres= div((int)(h * YSCALE_FACTOR), (int)viewHeight);
 
369
          viewHeight= divres.quot * viewHeight + (divres.rem ? viewHeight : 0);
 
370
        }
 
371
      }
 
372
 
 
373
      std::string name_prefix= "DBD4 Model";
 
374
      /// std::string view_class_name= bec::replace_string(model.class_name(), ".Model", ".View");
 
375
      std::string name= grt::get_name_suggestion_for_list_object(
 
376
        grt::ObjectListRef::cast_from(model->diagrams()),
 
377
        name_prefix, false);
 
378
 
 
379
      ///view= _grt->create_object<workbench_physical_View>(view_class_name);
 
380
      ///view->owner(model);
 
381
      view->name(grt::StringRef(name));
 
382
      view->width(grt::DoubleRef(viewWidth));
 
383
      view->height(grt::DoubleRef(viewHeight));
 
384
      ///view->zoom(grt::DoubleRef(1));
 
385
 
 
386
      ///do_transactable_list_insert(_undo_man, model->views(), view);
 
387
    }
 
388
 
 
389
    db_mgmt_RdbmsRef rdbms= model->rdbms();
 
390
 
 
391
    // settings
 
392
    std::map<int, std::string> region_colors;
 
393
    const TiXmlElement *settings_el= dbmodel_el->FirstChildElement("SETTINGS");
 
394
    if (settings_el)
 
395
    {
 
396
      // DBD4 model datatypes mapping
 
397
      const TiXmlElement *datatypes_el= settings_el->FirstChildElement("DATATYPES");
 
398
      {
 
399
        if (datatypes_el)
 
400
        {
 
401
          const TiXmlElement *datatype_el= datatypes_el->FirstChildElement("DATATYPE");
 
402
          while (datatype_el)
 
403
          {
 
404
            datatype_el->QueryIntAttribute("PhysicalMapping", &id);
 
405
            int is_datatype_synonym= id;
 
406
            int datatype_id;
 
407
            datatype_el->QueryIntAttribute("ID", &datatype_id);
 
408
            const char *attr_name= (is_datatype_synonym ? "PhysicalTypeName" : "TypeName");
 
409
            const char *type_name= datatype_el->Attribute(attr_name);
 
410
 
 
411
            _datatypes[datatype_id]= type_name;
 
412
            if (!is_datatype_synonym)
 
413
            {
 
414
              _datatypes_revind[type_name]= datatype_id;
 
415
 
 
416
              const TiXmlElement *options_el= datatype_el->FirstChildElement("OPTIONS");
 
417
              if (options_el)
 
418
              {
 
419
                std::list<Simple_type_flag> flags;
 
420
 
 
421
                const TiXmlElement *option_el= options_el->FirstChildElement("OPTION");
 
422
                while (option_el)
 
423
                {
 
424
                  Simple_type_flag flag;
 
425
                  flag.name= option_el->Attribute("Name");
 
426
                  option_el->QueryIntAttribute("Default", &id);
 
427
                  flag.default_val= id;
 
428
                  flags.push_back(flag);
 
429
 
 
430
                  option_el= option_el->NextSiblingElement();
 
431
                }
 
432
 
 
433
                _datatypes_flags[datatype_id]= flags;
 
434
              }
 
435
            }
 
436
            else
 
437
              _datatypes_flags[datatype_id]= _datatypes_flags[_datatypes_revind[type_name]];
 
438
 
 
439
            datatype_el= datatype_el->NextSiblingElement();
 
440
          }
 
441
        }
 
442
      }
 
443
 
 
444
      // cache schemata
 
445
      const TiXmlElement *table_prefixes_el= settings_el->FirstChildElement("TABLEPREFIXES");
 
446
      {
 
447
        if (table_prefixes_el)
 
448
        {
 
449
          const TiXmlElement *table_prefix_el= table_prefixes_el->FirstChildElement("TABLEPREFIX");
 
450
 
 
451
          // skip default schema (use mydb instead)
 
452
          if (table_prefix_el)
 
453
            table_prefix_el= table_prefix_el->NextSiblingElement();
 
454
 
 
455
          _grt->send_info("Schemata:");
 
456
          while (table_prefix_el)
 
457
          {
 
458
            std::string schema_name= dbd_string_to_utf8(table_prefix_el->Attribute("Name"));
 
459
            _grt->send_info(std::string("...").append(schema_name));
 
460
 
 
461
            ensure_schema_created(_schemata.size(), schema_name.c_str());
 
462
 
 
463
            table_prefix_el= table_prefix_el->NextSiblingElement();
 
464
          }
 
465
        }
 
466
      }
 
467
 
 
468
      // colors
 
469
      const TiXmlElement *regions_colors_el= settings_el->FirstChildElement("REGIONCOLORS");
 
470
      {
 
471
        if (regions_colors_el)
 
472
        {
 
473
          int id= 0;
 
474
          const TiXmlElement *regions_color_el= regions_colors_el->FirstChildElement("REGIONCOLOR");
 
475
          while (regions_color_el)
 
476
          {
 
477
            std::string color= regions_color_el->Attribute("Color");
 
478
            std::vector<std::string> color_pair;
 
479
            split_string(color, "=", color_pair);
 
480
            region_colors[id]= (2 == color_pair.size()) ? color_pair[1] : std::string();
 
481
 
 
482
            ++id;
 
483
            regions_color_el= regions_color_el->NextSiblingElement();
 
484
          }
 
485
        }
 
486
      }
 
487
    }
 
488
 
 
489
    // metadata
 
490
    const TiXmlElement *metadata_el= dbmodel_el->FirstChildElement("METADATA");
 
491
    if (metadata_el)
 
492
    {
 
493
      // regions
 
494
      Layers layers;
 
495
      const TiXmlElement *regions_el= metadata_el->FirstChildElement("REGIONS");
 
496
      {
 
497
        if (regions_el)
 
498
        {
 
499
          _grt->send_info("Layers:");
 
500
 
 
501
          const TiXmlElement *region_el= regions_el->FirstChildElement("REGION");
 
502
          while (region_el)
 
503
          {
 
504
            std::string layer_name= dbd_string_to_utf8(region_el->Attribute("RegionName"));
 
505
            _grt->send_info(std::string("...").append(layer_name));
 
506
 
 
507
            model_LayerRef layer= workbench_physical_LayerRef(_grt);
 
508
            layer->owner(view);
 
509
            layer->name(layer_name);
 
510
 
 
511
            region_el->QueryIntAttribute("XPos", &id);
 
512
            layer->left(id*XSCALE_FACTOR);
 
513
            region_el->QueryIntAttribute("YPos", &id);
 
514
            layer->top(id*YSCALE_FACTOR);
 
515
            region_el->QueryIntAttribute("Width", &id);
 
516
            layer->width(id*XSCALE_FACTOR);
 
517
            region_el->QueryIntAttribute("Height", &id);
 
518
            layer->height(id*YSCALE_FACTOR);
 
519
            region_el->QueryIntAttribute("RegionColor", &id);
 
520
            layer->color(region_colors[id]);
 
521
            layer->description(dbd_string_to_utf8(region_el->Attribute("Comments")));
 
522
 
 
523
            view->layers().insert(layer);
 
524
 
 
525
            region_el->QueryIntAttribute("ID", &id);
 
526
            layers[id]= layer;
 
527
 
 
528
            region_el= region_el->NextSiblingElement();
 
529
          }
 
530
        }
 
531
      }
 
532
 
 
533
      // tables
 
534
      const TiXmlElement *tables_el= metadata_el->FirstChildElement("TABLES");
 
535
      {
 
536
        if (tables_el)
 
537
        {
 
538
          _grt->send_info("Tables:");
 
539
 
 
540
          TableInsertsLoader table_inserts_loader(grtm);
 
541
 
 
542
          const TiXmlElement *table_el= tables_el->FirstChildElement("TABLE");
 
543
          while (table_el)
 
544
          {
 
545
            std::string table_name= dbd_string_to_utf8(table_el->Attribute("Tablename"));
 
546
            _grt->send_info(std::string("...").append(table_name));
 
547
 
 
548
            // table
 
549
            table_el->QueryIntAttribute("TablePrefix", &id);
 
550
            db_mysql_SchemaRef schema= _schemata[id];
 
551
 
 
552
            db_mysql_TableRef table(_grt);
 
553
            table->owner(schema);
 
554
 
 
555
            table->name(table_name);
 
556
            table_el->QueryIntAttribute("Temporary", &id);
 
557
            table->isTemporary(id);
 
558
            table->comment(dbd_string_to_utf8(table_el->Attribute("Comments")));
 
559
            parse_table_options(table, table_el->Attribute("TableOptions"));
 
560
 
 
561
            table_el->QueryIntAttribute("ID", &id);
 
562
            _tables[id]= table;
 
563
 
 
564
            // columns
 
565
            const TiXmlElement *columns_el= table_el->FirstChildElement("COLUMNS");
 
566
            if (columns_el)
 
567
            {
 
568
              ListRef<db_mysql_Column> columns= table->columns();
 
569
              const TiXmlElement *column_el= columns_el->FirstChildElement("COLUMN");
 
570
              while(column_el)
 
571
              {
 
572
                db_mysql_ColumnRef column(_grt);
 
573
                column->owner(table);
 
574
 
 
575
                column->name(dbd_string_to_utf8(column_el->Attribute("ColName")));
 
576
                column_el->QueryIntAttribute("NotNull", &id);
 
577
                column->isNotNull(id);
 
578
                column_el->QueryIntAttribute("AutoInc", &id);
 
579
                column->autoIncrement(id);
 
580
                column->comment(dbd_string_to_utf8(column_el->Attribute("Comments")));
 
581
                bec::ColumnHelper::set_default_value(column, 
 
582
                  dbd_string_to_utf8(column_el->Attribute("DefaultValue")));
 
583
                column->datatypeExplicitParams(column_el->Attribute("DatatypeParams"));
 
584
 
 
585
                column_el->QueryIntAttribute("idDatatype", &id);
 
586
                std::string typestr= _datatypes[id];
 
587
                std::list<Simple_type_flag> flags= _datatypes_flags[id];
 
588
                // append datatype params to type name
 
589
                typestr.append(dbd_string_to_utf8(column_el->Attribute("DatatypeParams")));
 
590
                if (!column->setParseType(typestr, rdbms->simpleDatatypes()))
 
591
                  _grt->send_warning(strfmt("Error parsing type for column '%s' (%s)", column->name().c_str(), typestr.c_str()));
 
592
 
 
593
                // flags
 
594
                std::list<int> flags2;
 
595
                const TiXmlElement *optionselected_el= column_el->FirstChildElement("OPTIONSELECTED");
 
596
                if (optionselected_el)
 
597
                {
 
598
                  const TiXmlElement *optionselect_el= optionselected_el->FirstChildElement("OPTIONSELECT");
 
599
                  while (optionselect_el)
 
600
                  {
 
601
                    optionselect_el->QueryIntAttribute("Value", &id);
 
602
                    flags2.push_back(id);
 
603
 
 
604
                    optionselect_el= optionselect_el->NextSiblingElement();
 
605
                  }
 
606
                }
 
607
                {
 
608
                  std::list<Simple_type_flag>::const_iterator i= flags.begin();
 
609
                  std::list<int>::const_iterator i2= flags2.begin();
 
610
                  for (; i != flags.end(); ++i)
 
611
                  {
 
612
                    int flag_value= (flags2.empty() ? i->default_val : *i2);
 
613
                    if (flag_value)
 
614
                      column->flags().insert(i->name);
 
615
                    if (!flags2.empty())
 
616
                      ++i2;
 
617
                  }
 
618
                }
 
619
 
 
620
                columns.insert(column);
 
621
                column_el->QueryIntAttribute("ID", &id);
 
622
                _columns[id]= column;
 
623
 
 
624
                column_el= column_el->NextSiblingElement();
 
625
              }
 
626
            }
 
627
 
 
628
            // indices
 
629
            const TiXmlElement *indices_el= table_el->FirstChildElement("INDICES");
 
630
            if (indices_el)
 
631
            {
 
632
              ListRef<db_mysql_Index> indices= table->indices();
 
633
              const TiXmlElement *index_el= indices_el->FirstChildElement("INDEX");
 
634
              while(index_el)
 
635
              {
 
636
                db_mysql_IndexRef index(_grt);
 
637
                index->owner(table);
 
638
 
 
639
                index->name(dbd_string_to_utf8(index_el->Attribute("IndexName")));
 
640
 
 
641
                // index->indexType
 
642
                index_el->QueryIntAttribute("IndexKind", &id);
 
643
                if (0 == id || (*index->name()).compare("PRIMARY") == 0)
 
644
                {
 
645
                  index->indexType("PRIMARY");
 
646
                  index->isPrimary(1);
 
647
                  index->unique(1);
 
648
                  table->primaryKey(index);
 
649
                }
 
650
                else if (2 == id)
 
651
                  index->indexType("UNIQUE");
 
652
                else if (3 == id)
 
653
                  index->indexType("FULLTEXT");
 
654
                else
 
655
                  index->indexType("INDEX");
 
656
 
 
657
                // index columns
 
658
                const TiXmlElement *index_columns_el= index_el->FirstChildElement("INDEXCOLUMNS");
 
659
                if (index_columns_el)
 
660
                {
 
661
                  ListRef<db_mysql_IndexColumn> index_columns= index->columns();
 
662
                  const TiXmlElement *index_column_el= index_columns_el->FirstChildElement("INDEXCOLUMN");
 
663
                  while(index_column_el)
 
664
                  {
 
665
                    db_mysql_IndexColumnRef index_column(_grt);
 
666
                    index_column->owner(index);
 
667
 
 
668
                    index_column_el->QueryIntAttribute("idColumn", &id);
 
669
                    index_column->referencedColumn(_columns[id]);
 
670
                    index_column_el->QueryIntAttribute("LengthParam", &id);
 
671
                    index_column->columnLength(id);
 
672
 
 
673
                    index_columns.insert(index_column);
 
674
 
 
675
                    index_column_el= index_column_el->NextSiblingElement();
 
676
                  }
 
677
                }
 
678
 
 
679
                indices.insert(index);
 
680
 
 
681
                index_el= index_el->NextSiblingElement();
 
682
              }
 
683
            }
 
684
 
 
685
            // table inserts
 
686
            {
 
687
              std::string inserts_script= dbd_string_to_utf8(table_el->Attribute("StandardInserts"));
 
688
              try
 
689
              {
 
690
                table_inserts_loader.process_table(table, inserts_script);
 
691
              }
 
692
              catch (const std::exception &exc)
 
693
              {
 
694
                _grt->send_error("Import DBD4 Model", base::strfmt("Error processing inserts importing DBD4 model %s: %s", exc.what(), inserts_script.c_str()));
 
695
                throw;
 
696
              }
 
697
            }
 
698
            schema->tables().insert(table);
 
699
 
 
700
            // table figure
 
701
            Rect rect;
 
702
            table_el->QueryIntAttribute("XPos", &id);
 
703
            rect.left= id*XSCALE_FACTOR;
 
704
            table_el->QueryIntAttribute("YPos", &id);
 
705
            rect.top= id*YSCALE_FACTOR;
 
706
 
 
707
            model_LayerRef layer= find_containing_layer(rect, layers);
 
708
            if (!layer.is_valid())
 
709
              layer= view->rootLayer();
 
710
            else
 
711
            {
 
712
              rect.left-= layer->left();
 
713
              rect.top-= layer->top();
 
714
            }
 
715
 
 
716
            workbench_physical_TableFigureRef table_figure= workbench_physical_TableFigureRef(_grt);
 
717
            table_figure->owner(view);
 
718
            table_figure->layer(layer);
 
719
            table_figure->left(rect.left);
 
720
            table_figure->top(rect.top);
 
721
            table_figure->table(table);
 
722
            table_figure->color(table_figure_color);
 
723
 
 
724
            table_el->QueryIntAttribute("Collapsed", &id);
 
725
            table_figure->expanded(abs(id-1));
 
726
 
 
727
            add_figure_on_layer(layer, table_figure);
 
728
 
 
729
            table_el->QueryIntAttribute("ID", &id);
 
730
            _table_figures[id]= table_figure;
 
731
 
 
732
            table_el= table_el->NextSiblingElement();
 
733
          }
 
734
        }
 
735
      }
 
736
 
 
737
      // relations / fkeys
 
738
      const TiXmlElement *relations_el= metadata_el->FirstChildElement("RELATIONS");
 
739
      {
 
740
        if (relations_el)
 
741
        {
 
742
          _grt->send_info("Connections:");
 
743
 
 
744
          const TiXmlElement *relation_el= relations_el->FirstChildElement("RELATION");
 
745
          while (relation_el)
 
746
          {
 
747
            std::string relation_name= dbd_string_to_utf8(relation_el->Attribute("RelationName"));
 
748
            _grt->send_info(std::string("...").append(relation_name));
 
749
 
 
750
            relation_el->QueryIntAttribute("DestTable", &id);
 
751
            db_mysql_TableRef srcTable= _tables[id];
 
752
            relation_el->QueryIntAttribute("SrcTable", &id);
 
753
            db_mysql_TableRef destTable= _tables[id];
 
754
 
 
755
            db_mysql_ForeignKeyRef fkey(_grt);
 
756
            fkey->owner(srcTable);
 
757
 
 
758
            /*
 
759
            real insert of fkey is occured after relation figure is added to model.
 
760
            that's needed to disable autocreation of relation.
 
761
            */
 
762
            //srctable->foreignKeys().insert(fkey);
 
763
 
 
764
            // connection figure
 
765
            workbench_physical_ConnectionRef conn_figure(_grt);
 
766
            conn_figure->owner(view);
 
767
 
 
768
            relation_el->QueryIntAttribute("DestTable", &id);
 
769
            workbench_physical_TableFigureRef start_table_figure= _table_figures[id];
 
770
            relation_el->QueryIntAttribute("SrcTable", &id);
 
771
            workbench_physical_TableFigureRef end_table_figure= _table_figures[id];
 
772
 
 
773
            conn_figure->startFigure(start_table_figure);
 
774
            conn_figure->endFigure(end_table_figure);
 
775
 
 
776
            conn_figure->foreignKey(fkey);
 
777
 
 
778
            conn_figure->name(dbd_string_to_utf8(relation_el->Attribute("RelationName")));
 
779
            conn_figure->caption(dbd_string_to_utf8(relation_el->Attribute("RelationName")));
 
780
            conn_figure->comment(dbd_string_to_utf8(relation_el->Attribute("Comments")));
 
781
            relation_el->QueryIntAttribute("CaptionOffsetX", &id);
 
782
            conn_figure->captionXOffs(id);
 
783
            relation_el->QueryIntAttribute("CaptionOffsetY", &id);
 
784
            conn_figure->captionYOffs(id);
 
785
            relation_el->QueryIntAttribute("StartIntervalOffsetX", &id);
 
786
            conn_figure->startCaptionXOffs(id);
 
787
            relation_el->QueryIntAttribute("StartIntervalOffsetY", &id);
 
788
            conn_figure->startCaptionYOffs(id);
 
789
            relation_el->QueryIntAttribute("EndIntervalOffsetX", &id);
 
790
            conn_figure->endCaptionXOffs(id);
 
791
            relation_el->QueryIntAttribute("EndIntervalOffsetY", &id);
 
792
            conn_figure->endCaptionYOffs(id);
 
793
 
 
794
            relation_el->QueryIntAttribute("Invisible", &id);
 
795
            conn_figure->visible(abs(id-1));
 
796
 
 
797
            relation_el->QueryIntAttribute("Splitted", &id);
 
798
            conn_figure->drawSplit(id);
 
799
 
 
800
            view->connections().insert(conn_figure);
 
801
 
 
802
            /*
 
803
            now connection figure auto-creation is disabled.
 
804
            continue with fkey.
 
805
            */
 
806
            fkey->referencedTable(destTable);
 
807
            if (_gen_fk_names_when_empty)
 
808
            {
 
809
              std::string name= bec::TableHelper::generate_foreign_key_name();
 
810
              fkey->name(name);
 
811
            }
 
812
            else
 
813
              fkey->name(relation_name); // for tests only (to keep names constant, hence comparable)
 
814
            fkey->comment(dbd_string_to_utf8(relation_el->Attribute("Comments")));
 
815
 
 
816
            std::string fk_fields= relation_el->Attribute("FKFields");
 
817
            std::vector<std::string> field_pairs;
 
818
            split_string(fk_fields, "\\n", field_pairs);
 
819
            for (std::vector<std::string>::iterator i= field_pairs.begin(); i != field_pairs.end(); ++i)
 
820
            {
 
821
              std::vector<std::string> field_pair;
 
822
              split_string(*i, "=", field_pair);
 
823
              {
 
824
                db_mysql_ColumnRef column= find_named_object_in_list(destTable->columns(), field_pair[0].c_str(), false);
 
825
                if (!column.is_valid())
 
826
                {
 
827
                  column= db_mysql_ColumnRef(_grt);
 
828
                  column->owner(destTable);
 
829
                  column->name(field_pair[0]);
 
830
                  destTable->columns().insert(column);
 
831
                }
 
832
                fkey->referencedColumns().insert(column);
 
833
              }
 
834
              {
 
835
                db_mysql_ColumnRef column= find_named_object_in_list(srcTable->columns(), field_pair[1].c_str(), false);
 
836
                if (!column.is_valid())
 
837
                {
 
838
                  column= db_mysql_ColumnRef(_grt);
 
839
                  column->owner(srcTable);
 
840
                  column->name(field_pair[1]);
 
841
                  srcTable->columns().insert(column);
 
842
                }
 
843
                fkey->columns().insert(column);
 
844
              }
 
845
            }
 
846
 
 
847
            relation_el->QueryIntAttribute("CreateRefDef", &id);
 
848
            if (1 == id)
 
849
            {
 
850
              std::string ref_def= relation_el->Attribute("RefDef");
 
851
              std::vector<std::string> ref_defs;
 
852
              split_string(ref_def, "\\n", ref_defs);
 
853
              for (std::vector<std::string>::iterator i= ref_defs.begin(); i != ref_defs.end(); ++i)
 
854
              {
 
855
                std::vector<std::string> ref_def_parts;
 
856
                split_string(*i, "=", ref_def_parts);
 
857
                {
 
858
                  if (ref_def_parts.size() != 2)
 
859
                    continue;
 
860
 
 
861
                  if (("OnUpdate" == ref_def_parts[0]) || ("OnDelete" == ref_def_parts[0]))
 
862
                  {
 
863
                    /*
 
864
                    on delete/update rule:
 
865
                    0 - restrict
 
866
                    1 - cascade
 
867
                    2 - set null
 
868
                    3 - no action
 
869
                    4 - set default
 
870
                    */
 
871
                    std::string rule;
 
872
                    int val;
 
873
                    {
 
874
                      std::stringstream ss;
 
875
                      ss << ref_def_parts[1];
 
876
                      ss >> val;
 
877
                    }
 
878
                    switch (val)
 
879
                    {
 
880
                    case 0: rule= "RESTRICT"; break;
 
881
                    case 1: rule= "CASCADE"; break;
 
882
                    case 2: rule= "SET NULL"; break;
 
883
                    case 3: rule= "NO ACTION"; break;
 
884
                    default: break;
 
885
                    }
 
886
                    if ("OnDelete" == ref_def_parts[0])
 
887
                      fkey->deleteRule(rule);
 
888
                    else if ("OnUpdate" == ref_def_parts[0])
 
889
                      fkey->updateRule(rule);
 
890
                  }
 
891
                }
 
892
              }
 
893
            }
 
894
 
 
895
            /*
 
896
            relation kind:
 
897
            0 - one_to_one
 
898
            1 - one_to_many
 
899
            2 - one_to_many non-identifying
 
900
            4 - arrow
 
901
            5 - one_to_one non-identifying
 
902
            */
 
903
            relation_el->QueryIntAttribute("Kind", &id);
 
904
            fkey->many((int)(1 == id || 2 == id));
 
905
            relation_el->QueryIntAttribute("OptionalEnd", &id);
 
906
            fkey->mandatory(abs(id-1));
 
907
            relation_el->QueryIntAttribute("OptionalStart", &id);
 
908
            fkey->referencedMandatory(abs(id-1));
 
909
 
 
910
            srcTable->foreignKeys().insert(fkey);
 
911
 
 
912
            relation_el= relation_el->NextSiblingElement();
 
913
          }
 
914
        }
 
915
      }
 
916
 
 
917
      // notes
 
918
      const TiXmlElement *notes_el= metadata_el->FirstChildElement("NOTES");
 
919
      {
 
920
        if (notes_el)
 
921
        {
 
922
          _grt->send_info("Notes:");
 
923
 
 
924
          const TiXmlElement *note_el= notes_el->FirstChildElement("NOTE");
 
925
          while (note_el)
 
926
          {
 
927
            std::string note_name= dbd_string_to_utf8(note_el->Attribute("NoteName"));
 
928
            _grt->send_info(std::string("...").append(note_name));
 
929
 
 
930
            workbench_model_NoteFigureRef note_figure(_grt);
 
931
            note_figure->owner(view);
 
932
            note_figure->layer(view->rootLayer());
 
933
            note_figure->name(note_name);
 
934
 
 
935
            note_el->QueryIntAttribute("XPos", &id);
 
936
            note_figure->left(id*XSCALE_FACTOR);
 
937
            note_el->QueryIntAttribute("YPos", &id);
 
938
            note_figure->top(id*YSCALE_FACTOR);
 
939
            note_figure->color(note_figure_color);
 
940
            note_figure->text(dbd_string_to_utf8(note_el->Attribute("NoteText")));
 
941
 
 
942
            add_figure_on_layer(view->rootLayer(), note_figure);
 
943
 
 
944
            note_el= note_el->NextSiblingElement();
 
945
          }
 
946
        }
 
947
      }
 
948
 
 
949
      // images
 
950
      const TiXmlElement *images_el= metadata_el->FirstChildElement("IMAGES");
 
951
      {
 
952
        if (images_el)
 
953
        {
 
954
          _grt->send_info("Images:");
 
955
 
 
956
          const std::string tmp_dir= grtm->get_unique_tmp_subdir();
 
957
          // crete temp dir
 
958
          {
 
959
            g_mkdir(grtm->get_tmp_dir().c_str(), 0700);
 
960
            g_mkdir(tmp_dir.c_str(), 0700);
 
961
          }
 
962
 
 
963
          const TiXmlElement *image_el= images_el->FirstChildElement("IMAGE");
 
964
          while (image_el)
 
965
          {
 
966
            image_el->QueryIntAttribute("IsLinkedObject", &id);
 
967
            std::string img_format= image_el->Attribute("ImgFormat");
 
968
            if ((img_format.compare("PNG") == 0) && (id == 0))
 
969
            {
 
970
              std::string image_name= dbd_string_to_utf8(image_el->Attribute("ImageName"));
 
971
              _grt->send_info(std::string("...").append(image_name));
 
972
 
 
973
              std::string filename;
 
974
              filename
 
975
                .append(tmp_dir)
 
976
                .append("/")
 
977
                .append(image_name)
 
978
                .append("(")
 
979
                .append(image_el->Attribute("ID"))
 
980
                .append(").png");
 
981
 
 
982
              {
 
983
                std::istringstream iss(image_el->Attribute("ImgData"));
 
984
                std::ofstream ofs(filename.c_str(), std::ios_base::out|std::ios_base::binary);
 
985
                stream_conv(iss, ofs, &unhex<2,char>);
 
986
              }
 
987
 
 
988
              workbench_model_ImageFigureRef image_figure(_grt);
 
989
              image_figure->owner(view);
 
990
              image_figure->layer(view->rootLayer());
 
991
              image_figure->name(image_name);
 
992
 
 
993
              image_el->QueryIntAttribute("XPos", &id);
 
994
              image_figure->left(id*XSCALE_FACTOR);
 
995
              image_el->QueryIntAttribute("YPos", &id);
 
996
              image_figure->top(id*YSCALE_FACTOR);
 
997
 
 
998
              image_el->QueryIntAttribute("Width", &id);
 
999
              image_figure->width(id);
 
1000
              image_el->QueryIntAttribute("Height", &id);
 
1001
              image_figure->height(id);
 
1002
 
 
1003
              image_figure->expanded(1);
 
1004
              image_figure->color(image_color_color);
 
1005
 
 
1006
              add_figure_on_layer(view->rootLayer(), image_figure);
 
1007
 
 
1008
              image_figure->setImageFile(filename);
 
1009
            }
 
1010
 
 
1011
            image_el= image_el->NextSiblingElement();
 
1012
          }
 
1013
        }
 
1014
      }
 
1015
    }
 
1016
  }
 
1017
 
 
1018
  remove_unused_schemata();
 
1019
 
 
1020
  _grt->send_info("Finished import DBD4 model.");
 
1021
 
 
1022
  return 1; // success
 
1023
}
 
1024
 
 
1025
 
 
1026
db_mysql_SchemaRef Wb_mysql_import_DBD4::ensure_schema_created(int index, const char *name)
 
1027
{
 
1028
  ListRef<db_mysql_Schema> schemata= _catalog->schemata();
 
1029
 
 
1030
  db_mysql_SchemaRef schema= find_named_object_in_list(schemata, name, false);
 
1031
 
 
1032
  if (!schema.is_valid())
 
1033
  {
 
1034
    schema= db_mysql_SchemaRef(_grt);
 
1035
    schema->owner(_catalog);
 
1036
    schema->name(name);
 
1037
    schemata.insert(schema);
 
1038
    _created_schemata.insert(schema);
 
1039
  }
 
1040
  _schemata[index]= schema;
 
1041
 
 
1042
  return schema;
 
1043
}
 
1044
 
 
1045
 
 
1046
/*
 
1047
removes schemata that were created during import but don't contain any object inside.
 
1048
*/
 
1049
void Wb_mysql_import_DBD4::remove_unused_schemata()
 
1050
{
 
1051
  for (size_t n= 0, count= _created_schemata.count(); n < count; ++n)
 
1052
  {
 
1053
    db_mysql_SchemaRef schema= _created_schemata.get(n);
 
1054
    if (schema->tables().count() == 0
 
1055
      && schema->views().count() == 0
 
1056
      && schema->routines().count() == 0)
 
1057
      _catalog->schemata().insert(schema);
 
1058
  }
 
1059
}