~drizzle-trunk/drizzle/development

« back to all changes in this revision

Viewing changes to storage/innobase/dict/dict0dict.c

  • Committer: Monty Taylor
  • Date: 2008-09-15 17:24:04 UTC
  • Revision ID: monty@inaugust.com-20080915172404-ygh6hiyu0q7qpa9x
Removed strndup calls.

Show diffs side-by-side

added added

removed removed

Lines of Context:
26
26
#include "pars0sym.h"
27
27
#include "que0que.h"
28
28
#include "rem0cmp.h"
29
 
#include "row0merge.h"
30
29
#ifndef UNIV_HOTBACKUP
31
 
# if defined(BUILD_DRIZZLE)
32
 
#  include <mystrings/m_ctype.h>
33
 
# else
34
 
#  include "m_ctype.h" /* my_isspace() */
35
 
# endif /* DRIZZLE */
36
 
# include "ha_prototypes.h" /* innobase_strcasecmp() */
 
30
# include <mystrings/m_ctype.h> /* my_isspace() */
37
31
#endif /* !UNIV_HOTBACKUP */
38
32
 
39
33
#include <ctype.h>
40
34
 
41
 
/* the dictionary system */
42
 
UNIV_INTERN dict_sys_t* dict_sys        = NULL;
43
 
 
44
 
/* table create, drop, etc. reserve this in X-mode; implicit or
45
 
backround operations purge, rollback, foreign key checks reserve this
46
 
in S-mode; we cannot trust that MySQL protects implicit or background
47
 
operations a table drop since MySQL does not know of them; therefore
48
 
we need this; NOTE: a transaction which reserves this must keep book
49
 
on the mode in trx->dict_operation_lock_mode */
50
 
UNIV_INTERN rw_lock_t   dict_operation_lock;
51
 
 
 
35
dict_sys_t*     dict_sys        = NULL; /* the dictionary system */
 
36
 
 
37
rw_lock_t       dict_operation_lock;    /* table create, drop, etc. reserve
 
38
                                        this in X-mode; implicit or backround
 
39
                                        operations purge, rollback, foreign
 
40
                                        key checks reserve this in S-mode; we
 
41
                                        cannot trust that MySQL protects
 
42
                                        implicit or background operations
 
43
                                        a table drop since MySQL does not
 
44
                                        know of them; therefore we need this;
 
45
                                        NOTE: a transaction which reserves
 
46
                                        this must keep book on the mode in
 
47
                                        trx->dict_operation_lock_mode */
 
48
 
 
49
#define DICT_HEAP_SIZE          100     /* initial memory heap size when
 
50
                                        creating a table or index object */
52
51
#define DICT_POOL_PER_TABLE_HASH 512    /* buffer pool max size per table
53
52
                                        hash table fixed size in bytes */
 
53
#define DICT_POOL_PER_VARYING   4       /* buffer pool max size per data
 
54
                                        dictionary varying size in bytes */
54
55
 
55
56
/* Identifies generated InnoDB foreign key names */
56
57
static char     dict_ibfk[] = "_ibfk_";
61
62
 
62
63
NOTE: the prototype of this function is copied from ha_innodb.cc! If you change
63
64
this function, you MUST change also the prototype here! */
64
 
UNIV_INTERN
 
65
extern
65
66
void
66
67
innobase_convert_from_table_id(
67
68
/*===========================*/
74
75
 
75
76
NOTE: the prototype of this function is copied from ha_innodb.cc! If you change
76
77
this function, you MUST change also the prototype here! */
77
 
UNIV_INTERN
 
78
extern
78
79
void
79
80
innobase_convert_from_id(
80
81
/*=====================*/
83
84
        ulint           len);   /* in: length of 'to', in bytes;
84
85
                                should be at least 3 * strlen(to) + 1 */
85
86
/**********************************************************************
 
87
Compares NUL-terminated UTF-8 strings case insensitively.
 
88
 
 
89
NOTE: the prototype of this function is copied from ha_innodb.cc! If you change
 
90
this function, you MUST change also the prototype here! */
 
91
extern
 
92
int
 
93
innobase_strcasecmp(
 
94
/*================*/
 
95
                                /* out: 0 if a=b, <0 if a<b, >1 if a>b */
 
96
        const char*     a,      /* in: first string to compare */
 
97
        const char*     b);     /* in: second string to compare */
 
98
 
 
99
/**********************************************************************
86
100
Makes all characters in a NUL-terminated UTF-8 string lower case.
87
101
 
88
102
NOTE: the prototype of this function is copied from ha_innodb.cc! If you change
89
103
this function, you MUST change also the prototype here! */
90
 
UNIV_INTERN
 
104
extern
91
105
void
92
106
innobase_casedn_str(
93
107
/*================*/
105
119
        void*   mysql_thd);     /* in: MySQL thread handle */
106
120
#endif /* !UNIV_HOTBACKUP */
107
121
 
 
122
/**************************************************************************
 
123
Removes an index from the dictionary cache. */
 
124
static
 
125
void
 
126
dict_index_remove_from_cache(
 
127
/*=========================*/
 
128
        dict_table_t*   table,  /* in: table */
 
129
        dict_index_t*   index); /* in, own: index */
 
130
/***********************************************************************
 
131
Copies fields contained in index2 to index1. */
 
132
static
 
133
void
 
134
dict_index_copy(
 
135
/*============*/
 
136
        dict_index_t*   index1, /* in: index to copy to */
 
137
        dict_index_t*   index2, /* in: index to copy from */
 
138
        dict_table_t*   table,  /* in: table */
 
139
        ulint           start,  /* in: first position to copy */
 
140
        ulint           end);   /* in: last position to copy */
108
141
/***********************************************************************
109
142
Tries to find column names for the index and sets the col field of the
110
143
index. */
121
154
dict_index_t*
122
155
dict_index_build_internal_clust(
123
156
/*============================*/
124
 
                                        /* out, own: the internal
125
 
                                        representation of the clustered
126
 
                                        index */
127
 
        const dict_table_t*     table,  /* in: table */
128
 
        dict_index_t*           index); /* in: user representation of
129
 
                                        a clustered index */
 
157
                                /* out, own: the internal representation
 
158
                                of the clustered index */
 
159
        dict_table_t*   table,  /* in: table */
 
160
        dict_index_t*   index); /* in: user representation of a clustered
 
161
                                index */
130
162
/***********************************************************************
131
163
Builds the internal dictionary cache representation for a non-clustered
132
164
index, containing also system fields not defined by the user. */
134
166
dict_index_t*
135
167
dict_index_build_internal_non_clust(
136
168
/*================================*/
137
 
                                        /* out, own: the internal
138
 
                                        representation of the non-clustered
139
 
                                        index */
140
 
        const dict_table_t*     table,  /* in: table */
141
 
        dict_index_t*           index); /* in: user representation of
142
 
                                        a non-clustered index */
 
169
                                /* out, own: the internal representation
 
170
                                of the non-clustered index */
 
171
        dict_table_t*   table,  /* in: table */
 
172
        dict_index_t*   index); /* in: user representation of a non-clustered
 
173
                                index */
143
174
/**************************************************************************
144
175
Removes a foreign constraint struct from the dictionary cache. */
145
176
static
179
210
 
180
211
/* Stream for storing detailed information about the latest foreign key
181
212
and unique key errors */
182
 
UNIV_INTERN FILE*       dict_foreign_err_file           = NULL;
183
 
/* mutex protecting the foreign and unique error buffers */
184
 
UNIV_INTERN mutex_t     dict_foreign_err_mutex;
 
213
FILE*   dict_foreign_err_file           = NULL;
 
214
mutex_t dict_foreign_err_mutex;         /* mutex protecting the foreign
 
215
                                        and unique error buffers */
185
216
 
186
217
#ifndef UNIV_HOTBACKUP
187
218
/**********************************************************************
188
219
Makes all characters in a NUL-terminated UTF-8 string lower case. */
189
 
UNIV_INTERN
 
220
 
190
221
void
191
222
dict_casedn_str(
192
223
/*============*/
198
229
 
199
230
/************************************************************************
200
231
Checks if the database name in two table names is the same. */
201
 
UNIV_INTERN
 
232
 
202
233
ibool
203
234
dict_tables_have_same_db(
204
235
/*=====================*/
219
250
 
220
251
/************************************************************************
221
252
Return the end of table name where we have removed dbname and '/'. */
222
 
UNIV_INTERN
 
253
 
223
254
const char*
224
255
dict_remove_db_name(
225
256
/*================*/
235
266
 
236
267
/************************************************************************
237
268
Get the database name length in a table name. */
238
 
UNIV_INTERN
 
269
 
239
270
ulint
240
271
dict_get_db_name_len(
241
272
/*=================*/
251
282
 
252
283
/************************************************************************
253
284
Reserves the dictionary system mutex for MySQL. */
254
 
UNIV_INTERN
 
285
 
255
286
void
256
287
dict_mutex_enter_for_mysql(void)
257
288
/*============================*/
261
292
 
262
293
/************************************************************************
263
294
Releases the dictionary system mutex for MySQL. */
264
 
UNIV_INTERN
 
295
 
265
296
void
266
297
dict_mutex_exit_for_mysql(void)
267
298
/*===========================*/
271
302
 
272
303
/************************************************************************
273
304
Decrements the count of open MySQL handles to a table. */
274
 
UNIV_INTERN
 
305
 
275
306
void
276
307
dict_table_decrement_handle_count(
277
308
/*==============================*/
278
 
        dict_table_t*   table,          /* in/out: table */
279
 
        ibool           dict_locked)    /* in: TRUE=data dictionary locked */
 
309
        dict_table_t*   table)  /* in: table */
280
310
{
281
 
        if (!dict_locked) {
282
 
                mutex_enter(&dict_sys->mutex);
283
 
        }
 
311
        mutex_enter(&(dict_sys->mutex));
284
312
 
285
 
        ut_ad(mutex_own(&dict_sys->mutex));
286
313
        ut_a(table->n_mysql_handles_opened > 0);
287
314
 
288
315
        table->n_mysql_handles_opened--;
289
316
 
290
 
        if (!dict_locked) {
291
 
                mutex_exit(&dict_sys->mutex);
292
 
        }
 
317
        mutex_exit(&(dict_sys->mutex));
 
318
}
 
319
 
 
320
/*************************************************************************
 
321
Gets the column data type. */
 
322
 
 
323
void
 
324
dict_col_copy_type_noninline(
 
325
/*=========================*/
 
326
        const dict_col_t*       col,    /* in: column */
 
327
        dtype_t*                type)   /* out: data type */
 
328
{
 
329
        dict_col_copy_type(col, type);
 
330
}
 
331
 
 
332
/************************************************************************
 
333
Gets the nth column of a table. */
 
334
 
 
335
const dict_col_t*
 
336
dict_table_get_nth_col_noninline(
 
337
/*=============================*/
 
338
                                        /* out: pointer to column object */
 
339
        const dict_table_t*     table,  /* in: table */
 
340
        ulint                   pos)    /* in: position of column */
 
341
{
 
342
        return(dict_table_get_nth_col(table, pos));
 
343
}
 
344
 
 
345
/************************************************************************
 
346
Gets the first index on the table (the clustered index). */
 
347
 
 
348
dict_index_t*
 
349
dict_table_get_first_index_noninline(
 
350
/*=================================*/
 
351
                                /* out: index, NULL if none exists */
 
352
        dict_table_t*   table)  /* in: table */
 
353
{
 
354
        return(dict_table_get_first_index(table));
 
355
}
 
356
 
 
357
/************************************************************************
 
358
Gets the next index on the table. */
 
359
 
 
360
dict_index_t*
 
361
dict_table_get_next_index_noninline(
 
362
/*================================*/
 
363
                                /* out: index, NULL if none left */
 
364
        dict_index_t*   index)  /* in: index */
 
365
{
 
366
        return(dict_table_get_next_index(index));
 
367
}
 
368
 
 
369
/**************************************************************************
 
370
Returns an index object. */
 
371
 
 
372
dict_index_t*
 
373
dict_table_get_index_noninline(
 
374
/*===========================*/
 
375
                                /* out: index, NULL if does not exist */
 
376
        dict_table_t*   table,  /* in: table */
 
377
        const char*     name)   /* in: index name */
 
378
{
 
379
        return(dict_table_get_index(table, name));
293
380
}
294
381
 
295
382
/**************************************************************************
296
383
Returns a column's name. */
297
 
UNIV_INTERN
 
384
 
298
385
const char*
299
386
dict_table_get_col_name(
300
387
/*====================*/
325
412
 
326
413
/************************************************************************
327
414
Acquire the autoinc lock.*/
328
 
UNIV_INTERN
 
415
 
329
416
void
330
417
dict_table_autoinc_lock(
331
418
/*====================*/
332
 
        dict_table_t*   table)  /* in/out: table */
 
419
        dict_table_t*   table)
333
420
{
334
421
        mutex_enter(&table->autoinc_mutex);
335
422
}
337
424
/************************************************************************
338
425
Initializes the autoinc counter. It is not an error to initialize an already
339
426
initialized counter. */
340
 
UNIV_INTERN
 
427
 
341
428
void
342
429
dict_table_autoinc_initialize(
343
430
/*==========================*/
344
 
        dict_table_t*   table,  /* in/out: table */
345
 
        ib_uint64_t     value)  /* in: next value to assign to a row */
 
431
        dict_table_t*   table,  /* in: table */
 
432
        ib_longlong     value)  /* in: next value to assign to a row */
346
433
{
347
434
        ut_ad(mutex_own(&table->autoinc_mutex));
348
435
 
353
440
/************************************************************************
354
441
Reads the next autoinc value (== autoinc counter value), 0 if not yet
355
442
initialized. */
356
 
UNIV_INTERN
357
 
ib_uint64_t
 
443
 
 
444
ib_longlong
358
445
dict_table_autoinc_read(
359
446
/*====================*/
360
 
                                        /* out: value for a new row, or 0 */
361
 
        const dict_table_t*     table)  /* in: table */
 
447
                                /* out: value for a new row, or 0 */
 
448
        dict_table_t*   table)  /* in: table */
362
449
{
363
 
        ib_int64_t      value;
 
450
        ib_longlong     value;
364
451
 
365
452
        ut_ad(mutex_own(&table->autoinc_mutex));
366
453
 
377
464
/************************************************************************
378
465
Updates the autoinc counter if the value supplied is greater than the
379
466
current value. If not inited, does nothing. */
380
 
UNIV_INTERN
 
467
 
381
468
void
382
469
dict_table_autoinc_update(
383
470
/*======================*/
384
471
 
385
 
        dict_table_t*   table,  /* in/out: table */
386
 
        ib_uint64_t     value)  /* in: value which was assigned to a row */
 
472
        dict_table_t*   table,  /* in: table */
 
473
        ib_longlong     value)  /* in: value which was assigned to a row */
387
474
{
388
475
        if (table->autoinc_inited && value > table->autoinc) {
389
476
 
393
480
 
394
481
/************************************************************************
395
482
Release the autoinc lock.*/
396
 
UNIV_INTERN
 
483
 
397
484
void
398
485
dict_table_autoinc_unlock(
399
486
/*======================*/
400
 
        dict_table_t*   table)  /* in/out: table */
 
487
        dict_table_t*   table)  /* in: release autoinc lock for this table */
401
488
{
402
489
        mutex_exit(&table->autoinc_mutex);
403
490
}
404
491
 
405
 
/**************************************************************************
406
 
Looks for an index with the given table and index id.
407
 
NOTE that we do not reserve the dictionary mutex. */
408
 
UNIV_INTERN
409
 
dict_index_t*
410
 
dict_index_get_on_id_low(
411
 
/*=====================*/
412
 
                                /* out: index or NULL if not found
413
 
                                from cache */
414
 
        dict_table_t*   table,  /* in: table */
415
 
        dulint          id)     /* in: index id */
416
 
{
417
 
        dict_index_t*   index;
418
 
 
419
 
        index = dict_table_get_first_index(table);
420
 
 
421
 
        while (index) {
422
 
                if (0 == ut_dulint_cmp(id, index->id)) {
423
 
                        /* Found */
424
 
 
425
 
                        return(index);
426
 
                }
427
 
 
428
 
                index = dict_table_get_next_index(index);
429
 
        }
430
 
 
431
 
        return(NULL);
432
 
}
433
 
 
434
492
/************************************************************************
435
493
Looks for column n in an index. */
436
 
UNIV_INTERN
 
494
 
437
495
ulint
438
496
dict_index_get_nth_col_pos(
439
497
/*=======================*/
440
 
                                        /* out: position in internal
441
 
                                        representation of the index;
442
 
                                        if not contained, returns
443
 
                                        ULINT_UNDEFINED */
444
 
        const dict_index_t*     index,  /* in: index */
445
 
        ulint                   n)      /* in: column number */
 
498
                                /* out: position in internal representation
 
499
                                of the index; if not contained, returns
 
500
                                ULINT_UNDEFINED */
 
501
        dict_index_t*   index,  /* in: index */
 
502
        ulint           n)      /* in: column number */
446
503
{
447
504
        const dict_field_t*     field;
448
505
        const dict_col_t*       col;
454
511
 
455
512
        col = dict_table_get_nth_col(index->table, n);
456
513
 
457
 
        if (dict_index_is_clust(index)) {
 
514
        if (index->type & DICT_CLUSTERED) {
458
515
 
459
516
                return(dict_col_get_clust_pos(col, index));
460
517
        }
475
532
 
476
533
/************************************************************************
477
534
Returns TRUE if the index contains a column or a prefix of that column. */
478
 
UNIV_INTERN
 
535
 
479
536
ibool
480
537
dict_index_contains_col_or_prefix(
481
538
/*==============================*/
482
 
                                        /* out: TRUE if contains the column
483
 
                                        or its prefix */
484
 
        const dict_index_t*     index,  /* in: index */
485
 
        ulint                   n)      /* in: column number */
 
539
                                /* out: TRUE if contains the column or its
 
540
                                prefix */
 
541
        dict_index_t*   index,  /* in: index */
 
542
        ulint           n)      /* in: column number */
486
543
{
487
544
        const dict_field_t*     field;
488
545
        const dict_col_t*       col;
492
549
        ut_ad(index);
493
550
        ut_ad(index->magic_n == DICT_INDEX_MAGIC_N);
494
551
 
495
 
        if (dict_index_is_clust(index)) {
 
552
        if (index->type & DICT_CLUSTERED) {
496
553
 
497
554
                return(TRUE);
498
555
        }
518
575
column in index must be complete, or must contain a prefix longer than the
519
576
column in index2. That is, we must be able to construct the prefix in index2
520
577
from the prefix in index. */
521
 
UNIV_INTERN
 
578
 
522
579
ulint
523
580
dict_index_get_nth_field_pos(
524
581
/*=========================*/
525
 
                                        /* out: position in internal
526
 
                                        representation of the index;
527
 
                                        if not contained, returns
528
 
                                        ULINT_UNDEFINED */
529
 
        const dict_index_t*     index,  /* in: index from which to search */
530
 
        const dict_index_t*     index2, /* in: index */
531
 
        ulint                   n)      /* in: field number in index2 */
 
582
                                /* out: position in internal representation
 
583
                                of the index; if not contained, returns
 
584
                                ULINT_UNDEFINED */
 
585
        dict_index_t*   index,  /* in: index from which to search */
 
586
        dict_index_t*   index2, /* in: index */
 
587
        ulint           n)      /* in: field number in index2 */
532
588
{
533
 
        const dict_field_t*     field;
534
 
        const dict_field_t*     field2;
535
 
        ulint                   n_fields;
536
 
        ulint                   pos;
 
589
        dict_field_t*   field;
 
590
        dict_field_t*   field2;
 
591
        ulint           n_fields;
 
592
        ulint           pos;
537
593
 
538
594
        ut_ad(index);
539
595
        ut_ad(index->magic_n == DICT_INDEX_MAGIC_N);
559
615
 
560
616
/**************************************************************************
561
617
Returns a table object based on table id. */
562
 
UNIV_INTERN
 
618
 
563
619
dict_table_t*
564
620
dict_table_get_on_id(
565
621
/*=================*/
593
649
 
594
650
/************************************************************************
595
651
Looks for column n position in the clustered index. */
596
 
UNIV_INTERN
 
652
 
597
653
ulint
598
654
dict_table_get_nth_col_pos(
599
655
/*=======================*/
600
 
                                        /* out: position in internal
601
 
                                        representation of
602
 
                                        the clustered index */
603
 
        const dict_table_t*     table,  /* in: table */
604
 
        ulint                   n)      /* in: column number */
 
656
                                /* out: position in internal representation
 
657
                                of the clustered index */
 
658
        dict_table_t*   table,  /* in: table */
 
659
        ulint           n)      /* in: column number */
605
660
{
606
661
        return(dict_index_get_nth_col_pos(dict_table_get_first_index(table),
607
662
                                          n));
608
663
}
609
664
 
610
665
/************************************************************************
 
666
Check whether the table uses the compact page format. */
 
667
 
 
668
ibool
 
669
dict_table_is_comp_noninline(
 
670
/*=========================*/
 
671
                                        /* out: TRUE if table uses the
 
672
                                        compact page format */
 
673
        const dict_table_t*     table)  /* in: table */
 
674
{
 
675
        return(dict_table_is_comp(table));
 
676
}
 
677
 
 
678
/************************************************************************
611
679
Checks if a column is in the ordering columns of the clustered index of a
612
680
table. Column prefixes are treated like whole columns. */
613
 
UNIV_INTERN
 
681
 
614
682
ibool
615
683
dict_table_col_in_clustered_key(
616
684
/*============================*/
617
 
                                        /* out: TRUE if the column, or its
618
 
                                        prefix, is in the clustered key */
619
 
        const dict_table_t*     table,  /* in: table */
620
 
        ulint                   n)      /* in: column number */
 
685
                                /* out: TRUE if the column, or its prefix, is
 
686
                                in the clustered key */
 
687
        dict_table_t*   table,  /* in: table */
 
688
        ulint           n)      /* in: column number */
621
689
{
622
 
        const dict_index_t*     index;
 
690
        dict_index_t*           index;
623
691
        const dict_field_t*     field;
624
692
        const dict_col_t*       col;
625
693
        ulint                   pos;
647
715
 
648
716
/**************************************************************************
649
717
Inits the data dictionary module. */
650
 
UNIV_INTERN
 
718
 
651
719
void
652
720
dict_init(void)
653
721
/*===========*/
656
724
 
657
725
        mutex_create(&dict_sys->mutex, SYNC_DICT);
658
726
 
659
 
        dict_sys->table_hash = hash_create(buf_pool_get_curr_size()
 
727
        dict_sys->table_hash = hash_create(buf_pool_get_max_size()
660
728
                                           / (DICT_POOL_PER_TABLE_HASH
661
729
                                              * UNIV_WORD_SIZE));
662
 
        dict_sys->table_id_hash = hash_create(buf_pool_get_curr_size()
 
730
        dict_sys->table_id_hash = hash_create(buf_pool_get_max_size()
663
731
                                              / (DICT_POOL_PER_TABLE_HASH
664
732
                                                 * UNIV_WORD_SIZE));
665
733
        dict_sys->size = 0;
679
747
NOTE! This is a high-level function to be used mainly from outside the
680
748
'dict' directory. Inside this directory dict_table_get_low is usually the
681
749
appropriate function. */
682
 
UNIV_INTERN
 
750
 
683
751
dict_table_t*
684
752
dict_table_get(
685
753
/*===========*/
687
755
                                        does not exist */
688
756
        const char*     table_name,     /* in: table name */
689
757
        ibool           inc_mysql_count)
690
 
                                        /* in: whether to increment the open
 
758
                                        /* in: whether to increment the open
691
759
                                        handle count on the table */
692
760
{
693
761
        dict_table_t*   table;
716
784
 
717
785
/**************************************************************************
718
786
Adds system columns to a table object. */
719
 
UNIV_INTERN
 
787
 
720
788
void
721
789
dict_table_add_system_columns(
722
790
/*==========================*/
762
830
 
763
831
/**************************************************************************
764
832
Adds a table object to the dictionary cache. */
765
 
UNIV_INTERN
 
833
 
766
834
void
767
835
dict_table_add_to_cache(
768
836
/*====================*/
807
875
        /* Look for a table with the same name: error if such exists */
808
876
        {
809
877
                dict_table_t*   table2;
810
 
                HASH_SEARCH(name_hash, dict_sys->table_hash, fold,
811
 
                            dict_table_t*, table2,
 
878
                HASH_SEARCH(name_hash, dict_sys->table_hash, fold, table2,
812
879
                            (ut_strcmp(table2->name, table->name) == 0));
813
880
                ut_a(table2 == NULL);
814
881
        }
816
883
        /* Look for a table with the same id: error if such exists */
817
884
        {
818
885
                dict_table_t*   table2;
819
 
                HASH_SEARCH(id_hash, dict_sys->table_id_hash, id_fold,
820
 
                            dict_table_t*, table2,
 
886
                HASH_SEARCH(id_hash, dict_sys->table_id_hash, id_fold, table2,
821
887
                            (ut_dulint_cmp(table2->id, table->id) == 0));
822
888
                ut_a(table2 == NULL);
823
889
        }
839
905
Looks for an index with the given id. NOTE that we do not reserve
840
906
the dictionary mutex: this function is for emergency purposes like
841
907
printing info of a corrupt database page! */
842
 
UNIV_INTERN
 
908
 
843
909
dict_index_t*
844
910
dict_index_find_on_id_low(
845
911
/*======================*/
872
938
 
873
939
/**************************************************************************
874
940
Renames a table object. */
875
 
UNIV_INTERN
 
941
 
876
942
ibool
877
943
dict_table_rename_in_cache(
878
944
/*=======================*/
879
945
                                        /* out: TRUE if success */
880
 
        dict_table_t*   table,          /* in/out: table */
 
946
        dict_table_t*   table,          /* in: table */
881
947
        const char*     new_name,       /* in: new name */
882
948
        ibool           rename_also_foreigns)/* in: in ALTER TABLE we want
883
949
                                        to preserve the original table name
887
953
        dict_index_t*   index;
888
954
        ulint           fold;
889
955
        ulint           old_size;
890
 
        const char*     old_name;
 
956
        char*           old_name;
 
957
        ibool           success;
891
958
 
892
959
        ut_ad(table);
893
960
        ut_ad(mutex_own(&(dict_sys->mutex)));
894
961
 
895
962
        old_size = mem_heap_get_size(table->heap);
896
 
        old_name = table->name;
897
963
 
898
964
        fold = ut_fold_string(new_name);
899
965
 
900
966
        /* Look for a table with the same name: error if such exists */
901
967
        {
902
968
                dict_table_t*   table2;
903
 
                HASH_SEARCH(name_hash, dict_sys->table_hash, fold,
904
 
                            dict_table_t*, table2,
 
969
                HASH_SEARCH(name_hash, dict_sys->table_hash, fold, table2,
905
970
                            (ut_strcmp(table2->name, new_name) == 0));
906
 
                if (UNIV_LIKELY_NULL(table2)) {
907
 
                        ut_print_timestamp(stderr);
908
 
                        fputs("  InnoDB: Error: dictionary cache"
909
 
                              " already contains a table ", stderr);
910
 
                        ut_print_name(stderr, NULL, TRUE, new_name);
911
 
                        fputs("\n"
912
 
                              "InnoDB: cannot rename table ", stderr);
913
 
                        ut_print_name(stderr, NULL, TRUE, old_name);
914
 
                        putc('\n', stderr);
 
971
                if (table2) {
 
972
                        fprintf(stderr,
 
973
                                "InnoDB: Error: dictionary cache"
 
974
                                " already contains a table of name %s\n",
 
975
                                new_name);
915
976
                        return(FALSE);
916
977
                }
917
978
        }
921
982
 
922
983
        if (table->space != 0) {
923
984
                if (table->dir_path_of_temp_table != NULL) {
924
 
                        ut_print_timestamp(stderr);
925
 
                        fputs("  InnoDB: Error: trying to rename a"
926
 
                              " TEMPORARY TABLE ", stderr);
927
 
                        ut_print_name(stderr, NULL, TRUE, old_name);
928
 
                        fputs(" (", stderr);
929
 
                        ut_print_filename(stderr,
930
 
                                          table->dir_path_of_temp_table);
931
 
                        fputs(" )\n", stderr);
932
 
                        return(FALSE);
933
 
                } else if (!fil_rename_tablespace(old_name, table->space,
934
 
                                                  new_name)) {
 
985
                        fprintf(stderr,
 
986
                                "InnoDB: Error: trying to rename a table"
 
987
                                " %s (%s) created with CREATE\n"
 
988
                                "InnoDB: TEMPORARY TABLE\n",
 
989
                                table->name, table->dir_path_of_temp_table);
 
990
                        success = FALSE;
 
991
                } else {
 
992
                        success = fil_rename_tablespace(
 
993
                                table->name, table->space, new_name);
 
994
                }
 
995
 
 
996
                if (!success) {
 
997
 
935
998
                        return(FALSE);
936
999
                }
937
1000
        }
938
1001
 
939
1002
        /* Remove table from the hash tables of tables */
940
1003
        HASH_DELETE(dict_table_t, name_hash, dict_sys->table_hash,
941
 
                    ut_fold_string(old_name), table);
 
1004
                    ut_fold_string(table->name), table);
 
1005
        old_name = mem_heap_strdup(table->heap, table->name);
942
1006
        table->name = mem_heap_strdup(table->heap, new_name);
943
1007
 
944
1008
        /* Add table to hash table of tables */
1089
1153
/**************************************************************************
1090
1154
Change the id of a table object in the dictionary cache. This is used in
1091
1155
DISCARD TABLESPACE. */
1092
 
UNIV_INTERN
 
1156
 
1093
1157
void
1094
1158
dict_table_change_id_in_cache(
1095
1159
/*==========================*/
1096
 
        dict_table_t*   table,  /* in/out: table object already in cache */
 
1160
        dict_table_t*   table,  /* in: table object already in cache */
1097
1161
        dulint          new_id) /* in: new id to set */
1098
1162
{
1099
1163
        ut_ad(table);
1113
1177
 
1114
1178
/**************************************************************************
1115
1179
Removes a table object from the dictionary cache. */
1116
 
UNIV_INTERN
 
1180
 
1117
1181
void
1118
1182
dict_table_remove_from_cache(
1119
1183
/*=========================*/
1178
1242
        dict_mem_table_free(table);
1179
1243
}
1180
1244
 
 
1245
/*************************************************************************
 
1246
Gets the column position in the clustered index. */
 
1247
 
 
1248
ulint
 
1249
dict_col_get_clust_pos_noninline(
 
1250
/*=============================*/
 
1251
        const dict_col_t*       col,            /* in: table column */
 
1252
        const dict_index_t*     clust_index)    /* in: clustered index */
 
1253
{
 
1254
        return(dict_col_get_clust_pos(col, clust_index));
 
1255
}
 
1256
 
1181
1257
/********************************************************************
1182
1258
If the given column name is reserved for InnoDB system columns, return
1183
1259
TRUE. */
1184
 
UNIV_INTERN
 
1260
 
1185
1261
ibool
1186
1262
dict_col_name_is_reserved(
1187
1263
/*======================*/
1210
1286
        return(FALSE);
1211
1287
}
1212
1288
 
1213
 
/********************************************************************
1214
 
If an undo log record for this table might not fit on a single page,
1215
 
return TRUE. */
1216
 
static
1217
 
ibool
1218
 
dict_index_too_big_for_undo(
1219
 
/*========================*/
1220
 
                                                /* out: TRUE if the undo log
1221
 
                                                record could become too big */
1222
 
        const dict_table_t*     table,          /* in: table */
1223
 
        const dict_index_t*     new_index)      /* in: index */
1224
 
{
1225
 
        /* Make sure that all column prefixes will fit in the undo log record
1226
 
        in trx_undo_page_report_modify() right after trx_undo_page_init(). */
1227
 
 
1228
 
        ulint                   i;
1229
 
        const dict_index_t*     clust_index
1230
 
                = dict_table_get_first_index(table);
1231
 
        ulint                   undo_page_len
1232
 
                = TRX_UNDO_PAGE_HDR - TRX_UNDO_PAGE_HDR_SIZE
1233
 
                + 2 /* next record pointer */
1234
 
                + 1 /* type_cmpl */
1235
 
                + 11 /* trx->undo_no */ - 11 /* table->id */
1236
 
                + 1 /* rec_get_info_bits() */
1237
 
                + 11 /* DB_TRX_ID */
1238
 
                + 11 /* DB_ROLL_PTR */
1239
 
                + 10 + FIL_PAGE_DATA_END /* trx_undo_left() */
1240
 
                + 2/* pointer to previous undo log record */;
1241
 
 
1242
 
        if (UNIV_UNLIKELY(!clust_index)) {
1243
 
                ut_a(dict_index_is_clust(new_index));
1244
 
                clust_index = new_index;
1245
 
        }
1246
 
 
1247
 
        /* Add the size of the ordering columns in the
1248
 
        clustered index. */
1249
 
        for (i = 0; i < clust_index->n_uniq; i++) {
1250
 
                const dict_col_t*       col
1251
 
                        = dict_index_get_nth_col(clust_index, i);
1252
 
 
1253
 
                /* Use the maximum output size of
1254
 
                mach_write_compressed(), although the encoded
1255
 
                length should always fit in 2 bytes. */
1256
 
                undo_page_len += 5 + dict_col_get_max_size(col);
1257
 
        }
1258
 
 
1259
 
        /* Add the old values of the columns to be updated.
1260
 
        First, the amount and the numbers of the columns.
1261
 
        These are written by mach_write_compressed() whose
1262
 
        maximum output length is 5 bytes.  However, given that
1263
 
        the quantities are below REC_MAX_N_FIELDS (10 bits),
1264
 
        the maximum length is 2 bytes per item. */
1265
 
        undo_page_len += 2 * (dict_table_get_n_cols(table) + 1);
1266
 
 
1267
 
        for (i = 0; i < clust_index->n_def; i++) {
1268
 
                const dict_col_t*       col
1269
 
                        = dict_index_get_nth_col(clust_index, i);
1270
 
                ulint                   max_size
1271
 
                        = dict_col_get_max_size(col);
1272
 
                ulint                   fixed_size
1273
 
                        = dict_col_get_fixed_size(col);
1274
 
 
1275
 
                if (fixed_size) {
1276
 
                        /* Fixed-size columns are stored locally. */
1277
 
                        max_size = fixed_size;
1278
 
                } else if (max_size <= BTR_EXTERN_FIELD_REF_SIZE * 2) {
1279
 
                        /* Short columns are stored locally. */
1280
 
                } else if (!col->ord_part) {
1281
 
                        /* See if col->ord_part would be set
1282
 
                        because of new_index. */
1283
 
                        ulint   j;
1284
 
 
1285
 
                        for (j = 0; j < new_index->n_uniq; j++) {
1286
 
                                if (dict_index_get_nth_col(
1287
 
                                            new_index, j) == col) {
1288
 
 
1289
 
                                        goto is_ord_part;
1290
 
                                }
1291
 
                        }
1292
 
 
1293
 
                        /* This is not an ordering column in any index.
1294
 
                        Thus, it can be stored completely externally. */
1295
 
                        max_size = BTR_EXTERN_FIELD_REF_SIZE;
1296
 
                } else {
1297
 
is_ord_part:
1298
 
                        /* This is an ordering column in some index.
1299
 
                        A long enough prefix must be written to the
1300
 
                        undo log.  See trx_undo_page_fetch_ext(). */
1301
 
 
1302
 
                        if (max_size > REC_MAX_INDEX_COL_LEN) {
1303
 
                                max_size = REC_MAX_INDEX_COL_LEN;
1304
 
                        }
1305
 
 
1306
 
                        max_size += BTR_EXTERN_FIELD_REF_SIZE;
1307
 
                }
1308
 
 
1309
 
                undo_page_len += 5 + max_size;
1310
 
        }
1311
 
 
1312
 
        return(undo_page_len >= UNIV_PAGE_SIZE);
1313
 
}
1314
 
 
1315
1289
/**************************************************************************
1316
1290
Adds an index to the dictionary cache. */
1317
 
UNIV_INTERN
1318
 
ulint
 
1291
 
 
1292
void
1319
1293
dict_index_add_to_cache(
1320
1294
/*====================*/
1321
 
                                /* out: DB_SUCCESS or DB_TOO_BIG_RECORD */
1322
1295
        dict_table_t*   table,  /* in: table on which the index is */
1323
1296
        dict_index_t*   index,  /* in, own: index; NOTE! The index memory
1324
1297
                                object is freed in this function! */
1334
1307
        ut_ad(index->magic_n == DICT_INDEX_MAGIC_N);
1335
1308
 
1336
1309
        ut_ad(mem_heap_validate(index->heap));
1337
 
        ut_a(!dict_index_is_clust(index)
 
1310
 
 
1311
#ifdef UNIV_DEBUG
 
1312
        {
 
1313
                dict_index_t*   index2;
 
1314
                index2 = UT_LIST_GET_FIRST(table->indexes);
 
1315
 
 
1316
                while (index2 != NULL) {
 
1317
                        ut_ad(ut_strcmp(index->name, index2->name) != 0);
 
1318
 
 
1319
                        index2 = UT_LIST_GET_NEXT(indexes, index2);
 
1320
                }
 
1321
        }
 
1322
#endif /* UNIV_DEBUG */
 
1323
 
 
1324
        ut_a(!(index->type & DICT_CLUSTERED)
1338
1325
             || UT_LIST_GET_LEN(table->indexes) == 0);
1339
1326
 
1340
1327
        dict_index_find_cols(table, index);
1342
1329
        /* Build the cache internal representation of the index,
1343
1330
        containing also the added system fields */
1344
1331
 
1345
 
        if (dict_index_is_clust(index)) {
 
1332
        if (index->type & DICT_CLUSTERED) {
1346
1333
                new_index = dict_index_build_internal_clust(table, index);
1347
1334
        } else {
1348
1335
                new_index = dict_index_build_internal_non_clust(table, index);
1349
1336
        }
1350
1337
 
 
1338
        new_index->search_info = btr_search_info_create(new_index->heap);
 
1339
 
1351
1340
        /* Set the n_fields value in new_index to the actual defined
1352
1341
        number of fields in the cache internal representation */
1353
1342
 
1354
1343
        new_index->n_fields = new_index->n_def;
1355
1344
 
1356
 
        if (UNIV_UNLIKELY(index->type & DICT_UNIVERSAL)) {
1357
 
                n_ord = new_index->n_fields;
1358
 
        } else {
1359
 
                n_ord = new_index->n_uniq;
1360
 
        }
1361
 
 
1362
 
        for (i = 0; i < n_ord; i++) {
1363
 
                const dict_field_t*     field
1364
 
                        = dict_index_get_nth_field(new_index, i);
1365
 
                const dict_col_t*       col
1366
 
                        = dict_field_get_col(field);
1367
 
 
1368
 
                /* In dtuple_convert_big_rec(), variable-length columns
1369
 
                that are longer than BTR_EXTERN_FIELD_REF_SIZE * 2
1370
 
                may be chosen for external storage.  If the column appears
1371
 
                in an ordering column of an index, a longer prefix of
1372
 
                REC_MAX_INDEX_COL_LEN will be copied to the undo log
1373
 
                by trx_undo_page_report_modify() and
1374
 
                trx_undo_page_fetch_ext().  It suffices to check the
1375
 
                capacity of the undo log whenever new_index includes
1376
 
                a column prefix on a column that may be stored externally. */
1377
 
 
1378
 
                if (field->prefix_len /* prefix index */
1379
 
                    && !col->ord_part /* not yet ordering column */
1380
 
                    && !dict_col_get_fixed_size(col) /* variable-length */
1381
 
                    && dict_col_get_max_size(col)
1382
 
                    > BTR_EXTERN_FIELD_REF_SIZE * 2 /* long enough */) {
1383
 
 
1384
 
                        if (dict_index_too_big_for_undo(table, new_index)) {
1385
 
                                /* An undo log record might not fit in
1386
 
                                a single page.  Refuse to create this index. */
1387
 
                                dict_mem_index_free(new_index);
1388
 
                                dict_mem_index_free(index);
1389
 
                                return(DB_TOO_BIG_RECORD);
1390
 
                        }
1391
 
 
1392
 
                        break;
1393
 
                }
1394
 
        }
1395
 
 
1396
 
        /* Flag the ordering columns */
1397
 
 
1398
 
        for (i = 0; i < n_ord; i++) {
1399
 
 
1400
 
                dict_index_get_nth_field(new_index, i)->col->ord_part = 1;
1401
 
        }
1402
 
 
1403
1345
        /* Add the new index as the last index for the table */
1404
1346
 
1405
1347
        UT_LIST_ADD_LAST(indexes, table->indexes, new_index);
1406
1348
        new_index->table = table;
1407
1349
        new_index->table_name = table->name;
1408
1350
 
1409
 
        new_index->search_info = btr_search_info_create(new_index->heap);
1410
 
 
1411
 
        new_index->stat_index_size = 1;
1412
 
        new_index->stat_n_leaf_pages = 1;
1413
 
 
1414
 
        new_index->page = page_no;
 
1351
        /* Increment the ord_part counts in columns which are ordering */
 
1352
 
 
1353
        if (UNIV_UNLIKELY(index->type & DICT_UNIVERSAL)) {
 
1354
                n_ord = new_index->n_fields;
 
1355
        } else {
 
1356
                n_ord = dict_index_get_n_unique(new_index);
 
1357
        }
 
1358
 
 
1359
        for (i = 0; i < n_ord; i++) {
 
1360
 
 
1361
                dict_index_get_nth_field(new_index, i)->col->ord_part = 1;
 
1362
        }
 
1363
 
 
1364
        new_index->page = (unsigned int) page_no;
1415
1365
        rw_lock_create(&new_index->lock, SYNC_INDEX_TREE);
1416
1366
 
1417
1367
        if (!UNIV_UNLIKELY(new_index->type & DICT_UNIVERSAL)) {
1419
1369
                new_index->stat_n_diff_key_vals = mem_heap_alloc(
1420
1370
                        new_index->heap,
1421
1371
                        (1 + dict_index_get_n_unique(new_index))
1422
 
                        * sizeof(ib_int64_t));
 
1372
                        * sizeof(ib_longlong));
1423
1373
                /* Give some sensible values to stat_n_... in case we do
1424
1374
                not calculate statistics quickly enough */
1425
1375
 
1432
1382
        dict_sys->size += mem_heap_get_size(new_index->heap);
1433
1383
 
1434
1384
        dict_mem_index_free(index);
1435
 
 
1436
 
        return(DB_SUCCESS);
1437
1385
}
1438
1386
 
1439
1387
/**************************************************************************
1440
1388
Removes an index from the dictionary cache. */
1441
 
UNIV_INTERN
 
1389
static
1442
1390
void
1443
1391
dict_index_remove_from_cache(
1444
1392
/*=========================*/
1445
 
        dict_table_t*   table,  /* in/out: table */
 
1393
        dict_table_t*   table,  /* in: table */
1446
1394
        dict_index_t*   index)  /* in, own: index */
1447
1395
{
1448
1396
        ulint           size;
1489
1437
                for (j = 0; j < table->n_cols; j++) {
1490
1438
                        if (!strcmp(dict_table_get_col_name(table, j),
1491
1439
                                    field->name)) {
1492
 
                                field->col = dict_table_get_nth_col(table, j);
 
1440
                                field->col = (dict_col_t*)
 
1441
                                        dict_table_get_nth_col(table, j);
1493
1442
 
1494
1443
                                goto found;
1495
1444
                        }
1498
1447
                /* It is an error not to find a matching column. */
1499
1448
                ut_error;
1500
1449
 
1501
 
found:
 
1450
        found:
1502
1451
                ;
1503
1452
        }
1504
1453
}
1505
1454
 
1506
1455
/***********************************************************************
1507
1456
Adds a column to index. */
1508
 
UNIV_INTERN
 
1457
 
1509
1458
void
1510
1459
dict_index_add_col(
1511
1460
/*===============*/
1512
 
        dict_index_t*           index,          /* in/out: index */
1513
 
        const dict_table_t*     table,          /* in: table */
1514
 
        dict_col_t*             col,            /* in: column */
1515
 
        ulint                   prefix_len)     /* in: column prefix length */
 
1461
        dict_index_t*   index,          /* in: index */
 
1462
        dict_table_t*   table,          /* in: table */
 
1463
        dict_col_t*     col,            /* in: column */
 
1464
        ulint           prefix_len)     /* in: column prefix length */
1516
1465
{
1517
1466
        dict_field_t*   field;
1518
1467
        const char*     col_name;
1555
1504
void
1556
1505
dict_index_copy(
1557
1506
/*============*/
1558
 
        dict_index_t*           index1, /* in: index to copy to */
1559
 
        dict_index_t*           index2, /* in: index to copy from */
1560
 
        const dict_table_t*     table,  /* in: table */
1561
 
        ulint                   start,  /* in: first position to copy */
1562
 
        ulint                   end)    /* in: last position to copy */
 
1507
        dict_index_t*   index1, /* in: index to copy to */
 
1508
        dict_index_t*   index2, /* in: index to copy from */
 
1509
        dict_table_t*   table,  /* in: table */
 
1510
        ulint           start,  /* in: first position to copy */
 
1511
        ulint           end)    /* in: last position to copy */
1563
1512
{
1564
1513
        dict_field_t*   field;
1565
1514
        ulint           i;
1576
1525
 
1577
1526
/***********************************************************************
1578
1527
Copies types of fields contained in index to tuple. */
1579
 
UNIV_INTERN
 
1528
 
1580
1529
void
1581
1530
dict_index_copy_types(
1582
1531
/*==================*/
1583
 
        dtuple_t*               tuple,          /* in/out: data tuple */
1584
 
        const dict_index_t*     index,          /* in: index */
1585
 
        ulint                   n_fields)       /* in: number of
1586
 
                                                field types to copy */
 
1532
        dtuple_t*       tuple,          /* in: data tuple */
 
1533
        dict_index_t*   index,          /* in: index */
 
1534
        ulint           n_fields)       /* in: number of field types to copy */
1587
1535
{
1588
1536
        ulint           i;
1589
1537
 
1594
1542
        }
1595
1543
 
1596
1544
        for (i = 0; i < n_fields; i++) {
1597
 
                const dict_field_t*     ifield;
1598
 
                dtype_t*                dfield_type;
 
1545
                dict_field_t*   ifield;
 
1546
                dtype_t*        dfield_type;
1599
1547
 
1600
1548
                ifield = dict_index_get_nth_field(index, i);
1601
1549
                dfield_type = dfield_get_type(dtuple_get_nth_field(tuple, i));
1604
1552
}
1605
1553
 
1606
1554
/***********************************************************************
1607
 
Copies types of columns contained in table to tuple and sets all
1608
 
fields of the tuple to the SQL NULL value.  This function should
1609
 
be called right after dtuple_create(). */
1610
 
UNIV_INTERN
 
1555
Copies types of columns contained in table to tuple. */
 
1556
 
1611
1557
void
1612
1558
dict_table_copy_types(
1613
1559
/*==================*/
1614
 
        dtuple_t*               tuple,  /* in/out: data tuple */
1615
 
        const dict_table_t*     table)  /* in: table */
 
1560
        dtuple_t*       tuple,  /* in: data tuple */
 
1561
        dict_table_t*   table)  /* in: index */
1616
1562
{
 
1563
        dtype_t*        dfield_type;
1617
1564
        ulint           i;
1618
1565
 
1619
1566
        for (i = 0; i < dtuple_get_n_fields(tuple); i++) {
1620
1567
 
1621
 
                dfield_t*       dfield  = dtuple_get_nth_field(tuple, i);
1622
 
                dtype_t*        dtype   = dfield_get_type(dfield);
1623
 
 
1624
 
                dfield_set_null(dfield);
1625
 
                dict_col_copy_type(dict_table_get_nth_col(table, i), dtype);
 
1568
                dfield_type = dfield_get_type(dtuple_get_nth_field(tuple, i));
 
1569
                dict_col_copy_type(dict_table_get_nth_col(table, i),
 
1570
                                   dfield_type);
1626
1571
        }
1627
1572
}
1628
1573
 
1633
1578
dict_index_t*
1634
1579
dict_index_build_internal_clust(
1635
1580
/*============================*/
1636
 
                                        /* out, own: the internal
1637
 
                                        representation of the clustered
1638
 
                                        index */
1639
 
        const dict_table_t*     table,  /* in: table */
1640
 
        dict_index_t*           index)  /* in: user representation of
1641
 
                                        a clustered index */
 
1581
                                /* out, own: the internal representation
 
1582
                                of the clustered index */
 
1583
        dict_table_t*   table,  /* in: table */
 
1584
        dict_index_t*   index)  /* in: user representation of a clustered
 
1585
                                index */
1642
1586
{
1643
1587
        dict_index_t*   new_index;
1644
1588
        dict_field_t*   field;
1648
1592
        ibool*          indexed;
1649
1593
 
1650
1594
        ut_ad(table && index);
1651
 
        ut_ad(dict_index_is_clust(index));
 
1595
        ut_ad(index->type & DICT_CLUSTERED);
1652
1596
        ut_ad(mutex_own(&(dict_sys->mutex)));
1653
1597
        ut_ad(table->magic_n == DICT_TABLE_MAGIC_N);
1654
1598
 
1673
1617
 
1674
1618
                new_index->n_uniq = REC_MAX_N_FIELDS;
1675
1619
 
1676
 
        } else if (dict_index_is_unique(index)) {
 
1620
        } else if (index->type & DICT_UNIQUE) {
1677
1621
                /* Only the fields defined so far are needed to identify
1678
1622
                the index entry uniquely */
1679
1623
 
1685
1629
 
1686
1630
        new_index->trx_id_offset = 0;
1687
1631
 
1688
 
        if (!dict_index_is_ibuf(index)) {
 
1632
        if (!(index->type & DICT_IBUF)) {
1689
1633
                /* Add system columns, trx id first */
1690
1634
 
1691
1635
                trx_id_pos = new_index->n_def;
1700
1644
# error "DATA_ROLL_PTR != 2"
1701
1645
#endif
1702
1646
 
1703
 
                if (!dict_index_is_unique(index)) {
1704
 
                        dict_index_add_col(new_index, table,
 
1647
                if (!(index->type & DICT_UNIQUE)) {
 
1648
                        dict_index_add_col(new_index, table, (dict_col_t*)
1705
1649
                                           dict_table_get_sys_col(
1706
1650
                                                   table, DATA_ROW_ID),
1707
1651
                                           0);
1708
1652
                        trx_id_pos++;
1709
1653
                }
1710
1654
 
1711
 
                dict_index_add_col(new_index, table,
 
1655
                dict_index_add_col(new_index, table, (dict_col_t*)
1712
1656
                                   dict_table_get_sys_col(table, DATA_TRX_ID),
1713
1657
                                   0);
1714
1658
 
1715
 
                dict_index_add_col(new_index, table,
 
1659
                dict_index_add_col(new_index, table, (dict_col_t*)
1716
1660
                                   dict_table_get_sys_col(table,
1717
1661
                                                          DATA_ROLL_PTR),
1718
1662
                                   0);
1741
1685
        }
1742
1686
 
1743
1687
        /* Remember the table columns already contained in new_index */
1744
 
        indexed = mem_zalloc(table->n_cols * sizeof *indexed);
 
1688
        indexed = mem_alloc(table->n_cols * sizeof *indexed);
 
1689
        memset(indexed, 0, table->n_cols * sizeof *indexed);
1745
1690
 
1746
 
        /* Mark the table columns already contained in new_index */
 
1691
        /* Mark with 0 the table columns already contained in new_index */
1747
1692
        for (i = 0; i < new_index->n_def; i++) {
1748
1693
 
1749
1694
                field = dict_index_get_nth_field(new_index, i);
1761
1706
        there */
1762
1707
        for (i = 0; i + DATA_N_SYS_COLS < (ulint) table->n_cols; i++) {
1763
1708
 
1764
 
                dict_col_t*     col = dict_table_get_nth_col(table, i);
 
1709
                dict_col_t*     col = (dict_col_t*)
 
1710
                        dict_table_get_nth_col(table, i);
1765
1711
                ut_ad(col->mtype != DATA_SYS);
1766
1712
 
1767
1713
                if (!indexed[col->ind]) {
1771
1717
 
1772
1718
        mem_free(indexed);
1773
1719
 
1774
 
        ut_ad(dict_index_is_ibuf(index)
 
1720
        ut_ad((index->type & DICT_IBUF)
1775
1721
              || (UT_LIST_GET_LEN(table->indexes) == 0));
1776
1722
 
1777
1723
        new_index->cached = TRUE;
1786
1732
dict_index_t*
1787
1733
dict_index_build_internal_non_clust(
1788
1734
/*================================*/
1789
 
                                        /* out, own: the internal
1790
 
                                        representation of the non-clustered
1791
 
                                        index */
1792
 
        const dict_table_t*     table,  /* in: table */
1793
 
        dict_index_t*           index)  /* in: user representation of
1794
 
                                        a non-clustered index */
 
1735
                                /* out, own: the internal representation
 
1736
                                of the non-clustered index */
 
1737
        dict_table_t*   table,  /* in: table */
 
1738
        dict_index_t*   index)  /* in: user representation of a non-clustered
 
1739
                                index */
1795
1740
{
1796
1741
        dict_field_t*   field;
1797
1742
        dict_index_t*   new_index;
1800
1745
        ibool*          indexed;
1801
1746
 
1802
1747
        ut_ad(table && index);
1803
 
        ut_ad(!dict_index_is_clust(index));
 
1748
        ut_ad(0 == (index->type & DICT_CLUSTERED));
1804
1749
        ut_ad(mutex_own(&(dict_sys->mutex)));
1805
1750
        ut_ad(table->magic_n == DICT_TABLE_MAGIC_N);
1806
1751
 
1808
1753
        clust_index = UT_LIST_GET_FIRST(table->indexes);
1809
1754
 
1810
1755
        ut_ad(clust_index);
1811
 
        ut_ad(dict_index_is_clust(clust_index));
 
1756
        ut_ad(clust_index->type & DICT_CLUSTERED);
1812
1757
        ut_ad(!(clust_index->type & DICT_UNIVERSAL));
1813
1758
 
1814
1759
        /* Create a new index */
1827
1772
        dict_index_copy(new_index, index, table, 0, index->n_fields);
1828
1773
 
1829
1774
        /* Remember the table columns already contained in new_index */
1830
 
        indexed = mem_zalloc(table->n_cols * sizeof *indexed);
 
1775
        indexed = mem_alloc(table->n_cols * sizeof *indexed);
 
1776
        memset(indexed, 0, table->n_cols * sizeof *indexed);
1831
1777
 
1832
 
        /* Mark the table columns already contained in new_index */
 
1778
        /* Mark with 0 table columns already contained in new_index */
1833
1779
        for (i = 0; i < new_index->n_def; i++) {
1834
1780
 
1835
1781
                field = dict_index_get_nth_field(new_index, i);
1858
1804
 
1859
1805
        mem_free(indexed);
1860
1806
 
1861
 
        if (dict_index_is_unique(index)) {
 
1807
        if ((index->type) & DICT_UNIQUE) {
1862
1808
                new_index->n_uniq = index->n_fields;
1863
1809
        } else {
1864
1810
                new_index->n_uniq = new_index->n_def;
1878
1824
 
1879
1825
/*************************************************************************
1880
1826
Checks if a table is referenced by foreign keys. */
1881
 
UNIV_INTERN
 
1827
 
1882
1828
ibool
1883
 
dict_table_is_referenced_by_foreign_key(
1884
 
/*====================================*/
1885
 
                                        /* out: TRUE if table is referenced
1886
 
                                        by a foreign key */
1887
 
        const dict_table_t*     table)  /* in: InnoDB table */
1888
 
{
1889
 
        return(UT_LIST_GET_LEN(table->referenced_list) > 0);
1890
 
}
1891
 
 
1892
 
/*************************************************************************
1893
 
Check if the index is referenced by a foreign key, if TRUE return foreign
1894
 
else return NULL */
1895
 
UNIV_INTERN
1896
 
dict_foreign_t*
1897
 
dict_table_get_referenced_constraint(
 
1829
dict_table_referenced_by_foreign_key(
1898
1830
/*=================================*/
1899
 
                                /* out: pointer to foreign key struct if index
1900
 
                                is defined for foreign key, otherwise NULL */
1901
 
        dict_table_t*   table,  /* in: InnoDB table */
1902
 
        dict_index_t*   index)  /* in: InnoDB index */
1903
 
{
1904
 
        dict_foreign_t* foreign  = NULL;
1905
 
 
1906
 
        ut_ad(index && table);
1907
 
 
1908
 
        /* If the referenced list is empty, nothing to do */
1909
 
 
1910
 
        if (UT_LIST_GET_LEN(table->referenced_list) == 0) {
1911
 
 
1912
 
                return(NULL);
1913
 
        }
1914
 
 
1915
 
        foreign = UT_LIST_GET_FIRST(table->referenced_list);
1916
 
 
1917
 
        while (foreign) {
1918
 
                if (foreign->referenced_index == index
1919
 
                    || foreign->referenced_index == index) {
1920
 
 
1921
 
                        return(foreign);
1922
 
                }
1923
 
 
1924
 
                foreign = UT_LIST_GET_NEXT(referenced_list, foreign);
1925
 
        }
1926
 
 
1927
 
        return(NULL);
1928
 
}
1929
 
 
1930
 
/*************************************************************************
1931
 
Checks if a index is defined for a foreign key constraint. Index is a part
1932
 
of a foreign key constraint if the index is referenced by foreign key
1933
 
or index is a foreign key index. */
1934
 
UNIV_INTERN
1935
 
dict_foreign_t*
1936
 
dict_table_get_foreign_constraint(
1937
 
/*==============================*/
1938
 
                                /* out: pointer to foreign key struct if index
1939
 
                                is defined for foreign key, otherwise NULL */
1940
 
        dict_table_t*   table,  /* in: InnoDB table */
1941
 
        dict_index_t*   index)  /* in: InnoDB index */
1942
 
{
1943
 
        dict_foreign_t* foreign  = NULL;
1944
 
 
1945
 
        ut_ad(index && table);
1946
 
 
1947
 
        /* If list empty then nothgin to do */
1948
 
 
1949
 
        if (UT_LIST_GET_LEN(table->foreign_list) == 0) {
1950
 
 
1951
 
                return(NULL);
1952
 
        }
1953
 
 
1954
 
        /* Check whether this index is defined for a foreign key */
1955
 
 
1956
 
        foreign = UT_LIST_GET_FIRST(table->foreign_list);
1957
 
 
1958
 
        while (foreign) {
1959
 
                if (foreign->foreign_index == index
1960
 
                    || foreign->referenced_index == index) {
1961
 
 
1962
 
                        return(foreign);
1963
 
                }
1964
 
 
1965
 
                foreign = UT_LIST_GET_NEXT(foreign_list, foreign);
1966
 
        }
1967
 
 
1968
 
        return(NULL);
 
1831
                                /* out: TRUE if table is referenced by a
 
1832
                                foreign key */
 
1833
        dict_table_t*   table)  /* in: InnoDB table */
 
1834
{
 
1835
        if (UT_LIST_GET_LEN(table->referenced_list) > 0) {
 
1836
 
 
1837
                return(TRUE);
 
1838
        }
 
1839
 
 
1840
        return(FALSE);
1969
1841
}
1970
1842
 
1971
1843
/*************************************************************************
2005
1877
        dict_foreign_free(foreign);
2006
1878
}
2007
1879
 
2008
 
#ifndef UNIV_HOTBACKUP
2009
1880
/**************************************************************************
2010
1881
Looks for the foreign constraint from the foreign and referenced lists
2011
1882
of a table. */
2046
1917
        return(NULL);
2047
1918
}
2048
1919
 
 
1920
#ifndef UNIV_HOTBACKUP
2049
1921
/*************************************************************************
2050
1922
Tries to find an index whose first fields are the columns in the array,
2051
 
in the same order and is not marked for deletion and is not the same
2052
 
as types_idx. */
 
1923
in the same order. */
2053
1924
static
2054
1925
dict_index_t*
2055
1926
dict_foreign_find_index(
2068
1939
                                be declared NOT NULL */
2069
1940
{
2070
1941
        dict_index_t*   index;
 
1942
        dict_field_t*   field;
 
1943
        const char*     col_name;
 
1944
        ulint           i;
2071
1945
 
2072
1946
        index = dict_table_get_first_index(table);
2073
1947
 
2074
1948
        while (index != NULL) {
2075
 
                /* Ignore matches that refer to the same instance
2076
 
                or the index is to be dropped */
2077
 
                if (index->to_be_dropped || types_idx == index) {
2078
 
 
2079
 
                        goto next_rec;
2080
 
 
2081
 
                } else if (dict_index_get_n_fields(index) >= n_cols) {
2082
 
                        ulint           i;
 
1949
                if (dict_index_get_n_fields(index) >= n_cols) {
2083
1950
 
2084
1951
                        for (i = 0; i < n_cols; i++) {
2085
 
                                dict_field_t*   field;
2086
 
                                const char*     col_name;
2087
 
 
2088
1952
                                field = dict_index_get_nth_field(index, i);
2089
1953
 
2090
1954
                                col_name = dict_table_get_col_name(
2125
1989
                        }
2126
1990
                }
2127
1991
 
2128
 
next_rec:
2129
1992
                index = dict_table_get_next_index(index);
2130
1993
        }
2131
1994
 
2133
1996
}
2134
1997
 
2135
1998
/**************************************************************************
2136
 
Returns an index object by matching on the name and column names and
2137
 
if more than one index matches return the index with the max id */
2138
 
UNIV_INTERN
2139
 
dict_index_t*
2140
 
dict_table_get_index_by_max_id(
2141
 
/*===========================*/
2142
 
                                /* out: matching index, NULL if not found */
2143
 
        dict_table_t*   table,  /* in: table */
2144
 
        const char*     name,   /* in: the index name to find */
2145
 
        const char**    columns,/* in: array of column names */
2146
 
        ulint           n_cols) /* in: number of columns */
2147
 
{
2148
 
        dict_index_t*   index;
2149
 
        dict_index_t*   found;
2150
 
 
2151
 
        found = NULL;
2152
 
        index = dict_table_get_first_index(table);
2153
 
 
2154
 
        while (index != NULL) {
2155
 
                if (ut_strcmp(index->name, name) == 0
2156
 
                    && dict_index_get_n_ordering_defined_by_user(index)
2157
 
                    == n_cols) {
2158
 
 
2159
 
                        ulint           i;
2160
 
 
2161
 
                        for (i = 0; i < n_cols; i++) {
2162
 
                                dict_field_t*   field;
2163
 
                                const char*     col_name;
2164
 
 
2165
 
                                field = dict_index_get_nth_field(index, i);
2166
 
 
2167
 
                                col_name = dict_table_get_col_name(
2168
 
                                        table, dict_col_get_no(field->col));
2169
 
 
2170
 
                                if (0 != innobase_strcasecmp(
2171
 
                                            columns[i], col_name)) {
2172
 
 
2173
 
                                        break;
2174
 
                                }
2175
 
                        }
2176
 
 
2177
 
                        if (i == n_cols) {
2178
 
                                /* We found a matching index, select
2179
 
                                the index with the higher id*/
2180
 
 
2181
 
                                if (!found
2182
 
                                    || ut_dulint_cmp(index->id, found->id) > 0) {
2183
 
 
2184
 
                                        found = index;
2185
 
                                }
2186
 
                        }
2187
 
                }
2188
 
 
2189
 
                index = dict_table_get_next_index(index);
2190
 
        }
2191
 
 
2192
 
        return(found);
2193
 
}
2194
 
 
2195
 
/**************************************************************************
2196
1999
Report an error in a foreign key definition. */
2197
2000
static
2198
2001
void
2240
2043
the object if there already is an object with the same identifier in.
2241
2044
At least one of the foreign table and the referenced table must already
2242
2045
be in the dictionary cache! */
2243
 
UNIV_INTERN
 
2046
 
2244
2047
ulint
2245
2048
dict_foreign_add_to_cache(
2246
2049
/*======================*/
2283
2086
        if (for_in_cache->referenced_table == NULL && ref_table) {
2284
2087
                index = dict_foreign_find_index(
2285
2088
                        ref_table,
2286
 
                        for_in_cache->referenced_col_names,
 
2089
                        (const char**) for_in_cache->referenced_col_names,
2287
2090
                        for_in_cache->n_fields, for_in_cache->foreign_index,
2288
2091
                        check_charsets, FALSE);
2289
2092
 
2315
2118
        if (for_in_cache->foreign_table == NULL && for_table) {
2316
2119
                index = dict_foreign_find_index(
2317
2120
                        for_table,
2318
 
                        for_in_cache->foreign_col_names,
 
2121
                        (const char**) for_in_cache->foreign_col_names,
2319
2122
                        for_in_cache->n_fields,
2320
2123
                        for_in_cache->referenced_index, check_charsets,
2321
2124
                        for_in_cache->type
2362
2165
Scans from pointer onwards. Stops if is at the start of a copy of
2363
2166
'string' where characters are compared without case sensitivity, and
2364
2167
only outside `` or "" quotes. Stops also at '\0'. */
2365
 
UNIV_INTERN
 
2168
 
2366
2169
const char*
2367
2170
dict_scan_to(
2368
2171
/*=========*/
2880
2683
                                        in the SQL string */
2881
2684
        const char*     ptr)            /* in: place of the syntax error */
2882
2685
{
2883
 
        FILE*   ef = dict_foreign_err_file;
 
2686
        FILE*    ef = dict_foreign_err_file;
2884
2687
 
2885
2688
        mutex_enter(&dict_foreign_err_mutex);
2886
2689
        dict_foreign_error_report_low(ef, name);
3470
3273
 
3471
3274
/**************************************************************************
3472
3275
Determines whether a string starts with the specified keyword. */
3473
 
UNIV_INTERN
 
3276
 
3474
3277
ibool
3475
3278
dict_str_starts_with_keyword(
3476
3279
/*=========================*/
3493
3296
the indexes for a table have been created. Each foreign key constraint must
3494
3297
be accompanied with indexes in both participating tables. The indexes are
3495
3298
allowed to contain more fields than mentioned in the constraint. */
3496
 
UNIV_INTERN
 
3299
 
3497
3300
ulint
3498
3301
dict_create_foreign_constraints(
3499
3302
/*============================*/
3536
3339
 
3537
3340
/**************************************************************************
3538
3341
Parses the CONSTRAINT id's to be dropped in an ALTER TABLE statement. */
3539
 
UNIV_INTERN
 
3342
 
3540
3343
ulint
3541
3344
dict_foreign_parse_drop_constraints(
3542
3345
/*================================*/
3672
3475
 
3673
3476
/*==================== END OF FOREIGN KEY PROCESSING ====================*/
3674
3477
 
3675
 
/**************************************************************************
3676
 
Returns an index object if it is found in the dictionary cache.
3677
 
Assumes that dict_sys->mutex is already being held. */
3678
 
UNIV_INTERN
3679
 
dict_index_t*
3680
 
dict_index_get_if_in_cache_low(
3681
 
/*===========================*/
3682
 
                                /* out: index, NULL if not found */
3683
 
        dulint  index_id)       /* in: index id */
3684
 
{
3685
 
        ut_ad(mutex_own(&(dict_sys->mutex)));
3686
 
 
3687
 
        return(dict_index_find_on_id_low(index_id));
3688
 
}
3689
 
 
3690
 
#if defined UNIV_DEBUG || defined UNIV_BUF_DEBUG
 
3478
#ifdef UNIV_DEBUG
3691
3479
/**************************************************************************
3692
3480
Returns an index object if it is found in the dictionary cache. */
3693
 
UNIV_INTERN
 
3481
 
3694
3482
dict_index_t*
3695
3483
dict_index_get_if_in_cache(
3696
3484
/*=======================*/
3705
3493
 
3706
3494
        mutex_enter(&(dict_sys->mutex));
3707
3495
 
3708
 
        index = dict_index_get_if_in_cache_low(index_id);
 
3496
        index = dict_index_find_on_id_low(index_id);
3709
3497
 
3710
3498
        mutex_exit(&(dict_sys->mutex));
3711
3499
 
3712
3500
        return(index);
3713
3501
}
3714
 
#endif /* UNIV_DEBUG || UNIV_BUF_DEBUG */
 
3502
#endif /* UNIV_DEBUG */
3715
3503
 
3716
3504
#ifdef UNIV_DEBUG
3717
3505
/**************************************************************************
3718
3506
Checks that a tuple has n_fields_cmp value in a sensible range, so that
3719
3507
no comparison can occur with the page number field in a node pointer. */
3720
 
UNIV_INTERN
 
3508
 
3721
3509
ibool
3722
3510
dict_index_check_search_tuple(
3723
3511
/*==========================*/
3724
 
                                        /* out: TRUE if ok */
3725
 
        const dict_index_t*     index,  /* in: index tree */
3726
 
        const dtuple_t*         tuple)  /* in: tuple used in a search */
 
3512
                                /* out: TRUE if ok */
 
3513
        dict_index_t*   index,  /* in: index tree */
 
3514
        dtuple_t*       tuple)  /* in: tuple used in a search */
3727
3515
{
3728
3516
        ut_a(index);
3729
3517
        ut_a(dtuple_get_n_fields_cmp(tuple)
3734
3522
 
3735
3523
/**************************************************************************
3736
3524
Builds a node pointer out of a physical record and a page number. */
3737
 
UNIV_INTERN
 
3525
 
3738
3526
dtuple_t*
3739
3527
dict_index_build_node_ptr(
3740
3528
/*======================*/
3741
 
                                        /* out, own: node pointer */
3742
 
        const dict_index_t*     index,  /* in: index */
3743
 
        const rec_t*            rec,    /* in: record for which to build node
3744
 
                                        pointer */
3745
 
        ulint                   page_no,/* in: page number to put in node
3746
 
                                        pointer */
3747
 
        mem_heap_t*             heap,   /* in: memory heap where pointer
3748
 
                                        created */
3749
 
        ulint                   level)  /* in: level of rec in tree:
3750
 
                                        0 means leaf level */
 
3529
                                /* out, own: node pointer */
 
3530
        dict_index_t*   index,  /* in: index tree */
 
3531
        rec_t*          rec,    /* in: record for which to build node
 
3532
                                pointer */
 
3533
        ulint           page_no,/* in: page number to put in node pointer */
 
3534
        mem_heap_t*     heap,   /* in: memory heap where pointer created */
 
3535
        ulint           level)  /* in: level of rec in tree: 0 means leaf
 
3536
                                level */
3751
3537
{
3752
3538
        dtuple_t*       tuple;
3753
3539
        dfield_t*       field;
3804
3590
/**************************************************************************
3805
3591
Copies an initial segment of a physical record, long enough to specify an
3806
3592
index entry uniquely. */
3807
 
UNIV_INTERN
 
3593
 
3808
3594
rec_t*
3809
3595
dict_index_copy_rec_order_prefix(
3810
3596
/*=============================*/
3811
 
                                        /* out: pointer to the prefix record */
3812
 
        const dict_index_t*     index,  /* in: index */
3813
 
        const rec_t*            rec,    /* in: record for which to
3814
 
                                        copy prefix */
3815
 
        ulint*                  n_fields,/* out: number of fields copied */
3816
 
        byte**                  buf,    /* in/out: memory buffer for the
3817
 
                                        copied prefix, or NULL */
3818
 
        ulint*                  buf_size)/* in/out: buffer size */
 
3597
                                /* out: pointer to the prefix record */
 
3598
        dict_index_t*   index,  /* in: index tree */
 
3599
        rec_t*          rec,    /* in: record for which to copy prefix */
 
3600
        ulint*          n_fields,/* out: number of fields copied */
 
3601
        byte**          buf,    /* in/out: memory buffer for the copied prefix,
 
3602
                                or NULL */
 
3603
        ulint*          buf_size)/* in/out: buffer size */
3819
3604
{
3820
3605
        ulint           n;
3821
3606
 
3834
3619
 
3835
3620
/**************************************************************************
3836
3621
Builds a typed data tuple out of a physical record. */
3837
 
UNIV_INTERN
 
3622
 
3838
3623
dtuple_t*
3839
3624
dict_index_build_data_tuple(
3840
3625
/*========================*/
3862
3647
 
3863
3648
/*************************************************************************
3864
3649
Calculates the minimum record length in an index. */
3865
 
UNIV_INTERN
 
3650
 
3866
3651
ulint
3867
3652
dict_index_calc_min_rec_len(
3868
3653
/*========================*/
3869
 
        const dict_index_t*     index)  /* in: index */
 
3654
        dict_index_t*   index)  /* in: index */
3870
3655
{
3871
3656
        ulint   sum     = 0;
3872
3657
        ulint   i;
3913
3698
/*************************************************************************
3914
3699
Calculates new estimates for table and index statistics. The statistics
3915
3700
are used in query optimization. */
3916
 
UNIV_INTERN
 
3701
 
3917
3702
void
3918
3703
dict_update_statistics_low(
3919
3704
/*=======================*/
3920
 
        dict_table_t*   table,          /* in/out: table */
 
3705
        dict_table_t*   table,          /* in: table */
3921
3706
        ibool           has_dict_mutex __attribute__((unused)))
3922
3707
                                        /* in: TRUE if the caller has the
3923
3708
                                        dictionary mutex */
3997
3782
/*************************************************************************
3998
3783
Calculates new estimates for table and index statistics. The statistics
3999
3784
are used in query optimization. */
4000
 
UNIV_INTERN
 
3785
 
4001
3786
void
4002
3787
dict_update_statistics(
4003
3788
/*===================*/
4004
 
        dict_table_t*   table)  /* in/out: table */
 
3789
        dict_table_t*   table)  /* in: table */
4005
3790
{
4006
3791
        dict_update_statistics_low(table, FALSE);
4007
3792
}
4008
3793
 
4009
3794
/**************************************************************************
 
3795
A noninlined version of dict_table_get_low. */
 
3796
 
 
3797
dict_table_t*
 
3798
dict_table_get_low_noninlined(
 
3799
/*==========================*/
 
3800
                                        /* out: table, NULL if not found */
 
3801
        const char*     table_name)     /* in: table name */
 
3802
{
 
3803
        return(dict_table_get_low(table_name));
 
3804
}
 
3805
 
 
3806
/**************************************************************************
4010
3807
Prints info of a foreign key constraint. */
4011
3808
static
4012
3809
void
4038
3835
 
4039
3836
/**************************************************************************
4040
3837
Prints a table data. */
4041
 
UNIV_INTERN
 
3838
 
4042
3839
void
4043
3840
dict_table_print(
4044
3841
/*=============*/
4051
3848
 
4052
3849
/**************************************************************************
4053
3850
Prints a table data when we know the table name. */
4054
 
UNIV_INTERN
 
3851
 
4055
3852
void
4056
3853
dict_table_print_by_name(
4057
3854
/*=====================*/
4071
3868
 
4072
3869
/**************************************************************************
4073
3870
Prints a table data. */
4074
 
UNIV_INTERN
 
3871
 
4075
3872
void
4076
3873
dict_table_print_low(
4077
3874
/*=================*/
4087
3884
 
4088
3885
        fprintf(stderr,
4089
3886
                "--------------------------------------\n"
4090
 
                "TABLE: name %s, id %lu %lu, flags %lx, columns %lu,"
4091
 
                " indexes %lu, appr.rows %lu\n"
 
3887
                "TABLE: name %s, id %lu %lu, columns %lu, indexes %lu,"
 
3888
                " appr.rows %lu\n"
4092
3889
                "  COLUMNS: ",
4093
3890
                table->name,
4094
3891
                (ulong) ut_dulint_get_high(table->id),
4095
3892
                (ulong) ut_dulint_get_low(table->id),
4096
 
                (ulong) table->flags,
4097
3893
                (ulong) table->n_cols,
4098
3894
                (ulong) UT_LIST_GET_LEN(table->indexes),
4099
3895
                (ulong) table->stat_n_rows);
4155
3951
/*=================*/
4156
3952
        dict_index_t*   index)  /* in: index */
4157
3953
{
4158
 
        ib_int64_t      n_vals;
 
3954
        ib_longlong     n_vals;
4159
3955
        ulint           i;
4160
 
        const char*     type_string;
4161
3956
 
4162
3957
        ut_ad(mutex_own(&(dict_sys->mutex)));
4163
3958
 
4168
3963
                n_vals = index->stat_n_diff_key_vals[1];
4169
3964
        }
4170
3965
 
4171
 
        if (dict_index_is_clust(index)) {
4172
 
                type_string = "clustered index";
4173
 
        } else if (dict_index_is_unique(index)) {
4174
 
                type_string = "unique index";
4175
 
        } else {
4176
 
                type_string = "secondary index";
4177
 
        }
4178
 
 
4179
3966
        fprintf(stderr,
4180
3967
                "  INDEX: name %s, id %lu %lu, fields %lu/%lu,"
4181
3968
                " uniq %lu, type %lu\n"
4227
4014
/**************************************************************************
4228
4015
Outputs info on a foreign key of a table in a format suitable for
4229
4016
CREATE TABLE. */
4230
 
UNIV_INTERN
 
4017
 
4231
4018
void
4232
4019
dict_print_info_on_foreign_key_in_create_format(
4233
4020
/*============================================*/
4324
4111
 
4325
4112
/**************************************************************************
4326
4113
Outputs info on foreign keys of a table. */
4327
 
UNIV_INTERN
 
4114
 
4328
4115
void
4329
4116
dict_print_info_on_foreign_keys(
4330
4117
/*============================*/
4414
4201
 
4415
4202
/************************************************************************
4416
4203
Displays the names of the index and the table. */
4417
 
UNIV_INTERN
4418
4204
void
4419
4205
dict_index_name_print(
4420
4206
/*==================*/
4427
4213
        fputs(" of table ", file);
4428
4214
        ut_print_name(file, trx, TRUE, index->table_name);
4429
4215
}
4430
 
 
4431
 
/**************************************************************************
4432
 
Get index by name */
4433
 
UNIV_INTERN
4434
 
dict_index_t*
4435
 
dict_table_get_index_on_name(
4436
 
/*=========================*/
4437
 
                                /* out: index, NULL if does not exist */
4438
 
        dict_table_t*   table,  /* in: table */
4439
 
        const char*     name)   /* in: name of the index to find */
4440
 
{
4441
 
        dict_index_t*   index;
4442
 
 
4443
 
        index = dict_table_get_first_index(table);
4444
 
 
4445
 
        while (index != NULL) {
4446
 
                if (ut_strcmp(index->name, name) == 0) {
4447
 
 
4448
 
                        return(index);
4449
 
                }
4450
 
 
4451
 
                index = dict_table_get_next_index(index);
4452
 
        }
4453
 
 
4454
 
        return(NULL);
4455
 
 
4456
 
}
4457
 
 
4458
 
/**************************************************************************
4459
 
Find and index that is equivalent to the one passed in. */
4460
 
UNIV_INTERN
4461
 
dict_index_t*
4462
 
dict_table_find_equivalent_index(
4463
 
/*=============================*/
4464
 
        dict_table_t*   table,  /* in/out: table */
4465
 
        dict_index_t*   index)  /* in: index to match */
4466
 
{
4467
 
        ulint           i;
4468
 
        const char**    column_names;
4469
 
        dict_index_t*   equiv_index;
4470
 
 
4471
 
        if (UT_LIST_GET_LEN(table->foreign_list) == 0) {
4472
 
 
4473
 
                return(NULL);
4474
 
        }
4475
 
 
4476
 
        column_names = mem_alloc(index->n_fields * sizeof *column_names);
4477
 
 
4478
 
        /* Convert the column names to the format & type accepted by the find
4479
 
        index function */
4480
 
        for (i = 0; i < index->n_fields; i++) {
4481
 
                column_names[i] = index->fields[i].name;
4482
 
        }
4483
 
 
4484
 
        equiv_index = dict_foreign_find_index(
4485
 
                table, column_names, index->n_fields,
4486
 
                index, TRUE, FALSE);
4487
 
 
4488
 
        mem_free((void*) column_names);
4489
 
 
4490
 
        return(equiv_index);
4491
 
}
4492
 
 
4493
 
/**************************************************************************
4494
 
Replace the index passed in with another equivalent index in the tables
4495
 
foreign key list. */
4496
 
UNIV_INTERN
4497
 
void
4498
 
dict_table_replace_index_in_foreign_list(
4499
 
/*=====================================*/
4500
 
        dict_table_t*   table,  /* in/out: table */
4501
 
        dict_index_t*   index)  /* in: index to be replaced */
4502
 
{
4503
 
        dict_index_t*   new_index;
4504
 
 
4505
 
        new_index = dict_table_find_equivalent_index(table, index);
4506
 
 
4507
 
        /* If match found */
4508
 
        if (new_index) {
4509
 
                dict_foreign_t* foreign;
4510
 
 
4511
 
                ut_a(new_index != index);
4512
 
 
4513
 
                foreign = UT_LIST_GET_FIRST(table->foreign_list);
4514
 
 
4515
 
                /* If the list is not empty then this should hold */
4516
 
                ut_a(foreign);
4517
 
 
4518
 
                /* Iterate over the foreign index list and replace the index
4519
 
                passed in with the new index */
4520
 
                while (foreign) {
4521
 
 
4522
 
                        if (foreign->foreign_index == index) {
4523
 
                                foreign->foreign_index = new_index;
4524
 
                        }
4525
 
 
4526
 
                        foreign = UT_LIST_GET_NEXT(foreign_list, foreign);
4527
 
                }
4528
 
        }
4529
 
}
4530
 
 
4531
 
/**************************************************************************
4532
 
In case there is more than one index with the same name return the index
4533
 
with the min(id). */
4534
 
UNIV_INTERN
4535
 
dict_index_t*
4536
 
dict_table_get_index_on_name_and_min_id(
4537
 
/*=====================================*/
4538
 
                                /* out: index, NULL if does not exist */
4539
 
        dict_table_t*   table,  /* in: table */
4540
 
        const char*     name)   /* in: name of the index to find */
4541
 
{
4542
 
        dict_index_t*   index;
4543
 
        dict_index_t*   min_index; /* Index with matching name and min(id) */
4544
 
 
4545
 
        min_index = NULL;
4546
 
        index = dict_table_get_first_index(table);
4547
 
 
4548
 
        while (index != NULL) {
4549
 
                if (ut_strcmp(index->name, name) == 0) {
4550
 
                        if (!min_index
4551
 
                            || ut_dulint_cmp(index->id, min_index->id) < 0) {
4552
 
 
4553
 
                                min_index = index;
4554
 
                        }
4555
 
                }
4556
 
 
4557
 
                index = dict_table_get_next_index(index);
4558
 
        }
4559
 
 
4560
 
        return(min_index);
4561
 
 
4562
 
}
4563
 
 
4564
 
#ifdef UNIV_DEBUG
4565
 
/**************************************************************************
4566
 
Check for duplicate index entries in a table [using the index name] */
4567
 
UNIV_INTERN
4568
 
void
4569
 
dict_table_check_for_dup_indexes(
4570
 
/*=============================*/
4571
 
        const dict_table_t*     table)  /* in: Check for dup indexes
4572
 
                                        in this table */
4573
 
{
4574
 
        /* Check for duplicates, ignoring indexes that are marked
4575
 
        as to be dropped */
4576
 
 
4577
 
        const dict_index_t*     index1;
4578
 
        const dict_index_t*     index2;
4579
 
 
4580
 
        /* The primary index _must_ exist */
4581
 
        ut_a(UT_LIST_GET_LEN(table->indexes) > 0);
4582
 
 
4583
 
        index1 = UT_LIST_GET_FIRST(table->indexes);
4584
 
        index2 = UT_LIST_GET_NEXT(indexes, index1);
4585
 
 
4586
 
        while (index1 && index2) {
4587
 
 
4588
 
                while (index2) {
4589
 
 
4590
 
                        if (!index2->to_be_dropped) {
4591
 
                                ut_ad(ut_strcmp(index1->name, index2->name));
4592
 
                        }
4593
 
 
4594
 
                        index2 = UT_LIST_GET_NEXT(indexes, index2);
4595
 
                }
4596
 
 
4597
 
                index1 = UT_LIST_GET_NEXT(indexes, index1);
4598
 
                index2 = UT_LIST_GET_NEXT(indexes, index1);
4599
 
        }
4600
 
}
4601
 
#endif /* UNIV_DEBUG */