~drizzle-trunk/drizzle/development

« back to all changes in this revision

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

Imported InnoDB plugin with changes.

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"
29
30
#ifndef UNIV_HOTBACKUP
30
 
# include <mystrings/m_ctype.h> /* my_isspace() */
 
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() */
31
37
#endif /* !UNIV_HOTBACKUP */
32
38
 
33
39
#include <ctype.h>
34
40
 
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 */
 
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
 
51
52
#define DICT_POOL_PER_TABLE_HASH 512    /* buffer pool max size per table
52
53
                                        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 */
55
54
 
56
55
/* Identifies generated InnoDB foreign key names */
57
56
static char     dict_ibfk[] = "_ibfk_";
62
61
 
63
62
NOTE: the prototype of this function is copied from ha_innodb.cc! If you change
64
63
this function, you MUST change also the prototype here! */
65
 
extern
 
64
UNIV_INTERN
66
65
void
67
66
innobase_convert_from_table_id(
68
67
/*===========================*/
75
74
 
76
75
NOTE: the prototype of this function is copied from ha_innodb.cc! If you change
77
76
this function, you MUST change also the prototype here! */
78
 
extern
 
77
UNIV_INTERN
79
78
void
80
79
innobase_convert_from_id(
81
80
/*=====================*/
84
83
        ulint           len);   /* in: length of 'to', in bytes;
85
84
                                should be at least 3 * strlen(to) + 1 */
86
85
/**********************************************************************
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
 
/**********************************************************************
100
86
Makes all characters in a NUL-terminated UTF-8 string lower case.
101
87
 
102
88
NOTE: the prototype of this function is copied from ha_innodb.cc! If you change
103
89
this function, you MUST change also the prototype here! */
104
 
extern
 
90
UNIV_INTERN
105
91
void
106
92
innobase_casedn_str(
107
93
/*================*/
119
105
        void*   mysql_thd);     /* in: MySQL thread handle */
120
106
#endif /* !UNIV_HOTBACKUP */
121
107
 
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 */
141
108
/***********************************************************************
142
109
Tries to find column names for the index and sets the col field of the
143
110
index. */
154
121
dict_index_t*
155
122
dict_index_build_internal_clust(
156
123
/*============================*/
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 */
 
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 */
162
130
/***********************************************************************
163
131
Builds the internal dictionary cache representation for a non-clustered
164
132
index, containing also system fields not defined by the user. */
166
134
dict_index_t*
167
135
dict_index_build_internal_non_clust(
168
136
/*================================*/
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 */
 
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 */
174
143
/**************************************************************************
175
144
Removes a foreign constraint struct from the dictionary cache. */
176
145
static
210
179
 
211
180
/* Stream for storing detailed information about the latest foreign key
212
181
and unique key errors */
213
 
FILE*   dict_foreign_err_file           = NULL;
214
 
mutex_t dict_foreign_err_mutex;         /* mutex protecting the foreign
215
 
                                        and unique error buffers */
 
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;
216
185
 
217
186
#ifndef UNIV_HOTBACKUP
218
187
/**********************************************************************
219
188
Makes all characters in a NUL-terminated UTF-8 string lower case. */
220
 
 
 
189
UNIV_INTERN
221
190
void
222
191
dict_casedn_str(
223
192
/*============*/
229
198
 
230
199
/************************************************************************
231
200
Checks if the database name in two table names is the same. */
232
 
 
 
201
UNIV_INTERN
233
202
ibool
234
203
dict_tables_have_same_db(
235
204
/*=====================*/
250
219
 
251
220
/************************************************************************
252
221
Return the end of table name where we have removed dbname and '/'. */
253
 
 
 
222
UNIV_INTERN
254
223
const char*
255
224
dict_remove_db_name(
256
225
/*================*/
266
235
 
267
236
/************************************************************************
268
237
Get the database name length in a table name. */
269
 
 
 
238
UNIV_INTERN
270
239
ulint
271
240
dict_get_db_name_len(
272
241
/*=================*/
282
251
 
283
252
/************************************************************************
284
253
Reserves the dictionary system mutex for MySQL. */
285
 
 
 
254
UNIV_INTERN
286
255
void
287
256
dict_mutex_enter_for_mysql(void)
288
257
/*============================*/
292
261
 
293
262
/************************************************************************
294
263
Releases the dictionary system mutex for MySQL. */
295
 
 
 
264
UNIV_INTERN
296
265
void
297
266
dict_mutex_exit_for_mysql(void)
298
267
/*===========================*/
302
271
 
303
272
/************************************************************************
304
273
Decrements the count of open MySQL handles to a table. */
305
 
 
 
274
UNIV_INTERN
306
275
void
307
276
dict_table_decrement_handle_count(
308
277
/*==============================*/
309
 
        dict_table_t*   table)  /* in: table */
 
278
        dict_table_t*   table,          /* in/out: table */
 
279
        ibool           dict_locked)    /* in: TRUE=data dictionary locked */
310
280
{
311
 
        mutex_enter(&(dict_sys->mutex));
 
281
        if (!dict_locked) {
 
282
                mutex_enter(&dict_sys->mutex);
 
283
        }
312
284
 
 
285
        ut_ad(mutex_own(&dict_sys->mutex));
313
286
        ut_a(table->n_mysql_handles_opened > 0);
314
287
 
315
288
        table->n_mysql_handles_opened--;
316
289
 
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));
 
290
        if (!dict_locked) {
 
291
                mutex_exit(&dict_sys->mutex);
 
292
        }
380
293
}
381
294
 
382
295
/**************************************************************************
383
296
Returns a column's name. */
384
 
 
 
297
UNIV_INTERN
385
298
const char*
386
299
dict_table_get_col_name(
387
300
/*====================*/
412
325
 
413
326
/************************************************************************
414
327
Acquire the autoinc lock.*/
415
 
 
 
328
UNIV_INTERN
416
329
void
417
330
dict_table_autoinc_lock(
418
331
/*====================*/
419
 
        dict_table_t*   table)
 
332
        dict_table_t*   table)  /* in/out: table */
420
333
{
421
334
        mutex_enter(&table->autoinc_mutex);
422
335
}
424
337
/************************************************************************
425
338
Initializes the autoinc counter. It is not an error to initialize an already
426
339
initialized counter. */
427
 
 
 
340
UNIV_INTERN
428
341
void
429
342
dict_table_autoinc_initialize(
430
343
/*==========================*/
431
 
        dict_table_t*   table,  /* in: table */
432
 
        ib_longlong     value)  /* in: next value to assign to a row */
 
344
        dict_table_t*   table,  /* in/out: table */
 
345
        ib_uint64_t     value)  /* in: next value to assign to a row */
433
346
{
434
347
        ut_ad(mutex_own(&table->autoinc_mutex));
435
348
 
440
353
/************************************************************************
441
354
Reads the next autoinc value (== autoinc counter value), 0 if not yet
442
355
initialized. */
443
 
 
444
 
ib_longlong
 
356
UNIV_INTERN
 
357
ib_uint64_t
445
358
dict_table_autoinc_read(
446
359
/*====================*/
447
 
                                /* out: value for a new row, or 0 */
448
 
        dict_table_t*   table)  /* in: table */
 
360
                                        /* out: value for a new row, or 0 */
 
361
        const dict_table_t*     table)  /* in: table */
449
362
{
450
 
        ib_longlong     value;
 
363
        ib_int64_t      value;
451
364
 
452
365
        ut_ad(mutex_own(&table->autoinc_mutex));
453
366
 
464
377
/************************************************************************
465
378
Updates the autoinc counter if the value supplied is greater than the
466
379
current value. If not inited, does nothing. */
467
 
 
 
380
UNIV_INTERN
468
381
void
469
382
dict_table_autoinc_update(
470
383
/*======================*/
471
384
 
472
 
        dict_table_t*   table,  /* in: table */
473
 
        ib_longlong     value)  /* in: value which was assigned to a row */
 
385
        dict_table_t*   table,  /* in/out: table */
 
386
        ib_uint64_t     value)  /* in: value which was assigned to a row */
474
387
{
475
388
        if (table->autoinc_inited && value > table->autoinc) {
476
389
 
480
393
 
481
394
/************************************************************************
482
395
Release the autoinc lock.*/
483
 
 
 
396
UNIV_INTERN
484
397
void
485
398
dict_table_autoinc_unlock(
486
399
/*======================*/
487
 
        dict_table_t*   table)  /* in: release autoinc lock for this table */
 
400
        dict_table_t*   table)  /* in/out: table */
488
401
{
489
402
        mutex_exit(&table->autoinc_mutex);
490
403
}
491
404
 
 
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
 
492
434
/************************************************************************
493
435
Looks for column n in an index. */
494
 
 
 
436
UNIV_INTERN
495
437
ulint
496
438
dict_index_get_nth_col_pos(
497
439
/*=======================*/
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 */
 
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 */
503
446
{
504
447
        const dict_field_t*     field;
505
448
        const dict_col_t*       col;
511
454
 
512
455
        col = dict_table_get_nth_col(index->table, n);
513
456
 
514
 
        if (index->type & DICT_CLUSTERED) {
 
457
        if (dict_index_is_clust(index)) {
515
458
 
516
459
                return(dict_col_get_clust_pos(col, index));
517
460
        }
532
475
 
533
476
/************************************************************************
534
477
Returns TRUE if the index contains a column or a prefix of that column. */
535
 
 
 
478
UNIV_INTERN
536
479
ibool
537
480
dict_index_contains_col_or_prefix(
538
481
/*==============================*/
539
 
                                /* out: TRUE if contains the column or its
540
 
                                prefix */
541
 
        dict_index_t*   index,  /* in: index */
542
 
        ulint           n)      /* in: column number */
 
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 */
543
486
{
544
487
        const dict_field_t*     field;
545
488
        const dict_col_t*       col;
549
492
        ut_ad(index);
550
493
        ut_ad(index->magic_n == DICT_INDEX_MAGIC_N);
551
494
 
552
 
        if (index->type & DICT_CLUSTERED) {
 
495
        if (dict_index_is_clust(index)) {
553
496
 
554
497
                return(TRUE);
555
498
        }
575
518
column in index must be complete, or must contain a prefix longer than the
576
519
column in index2. That is, we must be able to construct the prefix in index2
577
520
from the prefix in index. */
578
 
 
 
521
UNIV_INTERN
579
522
ulint
580
523
dict_index_get_nth_field_pos(
581
524
/*=========================*/
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 */
 
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 */
588
532
{
589
 
        dict_field_t*   field;
590
 
        dict_field_t*   field2;
591
 
        ulint           n_fields;
592
 
        ulint           pos;
 
533
        const dict_field_t*     field;
 
534
        const dict_field_t*     field2;
 
535
        ulint                   n_fields;
 
536
        ulint                   pos;
593
537
 
594
538
        ut_ad(index);
595
539
        ut_ad(index->magic_n == DICT_INDEX_MAGIC_N);
615
559
 
616
560
/**************************************************************************
617
561
Returns a table object based on table id. */
618
 
 
 
562
UNIV_INTERN
619
563
dict_table_t*
620
564
dict_table_get_on_id(
621
565
/*=================*/
649
593
 
650
594
/************************************************************************
651
595
Looks for column n position in the clustered index. */
652
 
 
 
596
UNIV_INTERN
653
597
ulint
654
598
dict_table_get_nth_col_pos(
655
599
/*=======================*/
656
 
                                /* out: position in internal representation
657
 
                                of the clustered index */
658
 
        dict_table_t*   table,  /* in: table */
659
 
        ulint           n)      /* in: column number */
 
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 */
660
605
{
661
606
        return(dict_index_get_nth_col_pos(dict_table_get_first_index(table),
662
607
                                          n));
663
608
}
664
609
 
665
610
/************************************************************************
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
 
/************************************************************************
679
611
Checks if a column is in the ordering columns of the clustered index of a
680
612
table. Column prefixes are treated like whole columns. */
681
 
 
 
613
UNIV_INTERN
682
614
ibool
683
615
dict_table_col_in_clustered_key(
684
616
/*============================*/
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 */
 
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 */
689
621
{
690
 
        dict_index_t*           index;
 
622
        const dict_index_t*     index;
691
623
        const dict_field_t*     field;
692
624
        const dict_col_t*       col;
693
625
        ulint                   pos;
715
647
 
716
648
/**************************************************************************
717
649
Inits the data dictionary module. */
718
 
 
 
650
UNIV_INTERN
719
651
void
720
652
dict_init(void)
721
653
/*===========*/
724
656
 
725
657
        mutex_create(&dict_sys->mutex, SYNC_DICT);
726
658
 
727
 
        dict_sys->table_hash = hash_create(buf_pool_get_max_size()
 
659
        dict_sys->table_hash = hash_create(buf_pool_get_curr_size()
728
660
                                           / (DICT_POOL_PER_TABLE_HASH
729
661
                                              * UNIV_WORD_SIZE));
730
 
        dict_sys->table_id_hash = hash_create(buf_pool_get_max_size()
 
662
        dict_sys->table_id_hash = hash_create(buf_pool_get_curr_size()
731
663
                                              / (DICT_POOL_PER_TABLE_HASH
732
664
                                                 * UNIV_WORD_SIZE));
733
665
        dict_sys->size = 0;
747
679
NOTE! This is a high-level function to be used mainly from outside the
748
680
'dict' directory. Inside this directory dict_table_get_low is usually the
749
681
appropriate function. */
750
 
 
 
682
UNIV_INTERN
751
683
dict_table_t*
752
684
dict_table_get(
753
685
/*===========*/
755
687
                                        does not exist */
756
688
        const char*     table_name,     /* in: table name */
757
689
        ibool           inc_mysql_count)
758
 
                                        /* in: whether to increment the open
 
690
                                        /* in: whether to increment the open
759
691
                                        handle count on the table */
760
692
{
761
693
        dict_table_t*   table;
784
716
 
785
717
/**************************************************************************
786
718
Adds system columns to a table object. */
787
 
 
 
719
UNIV_INTERN
788
720
void
789
721
dict_table_add_system_columns(
790
722
/*==========================*/
830
762
 
831
763
/**************************************************************************
832
764
Adds a table object to the dictionary cache. */
833
 
 
 
765
UNIV_INTERN
834
766
void
835
767
dict_table_add_to_cache(
836
768
/*====================*/
875
807
        /* Look for a table with the same name: error if such exists */
876
808
        {
877
809
                dict_table_t*   table2;
878
 
                HASH_SEARCH(name_hash, dict_sys->table_hash, fold, table2,
 
810
                HASH_SEARCH(name_hash, dict_sys->table_hash, fold,
 
811
                            dict_table_t*, table2,
879
812
                            (ut_strcmp(table2->name, table->name) == 0));
880
813
                ut_a(table2 == NULL);
881
814
        }
883
816
        /* Look for a table with the same id: error if such exists */
884
817
        {
885
818
                dict_table_t*   table2;
886
 
                HASH_SEARCH(id_hash, dict_sys->table_id_hash, id_fold, table2,
 
819
                HASH_SEARCH(id_hash, dict_sys->table_id_hash, id_fold,
 
820
                            dict_table_t*, table2,
887
821
                            (ut_dulint_cmp(table2->id, table->id) == 0));
888
822
                ut_a(table2 == NULL);
889
823
        }
905
839
Looks for an index with the given id. NOTE that we do not reserve
906
840
the dictionary mutex: this function is for emergency purposes like
907
841
printing info of a corrupt database page! */
908
 
 
 
842
UNIV_INTERN
909
843
dict_index_t*
910
844
dict_index_find_on_id_low(
911
845
/*======================*/
938
872
 
939
873
/**************************************************************************
940
874
Renames a table object. */
941
 
 
 
875
UNIV_INTERN
942
876
ibool
943
877
dict_table_rename_in_cache(
944
878
/*=======================*/
945
879
                                        /* out: TRUE if success */
946
 
        dict_table_t*   table,          /* in: table */
 
880
        dict_table_t*   table,          /* in/out: table */
947
881
        const char*     new_name,       /* in: new name */
948
882
        ibool           rename_also_foreigns)/* in: in ALTER TABLE we want
949
883
                                        to preserve the original table name
953
887
        dict_index_t*   index;
954
888
        ulint           fold;
955
889
        ulint           old_size;
956
 
        char*           old_name;
957
 
        ibool           success;
 
890
        const char*     old_name;
958
891
 
959
892
        ut_ad(table);
960
893
        ut_ad(mutex_own(&(dict_sys->mutex)));
961
894
 
962
895
        old_size = mem_heap_get_size(table->heap);
 
896
        old_name = table->name;
963
897
 
964
898
        fold = ut_fold_string(new_name);
965
899
 
966
900
        /* Look for a table with the same name: error if such exists */
967
901
        {
968
902
                dict_table_t*   table2;
969
 
                HASH_SEARCH(name_hash, dict_sys->table_hash, fold, table2,
 
903
                HASH_SEARCH(name_hash, dict_sys->table_hash, fold,
 
904
                            dict_table_t*, table2,
970
905
                            (ut_strcmp(table2->name, new_name) == 0));
971
 
                if (table2) {
972
 
                        fprintf(stderr,
973
 
                                "InnoDB: Error: dictionary cache"
974
 
                                " already contains a table of name %s\n",
975
 
                                new_name);
 
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);
976
915
                        return(FALSE);
977
916
                }
978
917
        }
982
921
 
983
922
        if (table->space != 0) {
984
923
                if (table->dir_path_of_temp_table != NULL) {
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
 
 
 
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)) {
998
935
                        return(FALSE);
999
936
                }
1000
937
        }
1001
938
 
1002
939
        /* Remove table from the hash tables of tables */
1003
940
        HASH_DELETE(dict_table_t, name_hash, dict_sys->table_hash,
1004
 
                    ut_fold_string(table->name), table);
1005
 
        old_name = mem_heap_strdup(table->heap, table->name);
 
941
                    ut_fold_string(old_name), table);
1006
942
        table->name = mem_heap_strdup(table->heap, new_name);
1007
943
 
1008
944
        /* Add table to hash table of tables */
1153
1089
/**************************************************************************
1154
1090
Change the id of a table object in the dictionary cache. This is used in
1155
1091
DISCARD TABLESPACE. */
1156
 
 
 
1092
UNIV_INTERN
1157
1093
void
1158
1094
dict_table_change_id_in_cache(
1159
1095
/*==========================*/
1160
 
        dict_table_t*   table,  /* in: table object already in cache */
 
1096
        dict_table_t*   table,  /* in/out: table object already in cache */
1161
1097
        dulint          new_id) /* in: new id to set */
1162
1098
{
1163
1099
        ut_ad(table);
1177
1113
 
1178
1114
/**************************************************************************
1179
1115
Removes a table object from the dictionary cache. */
1180
 
 
 
1116
UNIV_INTERN
1181
1117
void
1182
1118
dict_table_remove_from_cache(
1183
1119
/*=========================*/
1242
1178
        dict_mem_table_free(table);
1243
1179
}
1244
1180
 
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
 
 
1257
1181
/********************************************************************
1258
1182
If the given column name is reserved for InnoDB system columns, return
1259
1183
TRUE. */
1260
 
 
 
1184
UNIV_INTERN
1261
1185
ibool
1262
1186
dict_col_name_is_reserved(
1263
1187
/*======================*/
1286
1210
        return(FALSE);
1287
1211
}
1288
1212
 
 
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
 
1289
1315
/**************************************************************************
1290
1316
Adds an index to the dictionary cache. */
1291
 
 
1292
 
void
 
1317
UNIV_INTERN
 
1318
ulint
1293
1319
dict_index_add_to_cache(
1294
1320
/*====================*/
 
1321
                                /* out: DB_SUCCESS or DB_TOO_BIG_RECORD */
1295
1322
        dict_table_t*   table,  /* in: table on which the index is */
1296
1323
        dict_index_t*   index,  /* in, own: index; NOTE! The index memory
1297
1324
                                object is freed in this function! */
1307
1334
        ut_ad(index->magic_n == DICT_INDEX_MAGIC_N);
1308
1335
 
1309
1336
        ut_ad(mem_heap_validate(index->heap));
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)
 
1337
        ut_a(!dict_index_is_clust(index)
1325
1338
             || UT_LIST_GET_LEN(table->indexes) == 0);
1326
1339
 
1327
1340
        dict_index_find_cols(table, index);
1329
1342
        /* Build the cache internal representation of the index,
1330
1343
        containing also the added system fields */
1331
1344
 
1332
 
        if (index->type & DICT_CLUSTERED) {
 
1345
        if (dict_index_is_clust(index)) {
1333
1346
                new_index = dict_index_build_internal_clust(table, index);
1334
1347
        } else {
1335
1348
                new_index = dict_index_build_internal_non_clust(table, index);
1336
1349
        }
1337
1350
 
1338
 
        new_index->search_info = btr_search_info_create(new_index->heap);
1339
 
 
1340
1351
        /* Set the n_fields value in new_index to the actual defined
1341
1352
        number of fields in the cache internal representation */
1342
1353
 
1343
1354
        new_index->n_fields = new_index->n_def;
1344
1355
 
 
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
 
1345
1403
        /* Add the new index as the last index for the table */
1346
1404
 
1347
1405
        UT_LIST_ADD_LAST(indexes, table->indexes, new_index);
1348
1406
        new_index->table = table;
1349
1407
        new_index->table_name = table->name;
1350
1408
 
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;
 
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;
1365
1415
        rw_lock_create(&new_index->lock, SYNC_INDEX_TREE);
1366
1416
 
1367
1417
        if (!UNIV_UNLIKELY(new_index->type & DICT_UNIVERSAL)) {
1369
1419
                new_index->stat_n_diff_key_vals = mem_heap_alloc(
1370
1420
                        new_index->heap,
1371
1421
                        (1 + dict_index_get_n_unique(new_index))
1372
 
                        * sizeof(ib_longlong));
 
1422
                        * sizeof(ib_int64_t));
1373
1423
                /* Give some sensible values to stat_n_... in case we do
1374
1424
                not calculate statistics quickly enough */
1375
1425
 
1382
1432
        dict_sys->size += mem_heap_get_size(new_index->heap);
1383
1433
 
1384
1434
        dict_mem_index_free(index);
 
1435
 
 
1436
        return(DB_SUCCESS);
1385
1437
}
1386
1438
 
1387
1439
/**************************************************************************
1388
1440
Removes an index from the dictionary cache. */
1389
 
static
 
1441
UNIV_INTERN
1390
1442
void
1391
1443
dict_index_remove_from_cache(
1392
1444
/*=========================*/
1393
 
        dict_table_t*   table,  /* in: table */
 
1445
        dict_table_t*   table,  /* in/out: table */
1394
1446
        dict_index_t*   index)  /* in, own: index */
1395
1447
{
1396
1448
        ulint           size;
1437
1489
                for (j = 0; j < table->n_cols; j++) {
1438
1490
                        if (!strcmp(dict_table_get_col_name(table, j),
1439
1491
                                    field->name)) {
1440
 
                                field->col = (dict_col_t*)
1441
 
                                        dict_table_get_nth_col(table, j);
 
1492
                                field->col = dict_table_get_nth_col(table, j);
1442
1493
 
1443
1494
                                goto found;
1444
1495
                        }
1447
1498
                /* It is an error not to find a matching column. */
1448
1499
                ut_error;
1449
1500
 
1450
 
        found:
 
1501
found:
1451
1502
                ;
1452
1503
        }
1453
1504
}
1454
1505
 
1455
1506
/***********************************************************************
1456
1507
Adds a column to index. */
1457
 
 
 
1508
UNIV_INTERN
1458
1509
void
1459
1510
dict_index_add_col(
1460
1511
/*===============*/
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 */
 
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 */
1465
1516
{
1466
1517
        dict_field_t*   field;
1467
1518
        const char*     col_name;
1504
1555
void
1505
1556
dict_index_copy(
1506
1557
/*============*/
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 */
 
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 */
1512
1563
{
1513
1564
        dict_field_t*   field;
1514
1565
        ulint           i;
1525
1576
 
1526
1577
/***********************************************************************
1527
1578
Copies types of fields contained in index to tuple. */
1528
 
 
 
1579
UNIV_INTERN
1529
1580
void
1530
1581
dict_index_copy_types(
1531
1582
/*==================*/
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 */
 
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 */
1535
1587
{
1536
1588
        ulint           i;
1537
1589
 
1542
1594
        }
1543
1595
 
1544
1596
        for (i = 0; i < n_fields; i++) {
1545
 
                dict_field_t*   ifield;
1546
 
                dtype_t*        dfield_type;
 
1597
                const dict_field_t*     ifield;
 
1598
                dtype_t*                dfield_type;
1547
1599
 
1548
1600
                ifield = dict_index_get_nth_field(index, i);
1549
1601
                dfield_type = dfield_get_type(dtuple_get_nth_field(tuple, i));
1552
1604
}
1553
1605
 
1554
1606
/***********************************************************************
1555
 
Copies types of columns contained in table to tuple. */
1556
 
 
 
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
1557
1611
void
1558
1612
dict_table_copy_types(
1559
1613
/*==================*/
1560
 
        dtuple_t*       tuple,  /* in: data tuple */
1561
 
        dict_table_t*   table)  /* in: index */
 
1614
        dtuple_t*               tuple,  /* in/out: data tuple */
 
1615
        const dict_table_t*     table)  /* in: table */
1562
1616
{
1563
 
        dtype_t*        dfield_type;
1564
1617
        ulint           i;
1565
1618
 
1566
1619
        for (i = 0; i < dtuple_get_n_fields(tuple); i++) {
1567
1620
 
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);
 
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);
1571
1626
        }
1572
1627
}
1573
1628
 
1578
1633
dict_index_t*
1579
1634
dict_index_build_internal_clust(
1580
1635
/*============================*/
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 */
 
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 */
1586
1642
{
1587
1643
        dict_index_t*   new_index;
1588
1644
        dict_field_t*   field;
1592
1648
        ibool*          indexed;
1593
1649
 
1594
1650
        ut_ad(table && index);
1595
 
        ut_ad(index->type & DICT_CLUSTERED);
 
1651
        ut_ad(dict_index_is_clust(index));
1596
1652
        ut_ad(mutex_own(&(dict_sys->mutex)));
1597
1653
        ut_ad(table->magic_n == DICT_TABLE_MAGIC_N);
1598
1654
 
1617
1673
 
1618
1674
                new_index->n_uniq = REC_MAX_N_FIELDS;
1619
1675
 
1620
 
        } else if (index->type & DICT_UNIQUE) {
 
1676
        } else if (dict_index_is_unique(index)) {
1621
1677
                /* Only the fields defined so far are needed to identify
1622
1678
                the index entry uniquely */
1623
1679
 
1629
1685
 
1630
1686
        new_index->trx_id_offset = 0;
1631
1687
 
1632
 
        if (!(index->type & DICT_IBUF)) {
 
1688
        if (!dict_index_is_ibuf(index)) {
1633
1689
                /* Add system columns, trx id first */
1634
1690
 
1635
1691
                trx_id_pos = new_index->n_def;
1644
1700
# error "DATA_ROLL_PTR != 2"
1645
1701
#endif
1646
1702
 
1647
 
                if (!(index->type & DICT_UNIQUE)) {
1648
 
                        dict_index_add_col(new_index, table, (dict_col_t*)
 
1703
                if (!dict_index_is_unique(index)) {
 
1704
                        dict_index_add_col(new_index, table,
1649
1705
                                           dict_table_get_sys_col(
1650
1706
                                                   table, DATA_ROW_ID),
1651
1707
                                           0);
1652
1708
                        trx_id_pos++;
1653
1709
                }
1654
1710
 
1655
 
                dict_index_add_col(new_index, table, (dict_col_t*)
 
1711
                dict_index_add_col(new_index, table,
1656
1712
                                   dict_table_get_sys_col(table, DATA_TRX_ID),
1657
1713
                                   0);
1658
1714
 
1659
 
                dict_index_add_col(new_index, table, (dict_col_t*)
 
1715
                dict_index_add_col(new_index, table,
1660
1716
                                   dict_table_get_sys_col(table,
1661
1717
                                                          DATA_ROLL_PTR),
1662
1718
                                   0);
1685
1741
        }
1686
1742
 
1687
1743
        /* Remember the table columns already contained in new_index */
1688
 
        indexed = mem_alloc(table->n_cols * sizeof *indexed);
1689
 
        memset(indexed, 0, table->n_cols * sizeof *indexed);
 
1744
        indexed = mem_zalloc(table->n_cols * sizeof *indexed);
1690
1745
 
1691
 
        /* Mark with 0 the table columns already contained in new_index */
 
1746
        /* Mark the table columns already contained in new_index */
1692
1747
        for (i = 0; i < new_index->n_def; i++) {
1693
1748
 
1694
1749
                field = dict_index_get_nth_field(new_index, i);
1706
1761
        there */
1707
1762
        for (i = 0; i + DATA_N_SYS_COLS < (ulint) table->n_cols; i++) {
1708
1763
 
1709
 
                dict_col_t*     col = (dict_col_t*)
1710
 
                        dict_table_get_nth_col(table, i);
 
1764
                dict_col_t*     col = dict_table_get_nth_col(table, i);
1711
1765
                ut_ad(col->mtype != DATA_SYS);
1712
1766
 
1713
1767
                if (!indexed[col->ind]) {
1717
1771
 
1718
1772
        mem_free(indexed);
1719
1773
 
1720
 
        ut_ad((index->type & DICT_IBUF)
 
1774
        ut_ad(dict_index_is_ibuf(index)
1721
1775
              || (UT_LIST_GET_LEN(table->indexes) == 0));
1722
1776
 
1723
1777
        new_index->cached = TRUE;
1732
1786
dict_index_t*
1733
1787
dict_index_build_internal_non_clust(
1734
1788
/*================================*/
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 */
 
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 */
1740
1795
{
1741
1796
        dict_field_t*   field;
1742
1797
        dict_index_t*   new_index;
1745
1800
        ibool*          indexed;
1746
1801
 
1747
1802
        ut_ad(table && index);
1748
 
        ut_ad(0 == (index->type & DICT_CLUSTERED));
 
1803
        ut_ad(!dict_index_is_clust(index));
1749
1804
        ut_ad(mutex_own(&(dict_sys->mutex)));
1750
1805
        ut_ad(table->magic_n == DICT_TABLE_MAGIC_N);
1751
1806
 
1753
1808
        clust_index = UT_LIST_GET_FIRST(table->indexes);
1754
1809
 
1755
1810
        ut_ad(clust_index);
1756
 
        ut_ad(clust_index->type & DICT_CLUSTERED);
 
1811
        ut_ad(dict_index_is_clust(clust_index));
1757
1812
        ut_ad(!(clust_index->type & DICT_UNIVERSAL));
1758
1813
 
1759
1814
        /* Create a new index */
1772
1827
        dict_index_copy(new_index, index, table, 0, index->n_fields);
1773
1828
 
1774
1829
        /* Remember the table columns already contained in new_index */
1775
 
        indexed = mem_alloc(table->n_cols * sizeof *indexed);
1776
 
        memset(indexed, 0, table->n_cols * sizeof *indexed);
 
1830
        indexed = mem_zalloc(table->n_cols * sizeof *indexed);
1777
1831
 
1778
 
        /* Mark with 0 table columns already contained in new_index */
 
1832
        /* Mark the table columns already contained in new_index */
1779
1833
        for (i = 0; i < new_index->n_def; i++) {
1780
1834
 
1781
1835
                field = dict_index_get_nth_field(new_index, i);
1804
1858
 
1805
1859
        mem_free(indexed);
1806
1860
 
1807
 
        if ((index->type) & DICT_UNIQUE) {
 
1861
        if (dict_index_is_unique(index)) {
1808
1862
                new_index->n_uniq = index->n_fields;
1809
1863
        } else {
1810
1864
                new_index->n_uniq = new_index->n_def;
1824
1878
 
1825
1879
/*************************************************************************
1826
1880
Checks if a table is referenced by foreign keys. */
1827
 
 
 
1881
UNIV_INTERN
1828
1882
ibool
1829
 
dict_table_referenced_by_foreign_key(
 
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(
1830
1898
/*=================================*/
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);
 
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);
1841
1969
}
1842
1970
 
1843
1971
/*************************************************************************
1877
2005
        dict_foreign_free(foreign);
1878
2006
}
1879
2007
 
 
2008
#ifndef UNIV_HOTBACKUP
1880
2009
/**************************************************************************
1881
2010
Looks for the foreign constraint from the foreign and referenced lists
1882
2011
of a table. */
1917
2046
        return(NULL);
1918
2047
}
1919
2048
 
1920
 
#ifndef UNIV_HOTBACKUP
1921
2049
/*************************************************************************
1922
2050
Tries to find an index whose first fields are the columns in the array,
1923
 
in the same order. */
 
2051
in the same order and is not marked for deletion and is not the same
 
2052
as types_idx. */
1924
2053
static
1925
2054
dict_index_t*
1926
2055
dict_foreign_find_index(
1939
2068
                                be declared NOT NULL */
1940
2069
{
1941
2070
        dict_index_t*   index;
1942
 
        dict_field_t*   field;
1943
 
        const char*     col_name;
1944
 
        ulint           i;
1945
2071
 
1946
2072
        index = dict_table_get_first_index(table);
1947
2073
 
1948
2074
        while (index != NULL) {
1949
 
                if (dict_index_get_n_fields(index) >= n_cols) {
 
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;
1950
2083
 
1951
2084
                        for (i = 0; i < n_cols; i++) {
 
2085
                                dict_field_t*   field;
 
2086
                                const char*     col_name;
 
2087
 
1952
2088
                                field = dict_index_get_nth_field(index, i);
1953
2089
 
1954
2090
                                col_name = dict_table_get_col_name(
1989
2125
                        }
1990
2126
                }
1991
2127
 
 
2128
next_rec:
1992
2129
                index = dict_table_get_next_index(index);
1993
2130
        }
1994
2131
 
1996
2133
}
1997
2134
 
1998
2135
/**************************************************************************
 
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
/**************************************************************************
1999
2196
Report an error in a foreign key definition. */
2000
2197
static
2001
2198
void
2043
2240
the object if there already is an object with the same identifier in.
2044
2241
At least one of the foreign table and the referenced table must already
2045
2242
be in the dictionary cache! */
2046
 
 
 
2243
UNIV_INTERN
2047
2244
ulint
2048
2245
dict_foreign_add_to_cache(
2049
2246
/*======================*/
2086
2283
        if (for_in_cache->referenced_table == NULL && ref_table) {
2087
2284
                index = dict_foreign_find_index(
2088
2285
                        ref_table,
2089
 
                        (const char**) for_in_cache->referenced_col_names,
 
2286
                        for_in_cache->referenced_col_names,
2090
2287
                        for_in_cache->n_fields, for_in_cache->foreign_index,
2091
2288
                        check_charsets, FALSE);
2092
2289
 
2118
2315
        if (for_in_cache->foreign_table == NULL && for_table) {
2119
2316
                index = dict_foreign_find_index(
2120
2317
                        for_table,
2121
 
                        (const char**) for_in_cache->foreign_col_names,
 
2318
                        for_in_cache->foreign_col_names,
2122
2319
                        for_in_cache->n_fields,
2123
2320
                        for_in_cache->referenced_index, check_charsets,
2124
2321
                        for_in_cache->type
2165
2362
Scans from pointer onwards. Stops if is at the start of a copy of
2166
2363
'string' where characters are compared without case sensitivity, and
2167
2364
only outside `` or "" quotes. Stops also at '\0'. */
2168
 
 
 
2365
UNIV_INTERN
2169
2366
const char*
2170
2367
dict_scan_to(
2171
2368
/*=========*/
2683
2880
                                        in the SQL string */
2684
2881
        const char*     ptr)            /* in: place of the syntax error */
2685
2882
{
2686
 
        FILE*    ef = dict_foreign_err_file;
 
2883
        FILE*   ef = dict_foreign_err_file;
2687
2884
 
2688
2885
        mutex_enter(&dict_foreign_err_mutex);
2689
2886
        dict_foreign_error_report_low(ef, name);
3273
3470
 
3274
3471
/**************************************************************************
3275
3472
Determines whether a string starts with the specified keyword. */
3276
 
 
 
3473
UNIV_INTERN
3277
3474
ibool
3278
3475
dict_str_starts_with_keyword(
3279
3476
/*=========================*/
3296
3493
the indexes for a table have been created. Each foreign key constraint must
3297
3494
be accompanied with indexes in both participating tables. The indexes are
3298
3495
allowed to contain more fields than mentioned in the constraint. */
3299
 
 
 
3496
UNIV_INTERN
3300
3497
ulint
3301
3498
dict_create_foreign_constraints(
3302
3499
/*============================*/
3339
3536
 
3340
3537
/**************************************************************************
3341
3538
Parses the CONSTRAINT id's to be dropped in an ALTER TABLE statement. */
3342
 
 
 
3539
UNIV_INTERN
3343
3540
ulint
3344
3541
dict_foreign_parse_drop_constraints(
3345
3542
/*================================*/
3475
3672
 
3476
3673
/*==================== END OF FOREIGN KEY PROCESSING ====================*/
3477
3674
 
3478
 
#ifdef UNIV_DEBUG
 
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
3479
3691
/**************************************************************************
3480
3692
Returns an index object if it is found in the dictionary cache. */
3481
 
 
 
3693
UNIV_INTERN
3482
3694
dict_index_t*
3483
3695
dict_index_get_if_in_cache(
3484
3696
/*=======================*/
3493
3705
 
3494
3706
        mutex_enter(&(dict_sys->mutex));
3495
3707
 
3496
 
        index = dict_index_find_on_id_low(index_id);
 
3708
        index = dict_index_get_if_in_cache_low(index_id);
3497
3709
 
3498
3710
        mutex_exit(&(dict_sys->mutex));
3499
3711
 
3500
3712
        return(index);
3501
3713
}
3502
 
#endif /* UNIV_DEBUG */
 
3714
#endif /* UNIV_DEBUG || UNIV_BUF_DEBUG */
3503
3715
 
3504
3716
#ifdef UNIV_DEBUG
3505
3717
/**************************************************************************
3506
3718
Checks that a tuple has n_fields_cmp value in a sensible range, so that
3507
3719
no comparison can occur with the page number field in a node pointer. */
3508
 
 
 
3720
UNIV_INTERN
3509
3721
ibool
3510
3722
dict_index_check_search_tuple(
3511
3723
/*==========================*/
3512
 
                                /* out: TRUE if ok */
3513
 
        dict_index_t*   index,  /* in: index tree */
3514
 
        dtuple_t*       tuple)  /* in: tuple used in a search */
 
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 */
3515
3727
{
3516
3728
        ut_a(index);
3517
3729
        ut_a(dtuple_get_n_fields_cmp(tuple)
3522
3734
 
3523
3735
/**************************************************************************
3524
3736
Builds a node pointer out of a physical record and a page number. */
3525
 
 
 
3737
UNIV_INTERN
3526
3738
dtuple_t*
3527
3739
dict_index_build_node_ptr(
3528
3740
/*======================*/
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 */
 
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 */
3537
3751
{
3538
3752
        dtuple_t*       tuple;
3539
3753
        dfield_t*       field;
3590
3804
/**************************************************************************
3591
3805
Copies an initial segment of a physical record, long enough to specify an
3592
3806
index entry uniquely. */
3593
 
 
 
3807
UNIV_INTERN
3594
3808
rec_t*
3595
3809
dict_index_copy_rec_order_prefix(
3596
3810
/*=============================*/
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 */
 
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 */
3604
3819
{
3605
3820
        ulint           n;
3606
3821
 
3619
3834
 
3620
3835
/**************************************************************************
3621
3836
Builds a typed data tuple out of a physical record. */
3622
 
 
 
3837
UNIV_INTERN
3623
3838
dtuple_t*
3624
3839
dict_index_build_data_tuple(
3625
3840
/*========================*/
3647
3862
 
3648
3863
/*************************************************************************
3649
3864
Calculates the minimum record length in an index. */
3650
 
 
 
3865
UNIV_INTERN
3651
3866
ulint
3652
3867
dict_index_calc_min_rec_len(
3653
3868
/*========================*/
3654
 
        dict_index_t*   index)  /* in: index */
 
3869
        const dict_index_t*     index)  /* in: index */
3655
3870
{
3656
3871
        ulint   sum     = 0;
3657
3872
        ulint   i;
3698
3913
/*************************************************************************
3699
3914
Calculates new estimates for table and index statistics. The statistics
3700
3915
are used in query optimization. */
3701
 
 
 
3916
UNIV_INTERN
3702
3917
void
3703
3918
dict_update_statistics_low(
3704
3919
/*=======================*/
3705
 
        dict_table_t*   table,          /* in: table */
 
3920
        dict_table_t*   table,          /* in/out: table */
3706
3921
        ibool           has_dict_mutex __attribute__((unused)))
3707
3922
                                        /* in: TRUE if the caller has the
3708
3923
                                        dictionary mutex */
3782
3997
/*************************************************************************
3783
3998
Calculates new estimates for table and index statistics. The statistics
3784
3999
are used in query optimization. */
3785
 
 
 
4000
UNIV_INTERN
3786
4001
void
3787
4002
dict_update_statistics(
3788
4003
/*===================*/
3789
 
        dict_table_t*   table)  /* in: table */
 
4004
        dict_table_t*   table)  /* in/out: table */
3790
4005
{
3791
4006
        dict_update_statistics_low(table, FALSE);
3792
4007
}
3793
4008
 
3794
4009
/**************************************************************************
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
 
/**************************************************************************
3807
4010
Prints info of a foreign key constraint. */
3808
4011
static
3809
4012
void
3835
4038
 
3836
4039
/**************************************************************************
3837
4040
Prints a table data. */
3838
 
 
 
4041
UNIV_INTERN
3839
4042
void
3840
4043
dict_table_print(
3841
4044
/*=============*/
3848
4051
 
3849
4052
/**************************************************************************
3850
4053
Prints a table data when we know the table name. */
3851
 
 
 
4054
UNIV_INTERN
3852
4055
void
3853
4056
dict_table_print_by_name(
3854
4057
/*=====================*/
3868
4071
 
3869
4072
/**************************************************************************
3870
4073
Prints a table data. */
3871
 
 
 
4074
UNIV_INTERN
3872
4075
void
3873
4076
dict_table_print_low(
3874
4077
/*=================*/
3884
4087
 
3885
4088
        fprintf(stderr,
3886
4089
                "--------------------------------------\n"
3887
 
                "TABLE: name %s, id %lu %lu, columns %lu, indexes %lu,"
3888
 
                " appr.rows %lu\n"
 
4090
                "TABLE: name %s, id %lu %lu, flags %lx, columns %lu,"
 
4091
                " indexes %lu, appr.rows %lu\n"
3889
4092
                "  COLUMNS: ",
3890
4093
                table->name,
3891
4094
                (ulong) ut_dulint_get_high(table->id),
3892
4095
                (ulong) ut_dulint_get_low(table->id),
 
4096
                (ulong) table->flags,
3893
4097
                (ulong) table->n_cols,
3894
4098
                (ulong) UT_LIST_GET_LEN(table->indexes),
3895
4099
                (ulong) table->stat_n_rows);
3951
4155
/*=================*/
3952
4156
        dict_index_t*   index)  /* in: index */
3953
4157
{
3954
 
        ib_longlong     n_vals;
 
4158
        ib_int64_t      n_vals;
3955
4159
        ulint           i;
 
4160
        const char*     type_string;
3956
4161
 
3957
4162
        ut_ad(mutex_own(&(dict_sys->mutex)));
3958
4163
 
3963
4168
                n_vals = index->stat_n_diff_key_vals[1];
3964
4169
        }
3965
4170
 
 
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
 
3966
4179
        fprintf(stderr,
3967
4180
                "  INDEX: name %s, id %lu %lu, fields %lu/%lu,"
3968
4181
                " uniq %lu, type %lu\n"
4014
4227
/**************************************************************************
4015
4228
Outputs info on a foreign key of a table in a format suitable for
4016
4229
CREATE TABLE. */
4017
 
 
 
4230
UNIV_INTERN
4018
4231
void
4019
4232
dict_print_info_on_foreign_key_in_create_format(
4020
4233
/*============================================*/
4111
4324
 
4112
4325
/**************************************************************************
4113
4326
Outputs info on foreign keys of a table. */
4114
 
 
 
4327
UNIV_INTERN
4115
4328
void
4116
4329
dict_print_info_on_foreign_keys(
4117
4330
/*============================*/
4201
4414
 
4202
4415
/************************************************************************
4203
4416
Displays the names of the index and the table. */
 
4417
UNIV_INTERN
4204
4418
void
4205
4419
dict_index_name_print(
4206
4420
/*==================*/
4213
4427
        fputs(" of table ", file);
4214
4428
        ut_print_name(file, trx, TRUE, index->table_name);
4215
4429
}
 
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 */