MySQL 5.6.14 Source Code Document
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Groups Pages
dict0mem.cc
Go to the documentation of this file.
1 /*****************************************************************************
2 
3 Copyright (c) 1996, 2013, Oracle and/or its affiliates. All Rights Reserved.
4 Copyright (c) 2012, Facebook Inc.
5 
6 This program is free software; you can redistribute it and/or modify it under
7 the terms of the GNU General Public License as published by the Free Software
8 Foundation; version 2 of the License.
9 
10 This program is distributed in the hope that it will be useful, but WITHOUT
11 ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
12 FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
13 
14 You should have received a copy of the GNU General Public License along with
15 this program; if not, write to the Free Software Foundation, Inc.,
16 51 Franklin Street, Suite 500, Boston, MA 02110-1335 USA
17 
18 *****************************************************************************/
19 
20 /******************************************************************/
27 #include "dict0mem.h"
28 
29 #ifdef UNIV_NONINL
30 #include "dict0mem.ic"
31 #endif
32 
33 #include "rem0rec.h"
34 #include "data0type.h"
35 #include "mach0data.h"
36 #include "dict0dict.h"
37 #include "fts0priv.h"
38 #ifndef UNIV_HOTBACKUP
39 # include "ha_prototypes.h" /* innobase_casedn_str(),
40  innobase_get_lower_case_table_names */
41 # include "mysql_com.h" /* NAME_LEN */
42 # include "lock0lock.h"
43 #endif /* !UNIV_HOTBACKUP */
44 #ifdef UNIV_BLOB_DEBUG
45 # include "ut0rbt.h"
46 #endif /* UNIV_BLOB_DEBUG */
47 
48 #define DICT_HEAP_SIZE 100
51 #ifdef UNIV_PFS_MUTEX
52 /* Key to register autoinc_mutex with performance schema */
53 UNIV_INTERN mysql_pfs_key_t autoinc_mutex_key;
54 #endif /* UNIV_PFS_MUTEX */
55 
56 /**********************************************************************/
59 UNIV_INTERN
62 /*==================*/
63  const char* name,
64  ulint space,
66  ulint n_cols,
67  ulint flags,
68  ulint flags2)
69 {
72 
73  ut_ad(name);
74  ut_a(dict_tf_is_valid(flags));
75  ut_a(!(flags2 & ~DICT_TF2_BIT_MASK));
76 
78 
79  table = static_cast<dict_table_t*>(
80  mem_heap_zalloc(heap, sizeof(dict_table_t)));
81 
82  table->heap = heap;
83 
84  table->flags = (unsigned int) flags;
85  table->flags2 = (unsigned int) flags2;
86  table->name = static_cast<char*>(ut_malloc(strlen(name) + 1));
87  memcpy(table->name, name, strlen(name) + 1);
88  table->space = (unsigned int) space;
89  table->n_cols = (unsigned int) (n_cols + DATA_N_SYS_COLS);
90 
91  table->cols = static_cast<dict_col_t*>(
92  mem_heap_alloc(heap,
93  (n_cols + DATA_N_SYS_COLS)
94  * sizeof(dict_col_t)));
95 
96  ut_d(table->magic_n = DICT_TABLE_MAGIC_N);
97 
98 #ifndef UNIV_HOTBACKUP
99  table->autoinc_lock = static_cast<ib_lock_t*>(
100  mem_heap_alloc(heap, lock_get_size()));
101 
102  mutex_create(autoinc_mutex_key,
103  &table->autoinc_mutex, SYNC_DICT_AUTOINC_MUTEX);
104 
105  table->autoinc = 0;
106 
107  /* The number of transactions that are either waiting on the
108  AUTOINC lock or have been granted the lock. */
110 
111  /* If the table has an FTS index or we are in the process
112  of building one, create the table->fts */
113  if (dict_table_has_fts_index(table)
114  || DICT_TF2_FLAG_IS_SET(table, DICT_TF2_FTS_HAS_DOC_ID)
115  || DICT_TF2_FLAG_IS_SET(table, DICT_TF2_FTS_ADD_DOC_ID)) {
116  table->fts = fts_create(table);
117  table->fts->cache = fts_cache_create(table);
118  } else {
119  table->fts = NULL;
120  }
121 #endif /* !UNIV_HOTBACKUP */
122 
123  return(table);
124 }
125 
126 /****************************************************************/
128 UNIV_INTERN
129 void
131 /*================*/
133 {
134  ut_ad(table);
135  ut_ad(table->magic_n == DICT_TABLE_MAGIC_N);
136  ut_d(table->cached = FALSE);
137 
138  if (dict_table_has_fts_index(table)
139  || DICT_TF2_FLAG_IS_SET(table, DICT_TF2_FTS_HAS_DOC_ID)
140  || DICT_TF2_FLAG_IS_SET(table, DICT_TF2_FTS_ADD_DOC_ID)) {
141  if (table->fts) {
142  fts_free(table);
143  }
144 
146  }
147 #ifndef UNIV_HOTBACKUP
148  mutex_free(&(table->autoinc_mutex));
149 #endif /* UNIV_HOTBACKUP */
150  ut_free(table->name);
151  mem_heap_free(table->heap);
152 }
153 
154 /****************************************************************/
157 static
158 const char*
159 dict_add_col_name(
160 /*==============*/
161  const char* col_names,
163  ulint cols,
164  const char* name,
165  mem_heap_t* heap)
166 {
167  ulint old_len;
168  ulint new_len;
169  ulint total_len;
170  char* res;
171 
172  ut_ad(!cols == !col_names);
173 
174  /* Find out length of existing array. */
175  if (col_names) {
176  const char* s = col_names;
177  ulint i;
178 
179  for (i = 0; i < cols; i++) {
180  s += strlen(s) + 1;
181  }
182 
183  old_len = s - col_names;
184  } else {
185  old_len = 0;
186  }
187 
188  new_len = strlen(name) + 1;
189  total_len = old_len + new_len;
190 
191  res = static_cast<char*>(mem_heap_alloc(heap, total_len));
192 
193  if (old_len > 0) {
194  memcpy(res, col_names, old_len);
195  }
196 
197  memcpy(res + old_len, name, new_len);
198 
199  return(res);
200 }
201 
202 /**********************************************************************/
204 UNIV_INTERN
205 void
207 /*===================*/
209  mem_heap_t* heap,
210  const char* name,
211  ulint mtype,
212  ulint prtype,
213  ulint len)
214 {
215  dict_col_t* col;
216  ulint i;
217 
218  ut_ad(table);
219  ut_ad(table->magic_n == DICT_TABLE_MAGIC_N);
220  ut_ad(!heap == !name);
221 
222  i = table->n_def++;
223 
224  if (name) {
225  if (UNIV_UNLIKELY(table->n_def == table->n_cols)) {
226  heap = table->heap;
227  }
228  if (UNIV_LIKELY(i) && UNIV_UNLIKELY(!table->col_names)) {
229  /* All preceding column names are empty. */
230  char* s = static_cast<char*>(
231  mem_heap_zalloc(heap, table->n_def));
232 
233  table->col_names = s;
234  }
235 
236  table->col_names = dict_add_col_name(table->col_names,
237  i, name, heap);
238  }
239 
240  col = dict_table_get_nth_col(table, i);
241 
242  dict_mem_fill_column_struct(col, i, mtype, prtype, len);
243 }
244 
245 /**********************************************************************/
247 static __attribute__((nonnull))
248 void
249 dict_mem_table_col_rename_low(
250 /*==========================*/
252  unsigned i,
253  const char* to,
254  const char* s)
255 {
256  size_t from_len = strlen(s), to_len = strlen(to);
257 
258  ut_ad(i < table->n_def);
259  ut_ad(from_len <= NAME_LEN);
260  ut_ad(to_len <= NAME_LEN);
261 
262  if (from_len == to_len) {
263  /* The easy case: simply replace the column name in
264  table->col_names. */
265  strcpy(const_cast<char*>(s), to);
266  } else {
267  /* We need to adjust all affected index->field
268  pointers, as in dict_index_add_col(). First, copy
269  table->col_names. */
270  ulint prefix_len = s - table->col_names;
271 
272  for (; i < table->n_def; i++) {
273  s += strlen(s) + 1;
274  }
275 
276  ulint full_len = s - table->col_names;
277  char* col_names;
278 
279  if (to_len > from_len) {
280  col_names = static_cast<char*>(
282  table->heap,
283  full_len + to_len - from_len));
284 
285  memcpy(col_names, table->col_names, prefix_len);
286  } else {
287  col_names = const_cast<char*>(table->col_names);
288  }
289 
290  memcpy(col_names + prefix_len, to, to_len);
291  memmove(col_names + prefix_len + to_len,
292  table->col_names + (prefix_len + from_len),
293  full_len - (prefix_len + from_len));
294 
295  /* Replace the field names in every index. */
296  for (dict_index_t* index = dict_table_get_first_index(table);
297  index != NULL;
298  index = dict_table_get_next_index(index)) {
299  ulint n_fields = dict_index_get_n_fields(index);
300 
301  for (ulint i = 0; i < n_fields; i++) {
302  dict_field_t* field
303  = dict_index_get_nth_field(
304  index, i);
305  ulint name_ofs
306  = field->name - table->col_names;
307  if (name_ofs <= prefix_len) {
308  field->name = col_names + name_ofs;
309  } else {
310  ut_a(name_ofs < full_len);
311  field->name = col_names
312  + name_ofs + to_len - from_len;
313  }
314  }
315  }
316 
317  table->col_names = col_names;
318  }
319 
320  /* Replace the field names in every foreign key constraint. */
321  for (dict_foreign_t* foreign = UT_LIST_GET_FIRST(table->foreign_list);
322  foreign != NULL;
323  foreign = UT_LIST_GET_NEXT(foreign_list, foreign)) {
324  for (unsigned f = 0; f < foreign->n_fields; f++) {
325  /* These can point straight to
326  table->col_names, because the foreign key
327  constraints will be freed at the same time
328  when the table object is freed. */
329  foreign->foreign_col_names[f]
330  = dict_index_get_nth_field(
331  foreign->foreign_index, f)->name;
332  }
333  }
334 
335  for (dict_foreign_t* foreign = UT_LIST_GET_FIRST(
336  table->referenced_list);
337  foreign != NULL;
338  foreign = UT_LIST_GET_NEXT(referenced_list, foreign)) {
339  for (unsigned f = 0; f < foreign->n_fields; f++) {
340  /* foreign->referenced_col_names[] need to be
341  copies, because the constraint may become
342  orphan when foreign_key_checks=0 and the
343  parent table is dropped. */
344 
345  const char* col_name = dict_index_get_nth_field(
346  foreign->referenced_index, f)->name;
347 
348  if (strcmp(foreign->referenced_col_names[f],
349  col_name)) {
350  char** rc = const_cast<char**>(
351  foreign->referenced_col_names + f);
352  size_t col_name_len_1 = strlen(col_name) + 1;
353 
354  if (col_name_len_1 <= strlen(*rc) + 1) {
355  memcpy(*rc, col_name, col_name_len_1);
356  } else {
357  *rc = static_cast<char*>(
358  mem_heap_dup(
359  foreign->heap,
360  col_name,
361  col_name_len_1));
362  }
363  }
364  }
365  }
366 }
367 
368 /**********************************************************************/
370 UNIV_INTERN
371 void
373 /*======================*/
375  unsigned nth_col,
376  const char* from,
377  const char* to)
378 {
379  const char* s = table->col_names;
380 
381  ut_ad(nth_col < table->n_def);
382 
383  for (unsigned i = 0; i < nth_col; i++) {
384  size_t len = strlen(s);
385  ut_ad(len > 0);
386  s += len + 1;
387  }
388 
389  /* This could fail if the data dictionaries are out of sync.
390  Proceed with the renaming anyway. */
391  ut_ad(!strcmp(from, s));
392 
393  dict_mem_table_col_rename_low(table, nth_col, to, s);
394 }
395 
396 /**********************************************************************/
399 UNIV_INTERN
400 void
402 /*========================*/
403  dict_col_t* column,
405  ulint col_pos,
406  ulint mtype,
407  ulint prtype,
408  ulint col_len)
409 {
410 #ifndef UNIV_HOTBACKUP
411  ulint mbminlen;
412  ulint mbmaxlen;
413 #endif /* !UNIV_HOTBACKUP */
414 
415  column->ind = (unsigned int) col_pos;
416  column->ord_part = 0;
417  column->max_prefix = 0;
418  column->mtype = (unsigned int) mtype;
419  column->prtype = (unsigned int) prtype;
420  column->len = (unsigned int) col_len;
421 #ifndef UNIV_HOTBACKUP
422  dtype_get_mblen(mtype, prtype, &mbminlen, &mbmaxlen);
423  dict_col_set_mbminmaxlen(column, mbminlen, mbmaxlen);
424 #endif /* !UNIV_HOTBACKUP */
425 }
426 
427 /**********************************************************************/
430 UNIV_INTERN
433 /*==================*/
434  const char* table_name,
435  const char* index_name,
436  ulint space,
439  ulint type,
441  ulint n_fields)
442 {
444  mem_heap_t* heap;
445 
446  ut_ad(table_name && index_name);
447 
449 
450  index = static_cast<dict_index_t*>(
451  mem_heap_zalloc(heap, sizeof(*index)));
452 
453  dict_mem_fill_index_struct(index, heap, table_name, index_name,
454  space, type, n_fields);
455 
456  os_fast_mutex_init(zip_pad_mutex_key, &index->zip_pad.mutex);
457 
458  return(index);
459 }
460 
461 #ifndef UNIV_HOTBACKUP
462 /**********************************************************************/
465 UNIV_INTERN
468 /*=========================*/
469 {
470  dict_foreign_t* foreign;
471  mem_heap_t* heap;
472 
473  heap = mem_heap_create(100);
474 
475  foreign = static_cast<dict_foreign_t*>(
476  mem_heap_zalloc(heap, sizeof(dict_foreign_t)));
477 
478  foreign->heap = heap;
479 
480  return(foreign);
481 }
482 
483 /**********************************************************************/
488 UNIV_INTERN
489 void
491 /*===================================*/
492  dict_foreign_t* foreign,
493  ibool do_alloc)
494 {
496  if (do_alloc) {
497  ulint len;
498 
499  len = strlen(foreign->foreign_table_name) + 1;
500 
501  foreign->foreign_table_name_lookup =
502  static_cast<char*>(
503  mem_heap_alloc(foreign->heap, len));
504  }
505  strcpy(foreign->foreign_table_name_lookup,
506  foreign->foreign_table_name);
508  } else {
510  = foreign->foreign_table_name;
511  }
512 }
513 
514 /**********************************************************************/
519 UNIV_INTERN
520 void
522 /*======================================*/
523  dict_foreign_t* foreign,
524  ibool do_alloc)
525 {
527  if (do_alloc) {
528  ulint len;
529 
530  len = strlen(foreign->referenced_table_name) + 1;
531 
533  static_cast<char*>(
534  mem_heap_alloc(foreign->heap, len));
535  }
536  strcpy(foreign->referenced_table_name_lookup,
537  foreign->referenced_table_name);
539  } else {
541  = foreign->referenced_table_name;
542  }
543 }
544 #endif /* !UNIV_HOTBACKUP */
545 
546 /**********************************************************************/
550 UNIV_INTERN
551 void
553 /*=====================*/
554  dict_index_t* index,
555  const char* name,
556  ulint prefix_len)
559 {
560  dict_field_t* field;
561 
562  ut_ad(index);
563  ut_ad(index->magic_n == DICT_INDEX_MAGIC_N);
564 
565  index->n_def++;
566 
567  field = dict_index_get_nth_field(index, index->n_def - 1);
568 
569  field->name = name;
570  field->prefix_len = (unsigned int) prefix_len;
571 }
572 
573 /**********************************************************************/
575 UNIV_INTERN
576 void
578 /*================*/
579  dict_index_t* index)
580 {
581  ut_ad(index);
582  ut_ad(index->magic_n == DICT_INDEX_MAGIC_N);
583 #ifdef UNIV_BLOB_DEBUG
584  if (index->blobs) {
585  mutex_free(&index->blobs_mutex);
586  rbt_free(index->blobs);
587  }
588 #endif /* UNIV_BLOB_DEBUG */
589 
590  os_fast_mutex_free(&index->zip_pad.mutex);
591 
592  mem_heap_free(index->heap);
593 }
594 
595 /*******************************************************************/
598 UNIV_INTERN
599 char*
600 dict_mem_create_temporary_tablename(
601 /*================================*/
602  mem_heap_t* heap,
603  const char* dbtab,
604  table_id_t id)
605 {
606  const char* dbend = strchr(dbtab, '/');
607  ut_ad(dbend);
608  size_t dblen = dbend - dbtab + 1;
609  size_t size = tmp_file_prefix_length + 4 + 9 + 9 + dblen;
610 
611  char* name = static_cast<char*>(mem_heap_alloc(heap, size));
612  memcpy(name, dbtab, dblen);
613  ut_snprintf(name + dblen, size - dblen,
614  tmp_file_prefix "-ib" UINT64PF, id);
615  return(name);
616 }
617