~drizzle-trunk/drizzle/development

« back to all changes in this revision

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

  • Committer: Brian Aker
  • Date: 2008-09-04 19:31:00 UTC
  • Revision ID: brian@tangent.org-20080904193100-l849hgghfy4urj43
Changing default character set from this point on.

Show diffs side-by-side

added added

removed removed

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