~ubuntu-branches/ubuntu/trusty/drizzle/trusty

« back to all changes in this revision

Viewing changes to drizzled/table_identifier.cc

  • Committer: Bazaar Package Importer
  • Author(s): Monty Taylor
  • Date: 2010-03-18 12:12:31 UTC
  • Revision ID: james.westby@ubuntu.com-20100318121231-k6g1xe6cshbwa0f8
Tags: upstream-2010.03.1347
ImportĀ upstreamĀ versionĀ 2010.03.1347

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
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
 
 
21
#include "config.h"
 
22
 
 
23
#include <assert.h>
 
24
 
 
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>
 
33
 
 
34
using namespace std;
 
35
 
 
36
namespace drizzled
 
37
{
 
38
 
 
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
 
 
280
 
 
281
const char *TableIdentifier::getPath()
 
282
{
 
283
  if (not path_inited)
 
284
  {
 
285
    size_t path_length= 0;
 
286
 
 
287
    switch (type) {
 
288
    case STANDARD_TABLE:
 
289
      path_length= build_table_filename(path, sizeof(path),
 
290
                                        db.c_str(), table_name.c_str(),
 
291
                                        false);
 
292
      break;
 
293
    case INTERNAL_TMP_TABLE:
 
294
      path_length= build_table_filename(path, sizeof(path),
 
295
                                        db.c_str(), table_name.c_str(),
 
296
                                        true);
 
297
      break;
 
298
    case TEMP_TABLE:
 
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
}
 
310
 
 
311
} /* namespace drizzled */