~drizzle-trunk/drizzle/development

« back to all changes in this revision

Viewing changes to drizzled/identifier/table.cc

  • Committer: Brian Aker
  • Date: 2010-10-28 17:12:01 UTC
  • mfrom: (1887.1.3 merge)
  • Revision ID: brian@tangent.org-20101028171201-baj6l1bnntn1s4ad
Merge in POTFILES changes.

Show diffs side-by-side

added added

removed removed

Lines of Context:
1
1
/* -*- mode: c++; c-basic-offset: 2; indent-tabs-mode: nil; -*-
2
2
 *  vim:expandtab:shiftwidth=2:tabstop=2:smarttab:
3
3
 *
4
 
 *  Copyright (C) 2009 Sun Microsystems, Inc.
 
4
 *  Copyright (C) 2009 Sun Microsystems
5
5
 *
6
6
 *  This program is free software; you can redistribute it and/or modify
7
7
 *  it under the terms of the GNU General Public License as published by
23
23
#include <assert.h>
24
24
#include <boost/lexical_cast.hpp>
25
25
#include "drizzled/identifier.h"
 
26
#include "drizzled/session.h"
26
27
#include "drizzled/internal/my_sys.h"
27
28
 
28
 
#include <drizzled/error.h>
29
 
#include <drizzled/errmsg_print.h>
30
 
#include <drizzled/gettext.h>
31
 
 
32
 
#include <drizzled/table.h>
 
29
#include "drizzled/table.h"
33
30
 
34
31
#include "drizzled/util/string.h"
35
 
#include "drizzled/util/tablename_to_filename.h"
36
32
 
37
33
#include <algorithm>
38
34
#include <sstream>
45
41
namespace drizzled
46
42
{
47
43
 
48
 
class Table;
49
 
 
50
44
extern std::string drizzle_tmpdir;
51
45
extern pid_t current_pid;
52
46
 
53
 
namespace identifier {
54
 
class Schema;
55
 
 
56
47
static const char hexchars[]= "0123456789abcdef";
57
48
 
 
49
static bool tablename_to_filename(const string &from, string &to);
 
50
 
58
51
/*
59
52
  Translate a cursor name to a table name (WL #1324).
60
53
 
67
60
  RETURN
68
61
    Table name length.
69
62
*/
70
 
uint32_t Table::filename_to_tablename(const char *from, char *to, uint32_t to_length)
 
63
uint32_t TableIdentifier::filename_to_tablename(const char *from, char *to, uint32_t to_length)
71
64
{
72
65
  uint32_t length= 0;
73
66
 
145
138
 
146
139
#endif
147
140
 
148
 
size_t Table::build_tmptable_filename(std::string &buffer)
 
141
size_t TableIdentifier::build_tmptable_filename(std::string &buffer)
149
142
{
150
143
  size_t tmpdir_length;
151
144
  ostringstream post_tmpdir_str;
163
156
  return buffer.length();
164
157
}
165
158
 
166
 
size_t Table::build_tmptable_filename(std::vector<char> &buffer)
 
159
size_t TableIdentifier::build_tmptable_filename(std::vector<char> &buffer)
167
160
{
168
161
  ostringstream post_tmpdir_str;
169
162
 
210
203
    path length on success, 0 on failure
211
204
*/
212
205
 
213
 
size_t Table::build_table_filename(std::string &in_path, const std::string &in_db, const std::string &in_table_name, bool is_tmp)
 
206
size_t TableIdentifier::build_table_filename(std::string &path, const std::string &db, const std::string &table_name, bool is_tmp)
214
207
{
215
208
  bool conversion_error= false;
216
209
 
217
 
  conversion_error= util::tablename_to_filename(in_db, in_path);
 
210
  conversion_error= tablename_to_filename(db, path);
218
211
  if (conversion_error)
219
212
  {
220
 
    errmsg_printf(error::ERROR,
 
213
    errmsg_printf(ERRMSG_LVL_ERROR,
221
214
                  _("Schema name cannot be encoded and fit within filesystem "
222
215
                    "name length restrictions."));
223
216
    return 0;
224
217
  }
225
218
 
226
 
  in_path.append(FN_ROOTDIR);
 
219
  path.append(FN_ROOTDIR);
227
220
 
228
221
  if (is_tmp) // It a conversion tmp
229
222
  {
230
 
    in_path.append(in_table_name);
 
223
    path.append(table_name);
231
224
  }
232
225
  else
233
226
  {
234
 
    conversion_error= util::tablename_to_filename(in_table_name, in_path);
 
227
    conversion_error= tablename_to_filename(table_name, path);
235
228
    if (conversion_error)
236
229
    {
237
 
      errmsg_printf(error::ERROR,
 
230
      errmsg_printf(ERRMSG_LVL_ERROR,
238
231
                    _("Table name cannot be encoded and fit within filesystem "
239
232
                      "name length restrictions."));
240
233
      return 0;
241
234
    }
242
235
  }
243
236
   
244
 
  return in_path.length();
245
 
}
246
 
 
247
 
Table::Table(const drizzled::Table &table) :
248
 
  identifier::Schema(table.getShare()->getSchemaName()),
 
237
  return path.length();
 
238
}
 
239
 
 
240
 
 
241
/*
 
242
  Translate a table name to a cursor name (WL #1324).
 
243
 
 
244
  SYNOPSIS
 
245
    tablename_to_filename()
 
246
      from                      The table name
 
247
      to                OUT     The cursor name
 
248
      to_length                 The size of the cursor name buffer.
 
249
 
 
250
  RETURN
 
251
    true if errors happen. false on success.
 
252
*/
 
253
static bool tablename_to_filename(const string &from, string &to)
 
254
{
 
255
  
 
256
  string::const_iterator iter= from.begin();
 
257
  for (; iter != from.end(); ++iter)
 
258
  {
 
259
    if (isascii(*iter))
 
260
    {
 
261
      if ((isdigit(*iter)) ||
 
262
          (islower(*iter)) ||
 
263
          (*iter == '_') ||
 
264
          (*iter == ' ') ||
 
265
          (*iter == '-'))
 
266
      {
 
267
        to.push_back(*iter);
 
268
        continue;
 
269
      }
 
270
 
 
271
      if (isupper(*iter))
 
272
      {
 
273
        to.push_back(tolower(*iter));
 
274
        continue;
 
275
      }
 
276
    }
 
277
   
 
278
    /* We need to escape this char in a way that can be reversed */
 
279
    to.push_back('@');
 
280
    to.push_back(hexchars[(*iter >> 4) & 15]);
 
281
    to.push_back(hexchars[(*iter) & 15]);
 
282
  }
 
283
 
 
284
  if (internal::check_if_legal_tablename(to.c_str()))
 
285
  {
 
286
    to.append("@@@");
 
287
  }
 
288
  return false;
 
289
}
 
290
 
 
291
TableIdentifier::TableIdentifier(const drizzled::Table &table) :
 
292
  SchemaIdentifier(table.getShare()->getSchemaName()),
249
293
  type(table.getShare()->getTableType()),
250
294
  table_name(table.getShare()->getTableName())
251
295
{
255
299
  init();
256
300
}
257
301
 
258
 
void Table::init()
 
302
void TableIdentifier::init()
259
303
{
260
304
  switch (type) {
261
305
  case message::Table::FUNCTION:
275
319
    break;
276
320
  }
277
321
 
278
 
  switch (type) {
279
 
  case message::Table::FUNCTION:
280
 
  case message::Table::STANDARD:
281
 
  case message::Table::INTERNAL:
282
 
    break;
283
 
  case message::Table::TEMPORARY:
284
 
    {
285
 
      size_t pos;
286
 
 
287
 
      pos= path.find("tmp/#sql");
288
 
      if (pos != std::string::npos) 
289
 
      {
290
 
        key_path= path.substr(pos);
291
 
      }
292
 
    }
293
 
    break;
294
 
  }
295
 
 
296
322
  util::insensitive_hash hasher;
297
323
  hash_value= hasher(path);
298
324
 
299
 
  std::string tb_name(getTableName());
300
 
  std::transform(tb_name.begin(), tb_name.end(), tb_name.begin(), ::tolower);
301
 
 
302
 
  key.set(getKeySize(), getSchemaName(), tb_name);
 
325
  key.set(getKeySize(), getSchemaName(), getTableName());
303
326
}
304
327
 
305
328
 
306
 
const std::string &Table::getPath() const
 
329
const std::string &TableIdentifier::getPath() const
307
330
{
308
331
  return path;
309
332
}
310
333
 
311
 
const std::string &Table::getKeyPath() const
312
 
{
313
 
  if (key_path.empty())
314
 
    return path;
315
 
 
316
 
  return key_path;
317
 
}
318
 
 
319
 
void Table::getSQLPath(std::string &sql_path) const  // @todo this is just used for errors, we should find a way to optimize it
320
 
{
321
 
  switch (type) {
322
 
  case message::Table::FUNCTION:
323
 
  case message::Table::STANDARD:
324
 
    sql_path.append(getSchemaName());
325
 
    sql_path.append(".");
326
 
    sql_path.append(table_name);
327
 
    break;
328
 
  case message::Table::INTERNAL:
329
 
    sql_path.append("temporary.");
330
 
    sql_path.append(table_name);
331
 
    break;
332
 
  case message::Table::TEMPORARY:
333
 
    sql_path.append(getSchemaName());
334
 
    sql_path.append(".#");
335
 
    sql_path.append(table_name);
336
 
    break;
337
 
  }
338
 
}
339
 
 
340
 
bool Table::isValid() const
341
 
{
342
 
  if (not identifier::Schema::isValid())
343
 
    return false;
344
 
 
345
 
  bool error= false;
346
 
  do
347
 
  {
348
 
    if (table_name.empty())
349
 
    {
350
 
      error= true;
351
 
      break;
352
 
    }
353
 
 
354
 
    if (table_name.size() > NAME_LEN)
355
 
    {
356
 
      error= true;
357
 
      break;
358
 
    }
359
 
 
360
 
    if (table_name.at(table_name.length() -1) == ' ')
361
 
    {
362
 
      error= true;
363
 
      break;
364
 
    }
365
 
 
366
 
    if (table_name.at(0) == '.')
367
 
    {
368
 
      error= true;
369
 
      break;
370
 
    }
371
 
 
372
 
    {
373
 
      const CHARSET_INFO * const cs= &my_charset_utf8mb4_general_ci;
374
 
 
375
 
      int well_formed_error;
376
 
      uint32_t res= cs->cset->well_formed_len(cs, table_name.c_str(), table_name.c_str() + table_name.length(),
377
 
                                              NAME_CHAR_LEN, &well_formed_error);
378
 
      if (well_formed_error or table_name.length() != res)
379
 
      {
380
 
        error= true;
381
 
        break;
382
 
      }
383
 
    }
384
 
  } while (0);
385
 
 
386
 
  if (error)
387
 
  {
388
 
    std::string name;
389
 
 
390
 
    getSQLPath(name);
391
 
    my_error(ER_WRONG_TABLE_NAME, MYF(0), name.c_str());
392
 
 
393
 
    return false;
394
 
  }
395
 
 
396
 
  return true;
397
 
}
398
 
 
399
 
 
400
 
void Table::copyToTableMessage(message::Table &message) const
 
334
const std::string &TableIdentifier::getSQLPath()  // @todo this is just used for errors, we should find a way to optimize it
 
335
{
 
336
  if (sql_path.empty())
 
337
  {
 
338
    switch (type) {
 
339
    case message::Table::FUNCTION:
 
340
    case message::Table::STANDARD:
 
341
      sql_path.append(getSchemaName());
 
342
      sql_path.append(".");
 
343
      sql_path.append(table_name);
 
344
      break;
 
345
    case message::Table::INTERNAL:
 
346
      sql_path.append("temporary.");
 
347
      sql_path.append(table_name);
 
348
      break;
 
349
    case message::Table::TEMPORARY:
 
350
      sql_path.append(getSchemaName());
 
351
      sql_path.append(".#");
 
352
      sql_path.append(table_name);
 
353
      break;
 
354
    }
 
355
  }
 
356
 
 
357
  return sql_path;
 
358
}
 
359
 
 
360
 
 
361
void TableIdentifier::copyToTableMessage(message::Table &message) const
401
362
{
402
363
  message.set_name(table_name);
403
364
  message.set_schema(getSchemaName());
404
365
}
405
366
 
406
 
void Table::Key::set(size_t resize_arg, const std::string &a, const std::string &b)
 
367
void TableIdentifier::Key::set(size_t resize_arg, const std::string &a, const std::string &b)
407
368
{
408
369
  key_buffer.resize(resize_arg);
409
370
 
414
375
  hash_value= hasher(key_buffer);
415
376
}
416
377
 
417
 
std::size_t hash_value(Table const& b)
418
 
{
419
 
  return b.getHashValue();
420
 
}
421
 
 
422
 
std::size_t hash_value(Table::Key const& b)
423
 
{
424
 
  return b.getHashValue();
425
 
}
426
 
 
427
 
 
428
 
std::ostream& operator<<(std::ostream& output, Table::const_reference identifier)
429
 
{
430
 
  output << "Table:(";
431
 
  output <<  identifier.getSchemaName();
432
 
  output << ", ";
433
 
  output << identifier.getTableName();
434
 
  output << ", ";
435
 
  output << message::type(identifier.getType());
436
 
  output << ", ";
437
 
  output << identifier.getPath();
438
 
  output << ", ";
439
 
  output << identifier.getHashValue();
440
 
  output << ")";
441
 
 
442
 
  return output;  // for multiple << operators.
443
 
}
444
 
 
445
 
} /* namespace identifier */
 
378
std::size_t hash_value(TableIdentifier const& b)
 
379
{
 
380
  return b.getHashValue();
 
381
}
 
382
 
 
383
std::size_t hash_value(TableIdentifier::Key const& b)
 
384
{
 
385
  return b.getHashValue();
 
386
}
 
387
 
446
388
} /* namespace drizzled */