ha_myisammrg.cc 19.2 KB
Newer Older
unknown's avatar
unknown committed
1
/* Copyright (C) 2000-2006 MySQL AB
2

unknown's avatar
unknown committed
3 4
   This program is free software; you can redistribute it and/or modify
   it under the terms of the GNU General Public License as published by
unknown's avatar
unknown committed
5
   the Free Software Foundation; version 2 of the License.
6

unknown's avatar
unknown committed
7 8 9 10
   This program is distributed in the hope that it will be useful,
   but WITHOUT ANY WARRANTY; without even the implied warranty of
   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
   GNU General Public License for more details.
11

unknown's avatar
unknown committed
12 13 14 15 16
   You should have received a copy of the GNU General Public License
   along with this program; if not, write to the Free Software
   Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA */


17
#ifdef USE_PRAGMA_IMPLEMENTATION
unknown's avatar
unknown committed
18 19 20
#pragma implementation				// gcc: Class implementation
#endif

21
#define MYSQL_SERVER 1
unknown's avatar
unknown committed
22
#include "mysql_priv.h"
23
#include <mysql/plugin.h>
unknown's avatar
unknown committed
24 25
#include <m_ctype.h>
#include "ha_myisammrg.h"
26
#include "myrg_def.h"
unknown's avatar
unknown committed
27

unknown's avatar
unknown committed
28

unknown's avatar
unknown committed
29 30 31 32
/*****************************************************************************
** MyISAM MERGE tables
*****************************************************************************/

33 34
static handler *myisammrg_create_handler(handlerton *hton,
                                         TABLE_SHARE *table,
35
                                         MEM_ROOT *mem_root)
36
{
37
  return new (mem_root) ha_myisammrg(hton, table);
38 39
}

40

41 42
ha_myisammrg::ha_myisammrg(handlerton *hton, TABLE_SHARE *table_arg)
  :handler(hton, table_arg), file(0)
43 44
{}

unknown's avatar
unknown committed
45 46 47 48
static const char *ha_myisammrg_exts[] = {
  ".MRG",
  NullS
};
49 50 51 52 53 54
extern int table2myisam(TABLE *table_arg, MI_KEYDEF **keydef_out,
                        MI_COLUMNDEF **recinfo_out, uint *records_out);
extern int check_definition(MI_KEYDEF *t1_keyinfo, MI_COLUMNDEF *t1_recinfo,
                            uint t1_keys, uint t1_recs,
                            MI_KEYDEF *t2_keyinfo, MI_COLUMNDEF *t2_recinfo,
                            uint t2_keys, uint t2_recs, bool strict);
unknown's avatar
unknown committed
55

unknown's avatar
unknown committed
56
const char **ha_myisammrg::bas_ext() const
unknown's avatar
unknown committed
57 58 59 60
{
  return ha_myisammrg_exts;
}

unknown's avatar
unknown committed
61

62 63 64 65 66 67 68 69 70 71 72
const char *ha_myisammrg::index_type(uint key_number)
{
  return ((table->key_info[key_number].flags & HA_FULLTEXT) ? 
	  "FULLTEXT" :
	  (table->key_info[key_number].flags & HA_SPATIAL) ?
	  "SPATIAL" :
	  (table->key_info[key_number].algorithm == HA_KEY_ALG_RTREE) ?
	  "RTREE" :
	  "BTREE");
}

73

74
int ha_myisammrg::open(const char *name, int mode, uint test_if_locked)
unknown's avatar
unknown committed
75
{
76 77 78 79
  MI_KEYDEF *keyinfo;
  MI_COLUMNDEF *recinfo;
  MYRG_TABLE *u_table;
  uint recs;
unknown's avatar
unknown committed
80
  uint keys= table->s->keys;
81
  int error;
unknown's avatar
unknown committed
82
  char name_buff[FN_REFLEN];
83

unknown's avatar
unknown committed
84
  DBUG_PRINT("info", ("ha_myisammrg::open"));
85 86 87
  if (!(file=myrg_open(fn_format(name_buff,name,"","",
                                 MY_UNPACK_FILENAME|MY_APPEND_EXT),
                       mode, test_if_locked)))
unknown's avatar
unknown committed
88 89
  {
    DBUG_PRINT("info", ("ha_myisammrg::open exit %d", my_errno));
unknown's avatar
unknown committed
90
    return (my_errno ? my_errno : -1);
unknown's avatar
unknown committed
91
  }
unknown's avatar
unknown committed
92
  DBUG_PRINT("info", ("ha_myisammrg::open myrg_extrafunc..."));
unknown's avatar
unknown committed
93
  myrg_extrafunc(file, query_cache_invalidate_by_MyISAM_filename_ref);
unknown's avatar
unknown committed
94 95
  if (!(test_if_locked == HA_OPEN_WAIT_IF_LOCKED ||
	test_if_locked == HA_OPEN_ABORT_IF_LOCKED))
unknown's avatar
unknown committed
96
    myrg_extra(file,HA_EXTRA_NO_WAIT_LOCK,0);
unknown's avatar
unknown committed
97 98
  info(HA_STATUS_NO_LOCK | HA_STATUS_VARIABLE | HA_STATUS_CONST);
  if (!(test_if_locked & HA_OPEN_WAIT_IF_LOCKED))
unknown's avatar
unknown committed
99
    myrg_extra(file,HA_EXTRA_WAIT_LOCK,0);
100

101
  if (table->s->reclength != stats.mean_rec_length && stats.mean_rec_length)
unknown's avatar
unknown committed
102
  {
unknown's avatar
unknown committed
103
    DBUG_PRINT("error",("reclength: %lu  mean_rec_length: %lu",
104
			table->s->reclength, stats.mean_rec_length));
105
    error= HA_ERR_WRONG_MRG_TABLE_DEF;
106
    goto err;
unknown's avatar
unknown committed
107
  }
108 109 110 111 112
  if ((error= table2myisam(table, &keyinfo, &recinfo, &recs)))
  {
    /* purecov: begin inspected */
    DBUG_PRINT("error", ("Failed to convert TABLE object to MyISAM "
                         "key and column definition"));
113
    goto err;
114
    /* purecov: end */
unknown's avatar
unknown committed
115
  }
116 117 118 119 120 121 122 123 124 125 126 127 128
  for (u_table= file->open_tables; u_table < file->end_table; u_table++)
  {
    if (check_definition(keyinfo, recinfo, keys, recs,
                         u_table->table->s->keyinfo, u_table->table->s->rec,
                         u_table->table->s->base.keys,
                         u_table->table->s->base.fields, false))
    {
      my_free((gptr) recinfo, MYF(0));
      error= HA_ERR_WRONG_MRG_TABLE_DEF;
      goto err;
    }
  }
  my_free((gptr) recinfo, MYF(0));
129 130
#if !defined(BIG_TABLES) || SIZEOF_OFF_T == 4
  /* Merge table has more than 2G rows */
131
  if (table->s->crashed)
132 133
  {
    error= HA_ERR_WRONG_MRG_TABLE_DEF;
134
    goto err;
135
  }
136
#endif
unknown's avatar
unknown committed
137
  return (0);
138 139 140
err:
  myrg_close(file);
  file=0;
141
  return (my_errno= error);
unknown's avatar
unknown committed
142 143 144 145
}

int ha_myisammrg::close(void)
{
unknown's avatar
unknown committed
146
  return myrg_close(file);
unknown's avatar
unknown committed
147 148 149 150
}

int ha_myisammrg::write_row(byte * buf)
{
151
  statistic_increment(table->in_use->status_var.ha_write_count,&LOCK_status);
152 153 154 155

  if (file->merge_insert_method == MERGE_INSERT_DISABLED || !file->tables)
    return (HA_ERR_TABLE_READONLY);

156 157
  if (table->timestamp_field_type & TIMESTAMP_AUTO_SET_ON_INSERT)
    table->timestamp_field->set_time();
158
  if (table->next_number_field && buf == table->record[0])
unknown's avatar
unknown committed
159 160 161 162 163
  {
    int error;
    if ((error= update_auto_increment()))
      return error;
  }
unknown's avatar
unknown committed
164
  return myrg_write(file,buf);
unknown's avatar
unknown committed
165 166 167 168
}

int ha_myisammrg::update_row(const byte * old_data, byte * new_data)
{
169
  statistic_increment(table->in_use->status_var.ha_update_count,&LOCK_status);
170 171
  if (table->timestamp_field_type & TIMESTAMP_AUTO_SET_ON_UPDATE)
    table->timestamp_field->set_time();
unknown's avatar
unknown committed
172
  return myrg_update(file,old_data,new_data);
unknown's avatar
unknown committed
173 174 175 176
}

int ha_myisammrg::delete_row(const byte * buf)
{
177
  statistic_increment(table->in_use->status_var.ha_delete_count,&LOCK_status);
unknown's avatar
unknown committed
178
  return myrg_delete(file,buf);
unknown's avatar
unknown committed
179 180 181 182 183
}

int ha_myisammrg::index_read(byte * buf, const byte * key,
			  uint key_len, enum ha_rkey_function find_flag)
{
184 185
  statistic_increment(table->in_use->status_var.ha_read_key_count,
		      &LOCK_status);
186 187
  int error=myrg_rkey(file,buf,active_index, key, key_len, find_flag);
  table->status=error ? STATUS_NOT_FOUND: 0;
unknown's avatar
unknown committed
188
  return error;
unknown's avatar
unknown committed
189 190 191 192 193
}

int ha_myisammrg::index_read_idx(byte * buf, uint index, const byte * key,
				 uint key_len, enum ha_rkey_function find_flag)
{
194 195
  statistic_increment(table->in_use->status_var.ha_read_key_count,
		      &LOCK_status);
196 197
  int error=myrg_rkey(file,buf,index, key, key_len, find_flag);
  table->status=error ? STATUS_NOT_FOUND: 0;
unknown's avatar
unknown committed
198
  return error;
unknown's avatar
unknown committed
199 200
}

201 202
int ha_myisammrg::index_read_last(byte * buf, const byte * key, uint key_len)
{
203 204
  statistic_increment(table->in_use->status_var.ha_read_key_count,
		      &LOCK_status);
205 206 207
  int error=myrg_rkey(file,buf,active_index, key, key_len,
		      HA_READ_PREFIX_LAST);
  table->status=error ? STATUS_NOT_FOUND: 0;
unknown's avatar
unknown committed
208
  return error;
209 210
}

unknown's avatar
unknown committed
211 212
int ha_myisammrg::index_next(byte * buf)
{
213 214
  statistic_increment(table->in_use->status_var.ha_read_next_count,
		      &LOCK_status);
215 216
  int error=myrg_rnext(file,buf,active_index);
  table->status=error ? STATUS_NOT_FOUND: 0;
unknown's avatar
unknown committed
217
  return error;
unknown's avatar
unknown committed
218 219 220 221
}

int ha_myisammrg::index_prev(byte * buf)
{
222 223
  statistic_increment(table->in_use->status_var.ha_read_prev_count,
		      &LOCK_status);
224 225
  int error=myrg_rprev(file,buf, active_index);
  table->status=error ? STATUS_NOT_FOUND: 0;
unknown's avatar
unknown committed
226
  return error;
unknown's avatar
unknown committed
227
}
228

unknown's avatar
unknown committed
229 230
int ha_myisammrg::index_first(byte * buf)
{
231
  statistic_increment(table->in_use->status_var.ha_read_first_count,
232
		      &LOCK_status);
233 234
  int error=myrg_rfirst(file, buf, active_index);
  table->status=error ? STATUS_NOT_FOUND: 0;
unknown's avatar
unknown committed
235
  return error;
unknown's avatar
unknown committed
236 237 238 239
}

int ha_myisammrg::index_last(byte * buf)
{
240 241
  statistic_increment(table->in_use->status_var.ha_read_last_count,
		      &LOCK_status);
242 243
  int error=myrg_rlast(file, buf, active_index);
  table->status=error ? STATUS_NOT_FOUND: 0;
unknown's avatar
unknown committed
244
  return error;
unknown's avatar
unknown committed
245 246
}

unknown's avatar
unknown committed
247 248 249 250
int ha_myisammrg::index_next_same(byte * buf,
                                  const byte *key __attribute__((unused)),
                                  uint length __attribute__((unused)))
{
251 252
  statistic_increment(table->in_use->status_var.ha_read_next_count,
		      &LOCK_status);
unknown's avatar
unknown committed
253 254 255 256 257
  int error=myrg_rnext_same(file,buf);
  table->status=error ? STATUS_NOT_FOUND: 0;
  return error;
}

258

unknown's avatar
unknown committed
259 260
int ha_myisammrg::rnd_init(bool scan)
{
261
  return myrg_reset(file);
unknown's avatar
unknown committed
262 263
}

264

unknown's avatar
unknown committed
265 266
int ha_myisammrg::rnd_next(byte *buf)
{
267
  statistic_increment(table->in_use->status_var.ha_read_rnd_next_count,
268
		      &LOCK_status);
unknown's avatar
unknown committed
269 270
  int error=myrg_rrnd(file, buf, HA_OFFSET_ERROR);
  table->status=error ? STATUS_NOT_FOUND: 0;
unknown's avatar
unknown committed
271
  return error;
unknown's avatar
unknown committed
272 273
}

274

unknown's avatar
unknown committed
275 276
int ha_myisammrg::rnd_pos(byte * buf, byte *pos)
{
277 278
  statistic_increment(table->in_use->status_var.ha_read_rnd_count,
		      &LOCK_status);
unknown's avatar
unknown committed
279
  int error=myrg_rrnd(file, buf, my_get_ptr(pos,ref_length));
unknown's avatar
unknown committed
280
  table->status=error ? STATUS_NOT_FOUND: 0;
unknown's avatar
unknown committed
281
  return error;
unknown's avatar
unknown committed
282 283 284 285
}

void ha_myisammrg::position(const byte *record)
{
286 287
  ulonglong row_position= myrg_position(file);
  my_store_ptr(ref, ref_length, (my_off_t) row_position);
unknown's avatar
unknown committed
288 289
}

unknown's avatar
unknown committed
290 291 292 293 294

ha_rows ha_myisammrg::records_in_range(uint inx, key_range *min_key,
                                       key_range *max_key)
{
  return (ha_rows) myrg_records_in_range(file, (int) inx, min_key, max_key);
unknown's avatar
unknown committed
295
}
unknown's avatar
unknown committed
296

unknown's avatar
unknown committed
297

298
int ha_myisammrg::info(uint flag)
unknown's avatar
unknown committed
299
{
300 301
  MYMERGE_INFO mrg_info;
  (void) myrg_status(file,&mrg_info,flag);
302 303 304 305
  /*
    The following fails if one has not compiled MySQL with -DBIG_TABLES
    and one has more than 2^32 rows in the merge tables.
  */
unknown's avatar
unknown committed
306 307
  stats.records = (ha_rows) mrg_info.records;
  stats.deleted = (ha_rows) mrg_info.deleted;
308
#if !defined(BIG_TABLES) || SIZEOF_OFF_T == 4
309 310
  if ((mrg_info.records >= (ulonglong) 1 << 32) ||
      (mrg_info.deleted >= (ulonglong) 1 << 32))
311
    table->s->crashed= 1;
312
#endif
unknown's avatar
unknown committed
313 314
  stats.data_file_length= mrg_info.data_file_length;
  errkey= mrg_info.errkey;
315
  table->s->keys_in_use.set_prefix(table->s->keys);
unknown's avatar
unknown committed
316
  stats.mean_rec_length= mrg_info.reclength;
317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333
  
  /* 
    The handler::block_size is used all over the code in index scan cost
    calculations. It is used to get number of disk seeks required to
    retrieve a number of index tuples.
    If the merge table has N underlying tables, then (assuming underlying
    tables have equal size, the only "simple" approach we can use)
    retrieving X index records from a merge table will require N times more
    disk seeks compared to doing the same on a MyISAM table with equal
    number of records.
    In the edge case (file_tables > myisam_block_size) we'll get
    block_size==0, and index calculation code will act as if we need one
    disk seek to retrieve one index tuple.

    TODO: In 5.2 index scan cost calculation will be factored out into a
    virtual function in class handler and we'll be able to remove this hack.
  */
334
  stats.block_size= 0;
335
  if (file->tables)
336
    stats.block_size= myisam_block_size / file->tables;
337
  
338
  stats.update_time= 0;
339
#if SIZEOF_OFF_T > 4
unknown's avatar
unknown committed
340
  ref_length=6;					// Should be big enough
341 342 343
#else
  ref_length=4;					// Can't be > than my_off_t
#endif
unknown's avatar
unknown committed
344 345
  if (flag & HA_STATUS_CONST)
  {
346
    if (table->s->key_parts && mrg_info.rec_per_key)
347 348 349 350 351 352 353 354 355
    {
#ifdef HAVE_purify
      /*
        valgrind may be unhappy about it, because optimizer may access values
        between file->keys and table->key_parts, that will be uninitialized.
        It's safe though, because even if opimizer will decide to use a key
        with such a number, it'll be an error later anyway.
      */
      bzero((char*) table->key_info[0].rec_per_key,
unknown's avatar
unknown committed
356
            sizeof(table->key_info[0].rec_per_key) * table->s->key_parts);
357
#endif
unknown's avatar
unknown committed
358
      memcpy((char*) table->key_info[0].rec_per_key,
359
	     (char*) mrg_info.rec_per_key,
360
             sizeof(table->key_info[0].rec_per_key) *
361
             min(file->keys, table->s->key_parts));
362
    }
unknown's avatar
unknown committed
363
  }
364
  return 0;
unknown's avatar
unknown committed
365 366 367 368 369
}


int ha_myisammrg::extra(enum ha_extra_function operation)
{
370 371 372 373
  /* As this is just a mapping, we don't have to force the underlying
     tables to be closed */
  if (operation == HA_EXTRA_FORCE_REOPEN ||
      operation == HA_EXTRA_PREPARE_FOR_DELETE)
unknown's avatar
unknown committed
374 375
    return 0;
  return myrg_extra(file,operation,0);
unknown's avatar
unknown committed
376 377
}

378 379 380 381
int ha_myisammrg::reset(void)
{
  return myrg_reset(file);
}
unknown's avatar
unknown committed
382 383 384 385 386

/* To be used with WRITE_CACHE, EXTRA_CACHE and BULK_INSERT_BEGIN */

int ha_myisammrg::extra_opt(enum ha_extra_function operation, ulong cache_size)
{
unknown's avatar
unknown committed
387
  if ((specialflag & SPECIAL_SAFE_MODE) && operation == HA_EXTRA_WRITE_CACHE)
unknown's avatar
unknown committed
388 389
    return 0;
  return myrg_extra(file, operation, (void*) &cache_size);
unknown's avatar
unknown committed
390 391
}

unknown's avatar
unknown committed
392 393
int ha_myisammrg::external_lock(THD *thd, int lock_type)
{
unknown's avatar
unknown committed
394
  return myrg_lock_database(file,lock_type);
395
}
unknown's avatar
unknown committed
396 397 398

uint ha_myisammrg::lock_count(void) const
{
unknown's avatar
unknown committed
399
  return file->tables;
unknown's avatar
unknown committed
400 401 402 403 404 405 406
}


THR_LOCK_DATA **ha_myisammrg::store_lock(THD *thd,
					 THR_LOCK_DATA **to,
					 enum thr_lock_type lock_type)
{
407
  MYRG_TABLE *open_table;
unknown's avatar
unknown committed
408

409 410 411
  for (open_table=file->open_tables ;
       open_table != file->end_table ;
       open_table++)
unknown's avatar
unknown committed
412
  {
413 414 415
    *(to++)= &open_table->table->lock;
    if (lock_type != TL_IGNORE && open_table->table->lock.type == TL_UNLOCK)
      open_table->table->lock.type=lock_type;
unknown's avatar
unknown committed
416
  }
unknown's avatar
unknown committed
417
  return to;
unknown's avatar
unknown committed
418 419
}

420 421 422 423 424 425

/* Find out database name and table name from a filename */

static void split_file_name(const char *file_name,
			    LEX_STRING *db, LEX_STRING *name)
{
unknown's avatar
unknown committed
426
  uint dir_length, prefix_length;
427 428 429
  char buff[FN_REFLEN];

  db->length= 0;
unknown's avatar
unknown committed
430
  strmake(buff, file_name, sizeof(buff)-1);
431 432 433 434 435 436 437 438 439 440 441 442 443 444
  dir_length= dirname_length(buff);
  if (dir_length > 1)
  {
    /* Get database */
    buff[dir_length-1]= 0;			// Remove end '/'
    prefix_length= dirname_length(buff);
    db->str= (char*) file_name+ prefix_length;
    db->length= dir_length - prefix_length -1;
  }
  name->str= (char*) file_name+ dir_length;
  name->length= (uint) (fn_ext(name->str) - name->str);
}


445 446
void ha_myisammrg::update_create_info(HA_CREATE_INFO *create_info)
{
unknown's avatar
unknown committed
447
  DBUG_ENTER("ha_myisammrg::update_create_info");
448

449 450
  if (!(create_info->used_fields & HA_CREATE_USED_UNION))
  {
451
    MYRG_TABLE *open_table;
452
    THD *thd=current_thd;
453

454
    create_info->merge_list.next= &create_info->merge_list.first;
455
    create_info->merge_list.elements=0;
456

457 458 459
    for (open_table=file->open_tables ;
	 open_table != file->end_table ;
	 open_table++)
460 461
    {
      TABLE_LIST *ptr;
462
      LEX_STRING db, name;
unknown's avatar
unknown committed
463 464
      db.length= 0;
      db.str= 0;
465

466 467
      if (!(ptr = (TABLE_LIST *) thd->calloc(sizeof(TABLE_LIST))))
	goto err;
468
      split_file_name(open_table->table->filename, &db, &name);
469
      if (!(ptr->table_name= thd->strmake(name.str, name.length)))
470 471
	goto err;
      if (db.length && !(ptr->db= thd->strmake(db.str, db.length)))
472
	goto err;
473

474
      create_info->merge_list.elements++;
475
      (*create_info->merge_list.next) = (byte*) ptr;
unknown's avatar
VIEW  
unknown committed
476
      create_info->merge_list.next= (byte**) &ptr->next_local;
477 478 479
    }
    *create_info->merge_list.next=0;
  }
480 481 482 483
  if (!(create_info->used_fields & HA_CREATE_USED_INSERT_METHOD))
  {
    create_info->merge_insert_method = file->merge_insert_method;
  }
484 485 486 487 488 489 490
  DBUG_VOID_RETURN;

err:
  create_info->merge_list.elements=0;
  create_info->merge_list.first=0;
  DBUG_VOID_RETURN;
}
unknown's avatar
unknown committed
491

492

unknown's avatar
unknown committed
493 494 495
int ha_myisammrg::create(const char *name, register TABLE *form,
			 HA_CREATE_INFO *create_info)
{
496 497
  char buff[FN_REFLEN];
  const char **table_names, **pos;
498
  TABLE_LIST *tables= (TABLE_LIST*) create_info->merge_list.first;
499
  THD *thd= current_thd;
500
  uint dirlgt= dirname_length(name);
501 502
  DBUG_ENTER("ha_myisammrg::create");

503 504
  if (!(table_names= (const char**)
        thd->alloc((create_info->merge_list.elements+1) * sizeof(char*))))
unknown's avatar
unknown committed
505
    DBUG_RETURN(HA_ERR_OUT_OF_MEM);
unknown's avatar
VIEW  
unknown committed
506
  for (pos= table_names; tables; tables= tables->next_local)
unknown's avatar
unknown committed
507
  {
508
    const char *table_name;
unknown's avatar
unknown committed
509
    TABLE *tbl= 0;
unknown's avatar
unknown committed
510
    if (create_info->options & HA_LEX_CREATE_TMP_TABLE)
unknown's avatar
unknown committed
511
      tbl= find_temporary_table(thd, tables);
512
    if (!tbl)
unknown's avatar
unknown committed
513
    {
514 515 516 517 518 519 520 521 522 523 524
      /*
        Construct the path to the MyISAM table. Try to meet two conditions:
        1.) Allow to include MyISAM tables from different databases, and
        2.) allow for moving DATADIR around in the file system.
        The first means that we need paths in the .MRG file. The second
        means that we should not have absolute paths in the .MRG file.
        The best, we can do, is to use 'mysql_data_home', which is '.'
        in mysqld and may be an absolute path in an embedded server.
        This means that it might not be possible to move the DATADIR of
        an embedded server without changing the paths in the .MRG file.
      */
525
      uint length= build_table_filename(buff, sizeof(buff),
526
                                        tables->db, tables->table_name, "", 0);
527 528 529 530 531 532 533
      /*
        If a MyISAM table is in the same directory as the MERGE table,
        we use the table name without a path. This means that the
        DATADIR can easily be moved even for an embedded server as long
        as the MyISAM tables are from the same database as the MERGE table.
      */
      if ((dirname_length(buff) == dirlgt) && ! memcmp(buff, name, dirlgt))
534
        table_name= tables->table_name;
535 536 537
      else
        if (! (table_name= thd->strmake(buff, length)))
          DBUG_RETURN(HA_ERR_OUT_OF_MEM);
unknown's avatar
unknown committed
538 539
    }
    else
unknown's avatar
unknown committed
540
      table_name= tbl->s->path.str;
unknown's avatar
unknown committed
541 542
    *pos++= table_name;
  }
543
  *pos=0;
544 545 546
  DBUG_RETURN(myrg_create(fn_format(buff,name,"","",
                                    MY_RESOLVE_SYMLINKS|
                                    MY_UNPACK_FILENAME|MY_APPEND_EXT),
547
			  table_names,
548 549
                          create_info->merge_insert_method,
                          (my_bool) 0));
unknown's avatar
unknown committed
550
}
unknown's avatar
unknown committed
551

552

unknown's avatar
unknown committed
553 554
void ha_myisammrg::append_create_info(String *packet)
{
555 556 557
  const char *current_db;
  uint db_length;
  THD *thd= current_thd;
unknown's avatar
unknown committed
558
  MYRG_TABLE *open_table, *first;
559

560 561
  if (file->merge_insert_method != MERGE_INSERT_DISABLED)
  {
562
    packet->append(STRING_WITH_LEN(" INSERT_METHOD="));
563
    packet->append(get_type(&merge_insert_method,file->merge_insert_method-1));
564
  }
565
  packet->append(STRING_WITH_LEN(" UNION=("));
unknown's avatar
unknown committed
566

unknown's avatar
unknown committed
567 568
  current_db= table->s->db.str;
  db_length=  table->s->db.length;
569

570 571 572
  for (first=open_table=file->open_tables ;
       open_table != file->end_table ;
       open_table++)
unknown's avatar
unknown committed
573
  {
574
    LEX_STRING db, name;
unknown's avatar
unknown committed
575 576
    db.length= 0;
    db.str= 0;
577
    split_file_name(open_table->table->filename, &db, &name);
578
    if (open_table != first)
unknown's avatar
unknown committed
579
      packet->append(',');
580 581 582 583 584 585 586 587 588
    /* Report database for mapped table if it isn't in current database */
    if (db.length &&
	(db_length != db.length ||
	 strncmp(current_db, db.str, db.length)))
    {
      append_identifier(thd, packet, db.str, db.length);
      packet->append('.');
    }
    append_identifier(thd, packet, name.str, name.length);
unknown's avatar
unknown committed
589 590 591
  }
  packet->append(')');
}
unknown's avatar
unknown committed
592 593 594 595 596 597 598 599 600 601 602


bool ha_myisammrg::check_if_incompatible_data(HA_CREATE_INFO *info,
					      uint table_changes)
{
  /*
    For myisammrg, we should always re-generate the mapping file as this
    is trivial to do
  */
  return COMPATIBLE_DATA_NO;
}
unknown's avatar
unknown committed
603

604 605 606 607 608 609
extern int myrg_panic(enum ha_panic_function flag);
int myisammrg_panic(handlerton *hton, ha_panic_function flag)
{
  return myrg_panic(flag);
}

610
static int myisammrg_init(void *p)
unknown's avatar
unknown committed
611
{
612 613
  handlerton *myisammrg_hton;

614 615
  myisammrg_hton= (handlerton *)p;

616
  myisammrg_hton->state= SHOW_OPTION_YES;
617 618 619 620
  myisammrg_hton->db_type= DB_TYPE_MRG_MYISAM;
  myisammrg_hton->create= myisammrg_create_handler;
  myisammrg_hton->panic= myisammrg_panic;
  myisammrg_hton->flags=  HTON_CAN_RECREATE|HTON_NO_PARTITION;
621

unknown's avatar
unknown committed
622 623 624 625
  return 0;
}

struct st_mysql_storage_engine myisammrg_storage_engine=
626
{ MYSQL_HANDLERTON_INTERFACE_VERSION };
unknown's avatar
unknown committed
627

unknown's avatar
unknown committed
628 629 630
mysql_declare_plugin(myisammrg)
{
  MYSQL_STORAGE_ENGINE_PLUGIN,
unknown's avatar
unknown committed
631 632
  &myisammrg_storage_engine,
  "MRG_MYISAM",
unknown's avatar
unknown committed
633
  "MySQL AB",
unknown's avatar
unknown committed
634
  "Collection of identical MyISAM tables",
635
  PLUGIN_LICENSE_GPL,
unknown's avatar
unknown committed
636
  myisammrg_init, /* Plugin Init */
unknown's avatar
unknown committed
637
  NULL, /* Plugin Deinit */
unknown's avatar
unknown committed
638
  0x0100, /* 1.0 */
639 640 641
  NULL,                       /* status variables                */
  NULL,                       /* system variables                */
  NULL                        /* config options                  */
unknown's avatar
unknown committed
642 643
}
mysql_declare_plugin_end;