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, Inc.
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/internal/my_sys.h"
28
#include <drizzled/error.h>
29
#include <drizzled/errmsg_print.h>
30
#include <drizzled/gettext.h>
32
#include <drizzled/table.h>
34
#include "drizzled/util/string.h"
35
#include "drizzled/util/tablename_to_filename.h"
41
#include <boost/thread.hpp>
50
extern std::string drizzle_tmpdir;
51
extern pid_t current_pid;
53
namespace identifier {
56
static const char hexchars[]= "0123456789abcdef";
59
Translate a cursor name to a table name (WL #1324).
62
filename_to_tablename()
65
to_length The size of the table name buffer.
70
uint32_t Table::filename_to_tablename(const char *from, char *to, uint32_t to_length)
74
if (!memcmp(from, TMP_FILE_PREFIX, TMP_FILE_PREFIX_LENGTH))
76
/* Temporary table name. */
77
length= strlen(strncpy(to, from, to_length));
81
for (; *from && length < to_length; length++, from++)
88
/* We've found an escaped char - skip the @ */
91
/* There will be a two-position hex-char version of the char */
92
for (int x=1; x >= 0; x--)
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));
99
/* Backup because we advanced extra in the inner loop */
108
Creates path to a cursor: drizzle_tmpdir/#sql1234_12_1.ext
111
build_tmptable_filename()
112
session The thread handle.
113
buff Where to write result
118
Uses current_pid, thread_id, and tmp_table counter to create
119
a cursor name in drizzle_tmpdir.
122
path length on success, 0 on failure
125
#ifdef _GLIBCXX_HAVE_TLS
126
__thread uint32_t counter= 0;
128
static uint32_t get_counter()
134
boost::mutex counter_mutex;
135
static uint32_t counter= 1;
137
static uint32_t get_counter()
139
boost::mutex::scoped_lock lock(counter_mutex);
148
size_t Table::build_tmptable_filename(std::string &buffer)
150
size_t tmpdir_length;
151
ostringstream post_tmpdir_str;
153
buffer.append(drizzle_tmpdir);
154
tmpdir_length= buffer.length();
156
post_tmpdir_str << "/" << TMP_FILE_PREFIX << current_pid;
157
post_tmpdir_str << pthread_self() << "-" << get_counter();
159
buffer.append(post_tmpdir_str.str());
161
transform(buffer.begin() + tmpdir_length, buffer.end(), buffer.begin() + tmpdir_length, ::tolower);
163
return buffer.length();
166
size_t Table::build_tmptable_filename(std::vector<char> &buffer)
168
ostringstream post_tmpdir_str;
170
post_tmpdir_str << drizzle_tmpdir << "/" << TMP_FILE_PREFIX << current_pid;
171
post_tmpdir_str << pthread_self() << "-" << get_counter();
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;
177
return buffer.size();
182
Creates path to a cursor: drizzle_data_dir/db/table.ext
185
build_table_filename()
186
buff Where to write result
187
This may be the same as table_name.
190
table_name Table name
192
flags table_name is temporary, do not change.
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.
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.
210
path length on success, 0 on failure
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)
215
bool conversion_error= false;
217
conversion_error= util::tablename_to_filename(in_db, in_path);
218
if (conversion_error)
220
errmsg_printf(error::ERROR,
221
_("Schema name cannot be encoded and fit within filesystem "
222
"name length restrictions."));
226
in_path.append(FN_ROOTDIR);
228
if (is_tmp) // It a conversion tmp
230
in_path.append(in_table_name);
234
conversion_error= util::tablename_to_filename(in_table_name, in_path);
235
if (conversion_error)
237
errmsg_printf(error::ERROR,
238
_("Table name cannot be encoded and fit within filesystem "
239
"name length restrictions."));
244
return in_path.length();
247
Table::Table(const drizzled::Table &table) :
248
identifier::Schema(table.getShare()->getSchemaName()),
249
type(table.getShare()->getTableType()),
250
table_name(table.getShare()->getTableName())
252
if (type == message::Table::TEMPORARY)
253
path= table.getShare()->getPath();
261
case message::Table::FUNCTION:
262
case message::Table::STANDARD:
263
assert(path.size() == 0);
264
build_table_filename(path, getSchemaName(), table_name, false);
266
case message::Table::INTERNAL:
267
assert(path.size() == 0);
268
build_table_filename(path, getSchemaName(), table_name, true);
270
case message::Table::TEMPORARY:
273
build_tmptable_filename(path);
279
case message::Table::FUNCTION:
280
case message::Table::STANDARD:
281
case message::Table::INTERNAL:
283
case message::Table::TEMPORARY:
287
pos= path.find("tmp/#sql");
288
if (pos != std::string::npos)
290
key_path= path.substr(pos);
296
util::insensitive_hash hasher;
297
hash_value= hasher(path);
299
std::string tb_name(getTableName());
300
std::transform(tb_name.begin(), tb_name.end(), tb_name.begin(), ::tolower);
302
key.set(getKeySize(), getSchemaName(), tb_name);
306
const std::string &Table::getPath() const
311
const std::string &Table::getKeyPath() const
313
if (key_path.empty())
319
void Table::getSQLPath(std::string &sql_path) const // @todo this is just used for errors, we should find a way to optimize it
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);
328
case message::Table::INTERNAL:
329
sql_path.append("temporary.");
330
sql_path.append(table_name);
332
case message::Table::TEMPORARY:
333
sql_path.append(getSchemaName());
334
sql_path.append(".#");
335
sql_path.append(table_name);
340
bool Table::isValid() const
342
if (not identifier::Schema::isValid())
348
if (table_name.empty())
354
if (table_name.size() > NAME_LEN)
360
if (table_name.at(table_name.length() -1) == ' ')
366
if (table_name.at(0) == '.')
373
const CHARSET_INFO * const cs= &my_charset_utf8mb4_general_ci;
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)
391
my_error(ER_WRONG_TABLE_NAME, MYF(0), name.c_str());
400
void Table::copyToTableMessage(message::Table &message) const
402
message.set_name(table_name);
403
message.set_schema(getSchemaName());
406
void Table::Key::set(size_t resize_arg, const std::string &a, const std::string &b)
408
key_buffer.resize(resize_arg);
410
std::copy(a.begin(), a.end(), key_buffer.begin());
411
std::copy(b.begin(), b.end(), key_buffer.begin() + a.length() + 1);
413
util::sensitive_hash hasher;
414
hash_value= hasher(key_buffer);
417
std::size_t hash_value(Table const& b)
419
return b.getHashValue();
422
std::size_t hash_value(Table::Key const& b)
424
return b.getHashValue();
428
std::ostream& operator<<(std::ostream& output, Table::const_reference identifier)
431
output << identifier.getSchemaName();
433
output << identifier.getTableName();
435
output << message::type(identifier.getType());
437
output << identifier.getPath();
439
output << identifier.getHashValue();
442
return output; // for multiple << operators.
445
} /* namespace identifier */
446
} /* namespace drizzled */