~drizzle-trunk/drizzle/development

« back to all changes in this revision

Viewing changes to drizzled/identifier/table.cc

  • Committer: Brian Aker
  • Date: 2010-12-08 22:35:56 UTC
  • mfrom: (1819.9.158 update-innobase)
  • Revision ID: brian@tangent.org-20101208223556-37mi4omqg7lkjzf3
Merge in Stewart's changes, 1.3 changes.

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/* -*- mode: c++; c-basic-offset: 2; indent-tabs-mode: nil; -*-
 
2
 *  vim:expandtab:shiftwidth=2:tabstop=2:smarttab:
 
3
 *
 
4
 *  Copyright (C) 2009 Sun Microsystems
 
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
 
 
21
#include "config.h"
 
22
 
 
23
#include <assert.h>
 
24
#include <boost/lexical_cast.hpp>
 
25
#include "drizzled/identifier.h"
 
26
#include "drizzled/session.h"
 
27
#include "drizzled/internal/my_sys.h"
 
28
 
 
29
#include "drizzled/table.h"
 
30
 
 
31
#include "drizzled/util/string.h"
 
32
#include "drizzled/util/tablename_to_filename.h"
 
33
 
 
34
#include <algorithm>
 
35
#include <sstream>
 
36
#include <cstdio>
 
37
 
 
38
#include <boost/thread.hpp>
 
39
 
 
40
using namespace std;
 
41
 
 
42
namespace drizzled
 
43
{
 
44
 
 
45
extern std::string drizzle_tmpdir;
 
46
extern pid_t current_pid;
 
47
 
 
48
static const char hexchars[]= "0123456789abcdef";
 
49
 
 
50
/*
 
51
  Translate a cursor name to a table name (WL #1324).
 
52
 
 
53
  SYNOPSIS
 
54
    filename_to_tablename()
 
55
      from                      The cursor name
 
56
      to                OUT     The table name
 
57
      to_length                 The size of the table name buffer.
 
58
 
 
59
  RETURN
 
60
    Table name length.
 
61
*/
 
62
uint32_t TableIdentifier::filename_to_tablename(const char *from, char *to, uint32_t to_length)
 
63
{
 
64
  uint32_t length= 0;
 
65
 
 
66
  if (!memcmp(from, TMP_FILE_PREFIX, TMP_FILE_PREFIX_LENGTH))
 
67
  {
 
68
    /* Temporary table name. */
 
69
    length= strlen(strncpy(to, from, to_length));
 
70
  }
 
71
  else
 
72
  {
 
73
    for (; *from  && length < to_length; length++, from++)
 
74
    {
 
75
      if (*from != '@')
 
76
      {
 
77
        to[length]= *from;
 
78
        continue;
 
79
      }
 
80
      /* We've found an escaped char - skip the @ */
 
81
      from++;
 
82
      to[length]= 0;
 
83
      /* There will be a two-position hex-char version of the char */
 
84
      for (int x=1; x >= 0; x--)
 
85
      {
 
86
        if (*from >= '0' && *from <= '9')
 
87
          to[length] += ((*from++ - '0') << (4 * x));
 
88
        else if (*from >= 'a' && *from <= 'f')
 
89
          to[length] += ((*from++ - 'a' + 10) << (4 * x));
 
90
      }
 
91
      /* Backup because we advanced extra in the inner loop */
 
92
      from--;
 
93
    } 
 
94
  }
 
95
 
 
96
  return length;
 
97
}
 
98
 
 
99
/*
 
100
  Creates path to a cursor: drizzle_tmpdir/#sql1234_12_1.ext
 
101
 
 
102
  SYNOPSIS
 
103
   build_tmptable_filename()
 
104
     session                    The thread handle.
 
105
     buff                       Where to write result
 
106
     bufflen                    buff size
 
107
 
 
108
  NOTES
 
109
 
 
110
    Uses current_pid, thread_id, and tmp_table counter to create
 
111
    a cursor name in drizzle_tmpdir.
 
112
 
 
113
  RETURN
 
114
    path length on success, 0 on failure
 
115
*/
 
116
 
 
117
#ifdef _GLIBCXX_HAVE_TLS 
 
118
__thread uint32_t counter= 0;
 
119
 
 
120
static uint32_t get_counter()
 
121
{
 
122
  return ++counter;
 
123
}
 
124
 
 
125
#else
 
126
boost::mutex counter_mutex;
 
127
static uint32_t counter= 1;
 
128
 
 
129
static uint32_t get_counter()
 
130
{
 
131
  boost::mutex::scoped_lock lock(counter_mutex);
 
132
  uint32_t x;
 
133
  x= ++counter;
 
134
 
 
135
  return x;
 
136
}
 
137
 
 
138
#endif
 
139
 
 
140
size_t TableIdentifier::build_tmptable_filename(std::string &buffer)
 
141
{
 
142
  size_t tmpdir_length;
 
143
  ostringstream post_tmpdir_str;
 
144
 
 
145
  buffer.append(drizzle_tmpdir);
 
146
  tmpdir_length= buffer.length();
 
147
 
 
148
  post_tmpdir_str << "/" << TMP_FILE_PREFIX << current_pid;
 
149
  post_tmpdir_str << pthread_self() << "-" << get_counter();
 
150
 
 
151
  buffer.append(post_tmpdir_str.str());
 
152
 
 
153
  transform(buffer.begin() + tmpdir_length, buffer.end(), buffer.begin() + tmpdir_length, ::tolower);
 
154
 
 
155
  return buffer.length();
 
156
}
 
157
 
 
158
size_t TableIdentifier::build_tmptable_filename(std::vector<char> &buffer)
 
159
{
 
160
  ostringstream post_tmpdir_str;
 
161
 
 
162
  post_tmpdir_str << drizzle_tmpdir << "/" << TMP_FILE_PREFIX << current_pid;
 
163
  post_tmpdir_str << pthread_self() << "-" << get_counter();
 
164
 
 
165
  buffer.resize(post_tmpdir_str.str().length() + 1);
 
166
  memcpy(&buffer[0], post_tmpdir_str.str().c_str(), post_tmpdir_str.str().size());
 
167
  buffer[post_tmpdir_str.str().size()]= 0;
 
168
 
 
169
  return buffer.size();
 
170
}
 
171
 
 
172
 
 
173
/*
 
174
  Creates path to a cursor: drizzle_data_dir/db/table.ext
 
175
 
 
176
  SYNOPSIS
 
177
   build_table_filename()
 
178
     buff                       Where to write result
 
179
                                This may be the same as table_name.
 
180
     bufflen                    buff size
 
181
     db                         Database name
 
182
     table_name                 Table name
 
183
     ext                        File extension.
 
184
     flags                      table_name is temporary, do not change.
 
185
 
 
186
  NOTES
 
187
 
 
188
    Uses database and table name, and extension to create
 
189
    a cursor name in drizzle_data_dir. Database and table
 
190
    names are converted from system_charset_info into "fscs".
 
191
    Unless flags indicate a temporary table name.
 
192
    'db' is always converted.
 
193
    'ext' is not converted.
 
194
 
 
195
    The conversion suppression is required for ALTER Table. This
 
196
    statement creates intermediate tables. These are regular
 
197
    (non-temporary) tables with a temporary name. Their path names must
 
198
    be derivable from the table name. So we cannot use
 
199
    build_tmptable_filename() for them.
 
200
 
 
201
  RETURN
 
202
    path length on success, 0 on failure
 
203
*/
 
204
 
 
205
size_t TableIdentifier::build_table_filename(std::string &in_path, const std::string &in_db, const std::string &in_table_name, bool is_tmp)
 
206
{
 
207
  bool conversion_error= false;
 
208
 
 
209
  conversion_error= util::tablename_to_filename(in_db, in_path);
 
210
  if (conversion_error)
 
211
  {
 
212
    errmsg_printf(ERRMSG_LVL_ERROR,
 
213
                  _("Schema name cannot be encoded and fit within filesystem "
 
214
                    "name length restrictions."));
 
215
    return 0;
 
216
  }
 
217
 
 
218
  in_path.append(FN_ROOTDIR);
 
219
 
 
220
  if (is_tmp) // It a conversion tmp
 
221
  {
 
222
    in_path.append(in_table_name);
 
223
  }
 
224
  else
 
225
  {
 
226
    conversion_error= util::tablename_to_filename(in_table_name, in_path);
 
227
    if (conversion_error)
 
228
    {
 
229
      errmsg_printf(ERRMSG_LVL_ERROR,
 
230
                    _("Table name cannot be encoded and fit within filesystem "
 
231
                      "name length restrictions."));
 
232
      return 0;
 
233
    }
 
234
  }
 
235
   
 
236
  return in_path.length();
 
237
}
 
238
 
 
239
TableIdentifier::TableIdentifier(const drizzled::Table &table) :
 
240
  SchemaIdentifier(table.getShare()->getSchemaName()),
 
241
  type(table.getShare()->getTableType()),
 
242
  table_name(table.getShare()->getTableName())
 
243
{
 
244
  if (type == message::Table::TEMPORARY)
 
245
    path= table.getShare()->getPath();
 
246
 
 
247
  init();
 
248
}
 
249
 
 
250
void TableIdentifier::init()
 
251
{
 
252
  switch (type) {
 
253
  case message::Table::FUNCTION:
 
254
  case message::Table::STANDARD:
 
255
    assert(path.size() == 0);
 
256
    build_table_filename(path, getSchemaName(), table_name, false);
 
257
    break;
 
258
  case message::Table::INTERNAL:
 
259
    assert(path.size() == 0);
 
260
    build_table_filename(path, getSchemaName(), table_name, true);
 
261
    break;
 
262
  case message::Table::TEMPORARY:
 
263
    if (path.empty())
 
264
    {
 
265
      build_tmptable_filename(path);
 
266
    }
 
267
    break;
 
268
  }
 
269
 
 
270
  util::insensitive_hash hasher;
 
271
  hash_value= hasher(path);
 
272
 
 
273
  std::string tb_name(getTableName());
 
274
  std::transform(tb_name.begin(), tb_name.end(), tb_name.begin(), ::tolower);
 
275
 
 
276
  key.set(getKeySize(), getSchemaName(), tb_name);
 
277
}
 
278
 
 
279
 
 
280
const std::string &TableIdentifier::getPath() const
 
281
{
 
282
  return path;
 
283
}
 
284
 
 
285
void TableIdentifier::getSQLPath(std::string &sql_path) const  // @todo this is just used for errors, we should find a way to optimize it
 
286
{
 
287
  switch (type) {
 
288
  case message::Table::FUNCTION:
 
289
  case message::Table::STANDARD:
 
290
    sql_path.append(getSchemaName());
 
291
    sql_path.append(".");
 
292
    sql_path.append(table_name);
 
293
    break;
 
294
  case message::Table::INTERNAL:
 
295
    sql_path.append("temporary.");
 
296
    sql_path.append(table_name);
 
297
    break;
 
298
  case message::Table::TEMPORARY:
 
299
    sql_path.append(getSchemaName());
 
300
    sql_path.append(".#");
 
301
    sql_path.append(table_name);
 
302
    break;
 
303
  }
 
304
}
 
305
 
 
306
 
 
307
void TableIdentifier::copyToTableMessage(message::Table &message) const
 
308
{
 
309
  message.set_name(table_name);
 
310
  message.set_schema(getSchemaName());
 
311
}
 
312
 
 
313
void TableIdentifier::Key::set(size_t resize_arg, const std::string &a, const std::string &b)
 
314
{
 
315
  key_buffer.resize(resize_arg);
 
316
 
 
317
  std::copy(a.begin(), a.end(), key_buffer.begin());
 
318
  std::copy(b.begin(), b.end(), key_buffer.begin() + a.length() + 1);
 
319
 
 
320
  util::sensitive_hash hasher;
 
321
  hash_value= hasher(key_buffer);
 
322
}
 
323
 
 
324
std::size_t hash_value(TableIdentifier const& b)
 
325
{
 
326
  return b.getHashValue();
 
327
}
 
328
 
 
329
std::size_t hash_value(TableIdentifier::Key const& b)
 
330
{
 
331
  return b.getHashValue();
 
332
}
 
333
 
 
334
} /* namespace drizzled */