~drizzle-trunk/drizzle/development

« back to all changes in this revision

Viewing changes to plugin/innobase/row/row0ins.cc

  • Committer: Monty Taylor
  • Date: 2011-02-13 17:26:39 UTC
  • mfrom: (2157.2.2 give-in-to-pkg-config)
  • mto: This revision was merged to the branch mainline in revision 2166.
  • Revision ID: mordred@inaugust.com-20110213172639-nhy7i72sfhoq13ms
Merged in pkg-config fixes.

Show diffs side-by-side

added added

removed removed

Lines of Context:
1
1
/*****************************************************************************
2
2
 
3
 
Copyright (c) 1996, 2009, Innobase Oy. All Rights Reserved.
 
3
Copyright (C) 1996, 2010, Innobase Oy. All Rights Reserved.
4
4
 
5
5
This program is free software; you can redistribute it and/or modify it under
6
6
the terms of the GNU General Public License as published by the Free Software
11
11
FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
12
12
 
13
13
You should have received a copy of the GNU General Public License along with
14
 
this program; if not, write to the Free Software Foundation, Inc., 59 Temple
15
 
Place, Suite 330, Boston, MA 02111-1307 USA
 
14
this program; if not, write to the Free Software Foundation, Inc., 51 Franklin
 
15
St, Fifth Floor, Boston, MA 02110-1301 USA
16
16
 
17
17
*****************************************************************************/
18
18
 
19
 
/******************************************************
 
19
/**************************************************//**
 
20
@file row/row0ins.c
20
21
Insert into a table
21
22
 
22
23
Created 4/20/1996 Heikki Tuuri
28
29
#include "row0ins.ic"
29
30
#endif
30
31
 
 
32
#include "ha_prototypes.h"
31
33
#include "dict0dict.h"
32
34
#include "dict0boot.h"
33
35
#include "trx0undo.h"
49
51
#define ROW_INS_PREV    1
50
52
#define ROW_INS_NEXT    2
51
53
 
52
 
 
53
54
/*************************************************************************
54
 
Creates an insert node struct. */
 
55
IMPORTANT NOTE: Any operation that generates redo MUST check that there
 
56
is enough space in the redo log before for that operation. This is
 
57
done by calling log_free_check(). The reason for checking the
 
58
availability of the redo log space before the start of the operation is
 
59
that we MUST not hold any synchonization objects when performing the
 
60
check.
 
61
If you make a change in this module make sure that no codepath is
 
62
introduced where a call to log_free_check() is bypassed. */
 
63
 
 
64
/*********************************************************************//**
 
65
Creates an insert node struct.
 
66
@return own: insert node struct */
55
67
UNIV_INTERN
56
68
ins_node_t*
57
69
ins_node_create(
58
70
/*============*/
59
 
                                        /* out, own: insert node struct */
60
 
        ulint           ins_type,       /* in: INS_VALUES, ... */
61
 
        dict_table_t*   table,          /* in: table where to insert */
62
 
        mem_heap_t*     heap)           /* in: mem heap where created */
 
71
        ulint           ins_type,       /*!< in: INS_VALUES, ... */
 
72
        dict_table_t*   table,          /*!< in: table where to insert */
 
73
        mem_heap_t*     heap)           /*!< in: mem heap where created */
63
74
{
64
75
        ins_node_t*     node;
65
76
 
66
 
        node = mem_heap_alloc(heap, sizeof(ins_node_t));
 
77
        node = static_cast<ins_node_t *>(mem_heap_alloc(heap, sizeof(ins_node_t)));
67
78
 
68
79
        node->common.type = QUE_NODE_INSERT;
69
80
 
76
87
 
77
88
        node->select = NULL;
78
89
 
79
 
        node->trx_id = ut_dulint_zero;
 
90
        node->trx_id = 0;
80
91
 
81
92
        node->entry_sys_heap = mem_heap_create(128);
82
93
 
85
96
        return(node);
86
97
}
87
98
 
88
 
/***************************************************************
 
99
/***********************************************************//**
89
100
Creates an entry template for each index of a table. */
90
101
UNIV_INTERN
91
102
void
92
103
ins_node_create_entry_list(
93
104
/*=======================*/
94
 
        ins_node_t*     node)   /* in: row insert node */
 
105
        ins_node_t*     node)   /*!< in: row insert node */
95
106
{
96
107
        dict_index_t*   index;
97
108
        dtuple_t*       entry;
111
122
        }
112
123
}
113
124
 
114
 
/*********************************************************************
 
125
/*****************************************************************//**
115
126
Adds system field buffers to a row. */
116
127
static
117
128
void
118
129
row_ins_alloc_sys_fields(
119
130
/*=====================*/
120
 
        ins_node_t*     node)   /* in: insert node */
 
131
        ins_node_t*     node)   /*!< in: insert node */
121
132
{
122
133
        dtuple_t*               row;
123
134
        dict_table_t*           table;
139
150
 
140
151
        dfield = dtuple_get_nth_field(row, dict_col_get_no(col));
141
152
 
142
 
        ptr = mem_heap_alloc(heap, DATA_ROW_ID_LEN);
 
153
        ptr = static_cast<byte *>(mem_heap_zalloc(heap, DATA_ROW_ID_LEN));
143
154
 
144
155
        dfield_set_data(dfield, ptr, DATA_ROW_ID_LEN);
145
156
 
150
161
        col = dict_table_get_sys_col(table, DATA_TRX_ID);
151
162
 
152
163
        dfield = dtuple_get_nth_field(row, dict_col_get_no(col));
153
 
        ptr = mem_heap_alloc(heap, DATA_TRX_ID_LEN);
 
164
        ptr = static_cast<byte *>(mem_heap_zalloc(heap, DATA_TRX_ID_LEN));
154
165
 
155
166
        dfield_set_data(dfield, ptr, DATA_TRX_ID_LEN);
156
167
 
161
172
        col = dict_table_get_sys_col(table, DATA_ROLL_PTR);
162
173
 
163
174
        dfield = dtuple_get_nth_field(row, dict_col_get_no(col));
164
 
        ptr = mem_heap_alloc(heap, DATA_ROLL_PTR_LEN);
 
175
        ptr = static_cast<byte *>(mem_heap_zalloc(heap, DATA_ROLL_PTR_LEN));
165
176
 
166
177
        dfield_set_data(dfield, ptr, DATA_ROLL_PTR_LEN);
167
178
}
168
179
 
169
 
/*************************************************************************
 
180
/*********************************************************************//**
170
181
Sets a new row to insert for an INS_DIRECT node. This function is only used
171
182
if we have constructed the row separately, which is a rare case; this
172
183
function is quite slow. */
174
185
void
175
186
ins_node_set_new_row(
176
187
/*=================*/
177
 
        ins_node_t*     node,   /* in: insert node */
178
 
        dtuple_t*       row)    /* in: new row (or first row) for the node */
 
188
        ins_node_t*     node,   /*!< in: insert node */
 
189
        dtuple_t*       row)    /*!< in: new row (or first row) for the node */
179
190
{
180
191
        node->state = INS_NODE_SET_IX_LOCK;
181
192
        node->index = NULL;
196
207
        /* As we allocated a new trx id buf, the trx id should be written
197
208
        there again: */
198
209
 
199
 
        node->trx_id = ut_dulint_zero;
 
210
        node->trx_id = 0;
200
211
}
201
212
 
202
 
/***********************************************************************
 
213
/*******************************************************************//**
203
214
Does an insert operation by updating a delete-marked existing record
204
215
in the index. This situation can occur if the delete-marked record is
205
 
kept in the index for consistent reads. */
 
216
kept in the index for consistent reads.
 
217
@return DB_SUCCESS or error code */
206
218
static
207
219
ulint
208
220
row_ins_sec_index_entry_by_modify(
209
221
/*==============================*/
210
 
                                /* out: DB_SUCCESS or error code */
211
 
        ulint           mode,   /* in: BTR_MODIFY_LEAF or BTR_MODIFY_TREE,
 
222
        ulint           mode,   /*!< in: BTR_MODIFY_LEAF or BTR_MODIFY_TREE,
212
223
                                depending on whether mtr holds just a leaf
213
224
                                latch or also a tree latch */
214
 
        btr_cur_t*      cursor, /* in: B-tree cursor */
215
 
        const dtuple_t* entry,  /* in: index entry to insert */
216
 
        que_thr_t*      thr,    /* in: query thread */
217
 
        mtr_t*          mtr)    /* in: mtr; must be committed before
 
225
        btr_cur_t*      cursor, /*!< in: B-tree cursor */
 
226
        const dtuple_t* entry,  /*!< in: index entry to insert */
 
227
        que_thr_t*      thr,    /*!< in: query thread */
 
228
        mtr_t*          mtr)    /*!< in: mtr; must be committed before
218
229
                                latching any further pages */
219
230
{
220
231
        big_rec_t*      dummy_big_rec;
270
281
        return(err);
271
282
}
272
283
 
273
 
/***********************************************************************
 
284
/*******************************************************************//**
274
285
Does an insert operation by delete unmarking and updating a delete marked
275
286
existing record in the index. This situation can occur if the delete marked
276
 
record is kept in the index for consistent reads. */
 
287
record is kept in the index for consistent reads.
 
288
@return DB_SUCCESS, DB_FAIL, or error code */
277
289
static
278
290
ulint
279
291
row_ins_clust_index_entry_by_modify(
280
292
/*================================*/
281
 
                                /* out: DB_SUCCESS, DB_FAIL, or error code */
282
 
        ulint           mode,   /* in: BTR_MODIFY_LEAF or BTR_MODIFY_TREE,
 
293
        ulint           mode,   /*!< in: BTR_MODIFY_LEAF or BTR_MODIFY_TREE,
283
294
                                depending on whether mtr holds just a leaf
284
295
                                latch or also a tree latch */
285
 
        btr_cur_t*      cursor, /* in: B-tree cursor */
286
 
        mem_heap_t**    heap,   /* in/out: pointer to memory heap, or NULL */
287
 
        big_rec_t**     big_rec,/* out: possible big rec vector of fields
 
296
        btr_cur_t*      cursor, /*!< in: B-tree cursor */
 
297
        mem_heap_t**    heap,   /*!< in/out: pointer to memory heap, or NULL */
 
298
        big_rec_t**     big_rec,/*!< out: possible big rec vector of fields
288
299
                                which have to be stored externally by the
289
300
                                caller */
290
 
        const dtuple_t* entry,  /* in: index entry to insert */
291
 
        que_thr_t*      thr,    /* in: query thread */
292
 
        mtr_t*          mtr)    /* in: mtr; must be committed before
 
301
        const dtuple_t* entry,  /*!< in: index entry to insert */
 
302
        que_thr_t*      thr,    /*!< in: query thread */
 
303
        mtr_t*          mtr)    /*!< in: mtr; must be committed before
293
304
                                latching any further pages */
294
305
{
295
306
        rec_t*          rec;
342
353
        return(err);
343
354
}
344
355
 
345
 
/*************************************************************************
 
356
/*********************************************************************//**
346
357
Returns TRUE if in a cascaded update/delete an ancestor node of node
347
 
updates (not DELETE, but UPDATE) table. */
 
358
updates (not DELETE, but UPDATE) table.
 
359
@return TRUE if an ancestor updates table */
348
360
static
349
361
ibool
350
362
row_ins_cascade_ancestor_updates_table(
351
363
/*===================================*/
352
 
                                /* out: TRUE if an ancestor updates table */
353
 
        que_node_t*     node,   /* in: node in a query graph */
354
 
        dict_table_t*   table)  /* in: table */
 
364
        que_node_t*     node,   /*!< in: node in a query graph */
 
365
        dict_table_t*   table)  /*!< in: table */
355
366
{
356
367
        que_node_t*     parent;
357
368
        upd_node_t*     upd_node;
360
371
 
361
372
        while (que_node_get_type(parent) == QUE_NODE_UPDATE) {
362
373
 
363
 
                upd_node = parent;
 
374
                upd_node = static_cast<upd_node_t *>(parent);
364
375
 
365
376
                if (upd_node->table == table && upd_node->is_delete == FALSE) {
366
377
 
375
386
        return(FALSE);
376
387
}
377
388
 
378
 
/*************************************************************************
 
389
/*********************************************************************//**
379
390
Returns the number of ancestor UPDATE or DELETE nodes of a
380
 
cascaded update/delete node. */
 
391
cascaded update/delete node.
 
392
@return number of ancestors */
381
393
static
382
394
ulint
383
395
row_ins_cascade_n_ancestors(
384
396
/*========================*/
385
 
                                /* out: number of ancestors */
386
 
        que_node_t*     node)   /* in: node in a query graph */
 
397
        que_node_t*     node)   /*!< in: node in a query graph */
387
398
{
388
399
        que_node_t*     parent;
389
400
        ulint           n_ancestors = 0;
401
412
        return(n_ancestors);
402
413
}
403
414
 
404
 
/**********************************************************************
 
415
/******************************************************************//**
405
416
Calculates the update vector node->cascade->update for a child table in
406
 
a cascaded update. */
 
417
a cascaded update.
 
418
@return number of fields in the calculated update vector; the value
 
419
can also be 0 if no foreign key fields changed; the returned value is
 
420
ULINT_UNDEFINED if the column type in the child table is too short to
 
421
fit the new value in the parent table: that means the update fails */
407
422
static
408
423
ulint
409
424
row_ins_cascade_calc_update_vec(
410
425
/*============================*/
411
 
                                        /* out: number of fields in the
412
 
                                        calculated update vector; the value
413
 
                                        can also be 0 if no foreign key
414
 
                                        fields changed; the returned value
415
 
                                        is ULINT_UNDEFINED if the column
416
 
                                        type in the child table is too short
417
 
                                        to fit the new value in the parent
418
 
                                        table: that means the update fails */
419
 
        upd_node_t*     node,           /* in: update node of the parent
 
426
        upd_node_t*     node,           /*!< in: update node of the parent
420
427
                                        table */
421
 
        dict_foreign_t* foreign,        /* in: foreign key constraint whose
 
428
        dict_foreign_t* foreign,        /*!< in: foreign key constraint whose
422
429
                                        type is != 0 */
423
 
        mem_heap_t*     heap)           /* in: memory heap to use as
 
430
        mem_heap_t*     heap)           /*!< in: memory heap to use as
424
431
                                        temporary storage */
425
432
{
426
433
        upd_node_t*     cascade         = node->cascade_node;
508
515
 
509
516
                                if (!dfield_is_null(&ufield->new_val)
510
517
                                    && dtype_get_at_most_n_mbchars(
511
 
                                        col->prtype,
512
 
                                        col->mbminlen, col->mbmaxlen,
 
518
                                        col->prtype, col->mbminmaxlen,
513
519
                                        col->len,
514
520
                                        ufield_len,
515
 
                                        dfield_get_data(&ufield->new_val))
 
521
                                        static_cast<const char *>(dfield_get_data(&ufield->new_val)))
516
522
                                    < ufield_len) {
517
523
 
518
524
                                        return(ULINT_UNDEFINED);
532
538
 
533
539
                                if (min_size > ufield_len) {
534
540
 
535
 
                                        char*           pad_start;
536
 
                                        const char*     pad_end;
537
 
                                        char*           padded_data
538
 
                                                = mem_heap_alloc(
539
 
                                                        heap, min_size);
540
 
                                        pad_start = padded_data + ufield_len;
541
 
                                        pad_end = padded_data + min_size;
 
541
                                        byte*   pad;
 
542
                                        ulint   pad_len;
 
543
                                        byte*   padded_data;
 
544
                                        ulint   mbminlen;
 
545
 
 
546
                                        padded_data = static_cast<unsigned char *>(mem_heap_alloc(
 
547
                                                heap, min_size));
 
548
 
 
549
                                        pad = padded_data + ufield_len;
 
550
                                        pad_len = min_size - ufield_len;
542
551
 
543
552
                                        memcpy(padded_data,
544
553
                                               dfield_get_data(&ufield
545
554
                                                               ->new_val),
546
 
                                               dfield_get_len(&ufield
547
 
                                                              ->new_val));
548
 
 
549
 
                                        switch (UNIV_EXPECT(col->mbminlen,1)) {
550
 
                                        default:
551
 
                                                ut_error;
 
555
                                               ufield_len);
 
556
 
 
557
                                        mbminlen = dict_col_get_mbminlen(col);
 
558
 
 
559
                                        ut_ad(!(ufield_len % mbminlen));
 
560
                                        ut_ad(!(min_size % mbminlen));
 
561
 
 
562
                                        if (mbminlen == 1
 
563
                                            && dtype_get_charset_coll(
 
564
                                                    col->prtype)
 
565
                                            == DATA_MYSQL_BINARY_CHARSET_COLL) {
 
566
                                                /* Do not pad BINARY columns */
552
567
                                                return(ULINT_UNDEFINED);
553
 
                                        case 1:
554
 
                                                if (UNIV_UNLIKELY
555
 
                                                    (dtype_get_charset_coll(
556
 
                                                            col->prtype)
557
 
                                                     == DATA_MYSQL_BINARY_CHARSET_COLL)) {
558
 
                                                        /* Do not pad BINARY
559
 
                                                        columns. */
560
 
                                                        return(ULINT_UNDEFINED);
561
 
                                                }
562
 
 
563
 
                                                /* space=0x20 */
564
 
                                                memset(pad_start, 0x20,
565
 
                                                       pad_end - pad_start);
566
 
                                                break;
567
 
                                        case 2:
568
 
                                                /* space=0x0020 */
569
 
                                                ut_a(!(ufield_len % 2));
570
 
                                                ut_a(!(min_size % 2));
571
 
                                                do {
572
 
                                                        *pad_start++ = 0x00;
573
 
                                                        *pad_start++ = 0x20;
574
 
                                                } while (pad_start < pad_end);
575
 
                                                break;
576
568
                                        }
577
569
 
 
570
                                        row_mysql_pad_col(mbminlen,
 
571
                                                          pad, pad_len);
578
572
                                        dfield_set_data(&ufield->new_val,
579
573
                                                        padded_data, min_size);
580
574
                                }
589
583
        return(n_fields_updated);
590
584
}
591
585
 
592
 
/*************************************************************************
 
586
/*********************************************************************//**
593
587
Set detailed error message associated with foreign key errors for
594
588
the given transaction. */
595
589
static
596
590
void
597
591
row_ins_set_detailed(
598
592
/*=================*/
599
 
        trx_t*          trx,            /* in: transaction */
600
 
        dict_foreign_t* foreign)        /* in: foreign key constraint */
 
593
        trx_t*          trx,            /*!< in: transaction */
 
594
        dict_foreign_t* foreign)        /*!< in: foreign key constraint */
601
595
{
602
596
        mutex_enter(&srv_misc_tmpfile_mutex);
603
597
        rewind(srv_misc_tmpfile);
615
609
        mutex_exit(&srv_misc_tmpfile_mutex);
616
610
}
617
611
 
618
 
/*************************************************************************
 
612
/*********************************************************************//**
619
613
Reports a foreign key error associated with an update or a delete of a
620
614
parent table index entry. */
621
615
static
622
616
void
623
617
row_ins_foreign_report_err(
624
618
/*=======================*/
625
 
        const char*     errstr,         /* in: error string from the viewpoint
 
619
        const char*     errstr,         /*!< in: error string from the viewpoint
626
620
                                        of the parent table */
627
 
        que_thr_t*      thr,            /* in: query thread whose run_node
 
621
        que_thr_t*      thr,            /*!< in: query thread whose run_node
628
622
                                        is an update node */
629
 
        dict_foreign_t* foreign,        /* in: foreign key constraint */
630
 
        const rec_t*    rec,            /* in: a matching index record in the
 
623
        dict_foreign_t* foreign,        /*!< in: foreign key constraint */
 
624
        const rec_t*    rec,            /*!< in: a matching index record in the
631
625
                                        child table */
632
 
        const dtuple_t* entry)          /* in: index entry in the parent
 
626
        const dtuple_t* entry)          /*!< in: index entry in the parent
633
627
                                        table */
634
628
{
635
629
        FILE*   ef      = dict_foreign_err_file;
671
665
        mutex_exit(&dict_foreign_err_mutex);
672
666
}
673
667
 
674
 
/*************************************************************************
 
668
/*********************************************************************//**
675
669
Reports a foreign key error to dict_foreign_err_file when we are trying
676
670
to add an index entry to a child table. Note that the adding may be the result
677
671
of an update, too. */
679
673
void
680
674
row_ins_foreign_report_add_err(
681
675
/*===========================*/
682
 
        trx_t*          trx,            /* in: transaction */
683
 
        dict_foreign_t* foreign,        /* in: foreign key constraint */
684
 
        const rec_t*    rec,            /* in: a record in the parent table:
 
676
        trx_t*          trx,            /*!< in: transaction */
 
677
        dict_foreign_t* foreign,        /*!< in: foreign key constraint */
 
678
        const rec_t*    rec,            /*!< in: a record in the parent table:
685
679
                                        it does not match entry because we
686
680
                                        have an error! */
687
 
        const dtuple_t* entry)          /* in: index entry to insert in the
 
681
        const dtuple_t* entry)          /*!< in: index entry to insert in the
688
682
                                        child table */
689
683
{
690
684
        FILE*   ef      = dict_foreign_err_file;
729
723
        mutex_exit(&dict_foreign_err_mutex);
730
724
}
731
725
 
732
 
/*************************************************************************
 
726
/*********************************************************************//**
733
727
Invalidate the query cache for the given table. */
734
728
static
735
729
void
736
730
row_ins_invalidate_query_cache(
737
731
/*===========================*/
738
 
        que_thr_t*      unused,         /* in: query thread whose run_node
 
732
        que_thr_t*      unused,         /*!< in: query thread whose run_node
739
733
                                        is an update node */
740
 
        const char*     name)           /* in: table name prefixed with
 
734
        const char*     name)           /*!< in: table name prefixed with
741
735
                                        database name and a '/' character */
742
736
{
743
737
        char*   buf;
755
749
        mem_free(buf);
756
750
}
757
751
 
758
 
/*************************************************************************
 
752
/*********************************************************************//**
759
753
Perform referential actions or checks when a parent row is deleted or updated
760
754
and the constraint had an ON DELETE or ON UPDATE condition which was not
761
 
RESTRICT. */
 
755
RESTRICT.
 
756
@return DB_SUCCESS, DB_LOCK_WAIT, or error code */
762
757
static
763
758
ulint
764
759
row_ins_foreign_check_on_constraint(
765
760
/*================================*/
766
 
                                        /* out: DB_SUCCESS, DB_LOCK_WAIT,
767
 
                                        or error code */
768
 
        que_thr_t*      thr,            /* in: query thread whose run_node
 
761
        que_thr_t*      thr,            /*!< in: query thread whose run_node
769
762
                                        is an update node */
770
 
        dict_foreign_t* foreign,        /* in: foreign key constraint whose
 
763
        dict_foreign_t* foreign,        /*!< in: foreign key constraint whose
771
764
                                        type is != 0 */
772
 
        btr_pcur_t*     pcur,           /* in: cursor placed on a matching
 
765
        btr_pcur_t*     pcur,           /*!< in: cursor placed on a matching
773
766
                                        index record in the child table */
774
 
        dtuple_t*       entry,          /* in: index entry in the parent
 
767
        dtuple_t*       entry,          /*!< in: index entry in the parent
775
768
                                        table */
776
 
        mtr_t*          mtr)            /* in: mtr holding the latch of pcur
 
769
        mtr_t*          mtr)            /*!< in: mtr holding the latch of pcur
777
770
                                        page */
778
771
{
779
772
        upd_node_t*     node;
808
801
 
809
802
        row_ins_invalidate_query_cache(thr, table->name);
810
803
 
811
 
        node = thr->run_node;
 
804
        node = static_cast<upd_node_t *>(thr->run_node);
812
805
 
813
806
        if (node->is_delete && 0 == (foreign->type
814
807
                                     & (DICT_FOREIGN_ON_DELETE_CASCADE
1122
1115
        return(err);
1123
1116
}
1124
1117
 
1125
 
/*************************************************************************
 
1118
/*********************************************************************//**
1126
1119
Sets a shared lock on a record. Used in locking possible duplicate key
1127
 
records and also in checking foreign key constraints. */
 
1120
records and also in checking foreign key constraints.
 
1121
@return DB_SUCCESS, DB_SUCCESS_LOCKED_REC, or error code */
1128
1122
static
1129
 
ulint
 
1123
enum db_err
1130
1124
row_ins_set_shared_rec_lock(
1131
1125
/*========================*/
1132
 
                                        /* out: DB_SUCCESS or error code */
1133
 
        ulint                   type,   /* in: LOCK_ORDINARY, LOCK_GAP, or
 
1126
        ulint                   type,   /*!< in: LOCK_ORDINARY, LOCK_GAP, or
1134
1127
                                        LOCK_REC_NOT_GAP type lock */
1135
 
        const buf_block_t*      block,  /* in: buffer block of rec */
1136
 
        const rec_t*            rec,    /* in: record */
1137
 
        dict_index_t*           index,  /* in: index */
1138
 
        const ulint*            offsets,/* in: rec_get_offsets(rec, index) */
1139
 
        que_thr_t*              thr)    /* in: query thread */
 
1128
        const buf_block_t*      block,  /*!< in: buffer block of rec */
 
1129
        const rec_t*            rec,    /*!< in: record */
 
1130
        dict_index_t*           index,  /*!< in: index */
 
1131
        const ulint*            offsets,/*!< in: rec_get_offsets(rec, index) */
 
1132
        que_thr_t*              thr)    /*!< in: query thread */
1140
1133
{
1141
 
        ulint   err;
 
1134
        enum db_err     err;
1142
1135
 
1143
1136
        ut_ad(rec_offs_validate(rec, index, offsets));
1144
1137
 
1153
1146
        return(err);
1154
1147
}
1155
1148
 
1156
 
#ifndef UNIV_HOTBACKUP
1157
 
/*************************************************************************
 
1149
/*********************************************************************//**
1158
1150
Sets a exclusive lock on a record. Used in locking possible duplicate key
1159
 
records */
 
1151
records
 
1152
@return DB_SUCCESS, DB_SUCCESS_LOCKED_REC, or error code */
1160
1153
static
1161
 
ulint
 
1154
enum db_err
1162
1155
row_ins_set_exclusive_rec_lock(
1163
1156
/*===========================*/
1164
 
                                        /* out: DB_SUCCESS or error code */
1165
 
        ulint                   type,   /* in: LOCK_ORDINARY, LOCK_GAP, or
 
1157
        ulint                   type,   /*!< in: LOCK_ORDINARY, LOCK_GAP, or
1166
1158
                                        LOCK_REC_NOT_GAP type lock */
1167
 
        const buf_block_t*      block,  /* in: buffer block of rec */
1168
 
        const rec_t*            rec,    /* in: record */
1169
 
        dict_index_t*           index,  /* in: index */
1170
 
        const ulint*            offsets,/* in: rec_get_offsets(rec, index) */
1171
 
        que_thr_t*              thr)    /* in: query thread */
 
1159
        const buf_block_t*      block,  /*!< in: buffer block of rec */
 
1160
        const rec_t*            rec,    /*!< in: record */
 
1161
        dict_index_t*           index,  /*!< in: index */
 
1162
        const ulint*            offsets,/*!< in: rec_get_offsets(rec, index) */
 
1163
        que_thr_t*              thr)    /*!< in: query thread */
1172
1164
{
1173
 
        ulint   err;
 
1165
        enum db_err     err;
1174
1166
 
1175
1167
        ut_ad(rec_offs_validate(rec, index, offsets));
1176
1168
 
1184
1176
 
1185
1177
        return(err);
1186
1178
}
1187
 
#endif /* !UNIV_HOTBACKUP */
1188
1179
 
1189
 
/*******************************************************************
 
1180
/***************************************************************//**
1190
1181
Checks if foreign key constraint fails for an index entry. Sets shared locks
1191
1182
which lock either the success or the failure of the constraint. NOTE that
1192
 
the caller must have a shared latch on dict_operation_lock. */
 
1183
the caller must have a shared latch on dict_operation_lock.
 
1184
@return DB_SUCCESS, DB_NO_REFERENCED_ROW, or DB_ROW_IS_REFERENCED */
1193
1185
UNIV_INTERN
1194
1186
ulint
1195
1187
row_ins_check_foreign_constraint(
1196
1188
/*=============================*/
1197
 
                                /* out: DB_SUCCESS,
1198
 
                                DB_NO_REFERENCED_ROW,
1199
 
                                or DB_ROW_IS_REFERENCED */
1200
 
        ibool           check_ref,/* in: TRUE if we want to check that
 
1189
        ibool           check_ref,/*!< in: TRUE if we want to check that
1201
1190
                                the referenced table is ok, FALSE if we
1202
 
                                want to to check the foreign key table */
1203
 
        dict_foreign_t* foreign,/* in: foreign constraint; NOTE that the
 
1191
                                want to check the foreign key table */
 
1192
        dict_foreign_t* foreign,/*!< in: foreign constraint; NOTE that the
1204
1193
                                tables mentioned in it must be in the
1205
1194
                                dictionary cache if they exist at all */
1206
 
        dict_table_t*   table,  /* in: if check_ref is TRUE, then the foreign
 
1195
        dict_table_t*   table,  /*!< in: if check_ref is TRUE, then the foreign
1207
1196
                                table, else the referenced table */
1208
 
        dtuple_t*       entry,  /* in: index entry for index */
1209
 
        que_thr_t*      thr)    /* in: query thread */
 
1197
        dtuple_t*       entry,  /*!< in: index entry for index */
 
1198
        que_thr_t*      thr)    /*!< in: query thread */
1210
1199
{
1211
1200
        upd_node_t*     upd_node;
1212
1201
        dict_table_t*   check_table;
1213
1202
        dict_index_t*   check_index;
1214
1203
        ulint           n_fields_cmp;
1215
1204
        btr_pcur_t      pcur;
1216
 
        ibool           moved;
1217
1205
        int             cmp;
1218
1206
        ulint           err;
1219
1207
        ulint           i;
1250
1238
        }
1251
1239
 
1252
1240
        if (que_node_get_type(thr->run_node) == QUE_NODE_UPDATE) {
1253
 
                upd_node = thr->run_node;
 
1241
                upd_node = static_cast<upd_node_t *>(thr->run_node);
1254
1242
 
1255
1243
                if (!(upd_node->is_delete) && upd_node->foreign == foreign) {
1256
1244
                        /* If a cascaded update is done as defined by a
1344
1332
 
1345
1333
        /* Scan index records and check if there is a matching record */
1346
1334
 
1347
 
        for (;;) {
 
1335
        do {
1348
1336
                const rec_t*            rec = btr_pcur_get_rec(&pcur);
1349
1337
                const buf_block_t*      block = btr_pcur_get_block(&pcur);
1350
1338
 
1351
1339
                if (page_rec_is_infimum(rec)) {
1352
1340
 
1353
 
                        goto next_rec;
 
1341
                        continue;
1354
1342
                }
1355
1343
 
1356
1344
                offsets = rec_get_offsets(rec, check_index,
1361
1349
                        err = row_ins_set_shared_rec_lock(LOCK_ORDINARY, block,
1362
1350
                                                          rec, check_index,
1363
1351
                                                          offsets, thr);
1364
 
                        if (err != DB_SUCCESS) {
1365
 
 
1366
 
                                break;
 
1352
                        switch (err) {
 
1353
                        case DB_SUCCESS_LOCKED_REC:
 
1354
                        case DB_SUCCESS:
 
1355
                                continue;
 
1356
                        default:
 
1357
                                goto end_scan;
1367
1358
                        }
1368
 
 
1369
 
                        goto next_rec;
1370
1359
                }
1371
1360
 
1372
1361
                cmp = cmp_dtuple_rec(entry, rec, offsets);
1377
1366
                                err = row_ins_set_shared_rec_lock(
1378
1367
                                        LOCK_ORDINARY, block,
1379
1368
                                        rec, check_index, offsets, thr);
1380
 
                                if (err != DB_SUCCESS) {
1381
 
 
 
1369
                                switch (err) {
 
1370
                                case DB_SUCCESS_LOCKED_REC:
 
1371
                                case DB_SUCCESS:
1382
1372
                                        break;
 
1373
                                default:
 
1374
                                        goto end_scan;
1383
1375
                                }
1384
1376
                        } else {
1385
1377
                                /* Found a matching record. Lock only
1390
1382
                                        LOCK_REC_NOT_GAP, block,
1391
1383
                                        rec, check_index, offsets, thr);
1392
1384
 
1393
 
                                if (err != DB_SUCCESS) {
1394
 
 
 
1385
                                switch (err) {
 
1386
                                case DB_SUCCESS_LOCKED_REC:
 
1387
                                case DB_SUCCESS:
1395
1388
                                        break;
 
1389
                                default:
 
1390
                                        goto end_scan;
1396
1391
                                }
1397
1392
 
1398
1393
                                if (check_ref) {
1399
1394
                                        err = DB_SUCCESS;
1400
1395
 
1401
 
                                        break;
 
1396
                                        goto end_scan;
1402
1397
                                } else if (foreign->type != 0) {
1403
1398
                                        /* There is an ON UPDATE or ON DELETE
1404
1399
                                        condition: check them in a separate
1424
1419
                                                        err = DB_FOREIGN_DUPLICATE_KEY;
1425
1420
                                                }
1426
1421
 
1427
 
                                                break;
 
1422
                                                goto end_scan;
1428
1423
                                        }
1429
1424
 
1430
1425
                                        /* row_ins_foreign_check_on_constraint
1437
1432
                                                thr, foreign, rec, entry);
1438
1433
 
1439
1434
                                        err = DB_ROW_IS_REFERENCED;
1440
 
                                        break;
 
1435
                                        goto end_scan;
1441
1436
                                }
1442
1437
                        }
1443
 
                }
 
1438
                } else {
 
1439
                        ut_a(cmp < 0);
1444
1440
 
1445
 
                if (cmp < 0) {
1446
1441
                        err = row_ins_set_shared_rec_lock(
1447
1442
                                LOCK_GAP, block,
1448
1443
                                rec, check_index, offsets, thr);
1449
 
                        if (err != DB_SUCCESS) {
1450
 
 
1451
 
                                break;
1452
 
                        }
1453
 
 
1454
 
                        if (check_ref) {
1455
 
                                err = DB_NO_REFERENCED_ROW;
1456
 
                                row_ins_foreign_report_add_err(
1457
 
                                        trx, foreign, rec, entry);
1458
 
                        } else {
1459
 
                                err = DB_SUCCESS;
1460
 
                        }
1461
 
 
1462
 
                        break;
1463
 
                }
1464
 
 
1465
 
                ut_a(cmp == 0);
1466
 
next_rec:
1467
 
                moved = btr_pcur_move_to_next(&pcur, &mtr);
1468
 
 
1469
 
                if (!moved) {
1470
 
                        if (check_ref) {
1471
 
                                rec = btr_pcur_get_rec(&pcur);
1472
 
                                row_ins_foreign_report_add_err(
1473
 
                                        trx, foreign, rec, entry);
1474
 
                                err = DB_NO_REFERENCED_ROW;
1475
 
                        } else {
1476
 
                                err = DB_SUCCESS;
1477
 
                        }
1478
 
 
1479
 
                        break;
1480
 
                }
 
1444
 
 
1445
                        switch (err) {
 
1446
                        case DB_SUCCESS_LOCKED_REC:
 
1447
                        case DB_SUCCESS:
 
1448
                                if (check_ref) {
 
1449
                                        err = DB_NO_REFERENCED_ROW;
 
1450
                                        row_ins_foreign_report_add_err(
 
1451
                                                trx, foreign, rec, entry);
 
1452
                                } else {
 
1453
                                        err = DB_SUCCESS;
 
1454
                                }
 
1455
                        }
 
1456
 
 
1457
                        goto end_scan;
 
1458
                }
 
1459
        } while (btr_pcur_move_to_next(&pcur, &mtr));
 
1460
 
 
1461
        if (check_ref) {
 
1462
                row_ins_foreign_report_add_err(
 
1463
                        trx, foreign, btr_pcur_get_rec(&pcur), entry);
 
1464
                err = DB_NO_REFERENCED_ROW;
 
1465
        } else {
 
1466
                err = DB_SUCCESS;
1481
1467
        }
1482
1468
 
 
1469
end_scan:
1483
1470
        btr_pcur_close(&pcur);
1484
1471
 
1485
1472
        mtr_commit(&mtr);
1510
1497
        return(err);
1511
1498
}
1512
1499
 
1513
 
/*******************************************************************
 
1500
/***************************************************************//**
1514
1501
Checks if foreign key constraints fail for an index entry. If index
1515
1502
is not mentioned in any constraint, this function does nothing,
1516
1503
Otherwise does searches to the indexes of referenced tables and
1517
1504
sets shared locks which lock either the success or the failure of
1518
 
a constraint. */
 
1505
a constraint.
 
1506
@return DB_SUCCESS or error code */
1519
1507
static
1520
1508
ulint
1521
1509
row_ins_check_foreign_constraints(
1522
1510
/*==============================*/
1523
 
                                /* out: DB_SUCCESS or error code */
1524
 
        dict_table_t*   table,  /* in: table */
1525
 
        dict_index_t*   index,  /* in: index */
1526
 
        dtuple_t*       entry,  /* in: index entry for index */
1527
 
        que_thr_t*      thr)    /* in: query thread */
 
1511
        dict_table_t*   table,  /*!< in: table */
 
1512
        dict_index_t*   index,  /*!< in: index */
 
1513
        dtuple_t*       entry,  /*!< in: index entry for index */
 
1514
        que_thr_t*      thr)    /*!< in: query thread */
1528
1515
{
1529
1516
        dict_foreign_t* foreign;
1530
1517
        ulint           err;
1592
1579
        return(DB_SUCCESS);
1593
1580
}
1594
1581
 
1595
 
#ifndef UNIV_HOTBACKUP
1596
 
/*******************************************************************
 
1582
/***************************************************************//**
1597
1583
Checks if a unique key violation to rec would occur at the index entry
1598
 
insert. */
 
1584
insert.
 
1585
@return TRUE if error */
1599
1586
static
1600
1587
ibool
1601
1588
row_ins_dupl_error_with_rec(
1602
1589
/*========================*/
1603
 
                                /* out: TRUE if error */
1604
 
        const rec_t*    rec,    /* in: user record; NOTE that we assume
 
1590
        const rec_t*    rec,    /*!< in: user record; NOTE that we assume
1605
1591
                                that the caller already has a record lock on
1606
1592
                                the record! */
1607
 
        const dtuple_t* entry,  /* in: entry to insert */
1608
 
        dict_index_t*   index,  /* in: index */
1609
 
        const ulint*    offsets)/* in: rec_get_offsets(rec, index) */
 
1593
        const dtuple_t* entry,  /*!< in: entry to insert */
 
1594
        dict_index_t*   index,  /*!< in: index */
 
1595
        const ulint*    offsets)/*!< in: rec_get_offsets(rec, index) */
1610
1596
{
1611
1597
        ulint   matched_fields;
1612
1598
        ulint   matched_bytes;
1644
1630
 
1645
1631
        return(!rec_get_deleted_flag(rec, rec_offs_comp(offsets)));
1646
1632
}
1647
 
#endif /* !UNIV_HOTBACKUP */
1648
1633
 
1649
 
/*******************************************************************
 
1634
/***************************************************************//**
1650
1635
Scans a unique non-clustered index at a given index entry to determine
1651
1636
whether a uniqueness violation has occurred for the key value of the entry.
1652
 
Set shared locks on possible duplicate records. */
 
1637
Set shared locks on possible duplicate records.
 
1638
@return DB_SUCCESS, DB_DUPLICATE_KEY, or DB_LOCK_WAIT */
1653
1639
static
1654
1640
ulint
1655
1641
row_ins_scan_sec_index_for_duplicate(
1656
1642
/*=================================*/
1657
 
                                /* out: DB_SUCCESS, DB_DUPLICATE_KEY, or
1658
 
                                DB_LOCK_WAIT */
1659
 
        dict_index_t*   index,  /* in: non-clustered unique index */
1660
 
        dtuple_t*       entry,  /* in: index entry */
1661
 
        que_thr_t*      thr)    /* in: query thread */
 
1643
        dict_index_t*   index,  /*!< in: non-clustered unique index */
 
1644
        dtuple_t*       entry,  /*!< in: index entry */
 
1645
        que_thr_t*      thr)    /*!< in: query thread */
1662
1646
{
1663
 
#ifndef UNIV_HOTBACKUP
1664
1647
        ulint           n_unique;
1665
1648
        ulint           i;
1666
1649
        int             cmp;
1731
1714
                                rec, index, offsets, thr);
1732
1715
                }
1733
1716
 
1734
 
                if (err != DB_SUCCESS) {
1735
 
 
 
1717
                switch (err) {
 
1718
                case DB_SUCCESS_LOCKED_REC:
 
1719
                        err = DB_SUCCESS;
 
1720
                case DB_SUCCESS:
1736
1721
                        break;
 
1722
                default:
 
1723
                        goto end_scan;
1737
1724
                }
1738
1725
 
1739
1726
                if (page_rec_is_supremum(rec)) {
1750
1737
 
1751
1738
                                thr_get_trx(thr)->error_info = index;
1752
1739
 
1753
 
                                break;
 
1740
                                goto end_scan;
1754
1741
                        }
1755
 
                }
1756
 
 
1757
 
                if (cmp < 0) {
1758
 
                        break;
1759
 
                }
1760
 
 
1761
 
                ut_a(cmp == 0);
 
1742
                } else {
 
1743
                        ut_a(cmp < 0);
 
1744
                        goto end_scan;
 
1745
                }
1762
1746
        } while (btr_pcur_move_to_next(&pcur, &mtr));
1763
1747
 
 
1748
end_scan:
1764
1749
        if (UNIV_LIKELY_NULL(heap)) {
1765
1750
                mem_heap_free(heap);
1766
1751
        }
1770
1755
        dtuple_set_n_fields_cmp(entry, n_fields_cmp);
1771
1756
 
1772
1757
        return(err);
1773
 
#else /* UNIV_HOTBACKUP */
1774
 
        /* This function depends on MySQL code that is not included in
1775
 
        InnoDB Hot Backup builds.  Besides, this function should never
1776
 
        be called in InnoDB Hot Backup. */
1777
 
        ut_error;
1778
 
        return(DB_FAIL);
1779
 
#endif /* UNIV_HOTBACKUP */
1780
1758
}
1781
1759
 
1782
 
/*******************************************************************
 
1760
/***************************************************************//**
1783
1761
Checks if a unique key violation error would occur at an index entry
1784
1762
insert. Sets shared locks on possible duplicate records. Works only
1785
 
for a clustered index! */
 
1763
for a clustered index!
 
1764
@return DB_SUCCESS if no error, DB_DUPLICATE_KEY if error,
 
1765
DB_LOCK_WAIT if we have to wait for a lock on a possible duplicate
 
1766
record */
1786
1767
static
1787
1768
ulint
1788
1769
row_ins_duplicate_error_in_clust(
1789
1770
/*=============================*/
1790
 
                                /* out: DB_SUCCESS if no error,
1791
 
                                DB_DUPLICATE_KEY if error, DB_LOCK_WAIT if we
1792
 
                                have to wait for a lock on a possible
1793
 
                                duplicate record */
1794
 
        btr_cur_t*      cursor, /* in: B-tree cursor */
1795
 
        dtuple_t*       entry,  /* in: entry to insert */
1796
 
        que_thr_t*      thr,    /* in: query thread */
1797
 
        mtr_t*          mtr)    /* in: mtr */
 
1771
        btr_cur_t*      cursor, /*!< in: B-tree cursor */
 
1772
        const dtuple_t* entry,  /*!< in: entry to insert */
 
1773
        que_thr_t*      thr,    /*!< in: query thread */
 
1774
        mtr_t*          mtr)    /*!< in: mtr */
1798
1775
{
1799
 
#ifndef UNIV_HOTBACKUP
1800
1776
        ulint   err;
1801
1777
        rec_t*  rec;
1802
1778
        ulint   n_unique;
1858
1834
                                        cursor->index, offsets, thr);
1859
1835
                        }
1860
1836
 
1861
 
                        if (err != DB_SUCCESS) {
 
1837
                        switch (err) {
 
1838
                        case DB_SUCCESS_LOCKED_REC:
 
1839
                        case DB_SUCCESS:
 
1840
                                break;
 
1841
                        default:
1862
1842
                                goto func_exit;
1863
1843
                        }
1864
1844
 
1898
1878
                                        rec, cursor->index, offsets, thr);
1899
1879
                        }
1900
1880
 
1901
 
                        if (err != DB_SUCCESS) {
 
1881
                        switch (err) {
 
1882
                        case DB_SUCCESS_LOCKED_REC:
 
1883
                        case DB_SUCCESS:
 
1884
                                break;
 
1885
                        default:
1902
1886
                                goto func_exit;
1903
1887
                        }
1904
1888
 
1920
1904
                mem_heap_free(heap);
1921
1905
        }
1922
1906
        return(err);
1923
 
#else /* UNIV_HOTBACKUP */
1924
 
        /* This function depends on MySQL code that is not included in
1925
 
        InnoDB Hot Backup builds.  Besides, this function should never
1926
 
        be called in InnoDB Hot Backup. */
1927
 
        ut_error;
1928
 
        return(DB_FAIL);
1929
 
#endif /* UNIV_HOTBACKUP */
1930
1907
}
1931
1908
 
1932
 
/*******************************************************************
 
1909
/***************************************************************//**
1933
1910
Checks if an index entry has long enough common prefix with an existing
1934
1911
record so that the intended insert of the entry must be changed to a modify of
1935
1912
the existing record. In the case of a clustered index, the prefix must be
1936
1913
n_unique fields long, and in the case of a secondary index, all fields must be
1937
 
equal. */
 
1914
equal.
 
1915
@return 0 if no update, ROW_INS_PREV if previous should be updated;
 
1916
currently we do the search so that only the low_match record can match
 
1917
enough to the search tuple, not the next record */
1938
1918
UNIV_INLINE
1939
1919
ulint
1940
1920
row_ins_must_modify(
1941
1921
/*================*/
1942
 
                                /* out: 0 if no update, ROW_INS_PREV if
1943
 
                                previous should be updated; currently we
1944
 
                                do the search so that only the low_match
1945
 
                                record can match enough to the search tuple,
1946
 
                                not the next record */
1947
 
        btr_cur_t*      cursor) /* in: B-tree cursor */
 
1922
        btr_cur_t*      cursor) /*!< in: B-tree cursor */
1948
1923
{
1949
1924
        ulint   enough_match;
1950
1925
        rec_t*  rec;
1971
1946
        return(0);
1972
1947
}
1973
1948
 
1974
 
/*******************************************************************
 
1949
/***************************************************************//**
1975
1950
Tries to insert an index entry to an index. If the index is clustered
1976
1951
and a record with the same unique key is found, the other record is
1977
1952
necessarily marked deleted by a committed transaction, or a unique key
1979
1954
existing record, and we must write an undo log record on the delete
1980
1955
marked record. If the index is secondary, and a record with exactly the
1981
1956
same fields is found, the other record is necessarily marked deleted.
1982
 
It is then unmarked. Otherwise, the entry is just inserted to the index. */
 
1957
It is then unmarked. Otherwise, the entry is just inserted to the index.
 
1958
@return DB_SUCCESS, DB_LOCK_WAIT, DB_FAIL if pessimistic retry needed,
 
1959
or error code */
1983
1960
static
1984
1961
ulint
1985
1962
row_ins_index_entry_low(
1986
1963
/*====================*/
1987
 
                                /* out: DB_SUCCESS, DB_LOCK_WAIT, DB_FAIL
1988
 
                                if pessimistic retry needed, or error code */
1989
 
        ulint           mode,   /* in: BTR_MODIFY_LEAF or BTR_MODIFY_TREE,
 
1964
        ulint           mode,   /*!< in: BTR_MODIFY_LEAF or BTR_MODIFY_TREE,
1990
1965
                                depending on whether we wish optimistic or
1991
1966
                                pessimistic descent down the index tree */
1992
 
        dict_index_t*   index,  /* in: index */
1993
 
        dtuple_t*       entry,  /* in: index entry to insert */
1994
 
        ulint           n_ext,  /* in: number of externally stored columns */
1995
 
        que_thr_t*      thr)    /* in: query thread */
 
1967
        dict_index_t*   index,  /*!< in: index */
 
1968
        dtuple_t*       entry,  /*!< in/out: index entry to insert */
 
1969
        ulint           n_ext,  /*!< in: number of externally stored columns */
 
1970
        que_thr_t*      thr)    /*!< in: query thread */
1996
1971
{
1997
1972
        btr_cur_t       cursor;
1998
 
        ulint           ignore_sec_unique       = 0;
 
1973
        ulint           search_mode;
1999
1974
        ulint           modify = 0; /* remove warning */
2000
1975
        rec_t*          insert_rec;
2001
1976
        rec_t*          rec;
2015
1990
        the function will return in both low_match and up_match of the
2016
1991
        cursor sensible values */
2017
1992
 
2018
 
        if (!(thr_get_trx(thr)->check_unique_secondary)) {
2019
 
                ignore_sec_unique = BTR_IGNORE_SEC_UNIQUE;
 
1993
        if (dict_index_is_clust(index)) {
 
1994
                search_mode = mode;
 
1995
        } else if (!(thr_get_trx(thr)->check_unique_secondary)) {
 
1996
                search_mode = mode | BTR_INSERT | BTR_IGNORE_SEC_UNIQUE;
 
1997
        } else {
 
1998
                search_mode = mode | BTR_INSERT;
2020
1999
        }
2021
2000
 
2022
2001
        btr_cur_search_to_nth_level(index, 0, entry, PAGE_CUR_LE,
2023
 
                                    mode | BTR_INSERT | ignore_sec_unique,
2024
 
                                    &cursor, 0, &mtr);
 
2002
                                    search_mode,
 
2003
                                    &cursor, 0, __FILE__, __LINE__, &mtr);
2025
2004
 
2026
2005
        if (cursor.flag == BTR_CUR_INSERT_TO_IBUF) {
2027
2006
                /* The insertion was made to the insert buffer already during
2028
2007
                the search: we are done */
2029
2008
 
 
2009
                ut_ad(search_mode & BTR_INSERT);
2030
2010
                err = DB_SUCCESS;
2031
2011
 
2032
2012
                goto function_exit;
2079
2059
                        btr_cur_search_to_nth_level(index, 0, entry,
2080
2060
                                                    PAGE_CUR_LE,
2081
2061
                                                    mode | BTR_INSERT,
2082
 
                                                    &cursor, 0, &mtr);
 
2062
                                                    &cursor, 0,
 
2063
                                                    __FILE__, __LINE__, &mtr);
2083
2064
                }
2084
2065
        }
2085
2066
 
2129
2110
        mtr_commit(&mtr);
2130
2111
 
2131
2112
        if (UNIV_LIKELY_NULL(big_rec)) {
2132
 
                rec_t*  rec;
 
2113
                rec_t*  exit_rec;
2133
2114
                ulint*  offsets;
2134
2115
                mtr_start(&mtr);
2135
2116
 
2136
2117
                btr_cur_search_to_nth_level(index, 0, entry, PAGE_CUR_LE,
2137
 
                                            BTR_MODIFY_TREE, &cursor, 0, &mtr);
2138
 
                rec = btr_cur_get_rec(&cursor);
2139
 
                offsets = rec_get_offsets(rec, index, NULL,
 
2118
                                            BTR_MODIFY_TREE, &cursor, 0,
 
2119
                                            __FILE__, __LINE__, &mtr);
 
2120
                exit_rec = btr_cur_get_rec(&cursor);
 
2121
                offsets = rec_get_offsets(exit_rec, index, NULL,
2140
2122
                                          ULINT_UNDEFINED, &heap);
2141
2123
 
2142
2124
                err = btr_store_big_rec_extern_fields(
2143
2125
                        index, btr_cur_get_block(&cursor),
2144
 
                        rec, offsets, big_rec, &mtr);
 
2126
                        exit_rec, offsets, big_rec, &mtr);
2145
2127
 
2146
2128
                if (modify) {
2147
2129
                        dtuple_big_rec_free(big_rec);
2158
2140
        return(err);
2159
2141
}
2160
2142
 
2161
 
/*******************************************************************
 
2143
/***************************************************************//**
2162
2144
Inserts an index entry to index. Tries first optimistic, then pessimistic
2163
2145
descent down the tree. If the entry matches enough to a delete marked record,
2164
2146
performs the insert by updating or delete unmarking the delete marked
2165
 
record. */
 
2147
record.
 
2148
@return DB_SUCCESS, DB_LOCK_WAIT, DB_DUPLICATE_KEY, or some other error code */
2166
2149
UNIV_INTERN
2167
2150
ulint
2168
2151
row_ins_index_entry(
2169
2152
/*================*/
2170
 
                                /* out: DB_SUCCESS, DB_LOCK_WAIT,
2171
 
                                DB_DUPLICATE_KEY, or some other error code */
2172
 
        dict_index_t*   index,  /* in: index */
2173
 
        dtuple_t*       entry,  /* in: index entry to insert */
2174
 
        ulint           n_ext,  /* in: number of externally stored columns */
2175
 
        ibool           foreign,/* in: TRUE=check foreign key constraints */
2176
 
        que_thr_t*      thr)    /* in: query thread */
 
2153
        dict_index_t*   index,  /*!< in: index */
 
2154
        dtuple_t*       entry,  /*!< in/out: index entry to insert */
 
2155
        ulint           n_ext,  /*!< in: number of externally stored columns */
 
2156
        ibool           foreign,/*!< in: TRUE=check foreign key constraints
 
2157
                                (foreign=FALSE only during CREATE INDEX) */
 
2158
        que_thr_t*      thr)    /*!< in: query thread */
2177
2159
{
2178
 
        ulint   err;
 
2160
        enum db_err     err;
2179
2161
 
2180
2162
        if (foreign && UT_LIST_GET_FIRST(index->table->foreign_list)) {
2181
 
                err = row_ins_check_foreign_constraints(index->table, index,
2182
 
                                                        entry, thr);
 
2163
                err = static_cast<db_err>(row_ins_check_foreign_constraints(index->table, index,
 
2164
                                                        entry, thr));
2183
2165
                if (err != DB_SUCCESS) {
2184
2166
 
2185
2167
                        return(err);
2188
2170
 
2189
2171
        /* Try first optimistic descent to the B-tree */
2190
2172
 
2191
 
        err = row_ins_index_entry_low(BTR_MODIFY_LEAF, index, entry,
2192
 
                                      n_ext, thr);
 
2173
        err = static_cast<db_err>(row_ins_index_entry_low(BTR_MODIFY_LEAF, index, entry,
 
2174
                                      n_ext, thr));
2193
2175
        if (err != DB_FAIL) {
2194
2176
 
2195
2177
                return(err);
2197
2179
 
2198
2180
        /* Try then pessimistic descent to the B-tree */
2199
2181
 
2200
 
        err = row_ins_index_entry_low(BTR_MODIFY_TREE, index, entry,
2201
 
                                      n_ext, thr);
 
2182
        err = static_cast<db_err>(row_ins_index_entry_low(BTR_MODIFY_TREE, index, entry,
 
2183
                                      n_ext, thr));
2202
2184
        return(err);
2203
2185
}
2204
2186
 
2205
 
/***************************************************************
 
2187
/***********************************************************//**
2206
2188
Sets the values of the dtuple fields in entry from the values of appropriate
2207
2189
columns in row. */
2208
2190
static
2209
2191
void
2210
2192
row_ins_index_entry_set_vals(
2211
2193
/*=========================*/
2212
 
        dict_index_t*   index,  /* in: index */
2213
 
        dtuple_t*       entry,  /* in: index entry to make */
2214
 
        const dtuple_t* row)    /* in: row */
 
2194
        dict_index_t*   index,  /*!< in: index */
 
2195
        dtuple_t*       entry,  /*!< in: index entry to make */
 
2196
        const dtuple_t* row)    /*!< in: row */
2215
2197
{
2216
2198
        ulint   n_fields;
2217
2199
        ulint   i;
2239
2221
                                = dict_field_get_col(ind_field);
2240
2222
 
2241
2223
                        len = dtype_get_at_most_n_mbchars(
2242
 
                                col->prtype, col->mbminlen, col->mbmaxlen,
 
2224
                                col->prtype, col->mbminmaxlen,
2243
2225
                                ind_field->prefix_len,
2244
 
                                len, dfield_get_data(row_field));
 
2226
                                len, static_cast<const char *>(dfield_get_data(row_field)));
2245
2227
 
2246
2228
                        ut_ad(!dfield_is_ext(row_field));
2247
2229
                }
2254
2236
        }
2255
2237
}
2256
2238
 
2257
 
/***************************************************************
2258
 
Inserts a single index entry to the table. */
 
2239
/***********************************************************//**
 
2240
Inserts a single index entry to the table.
 
2241
@return DB_SUCCESS if operation successfully completed, else error
 
2242
code or DB_LOCK_WAIT */
2259
2243
static
2260
2244
ulint
2261
2245
row_ins_index_entry_step(
2262
2246
/*=====================*/
2263
 
                                /* out: DB_SUCCESS if operation successfully
2264
 
                                completed, else error code or DB_LOCK_WAIT */
2265
 
        ins_node_t*     node,   /* in: row insert node */
2266
 
        que_thr_t*      thr)    /* in: query thread */
 
2247
        ins_node_t*     node,   /*!< in: row insert node */
 
2248
        que_thr_t*      thr)    /*!< in: query thread */
2267
2249
{
2268
 
        ulint   err;
 
2250
        enum db_err     err;
2269
2251
 
2270
2252
        ut_ad(dtuple_check_typed(node->row));
2271
2253
 
2273
2255
 
2274
2256
        ut_ad(dtuple_check_typed(node->entry));
2275
2257
 
2276
 
        err = row_ins_index_entry(node->index, node->entry, 0, TRUE, thr);
 
2258
        err = static_cast<db_err>(row_ins_index_entry(node->index, node->entry, 0, TRUE, thr));
2277
2259
 
2278
2260
        return(err);
2279
2261
}
2280
2262
 
2281
 
/***************************************************************
 
2263
/***********************************************************//**
2282
2264
Allocates a row id for row and inits the node->index field. */
2283
2265
UNIV_INLINE
2284
2266
void
2285
2267
row_ins_alloc_row_id_step(
2286
2268
/*======================*/
2287
 
        ins_node_t*     node)   /* in: row insert node */
 
2269
        ins_node_t*     node)   /*!< in: row insert node */
2288
2270
{
2289
 
        dulint  row_id;
 
2271
        row_id_t        row_id;
2290
2272
 
2291
2273
        ut_ad(node->state == INS_NODE_ALLOC_ROW_ID);
2292
2274
 
2304
2286
        dict_sys_write_row_id(node->row_id_buf, row_id);
2305
2287
}
2306
2288
 
2307
 
/***************************************************************
 
2289
/***********************************************************//**
2308
2290
Gets a row to insert from the values list. */
2309
2291
UNIV_INLINE
2310
2292
void
2311
2293
row_ins_get_row_from_values(
2312
2294
/*========================*/
2313
 
        ins_node_t*     node)   /* in: row insert node */
 
2295
        ins_node_t*     node)   /*!< in: row insert node */
2314
2296
{
2315
2297
        que_node_t*     list_node;
2316
2298
        dfield_t*       dfield;
2337
2319
        }
2338
2320
}
2339
2321
 
2340
 
/***************************************************************
 
2322
/***********************************************************//**
2341
2323
Gets a row to insert from the select list. */
2342
2324
UNIV_INLINE
2343
2325
void
2344
2326
row_ins_get_row_from_select(
2345
2327
/*========================*/
2346
 
        ins_node_t*     node)   /* in: row insert node */
 
2328
        ins_node_t*     node)   /*!< in: row insert node */
2347
2329
{
2348
2330
        que_node_t*     list_node;
2349
2331
        dfield_t*       dfield;
2368
2350
        }
2369
2351
}
2370
2352
 
2371
 
/***************************************************************
2372
 
Inserts a row to a table. */
 
2353
/***********************************************************//**
 
2354
Inserts a row to a table.
 
2355
@return DB_SUCCESS if operation successfully completed, else error
 
2356
code or DB_LOCK_WAIT */
2373
2357
static
2374
2358
ulint
2375
2359
row_ins(
2376
2360
/*====*/
2377
 
                                /* out: DB_SUCCESS if operation successfully
2378
 
                                completed, else error code or DB_LOCK_WAIT */
2379
 
        ins_node_t*     node,   /* in: row insert node */
2380
 
        que_thr_t*      thr)    /* in: query thread */
 
2361
        ins_node_t*     node,   /*!< in: row insert node */
 
2362
        que_thr_t*      thr)    /*!< in: query thread */
2381
2363
{
2382
2364
        ulint   err;
2383
2365
 
2423
2405
        return(DB_SUCCESS);
2424
2406
}
2425
2407
 
2426
 
/***************************************************************
 
2408
/***********************************************************//**
2427
2409
Inserts a row to a table. This is a high-level function used in SQL execution
2428
 
graphs. */
 
2410
graphs.
 
2411
@return query thread to run next or NULL */
2429
2412
UNIV_INTERN
2430
2413
que_thr_t*
2431
2414
row_ins_step(
2432
2415
/*=========*/
2433
 
                                /* out: query thread to run next or NULL */
2434
 
        que_thr_t*      thr)    /* in: query thread */
 
2416
        que_thr_t*      thr)    /*!< in: query thread */
2435
2417
{
2436
2418
        ins_node_t*     node;
2437
2419
        que_node_t*     parent;
2445
2427
 
2446
2428
        trx_start_if_not_started(trx);
2447
2429
 
2448
 
        node = thr->run_node;
 
2430
        node = static_cast<ins_node_t *>(thr->run_node);
2449
2431
 
2450
2432
        ut_ad(que_node_get_type(node) == QUE_NODE_INSERT);
2451
2433
 
2473
2455
                /* It may be that the current session has not yet started
2474
2456
                its transaction, or it has been committed: */
2475
2457
 
2476
 
                if (UT_DULINT_EQ(trx->id, node->trx_id)) {
 
2458
                if (trx->id == node->trx_id) {
2477
2459
                        /* No need to do IX-locking */
2478
2460
 
2479
2461
                        goto same_trx;