Drizzled Public API Documentation

drizzledump_drizzle.cc
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 
28 extern bool verbose;
29 extern bool ignore_errors;
30 
31 bool DrizzleDumpDatabaseDrizzle::populateTables()
32 {
33  drizzle_result_st *result;
34  drizzle_row_t row;
35  std::string query;
36 
37  if (not dcon->setDB(databaseName))
38  return false;
39 
40  if (verbose)
41  std::cerr << _("-- Retrieving table structures for ") << databaseName << "..." << std::endl;
42 
43  query="SELECT TABLE_NAME, TABLE_COLLATION, ENGINE, AUTO_INCREMENT, TABLE_COMMENT, IS_REPLICATED FROM DATA_DICTIONARY.TABLES WHERE TABLE_SCHEMA='";
44  query.append(databaseName);
45  query.append("' ORDER BY TABLE_NAME");
46 
47  result= dcon->query(query);
48 
49  if (result == NULL)
50  return false;
51 
52  while ((row= drizzle_row_next(result)))
53  {
54  size_t* row_sizes= drizzle_row_field_sizes(result);
55  std::string tableName(row[0]);
56  std::string displayName(tableName);
57  cleanTableName(displayName);
58  if (not ignoreTable(displayName))
59  continue;
60 
61  DrizzleDumpTable *table = new DrizzleDumpTableDrizzle(tableName, dcon);
62  table->displayName= displayName;
63  table->collate= row[1];
64  table->engineName= row[2];
65  table->autoIncrement= boost::lexical_cast<uint64_t>(row[3]);
66  if (row[4])
67  table->comment= DrizzleDumpData::escape(row[4], row_sizes[4]);
68  else
69  table->comment= "";
70 
71  table->replicate= strcmp(row[5], "1") == 0;
72  table->database= this;
73  if ((not table->populateFields()) or (not table->populateIndexes()) or
74  (not table->populateFkeys()))
75  {
76  delete table;
77  if (not ignore_errors)
78  return false;
79  else
80  continue;
81  }
82  tables.push_back(table);
83  }
84 
85  dcon->freeResult(result);
86 
87  return true;
88 }
89 
90 bool DrizzleDumpDatabaseDrizzle::populateTables(const std::vector<std::string> &table_names)
91 {
92  drizzle_result_st *result;
93  drizzle_row_t row;
94  std::string query;
95 
96  if (not dcon->setDB(databaseName))
97  return false;
98 
99  if (verbose)
100  std::cerr << _("-- Retrieving table structures for ") << databaseName << "..." << std::endl;
101  for (std::vector<std::string>::const_iterator it= table_names.begin(); it != table_names.end(); ++it)
102  {
103  std::string tableName= *it;
104  std::string displayName(tableName);
105  cleanTableName(displayName);
106  if (not ignoreTable(displayName))
107  continue;
108 
109  query="SELECT TABLE_NAME, TABLE_COLLATION, ENGINE, IS_REPLICATED FROM DATA_DICTIONARY.TABLES WHERE TABLE_SCHEMA='";
110  query.append(databaseName);
111  query.append("' AND TABLE_NAME = '");
112  query.append(tableName);
113  query.append("'");
114 
115  result= dcon->query(query);
116 
117  if (result == NULL)
118  {
119  std::cerr << "Error: Could not obtain schema for table " << displayName << std::endl;
120  return false;
121  }
122 
123  if ((row= drizzle_row_next(result)))
124  {
125  DrizzleDumpTableDrizzle *table = new DrizzleDumpTableDrizzle(tableName, dcon);
126  table->displayName= displayName;
127  table->collate= row[1];
128  table->engineName= row[2];
129  table->replicate= strcmp(row[3], "1") == 0;
130  table->autoIncrement= 0;
131  table->database= this;
132  if ((not table->populateFields()) or (not table->populateIndexes()))
133  {
134  std::cerr << "Error: Could not get fields and/ot indexes for table " << displayName << std::endl;
135  delete table;
136  dcon->freeResult(result);
137  if (not ignore_errors)
138  return false;
139  else
140  continue;
141  }
142  tables.push_back(table);
143  dcon->freeResult(result);
144  }
145  else
146  {
147  std::cerr << "Error: Table " << displayName << " not found." << std::endl;
148  dcon->freeResult(result);
149  if (not ignore_errors)
150  return false;
151  else
152  continue;
153  }
154  }
155 
156  return true;
157 
158 }
159 
160 void DrizzleDumpDatabaseDrizzle::setCollate(const char* newCollate)
161 {
162  if (newCollate)
163  collate= newCollate;
164  else
165  collate= "utf8_general_ci";
166 }
167 
168 bool DrizzleDumpTableDrizzle::populateFields()
169 {
170  drizzle_result_st *result;
171  drizzle_row_t row;
172  std::string query;
173 
174  if (verbose)
175  std::cerr << _("-- Retrieving fields for ") << tableName << "..." << std::endl;
176 
177  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, COLUMN_COMMENT FROM DATA_DICTIONARY.COLUMNS WHERE TABLE_SCHEMA='";
178  query.append(database->databaseName);
179  query.append("' AND TABLE_NAME='");
180  query.append(tableName);
181  query.append("'");
182 
183  result= dcon->query(query);
184 
185  if (result == NULL)
186  return false;
187 
188  while ((row= drizzle_row_next(result)))
189  {
190  std::string fieldName(row[0]);
191  DrizzleDumpField *field = new DrizzleDumpFieldDrizzle(fieldName, dcon);
192  /* Stop valgrind warning */
193  field->convertDateTime= false;
194  /* Also sets collation */
195  field->setType(row[1], row[8]);
196  if (row[2])
197  field->defaultValue= row[2];
198  else
199  field->defaultValue= "";
200 
201  field->isNull= (boost::lexical_cast<uint32_t>(row[4])) ? true : false;
202  field->isAutoIncrement= (boost::lexical_cast<uint32_t>(row[9])) ? true : false;
203  field->defaultIsNull= (boost::lexical_cast<uint32_t>(row[3])) ? true : false;
204  field->enumValues= (row[10]) ? row[10] : "";
205  field->length= (row[5]) ? boost::lexical_cast<uint32_t>(row[5]) : 0;
206  field->decimalPrecision= (row[6]) ? boost::lexical_cast<uint32_t>(row[6]) : 0;
207  field->decimalScale= (row[7]) ? boost::lexical_cast<uint32_t>(row[7]) : 0;
208  field->comment= (row[11]) ? row[11] : "";
209 
210  fields.push_back(field);
211  }
212 
213  dcon->freeResult(result);
214  return true;
215 }
216 
217 
218 bool DrizzleDumpTableDrizzle::populateIndexes()
219 {
220  drizzle_result_st *result;
221  drizzle_row_t row;
222  std::string query;
223  std::string lastKey;
224  bool firstIndex= true;
225  DrizzleDumpIndex *index;
226 
227  if (verbose)
228  std::cerr << _("-- Retrieving indexes for ") << tableName << "..." << std::endl;
229 
230  query= "SELECT INDEX_NAME, COLUMN_NAME, IS_USED_IN_PRIMARY, IS_UNIQUE, COMPARE_LENGTH FROM DATA_DICTIONARY.INDEX_PARTS WHERE TABLE_SCHEMA='";
231  query.append(database->databaseName);
232  query.append("' AND TABLE_NAME='");
233  query.append(tableName);
234  query.append("'");
235 
236  result= dcon->query(query);
237 
238  if (result == NULL)
239  return false;
240 
241  while ((row= drizzle_row_next(result)))
242  {
243  std::string indexName(row[0]);
244  if (indexName.compare(lastKey) != 0)
245  {
246  if (!firstIndex)
247  indexes.push_back(index);
248  index = new DrizzleDumpIndexDrizzle(indexName, dcon);
249  index->isPrimary= (strcmp(row[0], "PRIMARY") == 0);
250  index->isUnique= boost::lexical_cast<uint32_t>(row[3]);
251  index->isHash= 0;
252  lastKey= row[0];
253  firstIndex= false;
254  }
255  uint32_t length= (row[4]) ? boost::lexical_cast<uint32_t>(row[4]) : 0;
256  index->columns.push_back(std::make_pair(row[1],length));
257  }
258  if (!firstIndex)
259  indexes.push_back(index);
260 
261  dcon->freeResult(result);
262  return true;
263 }
264 
265 bool DrizzleDumpTableDrizzle::populateFkeys()
266 {
267  drizzle_result_st *result;
268  drizzle_row_t row;
269  std::string query;
270  DrizzleDumpForeignKey *fkey;
271 
272  if (verbose)
273  std::cerr << _("-- Retrieving foreign keys for ") << tableName << "..." << std::endl;
274 
275  query= "SELECT CONSTRAINT_NAME, CONSTRAINT_COLUMNS, REFERENCED_TABLE_NAME, REFERENCED_TABLE_COLUMNS, MATCH_OPTION, DELETE_RULE, UPDATE_RULE FROM DATA_DICTIONARY.FOREIGN_KEYS WHERE CONSTRAINT_SCHEMA='";
276  query.append(database->databaseName);
277  query.append("' AND CONSTRAINT_TABLE='");
278  query.append(tableName);
279  query.append("'");
280 
281  result= dcon->query(query);
282 
283  if (result == NULL)
284  return false;
285 
286  while ((row= drizzle_row_next(result)))
287  {
288  fkey= new DrizzleDumpForeignKey(row[0], dcon);
289  fkey->parentColumns= row[1];
290  fkey->childTable= row[2];
291  fkey->childColumns= row[3];
292  fkey->matchOption= (strcmp(row[4], "NONE") != 0) ? row[4] : "";
293  fkey->deleteRule= (strcmp(row[5], "UNDEFINED") != 0) ? row[5] : "";
294  fkey->updateRule= (strcmp(row[6], "UNDEFINED") != 0) ? row[6] : "";
295 
296  fkeys.push_back(fkey);
297  }
298  dcon->freeResult(result);
299  return true;
300 }
301 
302 DrizzleDumpData* DrizzleDumpTableDrizzle::getData(void)
303 {
304  try
305  {
306  return new DrizzleDumpDataDrizzle(this, dcon);
307  }
308  catch(...)
309  {
310  return NULL;
311  }
312 }
313 
314 
315 void DrizzleDumpFieldDrizzle::setType(const char* raw_type, const char* raw_collation)
316 {
317  collation= raw_collation;
318  if (strcmp(raw_type, "BLOB") == 0)
319  {
320  if (strcmp(raw_collation, "binary") != 0)
321  type= "TEXT";
322  else
323  type= raw_type;
324  return;
325  }
326 
327  if (strcmp(raw_type, "VARCHAR") == 0)
328  {
329  if (strcmp(raw_collation, "binary") != 0)
330  type= "VARCHAR";
331  else
332  type= "VARBINARY";
333  return;
334  }
335 
336  if (strcmp(raw_type, "INTEGER") == 0)
337  {
338  type= "INT";
339  return;
340  }
341 
342  type= raw_type;
343 }
344 
345 DrizzleDumpDataDrizzle::DrizzleDumpDataDrizzle(DrizzleDumpTable *dataTable,
346  DrizzleDumpConnection *connection)
347  : DrizzleDumpData(dataTable, connection)
348 {
349  std::string query;
350  query= "SELECT * FROM `";
351  query.append(table->displayName);
352  query.append("`");
353 
354  result= dcon->query(query);
355 
356  if (result == NULL)
357  throw std::exception();
358 }
359 
360 DrizzleDumpDataDrizzle::~DrizzleDumpDataDrizzle()
361 {
362  dcon->freeResult(result);
363 }