1223.4.18
by Brian Aker
More TableIdentifier code. |
1 |
/* -*- mode: c++; c-basic-offset: 2; indent-tabs-mode: nil; -*-
|
2 |
* vim:expandtab:shiftwidth=2:tabstop=2:smarttab:
|
|
3 |
*
|
|
4 |
* Copyright (C) 2009 Sun Microsystems
|
|
5 |
*
|
|
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.
|
|
10 |
*
|
|
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.
|
|
15 |
*
|
|
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
|
|
19 |
*/
|
|
20 |
||
1241.9.1
by Monty Taylor
Removed global.h. Fixed all the headers. |
21 |
#include "config.h" |
22 |
||
23 |
#include <assert.h> |
|
24 |
||
1309.1.24
by Brian Aker
Moved the build table stuff into table_identifier (all to make it simpler to |
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" |
|
30 |
||
31 |
#include <algorithm> |
|
32 |
#include <sstream> |
|
1223.4.18
by Brian Aker
More TableIdentifier code. |
33 |
|
34 |
using namespace std; |
|
1280.1.10
by Monty Taylor
Put everything in drizzled into drizzled namespace. |
35 |
|
36 |
namespace drizzled |
|
37 |
{
|
|
1223.4.18
by Brian Aker
More TableIdentifier code. |
38 |
|
1309.1.24
by Brian Aker
Moved the build table stuff into table_identifier (all to make it simpler to |
39 |
extern char *drizzle_tmpdir; |
40 |
extern pid_t current_pid; |
|
41 |
||
42 |
static const char hexchars[]= "0123456789abcdef"; |
|
43 |
||
44 |
/*
|
|
45 |
Translate a cursor name to a table name (WL #1324).
|
|
46 |
||
47 |
SYNOPSIS
|
|
48 |
filename_to_tablename()
|
|
49 |
from The cursor name
|
|
50 |
to OUT The table name
|
|
51 |
to_length The size of the table name buffer.
|
|
52 |
||
53 |
RETURN
|
|
54 |
Table name length.
|
|
55 |
*/
|
|
56 |
uint32_t filename_to_tablename(const char *from, char *to, uint32_t to_length) |
|
57 |
{
|
|
58 |
uint32_t length= 0; |
|
59 |
||
60 |
if (!memcmp(from, TMP_FILE_PREFIX, TMP_FILE_PREFIX_LENGTH)) |
|
61 |
{
|
|
62 |
/* Temporary table name. */
|
|
63 |
length= strlen(strncpy(to, from, to_length)); |
|
64 |
}
|
|
65 |
else
|
|
66 |
{
|
|
67 |
for (; *from && length < to_length; length++, from++) |
|
68 |
{
|
|
69 |
if (*from != '@') |
|
70 |
{
|
|
71 |
to[length]= *from; |
|
72 |
continue; |
|
73 |
}
|
|
74 |
/* We've found an escaped char - skip the @ */
|
|
75 |
from++; |
|
76 |
to[length]= 0; |
|
77 |
/* There will be a two-position hex-char version of the char */
|
|
78 |
for (int x=1; x >= 0; x--) |
|
79 |
{
|
|
80 |
if (*from >= '0' && *from <= '9') |
|
81 |
to[length] += ((*from++ - '0') << (4 * x)); |
|
82 |
else if (*from >= 'a' && *from <= 'f') |
|
83 |
to[length] += ((*from++ - 'a' + 10) << (4 * x)); |
|
84 |
}
|
|
85 |
/* Backup because we advanced extra in the inner loop */
|
|
86 |
from--; |
|
87 |
}
|
|
88 |
}
|
|
89 |
||
90 |
return length; |
|
91 |
}
|
|
92 |
||
93 |
/*
|
|
94 |
Creates path to a cursor: drizzle_tmpdir/#sql1234_12_1.ext
|
|
95 |
||
96 |
SYNOPSIS
|
|
97 |
build_tmptable_filename()
|
|
98 |
session The thread handle.
|
|
99 |
buff Where to write result
|
|
100 |
bufflen buff size
|
|
101 |
||
102 |
NOTES
|
|
103 |
||
104 |
Uses current_pid, thread_id, and tmp_table counter to create
|
|
105 |
a cursor name in drizzle_tmpdir.
|
|
106 |
||
107 |
RETURN
|
|
108 |
path length on success, 0 on failure
|
|
109 |
*/
|
|
110 |
||
111 |
size_t build_tmptable_filename(char *buff, size_t bufflen) |
|
112 |
{
|
|
113 |
size_t length; |
|
114 |
ostringstream path_str, post_tmpdir_str; |
|
115 |
string tmp; |
|
116 |
||
117 |
Session *session= current_session; |
|
118 |
||
119 |
path_str << drizzle_tmpdir; |
|
120 |
post_tmpdir_str << "/" << TMP_FILE_PREFIX << current_pid; |
|
121 |
post_tmpdir_str << session->thread_id << session->tmp_table++; |
|
122 |
tmp= post_tmpdir_str.str(); |
|
123 |
||
124 |
transform(tmp.begin(), tmp.end(), tmp.begin(), ::tolower); |
|
125 |
||
126 |
path_str << tmp; |
|
127 |
||
128 |
if (bufflen < path_str.str().length()) |
|
129 |
length= 0; |
|
130 |
else
|
|
131 |
length= internal::unpack_filename(buff, path_str.str().c_str()); |
|
132 |
||
133 |
return length; |
|
134 |
}
|
|
135 |
||
136 |
/*
|
|
137 |
Creates path to a cursor: drizzle_data_dir/db/table.ext
|
|
138 |
||
139 |
SYNOPSIS
|
|
140 |
build_table_filename()
|
|
141 |
buff Where to write result
|
|
142 |
This may be the same as table_name.
|
|
143 |
bufflen buff size
|
|
144 |
db Database name
|
|
145 |
table_name Table name
|
|
146 |
ext File extension.
|
|
147 |
flags FN_FROM_IS_TMP or FN_TO_IS_TMP
|
|
148 |
table_name is temporary, do not change.
|
|
149 |
||
150 |
NOTES
|
|
151 |
||
152 |
Uses database and table name, and extension to create
|
|
153 |
a cursor name in drizzle_data_dir. Database and table
|
|
154 |
names are converted from system_charset_info into "fscs".
|
|
155 |
Unless flags indicate a temporary table name.
|
|
156 |
'db' is always converted.
|
|
157 |
'ext' is not converted.
|
|
158 |
||
159 |
The conversion suppression is required for ALTER Table. This
|
|
160 |
statement creates intermediate tables. These are regular
|
|
161 |
(non-temporary) tables with a temporary name. Their path names must
|
|
162 |
be derivable from the table name. So we cannot use
|
|
163 |
build_tmptable_filename() for them.
|
|
164 |
||
165 |
RETURN
|
|
166 |
path length on success, 0 on failure
|
|
167 |
*/
|
|
168 |
||
169 |
size_t build_table_filename(char *buff, size_t bufflen, const char *db, const char *table_name, bool is_tmp) |
|
170 |
{
|
|
171 |
char dbbuff[FN_REFLEN]; |
|
172 |
char tbbuff[FN_REFLEN]; |
|
173 |
bool conversion_error= false; |
|
174 |
||
175 |
memset(tbbuff, 0, sizeof(tbbuff)); |
|
176 |
if (is_tmp) // FN_FROM_IS_TMP | FN_TO_IS_TMP |
|
177 |
strncpy(tbbuff, table_name, sizeof(tbbuff)); |
|
178 |
else
|
|
179 |
{
|
|
180 |
conversion_error= tablename_to_filename(table_name, tbbuff, sizeof(tbbuff)); |
|
181 |
if (conversion_error) |
|
182 |
{
|
|
183 |
errmsg_printf(ERRMSG_LVL_ERROR, |
|
184 |
_("Table name cannot be encoded and fit within filesystem " |
|
185 |
"name length restrictions.")); |
|
186 |
return 0; |
|
187 |
}
|
|
188 |
}
|
|
189 |
memset(dbbuff, 0, sizeof(dbbuff)); |
|
190 |
conversion_error= tablename_to_filename(db, dbbuff, sizeof(dbbuff)); |
|
191 |
if (conversion_error) |
|
192 |
{
|
|
193 |
errmsg_printf(ERRMSG_LVL_ERROR, |
|
194 |
_("Schema name cannot be encoded and fit within filesystem " |
|
195 |
"name length restrictions.")); |
|
196 |
return 0; |
|
197 |
}
|
|
198 |
||
199 |
||
200 |
int rootdir_len= strlen(FN_ROOTDIR); |
|
201 |
string table_path(drizzle_data_home); |
|
202 |
int without_rootdir= table_path.length()-rootdir_len; |
|
203 |
||
204 |
/* Don't add FN_ROOTDIR if dirzzle_data_home already includes it */
|
|
205 |
if (without_rootdir >= 0) |
|
206 |
{
|
|
207 |
const char *tmp= table_path.c_str()+without_rootdir; |
|
208 |
if (memcmp(tmp, FN_ROOTDIR, rootdir_len) != 0) |
|
209 |
table_path.append(FN_ROOTDIR); |
|
210 |
}
|
|
211 |
||
212 |
table_path.append(dbbuff); |
|
213 |
table_path.append(FN_ROOTDIR); |
|
214 |
table_path.append(tbbuff); |
|
215 |
||
216 |
if (bufflen < table_path.length()) |
|
217 |
return 0; |
|
218 |
||
219 |
strcpy(buff, table_path.c_str()); |
|
220 |
||
221 |
return table_path.length(); |
|
222 |
}
|
|
223 |
||
224 |
||
225 |
/*
|
|
226 |
Translate a table name to a cursor name (WL #1324).
|
|
227 |
||
228 |
SYNOPSIS
|
|
229 |
tablename_to_filename()
|
|
230 |
from The table name
|
|
231 |
to OUT The cursor name
|
|
232 |
to_length The size of the cursor name buffer.
|
|
233 |
||
234 |
RETURN
|
|
235 |
true if errors happen. false on success.
|
|
236 |
*/
|
|
237 |
bool tablename_to_filename(const char *from, char *to, size_t to_length) |
|
238 |
{
|
|
239 |
||
240 |
size_t length= 0; |
|
241 |
for (; *from && length < to_length; length++, from++) |
|
242 |
{
|
|
243 |
if ((*from >= '0' && *from <= '9') || |
|
244 |
(*from >= 'A' && *from <= 'Z') || |
|
245 |
(*from >= 'a' && *from <= 'z') || |
|
246 |
/* OSX defines an extra set of high-bit and multi-byte characters
|
|
247 |
that cannot be used on the filesystem. Instead of trying to sort
|
|
248 |
those out, we'll just escape encode all high-bit-set chars on OSX.
|
|
249 |
It won't really hurt anything - it'll just make some filenames ugly. */
|
|
250 |
#if !defined(TARGET_OS_OSX)
|
|
251 |
((unsigned char)*from >= 128) || |
|
252 |
#endif
|
|
253 |
(*from == '_') || |
|
254 |
(*from == ' ') || |
|
255 |
(*from == '-')) |
|
256 |
{
|
|
257 |
to[length]= *from; |
|
258 |
continue; |
|
259 |
}
|
|
260 |
||
261 |
if (length + 3 >= to_length) |
|
262 |
return true; |
|
263 |
||
264 |
/* We need to escape this char in a way that can be reversed */
|
|
265 |
to[length++]= '@'; |
|
266 |
to[length++]= hexchars[(*from >> 4) & 15]; |
|
267 |
to[length]= hexchars[(*from) & 15]; |
|
268 |
}
|
|
269 |
||
270 |
if (internal::check_if_legal_tablename(to) && |
|
271 |
length + 4 < to_length) |
|
272 |
{
|
|
273 |
memcpy(to + length, "@@@", 4); |
|
274 |
length+= 3; |
|
275 |
}
|
|
276 |
return false; |
|
277 |
}
|
|
278 |
||
279 |
||
1223.4.18
by Brian Aker
More TableIdentifier code. |
280 |
|
281 |
const char *TableIdentifier::getPath() |
|
282 |
{
|
|
283 |
if (! path_inited) |
|
284 |
{
|
|
285 |
size_t path_length= 0; |
|
286 |
||
287 |
switch (type) { |
|
1309.2.16
by Brian Aker
Small name change (AKA... I hate reading the NO_**@##@$# logic). |
288 |
case STANDARD_TABLE: |
1223.4.18
by Brian Aker
More TableIdentifier code. |
289 |
path_length= build_table_filename(path, sizeof(path), |
290 |
db, table_name, |
|
291 |
false); |
|
292 |
break; |
|
293 |
case INTERNAL_TMP_TABLE: |
|
294 |
path_length= build_table_filename(path, sizeof(path), |
|
295 |
db, table_name, |
|
296 |
true); |
|
297 |
break; |
|
1235.1.3
by Brian Aker
Remove the need for trans/non-trans temp tables for lock conditions. |
298 |
case TEMP_TABLE: |
1223.4.18
by Brian Aker
More TableIdentifier code. |
299 |
path_length= build_tmptable_filename(path, sizeof(path)); |
300 |
break; |
|
301 |
case SYSTEM_TMP_TABLE: |
|
302 |
assert(0); |
|
303 |
}
|
|
304 |
path_inited= true; |
|
305 |
assert(path_length); // TODO throw exception, this is a possibility |
|
306 |
}
|
|
307 |
||
308 |
return path; |
|
309 |
}
|
|
1280.1.10
by Monty Taylor
Put everything in drizzled into drizzled namespace. |
310 |
|
311 |
} /* namespace drizzled */ |