~drizzle-trunk/drizzle/development

1223.4.18 by Brian Aker
More TableIdentifier code.
1
/* -*- mode: c++; c-basic-offset: 2; indent-tabs-mode: nil; -*-
2
 *  vim:expandtab:shiftwidth=2:tabstop=2:smarttab:
3
 *
1999.6.1 by kalebral at gmail
update Copyright strings to a more common format to help with creating the master debian copyright file
4
 *  Copyright (C) 2009 Sun Microsystems, Inc.
1223.4.18 by Brian Aker
More TableIdentifier code.
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; either version 2 of the License, or
9
 *  (at your option) any later version.
10
 *
11
 *  This program is distributed in the hope that it will be useful,
12
 *  but WITHOUT ANY WARRANTY; without even the implied warranty of
13
 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14
 *  GNU General Public License for more details.
15
 *
16
 *  You should have received a copy of the GNU General Public License
17
 *  along with this program; if not, write to the Free Software
18
 *  Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
19
 */
20
2173.2.1 by Monty Taylor
Fixes incorrect usage of include
21
#include <config.h>
1241.9.1 by Monty Taylor
Removed global.h. Fixed all the headers.
22
23
#include <assert.h>
1775.5.1 by earney
modified files containing stringstream to use boost:lexical_cast instead as
24
#include <boost/lexical_cast.hpp>
2173.2.1 by Monty Taylor
Fixes incorrect usage of include
25
#include <drizzled/identifier.h>
26
#include <drizzled/internal/my_sys.h>
1309.1.24 by Brian Aker
Moved the build table stuff into table_identifier (all to make it simpler to
27
2087.4.1 by Brian Aker
Merge in schema identifier.
28
#include <drizzled/error.h>
29
#include <drizzled/errmsg_print.h>
30
#include <drizzled/gettext.h>
31
32
#include <drizzled/table.h>
1417 by Brian Aker
Interface for Stewart.
33
2173.2.1 by Monty Taylor
Fixes incorrect usage of include
34
#include <drizzled/util/string.h>
35
#include <drizzled/util/tablename_to_filename.h>
1669.3.7 by Brian Aker
Use different hash now for identifier.
36
1309.1.24 by Brian Aker
Moved the build table stuff into table_identifier (all to make it simpler to
37
#include <algorithm>
38
#include <sstream>
1358.1.5 by Brian Aker
Cleans up use of static buffer in TableIdentifier.
39
#include <cstdio>
1223.4.18 by Brian Aker
More TableIdentifier code.
40
1602 by Brian Aker
Update for current_session removal.
41
#include <boost/thread.hpp>
42
1223.4.18 by Brian Aker
More TableIdentifier code.
43
using namespace std;
1280.1.10 by Monty Taylor
Put everything in drizzled into drizzled namespace.
44
45
namespace drizzled
46
{
1223.4.18 by Brian Aker
More TableIdentifier code.
47
2087.4.1 by Brian Aker
Merge in schema identifier.
48
class Table;
49
2087.4.2 by Brian Aker
Modify TableIdentifier to fit with the rest of the identifiers.
50
extern std::string drizzle_tmpdir;
51
extern pid_t current_pid;
52
2087.4.1 by Brian Aker
Merge in schema identifier.
53
namespace identifier {
54
class Schema;
1309.1.24 by Brian Aker
Moved the build table stuff into table_identifier (all to make it simpler to
55
56
static const char hexchars[]= "0123456789abcdef";
57
58
/*
59
  Translate a cursor name to a table name (WL #1324).
60
61
  SYNOPSIS
62
    filename_to_tablename()
63
      from                      The cursor name
64
      to                OUT     The table name
65
      to_length                 The size of the table name buffer.
66
67
  RETURN
68
    Table name length.
69
*/
2087.4.2 by Brian Aker
Modify TableIdentifier to fit with the rest of the identifiers.
70
uint32_t Table::filename_to_tablename(const char *from, char *to, uint32_t to_length)
1309.1.24 by Brian Aker
Moved the build table stuff into table_identifier (all to make it simpler to
71
{
72
  uint32_t length= 0;
73
74
  if (!memcmp(from, TMP_FILE_PREFIX, TMP_FILE_PREFIX_LENGTH))
75
  {
76
    /* Temporary table name. */
77
    length= strlen(strncpy(to, from, to_length));
78
  }
79
  else
80
  {
81
    for (; *from  && length < to_length; length++, from++)
82
    {
83
      if (*from != '@')
84
      {
85
        to[length]= *from;
86
        continue;
87
      }
88
      /* We've found an escaped char - skip the @ */
89
      from++;
90
      to[length]= 0;
91
      /* There will be a two-position hex-char version of the char */
92
      for (int x=1; x >= 0; x--)
93
      {
94
        if (*from >= '0' && *from <= '9')
95
          to[length] += ((*from++ - '0') << (4 * x));
96
        else if (*from >= 'a' && *from <= 'f')
97
          to[length] += ((*from++ - 'a' + 10) << (4 * x));
98
      }
99
      /* Backup because we advanced extra in the inner loop */
100
      from--;
101
    } 
102
  }
103
104
  return length;
105
}
106
107
/*
108
  Creates path to a cursor: drizzle_tmpdir/#sql1234_12_1.ext
109
110
  SYNOPSIS
111
   build_tmptable_filename()
112
     session                    The thread handle.
113
     buff                       Where to write result
114
     bufflen                    buff size
115
116
  NOTES
117
118
    Uses current_pid, thread_id, and tmp_table counter to create
119
    a cursor name in drizzle_tmpdir.
120
121
  RETURN
122
    path length on success, 0 on failure
123
*/
124
1602 by Brian Aker
Update for current_session removal.
125
#ifdef _GLIBCXX_HAVE_TLS 
126
__thread uint32_t counter= 0;
127
128
static uint32_t get_counter()
129
{
130
  return ++counter;
131
}
132
133
#else
134
boost::mutex counter_mutex;
135
static uint32_t counter= 1;
136
137
static uint32_t get_counter()
138
{
139
  boost::mutex::scoped_lock lock(counter_mutex);
140
  uint32_t x;
141
  x= ++counter;
142
143
  return x;
144
}
145
146
#endif
147
2087.4.2 by Brian Aker
Modify TableIdentifier to fit with the rest of the identifiers.
148
size_t Table::build_tmptable_filename(std::string &buffer)
1309.1.24 by Brian Aker
Moved the build table stuff into table_identifier (all to make it simpler to
149
{
1358.1.5 by Brian Aker
Cleans up use of static buffer in TableIdentifier.
150
  size_t tmpdir_length;
151
  ostringstream post_tmpdir_str;
1309.1.24 by Brian Aker
Moved the build table stuff into table_identifier (all to make it simpler to
152
1358.1.5 by Brian Aker
Cleans up use of static buffer in TableIdentifier.
153
  buffer.append(drizzle_tmpdir);
154
  tmpdir_length= buffer.length();
155
1309.1.24 by Brian Aker
Moved the build table stuff into table_identifier (all to make it simpler to
156
  post_tmpdir_str << "/" << TMP_FILE_PREFIX << current_pid;
1608.2.1 by Brian Aker
Modified to table identifier to fix temporary table creation loss of file.
157
  post_tmpdir_str << pthread_self() << "-" << get_counter();
1358.1.5 by Brian Aker
Cleans up use of static buffer in TableIdentifier.
158
159
  buffer.append(post_tmpdir_str.str());
160
161
  transform(buffer.begin() + tmpdir_length, buffer.end(), buffer.begin() + tmpdir_length, ::tolower);
162
163
  return buffer.length();
1309.1.24 by Brian Aker
Moved the build table stuff into table_identifier (all to make it simpler to
164
}
165
2087.4.2 by Brian Aker
Modify TableIdentifier to fit with the rest of the identifiers.
166
size_t Table::build_tmptable_filename(std::vector<char> &buffer)
1618 by Brian Aker
This is a rollup set of patches for modifications to TableIdentifier to have
167
{
168
  ostringstream post_tmpdir_str;
169
170
  post_tmpdir_str << drizzle_tmpdir << "/" << TMP_FILE_PREFIX << current_pid;
171
  post_tmpdir_str << pthread_self() << "-" << get_counter();
172
173
  buffer.resize(post_tmpdir_str.str().length() + 1);
174
  memcpy(&buffer[0], post_tmpdir_str.str().c_str(), post_tmpdir_str.str().size());
175
  buffer[post_tmpdir_str.str().size()]= 0;
176
177
  return buffer.size();
178
}
179
180
1309.1.24 by Brian Aker
Moved the build table stuff into table_identifier (all to make it simpler to
181
/*
182
  Creates path to a cursor: drizzle_data_dir/db/table.ext
183
184
  SYNOPSIS
185
   build_table_filename()
186
     buff                       Where to write result
187
                                This may be the same as table_name.
188
     bufflen                    buff size
189
     db                         Database name
190
     table_name                 Table name
191
     ext                        File extension.
1481 by Brian Aker
Remove dead code.
192
     flags                      table_name is temporary, do not change.
1309.1.24 by Brian Aker
Moved the build table stuff into table_identifier (all to make it simpler to
193
194
  NOTES
195
196
    Uses database and table name, and extension to create
197
    a cursor name in drizzle_data_dir. Database and table
198
    names are converted from system_charset_info into "fscs".
199
    Unless flags indicate a temporary table name.
200
    'db' is always converted.
201
    'ext' is not converted.
202
203
    The conversion suppression is required for ALTER Table. This
204
    statement creates intermediate tables. These are regular
205
    (non-temporary) tables with a temporary name. Their path names must
206
    be derivable from the table name. So we cannot use
207
    build_tmptable_filename() for them.
208
209
  RETURN
210
    path length on success, 0 on failure
211
*/
212
2087.4.2 by Brian Aker
Modify TableIdentifier to fit with the rest of the identifiers.
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)
1309.1.24 by Brian Aker
Moved the build table stuff into table_identifier (all to make it simpler to
214
{
215
  bool conversion_error= false;
216
1904.1.1 by Brian Aker
Merge in change to have just a single function for both
217
  conversion_error= util::tablename_to_filename(in_db, in_path);
1864.3.9 by Brian Aker
Remove a couple of memset and now just build the table name in the string of
218
  if (conversion_error)
219
  {
2126.3.3 by Brian Aker
Merge in error message rework. Many error messages are fixed in this patch.
220
    errmsg_printf(error::ERROR,
1864.3.9 by Brian Aker
Remove a couple of memset and now just build the table name in the string of
221
                  _("Schema name cannot be encoded and fit within filesystem "
222
                    "name length restrictions."));
223
    return 0;
224
  }
225
1891.2.1 by Monty Taylor
Fixed things to make things compile with clang
226
  in_path.append(FN_ROOTDIR);
1864.3.9 by Brian Aker
Remove a couple of memset and now just build the table name in the string of
227
1481 by Brian Aker
Remove dead code.
228
  if (is_tmp) // It a conversion tmp
1358.1.5 by Brian Aker
Cleans up use of static buffer in TableIdentifier.
229
  {
1891.2.1 by Monty Taylor
Fixed things to make things compile with clang
230
    in_path.append(in_table_name);
1358.1.5 by Brian Aker
Cleans up use of static buffer in TableIdentifier.
231
  }
1309.1.24 by Brian Aker
Moved the build table stuff into table_identifier (all to make it simpler to
232
  else
233
  {
1904.1.1 by Brian Aker
Merge in change to have just a single function for both
234
    conversion_error= util::tablename_to_filename(in_table_name, in_path);
1309.1.24 by Brian Aker
Moved the build table stuff into table_identifier (all to make it simpler to
235
    if (conversion_error)
236
    {
2126.3.3 by Brian Aker
Merge in error message rework. Many error messages are fixed in this patch.
237
      errmsg_printf(error::ERROR,
1309.1.24 by Brian Aker
Moved the build table stuff into table_identifier (all to make it simpler to
238
                    _("Table name cannot be encoded and fit within filesystem "
239
                      "name length restrictions."));
240
      return 0;
241
    }
242
  }
243
   
1891.2.1 by Monty Taylor
Fixed things to make things compile with clang
244
  return in_path.length();
1309.1.24 by Brian Aker
Moved the build table stuff into table_identifier (all to make it simpler to
245
}
246
2087.4.2 by Brian Aker
Modify TableIdentifier to fit with the rest of the identifiers.
247
Table::Table(const drizzled::Table &table) :
2087.4.1 by Brian Aker
Merge in schema identifier.
248
  identifier::Schema(table.getShare()->getSchemaName()),
1608.2.1 by Brian Aker
Modified to table identifier to fix temporary table creation loss of file.
249
  type(table.getShare()->getTableType()),
250
  table_name(table.getShare()->getTableName())
1417 by Brian Aker
Interface for Stewart.
251
{
252
  if (type == message::Table::TEMPORARY)
1574 by Brian Aker
Rollup patch for hiding tableshare.
253
    path= table.getShare()->getPath();
1417 by Brian Aker
Interface for Stewart.
254
255
  init();
256
}
257
2087.4.2 by Brian Aker
Modify TableIdentifier to fit with the rest of the identifiers.
258
void Table::init()
1395.1.6 by Brian Aker
Modified TableIdentifier output for errors.
259
{
1608.2.1 by Brian Aker
Modified to table identifier to fix temporary table creation loss of file.
260
  switch (type) {
261
  case message::Table::FUNCTION:
262
  case message::Table::STANDARD:
1626.3.3 by Brian Aker
Additional checks on path.
263
    assert(path.size() == 0);
1864.3.9 by Brian Aker
Remove a couple of memset and now just build the table name in the string of
264
    build_table_filename(path, getSchemaName(), table_name, false);
1608.2.1 by Brian Aker
Modified to table identifier to fix temporary table creation loss of file.
265
    break;
266
  case message::Table::INTERNAL:
1626.3.3 by Brian Aker
Additional checks on path.
267
    assert(path.size() == 0);
1864.3.9 by Brian Aker
Remove a couple of memset and now just build the table name in the string of
268
    build_table_filename(path, getSchemaName(), table_name, true);
1608.2.1 by Brian Aker
Modified to table identifier to fix temporary table creation loss of file.
269
    break;
270
  case message::Table::TEMPORARY:
271
    if (path.empty())
272
    {
1358.1.5 by Brian Aker
Cleans up use of static buffer in TableIdentifier.
273
      build_tmptable_filename(path);
1223.4.18 by Brian Aker
More TableIdentifier code.
274
    }
1608.2.1 by Brian Aker
Modified to table identifier to fix temporary table creation loss of file.
275
    break;
1223.4.18 by Brian Aker
More TableIdentifier code.
276
  }
277
2139.3.2 by Brian Aker
Fix innodb to just directly use the identifier (this way we only need to
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
1669.3.7 by Brian Aker
Use different hash now for identifier.
296
  util::insensitive_hash hasher;
1608.2.1 by Brian Aker
Modified to table identifier to fix temporary table creation loss of file.
297
  hash_value= hasher(path);
1618 by Brian Aker
This is a rollup set of patches for modifications to TableIdentifier to have
298
1937.4.1 by Andrew Hutchings
Make mixed case table names work again
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);
1608.2.1 by Brian Aker
Modified to table identifier to fix temporary table creation loss of file.
303
}
304
305
2087.4.2 by Brian Aker
Modify TableIdentifier to fit with the rest of the identifiers.
306
const std::string &Table::getPath() const
1608.2.1 by Brian Aker
Modified to table identifier to fix temporary table creation loss of file.
307
{
1358.1.9 by Brian Aker
Update for std::string
308
  return path;
1223.4.18 by Brian Aker
More TableIdentifier code.
309
}
1280.1.10 by Monty Taylor
Put everything in drizzled into drizzled namespace.
310
2139.3.2 by Brian Aker
Fix innodb to just directly use the identifier (this way we only need to
311
const std::string &Table::getKeyPath() const
312
{
313
  if (key_path.empty())
314
    return path;
315
316
  return key_path;
317
}
318
2087.4.2 by Brian Aker
Modify TableIdentifier to fit with the rest of the identifiers.
319
void Table::getSQLPath(std::string &sql_path) const  // @todo this is just used for errors, we should find a way to optimize it
1395.1.6 by Brian Aker
Modified TableIdentifier output for errors.
320
{
1954.2.1 by Brian Aker
getSQLPath() modified to take a string so that we can const the table
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;
1395.1.6 by Brian Aker
Modified TableIdentifier output for errors.
337
  }
338
}
339
2087.4.2 by Brian Aker
Modify TableIdentifier to fit with the rest of the identifiers.
340
bool Table::isValid() const
1992.4.1 by Brian Aker
Update code for testing identifiers/table/schema name correctness.
341
{
2087.4.1 by Brian Aker
Merge in schema identifier.
342
  if (not identifier::Schema::isValid())
1992.4.1 by Brian Aker
Update code for testing identifiers/table/schema name correctness.
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
1395.1.6 by Brian Aker
Modified TableIdentifier output for errors.
399
2087.4.2 by Brian Aker
Modify TableIdentifier to fit with the rest of the identifiers.
400
void Table::copyToTableMessage(message::Table &message) const
1395.1.1 by Brian Aker
Fixes for alter table to make sure that the proto on disk is valid.
401
{
402
  message.set_name(table_name);
1415 by Brian Aker
Mass overhaul to use schema_identifier.
403
  message.set_schema(getSchemaName());
1395.1.1 by Brian Aker
Fixes for alter table to make sure that the proto on disk is valid.
404
}
405
2087.4.2 by Brian Aker
Modify TableIdentifier to fit with the rest of the identifiers.
406
void Table::Key::set(size_t resize_arg, const std::string &a, const std::string &b)
1878.5.3 by Brian Aker
Update Key to work a bit faster.
407
{
408
  key_buffer.resize(resize_arg);
409
410
  std::copy(a.begin(), a.end(), key_buffer.begin());
411
  std::copy(b.begin(), b.end(), key_buffer.begin() + a.length() + 1);
412
413
  util::sensitive_hash hasher;
414
  hash_value= hasher(key_buffer);
415
}
416
2087.4.2 by Brian Aker
Modify TableIdentifier to fit with the rest of the identifiers.
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
2134.1.7 by Brian Aker
Collapse strings used for table.
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
2087.4.2 by Brian Aker
Modify TableIdentifier to fit with the rest of the identifiers.
445
} /* namespace identifier */
1280.1.10 by Monty Taylor
Put everything in drizzled into drizzled namespace.
446
} /* namespace drizzled */