~drizzle-pbxt/drizzle/drizzle-pbxt-2

« back to all changes in this revision

Viewing changes to plugin/innobase/row/row0merge.c

  • Committer: Paul McCullagh
  • Date: 2009-11-10 14:18:39 UTC
  • mfrom: (1038.1.7 drizzle-pbxt-pre-merge)
  • Revision ID: paul.mccullagh@primebase.org-20091110141839-2j3k43b17ag6f605
Merged Drizzle trunk and PBXT 1.0.09

Show diffs side-by-side

added added

removed removed

Lines of Context:
16
16
 
17
17
*****************************************************************************/
18
18
 
19
 
/******************************************************
 
19
/**************************************************//**
 
20
@file row/row0merge.c
20
21
New index creation routines using a merge sort
21
22
 
22
23
Created 12/4/2005 Jan Lindstrom
57
58
#include "handler0alter.h"
58
59
 
59
60
#ifdef UNIV_DEBUG
60
 
/* Set these in order ot enable debug printout. */
 
61
/** Set these in order ot enable debug printout. */
 
62
/* @{ */
61
63
static ibool    row_merge_print_cmp;
62
64
static ibool    row_merge_print_read;
63
65
static ibool    row_merge_print_write;
 
66
/* @} */
64
67
#endif /* UNIV_DEBUG */
65
68
 
66
 
/* Block size for I/O operations in merge sort.  The minimum is
67
 
UNIV_PAGE_SIZE, or page_get_free_space_of_empty() rounded to a power of 2.
 
69
/** @brief Block size for I/O operations in merge sort.
 
70
 
 
71
The minimum is UNIV_PAGE_SIZE, or page_get_free_space_of_empty()
 
72
rounded to a power of 2.
68
73
 
69
74
When not creating a PRIMARY KEY that contains column prefixes, this
70
75
can be set as small as UNIV_PAGE_SIZE / 2.  See the comment above
71
76
ut_ad(data_size < sizeof(row_merge_block_t)). */
72
 
 
73
77
typedef byte    row_merge_block_t[1048576];
74
78
 
75
 
/* Secondary buffer for I/O operations of merge records.  This buffer
76
 
is used for writing or reading a record that spans two row_merge_block_t.
77
 
Thus, it must be able to hold one merge record, whose maximum size is
78
 
the same as the minimum size of row_merge_block_t. */
 
79
/** @brief Secondary buffer for I/O operations of merge records.
79
80
 
 
81
This buffer is used for writing or reading a record that spans two
 
82
row_merge_block_t.  Thus, it must be able to hold one merge record,
 
83
whose maximum size is the same as the minimum size of
 
84
row_merge_block_t. */
80
85
typedef byte    mrec_buf_t[UNIV_PAGE_SIZE];
81
86
 
82
 
/* Merge record in row_merge_block_t.  The format is the same as a
83
 
record in ROW_FORMAT=COMPACT with the exception that the
84
 
REC_N_NEW_EXTRA_BYTES are omitted. */
 
87
/** @brief Merge record in row_merge_block_t.
 
88
 
 
89
The format is the same as a record in ROW_FORMAT=COMPACT with the
 
90
exception that the REC_N_NEW_EXTRA_BYTES are omitted. */
85
91
typedef byte    mrec_t;
86
92
 
87
 
/* Buffer for sorting in main memory. */
 
93
/** Buffer for sorting in main memory. */
88
94
struct row_merge_buf_struct {
89
 
        mem_heap_t*     heap;           /* memory heap where allocated */
90
 
        dict_index_t*   index;          /* the index the tuples belong to */
91
 
        ulint           total_size;     /* total amount of data bytes */
92
 
        ulint           n_tuples;       /* number of data tuples */
93
 
        ulint           max_tuples;     /* maximum number of data tuples */
94
 
        const dfield_t**tuples;         /* array of pointers to
 
95
        mem_heap_t*     heap;           /*!< memory heap where allocated */
 
96
        dict_index_t*   index;          /*!< the index the tuples belong to */
 
97
        ulint           total_size;     /*!< total amount of data bytes */
 
98
        ulint           n_tuples;       /*!< number of data tuples */
 
99
        ulint           max_tuples;     /*!< maximum number of data tuples */
 
100
        const dfield_t**tuples;         /*!< array of pointers to
95
101
                                        arrays of fields that form
96
102
                                        the data tuples */
97
 
        const dfield_t**tmp_tuples;     /* temporary copy of tuples,
 
103
        const dfield_t**tmp_tuples;     /*!< temporary copy of tuples,
98
104
                                        for sorting */
99
105
};
100
106
 
 
107
/** Buffer for sorting in main memory. */
101
108
typedef struct row_merge_buf_struct row_merge_buf_t;
102
109
 
103
 
/* Information about temporary files used in merge sort are stored
104
 
to this structure */
105
 
 
 
110
/** Information about temporary files used in merge sort */
106
111
struct merge_file_struct {
107
 
        int     fd;             /* File descriptor */
108
 
        ulint   offset;         /* File offset */
 
112
        int     fd;             /*!< file descriptor */
 
113
        ulint   offset;         /*!< file offset */
109
114
};
110
115
 
 
116
/** Information about temporary files used in merge sort */
111
117
typedef struct merge_file_struct merge_file_t;
112
118
 
113
119
#ifdef UNIV_DEBUG
114
 
/**********************************************************
 
120
/******************************************************//**
115
121
Display a merge tuple. */
116
122
static
117
123
void
118
124
row_merge_tuple_print(
119
125
/*==================*/
120
 
        FILE*           f,      /* in: output stream */
121
 
        const dfield_t* entry,  /* in: tuple to print */
122
 
        ulint           n_fields)/* in: number of fields in the tuple */
 
126
        FILE*           f,      /*!< in: output stream */
 
127
        const dfield_t* entry,  /*!< in: tuple to print */
 
128
        ulint           n_fields)/*!< in: number of fields in the tuple */
123
129
{
124
130
        ulint   j;
125
131
 
146
152
}
147
153
#endif /* UNIV_DEBUG */
148
154
 
149
 
/**********************************************************
150
 
Allocate a sort buffer. */
 
155
/******************************************************//**
 
156
Allocate a sort buffer.
 
157
@return own: sort buffer */
151
158
static
152
159
row_merge_buf_t*
153
160
row_merge_buf_create_low(
154
161
/*=====================*/
155
 
                                        /* out,own: sort buffer */
156
 
        mem_heap_t*     heap,           /* in: heap where allocated */
157
 
        dict_index_t*   index,          /* in: secondary index */
158
 
        ulint           max_tuples,     /* in: maximum number of data tuples */
159
 
        ulint           buf_size)       /* in: size of the buffer, in bytes */
 
162
        mem_heap_t*     heap,           /*!< in: heap where allocated */
 
163
        dict_index_t*   index,          /*!< in: secondary index */
 
164
        ulint           max_tuples,     /*!< in: maximum number of data tuples */
 
165
        ulint           buf_size)       /*!< in: size of the buffer, in bytes */
160
166
{
161
167
        row_merge_buf_t*        buf;
162
168
 
175
181
        return(buf);
176
182
}
177
183
 
178
 
/**********************************************************
179
 
Allocate a sort buffer. */
 
184
/******************************************************//**
 
185
Allocate a sort buffer.
 
186
@return own: sort buffer */
180
187
static
181
188
row_merge_buf_t*
182
189
row_merge_buf_create(
183
190
/*=================*/
184
 
                                /* out,own: sort buffer */
185
 
        dict_index_t*   index)  /* in: secondary index */
 
191
        dict_index_t*   index)  /*!< in: secondary index */
186
192
{
187
193
        row_merge_buf_t*        buf;
188
194
        ulint                   max_tuples;
201
207
        return(buf);
202
208
}
203
209
 
204
 
/**********************************************************
205
 
Empty a sort buffer. */
 
210
/******************************************************//**
 
211
Empty a sort buffer.
 
212
@return sort buffer */
206
213
static
207
214
row_merge_buf_t*
208
215
row_merge_buf_empty(
209
216
/*================*/
210
 
                                        /* out: sort buffer */
211
 
        row_merge_buf_t*        buf)    /* in,own: sort buffer */
 
217
        row_merge_buf_t*        buf)    /*!< in,own: sort buffer */
212
218
{
213
219
        ulint           buf_size;
214
220
        ulint           max_tuples      = buf->max_tuples;
222
228
        return(row_merge_buf_create_low(heap, index, max_tuples, buf_size));
223
229
}
224
230
 
225
 
/**********************************************************
 
231
/******************************************************//**
226
232
Deallocate a sort buffer. */
227
233
static
228
234
void
229
235
row_merge_buf_free(
230
236
/*===============*/
231
 
        row_merge_buf_t*        buf)    /* in,own: sort buffer, to be freed */
 
237
        row_merge_buf_t*        buf)    /*!< in,own: sort buffer, to be freed */
232
238
{
233
239
        mem_heap_free(buf->heap);
234
240
}
235
241
 
236
 
/**********************************************************
237
 
Insert a data tuple into a sort buffer. */
 
242
/******************************************************//**
 
243
Insert a data tuple into a sort buffer.
 
244
@return TRUE if added, FALSE if out of space */
238
245
static
239
246
ibool
240
247
row_merge_buf_add(
241
248
/*==============*/
242
 
                                        /* out: TRUE if added,
243
 
                                        FALSE if out of space */
244
 
        row_merge_buf_t*        buf,    /* in/out: sort buffer */
245
 
        const dtuple_t*         row,    /* in: row in clustered index */
246
 
        const row_ext_t*        ext)    /* in: cache of externally stored
 
249
        row_merge_buf_t*        buf,    /*!< in/out: sort buffer */
 
250
        const dtuple_t*         row,    /*!< in: row in clustered index */
 
251
        const row_ext_t*        ext)    /*!< in: cache of externally stored
247
252
                                        column prefixes, or NULL */
248
253
{
249
254
        ulint                   i;
389
394
        return(TRUE);
390
395
}
391
396
 
392
 
/* Structure for reporting duplicate records. */
 
397
/** Structure for reporting duplicate records. */
393
398
struct row_merge_dup_struct {
394
 
        const dict_index_t*     index;          /* index being sorted */
395
 
        TABLE*                  table;          /* MySQL table object */
396
 
        ulint                   n_dup;          /* number of duplicates */
 
399
        const dict_index_t*     index;          /*!< index being sorted */
 
400
        TABLE*                  table;          /*!< MySQL table object */
 
401
        ulint                   n_dup;          /*!< number of duplicates */
397
402
};
398
403
 
 
404
/** Structure for reporting duplicate records. */
399
405
typedef struct row_merge_dup_struct row_merge_dup_t;
400
406
 
401
 
/*****************************************************************
 
407
/*************************************************************//**
402
408
Report a duplicate key. */
403
409
static
404
410
void
405
411
row_merge_dup_report(
406
412
/*=================*/
407
 
        row_merge_dup_t*        dup,    /* in/out: for reporting duplicates */
408
 
        const dfield_t*         entry)  /* in: duplicate index entry */
 
413
        row_merge_dup_t*        dup,    /*!< in/out: for reporting duplicates */
 
414
        const dfield_t*         entry)  /*!< in: duplicate index entry */
409
415
{
410
416
        mrec_buf_t              buf;
411
417
        const dtuple_t*         tuple;
442
448
        }
443
449
}
444
450
 
445
 
/*****************************************************************
446
 
Compare two tuples. */
 
451
/*************************************************************//**
 
452
Compare two tuples.
 
453
@return 1, 0, -1 if a is greater, equal, less, respectively, than b */
447
454
static
448
455
int
449
456
row_merge_tuple_cmp(
450
457
/*================*/
451
 
                                        /* out: 1, 0, -1 if a is greater,
452
 
                                        equal, less, respectively, than b */
453
 
        ulint                   n_field,/* in: number of fields */
454
 
        const dfield_t*         a,      /* in: first tuple to be compared */
455
 
        const dfield_t*         b,      /* in: second tuple to be compared */
456
 
        row_merge_dup_t*        dup)    /* in/out: for reporting duplicates */
 
458
        ulint                   n_field,/*!< in: number of fields */
 
459
        const dfield_t*         a,      /*!< in: first tuple to be compared */
 
460
        const dfield_t*         b,      /*!< in: second tuple to be compared */
 
461
        row_merge_dup_t*        dup)    /*!< in/out: for reporting duplicates */
457
462
{
458
463
        int             cmp;
459
464
        const dfield_t* field   = a;
484
489
        return(cmp);
485
490
}
486
491
 
487
 
/**************************************************************************
 
492
/** Wrapper for row_merge_tuple_sort() to inject some more context to
 
493
UT_SORT_FUNCTION_BODY().
 
494
@param a        array of tuples that being sorted
 
495
@param b        aux (work area), same size as tuples[]
 
496
@param c        lower bound of the sorting area, inclusive
 
497
@param d        upper bound of the sorting area, inclusive */
 
498
#define row_merge_tuple_sort_ctx(a,b,c,d) \
 
499
        row_merge_tuple_sort(n_field, dup, a, b, c, d)
 
500
/** Wrapper for row_merge_tuple_cmp() to inject some more context to
 
501
UT_SORT_FUNCTION_BODY().
 
502
@param a        first tuple to be compared
 
503
@param b        second tuple to be compared
 
504
@return 1, 0, -1 if a is greater, equal, less, respectively, than b */
 
505
#define row_merge_tuple_cmp_ctx(a,b) row_merge_tuple_cmp(n_field, a, b, dup)
 
506
 
 
507
/**********************************************************************//**
488
508
Merge sort the tuple buffer in main memory. */
489
509
static
490
510
void
491
511
row_merge_tuple_sort(
492
512
/*=================*/
493
 
        ulint                   n_field,/* in: number of fields */
494
 
        row_merge_dup_t*        dup,    /* in/out: for reporting duplicates */
495
 
        const dfield_t**        tuples, /* in/out: tuples */
496
 
        const dfield_t**        aux,    /* in/out: work area */
497
 
        ulint                   low,    /* in: lower bound of the
 
513
        ulint                   n_field,/*!< in: number of fields */
 
514
        row_merge_dup_t*        dup,    /*!< in/out: for reporting duplicates */
 
515
        const dfield_t**        tuples, /*!< in/out: tuples */
 
516
        const dfield_t**        aux,    /*!< in/out: work area */
 
517
        ulint                   low,    /*!< in: lower bound of the
498
518
                                        sorting area, inclusive */
499
 
        ulint                   high)   /* in: upper bound of the
 
519
        ulint                   high)   /*!< in: upper bound of the
500
520
                                        sorting area, exclusive */
501
521
{
502
 
#define row_merge_tuple_sort_ctx(a,b,c,d) \
503
 
        row_merge_tuple_sort(n_field, dup, a, b, c, d)
504
 
#define row_merge_tuple_cmp_ctx(a,b) row_merge_tuple_cmp(n_field, a, b, dup)
505
 
 
506
522
        UT_SORT_FUNCTION_BODY(row_merge_tuple_sort_ctx,
507
523
                              tuples, aux, low, high, row_merge_tuple_cmp_ctx);
508
524
}
509
525
 
510
 
/**********************************************************
 
526
/******************************************************//**
511
527
Sort a buffer. */
512
528
static
513
529
void
514
530
row_merge_buf_sort(
515
531
/*===============*/
516
 
        row_merge_buf_t*        buf,    /* in/out: sort buffer */
517
 
        row_merge_dup_t*        dup)    /* in/out: for reporting duplicates */
 
532
        row_merge_buf_t*        buf,    /*!< in/out: sort buffer */
 
533
        row_merge_dup_t*        dup)    /*!< in/out: for reporting duplicates */
518
534
{
519
535
        row_merge_tuple_sort(dict_index_get_n_unique(buf->index), dup,
520
536
                             buf->tuples, buf->tmp_tuples, 0, buf->n_tuples);
521
537
}
522
538
 
523
 
/**********************************************************
 
539
/******************************************************//**
524
540
Write a buffer to a block. */
525
541
static
526
542
void
527
543
row_merge_buf_write(
528
544
/*================*/
529
 
        const row_merge_buf_t*  buf,    /* in: sorted buffer */
 
545
        const row_merge_buf_t*  buf,    /*!< in: sorted buffer */
530
546
#ifdef UNIV_DEBUG
531
 
        const merge_file_t*     of,     /* in: output file */
 
547
        const merge_file_t*     of,     /*!< in: output file */
532
548
#endif /* UNIV_DEBUG */
533
 
        row_merge_block_t*      block)  /* out: buffer for writing to file */
 
549
        row_merge_block_t*      block)  /*!< out: buffer for writing to file */
534
550
#ifndef UNIV_DEBUG
535
551
# define row_merge_buf_write(buf, of, block) row_merge_buf_write(buf, block)
536
552
#endif /* !UNIV_DEBUG */
599
615
#endif /* UNIV_DEBUG */
600
616
}
601
617
 
602
 
/**********************************************************
603
 
Create a memory heap and allocate space for row_merge_rec_offsets(). */
 
618
/******************************************************//**
 
619
Create a memory heap and allocate space for row_merge_rec_offsets().
 
620
@return memory heap */
604
621
static
605
622
mem_heap_t*
606
623
row_merge_heap_create(
607
624
/*==================*/
608
 
                                                /* out: memory heap */
609
 
        const dict_index_t*     index,          /* in: record descriptor */
610
 
        ulint**                 offsets1,       /* out: offsets */
611
 
        ulint**                 offsets2)       /* out: offsets */
 
625
        const dict_index_t*     index,          /*!< in: record descriptor */
 
626
        ulint**                 offsets1,       /*!< out: offsets */
 
627
        ulint**                 offsets2)       /*!< out: offsets */
612
628
{
613
629
        ulint           i       = 1 + REC_OFFS_HEADER_SIZE
614
630
                + dict_index_get_n_fields(index);
623
639
        return(heap);
624
640
}
625
641
 
626
 
/**************************************************************************
 
642
/**********************************************************************//**
627
643
Search an index object by name and column names.  If several indexes match,
628
 
return the index with the max id. */
 
644
return the index with the max id.
 
645
@return matching index, NULL if not found */
629
646
static
630
647
dict_index_t*
631
648
row_merge_dict_table_get_index(
632
649
/*===========================*/
633
 
                                                /* out: matching index,
634
 
                                                NULL if not found */
635
 
        dict_table_t*           table,          /* in: table */
636
 
        const merge_index_def_t*index_def)      /* in: index definition */
 
650
        dict_table_t*           table,          /*!< in: table */
 
651
        const merge_index_def_t*index_def)      /*!< in: index definition */
637
652
{
638
653
        ulint           i;
639
654
        dict_index_t*   index;
653
668
        return(index);
654
669
}
655
670
 
656
 
/************************************************************************
657
 
Read a merge block from the file system. */
 
671
/********************************************************************//**
 
672
Read a merge block from the file system.
 
673
@return TRUE if request was successful, FALSE if fail */
658
674
static
659
675
ibool
660
676
row_merge_read(
661
677
/*===========*/
662
 
                                        /* out: TRUE if request was
663
 
                                        successful, FALSE if fail */
664
 
        int                     fd,     /* in: file descriptor */
665
 
        ulint                   offset, /* in: offset where to read */
666
 
        row_merge_block_t*      buf)    /* out: data */
 
678
        int                     fd,     /*!< in: file descriptor */
 
679
        ulint                   offset, /*!< in: offset where to read */
 
680
        row_merge_block_t*      buf)    /*!< out: data */
667
681
{
668
682
        ib_uint64_t     ofs = ((ib_uint64_t) offset) * sizeof *buf;
669
683
        ibool           success;
681
695
        return(UNIV_LIKELY(success));
682
696
}
683
697
 
684
 
/************************************************************************
685
 
Read a merge block from the file system. */
 
698
/********************************************************************//**
 
699
Read a merge block from the file system.
 
700
@return TRUE if request was successful, FALSE if fail */
686
701
static
687
702
ibool
688
703
row_merge_write(
689
704
/*============*/
690
 
                                /* out: TRUE if request was
691
 
                                successful, FALSE if fail */
692
 
        int             fd,     /* in: file descriptor */
693
 
        ulint           offset, /* in: offset where to write */
694
 
        const void*     buf)    /* in: data */
 
705
        int             fd,     /*!< in: file descriptor */
 
706
        ulint           offset, /*!< in: offset where to write */
 
707
        const void*     buf)    /*!< in: data */
695
708
{
696
709
        ib_uint64_t     ofs = ((ib_uint64_t) offset)
697
710
                * sizeof(row_merge_block_t);
702
715
                                         sizeof(row_merge_block_t))));
703
716
}
704
717
 
705
 
/************************************************************************
706
 
Read a merge record. */
 
718
/********************************************************************//**
 
719
Read a merge record.
 
720
@return pointer to next record, or NULL on I/O error or end of list */
707
721
static
708
722
const byte*
709
723
row_merge_read_rec(
710
724
/*===============*/
711
 
                                        /* out: pointer to next record,
712
 
                                        or NULL on I/O error
713
 
                                        or end of list */
714
 
        row_merge_block_t*      block,  /* in/out: file buffer */
715
 
        mrec_buf_t*             buf,    /* in/out: secondary buffer */
716
 
        const byte*             b,      /* in: pointer to record */
717
 
        const dict_index_t*     index,  /* in: index of the record */
718
 
        int                     fd,     /* in: file descriptor */
719
 
        ulint*                  foffs,  /* in/out: file offset */
720
 
        const mrec_t**          mrec,   /* out: pointer to merge record,
 
725
        row_merge_block_t*      block,  /*!< in/out: file buffer */
 
726
        mrec_buf_t*             buf,    /*!< in/out: secondary buffer */
 
727
        const byte*             b,      /*!< in: pointer to record */
 
728
        const dict_index_t*     index,  /*!< in: index of the record */
 
729
        int                     fd,     /*!< in: file descriptor */
 
730
        ulint*                  foffs,  /*!< in/out: file offset */
 
731
        const mrec_t**          mrec,   /*!< out: pointer to merge record,
721
732
                                        or NULL on end of list
722
733
                                        (non-NULL on I/O error) */
723
 
        ulint*                  offsets)/* out: offsets of mrec */
 
734
        ulint*                  offsets)/*!< out: offsets of mrec */
724
735
{
725
736
        ulint   extra_size;
726
737
        ulint   data_size;
838
849
        avail_size = block[1] - b;
839
850
        memcpy(*buf, b, avail_size);
840
851
        *mrec = *buf + extra_size;
841
 
        rec_offs_make_valid(*mrec, index, offsets);
 
852
#ifdef UNIV_DEBUG
 
853
        /* We cannot invoke rec_offs_make_valid() here, because there
 
854
        are no REC_N_NEW_EXTRA_BYTES between extra_size and data_size.
 
855
        Similarly, rec_offs_validate() would fail, because it invokes
 
856
        rec_get_status(). */
 
857
        offsets[2] = (ulint) *mrec;
 
858
        offsets[3] = (ulint) index;
 
859
#endif /* UNIV_DEBUG */
842
860
 
843
861
        if (!row_merge_read(fd, ++(*foffs), block)) {
844
862
 
866
884
        return(b);
867
885
}
868
886
 
869
 
/************************************************************************
 
887
/********************************************************************//**
870
888
Write a merge record. */
871
889
static
872
890
void
873
891
row_merge_write_rec_low(
874
892
/*====================*/
875
 
        byte*           b,      /* out: buffer */
876
 
        ulint           e,      /* in: encoded extra_size */
 
893
        byte*           b,      /*!< out: buffer */
 
894
        ulint           e,      /*!< in: encoded extra_size */
877
895
#ifdef UNIV_DEBUG
878
 
        ulint           size,   /* in: total size to write */
879
 
        int             fd,     /* in: file descriptor */
880
 
        ulint           foffs,  /* in: file offset */
 
896
        ulint           size,   /*!< in: total size to write */
 
897
        int             fd,     /*!< in: file descriptor */
 
898
        ulint           foffs,  /*!< in: file offset */
881
899
#endif /* UNIV_DEBUG */
882
 
        const mrec_t*   mrec,   /* in: record to write */
883
 
        const ulint*    offsets)/* in: offsets of mrec */
 
900
        const mrec_t*   mrec,   /*!< in: record to write */
 
901
        const ulint*    offsets)/*!< in: offsets of mrec */
884
902
#ifndef UNIV_DEBUG
885
903
# define row_merge_write_rec_low(b, e, size, fd, foffs, mrec, offsets)  \
886
904
        row_merge_write_rec_low(b, e, mrec, offsets)
909
927
        ut_ad(b + rec_offs_size(offsets) == end);
910
928
}
911
929
 
912
 
/************************************************************************
913
 
Write a merge record. */
 
930
/********************************************************************//**
 
931
Write a merge record.
 
932
@return pointer to end of block, or NULL on error */
914
933
static
915
934
byte*
916
935
row_merge_write_rec(
917
936
/*================*/
918
 
                                        /* out: pointer to end of block,
919
 
                                        or NULL on error */
920
 
        row_merge_block_t*      block,  /* in/out: file buffer */
921
 
        mrec_buf_t*             buf,    /* in/out: secondary buffer */
922
 
        byte*                   b,      /* in: pointer to end of block */
923
 
        int                     fd,     /* in: file descriptor */
924
 
        ulint*                  foffs,  /* in/out: file offset */
925
 
        const mrec_t*           mrec,   /* in: record to write */
926
 
        const ulint*            offsets)/* in: offsets of mrec */
 
937
        row_merge_block_t*      block,  /*!< in/out: file buffer */
 
938
        mrec_buf_t*             buf,    /*!< in/out: secondary buffer */
 
939
        byte*                   b,      /*!< in: pointer to end of block */
 
940
        int                     fd,     /*!< in: file descriptor */
 
941
        ulint*                  foffs,  /*!< in/out: file offset */
 
942
        const mrec_t*           mrec,   /*!< in: record to write */
 
943
        const ulint*            offsets)/*!< in: offsets of mrec */
927
944
{
928
945
        ulint   extra_size;
929
946
        ulint   size;
977
994
        return(b);
978
995
}
979
996
 
980
 
/************************************************************************
981
 
Write an end-of-list marker. */
 
997
/********************************************************************//**
 
998
Write an end-of-list marker.
 
999
@return pointer to end of block, or NULL on error */
982
1000
static
983
1001
byte*
984
1002
row_merge_write_eof(
985
1003
/*================*/
986
 
                                        /* out: pointer to end of block,
987
 
                                        or NULL on error */
988
 
        row_merge_block_t*      block,  /* in/out: file buffer */
989
 
        byte*                   b,      /* in: pointer to end of block */
990
 
        int                     fd,     /* in: file descriptor */
991
 
        ulint*                  foffs)  /* in/out: file offset */
 
1004
        row_merge_block_t*      block,  /*!< in/out: file buffer */
 
1005
        byte*                   b,      /*!< in: pointer to end of block */
 
1006
        int                     fd,     /*!< in: file descriptor */
 
1007
        ulint*                  foffs)  /*!< in/out: file offset */
992
1008
{
993
1009
        ut_ad(block);
994
1010
        ut_ad(b >= block[0]);
1018
1034
        return(block[0]);
1019
1035
}
1020
1036
 
1021
 
/*****************************************************************
1022
 
Compare two merge records. */
 
1037
/*************************************************************//**
 
1038
Compare two merge records.
 
1039
@return 1, 0, -1 if mrec1 is greater, equal, less, respectively, than mrec2 */
1023
1040
static
1024
1041
int
1025
1042
row_merge_cmp(
1026
1043
/*==========*/
1027
 
                                                /* out: 1, 0, -1 if
1028
 
                                                mrec1 is greater, equal, less,
1029
 
                                                respectively, than mrec2 */
1030
 
        const mrec_t*           mrec1,          /* in: first merge
1031
 
                                                record to be compared */
1032
 
        const mrec_t*           mrec2,          /* in: second merge
1033
 
                                                record to be compared */
1034
 
        const ulint*            offsets1,       /* in: first record offsets */
1035
 
        const ulint*            offsets2,       /* in: second record offsets */
1036
 
        const dict_index_t*     index)          /* in: index */
 
1044
        const mrec_t*           mrec1,          /*!< in: first merge
 
1045
                                                record to be compared */
 
1046
        const mrec_t*           mrec2,          /*!< in: second merge
 
1047
                                                record to be compared */
 
1048
        const ulint*            offsets1,       /*!< in: first record offsets */
 
1049
        const ulint*            offsets2,       /*!< in: second record offsets */
 
1050
        const dict_index_t*     index)          /*!< in: index */
1037
1051
{
1038
1052
        int     cmp;
1039
1053
 
1052
1066
        return(cmp);
1053
1067
}
1054
1068
 
1055
 
/************************************************************************
 
1069
/********************************************************************//**
1056
1070
Reads clustered index of the table and create temporary files
1057
 
containing the index entries for the indexes to be built. */
 
1071
containing the index entries for the indexes to be built.
 
1072
@return DB_SUCCESS or error */
1058
1073
static
1059
1074
ulint
1060
1075
row_merge_read_clustered_index(
1061
1076
/*===========================*/
1062
 
                                        /* out: DB_SUCCESS or error */
1063
 
        trx_t*                  trx,    /* in: transaction */
1064
 
        TABLE*                  table,  /* in/out: MySQL table object,
 
1077
        trx_t*                  trx,    /*!< in: transaction */
 
1078
        TABLE*                  table,  /*!< in/out: MySQL table object,
1065
1079
                                        for reporting erroneous records */
1066
 
        const dict_table_t*     old_table,/* in: table where rows are
 
1080
        const dict_table_t*     old_table,/*!< in: table where rows are
1067
1081
                                        read from */
1068
 
        const dict_table_t*     new_table,/* in: table where indexes are
 
1082
        const dict_table_t*     new_table,/*!< in: table where indexes are
1069
1083
                                        created; identical to old_table
1070
1084
                                        unless creating a PRIMARY KEY */
1071
 
        dict_index_t**          index,  /* in: indexes to be created */
1072
 
        merge_file_t*           files,  /* in: temporary files */
1073
 
        ulint                   n_index,/* in: number of indexes to create */
1074
 
        row_merge_block_t*      block)  /* in/out: file buffer */
 
1085
        dict_index_t**          index,  /*!< in: indexes to be created */
 
1086
        merge_file_t*           files,  /*!< in: temporary files */
 
1087
        ulint                   n_index,/*!< in: number of indexes to create */
 
1088
        row_merge_block_t*      block)  /*!< in/out: file buffer */
1075
1089
{
1076
1090
        dict_index_t*           clust_index;    /* Clustered index */
1077
1091
        mem_heap_t*             row_heap;       /* Heap memory to create
1298
1312
        return(err);
1299
1313
}
1300
1314
 
1301
 
/*****************************************************************
1302
 
Merge two blocks of linked lists on disk and write a bigger block. */
1303
 
static
1304
 
ulint
1305
 
row_merge_blocks(
1306
 
/*=============*/
1307
 
                                        /* out: DB_SUCCESS or error code */
1308
 
        const dict_index_t*     index,  /* in: index being created */
1309
 
        merge_file_t*           file,   /* in/out: file containing
1310
 
                                        index entries */
1311
 
        row_merge_block_t*      block,  /* in/out: 3 buffers */
1312
 
        ulint*                  foffs0, /* in/out: offset of first
1313
 
                                        source list in the file */
1314
 
        ulint*                  foffs1, /* in/out: offset of second
1315
 
                                        source list in the file */
1316
 
        merge_file_t*           of,     /* in/out: output file */
1317
 
        TABLE*                  table)  /* in/out: MySQL table, for
1318
 
                                        reporting erroneous key value
1319
 
                                        if applicable */
1320
 
{
1321
 
        mem_heap_t*     heap;   /* memory heap for offsets0, offsets1 */
1322
 
 
1323
 
        mrec_buf_t      buf[3]; /* buffer for handling split mrec in block[] */
1324
 
        const byte*     b0;     /* pointer to block[0] */
1325
 
        const byte*     b1;     /* pointer to block[1] */
1326
 
        byte*           b2;     /* pointer to block[2] */
1327
 
        const mrec_t*   mrec0;  /* merge rec, points to block[0] or buf[0] */
1328
 
        const mrec_t*   mrec1;  /* merge rec, points to block[1] or buf[1] */
1329
 
        ulint*          offsets0;/* offsets of mrec0 */
1330
 
        ulint*          offsets1;/* offsets of mrec1 */
1331
 
 
1332
 
        heap = row_merge_heap_create(index, &offsets0, &offsets1);
1333
 
 
1334
 
        /* Write a record and read the next record.  Split the output
1335
 
        file in two halves, which can be merged on the following pass. */
 
1315
/** Write a record via buffer 2 and read the next record to buffer N.
 
1316
@param N        number of the buffer (0 or 1)
 
1317
@param AT_END   statement to execute at end of input */
1336
1318
#define ROW_MERGE_WRITE_GET_NEXT(N, AT_END)                             \
1337
1319
        do {                                                            \
1338
1320
                b2 = row_merge_write_rec(&block[2], &buf[2], b2,        \
1353
1335
                }                                                       \
1354
1336
        } while (0)
1355
1337
 
 
1338
/*************************************************************//**
 
1339
Merge two blocks of linked lists on disk and write a bigger block.
 
1340
@return DB_SUCCESS or error code */
 
1341
static
 
1342
ulint
 
1343
row_merge_blocks(
 
1344
/*=============*/
 
1345
        const dict_index_t*     index,  /*!< in: index being created */
 
1346
        merge_file_t*           file,   /*!< in/out: file containing
 
1347
                                        index entries */
 
1348
        row_merge_block_t*      block,  /*!< in/out: 3 buffers */
 
1349
        ulint*                  foffs0, /*!< in/out: offset of first
 
1350
                                        source list in the file */
 
1351
        ulint*                  foffs1, /*!< in/out: offset of second
 
1352
                                        source list in the file */
 
1353
        merge_file_t*           of,     /*!< in/out: output file */
 
1354
        TABLE*                  table)  /*!< in/out: MySQL table, for
 
1355
                                        reporting erroneous key value
 
1356
                                        if applicable */
 
1357
{
 
1358
        mem_heap_t*     heap;   /*!< memory heap for offsets0, offsets1 */
 
1359
 
 
1360
        mrec_buf_t      buf[3]; /*!< buffer for handling split mrec in block[] */
 
1361
        const byte*     b0;     /*!< pointer to block[0] */
 
1362
        const byte*     b1;     /*!< pointer to block[1] */
 
1363
        byte*           b2;     /*!< pointer to block[2] */
 
1364
        const mrec_t*   mrec0;  /*!< merge rec, points to block[0] or buf[0] */
 
1365
        const mrec_t*   mrec1;  /*!< merge rec, points to block[1] or buf[1] */
 
1366
        ulint*          offsets0;/* offsets of mrec0 */
 
1367
        ulint*          offsets1;/* offsets of mrec1 */
 
1368
 
 
1369
        heap = row_merge_heap_create(index, &offsets0, &offsets1);
 
1370
 
 
1371
        /* Write a record and read the next record.  Split the output
 
1372
        file in two halves, which can be merged on the following pass. */
 
1373
 
1356
1374
        if (!row_merge_read(file->fd, *foffs0, &block[0])
1357
1375
            || !row_merge_read(file->fd, *foffs1, &block[1])) {
1358
1376
corrupt:
1419
1437
        return(b2 ? DB_SUCCESS : DB_CORRUPTION);
1420
1438
}
1421
1439
 
1422
 
/*****************************************************************
1423
 
Merge disk files. */
 
1440
/*************************************************************//**
 
1441
Merge disk files.
 
1442
@return DB_SUCCESS or error code */
1424
1443
static
1425
1444
ulint
1426
1445
row_merge(
1427
1446
/*======*/
1428
 
                                        /* out: DB_SUCCESS or error code */
1429
 
        const dict_index_t*     index,  /* in: index being created */
1430
 
        merge_file_t*           file,   /* in/out: file containing
 
1447
        const dict_index_t*     index,  /*!< in: index being created */
 
1448
        merge_file_t*           file,   /*!< in/out: file containing
1431
1449
                                        index entries */
1432
 
        ulint                   half,   /* in: half the file */
1433
 
        row_merge_block_t*      block,  /* in/out: 3 buffers */
1434
 
        int*                    tmpfd,  /* in/out: temporary file handle */
1435
 
        TABLE*                  table)  /* in/out: MySQL table, for
 
1450
        ulint                   half,   /*!< in: half the file */
 
1451
        row_merge_block_t*      block,  /*!< in/out: 3 buffers */
 
1452
        int*                    tmpfd,  /*!< in/out: temporary file handle */
 
1453
        TABLE*                  table)  /*!< in/out: MySQL table, for
1436
1454
                                        reporting erroneous key value
1437
1455
                                        if applicable */
1438
1456
{
1439
 
        ulint           foffs0; /* first input offset */
1440
 
        ulint           foffs1; /* second input offset */
1441
 
        ulint           error;  /* error code */
1442
 
        merge_file_t    of;     /* output file */
 
1457
        ulint           foffs0; /*!< first input offset */
 
1458
        ulint           foffs1; /*!< second input offset */
 
1459
        ulint           error;  /*!< error code */
 
1460
        merge_file_t    of;     /*!< output file */
1443
1461
 
1444
1462
        UNIV_MEM_ASSERT_W(block[0], 3 * sizeof block[0]);
1445
1463
        ut_ad(half > 0);
1483
1501
        return(DB_SUCCESS);
1484
1502
}
1485
1503
 
1486
 
/*****************************************************************
1487
 
Merge disk files. */
 
1504
/*************************************************************//**
 
1505
Merge disk files.
 
1506
@return DB_SUCCESS or error code */
1488
1507
static
1489
1508
ulint
1490
1509
row_merge_sort(
1491
1510
/*===========*/
1492
 
                                        /* out: DB_SUCCESS or error code */
1493
 
        const dict_index_t*     index,  /* in: index being created */
1494
 
        merge_file_t*           file,   /* in/out: file containing
 
1511
        const dict_index_t*     index,  /*!< in: index being created */
 
1512
        merge_file_t*           file,   /*!< in/out: file containing
1495
1513
                                        index entries */
1496
 
        row_merge_block_t*      block,  /* in/out: 3 buffers */
1497
 
        int*                    tmpfd,  /* in/out: temporary file handle */
1498
 
        TABLE*                  table)  /* in/out: MySQL table, for
 
1514
        row_merge_block_t*      block,  /*!< in/out: 3 buffers */
 
1515
        int*                    tmpfd,  /*!< in/out: temporary file handle */
 
1516
        TABLE*                  table)  /*!< in/out: MySQL table, for
1499
1517
                                        reporting erroneous key value
1500
1518
                                        if applicable */
1501
1519
{
1502
 
        ulint   blksz;  /* block size */
 
1520
        ulint   blksz;  /*!< block size */
1503
1521
 
1504
1522
        for (blksz = 1; blksz < file->offset; blksz *= 2) {
1505
1523
                ulint   half;
1517
1535
        return(DB_SUCCESS);
1518
1536
}
1519
1537
 
1520
 
/*****************************************************************
 
1538
/*************************************************************//**
1521
1539
Copy externally stored columns to the data tuple. */
1522
1540
static
1523
1541
void
1524
1542
row_merge_copy_blobs(
1525
1543
/*=================*/
1526
 
        const mrec_t*   mrec,   /* in: merge record */
1527
 
        const ulint*    offsets,/* in: offsets of mrec */
1528
 
        ulint           zip_size,/* in: compressed page size in bytes, or 0 */
1529
 
        dtuple_t*       tuple,  /* in/out: data tuple */
1530
 
        mem_heap_t*     heap)   /* in/out: memory heap */
 
1544
        const mrec_t*   mrec,   /*!< in: merge record */
 
1545
        const ulint*    offsets,/*!< in: offsets of mrec */
 
1546
        ulint           zip_size,/*!< in: compressed page size in bytes, or 0 */
 
1547
        dtuple_t*       tuple,  /*!< in/out: data tuple */
 
1548
        mem_heap_t*     heap)   /*!< in/out: memory heap */
1531
1549
{
1532
1550
        ulint   i;
1533
1551
        ulint   n_fields = dtuple_get_n_fields(tuple);
1555
1573
        }
1556
1574
}
1557
1575
 
1558
 
/************************************************************************
 
1576
/********************************************************************//**
1559
1577
Read sorted file containing index data tuples and insert these data
1560
 
tuples to the index */
 
1578
tuples to the index
 
1579
@return DB_SUCCESS or error number */
1561
1580
static
1562
1581
ulint
1563
1582
row_merge_insert_index_tuples(
1564
1583
/*==========================*/
1565
 
                                        /* out: DB_SUCCESS or error number */
1566
 
        trx_t*                  trx,    /* in: transaction */
1567
 
        dict_index_t*           index,  /* in: index */
1568
 
        dict_table_t*           table,  /* in: new table */
1569
 
        ulint                   zip_size,/* in: compressed page size of
 
1584
        trx_t*                  trx,    /*!< in: transaction */
 
1585
        dict_index_t*           index,  /*!< in: index */
 
1586
        dict_table_t*           table,  /*!< in: new table */
 
1587
        ulint                   zip_size,/*!< in: compressed page size of
1570
1588
                                         the old table, or 0 if uncompressed */
1571
 
        int                     fd,     /* in: file descriptor */
1572
 
        row_merge_block_t*      block)  /* in/out: file buffer */
 
1589
        int                     fd,     /*!< in: file descriptor */
 
1590
        row_merge_block_t*      block)  /*!< in/out: file buffer */
1573
1591
{
1574
1592
        mrec_buf_t              buf;
1575
1593
        const byte*             b;
1677
1695
        return(error);
1678
1696
}
1679
1697
 
1680
 
/*************************************************************************
1681
 
Sets an exclusive lock on a table, for the duration of creating indexes. */
 
1698
/*********************************************************************//**
 
1699
Sets an exclusive lock on a table, for the duration of creating indexes.
 
1700
@return error code or DB_SUCCESS */
1682
1701
UNIV_INTERN
1683
1702
ulint
1684
1703
row_merge_lock_table(
1685
1704
/*=================*/
1686
 
                                        /* out: error code or DB_SUCCESS */
1687
 
        trx_t*          trx,            /* in/out: transaction */
1688
 
        dict_table_t*   table,          /* in: table to lock */
1689
 
        enum lock_mode  mode)           /* in: LOCK_X or LOCK_S */
 
1705
        trx_t*          trx,            /*!< in/out: transaction */
 
1706
        dict_table_t*   table,          /*!< in: table to lock */
 
1707
        enum lock_mode  mode)           /*!< in: LOCK_X or LOCK_S */
1690
1708
{
1691
1709
        mem_heap_t*     heap;
1692
1710
        que_thr_t*      thr;
1756
1774
        return(err);
1757
1775
}
1758
1776
 
1759
 
/*************************************************************************
 
1777
/*********************************************************************//**
1760
1778
Drop an index from the InnoDB system tables.  The data dictionary must
1761
1779
have been locked exclusively by the caller, because the transaction
1762
1780
will not be committed. */
1764
1782
void
1765
1783
row_merge_drop_index(
1766
1784
/*=================*/
1767
 
        dict_index_t*   index,  /* in: index to be removed */
1768
 
        dict_table_t*   table,  /* in: table */
1769
 
        trx_t*          trx)    /* in: transaction handle */
 
1785
        dict_index_t*   index,  /*!< in: index to be removed */
 
1786
        dict_table_t*   table,  /*!< in: table */
 
1787
        trx_t*          trx)    /*!< in: transaction handle */
1770
1788
{
1771
1789
        ulint           err;
1772
1790
        pars_info_t*    info = pars_info_create();
1807
1825
        trx->op_info = "";
1808
1826
}
1809
1827
 
1810
 
/*************************************************************************
 
1828
/*********************************************************************//**
1811
1829
Drop those indexes which were created before an error occurred when
1812
1830
building an index.  The data dictionary must have been locked
1813
1831
exclusively by the caller, because the transaction will not be
1816
1834
void
1817
1835
row_merge_drop_indexes(
1818
1836
/*===================*/
1819
 
        trx_t*          trx,            /* in: transaction */
1820
 
        dict_table_t*   table,          /* in: table containing the indexes */
1821
 
        dict_index_t**  index,          /* in: indexes to drop */
1822
 
        ulint           num_created)    /* in: number of elements in index[] */
 
1837
        trx_t*          trx,            /*!< in: transaction */
 
1838
        dict_table_t*   table,          /*!< in: table containing the indexes */
 
1839
        dict_index_t**  index,          /*!< in: indexes to drop */
 
1840
        ulint           num_created)    /*!< in: number of elements in index[] */
1823
1841
{
1824
1842
        ulint   key_num;
1825
1843
 
1828
1846
        }
1829
1847
}
1830
1848
 
1831
 
/*************************************************************************
 
1849
/*********************************************************************//**
1832
1850
Drop all partially created indexes during crash recovery. */
1833
1851
UNIV_INTERN
1834
1852
void
1842
1860
        query graphs needed in deleting the dictionary data from system
1843
1861
        tables in Innobase. Deleting a row from SYS_INDEXES table also
1844
1862
        frees the file segments of the B-tree associated with the index. */
1845
 
#if TEMP_INDEX_PREFIX != '\377'
1846
 
# error "TEMP_INDEX_PREFIX != '\377'"
1847
 
#endif
1848
1863
        static const char drop_temp_indexes[] =
1849
1864
                "PROCEDURE DROP_TEMP_INDEXES_PROC () IS\n"
1850
1865
                "indexid CHAR;\n"
1851
1866
                "DECLARE CURSOR c IS SELECT ID FROM SYS_INDEXES\n"
1852
 
                "WHERE SUBSTR(NAME,0,1)='\377';\n"
 
1867
                "WHERE SUBSTR(NAME,0,1)='" TEMP_INDEX_PREFIX_STR "';\n"
1853
1868
                "BEGIN\n"
1854
1869
                "\tOPEN c;\n"
1855
1870
                "\tWHILE 1=1 LOOP\n"
1884
1899
        trx_free_for_background(trx);
1885
1900
}
1886
1901
 
1887
 
/*************************************************************************
 
1902
/*********************************************************************//**
1888
1903
Create a merge file. */
1889
1904
static
1890
1905
void
1891
1906
row_merge_file_create(
1892
1907
/*==================*/
1893
 
        merge_file_t*   merge_file)     /* out: merge file structure */
 
1908
        merge_file_t*   merge_file)     /*!< out: merge file structure */
1894
1909
{
1895
1910
        merge_file->fd = innobase_mysql_tmpfile();
1896
1911
        merge_file->offset = 0;
1897
1912
}
1898
1913
 
1899
 
/*************************************************************************
 
1914
/*********************************************************************//**
1900
1915
Destroy a merge file. */
1901
1916
static
1902
1917
void
1903
1918
row_merge_file_destroy(
1904
1919
/*===================*/
1905
 
        merge_file_t*   merge_file)     /* out: merge file structure */
 
1920
        merge_file_t*   merge_file)     /*!< out: merge file structure */
1906
1921
{
1907
1922
        if (merge_file->fd != -1) {
1908
1923
                close(merge_file->fd);
1910
1925
        }
1911
1926
}
1912
1927
 
1913
 
/*************************************************************************
 
1928
/*********************************************************************//**
1914
1929
Determine the precise type of a column that is added to a tem
1915
 
if a column must be constrained NOT NULL. */
 
1930
if a column must be constrained NOT NULL.
 
1931
@return col->prtype, possibly ORed with DATA_NOT_NULL */
1916
1932
UNIV_INLINE
1917
1933
ulint
1918
1934
row_merge_col_prtype(
1919
1935
/*=================*/
1920
 
                                                /* out: col->prtype, possibly
1921
 
                                                ORed with DATA_NOT_NULL */
1922
 
        const dict_col_t*       col,            /* in: column */
1923
 
        const char*             col_name,       /* in: name of the column */
1924
 
        const merge_index_def_t*index_def)      /* in: the index definition
 
1936
        const dict_col_t*       col,            /*!< in: column */
 
1937
        const char*             col_name,       /*!< in: name of the column */
 
1938
        const merge_index_def_t*index_def)      /*!< in: the index definition
1925
1939
                                                of the primary key */
1926
1940
{
1927
1941
        ulint   prtype = col->prtype;
1946
1960
        return(prtype);
1947
1961
}
1948
1962
 
1949
 
/*************************************************************************
 
1963
/*********************************************************************//**
1950
1964
Create a temporary table for creating a primary key, using the definition
1951
 
of an existing table. */
 
1965
of an existing table.
 
1966
@return table, or NULL on error */
1952
1967
UNIV_INTERN
1953
1968
dict_table_t*
1954
1969
row_merge_create_temporary_table(
1955
1970
/*=============================*/
1956
 
                                                /* out: table,
1957
 
                                                or NULL on error */
1958
 
        const char*             table_name,     /* in: new table name */
1959
 
        const merge_index_def_t*index_def,      /* in: the index definition
 
1971
        const char*             table_name,     /*!< in: new table name */
 
1972
        const merge_index_def_t*index_def,      /*!< in: the index definition
1960
1973
                                                of the primary key */
1961
 
        const dict_table_t*     table,          /* in: old table definition */
1962
 
        trx_t*                  trx)            /* in/out: transaction
 
1974
        const dict_table_t*     table,          /*!< in: old table definition */
 
1975
        trx_t*                  trx)            /*!< in/out: transaction
1963
1976
                                                (sets error_state) */
1964
1977
{
1965
1978
        ulint           i;
1999
2012
        return(new_table);
2000
2013
}
2001
2014
 
2002
 
/*************************************************************************
 
2015
/*********************************************************************//**
2003
2016
Rename the temporary indexes in the dictionary to permanent ones.  The
2004
2017
data dictionary must have been locked exclusively by the caller,
2005
 
because the transaction will not be committed. */
 
2018
because the transaction will not be committed.
 
2019
@return DB_SUCCESS if all OK */
2006
2020
UNIV_INTERN
2007
2021
ulint
2008
2022
row_merge_rename_indexes(
2009
2023
/*=====================*/
2010
 
                                        /* out: DB_SUCCESS if all OK */
2011
 
        trx_t*          trx,            /* in/out: transaction */
2012
 
        dict_table_t*   table)          /* in/out: table with new indexes */
 
2024
        trx_t*          trx,            /*!< in/out: transaction */
 
2025
        dict_table_t*   table)          /*!< in/out: table with new indexes */
2013
2026
{
2014
2027
        ulint           err = DB_SUCCESS;
2015
2028
        pars_info_t*    info = pars_info_create();
2017
2030
        /* We use the private SQL parser of Innobase to generate the
2018
2031
        query graphs needed in renaming indexes. */
2019
2032
 
2020
 
#if TEMP_INDEX_PREFIX != '\377'
2021
 
# error "TEMP_INDEX_PREFIX != '\377'"
2022
 
#endif
2023
 
 
2024
2033
        static const char rename_indexes[] =
2025
2034
                "PROCEDURE RENAME_INDEXES_PROC () IS\n"
2026
2035
                "BEGIN\n"
2027
2036
                "UPDATE SYS_INDEXES SET NAME=SUBSTR(NAME,1,LENGTH(NAME)-1)\n"
2028
 
                "WHERE TABLE_ID = :tableid AND SUBSTR(NAME,0,1)='\377';\n"
 
2037
                "WHERE TABLE_ID = :tableid AND SUBSTR(NAME,0,1)='"
 
2038
                TEMP_INDEX_PREFIX_STR "';\n"
2029
2039
                "END;\n";
2030
2040
 
2031
2041
        ut_ad(table);
2053
2063
        return(err);
2054
2064
}
2055
2065
 
2056
 
/*************************************************************************
 
2066
/*********************************************************************//**
2057
2067
Rename the tables in the data dictionary.  The data dictionary must
2058
2068
have been locked exclusively by the caller, because the transaction
2059
 
will not be committed. */
 
2069
will not be committed.
 
2070
@return error code or DB_SUCCESS */
2060
2071
UNIV_INTERN
2061
2072
ulint
2062
2073
row_merge_rename_tables(
2063
2074
/*====================*/
2064
 
                                        /* out: error code or DB_SUCCESS */
2065
 
        dict_table_t*   old_table,      /* in/out: old table, renamed to
 
2075
        dict_table_t*   old_table,      /*!< in/out: old table, renamed to
2066
2076
                                        tmp_name */
2067
 
        dict_table_t*   new_table,      /* in/out: new table, renamed to
 
2077
        dict_table_t*   new_table,      /*!< in/out: new table, renamed to
2068
2078
                                        old_table->name */
2069
 
        const char*     tmp_name,       /* in: new name for old_table */
2070
 
        trx_t*          trx)            /* in: transaction handle */
 
2079
        const char*     tmp_name,       /*!< in: new name for old_table */
 
2080
        trx_t*          trx)            /*!< in: transaction handle */
2071
2081
{
2072
2082
        ulint           err     = DB_ERROR;
2073
2083
        pars_info_t*    info;
2128
2138
        return(err);
2129
2139
}
2130
2140
 
2131
 
/*************************************************************************
2132
 
Create and execute a query graph for creating an index. */
 
2141
/*********************************************************************//**
 
2142
Create and execute a query graph for creating an index.
 
2143
@return DB_SUCCESS or error code */
2133
2144
static
2134
2145
ulint
2135
2146
row_merge_create_index_graph(
2136
2147
/*=========================*/
2137
 
                                        /* out: DB_SUCCESS or error code */
2138
 
        trx_t*          trx,            /* in: trx */
2139
 
        dict_table_t*   table,          /* in: table */
2140
 
        dict_index_t*   index)          /* in: index */
 
2148
        trx_t*          trx,            /*!< in: trx */
 
2149
        dict_table_t*   table,          /*!< in: table */
 
2150
        dict_index_t*   index)          /*!< in: index */
2141
2151
{
2142
 
        ind_node_t*     node;           /* Index creation node */
2143
 
        mem_heap_t*     heap;           /* Memory heap */
2144
 
        que_thr_t*      thr;            /* Query thread */
 
2152
        ind_node_t*     node;           /*!< Index creation node */
 
2153
        mem_heap_t*     heap;           /*!< Memory heap */
 
2154
        que_thr_t*      thr;            /*!< Query thread */
2145
2155
        ulint           err;
2146
2156
 
2147
2157
        ut_ad(trx);
2165
2175
        return(err);
2166
2176
}
2167
2177
 
2168
 
/*************************************************************************
2169
 
Create the index and load in to the dictionary. */
 
2178
/*********************************************************************//**
 
2179
Create the index and load in to the dictionary.
 
2180
@return index, or NULL on error */
2170
2181
UNIV_INTERN
2171
2182
dict_index_t*
2172
2183
row_merge_create_index(
2173
2184
/*===================*/
2174
 
                                        /* out: index, or NULL on error */
2175
 
        trx_t*          trx,            /* in/out: trx (sets error_state) */
2176
 
        dict_table_t*   table,          /* in: the index is on this table */
2177
 
        const merge_index_def_t*        /* in: the index definition */
2178
 
                        index_def)
 
2185
        trx_t*                  trx,    /*!< in/out: trx (sets error_state) */
 
2186
        dict_table_t*           table,  /*!< in: the index is on this table */
 
2187
        const merge_index_def_t*index_def)
 
2188
                                        /*!< in: the index definition */
2179
2189
{
2180
2190
        dict_index_t*   index;
2181
2191
        ulint           err;
2208
2218
 
2209
2219
                ut_a(index);
2210
2220
 
2211
 
#ifdef ROW_MERGE_IS_INDEX_USABLE
2212
2221
                /* Note the id of the transaction that created this
2213
2222
                index, we use it to restrict readers from accessing
2214
2223
                this index, to ensure read consistency. */
2215
 
                index->trx_id = trx->id;
2216
 
#endif /* ROW_MERGE_IS_INDEX_USABLE */
 
2224
                index->trx_id = (ib_uint64_t)
 
2225
                        ut_conv_dulint_to_longlong(trx->id);
2217
2226
        } else {
2218
2227
                index = NULL;
2219
2228
        }
2221
2230
        return(index);
2222
2231
}
2223
2232
 
2224
 
#ifdef ROW_MERGE_IS_INDEX_USABLE
2225
 
/*************************************************************************
 
2233
/*********************************************************************//**
2226
2234
Check if a transaction can use an index. */
2227
2235
UNIV_INTERN
2228
2236
ibool
2229
2237
row_merge_is_index_usable(
2230
2238
/*======================*/
2231
 
        const trx_t*            trx,    /* in: transaction */
2232
 
        const dict_index_t*     index)  /* in: index to check */
 
2239
        const trx_t*            trx,    /*!< in: transaction */
 
2240
        const dict_index_t*     index)  /*!< in: index to check */
2233
2241
{
2234
 
        if (!trx->read_view) {
2235
 
                return(TRUE);
2236
 
        }
2237
 
 
2238
 
        return(ut_dulint_cmp(index->trx_id, trx->read_view->low_limit_id) < 0);
 
2242
        return(!trx->read_view || read_view_sees_trx_id(
 
2243
                       trx->read_view,
 
2244
                       ut_dulint_create((ulint) (index->trx_id >> 32),
 
2245
                                        (ulint) index->trx_id & 0xFFFFFFFF)));
2239
2246
}
2240
 
#endif /* ROW_MERGE_IS_INDEX_USABLE */
2241
2247
 
2242
 
/*************************************************************************
2243
 
Drop the old table. */
 
2248
/*********************************************************************//**
 
2249
Drop the old table.
 
2250
@return DB_SUCCESS or error code */
2244
2251
UNIV_INTERN
2245
2252
ulint
2246
2253
row_merge_drop_table(
2247
2254
/*=================*/
2248
 
                                        /* out: DB_SUCCESS or error code */
2249
 
        trx_t*          trx,            /* in: transaction */
2250
 
        dict_table_t*   table)          /* in: table to drop */
 
2255
        trx_t*          trx,            /*!< in: transaction */
 
2256
        dict_table_t*   table)          /*!< in: table to drop */
2251
2257
{
2252
2258
        /* There must be no open transactions on the table. */
2253
2259
        ut_a(table->n_mysql_handles_opened == 0);
2255
2261
        return(row_drop_table_for_mysql(table->name, trx, FALSE));
2256
2262
}
2257
2263
 
2258
 
/*************************************************************************
 
2264
/*********************************************************************//**
2259
2265
Build indexes on a table by reading a clustered index,
2260
2266
creating a temporary file containing index entries, merge sorting
2261
 
these index entries and inserting sorted index entries to indexes. */
 
2267
these index entries and inserting sorted index entries to indexes.
 
2268
@return DB_SUCCESS or error code */
2262
2269
UNIV_INTERN
2263
2270
ulint
2264
2271
row_merge_build_indexes(
2265
2272
/*====================*/
2266
 
                                        /* out: DB_SUCCESS or error code */
2267
 
        trx_t*          trx,            /* in: transaction */
2268
 
        dict_table_t*   old_table,      /* in: table where rows are
 
2273
        trx_t*          trx,            /*!< in: transaction */
 
2274
        dict_table_t*   old_table,      /*!< in: table where rows are
2269
2275
                                        read from */
2270
 
        dict_table_t*   new_table,      /* in: table where indexes are
 
2276
        dict_table_t*   new_table,      /*!< in: table where indexes are
2271
2277
                                        created; identical to old_table
2272
2278
                                        unless creating a PRIMARY KEY */
2273
 
        dict_index_t**  indexes,        /* in: indexes to be created */
2274
 
        ulint           n_indexes,      /* in: size of indexes[] */
2275
 
        TABLE*          table)          /* in/out: MySQL table, for
 
2279
        dict_index_t**  indexes,        /*!< in: indexes to be created */
 
2280
        ulint           n_indexes,      /*!< in: size of indexes[] */
 
2281
        TABLE*          table)          /*!< in/out: MySQL table, for
2276
2282
                                        reporting erroneous key value
2277
2283
                                        if applicable */
2278
2284
{