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
25
#include "drizzled/table_identifier.h"
26
#include "drizzled/session.h"
27
#include "drizzled/current_session.h"
28
#include "drizzled/internal/my_sys.h"
29
#include "drizzled/data_home.h"
31
#include "drizzled/table.h"
42
extern char *drizzle_tmpdir;
43
extern pid_t current_pid;
45
static const char hexchars[]= "0123456789abcdef";
47
static bool tablename_to_filename(const char *from, char *to, size_t to_length);
48
static size_t build_tmptable_filename(std::string &path);
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 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
static size_t build_tmptable_filename(std::string &buffer)
119
size_t tmpdir_length;
120
ostringstream post_tmpdir_str;
122
Session *session= current_session;
124
buffer.append(drizzle_tmpdir);
125
tmpdir_length= buffer.length();
127
post_tmpdir_str << "/" << TMP_FILE_PREFIX << current_pid;
128
post_tmpdir_str << session->thread_id << session->tmp_table++;
130
buffer.append(post_tmpdir_str.str());
132
transform(buffer.begin() + tmpdir_length, buffer.end(), buffer.begin() + tmpdir_length, ::tolower);
134
return buffer.length();
138
Creates path to a cursor: drizzle_data_dir/db/table.ext
141
build_table_filename()
142
buff Where to write result
143
This may be the same as table_name.
146
table_name Table name
148
flags FN_FROM_IS_TMP or FN_TO_IS_TMP
149
table_name is temporary, do not change.
153
Uses database and table name, and extension to create
154
a cursor name in drizzle_data_dir. Database and table
155
names are converted from system_charset_info into "fscs".
156
Unless flags indicate a temporary table name.
157
'db' is always converted.
158
'ext' is not converted.
160
The conversion suppression is required for ALTER Table. This
161
statement creates intermediate tables. These are regular
162
(non-temporary) tables with a temporary name. Their path names must
163
be derivable from the table name. So we cannot use
164
build_tmptable_filename() for them.
167
path length on success, 0 on failure
170
size_t build_table_filename(std::string &path, const char *db, const char *table_name, bool is_tmp)
172
char dbbuff[FN_REFLEN];
173
char tbbuff[FN_REFLEN];
174
bool conversion_error= false;
176
memset(tbbuff, 0, sizeof(tbbuff));
177
if (is_tmp) // FN_FROM_IS_TMP | FN_TO_IS_TMP
179
strncpy(tbbuff, table_name, sizeof(tbbuff));
183
conversion_error= tablename_to_filename(table_name, tbbuff, sizeof(tbbuff));
184
if (conversion_error)
186
errmsg_printf(ERRMSG_LVL_ERROR,
187
_("Table name cannot be encoded and fit within filesystem "
188
"name length restrictions."));
192
memset(dbbuff, 0, sizeof(dbbuff));
193
conversion_error= tablename_to_filename(db, dbbuff, sizeof(dbbuff));
194
if (conversion_error)
196
errmsg_printf(ERRMSG_LVL_ERROR,
197
_("Schema name cannot be encoded and fit within filesystem "
198
"name length restrictions."));
203
int rootdir_len= strlen(FN_ROOTDIR);
204
path.append(drizzle_data_home);
205
ssize_t without_rootdir= path.length() - rootdir_len;
207
/* Don't add FN_ROOTDIR if dirzzle_data_home already includes it */
208
if (without_rootdir >= 0)
210
const char *tmp= path.c_str() + without_rootdir;
212
if (memcmp(tmp, FN_ROOTDIR, rootdir_len) != 0)
213
path.append(FN_ROOTDIR);
217
path.append(FN_ROOTDIR);
220
return path.length();
225
Translate a table name to a cursor name (WL #1324).
228
tablename_to_filename()
230
to OUT The cursor name
231
to_length The size of the cursor name buffer.
234
true if errors happen. false on success.
236
static bool tablename_to_filename(const char *from, char *to, size_t to_length)
240
for (; *from && length < to_length; length++, from++)
242
if ((*from >= '0' && *from <= '9') ||
243
(*from >= 'A' && *from <= 'Z') ||
244
(*from >= 'a' && *from <= 'z') ||
245
/* OSX defines an extra set of high-bit and multi-byte characters
246
that cannot be used on the filesystem. Instead of trying to sort
247
those out, we'll just escape encode all high-bit-set chars on OSX.
248
It won't really hurt anything - it'll just make some filenames ugly. */
249
#if !defined(TARGET_OS_OSX)
250
((unsigned char)*from >= 128) ||
256
to[length]= tolower(*from);
260
if (length + 3 >= to_length)
263
/* We need to escape this char in a way that can be reversed */
265
to[length++]= hexchars[(*from >> 4) & 15];
266
to[length]= hexchars[(*from) & 15];
269
if (internal::check_if_legal_tablename(to) &&
270
length + 4 < to_length)
272
memcpy(to + length, "@@@", 4);
278
TableIdentifier::TableIdentifier(const drizzled::Table &table) :
279
SchemaIdentifier(table.s->getTableProto()->schema()),
280
type(table.s->getTableProto()->type()),
281
table_name(table.s->getTableProto()->name())
283
if (type == message::Table::TEMPORARY)
284
path= table.s->path.str;
289
void TableIdentifier::init()
291
lower_table_name.append(table_name);
292
std::transform(lower_table_name.begin(), lower_table_name.end(),
293
lower_table_name.begin(), ::tolower);
297
const std::string &TableIdentifier::getPath()
299
assert(not lower_table_name.empty());
304
case message::Table::STANDARD:
305
build_table_filename(path, getLower().c_str(), lower_table_name.c_str(), false);
307
case message::Table::INTERNAL:
308
build_table_filename(path, getLower().c_str(), lower_table_name.c_str(), true);
310
case message::Table::TEMPORARY:
311
build_tmptable_filename(path);
313
case message::Table::FUNCTION:
314
path.append(getSchemaName());
316
path.append(table_name);
319
assert(path.length()); // TODO throw exception, this is a possibility
325
bool TableIdentifier::compare(std::string schema_arg, std::string table_arg)
327
std::transform(schema_arg.begin(), schema_arg.end(),
328
schema_arg.begin(), ::tolower);
330
std::transform(table_arg.begin(), table_arg.end(),
331
table_arg.begin(), ::tolower);
333
if (schema_arg == getLower() && table_arg == lower_table_name)
341
const std::string &TableIdentifier::getSQLPath()
343
if (sql_path.empty())
346
case message::Table::FUNCTION:
347
case message::Table::STANDARD:
348
sql_path.append(getLower());
349
sql_path.append(".");
350
sql_path.append(table_name);
352
case message::Table::INTERNAL:
353
sql_path.append("temporary.");
354
sql_path.append(table_name);
356
case message::Table::TEMPORARY:
357
sql_path.append(getLower());
358
sql_path.append(".#");
359
sql_path.append(table_name);
368
void TableIdentifier::copyToTableMessage(message::Table &message)
370
message.set_name(table_name);
371
message.set_schema(getSchemaName());
374
} /* namespace drizzled */