~drizzle-trunk/drizzle/development

« back to all changes in this revision

Viewing changes to drizzled/identifier/table.cc

  • Committer: Brian Aker
  • Date: 2010-07-15 23:18:11 UTC
  • mto: This revision was merged to the branch mainline in revision 1661.
  • Revision ID: brian@gaz-20100715231811-c5erivy1nvwf6bii
Merge in move identifier work.

Show diffs side-by-side

added added

removed removed

Lines of Context:
21
21
#include "config.h"
22
22
 
23
23
#include <assert.h>
24
 
#include <boost/lexical_cast.hpp>
 
24
 
25
25
#include "drizzled/identifier.h"
26
26
#include "drizzled/session.h"
27
27
#include "drizzled/internal/my_sys.h"
 
28
#include "drizzled/data_home.h"
28
29
 
29
30
#include "drizzled/table.h"
30
31
 
31
 
#include "drizzled/util/string.h"
32
 
#include "drizzled/util/tablename_to_filename.h"
33
 
 
34
32
#include <algorithm>
35
33
#include <sstream>
36
34
#include <cstdio>
42
40
namespace drizzled
43
41
{
44
42
 
45
 
class SchemaIdentifier;
46
 
 
47
43
extern std::string drizzle_tmpdir;
48
44
extern pid_t current_pid;
49
45
 
50
46
static const char hexchars[]= "0123456789abcdef";
51
47
 
 
48
static bool tablename_to_filename(const char *from, char *to, size_t to_length);
 
49
 
52
50
/*
53
51
  Translate a cursor name to a table name (WL #1324).
54
52
 
204
202
    path length on success, 0 on failure
205
203
*/
206
204
 
207
 
size_t TableIdentifier::build_table_filename(std::string &in_path, const std::string &in_db, const std::string &in_table_name, bool is_tmp)
 
205
size_t TableIdentifier::build_table_filename(std::string &path, const char *db, const char *table_name, bool is_tmp)
208
206
{
 
207
  char dbbuff[FN_REFLEN];
 
208
  char tbbuff[FN_REFLEN];
209
209
  bool conversion_error= false;
210
210
 
211
 
  conversion_error= util::tablename_to_filename(in_db, in_path);
212
 
  if (conversion_error)
213
 
  {
214
 
    errmsg_printf(ERRMSG_LVL_ERROR,
215
 
                  _("Schema name cannot be encoded and fit within filesystem "
216
 
                    "name length restrictions."));
217
 
    return 0;
218
 
  }
219
 
 
220
 
  in_path.append(FN_ROOTDIR);
221
 
 
 
211
  memset(tbbuff, 0, sizeof(tbbuff));
222
212
  if (is_tmp) // It a conversion tmp
223
213
  {
224
 
    in_path.append(in_table_name);
 
214
    strncpy(tbbuff, table_name, sizeof(tbbuff));
225
215
  }
226
216
  else
227
217
  {
228
 
    conversion_error= util::tablename_to_filename(in_table_name, in_path);
 
218
    conversion_error= tablename_to_filename(table_name, tbbuff, sizeof(tbbuff));
229
219
    if (conversion_error)
230
220
    {
231
221
      errmsg_printf(ERRMSG_LVL_ERROR,
234
224
      return 0;
235
225
    }
236
226
  }
237
 
   
238
 
  return in_path.length();
 
227
  memset(dbbuff, 0, sizeof(dbbuff));
 
228
  conversion_error= tablename_to_filename(db, dbbuff, sizeof(dbbuff));
 
229
  if (conversion_error)
 
230
  {
 
231
    errmsg_printf(ERRMSG_LVL_ERROR,
 
232
                  _("Schema name cannot be encoded and fit within filesystem "
 
233
                    "name length restrictions."));
 
234
    return 0;
 
235
  }
 
236
   
 
237
 
 
238
  int rootdir_len= strlen(FN_ROOTDIR);
 
239
  path.append(data_home);
 
240
  ssize_t without_rootdir= path.length() - rootdir_len;
 
241
 
 
242
  /* Don't add FN_ROOTDIR if dirzzle_data_home already includes it */
 
243
  if (without_rootdir >= 0)
 
244
  {
 
245
    const char *tmp= path.c_str() + without_rootdir;
 
246
 
 
247
    if (memcmp(tmp, FN_ROOTDIR, rootdir_len) != 0)
 
248
      path.append(FN_ROOTDIR);
 
249
  }
 
250
 
 
251
  path.append(dbbuff);
 
252
  path.append(FN_ROOTDIR);
 
253
  path.append(tbbuff);
 
254
 
 
255
  return path.length();
 
256
}
 
257
 
 
258
 
 
259
/*
 
260
  Translate a table name to a cursor name (WL #1324).
 
261
 
 
262
  SYNOPSIS
 
263
    tablename_to_filename()
 
264
      from                      The table name
 
265
      to                OUT     The cursor name
 
266
      to_length                 The size of the cursor name buffer.
 
267
 
 
268
  RETURN
 
269
    true if errors happen. false on success.
 
270
*/
 
271
static bool tablename_to_filename(const char *from, char *to, size_t to_length)
 
272
{
 
273
  
 
274
  size_t length= 0;
 
275
  for (; *from  && length < to_length; length++, from++)
 
276
  {
 
277
    if ((*from >= '0' && *from <= '9') ||
 
278
        (*from >= 'A' && *from <= 'Z') ||
 
279
        (*from >= 'a' && *from <= 'z') ||
 
280
/* OSX defines an extra set of high-bit and multi-byte characters
 
281
   that cannot be used on the filesystem. Instead of trying to sort
 
282
   those out, we'll just escape encode all high-bit-set chars on OSX.
 
283
   It won't really hurt anything - it'll just make some filenames ugly. */
 
284
#if !defined(TARGET_OS_OSX)
 
285
        ((unsigned char)*from >= 128) ||
 
286
#endif
 
287
        (*from == '_') ||
 
288
        (*from == ' ') ||
 
289
        (*from == '-'))
 
290
    {
 
291
      to[length]= tolower(*from);
 
292
      continue;
 
293
    }
 
294
   
 
295
    if (length + 3 >= to_length)
 
296
      return true;
 
297
 
 
298
    /* We need to escape this char in a way that can be reversed */
 
299
    to[length++]= '@';
 
300
    to[length++]= hexchars[(*from >> 4) & 15];
 
301
    to[length]= hexchars[(*from) & 15];
 
302
  }
 
303
 
 
304
  if (internal::check_if_legal_tablename(to) &&
 
305
      length + 4 < to_length)
 
306
  {
 
307
    memcpy(to + length, "@@@", 4);
 
308
    length+= 3;
 
309
  }
 
310
  return false;
239
311
}
240
312
 
241
313
TableIdentifier::TableIdentifier(const drizzled::Table &table) :
251
323
 
252
324
void TableIdentifier::init()
253
325
{
 
326
  lower_table_name.append(table_name);
 
327
  std::transform(lower_table_name.begin(), lower_table_name.end(),
 
328
                 lower_table_name.begin(), ::tolower);
 
329
 
254
330
  switch (type) {
255
331
  case message::Table::FUNCTION:
256
332
  case message::Table::STANDARD:
257
333
    assert(path.size() == 0);
258
 
    build_table_filename(path, getSchemaName(), table_name, false);
 
334
    build_table_filename(path, getLower().c_str(), lower_table_name.c_str(), false);
259
335
    break;
260
336
  case message::Table::INTERNAL:
261
337
    assert(path.size() == 0);
262
 
    build_table_filename(path, getSchemaName(), table_name, true);
 
338
    build_table_filename(path, getLower().c_str(), lower_table_name.c_str(), true);
263
339
    break;
264
340
  case message::Table::TEMPORARY:
265
341
    if (path.empty())
269
345
    break;
270
346
  }
271
347
 
272
 
  util::insensitive_hash hasher;
 
348
  boost::hash<std::string> hasher;
273
349
  hash_value= hasher(path);
274
350
 
275
 
  std::string tb_name(getTableName());
276
 
  std::transform(tb_name.begin(), tb_name.end(), tb_name.begin(), ::tolower);
 
351
  key.resize(getKeySize());
 
352
  size_t key_length= TableIdentifier::createKey(&key[0], *this);
277
353
 
278
 
  key.set(getKeySize(), getSchemaName(), tb_name);
 
354
  assert(key_length == getKeySize()); // If this is off, then we have a memory issue.
279
355
}
280
356
 
281
357
 
284
360
  return path;
285
361
}
286
362
 
287
 
void TableIdentifier::getSQLPath(std::string &sql_path) const  // @todo this is just used for errors, we should find a way to optimize it
 
363
bool TableIdentifier::compare(std::string schema_arg, std::string table_arg) const
288
364
{
289
 
  switch (type) {
290
 
  case message::Table::FUNCTION:
291
 
  case message::Table::STANDARD:
292
 
    sql_path.append(getSchemaName());
293
 
    sql_path.append(".");
294
 
    sql_path.append(table_name);
295
 
    break;
296
 
  case message::Table::INTERNAL:
297
 
    sql_path.append("temporary.");
298
 
    sql_path.append(table_name);
299
 
    break;
300
 
  case message::Table::TEMPORARY:
301
 
    sql_path.append(getSchemaName());
302
 
    sql_path.append(".#");
303
 
    sql_path.append(table_name);
304
 
    break;
 
365
  std::transform(schema_arg.begin(), schema_arg.end(),
 
366
                 schema_arg.begin(), ::tolower);
 
367
 
 
368
  std::transform(table_arg.begin(), table_arg.end(),
 
369
                 table_arg.begin(), ::tolower);
 
370
 
 
371
  if (schema_arg == getLower() && table_arg == lower_table_name)
 
372
  {
 
373
    return true;
305
374
  }
 
375
 
 
376
  return false;
306
377
}
307
378
 
308
 
bool TableIdentifier::isValid() const
 
379
const std::string &TableIdentifier::getSQLPath()
309
380
{
310
 
  if (not SchemaIdentifier::isValid())
311
 
    return false;
312
 
 
313
 
  bool error= false;
314
 
  do
315
 
  {
316
 
    if (table_name.empty())
317
 
    {
318
 
      error= true;
319
 
      break;
320
 
    }
321
 
 
322
 
    if (table_name.size() > NAME_LEN)
323
 
    {
324
 
      error= true;
325
 
      break;
326
 
    }
327
 
 
328
 
    if (table_name.at(table_name.length() -1) == ' ')
329
 
    {
330
 
      error= true;
331
 
      break;
332
 
    }
333
 
 
334
 
    if (table_name.at(0) == '.')
335
 
    {
336
 
      error= true;
337
 
      break;
338
 
    }
339
 
 
340
 
    {
341
 
      const CHARSET_INFO * const cs= &my_charset_utf8mb4_general_ci;
342
 
 
343
 
      int well_formed_error;
344
 
      uint32_t res= cs->cset->well_formed_len(cs, table_name.c_str(), table_name.c_str() + table_name.length(),
345
 
                                              NAME_CHAR_LEN, &well_formed_error);
346
 
      if (well_formed_error or table_name.length() != res)
347
 
      {
348
 
        error= true;
349
 
        break;
350
 
      }
351
 
    }
352
 
  } while (0);
353
 
 
354
 
  if (error)
355
 
  {
356
 
    std::string name;
357
 
 
358
 
    getSQLPath(name);
359
 
    my_error(ER_WRONG_TABLE_NAME, MYF(0), name.c_str());
360
 
 
361
 
    return false;
 
381
  if (sql_path.empty())
 
382
  {
 
383
    switch (type) {
 
384
    case message::Table::FUNCTION:
 
385
    case message::Table::STANDARD:
 
386
      sql_path.append(getLower());
 
387
      sql_path.append(".");
 
388
      sql_path.append(table_name);
 
389
      break;
 
390
    case message::Table::INTERNAL:
 
391
      sql_path.append("temporary.");
 
392
      sql_path.append(table_name);
 
393
      break;
 
394
    case message::Table::TEMPORARY:
 
395
      sql_path.append(getLower());
 
396
      sql_path.append(".#");
 
397
      sql_path.append(table_name);
 
398
      break;
 
399
    }
362
400
  }
363
401
 
364
 
  return true;
 
402
  return sql_path;
365
403
}
366
404
 
367
405
 
371
409
  message.set_schema(getSchemaName());
372
410
}
373
411
 
374
 
void TableIdentifier::Key::set(size_t resize_arg, const std::string &a, const std::string &b)
375
 
{
376
 
  key_buffer.resize(resize_arg);
377
 
 
378
 
  std::copy(a.begin(), a.end(), key_buffer.begin());
379
 
  std::copy(b.begin(), b.end(), key_buffer.begin() + a.length() + 1);
380
 
 
381
 
  util::sensitive_hash hasher;
382
 
  hash_value= hasher(key_buffer);
383
 
}
384
 
 
385
412
std::size_t hash_value(TableIdentifier const& b)
386
413
{
387
414
  return b.getHashValue();
388
415
}
389
416
 
390
 
std::size_t hash_value(TableIdentifier::Key const& b)
391
 
{
392
 
  return b.getHashValue();
393
 
}
394
 
 
395
417
} /* namespace drizzled */