210
165
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)
168
size_t build_table_filename(std::string &path, const char *db, const char *table_name, bool is_tmp)
170
char dbbuff[FN_REFLEN];
171
char tbbuff[FN_REFLEN];
215
172
bool conversion_error= false;
217
conversion_error= util::tablename_to_filename(in_db, in_path);
174
memset(tbbuff, 0, sizeof(tbbuff));
175
if (is_tmp) // FN_FROM_IS_TMP | FN_TO_IS_TMP
177
strncpy(tbbuff, table_name, sizeof(tbbuff));
181
conversion_error= tablename_to_filename(table_name, tbbuff, sizeof(tbbuff));
182
if (conversion_error)
184
errmsg_printf(ERRMSG_LVL_ERROR,
185
_("Table name cannot be encoded and fit within filesystem "
186
"name length restrictions."));
190
memset(dbbuff, 0, sizeof(dbbuff));
191
conversion_error= tablename_to_filename(db, dbbuff, sizeof(dbbuff));
218
192
if (conversion_error)
220
errmsg_printf(error::ERROR,
194
errmsg_printf(ERRMSG_LVL_ERROR,
221
195
_("Schema name cannot be encoded and fit within filesystem "
222
196
"name length restrictions."));
226
in_path.append(FN_ROOTDIR);
228
if (is_tmp) // It a conversion tmp
201
int rootdir_len= strlen(FN_ROOTDIR);
202
path.append(drizzle_data_home);
203
ssize_t without_rootdir= path.length() - rootdir_len;
205
/* Don't add FN_ROOTDIR if dirzzle_data_home already includes it */
206
if (without_rootdir >= 0)
230
in_path.append(in_table_name);
208
const char *tmp= path.c_str() + without_rootdir;
210
if (memcmp(tmp, FN_ROOTDIR, rootdir_len) != 0)
211
path.append(FN_ROOTDIR);
215
path.append(FN_ROOTDIR);
218
return path.length();
223
Translate a table name to a cursor name (WL #1324).
226
tablename_to_filename()
228
to OUT The cursor name
229
to_length The size of the cursor name buffer.
232
true if errors happen. false on success.
234
static bool tablename_to_filename(const char *from, char *to, size_t to_length)
238
for (; *from && length < to_length; length++, from++)
234
conversion_error= util::tablename_to_filename(in_table_name, in_path);
235
if (conversion_error)
240
if ((*from >= '0' && *from <= '9') ||
241
(*from >= 'A' && *from <= 'Z') ||
242
(*from >= 'a' && *from <= 'z') ||
243
/* OSX defines an extra set of high-bit and multi-byte characters
244
that cannot be used on the filesystem. Instead of trying to sort
245
those out, we'll just escape encode all high-bit-set chars on OSX.
246
It won't really hurt anything - it'll just make some filenames ugly. */
247
#if !defined(TARGET_OS_OSX)
248
((unsigned char)*from >= 128) ||
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:
258
if (length + 3 >= to_length)
261
/* We need to escape this char in a way that can be reversed */
263
to[length++]= hexchars[(*from >> 4) & 15];
264
to[length]= hexchars[(*from) & 15];
267
if (internal::check_if_legal_tablename(to) &&
268
length + 4 < to_length)
270
memcpy(to + length, "@@@", 4);
276
void TableIdentifier::primeLower()
278
if (lower_db.empty())
281
lower_table_name.append(table_name);
283
std::transform(lower_table_name.begin(), lower_table_name.end(),
284
lower_table_name.begin(), ::tolower);
286
std::transform(lower_db.begin(), lower_db.end(),
287
lower_db.begin(), ::tolower);
292
const std::string &TableIdentifier::getPath()
298
case message::Table::STANDARD:
299
build_table_filename(path, lower_db.c_str(), lower_table_name.c_str(), false);
301
case message::Table::INTERNAL:
302
build_table_filename(path, lower_db.c_str(), lower_table_name.c_str(), true);
304
case message::Table::TEMPORARY:
273
305
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
307
case message::Table::FUNCTION:
310
path.append(table_name);
313
assert(path.length()); // TODO throw exception, this is a possibility
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
320
const std::string &TableIdentifier::getSQLPath()
322
if (sql_path.empty())
325
case message::Table::FUNCTION:
326
case message::Table::STANDARD:
328
sql_path.append(".");
329
sql_path.append(table_name);
331
case message::Table::INTERNAL:
332
sql_path.append("temporary.");
333
sql_path.append(table_name);
335
case message::Table::TEMPORARY:
337
sql_path.append(".#");
338
sql_path.append(table_name);
347
void TableIdentifier::copyToTableMessage(message::Table &message)
402
349
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 */
350
message.set_schema(db);
446
353
} /* namespace drizzled */