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
class SchemaIdentifier;
47
extern std::string drizzle_tmpdir;
48
extern pid_t current_pid;
50
static const char hexchars[]= "0123456789abcdef";
53
Translate a cursor name to a table name (WL #1324).
56
filename_to_tablename()
59
to_length The size of the table name buffer.
64
uint32_t TableIdentifier::filename_to_tablename(const char *from, char *to, uint32_t to_length)
68
if (!memcmp(from, TMP_FILE_PREFIX, TMP_FILE_PREFIX_LENGTH))
70
/* Temporary table name. */
71
length= strlen(strncpy(to, from, to_length));
75
for (; *from && length < to_length; length++, from++)
82
/* We've found an escaped char - skip the @ */
85
/* There will be a two-position hex-char version of the char */
86
for (int x=1; x >= 0; x--)
88
if (*from >= '0' && *from <= '9')
89
to[length] += ((*from++ - '0') << (4 * x));
90
else if (*from >= 'a' && *from <= 'f')
91
to[length] += ((*from++ - 'a' + 10) << (4 * x));
93
/* Backup because we advanced extra in the inner loop */
102
Creates path to a cursor: drizzle_tmpdir/#sql1234_12_1.ext
105
build_tmptable_filename()
106
session The thread handle.
107
buff Where to write result
112
Uses current_pid, thread_id, and tmp_table counter to create
113
a cursor name in drizzle_tmpdir.
116
path length on success, 0 on failure
119
#ifdef _GLIBCXX_HAVE_TLS
120
__thread uint32_t counter= 0;
122
static uint32_t get_counter()
128
boost::mutex counter_mutex;
129
static uint32_t counter= 1;
131
static uint32_t get_counter()
133
boost::mutex::scoped_lock lock(counter_mutex);
142
size_t TableIdentifier::build_tmptable_filename(std::string &buffer)
144
size_t tmpdir_length;
145
ostringstream post_tmpdir_str;
147
buffer.append(drizzle_tmpdir);
148
tmpdir_length= buffer.length();
150
post_tmpdir_str << "/" << TMP_FILE_PREFIX << current_pid;
151
post_tmpdir_str << pthread_self() << "-" << get_counter();
153
buffer.append(post_tmpdir_str.str());
155
transform(buffer.begin() + tmpdir_length, buffer.end(), buffer.begin() + tmpdir_length, ::tolower);
157
return buffer.length();
160
size_t TableIdentifier::build_tmptable_filename(std::vector<char> &buffer)
162
ostringstream post_tmpdir_str;
164
post_tmpdir_str << drizzle_tmpdir << "/" << TMP_FILE_PREFIX << current_pid;
165
post_tmpdir_str << pthread_self() << "-" << get_counter();
167
buffer.resize(post_tmpdir_str.str().length() + 1);
168
memcpy(&buffer[0], post_tmpdir_str.str().c_str(), post_tmpdir_str.str().size());
169
buffer[post_tmpdir_str.str().size()]= 0;
171
return buffer.size();
176
Creates path to a cursor: drizzle_data_dir/db/table.ext
179
build_table_filename()
180
buff Where to write result
181
This may be the same as table_name.
184
table_name Table name
186
flags table_name is temporary, do not change.
190
Uses database and table name, and extension to create
191
a cursor name in drizzle_data_dir. Database and table
192
names are converted from system_charset_info into "fscs".
193
Unless flags indicate a temporary table name.
194
'db' is always converted.
195
'ext' is not converted.
197
The conversion suppression is required for ALTER Table. This
198
statement creates intermediate tables. These are regular
199
(non-temporary) tables with a temporary name. Their path names must
200
be derivable from the table name. So we cannot use
201
build_tmptable_filename() for them.
204
path length on success, 0 on failure
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)
209
bool conversion_error= false;
211
conversion_error= util::tablename_to_filename(in_db, in_path);
212
if (conversion_error)
214
errmsg_printf(ERRMSG_LVL_ERROR,
215
_("Schema name cannot be encoded and fit within filesystem "
216
"name length restrictions."));
220
in_path.append(FN_ROOTDIR);
222
if (is_tmp) // It a conversion tmp
224
in_path.append(in_table_name);
228
conversion_error= util::tablename_to_filename(in_table_name, in_path);
229
if (conversion_error)
231
errmsg_printf(ERRMSG_LVL_ERROR,
232
_("Table name cannot be encoded and fit within filesystem "
233
"name length restrictions."));
238
return in_path.length();
241
TableIdentifier::TableIdentifier(const drizzled::Table &table) :
242
SchemaIdentifier(table.getShare()->getSchemaName()),
243
type(table.getShare()->getTableType()),
244
table_name(table.getShare()->getTableName())
246
if (type == message::Table::TEMPORARY)
247
path= table.getShare()->getPath();
252
void TableIdentifier::init()
255
case message::Table::FUNCTION:
256
case message::Table::STANDARD:
257
assert(path.size() == 0);
258
build_table_filename(path, getSchemaName(), table_name, false);
260
case message::Table::INTERNAL:
261
assert(path.size() == 0);
262
build_table_filename(path, getSchemaName(), table_name, true);
264
case message::Table::TEMPORARY:
267
build_tmptable_filename(path);
272
util::insensitive_hash hasher;
273
hash_value= hasher(path);
275
std::string tb_name(getTableName());
276
std::transform(tb_name.begin(), tb_name.end(), tb_name.begin(), ::tolower);
278
key.set(getKeySize(), getSchemaName(), tb_name);
282
const std::string &TableIdentifier::getPath() const
287
void TableIdentifier::getSQLPath(std::string &sql_path) const // @todo this is just used for errors, we should find a way to optimize it
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);
296
case message::Table::INTERNAL:
297
sql_path.append("temporary.");
298
sql_path.append(table_name);
300
case message::Table::TEMPORARY:
301
sql_path.append(getSchemaName());
302
sql_path.append(".#");
303
sql_path.append(table_name);
308
bool TableIdentifier::isValid() const
310
if (not SchemaIdentifier::isValid())
316
if (table_name.empty())
322
if (table_name.size() > NAME_LEN)
328
if (table_name.at(table_name.length() -1) == ' ')
334
if (table_name.at(0) == '.')
341
const CHARSET_INFO * const cs= &my_charset_utf8mb4_general_ci;
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)
359
my_error(ER_WRONG_TABLE_NAME, MYF(0), name.c_str());
368
void TableIdentifier::copyToTableMessage(message::Table &message) const
370
message.set_name(table_name);
371
message.set_schema(getSchemaName());
374
void TableIdentifier::Key::set(size_t resize_arg, const std::string &a, const std::string &b)
376
key_buffer.resize(resize_arg);
378
std::copy(a.begin(), a.end(), key_buffer.begin());
379
std::copy(b.begin(), b.end(), key_buffer.begin() + a.length() + 1);
381
util::sensitive_hash hasher;
382
hash_value= hasher(key_buffer);
385
std::size_t hash_value(TableIdentifier const& b)
387
return b.getHashValue();
390
std::size_t hash_value(TableIdentifier::Key const& b)
392
return b.getHashValue();
395
} /* namespace drizzled */