~drizzle-trunk/drizzle/development

« back to all changes in this revision

Viewing changes to storage/innobase/row/row0ins.c

  • Committer: Brian Aker
  • Date: 2008-10-28 08:36:02 UTC
  • mfrom: (520.4.13 merge-innodb-plugin)
  • Revision ID: brian@tangent.org-20081028083602-0p3zzlhlxr5q2sqo
Merging Monty's work

Show diffs side-by-side

added added

removed removed

Lines of Context:
53
53
 
54
54
/*************************************************************************
55
55
Creates an insert node struct. */
56
 
 
 
56
UNIV_INTERN
57
57
ins_node_t*
58
58
ins_node_create(
59
59
/*============*/
88
88
 
89
89
/***************************************************************
90
90
Creates an entry template for each index of a table. */
91
 
static
 
91
UNIV_INTERN
92
92
void
93
93
ins_node_create_entry_list(
94
94
/*=======================*/
104
104
        index = dict_table_get_first_index(node->table);
105
105
 
106
106
        while (index != NULL) {
107
 
                entry = row_build_index_entry(node->row, index,
 
107
                entry = row_build_index_entry(node->row, NULL, index,
108
108
                                              node->entry_sys_heap);
109
109
                UT_LIST_ADD_LAST(tuple_list, node->entry_list, entry);
110
110
 
171
171
Sets a new row to insert for an INS_DIRECT node. This function is only used
172
172
if we have constructed the row separately, which is a rare case; this
173
173
function is quite slow. */
174
 
 
 
174
UNIV_INTERN
175
175
void
176
176
ins_node_set_new_row(
177
177
/*=================*/
213
213
                                depending on whether mtr holds just a leaf
214
214
                                latch or also a tree latch */
215
215
        btr_cur_t*      cursor, /* in: B-tree cursor */
216
 
        dtuple_t*       entry,  /* in: index entry to insert */
 
216
        const dtuple_t* entry,  /* in: index entry to insert */
217
217
        que_thr_t*      thr,    /* in: query thread */
218
 
        mtr_t*          mtr)    /* in: mtr */
 
218
        mtr_t*          mtr)    /* in: mtr; must be committed before
 
219
                                latching any further pages */
219
220
{
220
221
        big_rec_t*      dummy_big_rec;
221
222
        mem_heap_t*     heap;
225
226
 
226
227
        rec = btr_cur_get_rec(cursor);
227
228
 
228
 
        ut_ad((cursor->index->type & DICT_CLUSTERED) == 0);
 
229
        ut_ad(!dict_index_is_clust(cursor->index));
229
230
        ut_ad(rec_get_deleted_flag(rec,
230
231
                                   dict_table_is_comp(cursor->index->table)));
231
232
 
244
245
 
245
246
                err = btr_cur_optimistic_update(BTR_KEEP_SYS_FLAG, cursor,
246
247
                                                update, 0, thr, mtr);
247
 
                if (err == DB_OVERFLOW || err == DB_UNDERFLOW) {
 
248
                switch (err) {
 
249
                case DB_OVERFLOW:
 
250
                case DB_UNDERFLOW:
 
251
                case DB_ZIP_OVERFLOW:
248
252
                        err = DB_FAIL;
249
253
                }
250
254
        } else {
257
261
                }
258
262
 
259
263
                err = btr_cur_pessimistic_update(BTR_KEEP_SYS_FLAG, cursor,
260
 
                                                 &dummy_big_rec, update,
 
264
                                                 &heap, &dummy_big_rec, update,
261
265
                                                 0, thr, mtr);
 
266
                ut_ad(!dummy_big_rec);
262
267
        }
263
268
func_exit:
264
269
        mem_heap_free(heap);
279
284
                                depending on whether mtr holds just a leaf
280
285
                                latch or also a tree latch */
281
286
        btr_cur_t*      cursor, /* in: B-tree cursor */
 
287
        mem_heap_t**    heap,   /* in/out: pointer to memory heap, or NULL */
282
288
        big_rec_t**     big_rec,/* out: possible big rec vector of fields
283
289
                                which have to be stored externally by the
284
290
                                caller */
285
 
        dtuple_t*       entry,  /* in: index entry to insert */
286
 
        ulint*          ext_vec,/* in: array containing field numbers of
287
 
                                externally stored fields in entry, or NULL */
288
 
        ulint           n_ext_vec,/* in: number of fields in ext_vec */
 
291
        const dtuple_t* entry,  /* in: index entry to insert */
289
292
        que_thr_t*      thr,    /* in: query thread */
290
 
        mtr_t*          mtr)    /* in: mtr */
 
293
        mtr_t*          mtr)    /* in: mtr; must be committed before
 
294
                                latching any further pages */
291
295
{
292
 
        mem_heap_t*     heap;
293
296
        rec_t*          rec;
294
297
        upd_t*          update;
295
298
        ulint           err;
296
299
 
297
 
        ut_ad(cursor->index->type & DICT_CLUSTERED);
 
300
        ut_ad(dict_index_is_clust(cursor->index));
298
301
 
299
302
        *big_rec = NULL;
300
303
 
303
306
        ut_ad(rec_get_deleted_flag(rec,
304
307
                                   dict_table_is_comp(cursor->index->table)));
305
308
 
306
 
        heap = mem_heap_create(1024);
 
309
        if (!*heap) {
 
310
                *heap = mem_heap_create(1024);
 
311
        }
307
312
 
308
313
        /* Build an update vector containing all the fields to be modified;
309
314
        NOTE that this vector may NOT contain system columns trx_id or
310
315
        roll_ptr */
311
316
 
312
 
        update = row_upd_build_difference_binary(cursor->index, entry, ext_vec,
313
 
                                                 n_ext_vec, rec,
314
 
                                                 thr_get_trx(thr), heap);
 
317
        update = row_upd_build_difference_binary(cursor->index, entry, rec,
 
318
                                                 thr_get_trx(thr), *heap);
315
319
        if (mode == BTR_MODIFY_LEAF) {
316
320
                /* Try optimistic updating of the record, keeping changes
317
321
                within the page */
318
322
 
319
323
                err = btr_cur_optimistic_update(0, cursor, update, 0, thr,
320
324
                                                mtr);
321
 
                if (err == DB_OVERFLOW || err == DB_UNDERFLOW) {
 
325
                switch (err) {
 
326
                case DB_OVERFLOW:
 
327
                case DB_UNDERFLOW:
 
328
                case DB_ZIP_OVERFLOW:
322
329
                        err = DB_FAIL;
323
330
                }
324
331
        } else {
325
332
                ut_a(mode == BTR_MODIFY_TREE);
326
333
                if (buf_LRU_buf_pool_running_out()) {
327
334
 
328
 
                        err = DB_LOCK_TABLE_FULL;
 
335
                        return(DB_LOCK_TABLE_FULL);
329
336
 
330
 
                        goto func_exit;
331
337
                }
332
 
                err = btr_cur_pessimistic_update(0, cursor, big_rec, update,
 
338
                err = btr_cur_pessimistic_update(0, cursor,
 
339
                                                 heap, big_rec, update,
333
340
                                                 0, thr, mtr);
334
341
        }
335
 
func_exit:
336
 
        mem_heap_free(heap);
337
342
 
338
343
        return(err);
339
344
}
469
474
 
470
475
                                ulint                   min_size;
471
476
                                const dict_col_t*       col;
 
477
                                ulint                   ufield_len;
472
478
 
473
479
                                col = dict_index_get_nth_col(index, i);
474
480
 
484
490
                                ufield->exp = NULL;
485
491
 
486
492
                                ufield->new_val = parent_ufield->new_val;
 
493
                                ufield_len = dfield_get_len(&ufield->new_val);
 
494
 
 
495
                                /* Clear the "external storage" flag */
 
496
                                dfield_set_len(&ufield->new_val, ufield_len);
487
497
 
488
498
                                /* Do not allow a NOT NULL column to be
489
499
                                updated as NULL */
490
500
 
491
 
                                if (ufield->new_val.len == UNIV_SQL_NULL
 
501
                                if (dfield_is_null(&ufield->new_val)
492
502
                                    && (col->prtype & DATA_NOT_NULL)) {
493
503
 
494
504
                                        return(ULINT_UNDEFINED);
497
507
                                /* If the new value would not fit in the
498
508
                                column, do not allow the update */
499
509
 
500
 
                                if (ufield->new_val.len != UNIV_SQL_NULL
 
510
                                if (!dfield_is_null(&ufield->new_val)
501
511
                                    && dtype_get_at_most_n_mbchars(
502
512
                                        col->prtype,
503
513
                                        col->mbminlen, col->mbmaxlen,
504
514
                                        col->len,
505
 
                                        ufield->new_val.len,
506
 
                                        ufield->new_val.data)
507
 
                                    < ufield->new_val.len) {
 
515
                                        ufield_len,
 
516
                                        dfield_get_data(&ufield->new_val))
 
517
                                    < ufield_len) {
508
518
 
509
519
                                        return(ULINT_UNDEFINED);
510
520
                                }
516
526
 
517
527
                                min_size = dict_col_get_min_size(col);
518
528
 
519
 
                                if (min_size
520
 
                                    && ufield->new_val.len != UNIV_SQL_NULL
521
 
                                    && ufield->new_val.len < min_size) {
 
529
                                /* Because UNIV_SQL_NULL (the marker
 
530
                                of SQL NULL values) exceeds all possible
 
531
                                values of min_size, the test below will
 
532
                                not hold for SQL NULL columns. */
 
533
 
 
534
                                if (min_size > ufield_len) {
522
535
 
523
536
                                        char*           pad_start;
524
537
                                        const char*     pad_end;
525
 
                                        ufield->new_val.data = mem_heap_alloc(
526
 
                                                heap, min_size);
527
 
                                        pad_start = ((char*) ufield
528
 
                                                     ->new_val.data)
529
 
                                                + ufield->new_val.len;
530
 
                                        pad_end = ((char*) ufield
531
 
                                                   ->new_val.data)
532
 
                                                + min_size;
533
 
                                        ufield->new_val.len = min_size;
534
 
                                        ut_memcpy(ufield->new_val.data,
535
 
                                                  parent_ufield->new_val.data,
536
 
                                                  parent_ufield->new_val.len);
 
538
                                        char*           padded_data
 
539
                                                = mem_heap_alloc(
 
540
                                                        heap, min_size);
 
541
                                        pad_start = padded_data + ufield_len;
 
542
                                        pad_end = padded_data + min_size;
 
543
 
 
544
                                        memcpy(padded_data,
 
545
                                               dfield_get_data(&ufield
 
546
                                                               ->new_val),
 
547
                                               dfield_get_len(&ufield
 
548
                                                              ->new_val));
537
549
 
538
550
                                        switch (UNIV_EXPECT(col->mbminlen,1)) {
539
551
                                        default:
540
552
                                                ut_error;
 
553
                                                return(ULINT_UNDEFINED);
541
554
                                        case 1:
542
555
                                                if (UNIV_UNLIKELY
543
556
                                                    (dtype_get_charset_coll(
544
557
                                                            col->prtype)
545
 
                                                     == DATA_DRIZZLE_BINARY_CHARSET_COLL)) {
 
558
                                                     == DATA_MYSQL_BINARY_CHARSET_COLL)) {
546
559
                                                        /* Do not pad BINARY
547
560
                                                        columns. */
548
561
                                                        return(ULINT_UNDEFINED);
554
567
                                                break;
555
568
                                        case 2:
556
569
                                                /* space=0x0020 */
557
 
                                                ut_a(!(ufield->new_val.len
558
 
                                                       % 2));
 
570
                                                ut_a(!(ufield_len % 2));
559
571
                                                ut_a(!(min_size % 2));
560
572
                                                do {
561
573
                                                        *pad_start++ = 0x00;
563
575
                                                } while (pad_start < pad_end);
564
576
                                                break;
565
577
                                        }
 
578
 
 
579
                                        dfield_set_data(&ufield->new_val,
 
580
                                                        padded_data, min_size);
566
581
                                }
567
582
 
568
 
                                ufield->extern_storage = FALSE;
569
 
 
570
583
                                n_fields_updated++;
571
584
                        }
572
585
                }
615
628
        que_thr_t*      thr,            /* in: query thread whose run_node
616
629
                                        is an update node */
617
630
        dict_foreign_t* foreign,        /* in: foreign key constraint */
618
 
        rec_t*          rec,            /* in: a matching index record in the
 
631
        const rec_t*    rec,            /* in: a matching index record in the
619
632
                                        child table */
620
 
        dtuple_t*       entry)          /* in: index entry in the parent
 
633
        const dtuple_t* entry)          /* in: index entry in the parent
621
634
                                        table */
622
635
{
623
636
        FILE*   ef      = dict_foreign_err_file;
669
682
/*===========================*/
670
683
        trx_t*          trx,            /* in: transaction */
671
684
        dict_foreign_t* foreign,        /* in: foreign key constraint */
672
 
        rec_t*          rec,            /* in: a record in the parent table:
 
685
        const rec_t*    rec,            /* in: a record in the parent table:
673
686
                                        it does not match entry because we
674
687
                                        have an error! */
675
 
        dtuple_t*       entry)          /* in: index entry to insert in the
 
688
        const dtuple_t* entry)          /* in: index entry to insert in the
676
689
                                        child table */
677
690
{
678
691
        FILE*   ef      = dict_foreign_err_file;
693
706
        ut_print_name(ef, trx, FALSE, foreign->foreign_index->name);
694
707
        if (entry) {
695
708
                fputs(" tuple:\n", ef);
 
709
                /* TODO: DB_TRX_ID and DB_ROLL_PTR may be uninitialized.
 
710
                It would be better to only display the user columns. */
696
711
                dtuple_print(ef, entry);
697
712
        }
698
713
        fputs("\nBut in parent table ", ef);
704
719
                /* If the cursor ended on a supremum record, it is better
705
720
                to report the previous record in the error message, so that
706
721
                the user gets a more descriptive error message. */
707
 
                rec = page_rec_get_prev(rec);
 
722
                rec = page_rec_get_prev_const(rec);
708
723
        }
709
724
 
710
725
        if (rec) {
771
786
        dict_index_t*   clust_index;
772
787
        dtuple_t*       ref;
773
788
        mem_heap_t*     upd_vec_heap    = NULL;
774
 
        rec_t*          rec;
775
 
        rec_t*          clust_rec;
 
789
        const rec_t*    rec;
 
790
        const rec_t*    clust_rec;
 
791
        const buf_block_t* clust_block;
776
792
        upd_t*          update;
777
793
        ulint           n_to_update;
778
794
        ulint           err;
899
915
 
900
916
        rec = btr_pcur_get_rec(pcur);
901
917
 
902
 
        if (index->type & DICT_CLUSTERED) {
 
918
        if (dict_index_is_clust(index)) {
903
919
                /* pcur is already positioned in the clustered index of
904
920
                the child table */
905
921
 
906
922
                clust_index = index;
907
923
                clust_rec = rec;
 
924
                clust_block = btr_pcur_get_block(pcur);
908
925
        } else {
909
926
                /* We have to look for the record in the clustered index
910
927
                in the child table */
920
937
                                           cascade->pcur, 0, mtr);
921
938
 
922
939
                clust_rec = btr_pcur_get_rec(cascade->pcur);
 
940
                clust_block = btr_pcur_get_block(cascade->pcur);
923
941
 
924
942
                if (!page_rec_is_user_rec(clust_rec)
925
943
                    || btr_pcur_get_low_match(cascade->pcur)
955
973
                gap if the search criterion was not unique */
956
974
 
957
975
                err = lock_clust_rec_read_check_and_lock_alt(
958
 
                        0, clust_rec, clust_index, LOCK_X, LOCK_REC_NOT_GAP,
959
 
                        thr);
 
976
                        0, clust_block, clust_rec, clust_index,
 
977
                        LOCK_X, LOCK_REC_NOT_GAP, thr);
960
978
        }
961
979
 
962
980
        if (err != DB_SUCCESS) {
987
1005
                update->n_fields = foreign->n_fields;
988
1006
 
989
1007
                for (i = 0; i < foreign->n_fields; i++) {
990
 
                        (update->fields + i)->field_no
991
 
                                = dict_table_get_nth_col_pos(
992
 
                                        table,
993
 
                                        dict_index_get_nth_col_no(index, i));
994
 
                        (update->fields + i)->exp = NULL;
995
 
                        (update->fields + i)->new_val.len = UNIV_SQL_NULL;
996
 
                        (update->fields + i)->new_val.data = NULL;
997
 
                        (update->fields + i)->extern_storage = FALSE;
 
1008
                        upd_field_t*    ufield = &update->fields[i];
 
1009
 
 
1010
                        ufield->field_no = dict_table_get_nth_col_pos(
 
1011
                                table,
 
1012
                                dict_index_get_nth_col_no(index, i));
 
1013
                        ufield->orig_len = 0;
 
1014
                        ufield->exp = NULL;
 
1015
                        dfield_set_null(&ufield->new_val);
998
1016
                }
999
1017
        }
1000
1018
 
1114
1132
ulint
1115
1133
row_ins_set_shared_rec_lock(
1116
1134
/*========================*/
1117
 
                                /* out: DB_SUCCESS or error code */
1118
 
        ulint           type,   /* in: LOCK_ORDINARY, LOCK_GAP, or
1119
 
                                LOCK_REC_NOT_GAP type lock */
1120
 
        rec_t*          rec,    /* in: record */
1121
 
        dict_index_t*   index,  /* in: index */
1122
 
        const ulint*    offsets,/* in: rec_get_offsets(rec, index) */
1123
 
        que_thr_t*      thr)    /* in: query thread */
 
1135
                                        /* out: DB_SUCCESS or error code */
 
1136
        ulint                   type,   /* in: LOCK_ORDINARY, LOCK_GAP, or
 
1137
                                        LOCK_REC_NOT_GAP type lock */
 
1138
        const buf_block_t*      block,  /* in: buffer block of rec */
 
1139
        const rec_t*            rec,    /* in: record */
 
1140
        dict_index_t*           index,  /* in: index */
 
1141
        const ulint*            offsets,/* in: rec_get_offsets(rec, index) */
 
1142
        que_thr_t*              thr)    /* in: query thread */
1124
1143
{
1125
1144
        ulint   err;
1126
1145
 
1127
1146
        ut_ad(rec_offs_validate(rec, index, offsets));
1128
1147
 
1129
 
        if (index->type & DICT_CLUSTERED) {
 
1148
        if (dict_index_is_clust(index)) {
1130
1149
                err = lock_clust_rec_read_check_and_lock(
1131
 
                        0, rec, index, offsets, LOCK_S, type, thr);
 
1150
                        0, block, rec, index, offsets, LOCK_S, type, thr);
1132
1151
        } else {
1133
1152
                err = lock_sec_rec_read_check_and_lock(
1134
 
                        0, rec, index, offsets, LOCK_S, type, thr);
 
1153
                        0, block, rec, index, offsets, LOCK_S, type, thr);
1135
1154
        }
1136
1155
 
1137
1156
        return(err);
1145
1164
ulint
1146
1165
row_ins_set_exclusive_rec_lock(
1147
1166
/*===========================*/
1148
 
                                /* out: DB_SUCCESS or error code */
1149
 
        ulint           type,   /* in: LOCK_ORDINARY, LOCK_GAP, or
1150
 
                                LOCK_REC_NOT_GAP type lock */
1151
 
        rec_t*          rec,    /* in: record */
1152
 
        dict_index_t*   index,  /* in: index */
1153
 
        const ulint*    offsets,/* in: rec_get_offsets(rec, index) */
1154
 
        que_thr_t*      thr)    /* in: query thread */
 
1167
                                        /* out: DB_SUCCESS or error code */
 
1168
        ulint                   type,   /* in: LOCK_ORDINARY, LOCK_GAP, or
 
1169
                                        LOCK_REC_NOT_GAP type lock */
 
1170
        const buf_block_t*      block,  /* in: buffer block of rec */
 
1171
        const rec_t*            rec,    /* in: record */
 
1172
        dict_index_t*           index,  /* in: index */
 
1173
        const ulint*            offsets,/* in: rec_get_offsets(rec, index) */
 
1174
        que_thr_t*              thr)    /* in: query thread */
1155
1175
{
1156
1176
        ulint   err;
1157
1177
 
1158
1178
        ut_ad(rec_offs_validate(rec, index, offsets));
1159
1179
 
1160
 
        if (index->type & DICT_CLUSTERED) {
 
1180
        if (dict_index_is_clust(index)) {
1161
1181
                err = lock_clust_rec_read_check_and_lock(
1162
 
                        0, rec, index, offsets, LOCK_X, type, thr);
 
1182
                        0, block, rec, index, offsets, LOCK_X, type, thr);
1163
1183
        } else {
1164
1184
                err = lock_sec_rec_read_check_and_lock(
1165
 
                        0, rec, index, offsets, LOCK_X, type, thr);
 
1185
                        0, block, rec, index, offsets, LOCK_X, type, thr);
1166
1186
        }
1167
1187
 
1168
1188
        return(err);
1173
1193
Checks if foreign key constraint fails for an index entry. Sets shared locks
1174
1194
which lock either the success or the failure of the constraint. NOTE that
1175
1195
the caller must have a shared latch on dict_operation_lock. */
1176
 
 
 
1196
UNIV_INTERN
1177
1197
ulint
1178
1198
row_ins_check_foreign_constraint(
1179
1199
/*=============================*/
1195
1215
        dict_table_t*   check_table;
1196
1216
        dict_index_t*   check_index;
1197
1217
        ulint           n_fields_cmp;
1198
 
        rec_t*          rec;
1199
1218
        btr_pcur_t      pcur;
1200
1219
        ibool           moved;
1201
1220
        int             cmp;
1206
1225
        mem_heap_t*     heap            = NULL;
1207
1226
        ulint           offsets_[REC_OFFS_NORMAL_SIZE];
1208
1227
        ulint*          offsets         = offsets_;
1209
 
        *offsets_ = (sizeof offsets_) / sizeof *offsets_;
 
1228
        rec_offs_init(offsets_);
1210
1229
 
1211
1230
run_again:
1212
1231
#ifdef UNIV_SYNC_DEBUG
1329
1348
        /* Scan index records and check if there is a matching record */
1330
1349
 
1331
1350
        for (;;) {
1332
 
                rec = btr_pcur_get_rec(&pcur);
 
1351
                const rec_t*            rec = btr_pcur_get_rec(&pcur);
 
1352
                const buf_block_t*      block = btr_pcur_get_block(&pcur);
1333
1353
 
1334
1354
                if (page_rec_is_infimum(rec)) {
1335
1355
 
1341
1361
 
1342
1362
                if (page_rec_is_supremum(rec)) {
1343
1363
 
1344
 
                        err = row_ins_set_shared_rec_lock(
1345
 
                                LOCK_ORDINARY, rec, check_index, offsets, thr);
 
1364
                        err = row_ins_set_shared_rec_lock(LOCK_ORDINARY, block,
 
1365
                                                          rec, check_index,
 
1366
                                                          offsets, thr);
1346
1367
                        if (err != DB_SUCCESS) {
1347
1368
 
1348
1369
                                break;
1357
1378
                        if (rec_get_deleted_flag(rec,
1358
1379
                                                 rec_offs_comp(offsets))) {
1359
1380
                                err = row_ins_set_shared_rec_lock(
1360
 
                                        LOCK_ORDINARY, rec, check_index,
1361
 
                                        offsets, thr);
 
1381
                                        LOCK_ORDINARY, block,
 
1382
                                        rec, check_index, offsets, thr);
1362
1383
                                if (err != DB_SUCCESS) {
1363
1384
 
1364
1385
                                        break;
1369
1390
                                into gaps */
1370
1391
 
1371
1392
                                err = row_ins_set_shared_rec_lock(
1372
 
                                        LOCK_REC_NOT_GAP, rec, check_index,
1373
 
                                        offsets, thr);
 
1393
                                        LOCK_REC_NOT_GAP, block,
 
1394
                                        rec, check_index, offsets, thr);
1374
1395
 
1375
1396
                                if (err != DB_SUCCESS) {
1376
1397
 
1408
1429
 
1409
1430
                                                break;
1410
1431
                                        }
 
1432
 
 
1433
                                        /* row_ins_foreign_check_on_constraint
 
1434
                                        may have repositioned pcur on a
 
1435
                                        different block */
 
1436
                                        block = btr_pcur_get_block(&pcur);
1411
1437
                                } else {
1412
1438
                                        row_ins_foreign_report_err(
1413
1439
                                                "Trying to delete or update",
1421
1447
 
1422
1448
                if (cmp < 0) {
1423
1449
                        err = row_ins_set_shared_rec_lock(
1424
 
                                LOCK_GAP, rec, check_index, offsets, thr);
 
1450
                                LOCK_GAP, block,
 
1451
                                rec, check_index, offsets, thr);
1425
1452
                        if (err != DB_SUCCESS) {
1426
1453
 
1427
1454
                                break;
1577
1604
row_ins_dupl_error_with_rec(
1578
1605
/*========================*/
1579
1606
                                /* out: TRUE if error */
1580
 
        rec_t*          rec,    /* in: user record; NOTE that we assume
 
1607
        const rec_t*    rec,    /* in: user record; NOTE that we assume
1581
1608
                                that the caller already has a record lock on
1582
1609
                                the record! */
1583
 
        dtuple_t*       entry,  /* in: entry to insert */
 
1610
        const dtuple_t* entry,  /* in: entry to insert */
1584
1611
        dict_index_t*   index,  /* in: index */
1585
1612
        const ulint*    offsets)/* in: rec_get_offsets(rec, index) */
1586
1613
{
1607
1634
        /* In a unique secondary index we allow equal key values if they
1608
1635
        contain SQL NULLs */
1609
1636
 
1610
 
        if (!(index->type & DICT_CLUSTERED)) {
 
1637
        if (!dict_index_is_clust(index)) {
1611
1638
 
1612
1639
                for (i = 0; i < n_unique; i++) {
1613
1640
                        if (UNIV_SQL_NULL == dfield_get_len(
1641
1668
        ulint           i;
1642
1669
        int             cmp;
1643
1670
        ulint           n_fields_cmp;
1644
 
        rec_t*          rec;
1645
1671
        btr_pcur_t      pcur;
1646
1672
        ulint           err             = DB_SUCCESS;
1647
 
        ibool           moved;
1648
1673
        unsigned        allow_duplicates;
1649
1674
        mtr_t           mtr;
1650
1675
        mem_heap_t*     heap            = NULL;
1651
1676
        ulint           offsets_[REC_OFFS_NORMAL_SIZE];
1652
1677
        ulint*          offsets         = offsets_;
1653
 
        *offsets_ = (sizeof offsets_) / sizeof *offsets_;
 
1678
        rec_offs_init(offsets_);
1654
1679
 
1655
1680
        n_unique = dict_index_get_n_unique(index);
1656
1681
 
1680
1705
 
1681
1706
        /* Scan index records and check if there is a duplicate */
1682
1707
 
1683
 
        for (;;) {
1684
 
                rec = btr_pcur_get_rec(&pcur);
 
1708
        do {
 
1709
                const rec_t*            rec     = btr_pcur_get_rec(&pcur);
 
1710
                const buf_block_t*      block   = btr_pcur_get_block(&pcur);
1685
1711
 
1686
1712
                if (page_rec_is_infimum(rec)) {
1687
1713
 
1688
 
                        goto next_rec;
 
1714
                        continue;
1689
1715
                }
1690
1716
 
1691
1717
                offsets = rec_get_offsets(rec, index, offsets,
1699
1725
                        INSERT ON DUPLICATE KEY UPDATE). */
1700
1726
 
1701
1727
                        err = row_ins_set_exclusive_rec_lock(
1702
 
                                LOCK_ORDINARY, rec, index, offsets, thr);
 
1728
                                LOCK_ORDINARY, block,
 
1729
                                rec, index, offsets, thr);
1703
1730
                } else {
1704
1731
 
1705
1732
                        err = row_ins_set_shared_rec_lock(
1706
 
                                LOCK_ORDINARY, rec, index, offsets, thr);
 
1733
                                LOCK_ORDINARY, block,
 
1734
                                rec, index, offsets, thr);
1707
1735
                }
1708
1736
 
1709
1737
                if (err != DB_SUCCESS) {
1713
1741
 
1714
1742
                if (page_rec_is_supremum(rec)) {
1715
1743
 
1716
 
                        goto next_rec;
 
1744
                        continue;
1717
1745
                }
1718
1746
 
1719
1747
                cmp = cmp_dtuple_rec(entry, rec, offsets);
1734
1762
                }
1735
1763
 
1736
1764
                ut_a(cmp == 0);
1737
 
next_rec:
1738
 
                moved = btr_pcur_move_to_next(&pcur, &mtr);
1739
 
 
1740
 
                if (!moved) {
1741
 
                        break;
1742
 
                }
1743
 
        }
 
1765
        } while (btr_pcur_move_to_next(&pcur, &mtr));
1744
1766
 
1745
1767
        if (UNIV_LIKELY_NULL(heap)) {
1746
1768
                mem_heap_free(heap);
1785
1807
        mem_heap_t*heap         = NULL;
1786
1808
        ulint   offsets_[REC_OFFS_NORMAL_SIZE];
1787
1809
        ulint*  offsets         = offsets_;
1788
 
        *offsets_ = (sizeof offsets_) / sizeof *offsets_;
 
1810
        rec_offs_init(offsets_);
1789
1811
 
1790
1812
        UT_NOT_USED(mtr);
1791
1813
 
1792
 
        ut_a(cursor->index->type & DICT_CLUSTERED);
1793
 
        ut_ad(cursor->index->type & DICT_UNIQUE);
 
1814
        ut_a(dict_index_is_clust(cursor->index));
 
1815
        ut_ad(dict_index_is_unique(cursor->index));
1794
1816
 
1795
1817
        /* NOTE: For unique non-clustered indexes there may be any number
1796
1818
        of delete marked records with the same value for the non-clustered
1828
1850
                                INSERT ON DUPLICATE KEY UPDATE). */
1829
1851
 
1830
1852
                                err = row_ins_set_exclusive_rec_lock(
1831
 
                                        LOCK_REC_NOT_GAP, rec,
1832
 
                                        cursor->index, offsets, thr);
 
1853
                                        LOCK_REC_NOT_GAP,
 
1854
                                        btr_cur_get_block(cursor),
 
1855
                                        rec, cursor->index, offsets, thr);
1833
1856
                        } else {
1834
1857
 
1835
1858
                                err = row_ins_set_shared_rec_lock(
1836
 
                                        LOCK_REC_NOT_GAP, rec,
 
1859
                                        LOCK_REC_NOT_GAP,
 
1860
                                        btr_cur_get_block(cursor), rec,
1837
1861
                                        cursor->index, offsets, thr);
1838
1862
                        }
1839
1863
 
1866
1890
                                INSERT ON DUPLICATE KEY UPDATE). */
1867
1891
 
1868
1892
                                err = row_ins_set_exclusive_rec_lock(
1869
 
                                        LOCK_REC_NOT_GAP, rec,
1870
 
                                        cursor->index, offsets, thr);
 
1893
                                        LOCK_REC_NOT_GAP,
 
1894
                                        btr_cur_get_block(cursor),
 
1895
                                        rec, cursor->index, offsets, thr);
1871
1896
                        } else {
1872
1897
 
1873
1898
                                err = row_ins_set_shared_rec_lock(
1874
 
                                        LOCK_REC_NOT_GAP, rec,
1875
 
                                        cursor->index, offsets, thr);
 
1899
                                        LOCK_REC_NOT_GAP,
 
1900
                                        btr_cur_get_block(cursor),
 
1901
                                        rec, cursor->index, offsets, thr);
1876
1902
                        }
1877
1903
 
1878
1904
                        if (err != DB_SUCCESS) {
1887
1913
                        }
1888
1914
                }
1889
1915
 
1890
 
                ut_a(!(cursor->index->type & DICT_CLUSTERED));
 
1916
                ut_a(!dict_index_is_clust(cursor->index));
1891
1917
                /* This should never happen */
1892
1918
        }
1893
1919
 
1957
1983
marked record. If the index is secondary, and a record with exactly the
1958
1984
same fields is found, the other record is necessarily marked deleted.
1959
1985
It is then unmarked. Otherwise, the entry is just inserted to the index. */
1960
 
 
 
1986
static
1961
1987
ulint
1962
1988
row_ins_index_entry_low(
1963
1989
/*====================*/
1968
1994
                                pessimistic descent down the index tree */
1969
1995
        dict_index_t*   index,  /* in: index */
1970
1996
        dtuple_t*       entry,  /* in: index entry to insert */
1971
 
        ulint*          ext_vec,/* in: array containing field numbers of
1972
 
                                externally stored fields in entry, or NULL */
1973
 
        ulint           n_ext_vec,/* in: number of fields in ext_vec */
 
1997
        ulint           n_ext,  /* in: number of externally stored columns */
1974
1998
        que_thr_t*      thr)    /* in: query thread */
1975
1999
{
1976
2000
        btr_cur_t       cursor;
1983
2007
        big_rec_t*      big_rec                 = NULL;
1984
2008
        mtr_t           mtr;
1985
2009
        mem_heap_t*     heap                    = NULL;
1986
 
        ulint           offsets_[REC_OFFS_NORMAL_SIZE];
1987
 
        ulint*          offsets                 = offsets_;
1988
 
        *offsets_ = (sizeof offsets_) / sizeof *offsets_;
1989
2010
 
1990
2011
        log_free_check();
1991
2012
 
2020
2041
                rec_t*  first_rec = page_rec_get_next(
2021
2042
                        page_get_infimum_rec(page));
2022
2043
 
2023
 
                if (UNIV_LIKELY(first_rec != page_get_supremum_rec(page))) {
2024
 
                        ut_a(rec_get_n_fields(first_rec, index)
2025
 
                             == dtuple_get_n_fields(entry));
2026
 
                }
 
2044
                ut_ad(page_rec_is_supremum(first_rec)
 
2045
                      || rec_get_n_fields(first_rec, index)
 
2046
                      == dtuple_get_n_fields(entry));
2027
2047
        }
2028
2048
#endif
2029
2049
 
2030
2050
        n_unique = dict_index_get_n_unique(index);
2031
2051
 
2032
 
        if (index->type & DICT_UNIQUE && (cursor.up_match >= n_unique
2033
 
                                          || cursor.low_match >= n_unique)) {
 
2052
        if (dict_index_is_unique(index) && (cursor.up_match >= n_unique
 
2053
                                            || cursor.low_match >= n_unique)) {
2034
2054
 
2035
 
                if (index->type & DICT_CLUSTERED) {
 
2055
                if (dict_index_is_clust(index)) {
2036
2056
                        /* Note that the following may return also
2037
2057
                        DB_LOCK_WAIT */
2038
2058
 
2076
2096
                if (modify == ROW_INS_NEXT) {
2077
2097
                        rec = page_rec_get_next(btr_cur_get_rec(&cursor));
2078
2098
 
2079
 
                        btr_cur_position(index, rec, &cursor);
 
2099
                        btr_cur_position(index, rec,
 
2100
                                         btr_cur_get_block(&cursor),&cursor);
2080
2101
                }
2081
2102
 
2082
 
                if (index->type & DICT_CLUSTERED) {
 
2103
                if (dict_index_is_clust(index)) {
2083
2104
                        err = row_ins_clust_index_entry_by_modify(
2084
 
                                mode, &cursor, &big_rec, entry,
2085
 
                                ext_vec, n_ext_vec, thr, &mtr);
 
2105
                                mode, &cursor, &heap, &big_rec, entry,
 
2106
                                thr, &mtr);
2086
2107
                } else {
 
2108
                        ut_ad(!n_ext);
2087
2109
                        err = row_ins_sec_index_entry_by_modify(
2088
2110
                                mode, &cursor, entry, thr, &mtr);
2089
2111
                }
2090
 
 
2091
2112
        } else {
2092
2113
                if (mode == BTR_MODIFY_LEAF) {
2093
2114
                        err = btr_cur_optimistic_insert(
2094
2115
                                0, &cursor, entry, &insert_rec, &big_rec,
2095
 
                                thr, &mtr);
 
2116
                                n_ext, thr, &mtr);
2096
2117
                } else {
2097
2118
                        ut_a(mode == BTR_MODIFY_TREE);
2098
2119
                        if (buf_LRU_buf_pool_running_out()) {
2103
2124
                        }
2104
2125
                        err = btr_cur_pessimistic_insert(
2105
2126
                                0, &cursor, entry, &insert_rec, &big_rec,
2106
 
                                thr, &mtr);
2107
 
                }
2108
 
 
2109
 
                if (err == DB_SUCCESS) {
2110
 
                        if (ext_vec) {
2111
 
                                rec_set_field_extern_bits(insert_rec, index,
2112
 
                                                          ext_vec, n_ext_vec,
2113
 
                                                          &mtr);
2114
 
                        }
 
2127
                                n_ext, thr, &mtr);
2115
2128
                }
2116
2129
        }
2117
2130
 
2118
2131
function_exit:
2119
2132
        mtr_commit(&mtr);
2120
2133
 
2121
 
        if (big_rec) {
2122
 
                rec_t*          rec;
 
2134
        if (UNIV_LIKELY_NULL(big_rec)) {
 
2135
                rec_t*  rec;
 
2136
                ulint*  offsets;
2123
2137
                mtr_start(&mtr);
2124
2138
 
2125
2139
                btr_cur_search_to_nth_level(index, 0, entry, PAGE_CUR_LE,
2126
2140
                                            BTR_MODIFY_TREE, &cursor, 0, &mtr);
2127
2141
                rec = btr_cur_get_rec(&cursor);
2128
 
                offsets = rec_get_offsets(rec, index, offsets,
 
2142
                offsets = rec_get_offsets(rec, index, NULL,
2129
2143
                                          ULINT_UNDEFINED, &heap);
2130
2144
 
2131
 
                err = btr_store_big_rec_extern_fields(index, rec,
2132
 
                                                      offsets, big_rec, &mtr);
 
2145
                err = btr_store_big_rec_extern_fields(
 
2146
                        index, btr_cur_get_block(&cursor),
 
2147
                        rec, offsets, big_rec, &mtr);
2133
2148
 
2134
2149
                if (modify) {
2135
2150
                        dtuple_big_rec_free(big_rec);
2151
2166
descent down the tree. If the entry matches enough to a delete marked record,
2152
2167
performs the insert by updating or delete unmarking the delete marked
2153
2168
record. */
2154
 
 
 
2169
UNIV_INTERN
2155
2170
ulint
2156
2171
row_ins_index_entry(
2157
2172
/*================*/
2159
2174
                                DB_DUPLICATE_KEY, or some other error code */
2160
2175
        dict_index_t*   index,  /* in: index */
2161
2176
        dtuple_t*       entry,  /* in: index entry to insert */
2162
 
        ulint*          ext_vec,/* in: array containing field numbers of
2163
 
                                externally stored fields in entry, or NULL */
2164
 
        ulint           n_ext_vec,/* in: number of fields in ext_vec */
 
2177
        ulint           n_ext,  /* in: number of externally stored columns */
 
2178
        ibool           foreign,/* in: TRUE=check foreign key constraints */
2165
2179
        que_thr_t*      thr)    /* in: query thread */
2166
2180
{
2167
2181
        ulint   err;
2168
2182
 
2169
 
        if (UT_LIST_GET_FIRST(index->table->foreign_list)) {
 
2183
        if (foreign && UT_LIST_GET_FIRST(index->table->foreign_list)) {
2170
2184
                err = row_ins_check_foreign_constraints(index->table, index,
2171
2185
                                                        entry, thr);
2172
2186
                if (err != DB_SUCCESS) {
2178
2192
        /* Try first optimistic descent to the B-tree */
2179
2193
 
2180
2194
        err = row_ins_index_entry_low(BTR_MODIFY_LEAF, index, entry,
2181
 
                                      ext_vec, n_ext_vec, thr);
 
2195
                                      n_ext, thr);
2182
2196
        if (err != DB_FAIL) {
2183
2197
 
2184
2198
                return(err);
2187
2201
        /* Try then pessimistic descent to the B-tree */
2188
2202
 
2189
2203
        err = row_ins_index_entry_low(BTR_MODIFY_TREE, index, entry,
2190
 
                                      ext_vec, n_ext_vec, thr);
 
2204
                                      n_ext, thr);
2191
2205
        return(err);
2192
2206
}
2193
2207
 
2200
2214
/*=========================*/
2201
2215
        dict_index_t*   index,  /* in: index */
2202
2216
        dtuple_t*       entry,  /* in: index entry to make */
2203
 
        dtuple_t*       row)    /* in: row */
 
2217
        const dtuple_t* row)    /* in: row */
2204
2218
{
2205
 
        dict_field_t*   ind_field;
2206
 
        dfield_t*       field;
2207
 
        dfield_t*       row_field;
2208
 
        ulint           n_fields;
2209
 
        ulint           i;
 
2219
        ulint   n_fields;
 
2220
        ulint   i;
2210
2221
 
2211
2222
        ut_ad(entry && row);
2212
2223
 
2213
2224
        n_fields = dtuple_get_n_fields(entry);
2214
2225
 
2215
2226
        for (i = 0; i < n_fields; i++) {
 
2227
                dict_field_t*   ind_field;
 
2228
                dfield_t*       field;
 
2229
                const dfield_t* row_field;
 
2230
                ulint           len;
 
2231
 
2216
2232
                field = dtuple_get_nth_field(entry, i);
2217
2233
                ind_field = dict_index_get_nth_field(index, i);
2218
 
 
2219
2234
                row_field = dtuple_get_nth_field(row, ind_field->col->ind);
 
2235
                len = dfield_get_len(row_field);
2220
2236
 
2221
2237
                /* Check column prefix indexes */
2222
2238
                if (ind_field->prefix_len > 0
2225
2241
                        const   dict_col_t*     col
2226
2242
                                = dict_field_get_col(ind_field);
2227
2243
 
2228
 
                        field->len = dtype_get_at_most_n_mbchars(
 
2244
                        len = dtype_get_at_most_n_mbchars(
2229
2245
                                col->prtype, col->mbminlen, col->mbmaxlen,
2230
2246
                                ind_field->prefix_len,
2231
 
                                row_field->len, row_field->data);
2232
 
                } else {
2233
 
                        field->len = row_field->len;
2234
 
                }
2235
 
 
2236
 
                field->data = row_field->data;
 
2247
                                len, dfield_get_data(row_field));
 
2248
 
 
2249
                        ut_ad(!dfield_is_ext(row_field));
 
2250
                }
 
2251
 
 
2252
                dfield_set_data(field, dfield_get_data(row_field), len);
 
2253
                if (dfield_is_ext(row_field)) {
 
2254
                        ut_ad(dict_index_is_clust(index));
 
2255
                        dfield_set_ext(field);
 
2256
                }
2237
2257
        }
2238
2258
}
2239
2259
 
2256
2276
 
2257
2277
        ut_ad(dtuple_check_typed(node->entry));
2258
2278
 
2259
 
        err = row_ins_index_entry(node->index, node->entry, NULL, 0, thr);
 
2279
        err = row_ins_index_entry(node->index, node->entry, 0, TRUE, thr);
2260
2280
 
2261
2281
        return(err);
2262
2282
}
2273
2293
 
2274
2294
        ut_ad(node->state == INS_NODE_ALLOC_ROW_ID);
2275
2295
 
2276
 
        if (dict_table_get_first_index(node->table)->type & DICT_UNIQUE) {
 
2296
        if (dict_index_is_unique(dict_table_get_first_index(node->table))) {
2277
2297
 
2278
2298
                /* No row id is stored if the clustered index is unique */
2279
2299
 
2353
2373
 
2354
2374
/***************************************************************
2355
2375
Inserts a row to a table. */
2356
 
 
 
2376
static
2357
2377
ulint
2358
2378
row_ins(
2359
2379
/*====*/
2409
2429
/***************************************************************
2410
2430
Inserts a row to a table. This is a high-level function used in SQL execution
2411
2431
graphs. */
2412
 
 
 
2432
UNIV_INTERN
2413
2433
que_thr_t*
2414
2434
row_ins_step(
2415
2435
/*=========*/