1
/* -*- mode: c++; c-basic-offset: 2; indent-tabs-mode: nil; -*-
2
* vim:expandtab:shiftwidth=2:tabstop=2:smarttab:
4
* Copyright (C) 2009 Sun Microsystems
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.
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.
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
24
#include <boost/lexical_cast.hpp>
25
#include "drizzled/identifier.h"
26
#include "drizzled/session.h"
27
#include "drizzled/internal/my_sys.h"
29
#include "drizzled/table.h"
31
#include "drizzled/util/string.h"
32
#include "drizzled/util/tablename_to_filename.h"
38
#include <boost/thread.hpp>
45
extern std::string drizzle_tmpdir;
46
extern pid_t current_pid;
48
static const char hexchars[]= "0123456789abcdef";
51
Translate a cursor name to a table name (WL #1324).
54
filename_to_tablename()
57
to_length The size of the table name buffer.
62
uint32_t TableIdentifier::filename_to_tablename(const char *from, char *to, uint32_t to_length)
66
if (!memcmp(from, TMP_FILE_PREFIX, TMP_FILE_PREFIX_LENGTH))
68
/* Temporary table name. */
69
length= strlen(strncpy(to, from, to_length));
73
for (; *from && length < to_length; length++, from++)
80
/* We've found an escaped char - skip the @ */
83
/* There will be a two-position hex-char version of the char */
84
for (int x=1; x >= 0; x--)
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));
91
/* Backup because we advanced extra in the inner loop */
100
Creates path to a cursor: drizzle_tmpdir/#sql1234_12_1.ext
103
build_tmptable_filename()
104
session The thread handle.
105
buff Where to write result
110
Uses current_pid, thread_id, and tmp_table counter to create
111
a cursor name in drizzle_tmpdir.
114
path length on success, 0 on failure
117
#ifdef _GLIBCXX_HAVE_TLS
118
__thread uint32_t counter= 0;
120
static uint32_t get_counter()
126
boost::mutex counter_mutex;
127
static uint32_t counter= 1;
129
static uint32_t get_counter()
131
boost::mutex::scoped_lock lock(counter_mutex);
140
size_t TableIdentifier::build_tmptable_filename(std::string &buffer)
142
size_t tmpdir_length;
143
ostringstream post_tmpdir_str;
145
buffer.append(drizzle_tmpdir);
146
tmpdir_length= buffer.length();
148
post_tmpdir_str << "/" << TMP_FILE_PREFIX << current_pid;
149
post_tmpdir_str << pthread_self() << "-" << get_counter();
151
buffer.append(post_tmpdir_str.str());
153
transform(buffer.begin() + tmpdir_length, buffer.end(), buffer.begin() + tmpdir_length, ::tolower);
155
return buffer.length();
158
size_t TableIdentifier::build_tmptable_filename(std::vector<char> &buffer)
160
ostringstream post_tmpdir_str;
162
post_tmpdir_str << drizzle_tmpdir << "/" << TMP_FILE_PREFIX << current_pid;
163
post_tmpdir_str << pthread_self() << "-" << get_counter();
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;
169
return buffer.size();
174
Creates path to a cursor: drizzle_data_dir/db/table.ext
177
build_table_filename()
178
buff Where to write result
179
This may be the same as table_name.
182
table_name Table name
184
flags table_name is temporary, do not change.
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.
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.
202
path length on success, 0 on failure
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)
207
bool conversion_error= false;
209
conversion_error= util::tablename_to_filename(in_db, in_path);
210
if (conversion_error)
212
errmsg_printf(ERRMSG_LVL_ERROR,
213
_("Schema name cannot be encoded and fit within filesystem "
214
"name length restrictions."));
218
in_path.append(FN_ROOTDIR);
220
if (is_tmp) // It a conversion tmp
222
in_path.append(in_table_name);
226
conversion_error= util::tablename_to_filename(in_table_name, in_path);
227
if (conversion_error)
229
errmsg_printf(ERRMSG_LVL_ERROR,
230
_("Table name cannot be encoded and fit within filesystem "
231
"name length restrictions."));
236
return in_path.length();
239
TableIdentifier::TableIdentifier(const drizzled::Table &table) :
240
SchemaIdentifier(table.getShare()->getSchemaName()),
241
type(table.getShare()->getTableType()),
242
table_name(table.getShare()->getTableName())
244
if (type == message::Table::TEMPORARY)
245
path= table.getShare()->getPath();
250
void TableIdentifier::init()
253
case message::Table::FUNCTION:
254
case message::Table::STANDARD:
255
assert(path.size() == 0);
256
build_table_filename(path, getSchemaName(), table_name, false);
258
case message::Table::INTERNAL:
259
assert(path.size() == 0);
260
build_table_filename(path, getSchemaName(), table_name, true);
262
case message::Table::TEMPORARY:
265
build_tmptable_filename(path);
270
util::insensitive_hash hasher;
271
hash_value= hasher(path);
273
std::string tb_name(getTableName());
274
std::transform(tb_name.begin(), tb_name.end(), tb_name.begin(), ::tolower);
276
key.set(getKeySize(), getSchemaName(), tb_name);
280
const std::string &TableIdentifier::getPath() const
285
void TableIdentifier::getSQLPath(std::string &sql_path) const // @todo this is just used for errors, we should find a way to optimize it
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);
294
case message::Table::INTERNAL:
295
sql_path.append("temporary.");
296
sql_path.append(table_name);
298
case message::Table::TEMPORARY:
299
sql_path.append(getSchemaName());
300
sql_path.append(".#");
301
sql_path.append(table_name);
307
void TableIdentifier::copyToTableMessage(message::Table &message) const
309
message.set_name(table_name);
310
message.set_schema(getSchemaName());
313
void TableIdentifier::Key::set(size_t resize_arg, const std::string &a, const std::string &b)
315
key_buffer.resize(resize_arg);
317
std::copy(a.begin(), a.end(), key_buffer.begin());
318
std::copy(b.begin(), b.end(), key_buffer.begin() + a.length() + 1);
320
util::sensitive_hash hasher;
321
hash_value= hasher(key_buffer);
324
std::size_t hash_value(TableIdentifier const& b)
326
return b.getHashValue();
329
std::size_t hash_value(TableIdentifier::Key const& b)
331
return b.getHashValue();
334
} /* namespace drizzled */