21
21
#include "config.h"
23
23
#include <assert.h>
24
#include <boost/lexical_cast.hpp>
25
25
#include "drizzled/identifier.h"
26
26
#include "drizzled/session.h"
27
27
#include "drizzled/internal/my_sys.h"
28
#include "drizzled/data_home.h"
29
30
#include "drizzled/table.h"
31
#include "drizzled/util/string.h"
32
#include "drizzled/util/tablename_to_filename.h"
34
32
#include <algorithm>
45
class SchemaIdentifier;
47
43
extern std::string drizzle_tmpdir;
48
44
extern pid_t current_pid;
50
46
static const char hexchars[]= "0123456789abcdef";
48
static bool tablename_to_filename(const char *from, char *to, size_t to_length);
53
51
Translate a cursor name to a table name (WL #1324).
204
202
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)
205
size_t TableIdentifier::build_table_filename(std::string &path, const char *db, const char *table_name, bool is_tmp)
207
char dbbuff[FN_REFLEN];
208
char tbbuff[FN_REFLEN];
209
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);
211
memset(tbbuff, 0, sizeof(tbbuff));
222
212
if (is_tmp) // It a conversion tmp
224
in_path.append(in_table_name);
214
strncpy(tbbuff, table_name, sizeof(tbbuff));
228
conversion_error= util::tablename_to_filename(in_table_name, in_path);
218
conversion_error= tablename_to_filename(table_name, tbbuff, sizeof(tbbuff));
229
219
if (conversion_error)
231
221
errmsg_printf(ERRMSG_LVL_ERROR,
238
return in_path.length();
227
memset(dbbuff, 0, sizeof(dbbuff));
228
conversion_error= tablename_to_filename(db, dbbuff, sizeof(dbbuff));
229
if (conversion_error)
231
errmsg_printf(ERRMSG_LVL_ERROR,
232
_("Schema name cannot be encoded and fit within filesystem "
233
"name length restrictions."));
238
int rootdir_len= strlen(FN_ROOTDIR);
239
path.append(data_home);
240
ssize_t without_rootdir= path.length() - rootdir_len;
242
/* Don't add FN_ROOTDIR if dirzzle_data_home already includes it */
243
if (without_rootdir >= 0)
245
const char *tmp= path.c_str() + without_rootdir;
247
if (memcmp(tmp, FN_ROOTDIR, rootdir_len) != 0)
248
path.append(FN_ROOTDIR);
252
path.append(FN_ROOTDIR);
255
return path.length();
260
Translate a table name to a cursor name (WL #1324).
263
tablename_to_filename()
265
to OUT The cursor name
266
to_length The size of the cursor name buffer.
269
true if errors happen. false on success.
271
static bool tablename_to_filename(const char *from, char *to, size_t to_length)
275
for (; *from && length < to_length; length++, from++)
277
if ((*from >= '0' && *from <= '9') ||
278
(*from >= 'A' && *from <= 'Z') ||
279
(*from >= 'a' && *from <= 'z') ||
280
/* OSX defines an extra set of high-bit and multi-byte characters
281
that cannot be used on the filesystem. Instead of trying to sort
282
those out, we'll just escape encode all high-bit-set chars on OSX.
283
It won't really hurt anything - it'll just make some filenames ugly. */
284
#if !defined(TARGET_OS_OSX)
285
((unsigned char)*from >= 128) ||
291
to[length]= tolower(*from);
295
if (length + 3 >= to_length)
298
/* We need to escape this char in a way that can be reversed */
300
to[length++]= hexchars[(*from >> 4) & 15];
301
to[length]= hexchars[(*from) & 15];
304
if (internal::check_if_legal_tablename(to) &&
305
length + 4 < to_length)
307
memcpy(to + length, "@@@", 4);
241
313
TableIdentifier::TableIdentifier(const drizzled::Table &table) :
252
324
void TableIdentifier::init()
326
lower_table_name.append(table_name);
327
std::transform(lower_table_name.begin(), lower_table_name.end(),
328
lower_table_name.begin(), ::tolower);
255
331
case message::Table::FUNCTION:
256
332
case message::Table::STANDARD:
257
333
assert(path.size() == 0);
258
build_table_filename(path, getSchemaName(), table_name, false);
334
build_table_filename(path, getLower().c_str(), lower_table_name.c_str(), false);
260
336
case message::Table::INTERNAL:
261
337
assert(path.size() == 0);
262
build_table_filename(path, getSchemaName(), table_name, true);
338
build_table_filename(path, getLower().c_str(), lower_table_name.c_str(), true);
264
340
case message::Table::TEMPORARY:
265
341
if (path.empty())
272
util::insensitive_hash hasher;
348
boost::hash<std::string> hasher;
273
349
hash_value= hasher(path);
275
std::string tb_name(getTableName());
276
std::transform(tb_name.begin(), tb_name.end(), tb_name.begin(), ::tolower);
351
key.resize(getKeySize());
352
size_t key_length= TableIdentifier::createKey(&key[0], *this);
278
key.set(getKeySize(), getSchemaName(), tb_name);
354
assert(key_length == getKeySize()); // If this is off, then we have a memory issue.
287
void TableIdentifier::getSQLPath(std::string &sql_path) const // @todo this is just used for errors, we should find a way to optimize it
363
bool TableIdentifier::compare(std::string schema_arg, std::string table_arg) const
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);
365
std::transform(schema_arg.begin(), schema_arg.end(),
366
schema_arg.begin(), ::tolower);
368
std::transform(table_arg.begin(), table_arg.end(),
369
table_arg.begin(), ::tolower);
371
if (schema_arg == getLower() && table_arg == lower_table_name)
308
bool TableIdentifier::isValid() const
379
const std::string &TableIdentifier::getSQLPath()
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());
381
if (sql_path.empty())
384
case message::Table::FUNCTION:
385
case message::Table::STANDARD:
386
sql_path.append(getLower());
387
sql_path.append(".");
388
sql_path.append(table_name);
390
case message::Table::INTERNAL:
391
sql_path.append("temporary.");
392
sql_path.append(table_name);
394
case message::Table::TEMPORARY:
395
sql_path.append(getLower());
396
sql_path.append(".#");
397
sql_path.append(table_name);
371
409
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
412
std::size_t hash_value(TableIdentifier const& b)
387
414
return b.getHashValue();
390
std::size_t hash_value(TableIdentifier::Key const& b)
392
return b.getHashValue();
395
417
} /* namespace drizzled */