MySQL 5.6.14 Source Code Document
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Groups Pages
ha_myisammrg.cc
1 /* Copyright (c) 2000, 2013, Oracle and/or its affiliates. All rights reserved.
2 
3  This program is free software; you can redistribute it and/or modify
4  it under the terms of the GNU General Public License as published by
5  the Free Software Foundation; version 2 of the License.
6 
7  This program is distributed in the hope that it will be useful,
8  but WITHOUT ANY WARRANTY; without even the implied warranty of
9  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
10  GNU General Public License for more details.
11 
12  You should have received a copy of the GNU General Public License
13  along with this program; if not, write to the Free Software
14  Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */
15 
16 
17 /*
18  MyISAM MERGE tables
19 
20  A MyISAM MERGE table is kind of a union of zero or more MyISAM tables.
21 
22  Besides the normal form file (.frm) a MERGE table has a meta file
23  (.MRG) with a list of tables. These are paths to the MyISAM table
24  files. The last two components of the path contain the database name
25  and the table name respectively.
26 
27  When a MERGE table is open, there exists an TABLE object for the MERGE
28  table itself and a TABLE object for each of the MyISAM tables. For
29  abbreviated writing, I call the MERGE table object "parent" and the
30  MyISAM table objects "children".
31 
32  A MERGE table is almost always opened through open_and_lock_tables()
33  and hence through open_tables(). When the parent appears in the list
34  of tables to open, the initial open of the handler does nothing but
35  read the meta file and collect a list of TABLE_LIST objects for the
36  children. This list is attached to the handler object as
37  ha_myisammrg::children_l. The end of the children list is saved in
38  ha_myisammrg::children_last_l.
39 
40  Back in open_tables(), handler::extra(HA_EXTRA_ADD_CHILDREN_LIST) is
41  called. It updates each list member with the lock type and a back
42  pointer to the parent TABLE_LIST object TABLE_LIST::parent_l. The list
43  is then inserted in the list of tables to open, right behind the
44  parent. Consequently, open_tables() opens the children, one after the
45  other. The TABLE references of the TABLE_LIST objects are implicitly
46  set to the open tables by open_table(). The children are opened as
47  independent MyISAM tables, right as if they are used by the SQL
48  statement.
49 
50  When all tables from the statement query list are open,
51  handler::extra(HA_EXTRA_ATTACH_CHILDREN) is called. It "attaches" the
52  children to the parent. All required references between parent and
53  children are set up.
54 
55  The MERGE storage engine sets up an array with references to the
56  low-level MyISAM table objects (MI_INFO). It remembers the state of
57  the table in MYRG_INFO::children_attached.
58 
59  If necessary, the compatibility of parent and children is checked.
60  This check is necessary when any of the objects are reopend. This is
61  detected by comparing the current table def version against the
62  remembered child def version. On parent open, the list members are
63  initialized to an "impossible"/"undefined" version value. So the check
64  is always executed on the first attach.
65 
66  The version check is done in myisammrg_attach_children_callback(),
67  which is called for every child. ha_myisammrg::attach_children()
68  initializes 'need_compat_check' to FALSE and
69  myisammrg_attach_children_callback() sets it ot TRUE if a table
70  def version mismatches the remembered child def version.
71 
72  The children chain remains in the statement query list until the table
73  is closed or the children are detached. This is done so that the
74  children are locked by lock_tables().
75 
76  At statement end the children are detached. At the next statement
77  begin the open-add-attach sequence repeats. There is no exception for
78  LOCK TABLES. The fresh establishment of the parent-child relationship
79  before every statement catches numerous cases of ALTER/FLUSH/DROP/etc
80  of parent or children during LOCK TABLES.
81 
82  ---
83 
84  On parent open the storage engine structures are allocated and initialized.
85  They stay with the open table until its final close.
86 */
87 
88 #define MYSQL_SERVER 1
89 #include "sql_priv.h"
90 #include "unireg.h"
91 #include "sql_cache.h" // query_cache_*
92 #include "sql_show.h" // append_identifier
93 #include "sql_table.h" // build_table_filename
94 #include "probes_mysql.h"
95 #include <mysql/plugin.h>
96 #include <m_ctype.h>
97 #include "../myisam/ha_myisam.h"
98 #include "ha_myisammrg.h"
99 #include "myrg_def.h"
100 #include "thr_malloc.h" // int_sql_alloc
101 #include "sql_class.h" // THD
102 #include "debug_sync.h"
103 
104 #include <algorithm>
105 
106 using std::min;
107 using std::max;
108 
109 static handler *myisammrg_create_handler(handlerton *hton,
111  MEM_ROOT *mem_root)
112 {
113  return new (mem_root) ha_myisammrg(hton, table);
114 }
115 
116 
122  :handler(hton, table_arg), file(0), is_cloned(0)
123 {
124  init_sql_alloc(&children_mem_root,
125  FN_REFLEN + ALLOC_ROOT_MIN_BLOCK_SIZE, 0);
126 }
127 
128 
134 {
135  free_root(&children_mem_root, MYF(0));
136 }
137 
138 
139 static const char *ha_myisammrg_exts[] = {
140  ".MRG",
141  NullS
142 };
143 extern int table2myisam(TABLE *table_arg, MI_KEYDEF **keydef_out,
144  MI_COLUMNDEF **recinfo_out, uint *records_out);
145 extern int check_definition(MI_KEYDEF *t1_keyinfo, MI_COLUMNDEF *t1_recinfo,
146  uint t1_keys, uint t1_recs,
147  MI_KEYDEF *t2_keyinfo, MI_COLUMNDEF *t2_recinfo,
148  uint t2_keys, uint t2_recs, bool strict,
149  TABLE *table_arg);
150 static void split_file_name(const char *file_name,
151  LEX_STRING *db, LEX_STRING *name);
152 
153 
154 extern "C" void myrg_print_wrong_table(const char *table_name)
155 {
156  LEX_STRING db= {NULL, 0}, name;
157  char buf[FN_REFLEN];
158  split_file_name(table_name, &db, &name);
159  memcpy(buf, db.str, db.length);
160  buf[db.length]= '.';
161  memcpy(buf + db.length + 1, name.str, name.length);
162  buf[db.length + name.length + 1]= 0;
163  /*
164  Push an error to be reported as part of CHECK/REPAIR result-set.
165  Note that calling my_error() from handler is a hack which is kept
166  here to avoid refactoring. Normally engines should report errors
167  through return value which will be interpreted by caller using
168  handler::print_error() call.
169  */
170  my_error(ER_ADMIN_WRONG_MRG_TABLE, MYF(0), buf);
171 }
172 
173 
174 const char **ha_myisammrg::bas_ext() const
175 {
176  return ha_myisammrg_exts;
177 }
178 
179 
180 const char *ha_myisammrg::index_type(uint key_number)
181 {
182  return ((table->key_info[key_number].flags & HA_FULLTEXT) ?
183  "FULLTEXT" :
184  (table->key_info[key_number].flags & HA_SPATIAL) ?
185  "SPATIAL" :
186  (table->key_info[key_number].algorithm == HA_KEY_ALG_RTREE) ?
187  "RTREE" :
188  "BTREE");
189 }
190 
191 
231 CPP_UNNAMED_NS_START
232 
233 extern "C" int myisammrg_parent_open_callback(void *callback_param,
234  const char *filename)
235 {
236  ha_myisammrg *ha_myrg= (ha_myisammrg*) callback_param;
237  TABLE *parent= ha_myrg->table_ptr();
238  Mrg_child_def *mrg_child_def;
239  char *db;
240  char *table_name;
241  uint dirlen;
242  uint db_length;
243  uint table_name_length;
244  char dir_path[FN_REFLEN];
245  char name_buf[NAME_LEN];
246  DBUG_ENTER("myisammrg_parent_open_callback");
247 
248  /*
249  Depending on MySQL version, filename may be encoded by table name to
250  file name encoding or not. Always encoded if parent table is created
251  by 5.1.46+. Encoded if parent is created by 5.1.6+ and child table is
252  in different database.
253  */
254  if (!has_path(filename))
255  {
256  /* Child is in the same database as parent. */
257  db_length= parent->s->db.length;
258  db= strmake_root(&ha_myrg->children_mem_root, parent->s->db.str, db_length);
259  /* Child table name is encoded in parent dot-MRG starting with 5.1.46. */
260  if (parent->s->mysql_version >= 50146)
261  {
262  table_name_length= filename_to_tablename(filename, name_buf,
263  sizeof(name_buf));
264  table_name= strmake_root(&ha_myrg->children_mem_root, name_buf,
265  table_name_length);
266  }
267  else
268  {
269  table_name_length= strlen(filename);
270  table_name= strmake_root(&ha_myrg->children_mem_root, filename,
271  table_name_length);
272  }
273  }
274  else
275  {
276  DBUG_ASSERT(strlen(filename) < sizeof(dir_path));
277  fn_format(dir_path, filename, "", "", 0);
278  /* Extract child table name and database name from filename. */
279  dirlen= dirname_length(dir_path);
280  /* Child db/table name is encoded in parent dot-MRG starting with 5.1.6. */
281  if (parent->s->mysql_version >= 50106)
282  {
283  table_name_length= filename_to_tablename(dir_path + dirlen, name_buf,
284  sizeof(name_buf));
285  table_name= strmake_root(&ha_myrg->children_mem_root, name_buf,
286  table_name_length);
287  dir_path[dirlen - 1]= 0;
288  dirlen= dirname_length(dir_path);
289  db_length= filename_to_tablename(dir_path + dirlen, name_buf, sizeof(name_buf));
290  db= strmake_root(&ha_myrg->children_mem_root, name_buf, db_length);
291  }
292  else
293  {
294  table_name_length= strlen(dir_path + dirlen);
295  table_name= strmake_root(&ha_myrg->children_mem_root, dir_path + dirlen,
296  table_name_length);
297  dir_path[dirlen - 1]= 0;
298  dirlen= dirname_length(dir_path);
299  db_length= strlen(dir_path + dirlen);
300  db= strmake_root(&ha_myrg->children_mem_root, dir_path + dirlen,
301  db_length);
302  }
303  }
304 
305  if (! db || ! table_name)
306  DBUG_RETURN(1);
307 
308  DBUG_PRINT("myrg", ("open: '%.*s'.'%.*s'", (int) db_length, db,
309  (int) table_name_length, table_name));
310 
311  /* Convert to lowercase if required. */
312  if (lower_case_table_names && table_name_length)
313  {
314  /* purecov: begin tested */
315  table_name_length= my_casedn_str(files_charset_info, table_name);
316  /* purecov: end */
317  }
318 
319  mrg_child_def= new (&ha_myrg->children_mem_root)
320  Mrg_child_def(db, db_length, table_name, table_name_length);
321 
322  if (! mrg_child_def ||
323  ha_myrg->child_def_list.push_back(mrg_child_def,
324  &ha_myrg->children_mem_root))
325  {
326  DBUG_RETURN(1);
327  }
328  DBUG_RETURN(0);
329 }
330 
331 CPP_UNNAMED_NS_END
332 
333 
350 int ha_myisammrg::open(const char *name, int mode __attribute__((unused)),
351  uint test_if_locked_arg)
352 {
353  DBUG_ENTER("ha_myisammrg::open");
354  DBUG_PRINT("myrg", ("name: '%s' table: 0x%lx", name, (long) table));
355  DBUG_PRINT("myrg", ("test_if_locked_arg: %u", test_if_locked_arg));
356 
357  /* Must not be used when table is open. */
358  DBUG_ASSERT(!this->file);
359 
360  /* Save for later use. */
361  test_if_locked= test_if_locked_arg;
362 
363  /* In case this handler was open and closed before, free old data. */
364  free_root(&this->children_mem_root, MYF(MY_MARK_BLOCKS_FREE));
365 
366  /*
367  Initialize variables that are used, modified, and/or set by
368  myisammrg_parent_open_callback().
369  'children_l' is the head of the children chain.
370  'children_last_l' points to the end of the children chain.
371  'my_errno' is set by myisammrg_parent_open_callback() in
372  case of an error.
373  */
374  children_l= NULL;
375  children_last_l= NULL;
376  child_def_list.empty();
377  my_errno= 0;
378 
379  /* retrieve children table list. */
380  if (is_cloned)
381  {
382  /*
383  Open and attaches the MyISAM tables,that are under the MERGE table
384  parent, on the MyISAM storage engine interface directly within the
385  MERGE engine. The new MyISAM table instances, as well as the MERGE
386  clone itself, are not visible in the table cache. This is not a
387  problem because all locking is handled by the original MERGE table
388  from which this is cloned of.
389  */
390  if (!(file= myrg_open(name, table->db_stat, HA_OPEN_IGNORE_IF_LOCKED)))
391  {
392  DBUG_PRINT("error", ("my_errno %d", my_errno));
393  DBUG_RETURN(my_errno ? my_errno : -1);
394  }
395 
396  file->children_attached= TRUE;
397 
398  info(HA_STATUS_NO_LOCK | HA_STATUS_VARIABLE | HA_STATUS_CONST);
399  }
400  else if (!(file= myrg_parent_open(name, myisammrg_parent_open_callback, this)))
401  {
402  /* purecov: begin inspected */
403  DBUG_PRINT("error", ("my_errno %d", my_errno));
404  DBUG_RETURN(my_errno ? my_errno : -1);
405  /* purecov: end */
406  }
407  DBUG_PRINT("myrg", ("MYRG_INFO: 0x%lx child tables: %u",
408  (long) file, file->tables));
409  DBUG_RETURN(0);
410 }
411 
412 
428 {
429  TABLE_LIST *parent_l= this->table->pos_in_table_list;
430  THD *thd= table->in_use;
431  List_iterator_fast<Mrg_child_def> it(child_def_list);
432  Mrg_child_def *mrg_child_def;
433  DBUG_ENTER("ha_myisammrg::add_children_list");
434  DBUG_PRINT("myrg", ("table: '%s'.'%s' 0x%lx", this->table->s->db.str,
435  this->table->s->table_name.str, (long) this->table));
436 
437  /* Must call this with open table. */
438  DBUG_ASSERT(this->file);
439 
440  /* Ignore this for empty MERGE tables (UNION=()). */
441  if (!this->file->tables)
442  {
443  DBUG_PRINT("myrg", ("empty merge table union"));
444  goto end;
445  }
446 
447  /* Must not call this with attached children. */
448  DBUG_ASSERT(!this->file->children_attached);
449 
450  /* Must not call this with children list in place. */
451  DBUG_ASSERT(this->children_l == NULL);
452 
453  /*
454  Prevent inclusion of another MERGE table, which could make infinite
455  recursion.
456  */
457  if (parent_l->parent_l)
458  {
459  my_error(ER_ADMIN_WRONG_MRG_TABLE, MYF(0), parent_l->alias);
460  DBUG_RETURN(1);
461  }
462 
463  while ((mrg_child_def= it++))
464  {
465  TABLE_LIST *child_l;
466  char *db;
467  char *table_name;
468 
469  child_l= (TABLE_LIST*) thd->alloc(sizeof(TABLE_LIST));
470  db= (char*) thd->memdup(mrg_child_def->db.str, mrg_child_def->db.length+1);
471  table_name= (char*) thd->memdup(mrg_child_def->name.str,
472  mrg_child_def->name.length+1);
473 
474  if (child_l == NULL || db == NULL || table_name == NULL)
475  DBUG_RETURN(1);
476 
477  child_l->init_one_table(db, mrg_child_def->db.length,
478  table_name, mrg_child_def->name.length,
479  table_name, parent_l->lock_type);
480  /* Set parent reference. Used to detect MERGE in children list. */
481  child_l->parent_l= parent_l;
482  /* Copy select_lex. Used in unique_table() at least. */
483  child_l->select_lex= parent_l->select_lex;
484  /* Set the expected table version, to not cause spurious re-prepare. */
485  child_l->set_table_ref_id(mrg_child_def->get_child_table_ref_type(),
486  mrg_child_def->get_child_def_version());
487  /*
488  Copy parent's prelocking attribute to allow opening of child
489  temporary residing in the prelocking list.
490  */
491  child_l->prelocking_placeholder= parent_l->prelocking_placeholder;
492  /*
493  For statements which acquire a SNW metadata lock on a parent table and
494  then later try to upgrade it to an X lock (e.g. ALTER TABLE), SNW
495  locks should be also taken on the children tables.
496 
497  Otherwise we end up in a situation where the thread trying to upgrade SNW
498  to X lock on the parent also holds a SR metadata lock and a read
499  thr_lock.c lock on the child. As a result, another thread might be
500  blocked on the thr_lock.c lock for the child after successfully acquiring
501  a SR or SW metadata lock on it. If at the same time this second thread
502  has a shared metadata lock on the parent table or there is some other
503  thread which has a shared metadata lock on the parent and is waiting for
504  this second thread, we get a deadlock. This deadlock cannot be properly
505  detected by the MDL subsystem as part of the waiting happens within
506  thr_lock.c. By taking SNW locks on the child tables we ensure that any
507  thread which waits for a thread doing SNW -> X upgrade, does this within
508  the MDL subsystem and thus potential deadlocks are exposed to the deadlock
509  detector.
510 
511  We don't do the same thing for SNRW locks as this would allow
512  DDL on implicitly locked underlying tables of a MERGE table.
513  */
514  if (! thd->locked_tables_mode &&
515  parent_l->mdl_request.type == MDL_SHARED_UPGRADABLE)
516  child_l->mdl_request.set_type(MDL_SHARED_NO_WRITE);
517  /* Link TABLE_LIST object into the children list. */
518  if (this->children_last_l)
519  child_l->prev_global= this->children_last_l;
520  else
521  {
522  /* Initialize children_last_l when handling first child. */
523  this->children_last_l= &this->children_l;
524  }
525  *this->children_last_l= child_l;
526  this->children_last_l= &child_l->next_global;
527  }
528 
529  /* Insert children into the table list. */
530  if (parent_l->next_global)
531  parent_l->next_global->prev_global= this->children_last_l;
532  *this->children_last_l= parent_l->next_global;
533  parent_l->next_global= this->children_l;
534  this->children_l->prev_global= &parent_l->next_global;
535  /*
536  We have to update LEX::query_tables_last if children are added to
537  the tail of the table list in order to be able correctly add more
538  elements to it (e.g. as part of prelocking process).
539  */
540  if (thd->lex->query_tables_last == &parent_l->next_global)
541  thd->lex->query_tables_last= this->children_last_l;
542  /*
543  The branch below works only when re-executing a prepared
544  statement or a stored routine statement:
545  We've just modified query_tables_last. Keep it in sync with
546  query_tables_last_own, if it was set by the prelocking code.
547  This ensures that the check that prohibits double updates (*)
548  can correctly identify what tables belong to the main statement.
549  (*) A double update is, e.g. when a user issues UPDATE t1 and
550  t1 has an AFTER UPDATE trigger that also modifies t1.
551  */
552  if (thd->lex->query_tables_own_last == &parent_l->next_global)
553  thd->lex->query_tables_own_last= this->children_last_l;
554 
555 end:
556  DBUG_RETURN(0);
557 }
558 
559 
565 {
566 public:
577  Mrg_child_def *mrg_child_def;
578 public:
580  TABLE_LIST *first_child,
581  List<Mrg_child_def> &child_def_list)
582  :need_compat_check(FALSE),
583  parent_l(parent_l_arg),
584  next_child_attach(first_child),
585  def_it(child_def_list),
586  mrg_child_def(def_it++)
587  {}
588  void next()
589  {
590  next_child_attach= next_child_attach->next_global;
591  if (next_child_attach && next_child_attach->parent_l != parent_l)
592  next_child_attach= NULL;
593  if (mrg_child_def)
594  mrg_child_def= def_it++;
595  }
596 };
597 
598 
614 CPP_UNNAMED_NS_START
615 
616 extern "C" MI_INFO *myisammrg_attach_children_callback(void *callback_param)
617 {
619  (Mrg_attach_children_callback_param*) callback_param;
620  TABLE *parent= param->parent_l->table;
621  TABLE *child;
622  TABLE_LIST *child_l= param->next_child_attach;
623  Mrg_child_def *mrg_child_def= param->mrg_child_def;
624  MI_INFO *myisam= NULL;
625  DBUG_ENTER("myisammrg_attach_children_callback");
626 
627  /*
628  Number of children in the list and MYRG_INFO::tables_count,
629  which is used by caller of this function, should always match.
630  */
631  DBUG_ASSERT(child_l);
632 
633  child= child_l->table;
634 
635  /* Prepare for next child. */
636  param->next();
637 
638  if (!child)
639  {
640  DBUG_PRINT("error", ("failed to open underlying table '%s'.'%s'",
641  child_l->db, child_l->table_name));
642  goto end;
643  }
644 
645  /*
646  Do a quick compatibility check. The table def version is set when
647  the table share is created. The child def version is copied
648  from the table def version after a successful compatibility check.
649  We need to repeat the compatibility check only if a child is opened
650  from a different share than last time it was used with this MERGE
651  table.
652  */
653  DBUG_PRINT("myrg", ("table_def_version last: %llu current: %llu",
654  mrg_child_def->get_child_def_version(),
655  child->s->get_table_def_version()));
656  if (mrg_child_def->get_child_def_version() != child->s->get_table_def_version())
657  param->need_compat_check= TRUE;
658 
659  /*
660  If child is temporary, parent must be temporary as well. Other
661  parent/child combinations are allowed. This check must be done for
662  every child on every open because the table def version can overlap
663  between temporary and non-temporary tables. We need to detect the
664  case where a non-temporary table has been replaced with a temporary
665  table of the same version. Or vice versa. A very unlikely case, but
666  it could happen. (Note that the condition was different from
667  5.1.23/6.0.4(Bug#19627) to 5.5.6 (Bug#36171): child->s->tmp_table !=
668  parent->s->tmp_table. Tables were required to have the same status.)
669  */
670  if (child->s->tmp_table && !parent->s->tmp_table)
671  {
672  DBUG_PRINT("error", ("temporary table mismatch parent: %d child: %d",
673  parent->s->tmp_table, child->s->tmp_table));
674  goto end;
675  }
676 
677  /* Extract the MyISAM table structure pointer from the handler object. */
678  if ((child->file->ht->db_type != DB_TYPE_MYISAM) ||
679  !(myisam= ((ha_myisam*) child->file)->file_ptr()))
680  {
681  DBUG_PRINT("error", ("no MyISAM handle for child table: '%s'.'%s' 0x%lx",
682  child->s->db.str, child->s->table_name.str,
683  (long) child));
684  }
685 
686  DBUG_PRINT("myrg", ("MyISAM handle: 0x%lx", (long) myisam));
687 
688  end:
689 
690  if (!myisam &&
691  (current_thd->open_options & HA_OPEN_FOR_REPAIR))
692  {
693  char buf[2*NAME_LEN + 1 + 1];
694  strxnmov(buf, sizeof(buf) - 1, child_l->db, ".", child_l->table_name, NULL);
695  /*
696  Push an error to be reported as part of CHECK/REPAIR result-set.
697  Note that calling my_error() from handler is a hack which is kept
698  here to avoid refactoring. Normally engines should report errors
699  through return value which will be interpreted by caller using
700  handler::print_error() call.
701  */
702  my_error(ER_ADMIN_WRONG_MRG_TABLE, MYF(0), buf);
703  }
704 
705  DBUG_RETURN(myisam);
706 }
707 
708 CPP_UNNAMED_NS_END
709 
710 
716 handler *ha_myisammrg::clone(const char *name, MEM_ROOT *mem_root)
717 {
718  MYRG_TABLE *u_table,*newu_table;
719  ha_myisammrg *new_handler=
720  (ha_myisammrg*) get_new_handler(table->s, mem_root, table->s->db_type());
721  if (!new_handler)
722  return NULL;
723 
724  /* Inform ha_myisammrg::open() that it is a cloned handler */
725  new_handler->is_cloned= TRUE;
726  /*
727  Allocate handler->ref here because otherwise ha_open will allocate it
728  on this->table->mem_root and we will not be able to reclaim that memory
729  when the clone handler object is destroyed.
730  */
731  if (!(new_handler->ref= (uchar*) alloc_root(mem_root, ALIGN_SIZE(ref_length)*2)))
732  {
733  delete new_handler;
734  return NULL;
735  }
736 
737  if (new_handler->ha_open(table, name, table->db_stat,
738  HA_OPEN_IGNORE_IF_LOCKED))
739  {
740  delete new_handler;
741  return NULL;
742  }
743 
744  /*
745  Iterate through the original child tables and
746  copy the state into the cloned child tables.
747  We need to do this because all the child tables
748  can be involved in delete.
749  */
750  newu_table= new_handler->file->open_tables;
751  for (u_table= file->open_tables; u_table < file->end_table; u_table++)
752  {
753  newu_table->table->state= u_table->table->state;
754  newu_table++;
755  }
756 
757  return new_handler;
758  }
759 
760 
783 {
784  MYRG_TABLE *u_table;
785  MI_COLUMNDEF *recinfo;
786  MI_KEYDEF *keyinfo;
787  uint recs;
788  uint keys= table->s->keys;
789  TABLE_LIST *parent_l= table->pos_in_table_list;
790  int error;
791  Mrg_attach_children_callback_param param(parent_l, this->children_l, child_def_list);
792  DBUG_ENTER("ha_myisammrg::attach_children");
793  DBUG_PRINT("myrg", ("table: '%s'.'%s' 0x%lx", table->s->db.str,
794  table->s->table_name.str, (long) table));
795  DBUG_PRINT("myrg", ("test_if_locked: %u", this->test_if_locked));
796 
797  /* Must call this with open table. */
798  DBUG_ASSERT(this->file);
799 
800  /*
801  A MERGE table with no children (empty union) is always seen as
802  attached internally.
803  */
804  if (!this->file->tables)
805  {
806  DBUG_PRINT("myrg", ("empty merge table union"));
807  goto end;
808  }
809  DBUG_PRINT("myrg", ("child tables: %u", this->file->tables));
810 
811  /* Must not call this with attached children. */
812  DBUG_ASSERT(!this->file->children_attached);
813 
814  DEBUG_SYNC(current_thd, "before_myisammrg_attach");
815  /* Must call this with children list in place. */
816  DBUG_ASSERT(this->table->pos_in_table_list->next_global == this->children_l);
817 
818  if (myrg_attach_children(this->file, this->test_if_locked |
819  current_thd->open_options,
820  myisammrg_attach_children_callback, &param,
821  (my_bool *) &param.need_compat_check))
822  {
823  error= my_errno;
824  goto err;
825  }
826  DBUG_PRINT("myrg", ("calling myrg_extrafunc"));
827  myrg_extrafunc(file, query_cache_invalidate_by_MyISAM_filename_ref);
828  if (!(test_if_locked == HA_OPEN_WAIT_IF_LOCKED ||
829  test_if_locked == HA_OPEN_ABORT_IF_LOCKED))
830  myrg_extra(file,HA_EXTRA_NO_WAIT_LOCK,0);
831  info(HA_STATUS_NO_LOCK | HA_STATUS_VARIABLE | HA_STATUS_CONST);
832  if (!(test_if_locked & HA_OPEN_WAIT_IF_LOCKED))
833  myrg_extra(file,HA_EXTRA_WAIT_LOCK,0);
834 
835  /*
836  The compatibility check is required only if one or more children do
837  not match their table def version from the last check. This will
838  always happen at the first attach because the reference child def
839  version is initialized to 'undefined' at open.
840  */
841  DBUG_PRINT("myrg", ("need_compat_check: %d", param.need_compat_check));
842  if (param.need_compat_check)
843  {
844  TABLE_LIST *child_l;
845 
846  if (table->s->reclength != stats.mean_rec_length && stats.mean_rec_length)
847  {
848  DBUG_PRINT("error",("reclength: %lu mean_rec_length: %lu",
849  table->s->reclength, stats.mean_rec_length));
850  if (test_if_locked & HA_OPEN_FOR_REPAIR)
851  {
852  /* purecov: begin inspected */
853  myrg_print_wrong_table(file->open_tables->table->filename);
854  /* purecov: end */
855  }
856  error= HA_ERR_WRONG_MRG_TABLE_DEF;
857  goto err;
858  }
859  /*
860  Both recinfo and keyinfo are allocated by my_multi_malloc(), thus
861  only recinfo must be freed.
862  */
863  if ((error= table2myisam(table, &keyinfo, &recinfo, &recs)))
864  {
865  /* purecov: begin inspected */
866  DBUG_PRINT("error", ("failed to convert TABLE object to MyISAM "
867  "key and column definition"));
868  goto err;
869  /* purecov: end */
870  }
871  for (u_table= file->open_tables; u_table < file->end_table; u_table++)
872  {
873  if (check_definition(keyinfo, recinfo, keys, recs,
874  u_table->table->s->keyinfo, u_table->table->s->rec,
875  u_table->table->s->base.keys,
876  u_table->table->s->base.fields, false, NULL))
877  {
878  DBUG_PRINT("error", ("table definition mismatch: '%s'",
879  u_table->table->filename));
880  error= HA_ERR_WRONG_MRG_TABLE_DEF;
881  if (!(this->test_if_locked & HA_OPEN_FOR_REPAIR))
882  {
883  my_free(recinfo);
884  goto err;
885  }
886  /* purecov: begin inspected */
887  myrg_print_wrong_table(u_table->table->filename);
888  /* purecov: end */
889  }
890  }
891  my_free(recinfo);
892  if (error == HA_ERR_WRONG_MRG_TABLE_DEF)
893  goto err; /* purecov: inspected */
894 
895  List_iterator_fast<Mrg_child_def> def_it(child_def_list);
896  DBUG_ASSERT(this->children_l);
897  for (child_l= this->children_l; ; child_l= child_l->next_global)
898  {
899  Mrg_child_def *mrg_child_def= def_it++;
900  mrg_child_def->set_child_def_version(
901  child_l->table->s->get_table_ref_type(),
902  child_l->table->s->get_table_def_version());
903 
904  if (&child_l->next_global == this->children_last_l)
905  break;
906  }
907  }
908 #if !defined(BIG_TABLES) || SIZEOF_OFF_T == 4
909  /* Merge table has more than 2G rows */
910  if (table->s->crashed)
911  {
912  DBUG_PRINT("error", ("MERGE table marked crashed"));
913  error= HA_ERR_WRONG_MRG_TABLE_DEF;
914  goto err;
915  }
916 #endif
917 
918  end:
919  DBUG_RETURN(0);
920 
921 err:
922  DBUG_PRINT("error", ("attaching MERGE children failed: %d", error));
923  print_error(error, MYF(0));
924  detach_children();
925  DBUG_RETURN(my_errno= error);
926 }
927 
928 
943 {
944  TABLE_LIST *child_l;
945  DBUG_ENTER("ha_myisammrg::detach_children");
946 
947  /* Must call this with open table. */
948  DBUG_ASSERT(this->file);
949 
950  /* A MERGE table with no children (empty union) cannot be detached. */
951  if (!this->file->tables)
952  {
953  DBUG_PRINT("myrg", ("empty merge table union"));
954  goto end;
955  }
956 
957  if (this->children_l)
958  {
959  THD *thd= table->in_use;
960 
961  /* Clear TABLE references. */
962  for (child_l= this->children_l; ; child_l= child_l->next_global)
963  {
964  /*
965  Do not DBUG_ASSERT(child_l->table); open_tables might be
966  incomplete.
967 
968  Clear the table reference.
969  */
970  child_l->table= NULL;
971  /* Similarly, clear the ticket reference. */
972  child_l->mdl_request.ticket= NULL;
973 
974  /* Break when this was the last child. */
975  if (&child_l->next_global == this->children_last_l)
976  break;
977  }
978  /*
979  Remove children from the table list. This won't fail if called
980  twice. The list is terminated after removal.
981 
982  If the parent is LEX::query_tables_own_last and pre-locked tables
983  follow (tables used by stored functions or triggers), the children
984  are inserted behind the parent and before the pre-locked tables. But
985  we do not adjust LEX::query_tables_own_last. The pre-locked tables
986  could have chopped off the list by clearing
987  *LEX::query_tables_own_last. This did also chop off the children. If
988  we would copy the reference from *this->children_last_l in this
989  case, we would put the chopped off pre-locked tables back to the
990  list. So we refrain from copying it back, if the destination has
991  been set to NULL meanwhile.
992  */
993  if (this->children_l->prev_global && *this->children_l->prev_global)
994  *this->children_l->prev_global= *this->children_last_l;
995  if (*this->children_last_l)
996  (*this->children_last_l)->prev_global= this->children_l->prev_global;
997 
998  /*
999  If table elements being removed are at the end of table list we
1000  need to adjust LEX::query_tables_last member to point to the
1001  new last element of the list.
1002  */
1003  if (thd->lex->query_tables_last == this->children_last_l)
1004  thd->lex->query_tables_last= this->children_l->prev_global;
1005 
1006  /*
1007  If the statement requires prelocking, and prelocked
1008  tables were added right after merge children, modify the
1009  last own table pointer to point at prev_global of the merge
1010  parent.
1011  */
1012  if (thd->lex->query_tables_own_last == this->children_last_l)
1013  thd->lex->query_tables_own_last= this->children_l->prev_global;
1014 
1015  /* Terminate child list. So it cannot be tried to remove again. */
1016  *this->children_last_l= NULL;
1017  this->children_l->prev_global= NULL;
1018 
1019  /* Forget about the children, we don't own their memory. */
1020  this->children_l= NULL;
1021  this->children_last_l= NULL;
1022  }
1023 
1024  if (!this->file->children_attached)
1025  {
1026  DBUG_PRINT("myrg", ("merge children are already detached"));
1027  goto end;
1028  }
1029 
1030  if (myrg_detach_children(this->file))
1031  {
1032  /* purecov: begin inspected */
1033  print_error(my_errno, MYF(0));
1034  DBUG_RETURN(my_errno ? my_errno : -1);
1035  /* purecov: end */
1036  }
1037 
1038  end:
1039  DBUG_RETURN(0);
1040 }
1041 
1042 
1055 {
1056  int rc;
1057  DBUG_ENTER("ha_myisammrg::close");
1058  /*
1059  There are cases where children are not explicitly detached before
1060  close. detach_children() protects itself against double detach.
1061  */
1062  if (!is_cloned)
1063  detach_children();
1064 
1065  rc= myrg_close(file);
1066  file= 0;
1067  DBUG_RETURN(rc);
1068 }
1069 
1070 int ha_myisammrg::write_row(uchar * buf)
1071 {
1072  DBUG_ENTER("ha_myisammrg::write_row");
1073  DBUG_ASSERT(this->file->children_attached);
1074  ha_statistic_increment(&SSV::ha_write_count);
1075 
1076  if (file->merge_insert_method == MERGE_INSERT_DISABLED || !file->tables)
1077  DBUG_RETURN(HA_ERR_TABLE_READONLY);
1078 
1079  if (table->next_number_field && buf == table->record[0])
1080  {
1081  int error;
1082  if ((error= update_auto_increment()))
1083  DBUG_RETURN(error); /* purecov: inspected */
1084  }
1085  DBUG_RETURN(myrg_write(file,buf));
1086 }
1087 
1088 int ha_myisammrg::update_row(const uchar * old_data, uchar * new_data)
1089 {
1090  DBUG_ASSERT(this->file->children_attached);
1091  ha_statistic_increment(&SSV::ha_update_count);
1092  return myrg_update(file,old_data,new_data);
1093 }
1094 
1095 int ha_myisammrg::delete_row(const uchar * buf)
1096 {
1097  DBUG_ASSERT(this->file->children_attached);
1098  ha_statistic_increment(&SSV::ha_delete_count);
1099  return myrg_delete(file,buf);
1100 }
1101 
1102 int ha_myisammrg::index_read_map(uchar * buf, const uchar * key,
1103  key_part_map keypart_map,
1104  enum ha_rkey_function find_flag)
1105 {
1106  DBUG_ASSERT(this->file->children_attached);
1107  MYSQL_INDEX_READ_ROW_START(table_share->db.str, table_share->table_name.str);
1108  ha_statistic_increment(&SSV::ha_read_key_count);
1109  int error=myrg_rkey(file,buf,active_index, key, keypart_map, find_flag);
1110  table->status=error ? STATUS_NOT_FOUND: 0;
1111  MYSQL_INDEX_READ_ROW_DONE(error);
1112  return error;
1113 }
1114 
1115 int ha_myisammrg::index_read_idx_map(uchar * buf, uint index, const uchar * key,
1116  key_part_map keypart_map,
1117  enum ha_rkey_function find_flag)
1118 {
1119  DBUG_ASSERT(this->file->children_attached);
1120  MYSQL_INDEX_READ_ROW_START(table_share->db.str, table_share->table_name.str);
1121  ha_statistic_increment(&SSV::ha_read_key_count);
1122  int error=myrg_rkey(file,buf,index, key, keypart_map, find_flag);
1123  table->status=error ? STATUS_NOT_FOUND: 0;
1124  MYSQL_INDEX_READ_ROW_DONE(error);
1125  return error;
1126 }
1127 
1128 int ha_myisammrg::index_read_last_map(uchar *buf, const uchar *key,
1129  key_part_map keypart_map)
1130 {
1131  DBUG_ASSERT(this->file->children_attached);
1132  MYSQL_INDEX_READ_ROW_START(table_share->db.str, table_share->table_name.str);
1133  ha_statistic_increment(&SSV::ha_read_key_count);
1134  int error=myrg_rkey(file,buf,active_index, key, keypart_map,
1135  HA_READ_PREFIX_LAST);
1136  table->status=error ? STATUS_NOT_FOUND: 0;
1137  MYSQL_INDEX_READ_ROW_DONE(error);
1138  return error;
1139 }
1140 
1142 {
1143  DBUG_ASSERT(this->file->children_attached);
1144  MYSQL_INDEX_READ_ROW_START(table_share->db.str, table_share->table_name.str);
1145  ha_statistic_increment(&SSV::ha_read_next_count);
1146  int error=myrg_rnext(file,buf,active_index);
1147  table->status=error ? STATUS_NOT_FOUND: 0;
1148  MYSQL_INDEX_READ_ROW_DONE(error);
1149  return error;
1150 }
1151 
1153 {
1154  DBUG_ASSERT(this->file->children_attached);
1155  MYSQL_INDEX_READ_ROW_START(table_share->db.str, table_share->table_name.str);
1156  ha_statistic_increment(&SSV::ha_read_prev_count);
1157  int error=myrg_rprev(file,buf, active_index);
1158  table->status=error ? STATUS_NOT_FOUND: 0;
1159  MYSQL_INDEX_READ_ROW_DONE(error);
1160  return error;
1161 }
1162 
1164 {
1165  DBUG_ASSERT(this->file->children_attached);
1166  MYSQL_INDEX_READ_ROW_START(table_share->db.str, table_share->table_name.str);
1167  ha_statistic_increment(&SSV::ha_read_first_count);
1168  int error=myrg_rfirst(file, buf, active_index);
1169  table->status=error ? STATUS_NOT_FOUND: 0;
1170  MYSQL_INDEX_READ_ROW_DONE(error);
1171  return error;
1172 }
1173 
1175 {
1176  DBUG_ASSERT(this->file->children_attached);
1177  MYSQL_INDEX_READ_ROW_START(table_share->db.str, table_share->table_name.str);
1178  ha_statistic_increment(&SSV::ha_read_last_count);
1179  int error=myrg_rlast(file, buf, active_index);
1180  table->status=error ? STATUS_NOT_FOUND: 0;
1181  MYSQL_INDEX_READ_ROW_DONE(error);
1182  return error;
1183 }
1184 
1186  const uchar *key __attribute__((unused)),
1187  uint length __attribute__((unused)))
1188 {
1189  int error;
1190  DBUG_ASSERT(this->file->children_attached);
1191  MYSQL_INDEX_READ_ROW_START(table_share->db.str, table_share->table_name.str);
1192  ha_statistic_increment(&SSV::ha_read_next_count);
1193  do
1194  {
1195  error= myrg_rnext_same(file,buf);
1196  } while (error == HA_ERR_RECORD_DELETED);
1197  table->status=error ? STATUS_NOT_FOUND: 0;
1198  MYSQL_INDEX_READ_ROW_DONE(error);
1199  return error;
1200 }
1201 
1202 
1204 {
1205  DBUG_ASSERT(this->file->children_attached);
1206  return myrg_reset(file);
1207 }
1208 
1209 
1210 int ha_myisammrg::rnd_next(uchar *buf)
1211 {
1212  DBUG_ASSERT(this->file->children_attached);
1213  MYSQL_READ_ROW_START(table_share->db.str, table_share->table_name.str,
1214  TRUE);
1215  ha_statistic_increment(&SSV::ha_read_rnd_next_count);
1216  int error=myrg_rrnd(file, buf, HA_OFFSET_ERROR);
1217  table->status=error ? STATUS_NOT_FOUND: 0;
1218  MYSQL_READ_ROW_DONE(error);
1219  return error;
1220 }
1221 
1222 
1223 int ha_myisammrg::rnd_pos(uchar * buf, uchar *pos)
1224 {
1225  DBUG_ASSERT(this->file->children_attached);
1226  MYSQL_READ_ROW_START(table_share->db.str, table_share->table_name.str,
1227  TRUE);
1228  ha_statistic_increment(&SSV::ha_read_rnd_count);
1229  int error=myrg_rrnd(file, buf, my_get_ptr(pos,ref_length));
1230  table->status=error ? STATUS_NOT_FOUND: 0;
1231  MYSQL_READ_ROW_DONE(error);
1232  return error;
1233 }
1234 
1235 void ha_myisammrg::position(const uchar *record)
1236 {
1237  DBUG_ASSERT(this->file->children_attached);
1238  ulonglong row_position= myrg_position(file);
1239  my_store_ptr(ref, ref_length, (my_off_t) row_position);
1240 }
1241 
1242 
1243 ha_rows ha_myisammrg::records_in_range(uint inx, key_range *min_key,
1244  key_range *max_key)
1245 {
1246  DBUG_ASSERT(this->file->children_attached);
1247  return (ha_rows) myrg_records_in_range(file, (int) inx, min_key, max_key);
1248 }
1249 
1250 
1252 {
1253  int err= 0;
1254  MYRG_TABLE *table;
1255  DBUG_ENTER("ha_myisammrg::truncate");
1256 
1257  for (table= file->open_tables; table != file->end_table; table++)
1258  {
1259  if ((err= mi_delete_all_rows(table->table)))
1260  break;
1261  }
1262 
1263  DBUG_RETURN(err);
1264 }
1265 
1266 
1267 int ha_myisammrg::info(uint flag)
1268 {
1269  MYMERGE_INFO mrg_info;
1270  DBUG_ASSERT(this->file->children_attached);
1271  (void) myrg_status(file,&mrg_info,flag);
1272  /*
1273  The following fails if one has not compiled MySQL with -DBIG_TABLES
1274  and one has more than 2^32 rows in the merge tables.
1275  */
1276  stats.records = (ha_rows) mrg_info.records;
1277  stats.deleted = (ha_rows) mrg_info.deleted;
1278 #if !defined(BIG_TABLES) || SIZEOF_OFF_T == 4
1279  if ((mrg_info.records >= (ulonglong) 1 << 32) ||
1280  (mrg_info.deleted >= (ulonglong) 1 << 32))
1281  table->s->crashed= 1;
1282 #endif
1283  stats.data_file_length= mrg_info.data_file_length;
1284  if (mrg_info.errkey >= (int) table_share->keys)
1285  {
1286  /*
1287  If value of errkey is higher than the number of keys
1288  on the table set errkey to MAX_KEY. This will be
1289  treated as unknown key case and error message generator
1290  won't try to locate key causing segmentation fault.
1291  */
1292  mrg_info.errkey= MAX_KEY;
1293  }
1294  table->s->keys_in_use.set_prefix(table->s->keys);
1295  stats.mean_rec_length= mrg_info.reclength;
1296 
1297  /*
1298  The handler::block_size is used all over the code in index scan cost
1299  calculations. It is used to get number of disk seeks required to
1300  retrieve a number of index tuples.
1301  If the merge table has N underlying tables, then (assuming underlying
1302  tables have equal size, the only "simple" approach we can use)
1303  retrieving X index records from a merge table will require N times more
1304  disk seeks compared to doing the same on a MyISAM table with equal
1305  number of records.
1306  In the edge case (file_tables > myisam_block_size) we'll get
1307  block_size==0, and index calculation code will act as if we need one
1308  disk seek to retrieve one index tuple.
1309 
1310  TODO: In 5.2 index scan cost calculation will be factored out into a
1311  virtual function in class handler and we'll be able to remove this hack.
1312  */
1313  stats.block_size= 0;
1314  if (file->tables)
1315  stats.block_size= myisam_block_size / file->tables;
1316 
1317  stats.update_time= 0;
1318 #if SIZEOF_OFF_T > 4
1319  ref_length=6; // Should be big enough
1320 #else
1321  ref_length=4; // Can't be > than my_off_t
1322 #endif
1323  if (flag & HA_STATUS_CONST)
1324  {
1325  if (table->s->key_parts && mrg_info.rec_per_key)
1326  {
1327 #ifdef HAVE_purify
1328  /*
1329  valgrind may be unhappy about it, because optimizer may access values
1330  between file->keys and table->key_parts, that will be uninitialized.
1331  It's safe though, because even if opimizer will decide to use a key
1332  with such a number, it'll be an error later anyway.
1333  */
1334  memset(table->key_info[0].rec_per_key, 0,
1335  sizeof(table->key_info[0].rec_per_key[0]) * table->s->key_parts);
1336 #endif
1337  memcpy((char*) table->key_info[0].rec_per_key,
1338  (char*) mrg_info.rec_per_key,
1339  sizeof(table->key_info[0].rec_per_key[0]) *
1340  min(file->keys, table->s->key_parts));
1341  }
1342  }
1343  if (flag & HA_STATUS_ERRKEY)
1344  {
1345  errkey= mrg_info.errkey;
1346  my_store_ptr(dup_ref, ref_length, mrg_info.dupp_key_pos);
1347  }
1348  return 0;
1349 }
1350 
1351 
1352 int ha_myisammrg::extra(enum ha_extra_function operation)
1353 {
1354  if (operation == HA_EXTRA_ADD_CHILDREN_LIST)
1355  {
1356  int rc= add_children_list();
1357  return(rc);
1358  }
1359  else if (operation == HA_EXTRA_ATTACH_CHILDREN)
1360  {
1361  int rc= attach_children();
1362  if (!rc)
1363  (void) extra(HA_EXTRA_NO_READCHECK); // Not needed in SQL
1364  return(rc);
1365  }
1366  else if (operation == HA_EXTRA_IS_ATTACHED_CHILDREN)
1367  {
1368  /* For the upper layer pretend empty MERGE union is never attached. */
1369  return(file && file->tables && file->children_attached);
1370  }
1371  else if (operation == HA_EXTRA_DETACH_CHILDREN)
1372  {
1373  /*
1374  Note that detach must not touch the children in any way.
1375  They may have been closed at ths point already.
1376  */
1377  int rc= detach_children();
1378  return(rc);
1379  }
1380 
1381  /* As this is just a mapping, we don't have to force the underlying
1382  tables to be closed */
1383  if (operation == HA_EXTRA_FORCE_REOPEN ||
1384  operation == HA_EXTRA_PREPARE_FOR_DROP)
1385  return 0;
1386  if (operation == HA_EXTRA_MMAP && !opt_myisam_use_mmap)
1387  return 0;
1388  return myrg_extra(file,operation,0);
1389 }
1390 
1392 {
1393  /* This is normally called with detached children. */
1394  return myrg_reset(file);
1395 }
1396 
1397 /* To be used with WRITE_CACHE, EXTRA_CACHE and BULK_INSERT_BEGIN */
1398 
1399 int ha_myisammrg::extra_opt(enum ha_extra_function operation, ulong cache_size)
1400 {
1401  DBUG_ASSERT(this->file->children_attached);
1402  return myrg_extra(file, operation, (void*) &cache_size);
1403 }
1404 
1405 int ha_myisammrg::external_lock(THD *thd, int lock_type)
1406 {
1407  /*
1408  This can be called with no children attached. E.g. FLUSH TABLES
1409  unlocks and re-locks tables under LOCK TABLES, but it does not open
1410  them first. So they are detached all the time. But locking of the
1411  children should work anyway because thd->open_tables is not changed
1412  during FLUSH TABLES.
1413 
1414  If this handler instance has been cloned, we still must call
1415  myrg_lock_database().
1416  */
1417  if (is_cloned)
1418  return myrg_lock_database(file, lock_type);
1419  return 0;
1420 }
1421 
1423 {
1424  return 0;
1425 }
1426 
1427 
1429  THR_LOCK_DATA **to,
1430  enum thr_lock_type lock_type)
1431 {
1432  return to;
1433 }
1434 
1435 
1436 /* Find out database name and table name from a filename */
1437 
1438 static void split_file_name(const char *file_name,
1439  LEX_STRING *db, LEX_STRING *name)
1440 {
1441  size_t dir_length, prefix_length;
1442  char buff[FN_REFLEN];
1443 
1444  db->length= 0;
1445  strmake(buff, file_name, sizeof(buff)-1);
1446  dir_length= dirname_length(buff);
1447  if (dir_length > 1)
1448  {
1449  /* Get database */
1450  buff[dir_length-1]= 0; // Remove end '/'
1451  prefix_length= dirname_length(buff);
1452  db->str= (char*) file_name+ prefix_length;
1453  db->length= dir_length - prefix_length -1;
1454  }
1455  name->str= (char*) file_name+ dir_length;
1456  name->length= (uint) (fn_ext(name->str) - name->str);
1457 }
1458 
1459 
1460 void ha_myisammrg::update_create_info(HA_CREATE_INFO *create_info)
1461 {
1462  DBUG_ENTER("ha_myisammrg::update_create_info");
1463 
1464  if (!(create_info->used_fields & HA_CREATE_USED_UNION))
1465  {
1466  TABLE_LIST *child_table;
1467  THD *thd=current_thd;
1468 
1469  create_info->merge_list.next= &create_info->merge_list.first;
1470  create_info->merge_list.elements=0;
1471 
1472  if (children_l != NULL)
1473  {
1474  for (child_table= children_l;;
1475  child_table= child_table->next_global)
1476  {
1477  TABLE_LIST *ptr;
1478 
1479  if (!(ptr= (TABLE_LIST *) thd->calloc(sizeof(TABLE_LIST))))
1480  goto err;
1481 
1482  if (!(ptr->table_name= thd->strmake(child_table->table_name,
1483  child_table->table_name_length)))
1484  goto err;
1485  if (child_table->db && !(ptr->db= thd->strmake(child_table->db,
1486  child_table->db_length)))
1487  goto err;
1488 
1489  create_info->merge_list.elements++;
1490  (*create_info->merge_list.next)= ptr;
1491  create_info->merge_list.next= &ptr->next_local;
1492 
1493  if (&child_table->next_global == children_last_l)
1494  break;
1495  }
1496  }
1497  *create_info->merge_list.next=0;
1498  }
1499  if (!(create_info->used_fields & HA_CREATE_USED_INSERT_METHOD))
1500  {
1501  create_info->merge_insert_method = file->merge_insert_method;
1502  }
1503  DBUG_VOID_RETURN;
1504 
1505 err:
1506  create_info->merge_list.elements=0;
1507  create_info->merge_list.first=0;
1508  DBUG_VOID_RETURN;
1509 }
1510 
1511 
1512 int ha_myisammrg::create(const char *name, register TABLE *form,
1513  HA_CREATE_INFO *create_info)
1514 {
1515  char buff[FN_REFLEN];
1516  const char **table_names, **pos;
1517  TABLE_LIST *tables= create_info->merge_list.first;
1518  THD *thd= current_thd;
1519  size_t dirlgt= dirname_length(name);
1520  DBUG_ENTER("ha_myisammrg::create");
1521 
1522  /* Allocate a table_names array in thread mem_root. */
1523  if (!(table_names= (const char**)
1524  thd->alloc((create_info->merge_list.elements+1) * sizeof(char*))))
1525  DBUG_RETURN(HA_ERR_OUT_OF_MEM); /* purecov: inspected */
1526 
1527  /* Create child path names. */
1528  for (pos= table_names; tables; tables= tables->next_local)
1529  {
1530  const char *table_name= buff;
1531 
1532  /*
1533  Construct the path to the MyISAM table. Try to meet two conditions:
1534  1.) Allow to include MyISAM tables from different databases, and
1535  2.) allow for moving DATADIR around in the file system.
1536  The first means that we need paths in the .MRG file. The second
1537  means that we should not have absolute paths in the .MRG file.
1538  The best, we can do, is to use 'mysql_data_home', which is '.'
1539  in mysqld and may be an absolute path in an embedded server.
1540  This means that it might not be possible to move the DATADIR of
1541  an embedded server without changing the paths in the .MRG file.
1542 
1543  Do the same even for temporary tables. MERGE children are now
1544  opened through the table cache. They are opened by db.table_name,
1545  not by their path name.
1546  */
1547  uint length= build_table_filename(buff, sizeof(buff),
1548  tables->db, tables->table_name, "", 0);
1549  /*
1550  If a MyISAM table is in the same directory as the MERGE table,
1551  we use the table name without a path. This means that the
1552  DATADIR can easily be moved even for an embedded server as long
1553  as the MyISAM tables are from the same database as the MERGE table.
1554  */
1555  if ((dirname_length(buff) == dirlgt) && ! memcmp(buff, name, dirlgt))
1556  {
1557  table_name+= dirlgt;
1558  length-= dirlgt;
1559  }
1560  if (!(table_name= thd->strmake(table_name, length)))
1561  DBUG_RETURN(HA_ERR_OUT_OF_MEM); /* purecov: inspected */
1562 
1563  *pos++= table_name;
1564  }
1565  *pos=0;
1566 
1567  /* Create a MERGE meta file from the table_names array. */
1568  DBUG_RETURN(myrg_create(fn_format(buff,name,"","",
1569  MY_RESOLVE_SYMLINKS|
1570  MY_UNPACK_FILENAME|MY_APPEND_EXT),
1571  table_names,
1572  create_info->merge_insert_method,
1573  (my_bool) 0));
1574 }
1575 
1576 
1577 void ha_myisammrg::append_create_info(String *packet)
1578 {
1579  const char *current_db;
1580  size_t db_length;
1581  THD *thd= current_thd;
1582  TABLE_LIST *open_table, *first;
1583 
1584  if (file->merge_insert_method != MERGE_INSERT_DISABLED)
1585  {
1586  packet->append(STRING_WITH_LEN(" INSERT_METHOD="));
1587  packet->append(get_type(&merge_insert_method,file->merge_insert_method-1));
1588  }
1589  /*
1590  There is no sence adding UNION clause in case there is no underlying
1591  tables specified.
1592  */
1593  if (file->open_tables == file->end_table)
1594  return;
1595  packet->append(STRING_WITH_LEN(" UNION=("));
1596 
1597  current_db= table->s->db.str;
1598  db_length= table->s->db.length;
1599 
1600  for (first= open_table= children_l;;
1601  open_table= open_table->next_global)
1602  {
1603  LEX_STRING db= { open_table->db, open_table->db_length };
1604 
1605  if (open_table != first)
1606  packet->append(',');
1607  /* Report database for mapped table if it isn't in current database */
1608  if (db.length &&
1609  (db_length != db.length ||
1610  strncmp(current_db, db.str, db.length)))
1611  {
1612  append_identifier(thd, packet, db.str, db.length);
1613  packet->append('.');
1614  }
1615  append_identifier(thd, packet, open_table->table_name,
1616  open_table->table_name_length);
1617  if (&open_table->next_global == children_last_l)
1618  break;
1619  }
1620  packet->append(')');
1621 }
1622 
1623 
1625  uint table_changes)
1626 {
1627  /*
1628  For myisammrg, we should always re-generate the mapping file as this
1629  is trivial to do
1630  */
1631  return COMPATIBLE_DATA_NO;
1632 }
1633 
1634 
1635 int ha_myisammrg::check(THD* thd, HA_CHECK_OPT* check_opt)
1636 {
1637  return this->file->children_attached ? HA_ADMIN_OK : HA_ADMIN_CORRUPT;
1638 }
1639 
1640 
1642 {
1643  return myrg_records(file);
1644 }
1645 
1646 
1647 extern int myrg_panic(enum ha_panic_function flag);
1648 int myisammrg_panic(handlerton *hton, ha_panic_function flag)
1649 {
1650  return myrg_panic(flag);
1651 }
1652 
1653 static int myisammrg_init(void *p)
1654 {
1655  handlerton *myisammrg_hton;
1656 
1657  myisammrg_hton= (handlerton *)p;
1658 
1659 #ifdef HAVE_PSI_INTERFACE
1660  init_myisammrg_psi_keys();
1661 #endif
1662 
1663  myisammrg_hton->db_type= DB_TYPE_MRG_MYISAM;
1664  myisammrg_hton->create= myisammrg_create_handler;
1665  myisammrg_hton->panic= myisammrg_panic;
1666  myisammrg_hton->flags= HTON_NO_PARTITION;
1667 
1668  return 0;
1669 }
1670 
1671 struct st_mysql_storage_engine myisammrg_storage_engine=
1672 { MYSQL_HANDLERTON_INTERFACE_VERSION };
1673 
1674 mysql_declare_plugin(myisammrg)
1675 {
1676  MYSQL_STORAGE_ENGINE_PLUGIN,
1677  &myisammrg_storage_engine,
1678  "MRG_MYISAM",
1679  "MySQL AB",
1680  "Collection of identical MyISAM tables",
1681  PLUGIN_LICENSE_GPL,
1682  myisammrg_init, /* Plugin Init */
1683  NULL, /* Plugin Deinit */
1684  0x0100, /* 1.0 */
1685  NULL, /* status variables */
1686  NULL, /* system variables */
1687  NULL, /* config options */
1688  0, /* flags */
1689 }
1690 mysql_declare_plugin_end;