~drizzle-trunk/drizzle/development

« back to all changes in this revision

Viewing changes to drizzled/sql_table.cc

  • Committer: Brian Aker
  • Date: 2010-03-02 07:03:12 UTC
  • mfrom: (1309.2.10 drizzle-build)
  • Revision ID: brian@gaz-20100302070312-u8xyk09u2970pgzp
Merge.

Show diffs side-by-side

added added

removed removed

Lines of Context:
56
56
 
57
57
extern pid_t current_pid;
58
58
 
59
 
static const char hexchars[]= "0123456789abcdef";
60
59
bool is_primary_key(KEY *key_info)
61
60
{
62
61
  static const char * primary_key_name="PRIMARY";
89
88
}
90
89
 
91
90
/*
92
 
  Translate a cursor name to a table name (WL #1324).
93
 
 
94
 
  SYNOPSIS
95
 
    filename_to_tablename()
96
 
      from                      The cursor name
97
 
      to                OUT     The table name
98
 
      to_length                 The size of the table name buffer.
99
 
 
100
 
  RETURN
101
 
    Table name length.
102
 
*/
103
 
uint32_t filename_to_tablename(const char *from, char *to, uint32_t to_length)
104
 
{
105
 
  uint32_t length= 0;
106
 
 
107
 
  if (!memcmp(from, TMP_FILE_PREFIX, TMP_FILE_PREFIX_LENGTH))
108
 
  {
109
 
    /* Temporary table name. */
110
 
    length= strlen(strncpy(to, from, to_length));
111
 
  }
112
 
  else
113
 
  {
114
 
    for (; *from  && length < to_length; length++, from++)
115
 
    {
116
 
      if (*from != '@')
117
 
      {
118
 
        to[length]= *from;
119
 
        continue;
120
 
      }
121
 
      /* We've found an escaped char - skip the @ */
122
 
      from++;
123
 
      to[length]= 0;
124
 
      /* There will be a two-position hex-char version of the char */
125
 
      for (int x=1; x >= 0; x--)
126
 
      {
127
 
        if (*from >= '0' && *from <= '9')
128
 
          to[length] += ((*from++ - '0') << (4 * x));
129
 
        else if (*from >= 'a' && *from <= 'f')
130
 
          to[length] += ((*from++ - 'a' + 10) << (4 * x));
131
 
      }
132
 
      /* Backup because we advanced extra in the inner loop */
133
 
      from--;
134
 
    } 
135
 
  }
136
 
 
137
 
  return length;
138
 
}
139
 
 
140
 
 
141
 
/*
142
 
  Translate a table name to a cursor name (WL #1324).
143
 
 
144
 
  SYNOPSIS
145
 
    tablename_to_filename()
146
 
      from                      The table name
147
 
      to                OUT     The cursor name
148
 
      to_length                 The size of the cursor name buffer.
149
 
 
150
 
  RETURN
151
 
    true if errors happen. false on success.
152
 
*/
153
 
bool tablename_to_filename(const char *from, char *to, size_t to_length)
154
 
{
155
 
  
156
 
  size_t length= 0;
157
 
  for (; *from  && length < to_length; length++, from++)
158
 
  {
159
 
    if ((*from >= '0' && *from <= '9') ||
160
 
        (*from >= 'A' && *from <= 'Z') ||
161
 
        (*from >= 'a' && *from <= 'z') ||
162
 
/* OSX defines an extra set of high-bit and multi-byte characters
163
 
   that cannot be used on the filesystem. Instead of trying to sort
164
 
   those out, we'll just escape encode all high-bit-set chars on OSX.
165
 
   It won't really hurt anything - it'll just make some filenames ugly. */
166
 
#if !defined(TARGET_OS_OSX)
167
 
        ((unsigned char)*from >= 128) ||
168
 
#endif
169
 
        (*from == '_') ||
170
 
        (*from == ' ') ||
171
 
        (*from == '-'))
172
 
    {
173
 
      to[length]= *from;
174
 
      continue;
175
 
    }
176
 
   
177
 
    if (length + 3 >= to_length)
178
 
      return true;
179
 
 
180
 
    /* We need to escape this char in a way that can be reversed */
181
 
    to[length++]= '@';
182
 
    to[length++]= hexchars[(*from >> 4) & 15];
183
 
    to[length]= hexchars[(*from) & 15];
184
 
  }
185
 
 
186
 
  if (internal::check_if_legal_tablename(to) &&
187
 
      length + 4 < to_length)
188
 
  {
189
 
    memcpy(to + length, "@@@", 4);
190
 
    length+= 3;
191
 
  }
192
 
  return false;
193
 
}
194
 
 
195
 
 
196
 
/*
197
 
  Creates path to a cursor: drizzle_data_dir/db/table.ext
198
 
 
199
 
  SYNOPSIS
200
 
   build_table_filename()
201
 
     buff                       Where to write result
202
 
                                This may be the same as table_name.
203
 
     bufflen                    buff size
204
 
     db                         Database name
205
 
     table_name                 Table name
206
 
     ext                        File extension.
207
 
     flags                      FN_FROM_IS_TMP or FN_TO_IS_TMP
208
 
                                table_name is temporary, do not change.
209
 
 
210
 
  NOTES
211
 
 
212
 
    Uses database and table name, and extension to create
213
 
    a cursor name in drizzle_data_dir. Database and table
214
 
    names are converted from system_charset_info into "fscs".
215
 
    Unless flags indicate a temporary table name.
216
 
    'db' is always converted.
217
 
    'ext' is not converted.
218
 
 
219
 
    The conversion suppression is required for ALTER Table. This
220
 
    statement creates intermediate tables. These are regular
221
 
    (non-temporary) tables with a temporary name. Their path names must
222
 
    be derivable from the table name. So we cannot use
223
 
    build_tmptable_filename() for them.
224
 
 
225
 
  RETURN
226
 
    path length on success, 0 on failure
227
 
*/
228
 
 
229
 
size_t build_table_filename(char *buff, size_t bufflen, const char *db, const char *table_name, bool is_tmp)
230
 
{
231
 
  char dbbuff[FN_REFLEN];
232
 
  char tbbuff[FN_REFLEN];
233
 
  bool conversion_error= false;
234
 
 
235
 
  memset(tbbuff, 0, sizeof(tbbuff));
236
 
  if (is_tmp) // FN_FROM_IS_TMP | FN_TO_IS_TMP
237
 
    strncpy(tbbuff, table_name, sizeof(tbbuff));
238
 
  else
239
 
  {
240
 
    conversion_error= tablename_to_filename(table_name, tbbuff, sizeof(tbbuff));
241
 
    if (conversion_error)
242
 
    {
243
 
      errmsg_printf(ERRMSG_LVL_ERROR,
244
 
                    _("Table name cannot be encoded and fit within filesystem "
245
 
                      "name length restrictions."));
246
 
      return 0;
247
 
    }
248
 
  }
249
 
  memset(dbbuff, 0, sizeof(dbbuff));
250
 
  conversion_error= tablename_to_filename(db, dbbuff, sizeof(dbbuff));
251
 
  if (conversion_error)
252
 
  {
253
 
    errmsg_printf(ERRMSG_LVL_ERROR,
254
 
                  _("Schema name cannot be encoded and fit within filesystem "
255
 
                    "name length restrictions."));
256
 
    return 0;
257
 
  }
258
 
   
259
 
 
260
 
  int rootdir_len= strlen(FN_ROOTDIR);
261
 
  string table_path(drizzle_data_home);
262
 
  int without_rootdir= table_path.length()-rootdir_len;
263
 
 
264
 
  /* Don't add FN_ROOTDIR if dirzzle_data_home already includes it */
265
 
  if (without_rootdir >= 0)
266
 
  {
267
 
    const char *tmp= table_path.c_str()+without_rootdir;
268
 
    if (memcmp(tmp, FN_ROOTDIR, rootdir_len) != 0)
269
 
      table_path.append(FN_ROOTDIR);
270
 
  }
271
 
 
272
 
  table_path.append(dbbuff);
273
 
  table_path.append(FN_ROOTDIR);
274
 
  table_path.append(tbbuff);
275
 
 
276
 
  if (bufflen < table_path.length())
277
 
    return 0;
278
 
 
279
 
  strcpy(buff, table_path.c_str());
280
 
 
281
 
  return table_path.length();
282
 
}
283
 
 
284
 
 
285
 
/*
286
 
  Creates path to a cursor: drizzle_tmpdir/#sql1234_12_1.ext
287
 
 
288
 
  SYNOPSIS
289
 
   build_tmptable_filename()
290
 
     session                    The thread handle.
291
 
     buff                       Where to write result
292
 
     bufflen                    buff size
293
 
 
294
 
  NOTES
295
 
 
296
 
    Uses current_pid, thread_id, and tmp_table counter to create
297
 
    a cursor name in drizzle_tmpdir.
298
 
 
299
 
  RETURN
300
 
    path length on success, 0 on failure
301
 
*/
302
 
 
303
 
size_t build_tmptable_filename(char *buff, size_t bufflen)
304
 
{
305
 
  size_t length;
306
 
  ostringstream path_str, post_tmpdir_str;
307
 
  string tmp;
308
 
 
309
 
  Session *session= current_session;
310
 
 
311
 
  path_str << drizzle_tmpdir;
312
 
  post_tmpdir_str << "/" << TMP_FILE_PREFIX << current_pid;
313
 
  post_tmpdir_str << session->thread_id << session->tmp_table++;
314
 
  tmp= post_tmpdir_str.str();
315
 
 
316
 
  transform(tmp.begin(), tmp.end(), tmp.begin(), ::tolower);
317
 
 
318
 
  path_str << tmp;
319
 
 
320
 
  if (bufflen < path_str.str().length())
321
 
    length= 0;
322
 
  else
323
 
    length= internal::unpack_filename(buff, path_str.str().c_str());
324
 
 
325
 
  return length;
326
 
}
327
 
 
328
 
/*
329
91
  SYNOPSIS
330
92
    write_bin_log()
331
93
    session                           Thread object
402
164
                         bool drop_temporary)
403
165
{
404
166
  TableList *table;
405
 
  char path[FN_REFLEN];
406
 
  uint32_t path_length= 0;
407
167
  String wrong_tables;
408
168
  int error= 0;
409
169
  bool foreign_key_error= false;
436
196
  for (table= tables; table; table= table->next_local)
437
197
  {
438
198
    char *db=table->db;
439
 
    plugin::StorageEngine *table_type;
440
199
 
441
200
    error= session->drop_temporary_table(table);
442
201
 
452
211
      error= 0;
453
212
    }
454
213
 
455
 
    table_type= table->db_type;
456
214
    if (drop_temporary == false)
457
215
    {
458
216
      Table *locked_table;
472
230
        error= -1;
473
231
        goto err_with_placeholders;
474
232
      }
475
 
      /* remove .frm cursor and engine files */
476
 
      path_length= build_table_filename(path, sizeof(path), db, table->table_name, table->internal_tmp_table);
477
233
    }
478
234
    TableIdentifier identifier(db, table->table_name, table->internal_tmp_table ? INTERNAL_TMP_TABLE : NO_TMP_TABLE);
479
235
 
480
 
    if (drop_temporary ||
481
 
        ((table_type == NULL
482
 
          && (plugin::StorageEngine::getTableDefinition(*session,
483
 
                                                        identifier) != EEXIST))))
 
236
    if (drop_temporary || not plugin::StorageEngine::doesTableExist(*session, identifier))
484
237
    {
485
238
      // Table was not found on disk and table can't be created from engine
486
239
      if (if_exists)
492
245
    }
493
246
    else
494
247
    {
495
 
      error= plugin::StorageEngine::dropTable(*session,
496
 
                                              identifier,
497
 
                                              true);
 
248
      error= plugin::StorageEngine::dropTable(*session, identifier);
498
249
 
499
250
      if ((error == ENOENT || error == HA_ERR_NO_SUCH_TABLE) && if_exists)
500
251
      {
564
315
bool quick_rm_table(Session& session,
565
316
                    TableIdentifier &identifier)
566
317
{
567
 
  return (plugin::StorageEngine::dropTable(session, identifier, false));
 
318
  return (plugin::StorageEngine::dropTable(session, identifier));
568
319
}
569
320
 
570
321
/*
2219
1970
                             bool is_engine_set)
2220
1971
{
2221
1972
  Table *name_lock= 0;
2222
 
  char src_path[FN_REFLEN];
2223
1973
  char *db= table->db;
2224
1974
  char *table_name= table->table_name;
2225
1975
  int  err;
2241
1991
  if (session->open_tables_from_list(&src_table, &not_used))
2242
1992
    return true;
2243
1993
 
2244
 
  strncpy(src_path, src_table->table->s->path.str, sizeof(src_path));
2245
 
 
2246
 
 
2247
1994
  TableIdentifier destination_identifier(db, table_name, lex_identified_temp_table ? TEMP_TABLE : NO_TMP_TABLE);
2248
1995
 
2249
1996
  /*
2259
2006
  {
2260
2007
    if (session->lock_table_name_if_not_cached(db, table_name, &name_lock))
2261
2008
      goto err;
2262
 
    if (! name_lock)
 
2009
    if (not name_lock)
2263
2010
      goto table_exists;
2264
2011
 
2265
 
    if (plugin::StorageEngine::getTableDefinition(*session,
2266
 
                                                  destination_identifier) == EEXIST)
 
2012
    if (plugin::StorageEngine::doesTableExist(*session, destination_identifier))
2267
2013
      goto table_exists;
2268
2014
  }
2269
2015
 
2286
2032
  {
2287
2033
    int protoerr= EEXIST;
2288
2034
 
 
2035
    TableIdentifier identifier(src_table->table->s->db.str,
 
2036
                               src_table->table->s->table_name.str, src_table->table->s->tmp_table);
2289
2037
    protoerr= plugin::StorageEngine::getTableDefinition(*session,
2290
 
                                                        src_path,
2291
 
                                                        db,
2292
 
                                                        table_name,
2293
 
                                                        false,
 
2038
                                                        identifier,
2294
2039
                                                        &src_proto);
2295
2040
 
2296
2041
    message::Table new_proto(src_proto);