~drizzle-trunk/drizzle/development

1751.4.19 by Andrew Hutchings
Put drizzle and mysql processes in seperate classes/files
1
/* -*- mode: c++; c-basic-offset: 2; indent-tabs-mode: nil; -*-
2
 *  vim:expandtab:shiftwidth=2:tabstop=2:smarttab:
3
 *
4
 *  Copyright (C) 2010 Andrew Hutchings
5
 *
6
 *  This program is free software; you can redistribute it and/or modify
7
 *  it under the terms of the GNU General Public License as published by
8
 *  the Free Software Foundation; version 2 of the License.
9
 *
10
 *  This program is distributed in the hope that it will be useful,
11
 *  but WITHOUT ANY WARRANTY; without even the implied warranty of
12
 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
13
 *  GNU General Public License for more details.
14
 *
15
 *  You should have received a copy of the GNU General Public License
16
 *  along with this program; if not, write to the Free Software
17
 *  Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
18
 */
19
20
#include "drizzledump_data.h"
21
#include "drizzledump_drizzle.h"
22
#include "client_priv.h"
23
#include <string>
24
#include <iostream>
25
#include <drizzled/gettext.h>
26
#include <boost/lexical_cast.hpp>
27
1751.4.23 by Andrew Hutchings
Fix various bugs
28
extern bool  verbose;
29
1751.4.19 by Andrew Hutchings
Put drizzle and mysql processes in seperate classes/files
30
bool DrizzleDumpDatabaseDrizzle::populateTables()
31
{
1751.4.20 by Andrew Hutchings
Add database connection class and the start of a database output ostream
32
  drizzle_result_st *result;
1751.4.19 by Andrew Hutchings
Put drizzle and mysql processes in seperate classes/files
33
  drizzle_row_t row;
34
  std::string query;
35
1751.4.25 by Andrew Hutchings
Fix error handling
36
  if (not dcon->setDB(databaseName))
37
    return false;
1751.4.19 by Andrew Hutchings
Put drizzle and mysql processes in seperate classes/files
38
1751.4.23 by Andrew Hutchings
Fix various bugs
39
  if (verbose)
40
    std::cerr << _("-- Retrieving table structures for ") << databaseName << "..." << std::endl;
41
1751.4.19 by Andrew Hutchings
Put drizzle and mysql processes in seperate classes/files
42
  query="SELECT TABLE_NAME, TABLE_COLLATION, ENGINE FROM DATA_DICTIONARY.TABLES WHERE TABLE_SCHEMA='";
43
  query.append(databaseName);
44
  query.append("' ORDER BY TABLE_NAME");
45
1751.4.20 by Andrew Hutchings
Add database connection class and the start of a database output ostream
46
  result= dcon->query(query);
47
1751.4.25 by Andrew Hutchings
Fix error handling
48
  if (result == NULL)
49
    return false;
50
1751.4.20 by Andrew Hutchings
Add database connection class and the start of a database output ostream
51
  while ((row= drizzle_row_next(result)))
1751.4.19 by Andrew Hutchings
Put drizzle and mysql processes in seperate classes/files
52
  {
53
    std::string tableName(row[0]);
1751.4.25 by Andrew Hutchings
Fix error handling
54
    std::string displayName(tableName);
55
    cleanTableName(displayName);
56
    if (not ignoreTable(displayName))
1751.4.24 by Andrew Hutchings
Fix ignore tables
57
      continue;
58
1751.4.20 by Andrew Hutchings
Add database connection class and the start of a database output ostream
59
    DrizzleDumpTable *table = new DrizzleDumpTableDrizzle(tableName, dcon);
1751.4.25 by Andrew Hutchings
Fix error handling
60
    table->displayName= displayName;
1751.4.19 by Andrew Hutchings
Put drizzle and mysql processes in seperate classes/files
61
    table->collate= row[1];
62
    table->engineName= row[2];
63
    table->autoIncrement= 0;
64
    table->database= this;
1751.4.25 by Andrew Hutchings
Fix error handling
65
    if ((not table->populateFields()) or (not table->populateIndexes()))
66
    {
67
      delete table;
68
      return false;
69
    }
1751.4.19 by Andrew Hutchings
Put drizzle and mysql processes in seperate classes/files
70
    tables.push_back(table);
71
  }
72
1751.4.20 by Andrew Hutchings
Add database connection class and the start of a database output ostream
73
  dcon->freeResult(result);
1751.4.19 by Andrew Hutchings
Put drizzle and mysql processes in seperate classes/files
74
75
  return true;
76
}
77
1751.4.23 by Andrew Hutchings
Fix various bugs
78
bool DrizzleDumpDatabaseDrizzle::populateTables(const std::vector<std::string> &table_names)
79
{
80
  drizzle_result_st *result;
81
  drizzle_row_t row;
82
  std::string query;
83
1751.4.25 by Andrew Hutchings
Fix error handling
84
  if (not dcon->setDB(databaseName))
85
    return false;
1751.4.23 by Andrew Hutchings
Fix various bugs
86
87
  if (verbose)
88
    std::cerr << _("-- Retrieving table structures for ") << databaseName << "..." << std::endl;
89
  for (std::vector<std::string>::const_iterator it= table_names.begin(); it != table_names.end(); ++it)
90
  {
91
    std::string tableName= *it;
1751.4.25 by Andrew Hutchings
Fix error handling
92
    std::string displayName(tableName);
93
    cleanTableName(displayName);
94
    if (not ignoreTable(displayName))
1751.4.24 by Andrew Hutchings
Fix ignore tables
95
      continue;
96
1751.4.23 by Andrew Hutchings
Fix various bugs
97
    query="SELECT TABLE_NAME, TABLE_COLLATION, ENGINE FROM DATA_DICTIONARY.TABLES WHERE TABLE_SCHEMA='";
98
    query.append(databaseName);
99
    query.append("' AND TABLE_NAME = '");
100
    query.append(tableName);
101
    query.append("'");
102
103
    result= dcon->query(query);
104
1751.4.25 by Andrew Hutchings
Fix error handling
105
    if (result == NULL)
106
    {
107
      std::cerr << "Error: Could not obtain schema for table " << displayName << std::endl;
108
      return false;
109
    }
110
1751.4.23 by Andrew Hutchings
Fix various bugs
111
    if ((row= drizzle_row_next(result)))
112
    {
1751.4.24 by Andrew Hutchings
Fix ignore tables
113
      DrizzleDumpTableDrizzle *table = new DrizzleDumpTableDrizzle(tableName, dcon);
1751.4.25 by Andrew Hutchings
Fix error handling
114
      table->displayName= displayName;
1751.4.23 by Andrew Hutchings
Fix various bugs
115
      table->collate= row[1];
116
      table->engineName= row[2];
117
      table->autoIncrement= 0;
118
      table->database= this;
1751.4.25 by Andrew Hutchings
Fix error handling
119
      if ((not table->populateFields()) or (not table->populateIndexes()))
120
      {
121
        std::cerr  << "Error: Could not get fields and/ot indexes for table " << displayName << std::endl;
122
        delete table;
123
        dcon->freeResult(result);
124
        return false;
125
      }
1751.4.23 by Andrew Hutchings
Fix various bugs
126
      tables.push_back(table);
127
      dcon->freeResult(result);
128
    }
129
    else
130
    {
1751.4.25 by Andrew Hutchings
Fix error handling
131
      std::cerr << "Error: Table " << displayName << " not found." << std::endl;
1751.4.23 by Andrew Hutchings
Fix various bugs
132
      dcon->freeResult(result);
133
      return false;
134
    }
135
  }
136
137
  return true;
138
139
}
140
1751.4.19 by Andrew Hutchings
Put drizzle and mysql processes in seperate classes/files
141
void DrizzleDumpDatabaseDrizzle::setCollate(const char* newCollate)
142
{
143
  if (newCollate)
144
    collate= newCollate;
145
  else
146
    collate= "utf8_general_ci";
147
}
148
149
bool DrizzleDumpTableDrizzle::populateFields()
150
{
1751.4.20 by Andrew Hutchings
Add database connection class and the start of a database output ostream
151
  drizzle_result_st *result;
1751.4.19 by Andrew Hutchings
Put drizzle and mysql processes in seperate classes/files
152
  drizzle_row_t row;
153
  std::string query;
154
1751.4.23 by Andrew Hutchings
Fix various bugs
155
  if (verbose)
156
    std::cerr << _("-- Retrieving fields for ") << tableName << "..." << std::endl;
157
1751.4.19 by Andrew Hutchings
Put drizzle and mysql processes in seperate classes/files
158
  query= "SELECT COLUMN_NAME, DATA_TYPE, COLUMN_DEFAULT, COLUMN_DEFAULT_IS_NULL, IS_NULLABLE, CHARACTER_MAXIMUM_LENGTH, NUMERIC_PRECISION, NUMERIC_SCALE, COLLATION_NAME, IS_AUTO_INCREMENT, ENUM_VALUES FROM DATA_DICTIONARY.COLUMNS WHERE TABLE_SCHEMA='";
159
  query.append(database->databaseName);
160
  query.append("' AND TABLE_NAME='");
161
  query.append(tableName);
1751.4.28 by Andrew Hutchings
Remove "ORDER BY ORDINAL_POSITION", eats RAM, sucks performance and it is already ordered correctly anyway
162
  query.append("'");
1751.4.19 by Andrew Hutchings
Put drizzle and mysql processes in seperate classes/files
163
1751.4.20 by Andrew Hutchings
Add database connection class and the start of a database output ostream
164
  result= dcon->query(query);
1751.4.19 by Andrew Hutchings
Put drizzle and mysql processes in seperate classes/files
165
1751.4.25 by Andrew Hutchings
Fix error handling
166
  if (result == NULL)
167
    return false;
168
1751.4.20 by Andrew Hutchings
Add database connection class and the start of a database output ostream
169
  while ((row= drizzle_row_next(result)))
1751.4.19 by Andrew Hutchings
Put drizzle and mysql processes in seperate classes/files
170
  {
171
    std::string fieldName(row[0]);
1751.4.20 by Andrew Hutchings
Add database connection class and the start of a database output ostream
172
    DrizzleDumpField *field = new DrizzleDumpFieldDrizzle(fieldName, dcon);
1751.4.19 by Andrew Hutchings
Put drizzle and mysql processes in seperate classes/files
173
    /* Stop valgrind warning */
174
    field->convertDateTime= false;
175
    /* Also sets collation */
176
    field->setType(row[1], row[8]);
177
    if (row[2])
178
      field->defaultValue= row[2];
179
    else
180
      field->defaultValue= "";
181
182
    field->isNull= (strcmp(row[4], "YES") == 0) ? true : false;
183
    field->isAutoIncrement= (strcmp(row[9], "YES") == 0) ? true : false;
184
    field->defaultIsNull= (strcmp(row[3], "YES") == 0) ? true : false;
185
    field->enumValues= (row[10]) ? row[10] : "";
186
    field->length= (row[5]) ? boost::lexical_cast<uint32_t>(row[5]) : 0;
187
    field->decimalPrecision= (row[6]) ? boost::lexical_cast<uint32_t>(row[6]) : 0;
188
    field->decimalScale= (row[7]) ? boost::lexical_cast<uint32_t>(row[7]) : 0;
189
190
191
    fields.push_back(field);
192
  }
193
1751.4.20 by Andrew Hutchings
Add database connection class and the start of a database output ostream
194
  dcon->freeResult(result);
1751.4.19 by Andrew Hutchings
Put drizzle and mysql processes in seperate classes/files
195
  return true;
196
}
197
198
199
bool DrizzleDumpTableDrizzle::populateIndexes()
200
{
1751.4.20 by Andrew Hutchings
Add database connection class and the start of a database output ostream
201
  drizzle_result_st *result;
1751.4.19 by Andrew Hutchings
Put drizzle and mysql processes in seperate classes/files
202
  drizzle_row_t row;
203
  std::string query;
204
  std::string lastKey;
205
  bool firstIndex= true;
206
  DrizzleDumpIndex *index;
207
1751.4.23 by Andrew Hutchings
Fix various bugs
208
  if (verbose)
209
    std::cerr << _("-- Retrieving indexes for ") << tableName << "..." << std::endl;
210
1751.4.19 by Andrew Hutchings
Put drizzle and mysql processes in seperate classes/files
211
  query= "SELECT INDEX_NAME, COLUMN_NAME, IS_USED_IN_PRIMARY, IS_UNIQUE FROM DATA_DICTIONARY.INDEX_PARTS WHERE TABLE_NAME='";
212
  query.append(tableName);
213
  query.append("'");
214
1751.4.20 by Andrew Hutchings
Add database connection class and the start of a database output ostream
215
  result= dcon->query(query);
1751.4.19 by Andrew Hutchings
Put drizzle and mysql processes in seperate classes/files
216
1751.4.25 by Andrew Hutchings
Fix error handling
217
  if (result == NULL)
218
    return false;
219
1751.4.20 by Andrew Hutchings
Add database connection class and the start of a database output ostream
220
  while ((row= drizzle_row_next(result)))
1751.4.19 by Andrew Hutchings
Put drizzle and mysql processes in seperate classes/files
221
  {
222
    std::string indexName(row[0]);
223
    if (indexName.compare(lastKey) != 0)
224
    {
225
      if (!firstIndex)
226
        indexes.push_back(index);
1751.4.20 by Andrew Hutchings
Add database connection class and the start of a database output ostream
227
      index = new DrizzleDumpIndexDrizzle(indexName, dcon);
1751.4.19 by Andrew Hutchings
Put drizzle and mysql processes in seperate classes/files
228
      index->isPrimary= (strcmp(row[0], "PRIMARY") == 0);
229
      index->isUnique= (strcmp(row[3], "YES") == 0);
230
      index->isHash= 0;
231
      lastKey= row[0];
232
      firstIndex= false;
233
    }
234
    index->columns.push_back(row[1]);
235
  }
236
  if (!firstIndex)
237
    indexes.push_back(index);
238
1751.4.20 by Andrew Hutchings
Add database connection class and the start of a database output ostream
239
  dcon->freeResult(result);
1751.4.19 by Andrew Hutchings
Put drizzle and mysql processes in seperate classes/files
240
  return true;
241
}
242
243
DrizzleDumpData* DrizzleDumpTableDrizzle::getData(void)
244
{
1751.4.25 by Andrew Hutchings
Fix error handling
245
  try
246
  {
247
    return new DrizzleDumpDataDrizzle(this, dcon);
248
  }
249
  catch(...)
250
  {
251
    return NULL;
252
  }
1751.4.19 by Andrew Hutchings
Put drizzle and mysql processes in seperate classes/files
253
}
254
255
256
void DrizzleDumpFieldDrizzle::setType(const char* raw_type, const char* raw_collation)
257
{
258
  collation= raw_collation;
259
  if (strcmp(raw_type, "BLOB") == 0)
260
  {
261
    if (strcmp(raw_collation, "binary") != 0)
262
      type= "TEXT";
263
    else
264
      type= raw_type;
265
    return;
266
  }
267
268
  if (strcmp(raw_type, "VARCHAR") == 0)
269
  {
270
    if (strcmp(raw_collation, "binary") != 0)
271
      type= "VARCHAR";
272
    else
273
      type= "VARBINARY";
274
    return;
275
  }
276
277
  if (strcmp(raw_type, "INTEGER") == 0)
278
  {
279
    type= "INT";
280
    return;
281
  }
282
283
  type= raw_type;
284
}
285
1751.4.20 by Andrew Hutchings
Add database connection class and the start of a database output ostream
286
DrizzleDumpDataDrizzle::DrizzleDumpDataDrizzle(DrizzleDumpTable *dataTable,
287
  DrizzleDumpConnection *connection)
288
  : DrizzleDumpData(dataTable, connection)
1751.4.19 by Andrew Hutchings
Put drizzle and mysql processes in seperate classes/files
289
{
290
  std::string query;
291
  query= "SELECT * FROM `";
1751.4.25 by Andrew Hutchings
Fix error handling
292
  query.append(table->displayName);
1751.4.19 by Andrew Hutchings
Put drizzle and mysql processes in seperate classes/files
293
  query.append("`");
1751.4.20 by Andrew Hutchings
Add database connection class and the start of a database output ostream
294
295
  result= dcon->query(query);
1751.4.25 by Andrew Hutchings
Fix error handling
296
297
  if (result == NULL)
298
    throw 1;
1751.4.19 by Andrew Hutchings
Put drizzle and mysql processes in seperate classes/files
299
}
300
301
DrizzleDumpDataDrizzle::~DrizzleDumpDataDrizzle()
302
{
1751.4.20 by Andrew Hutchings
Add database connection class and the start of a database output ostream
303
  dcon->freeResult(result);
1751.4.19 by Andrew Hutchings
Put drizzle and mysql processes in seperate classes/files
304
}