~drizzle-trunk/drizzle/development

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
1660.1.1 by Brian Aker
Merge in move identifier work.
25
#include "drizzled/identifier.h"
1309.1.24 by Brian Aker
Moved the build table stuff into table_identifier (all to make it simpler to
26
#include "drizzled/session.h"
27
#include "drizzled/internal/my_sys.h"
28
#include "drizzled/data_home.h"
29
1417 by Brian Aker
Interface for Stewart.
30
#include "drizzled/table.h"
31
1669.3.7 by Brian Aker
Use different hash now for identifier.
32
#include "drizzled/util/string.h"
33
1309.1.24 by Brian Aker
Moved the build table stuff into table_identifier (all to make it simpler to
34
#include <algorithm>
35
#include <sstream>
1358.1.5 by Brian Aker
Cleans up use of static buffer in TableIdentifier.
36
#include <cstdio>
1223.4.18 by Brian Aker
More TableIdentifier code.
37
1602 by Brian Aker
Update for current_session removal.
38
#include <boost/thread.hpp>
39
1223.4.18 by Brian Aker
More TableIdentifier code.
40
using namespace std;
1280.1.10 by Monty Taylor
Put everything in drizzled into drizzled namespace.
41
42
namespace drizzled
43
{
1223.4.18 by Brian Aker
More TableIdentifier code.
44
1556.1.1 by Brian Aker
Updates for moving temporary directory.
45
extern std::string drizzle_tmpdir;
1309.1.24 by Brian Aker
Moved the build table stuff into table_identifier (all to make it simpler to
46
extern pid_t current_pid;
47
48
static const char hexchars[]= "0123456789abcdef";
49
1354.1.1 by Brian Aker
Modify ptr to reference.
50
static bool tablename_to_filename(const char *from, char *to, size_t to_length);
51
1309.1.24 by Brian Aker
Moved the build table stuff into table_identifier (all to make it simpler to
52
/*
53
  Translate a cursor name to a table name (WL #1324).
54
55
  SYNOPSIS
56
    filename_to_tablename()
57
      from                      The cursor name
58
      to                OUT     The table name
59
      to_length                 The size of the table name buffer.
60
61
  RETURN
62
    Table name length.
63
*/
1601 by Brian Aker
Move functions to class methods.
64
uint32_t TableIdentifier::filename_to_tablename(const char *from, char *to, uint32_t to_length)
1309.1.24 by Brian Aker
Moved the build table stuff into table_identifier (all to make it simpler to
65
{
66
  uint32_t length= 0;
67
68
  if (!memcmp(from, TMP_FILE_PREFIX, TMP_FILE_PREFIX_LENGTH))
69
  {
70
    /* Temporary table name. */
71
    length= strlen(strncpy(to, from, to_length));
72
  }
73
  else
74
  {
75
    for (; *from  && length < to_length; length++, from++)
76
    {
77
      if (*from != '@')
78
      {
79
        to[length]= *from;
80
        continue;
81
      }
82
      /* We've found an escaped char - skip the @ */
83
      from++;
84
      to[length]= 0;
85
      /* There will be a two-position hex-char version of the char */
86
      for (int x=1; x >= 0; x--)
87
      {
88
        if (*from >= '0' && *from <= '9')
89
          to[length] += ((*from++ - '0') << (4 * x));
90
        else if (*from >= 'a' && *from <= 'f')
91
          to[length] += ((*from++ - 'a' + 10) << (4 * x));
92
      }
93
      /* Backup because we advanced extra in the inner loop */
94
      from--;
95
    } 
96
  }
97
98
  return length;
99
}
100
101
/*
102
  Creates path to a cursor: drizzle_tmpdir/#sql1234_12_1.ext
103
104
  SYNOPSIS
105
   build_tmptable_filename()
106
     session                    The thread handle.
107
     buff                       Where to write result
108
     bufflen                    buff size
109
110
  NOTES
111
112
    Uses current_pid, thread_id, and tmp_table counter to create
113
    a cursor name in drizzle_tmpdir.
114
115
  RETURN
116
    path length on success, 0 on failure
117
*/
118
1602 by Brian Aker
Update for current_session removal.
119
#ifdef _GLIBCXX_HAVE_TLS 
120
__thread uint32_t counter= 0;
121
122
static uint32_t get_counter()
123
{
124
  return ++counter;
125
}
126
127
#else
128
boost::mutex counter_mutex;
129
static uint32_t counter= 1;
130
131
static uint32_t get_counter()
132
{
133
  boost::mutex::scoped_lock lock(counter_mutex);
134
  uint32_t x;
135
  x= ++counter;
136
137
  return x;
138
}
139
140
#endif
141
1618 by Brian Aker
This is a rollup set of patches for modifications to TableIdentifier to have
142
size_t TableIdentifier::build_tmptable_filename(std::string &buffer)
1309.1.24 by Brian Aker
Moved the build table stuff into table_identifier (all to make it simpler to
143
{
1358.1.5 by Brian Aker
Cleans up use of static buffer in TableIdentifier.
144
  size_t tmpdir_length;
145
  ostringstream post_tmpdir_str;
1309.1.24 by Brian Aker
Moved the build table stuff into table_identifier (all to make it simpler to
146
1358.1.5 by Brian Aker
Cleans up use of static buffer in TableIdentifier.
147
  buffer.append(drizzle_tmpdir);
148
  tmpdir_length= buffer.length();
149
1309.1.24 by Brian Aker
Moved the build table stuff into table_identifier (all to make it simpler to
150
  post_tmpdir_str << "/" << TMP_FILE_PREFIX << current_pid;
1608.2.1 by Brian Aker
Modified to table identifier to fix temporary table creation loss of file.
151
  post_tmpdir_str << pthread_self() << "-" << get_counter();
1358.1.5 by Brian Aker
Cleans up use of static buffer in TableIdentifier.
152
153
  buffer.append(post_tmpdir_str.str());
154
155
  transform(buffer.begin() + tmpdir_length, buffer.end(), buffer.begin() + tmpdir_length, ::tolower);
156
157
  return buffer.length();
1309.1.24 by Brian Aker
Moved the build table stuff into table_identifier (all to make it simpler to
158
}
159
1618 by Brian Aker
This is a rollup set of patches for modifications to TableIdentifier to have
160
size_t TableIdentifier::build_tmptable_filename(std::vector<char> &buffer)
161
{
162
  ostringstream post_tmpdir_str;
163
164
  post_tmpdir_str << drizzle_tmpdir << "/" << TMP_FILE_PREFIX << current_pid;
165
  post_tmpdir_str << pthread_self() << "-" << get_counter();
166
167
  buffer.resize(post_tmpdir_str.str().length() + 1);
168
  memcpy(&buffer[0], post_tmpdir_str.str().c_str(), post_tmpdir_str.str().size());
169
  buffer[post_tmpdir_str.str().size()]= 0;
170
171
  return buffer.size();
172
}
173
174
1309.1.24 by Brian Aker
Moved the build table stuff into table_identifier (all to make it simpler to
175
/*
176
  Creates path to a cursor: drizzle_data_dir/db/table.ext
177
178
  SYNOPSIS
179
   build_table_filename()
180
     buff                       Where to write result
181
                                This may be the same as table_name.
182
     bufflen                    buff size
183
     db                         Database name
184
     table_name                 Table name
185
     ext                        File extension.
1481 by Brian Aker
Remove dead code.
186
     flags                      table_name is temporary, do not change.
1309.1.24 by Brian Aker
Moved the build table stuff into table_identifier (all to make it simpler to
187
188
  NOTES
189
190
    Uses database and table name, and extension to create
191
    a cursor name in drizzle_data_dir. Database and table
192
    names are converted from system_charset_info into "fscs".
193
    Unless flags indicate a temporary table name.
194
    'db' is always converted.
195
    'ext' is not converted.
196
197
    The conversion suppression is required for ALTER Table. This
198
    statement creates intermediate tables. These are regular
199
    (non-temporary) tables with a temporary name. Their path names must
200
    be derivable from the table name. So we cannot use
201
    build_tmptable_filename() for them.
202
203
  RETURN
204
    path length on success, 0 on failure
205
*/
206
1601 by Brian Aker
Move functions to class methods.
207
size_t TableIdentifier::build_table_filename(std::string &path, const char *db, const char *table_name, bool is_tmp)
1309.1.24 by Brian Aker
Moved the build table stuff into table_identifier (all to make it simpler to
208
{
209
  char dbbuff[FN_REFLEN];
210
  char tbbuff[FN_REFLEN];
211
  bool conversion_error= false;
212
213
  memset(tbbuff, 0, sizeof(tbbuff));
1481 by Brian Aker
Remove dead code.
214
  if (is_tmp) // It a conversion tmp
1358.1.5 by Brian Aker
Cleans up use of static buffer in TableIdentifier.
215
  {
1309.1.24 by Brian Aker
Moved the build table stuff into table_identifier (all to make it simpler to
216
    strncpy(tbbuff, table_name, sizeof(tbbuff));
1358.1.5 by Brian Aker
Cleans up use of static buffer in TableIdentifier.
217
  }
1309.1.24 by Brian Aker
Moved the build table stuff into table_identifier (all to make it simpler to
218
  else
219
  {
220
    conversion_error= tablename_to_filename(table_name, tbbuff, sizeof(tbbuff));
221
    if (conversion_error)
222
    {
223
      errmsg_printf(ERRMSG_LVL_ERROR,
224
                    _("Table name cannot be encoded and fit within filesystem "
225
                      "name length restrictions."));
226
      return 0;
227
    }
228
  }
229
  memset(dbbuff, 0, sizeof(dbbuff));
230
  conversion_error= tablename_to_filename(db, dbbuff, sizeof(dbbuff));
231
  if (conversion_error)
232
  {
233
    errmsg_printf(ERRMSG_LVL_ERROR,
234
                  _("Schema name cannot be encoded and fit within filesystem "
235
                    "name length restrictions."));
236
    return 0;
237
  }
238
   
239
240
  int rootdir_len= strlen(FN_ROOTDIR);
1300.5.20 by Monty Taylor
Merged trunk.
241
  path.append(data_home);
1358.1.5 by Brian Aker
Cleans up use of static buffer in TableIdentifier.
242
  ssize_t without_rootdir= path.length() - rootdir_len;
1309.1.24 by Brian Aker
Moved the build table stuff into table_identifier (all to make it simpler to
243
244
  /* Don't add FN_ROOTDIR if dirzzle_data_home already includes it */
245
  if (without_rootdir >= 0)
246
  {
1358.1.5 by Brian Aker
Cleans up use of static buffer in TableIdentifier.
247
    const char *tmp= path.c_str() + without_rootdir;
248
1309.1.24 by Brian Aker
Moved the build table stuff into table_identifier (all to make it simpler to
249
    if (memcmp(tmp, FN_ROOTDIR, rootdir_len) != 0)
1358.1.5 by Brian Aker
Cleans up use of static buffer in TableIdentifier.
250
      path.append(FN_ROOTDIR);
1309.1.24 by Brian Aker
Moved the build table stuff into table_identifier (all to make it simpler to
251
  }
252
1358.1.5 by Brian Aker
Cleans up use of static buffer in TableIdentifier.
253
  path.append(dbbuff);
254
  path.append(FN_ROOTDIR);
255
  path.append(tbbuff);
256
257
  return path.length();
1309.1.24 by Brian Aker
Moved the build table stuff into table_identifier (all to make it simpler to
258
}
259
260
261
/*
262
  Translate a table name to a cursor name (WL #1324).
263
264
  SYNOPSIS
265
    tablename_to_filename()
266
      from                      The table name
267
      to                OUT     The cursor name
268
      to_length                 The size of the cursor name buffer.
269
270
  RETURN
271
    true if errors happen. false on success.
272
*/
1354.1.1 by Brian Aker
Modify ptr to reference.
273
static bool tablename_to_filename(const char *from, char *to, size_t to_length)
1309.1.24 by Brian Aker
Moved the build table stuff into table_identifier (all to make it simpler to
274
{
275
  
276
  size_t length= 0;
277
  for (; *from  && length < to_length; length++, from++)
278
  {
279
    if ((*from >= '0' && *from <= '9') ||
280
        (*from >= 'a' && *from <= 'z') ||
281
/* OSX defines an extra set of high-bit and multi-byte characters
282
   that cannot be used on the filesystem. Instead of trying to sort
283
   those out, we'll just escape encode all high-bit-set chars on OSX.
284
   It won't really hurt anything - it'll just make some filenames ugly. */
285
#if !defined(TARGET_OS_OSX)
286
        ((unsigned char)*from >= 128) ||
287
#endif
288
        (*from == '_') ||
289
        (*from == ' ') ||
290
        (*from == '-'))
291
    {
1415 by Brian Aker
Mass overhaul to use schema_identifier.
292
      to[length]= tolower(*from);
1309.1.24 by Brian Aker
Moved the build table stuff into table_identifier (all to make it simpler to
293
      continue;
294
    }
1685.2.12 by Brian Aker
This fixes the lower casing of names from Schema even when we should not.
295
296
    if ((*from >= 'A' && *from <= 'Z'))
297
    {
298
      to[length]= tolower(*from);
299
      continue;
300
    }
1309.1.24 by Brian Aker
Moved the build table stuff into table_identifier (all to make it simpler to
301
   
302
    if (length + 3 >= to_length)
303
      return true;
304
305
    /* We need to escape this char in a way that can be reversed */
306
    to[length++]= '@';
307
    to[length++]= hexchars[(*from >> 4) & 15];
308
    to[length]= hexchars[(*from) & 15];
309
  }
310
311
  if (internal::check_if_legal_tablename(to) &&
312
      length + 4 < to_length)
313
  {
314
    memcpy(to + length, "@@@", 4);
315
    length+= 3;
316
  }
317
  return false;
318
}
319
1417 by Brian Aker
Interface for Stewart.
320
TableIdentifier::TableIdentifier(const drizzled::Table &table) :
1608.2.1 by Brian Aker
Modified to table identifier to fix temporary table creation loss of file.
321
  SchemaIdentifier(table.getShare()->getSchemaName()),
322
  type(table.getShare()->getTableType()),
323
  table_name(table.getShare()->getTableName())
1417 by Brian Aker
Interface for Stewart.
324
{
325
  if (type == message::Table::TEMPORARY)
1574 by Brian Aker
Rollup patch for hiding tableshare.
326
    path= table.getShare()->getPath();
1417 by Brian Aker
Interface for Stewart.
327
328
  init();
329
}
330
1415 by Brian Aker
Mass overhaul to use schema_identifier.
331
void TableIdentifier::init()
1395.1.6 by Brian Aker
Modified TableIdentifier output for errors.
332
{
1608.2.1 by Brian Aker
Modified to table identifier to fix temporary table creation loss of file.
333
  switch (type) {
334
  case message::Table::FUNCTION:
335
  case message::Table::STANDARD:
1626.3.3 by Brian Aker
Additional checks on path.
336
    assert(path.size() == 0);
1685.2.12 by Brian Aker
This fixes the lower casing of names from Schema even when we should not.
337
    build_table_filename(path, getSchemaName().c_str(), table_name.c_str(), false);
1608.2.1 by Brian Aker
Modified to table identifier to fix temporary table creation loss of file.
338
    break;
339
  case message::Table::INTERNAL:
1626.3.3 by Brian Aker
Additional checks on path.
340
    assert(path.size() == 0);
1685.2.12 by Brian Aker
This fixes the lower casing of names from Schema even when we should not.
341
    build_table_filename(path, getSchemaName().c_str(), table_name.c_str(), true);
1608.2.1 by Brian Aker
Modified to table identifier to fix temporary table creation loss of file.
342
    break;
343
  case message::Table::TEMPORARY:
344
    if (path.empty())
345
    {
1358.1.5 by Brian Aker
Cleans up use of static buffer in TableIdentifier.
346
      build_tmptable_filename(path);
1223.4.18 by Brian Aker
More TableIdentifier code.
347
    }
1608.2.1 by Brian Aker
Modified to table identifier to fix temporary table creation loss of file.
348
    break;
1223.4.18 by Brian Aker
More TableIdentifier code.
349
  }
350
1669.3.7 by Brian Aker
Use different hash now for identifier.
351
  util::insensitive_hash hasher;
1608.2.1 by Brian Aker
Modified to table identifier to fix temporary table creation loss of file.
352
  hash_value= hasher(path);
1618 by Brian Aker
This is a rollup set of patches for modifications to TableIdentifier to have
353
354
  key.resize(getKeySize());
355
  size_t key_length= TableIdentifier::createKey(&key[0], *this);
356
357
  assert(key_length == getKeySize()); // If this is off, then we have a memory issue.
1608.2.1 by Brian Aker
Modified to table identifier to fix temporary table creation loss of file.
358
}
359
360
361
const std::string &TableIdentifier::getPath() const
362
{
1358.1.9 by Brian Aker
Update for std::string
363
  return path;
1223.4.18 by Brian Aker
More TableIdentifier code.
364
}
1280.1.10 by Monty Taylor
Put everything in drizzled into drizzled namespace.
365
1685.2.12 by Brian Aker
This fixes the lower casing of names from Schema even when we should not.
366
const std::string &TableIdentifier::getSQLPath()  // @todo this is just used for errors, we should find a way to optimize it
1395.1.6 by Brian Aker
Modified TableIdentifier output for errors.
367
{
368
  if (sql_path.empty())
369
  {
370
    switch (type) {
1395.1.7 by Brian Aker
Removed the internal table type in favor of the protobuf one.
371
    case message::Table::FUNCTION:
372
    case message::Table::STANDARD:
1685.2.12 by Brian Aker
This fixes the lower casing of names from Schema even when we should not.
373
      sql_path.append(getSchemaName());
1395.1.6 by Brian Aker
Modified TableIdentifier output for errors.
374
      sql_path.append(".");
375
      sql_path.append(table_name);
376
      break;
1395.1.7 by Brian Aker
Removed the internal table type in favor of the protobuf one.
377
    case message::Table::INTERNAL:
1395.1.6 by Brian Aker
Modified TableIdentifier output for errors.
378
      sql_path.append("temporary.");
379
      sql_path.append(table_name);
380
      break;
1395.1.7 by Brian Aker
Removed the internal table type in favor of the protobuf one.
381
    case message::Table::TEMPORARY:
1685.2.12 by Brian Aker
This fixes the lower casing of names from Schema even when we should not.
382
      sql_path.append(getSchemaName());
1395.1.6 by Brian Aker
Modified TableIdentifier output for errors.
383
      sql_path.append(".#");
384
      sql_path.append(table_name);
385
      break;
386
    }
387
  }
388
389
  return sql_path;
390
}
391
392
1618.1.1 by Brian Aker
Modify TableIdentifier to be const
393
void TableIdentifier::copyToTableMessage(message::Table &message) const
1395.1.1 by Brian Aker
Fixes for alter table to make sure that the proto on disk is valid.
394
{
395
  message.set_name(table_name);
1415 by Brian Aker
Mass overhaul to use schema_identifier.
396
  message.set_schema(getSchemaName());
1395.1.1 by Brian Aker
Fixes for alter table to make sure that the proto on disk is valid.
397
}
398
1608.2.1 by Brian Aker
Modified to table identifier to fix temporary table creation loss of file.
399
std::size_t hash_value(TableIdentifier const& b)
400
{
401
  return b.getHashValue();
402
}
403
1280.1.10 by Monty Taylor
Put everything in drizzled into drizzled namespace.
404
} /* namespace drizzled */