~drizzle-trunk/drizzle/development

« back to all changes in this revision

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

  • Committer: Monty Taylor
  • Date: 2008-09-14 22:10:23 UTC
  • mto: This revision was merged to the branch mainline in revision 388.
  • Revision ID: monty@inaugust.com-20080914221023-otz8vuui590zp5yf
Got rid of libsqlcommon and some surious defines.

Show diffs side-by-side

added added

removed removed

Lines of Context:
20
20
#include "btr0btr.h"
21
21
#include "btr0cur.h"
22
22
#include "que0que.h"
23
 
#include "row0ext.h"
24
23
#include "row0ins.h"
25
24
#include "row0sel.h"
26
25
#include "row0row.h"
84
83
                                /* out: TRUE if changes */
85
84
        dtuple_t*       entry,  /* in: old value of index entry */
86
85
        dict_index_t*   index,  /* in: index of entry */
87
 
        const upd_t*    update, /* in: update vector for the row */
 
86
        upd_t*          update, /* in: update vector for the row */
88
87
        ulint           n);     /* in: how many first fields to check */
89
88
 
90
89
 
107
106
        dict_table_t*   table           = index->table;
108
107
        dict_foreign_t* foreign;
109
108
        ibool           froze_data_dict = FALSE;
110
 
        ibool           is_referenced   = FALSE;
111
109
 
112
110
        if (!UT_LIST_GET_FIRST(table->referenced_list)) {
113
111
 
124
122
        while (foreign) {
125
123
                if (foreign->referenced_index == index) {
126
124
 
127
 
                        is_referenced = TRUE;
128
 
                        goto func_exit;
 
125
                        if (froze_data_dict) {
 
126
                                row_mysql_unfreeze_data_dictionary(trx);
 
127
                        }
 
128
 
 
129
                        return(TRUE);
129
130
                }
130
131
 
131
132
                foreign = UT_LIST_GET_NEXT(referenced_list, foreign);
132
133
        }
133
134
 
134
 
func_exit:
135
135
        if (froze_data_dict) {
136
136
                row_mysql_unfreeze_data_dictionary(trx);
137
137
        }
138
138
 
139
 
        return(is_referenced);
 
139
        return(FALSE);
140
140
}
141
141
 
142
142
/*************************************************************************
153
153
                                cursor position is lost in this function! */
154
154
        dict_table_t*   table,  /* in: table in question */
155
155
        dict_index_t*   index,  /* in: index of the cursor */
156
 
        ulint*          offsets,/* in/out: rec_get_offsets(pcur.rec, index) */
157
156
        que_thr_t*      thr,    /* in: query thread */
158
157
        mtr_t*          mtr)    /* in: mtr */
159
158
{
161
160
        mem_heap_t*     heap;
162
161
        dtuple_t*       entry;
163
162
        trx_t*          trx;
164
 
        const rec_t*    rec;
165
 
        ulint           n_ext;
 
163
        rec_t*          rec;
166
164
        ulint           err;
167
165
        ibool           got_s_lock      = FALSE;
168
166
 
174
172
        trx = thr_get_trx(thr);
175
173
 
176
174
        rec = btr_pcur_get_rec(pcur);
177
 
        ut_ad(rec_offs_validate(rec, index, offsets));
178
175
 
179
176
        heap = mem_heap_create(500);
180
177
 
181
 
        entry = row_rec_to_index_entry(ROW_COPY_DATA, rec, index, offsets,
182
 
                                       &n_ext, heap);
 
178
        entry = row_rec_to_index_entry(ROW_COPY_DATA, index, rec, heap);
183
179
 
184
180
        mtr_commit(mtr);
185
181
 
240
236
                        }
241
237
 
242
238
                        if (err != DB_SUCCESS) {
243
 
 
244
 
                                goto func_exit;
 
239
                                if (got_s_lock) {
 
240
                                        row_mysql_unfreeze_data_dictionary(
 
241
                                                trx);
 
242
                                }
 
243
 
 
244
                                mem_heap_free(heap);
 
245
 
 
246
                                return(err);
245
247
                        }
246
248
                }
247
249
 
248
250
                foreign = UT_LIST_GET_NEXT(referenced_list, foreign);
249
251
        }
250
252
 
251
 
        err = DB_SUCCESS;
252
 
 
253
 
func_exit:
254
253
        if (got_s_lock) {
255
254
                row_mysql_unfreeze_data_dictionary(trx);
256
255
        }
257
256
 
258
257
        mem_heap_free(heap);
259
258
 
260
 
        return(err);
 
259
        return(DB_SUCCESS);
261
260
}
262
261
 
263
262
/*************************************************************************
264
263
Creates an update node for a query graph. */
265
 
UNIV_INTERN
 
264
 
266
265
upd_node_t*
267
266
upd_node_create(
268
267
/*============*/
279
278
        node->in_mysql_interface = FALSE;
280
279
 
281
280
        node->row = NULL;
282
 
        node->ext = NULL;
283
 
        node->upd_row = NULL;
284
 
        node->upd_ext = NULL;
 
281
        node->ext_vec = NULL;
285
282
        node->index = NULL;
286
283
        node->update = NULL;
287
284
 
302
299
/*************************************************************************
303
300
Updates the trx id and roll ptr field in a clustered index record in database
304
301
recovery. */
305
 
UNIV_INTERN
 
302
 
306
303
void
307
304
row_upd_rec_sys_fields_in_recovery(
308
305
/*===============================*/
309
 
        rec_t*          rec,    /* in/out: record */
310
 
        page_zip_des_t* page_zip,/* in/out: compressed page, or NULL */
 
306
        rec_t*          rec,    /* in: record */
311
307
        const ulint*    offsets,/* in: array returned by rec_get_offsets() */
312
308
        ulint           pos,    /* in: TRX_ID position in rec */
313
309
        dulint          trx_id, /* in: transaction id */
314
310
        dulint          roll_ptr)/* in: roll ptr of the undo log record */
315
311
{
316
 
        ut_ad(rec_offs_validate(rec, NULL, offsets));
317
 
 
318
 
        if (UNIV_LIKELY_NULL(page_zip)) {
319
 
                page_zip_write_trx_id_and_roll_ptr(
320
 
                        page_zip, rec, offsets, pos, trx_id, roll_ptr);
321
 
        } else {
322
 
                byte*   field;
323
 
                ulint   len;
324
 
 
325
 
                field = rec_get_nth_field(rec, offsets, pos, &len);
326
 
                ut_ad(len == DATA_TRX_ID_LEN);
327
 
#if DATA_TRX_ID + 1 != DATA_ROLL_PTR
328
 
# error "DATA_TRX_ID + 1 != DATA_ROLL_PTR"
329
 
#endif
330
 
                trx_write_trx_id(field, trx_id);
331
 
                trx_write_roll_ptr(field + DATA_TRX_ID_LEN, roll_ptr);
332
 
        }
 
312
        byte*   field;
 
313
        ulint   len;
 
314
 
 
315
        field = rec_get_nth_field(rec, offsets, pos, &len);
 
316
        ut_ad(len == DATA_TRX_ID_LEN);
 
317
        trx_write_trx_id(field, trx_id);
 
318
 
 
319
        field = rec_get_nth_field(rec, offsets, pos + 1, &len);
 
320
        ut_ad(len == DATA_ROLL_PTR_LEN);
 
321
        trx_write_roll_ptr(field, roll_ptr);
333
322
}
334
323
 
335
324
/*************************************************************************
336
325
Sets the trx id or roll ptr field of a clustered index entry. */
337
 
UNIV_INTERN
 
326
 
338
327
void
339
328
row_upd_index_entry_sys_field(
340
329
/*==========================*/
341
 
        const dtuple_t* entry,  /* in: index entry, where the memory buffers
 
330
        dtuple_t*       entry,  /* in: index entry, where the memory buffers
342
331
                                for sys fields are already allocated:
343
332
                                the function just copies the new values to
344
333
                                them */
350
339
        byte*           field;
351
340
        ulint           pos;
352
341
 
353
 
        ut_ad(dict_index_is_clust(index));
 
342
        ut_ad(index->type & DICT_CLUSTERED);
354
343
 
355
344
        pos = dict_index_get_sys_col_pos(index, type);
356
345
 
368
357
/***************************************************************
369
358
Returns TRUE if row update changes size of some field in index or if some
370
359
field to be updated is stored externally in rec or update. */
371
 
UNIV_INTERN
 
360
 
372
361
ibool
373
362
row_upd_changes_field_size_or_external(
374
363
/*===================================*/
377
366
                                in rec or update */
378
367
        dict_index_t*   index,  /* in: index */
379
368
        const ulint*    offsets,/* in: rec_get_offsets(rec, index) */
380
 
        const upd_t*    update) /* in: update vector */
 
369
        upd_t*          update) /* in: update vector */
381
370
{
382
 
        const upd_field_t*      upd_field;
383
 
        const dfield_t*         new_val;
384
 
        ulint                   old_len;
385
 
        ulint                   new_len;
386
 
        ulint                   n_fields;
387
 
        ulint                   i;
 
371
        upd_field_t*    upd_field;
 
372
        dfield_t*       new_val;
 
373
        ulint           old_len;
 
374
        ulint           new_len;
 
375
        ulint           n_fields;
 
376
        ulint           i;
388
377
 
389
378
        ut_ad(rec_offs_validate(NULL, index, offsets));
390
379
        n_fields = upd_get_n_fields(update);
393
382
                upd_field = upd_get_nth_field(update, i);
394
383
 
395
384
                new_val = &(upd_field->new_val);
396
 
                new_len = dfield_get_len(new_val);
 
385
                new_len = new_val->len;
397
386
 
398
 
                if (dfield_is_null(new_val) && !rec_offs_comp(offsets)) {
 
387
                if (new_len == UNIV_SQL_NULL && !rec_offs_comp(offsets)) {
399
388
                        /* A bug fixed on Dec 31st, 2004: we looked at the
400
389
                        SQL NULL size from the wrong field! We may backport
401
390
                        this fix also to 4.0. The merge to 5.0 will be made
421
410
                        old_len = UNIV_SQL_NULL;
422
411
                }
423
412
 
424
 
                if (dfield_is_ext(new_val) || old_len != new_len
425
 
                    || rec_offs_nth_extern(offsets, upd_field->field_no)) {
 
413
                if (old_len != new_len) {
 
414
 
 
415
                        return(TRUE);
 
416
                }
 
417
 
 
418
                if (rec_offs_nth_extern(offsets, upd_field->field_no)) {
 
419
 
 
420
                        return(TRUE);
 
421
                }
 
422
 
 
423
                if (upd_field->extern_storage) {
426
424
 
427
425
                        return(TRUE);
428
426
                }
433
431
 
434
432
/***************************************************************
435
433
Replaces the new column values stored in the update vector to the record
436
 
given. No field size changes are allowed. */
437
 
UNIV_INTERN
 
434
given. No field size changes are allowed. This function is used only for
 
435
a clustered index */
 
436
 
438
437
void
439
438
row_upd_rec_in_place(
440
439
/*=================*/
441
440
        rec_t*          rec,    /* in/out: record where replaced */
442
 
        dict_index_t*   index,  /* in: the index the record belongs to */
443
441
        const ulint*    offsets,/* in: array returned by rec_get_offsets() */
444
 
        const upd_t*    update, /* in: update vector */
445
 
        page_zip_des_t* page_zip)/* in: compressed page with enough space
446
 
                                available, or NULL */
 
442
        upd_t*          update) /* in: update vector */
447
443
{
448
 
        const upd_field_t*      upd_field;
449
 
        const dfield_t*         new_val;
450
 
        ulint                   n_fields;
451
 
        ulint                   i;
452
 
 
453
 
        ut_ad(rec_offs_validate(rec, index, offsets));
454
 
 
455
 
        if (rec_offs_comp(offsets)) {
456
 
                rec_set_info_bits_new(rec, update->info_bits);
457
 
        } else {
458
 
                rec_set_info_bits_old(rec, update->info_bits);
459
 
        }
 
444
        upd_field_t*    upd_field;
 
445
        dfield_t*       new_val;
 
446
        ulint           n_fields;
 
447
        ulint           i;
 
448
 
 
449
        ut_ad(rec_offs_validate(rec, NULL, offsets));
 
450
 
 
451
        rec_set_info_bits(rec, rec_offs_comp(offsets), update->info_bits);
460
452
 
461
453
        n_fields = upd_get_n_fields(update);
462
454
 
463
455
        for (i = 0; i < n_fields; i++) {
464
456
                upd_field = upd_get_nth_field(update, i);
465
457
                new_val = &(upd_field->new_val);
466
 
                ut_ad(!dfield_is_ext(new_val) ==
467
 
                      !rec_offs_nth_extern(offsets, upd_field->field_no));
468
458
 
469
459
                rec_set_nth_field(rec, offsets, upd_field->field_no,
470
460
                                  dfield_get_data(new_val),
471
461
                                  dfield_get_len(new_val));
472
462
        }
473
 
 
474
 
        if (UNIV_LIKELY_NULL(page_zip)) {
475
 
                page_zip_write_rec(page_zip, rec, index, offsets, 0);
476
 
        }
477
463
}
478
464
 
479
465
/*************************************************************************
480
466
Writes into the redo log the values of trx id and roll ptr and enough info
481
467
to determine their positions within a clustered index record. */
482
 
UNIV_INTERN
 
468
 
483
469
byte*
484
470
row_upd_write_sys_vals_to_log(
485
471
/*==========================*/
491
477
                                in mlog */
492
478
        mtr_t*          mtr __attribute__((unused))) /* in: mtr */
493
479
{
494
 
        ut_ad(dict_index_is_clust(index));
 
480
        ut_ad(index->type & DICT_CLUSTERED);
495
481
        ut_ad(mtr);
496
482
 
497
483
        log_ptr += mach_write_compressed(log_ptr,
508
494
 
509
495
/*************************************************************************
510
496
Parses the log data of system field values. */
511
 
UNIV_INTERN
 
497
 
512
498
byte*
513
499
row_upd_parse_sys_vals(
514
500
/*===================*/
541
527
 
542
528
/***************************************************************
543
529
Writes to the redo log the new values of the fields occurring in the index. */
544
 
UNIV_INTERN
 
530
 
545
531
void
546
532
row_upd_index_write_log(
547
533
/*====================*/
548
 
        const upd_t*    update, /* in: update vector */
549
 
        byte*           log_ptr,/* in: pointer to mlog buffer: must
550
 
                                contain at least MLOG_BUF_MARGIN bytes
551
 
                                of free space; the buffer is closed
552
 
                                within this function */
553
 
        mtr_t*          mtr)    /* in: mtr into whose log to write */
 
534
        upd_t*  update, /* in: update vector */
 
535
        byte*   log_ptr,/* in: pointer to mlog buffer: must contain at least
 
536
                        MLOG_BUF_MARGIN bytes of free space; the buffer is
 
537
                        closed within this function */
 
538
        mtr_t*  mtr)    /* in: mtr into whose log to write */
554
539
{
555
 
        const upd_field_t*      upd_field;
556
 
        const dfield_t*         new_val;
557
 
        ulint                   len;
558
 
        ulint                   n_fields;
559
 
        byte*                   buf_end;
560
 
        ulint                   i;
 
540
        upd_field_t*    upd_field;
 
541
        dfield_t*       new_val;
 
542
        ulint           len;
 
543
        ulint           n_fields;
 
544
        byte*           buf_end;
 
545
        ulint           i;
561
546
 
562
547
        n_fields = upd_get_n_fields(update);
563
548
 
584
569
 
585
570
                new_val = &(upd_field->new_val);
586
571
 
587
 
                len = dfield_get_len(new_val);
 
572
                len = new_val->len;
588
573
 
589
574
                log_ptr += mach_write_compressed(log_ptr, upd_field->field_no);
590
575
                log_ptr += mach_write_compressed(log_ptr, len);
591
576
 
592
577
                if (len != UNIV_SQL_NULL) {
593
578
                        if (log_ptr + len < buf_end) {
594
 
                                memcpy(log_ptr, dfield_get_data(new_val), len);
 
579
                                ut_memcpy(log_ptr, new_val->data, len);
595
580
 
596
581
                                log_ptr += len;
597
582
                        } else {
598
583
                                mlog_close(mtr, log_ptr);
599
584
 
600
 
                                mlog_catenate_string(mtr,
601
 
                                                     dfield_get_data(new_val),
602
 
                                                     len);
 
585
                                mlog_catenate_string(mtr, new_val->data, len);
603
586
 
604
587
                                log_ptr = mlog_open(mtr, MLOG_BUF_MARGIN);
605
588
                                buf_end = log_ptr + MLOG_BUF_MARGIN;
612
595
 
613
596
/*************************************************************************
614
597
Parses the log data written by row_upd_index_write_log. */
615
 
UNIV_INTERN
 
598
 
616
599
byte*
617
600
row_upd_index_parse(
618
601
/*================*/
628
611
        dfield_t*       new_val;
629
612
        ulint           len;
630
613
        ulint           n_fields;
 
614
        byte*           buf;
631
615
        ulint           info_bits;
632
616
        ulint           i;
633
617
 
649
633
        update->info_bits = info_bits;
650
634
 
651
635
        for (i = 0; i < n_fields; i++) {
652
 
                ulint   field_no;
653
636
                upd_field = upd_get_nth_field(update, i);
654
637
                new_val = &(upd_field->new_val);
655
638
 
656
 
                ptr = mach_parse_compressed(ptr, end_ptr, &field_no);
657
 
 
 
639
                ptr = mach_parse_compressed(ptr, end_ptr,
 
640
                                            &(upd_field->field_no));
658
641
                if (ptr == NULL) {
659
642
 
660
643
                        return(NULL);
661
644
                }
662
645
 
663
 
                upd_field->field_no = field_no;
664
 
 
665
646
                ptr = mach_parse_compressed(ptr, end_ptr, &len);
666
647
 
667
648
                if (ptr == NULL) {
669
650
                        return(NULL);
670
651
                }
671
652
 
 
653
                new_val->len = len;
 
654
 
672
655
                if (len != UNIV_SQL_NULL) {
673
656
 
674
657
                        if (end_ptr < ptr + len) {
675
658
 
676
659
                                return(NULL);
 
660
                        } else {
 
661
                                buf = mem_heap_alloc(heap, len);
 
662
                                ut_memcpy(buf, ptr, len);
 
663
 
 
664
                                ptr += len;
 
665
 
 
666
                                new_val->data = buf;
677
667
                        }
678
 
 
679
 
                        dfield_set_data(new_val,
680
 
                                        mem_heap_dup(heap, ptr, len), len);
681
 
                        ptr += len;
682
 
                } else {
683
 
                        dfield_set_null(new_val);
684
668
                }
685
669
        }
686
670
 
690
674
}
691
675
 
692
676
/*******************************************************************
 
677
Returns TRUE if ext_vec contains i. */
 
678
static
 
679
ibool
 
680
upd_ext_vec_contains(
 
681
/*=================*/
 
682
                                /* out: TRUE if i is in ext_vec */
 
683
        ulint*  ext_vec,        /* in: array of indexes or NULL */
 
684
        ulint   n_ext_vec,      /* in: number of numbers in ext_vec */
 
685
        ulint   i)              /* in: a number */
 
686
{
 
687
        ulint   j;
 
688
 
 
689
        if (ext_vec == NULL) {
 
690
 
 
691
                return(FALSE);
 
692
        }
 
693
 
 
694
        for (j = 0; j < n_ext_vec; j++) {
 
695
                if (ext_vec[j] == i) {
 
696
 
 
697
                        return(TRUE);
 
698
                }
 
699
        }
 
700
 
 
701
        return(FALSE);
 
702
}
 
703
 
 
704
/*******************************************************************
693
705
Builds an update vector from those fields which in a secondary index entry
694
706
differ from a record that has the equal ordering fields. NOTE: we compare
695
707
the fields as binary strings! */
696
 
UNIV_INTERN
 
708
 
697
709
upd_t*
698
710
row_upd_build_sec_rec_difference_binary(
699
711
/*====================================*/
700
712
                                /* out, own: update vector of differing
701
713
                                fields */
702
714
        dict_index_t*   index,  /* in: index */
703
 
        const dtuple_t* entry,  /* in: entry to insert */
704
 
        const rec_t*    rec,    /* in: secondary index record */
 
715
        dtuple_t*       entry,  /* in: entry to insert */
 
716
        rec_t*          rec,    /* in: secondary index record */
705
717
        trx_t*          trx,    /* in: transaction */
706
718
        mem_heap_t*     heap)   /* in: memory heap from which allocated */
707
719
{
708
720
        upd_field_t*    upd_field;
709
 
        const dfield_t* dfield;
710
 
        const byte*     data;
 
721
        dfield_t*       dfield;
 
722
        byte*           data;
711
723
        ulint           len;
712
724
        upd_t*          update;
713
725
        ulint           n_diff;
714
726
        ulint           i;
715
727
        ulint           offsets_[REC_OFFS_SMALL_SIZE];
716
728
        const ulint*    offsets;
717
 
        rec_offs_init(offsets_);
 
729
        *offsets_ = (sizeof offsets_) / sizeof *offsets_;
718
730
 
719
731
        /* This function is used only for a secondary index */
720
 
        ut_a(!dict_index_is_clust(index));
 
732
        ut_a(0 == (index->type & DICT_CLUSTERED));
721
733
 
722
734
        update = upd_create(dtuple_get_n_fields(entry), heap);
723
735
 
750
762
 
751
763
                        upd_field_set_field_no(upd_field, i, index, trx);
752
764
 
 
765
                        upd_field->extern_storage = FALSE;
 
766
 
753
767
                        n_diff++;
754
768
                }
755
769
        }
763
777
Builds an update vector from those fields, excluding the roll ptr and
764
778
trx id fields, which in an index entry differ from a record that has
765
779
the equal ordering fields. NOTE: we compare the fields as binary strings! */
766
 
UNIV_INTERN
 
780
 
767
781
upd_t*
768
782
row_upd_build_difference_binary(
769
783
/*============================*/
770
784
                                /* out, own: update vector of differing
771
785
                                fields, excluding roll ptr and trx id */
772
786
        dict_index_t*   index,  /* in: clustered index */
773
 
        const dtuple_t* entry,  /* in: entry to insert */
774
 
        const rec_t*    rec,    /* in: clustered index record */
 
787
        dtuple_t*       entry,  /* in: entry to insert */
 
788
        ulint*          ext_vec,/* in: array containing field numbers of
 
789
                                externally stored fields in entry, or NULL */
 
790
        ulint           n_ext_vec,/* in: number of fields in ext_vec */
 
791
        rec_t*          rec,    /* in: clustered index record */
775
792
        trx_t*          trx,    /* in: transaction */
776
793
        mem_heap_t*     heap)   /* in: memory heap from which allocated */
777
794
{
778
795
        upd_field_t*    upd_field;
779
 
        const dfield_t* dfield;
780
 
        const byte*     data;
 
796
        dfield_t*       dfield;
 
797
        byte*           data;
781
798
        ulint           len;
782
799
        upd_t*          update;
783
800
        ulint           n_diff;
784
801
        ulint           roll_ptr_pos;
785
802
        ulint           trx_id_pos;
 
803
        ibool           extern_bit;
786
804
        ulint           i;
787
805
        ulint           offsets_[REC_OFFS_NORMAL_SIZE];
788
806
        const ulint*    offsets;
789
 
        rec_offs_init(offsets_);
 
807
        *offsets_ = (sizeof offsets_) / sizeof *offsets_;
790
808
 
791
809
        /* This function is used only for a clustered index */
792
 
        ut_a(dict_index_is_clust(index));
 
810
        ut_a(index->type & DICT_CLUSTERED);
793
811
 
794
812
        update = upd_create(dtuple_get_n_fields(entry), heap);
795
813
 
815
833
                        goto skip_compare;
816
834
                }
817
835
 
818
 
                if (UNIV_UNLIKELY(!dfield_is_ext(dfield)
819
 
                                  != !rec_offs_nth_extern(offsets, i))
 
836
                extern_bit = upd_ext_vec_contains(ext_vec, n_ext_vec, i);
 
837
 
 
838
                if (UNIV_UNLIKELY(extern_bit
 
839
                                  == (ibool)!rec_offs_nth_extern(offsets, i))
820
840
                    || !dfield_data_is_binary_equal(dfield, len, data)) {
821
841
 
822
842
                        upd_field = upd_get_nth_field(update, n_diff);
825
845
 
826
846
                        upd_field_set_field_no(upd_field, i, index, trx);
827
847
 
 
848
                        upd_field->extern_storage = extern_bit;
 
849
 
828
850
                        n_diff++;
829
851
                }
830
852
skip_compare:
837
859
}
838
860
 
839
861
/***************************************************************
840
 
Fetch a prefix of an externally stored column.  This is similar
841
 
to row_ext_lookup(), but the row_ext_t holds the old values
842
 
of the column and must not be poisoned with the new values. */
843
 
static
844
 
byte*
845
 
row_upd_ext_fetch(
846
 
/*==============*/
847
 
                                        /* out: BLOB prefix */
848
 
        const byte*     data,           /* in: 'internally' stored part of the
849
 
                                        field containing also the reference to
850
 
                                        the external part */
851
 
        ulint           local_len,      /* in: length of data, in bytes */
852
 
        ulint           zip_size,       /* in: nonzero=compressed BLOB
853
 
                                        page size, zero for uncompressed
854
 
                                        BLOBs */
855
 
        ulint*          len,            /* in: length of prefix to fetch;
856
 
                                        out: fetched length of the prefix */
857
 
        mem_heap_t*     heap)           /* in: heap where to allocate */
858
 
{
859
 
        byte*   buf = mem_heap_alloc(heap, *len);
860
 
 
861
 
        *len = btr_copy_externally_stored_field_prefix(buf, *len,
862
 
                                                       zip_size,
863
 
                                                       data, local_len);
864
 
 
865
 
        return(buf);
866
 
}
867
 
 
868
 
/***************************************************************
869
 
Replaces the new column value stored in the update vector in
870
 
the given index entry field. */
871
 
static
872
 
void
873
 
row_upd_index_replace_new_col_val(
874
 
/*==============================*/
875
 
        dfield_t*               dfield, /* in/out: data field
876
 
                                        of the index entry */
877
 
        const dict_field_t*     field,  /* in: index field */
878
 
        const dict_col_t*       col,    /* in: field->col */
879
 
        const upd_field_t*      uf,     /* in: update field */
880
 
        mem_heap_t*             heap,   /* in: memory heap for allocating
881
 
                                        and copying the new value */
882
 
        ulint                   zip_size)/* in: compressed page
883
 
                                         size of the table, or 0 */
884
 
{
885
 
        ulint           len;
886
 
        const byte*     data;
887
 
 
888
 
        dfield_copy_data(dfield, &uf->new_val);
889
 
 
890
 
        if (dfield_is_null(dfield)) {
891
 
                return;
892
 
        }
893
 
 
894
 
        len = dfield_get_len(dfield);
895
 
        data = dfield_get_data(dfield);
896
 
 
897
 
        if (field->prefix_len > 0) {
898
 
                ibool           fetch_ext = dfield_is_ext(dfield)
899
 
                        && len < (ulint) field->prefix_len
900
 
                        + BTR_EXTERN_FIELD_REF_SIZE;
901
 
 
902
 
                if (fetch_ext) {
903
 
                        ulint   l = len;
904
 
 
905
 
                        len = field->prefix_len;
906
 
 
907
 
                        data = row_upd_ext_fetch(data, l, zip_size,
908
 
                                                 &len, heap);
909
 
                }
910
 
 
911
 
                len = dtype_get_at_most_n_mbchars(col->prtype,
912
 
                                                  col->mbminlen, col->mbmaxlen,
913
 
                                                  field->prefix_len, len,
914
 
                                                  (const char*) data);
915
 
 
916
 
                dfield_set_data(dfield, data, len);
917
 
 
918
 
                if (!fetch_ext) {
919
 
                        dfield_dup(dfield, heap);
920
 
                }
921
 
 
922
 
                return;
923
 
        }
924
 
 
925
 
        switch (uf->orig_len) {
926
 
                byte*   buf;
927
 
        case BTR_EXTERN_FIELD_REF_SIZE:
928
 
                /* Restore the original locally stored
929
 
                part of the column.  In the undo log,
930
 
                InnoDB writes a longer prefix of externally
931
 
                stored columns, so that column prefixes
932
 
                in secondary indexes can be reconstructed. */
933
 
                dfield_set_data(dfield,
934
 
                                data + len - BTR_EXTERN_FIELD_REF_SIZE,
935
 
                                BTR_EXTERN_FIELD_REF_SIZE);
936
 
                dfield_set_ext(dfield);
937
 
                /* fall through */
938
 
        case 0:
939
 
                dfield_dup(dfield, heap);
940
 
                break;
941
 
        default:
942
 
                /* Reconstruct the original locally
943
 
                stored part of the column.  The data
944
 
                will have to be copied. */
945
 
                ut_a(uf->orig_len > BTR_EXTERN_FIELD_REF_SIZE);
946
 
                buf = mem_heap_alloc(heap, uf->orig_len);
947
 
                /* Copy the locally stored prefix. */
948
 
                memcpy(buf, data,
949
 
                       uf->orig_len - BTR_EXTERN_FIELD_REF_SIZE);
950
 
                /* Copy the BLOB pointer. */
951
 
                memcpy(buf + uf->orig_len - BTR_EXTERN_FIELD_REF_SIZE,
952
 
                       data + len - BTR_EXTERN_FIELD_REF_SIZE,
953
 
                       BTR_EXTERN_FIELD_REF_SIZE);
954
 
 
955
 
                dfield_set_data(dfield, buf, uf->orig_len);
956
 
                dfield_set_ext(dfield);
957
 
                break;
958
 
        }
959
 
}
960
 
 
961
 
/***************************************************************
962
862
Replaces the new column values stored in the update vector to the index entry
963
863
given. */
964
 
UNIV_INTERN
 
864
 
965
865
void
966
866
row_upd_index_replace_new_col_vals_index_pos(
967
867
/*=========================================*/
968
 
        dtuple_t*       entry,  /* in/out: index entry where replaced;
969
 
                                the clustered index record must be
970
 
                                covered by a lock or a page latch to
971
 
                                prevent deletion (rollback or purge) */
 
868
        dtuple_t*       entry,  /* in/out: index entry where replaced */
972
869
        dict_index_t*   index,  /* in: index; NOTE that this may also be a
973
870
                                non-clustered index */
974
 
        const upd_t*    update, /* in: an update vector built for the index so
 
871
        upd_t*          update, /* in: an update vector built for the index so
975
872
                                that the field number in an upd_field is the
976
873
                                index position */
977
874
        ibool           order_only,
978
875
                                /* in: if TRUE, limit the replacement to
979
876
                                ordering fields of index; note that this
980
877
                                does not work for non-clustered indexes. */
981
 
        mem_heap_t*     heap)   /* in: memory heap for allocating and
982
 
                                copying the new values */
 
878
        mem_heap_t*     heap)   /* in: memory heap to which we allocate and
 
879
                                copy the new values, set this as NULL if you
 
880
                                do not want allocation */
983
881
{
 
882
        dict_field_t*   field;
 
883
        upd_field_t*    upd_field;
 
884
        dfield_t*       dfield;
 
885
        dfield_t*       new_val;
 
886
        ulint           j;
984
887
        ulint           i;
985
888
        ulint           n_fields;
986
 
        const ulint     zip_size        = dict_table_zip_size(index->table);
987
889
 
988
890
        ut_ad(index);
989
891
 
995
897
                n_fields = dict_index_get_n_fields(index);
996
898
        }
997
899
 
998
 
        for (i = 0; i < n_fields; i++) {
999
 
                const dict_field_t*     field;
1000
 
                const dict_col_t*       col;
1001
 
                const upd_field_t*      uf;
1002
 
 
1003
 
                field = dict_index_get_nth_field(index, i);
1004
 
                col = dict_field_get_col(field);
1005
 
                uf = upd_get_field_by_field_no(update, i);
1006
 
 
1007
 
                if (uf) {
1008
 
                        row_upd_index_replace_new_col_val(
1009
 
                                dtuple_get_nth_field(entry, i),
1010
 
                                field, col, uf, heap, zip_size);
 
900
        for (j = 0; j < n_fields; j++) {
 
901
 
 
902
                field = dict_index_get_nth_field(index, j);
 
903
 
 
904
                for (i = 0; i < upd_get_n_fields(update); i++) {
 
905
 
 
906
                        upd_field = upd_get_nth_field(update, i);
 
907
 
 
908
                        if (upd_field->field_no == j) {
 
909
 
 
910
                                dfield = dtuple_get_nth_field(entry, j);
 
911
 
 
912
                                new_val = &(upd_field->new_val);
 
913
 
 
914
                                dfield_set_data(dfield, new_val->data,
 
915
                                                new_val->len);
 
916
                                if (heap && new_val->len != UNIV_SQL_NULL) {
 
917
                                        dfield->data = mem_heap_alloc(
 
918
                                                heap, new_val->len);
 
919
                                        ut_memcpy(dfield->data, new_val->data,
 
920
                                                  new_val->len);
 
921
                                }
 
922
 
 
923
                                if (field->prefix_len > 0
 
924
                                    && new_val->len != UNIV_SQL_NULL) {
 
925
 
 
926
                                        const dict_col_t*       col
 
927
                                                = dict_field_get_col(field);
 
928
 
 
929
                                        dfield->len
 
930
                                                = dtype_get_at_most_n_mbchars(
 
931
                                                        col->prtype,
 
932
                                                        col->mbminlen,
 
933
                                                        col->mbmaxlen,
 
934
                                                        field->prefix_len,
 
935
                                                        new_val->len,
 
936
                                                        new_val->data);
 
937
                                }
 
938
                        }
1011
939
                }
1012
940
        }
1013
941
}
1015
943
/***************************************************************
1016
944
Replaces the new column values stored in the update vector to the index entry
1017
945
given. */
1018
 
UNIV_INTERN
 
946
 
1019
947
void
1020
948
row_upd_index_replace_new_col_vals(
1021
949
/*===============================*/
1022
 
        dtuple_t*       entry,  /* in/out: index entry where replaced;
1023
 
                                the clustered index record must be
1024
 
                                covered by a lock or a page latch to
1025
 
                                prevent deletion (rollback or purge) */
 
950
        dtuple_t*       entry,  /* in/out: index entry where replaced */
1026
951
        dict_index_t*   index,  /* in: index; NOTE that this may also be a
1027
952
                                non-clustered index */
1028
 
        const upd_t*    update, /* in: an update vector built for the
 
953
        upd_t*          update, /* in: an update vector built for the
1029
954
                                CLUSTERED index so that the field number in
1030
955
                                an upd_field is the clustered index position */
1031
 
        mem_heap_t*     heap)   /* in: memory heap for allocating and
1032
 
                                copying the new values */
 
956
        mem_heap_t*     heap)   /* in: memory heap to which we allocate and
 
957
                                copy the new values, set this as NULL if you
 
958
                                do not want allocation */
1033
959
{
1034
 
        ulint                   i;
1035
 
        const dict_index_t*     clust_index
1036
 
                = dict_table_get_first_index(index->table);
1037
 
        const ulint             zip_size
1038
 
                = dict_table_zip_size(index->table);
 
960
        upd_field_t*    upd_field;
 
961
        dfield_t*       dfield;
 
962
        dfield_t*       new_val;
 
963
        ulint           j;
 
964
        ulint           i;
 
965
        dict_index_t*   clust_index;
 
966
 
 
967
        ut_ad(index);
 
968
 
 
969
        clust_index = dict_table_get_first_index(index->table);
1039
970
 
1040
971
        dtuple_set_info_bits(entry, update->info_bits);
1041
972
 
1042
 
        for (i = 0; i < dict_index_get_n_fields(index); i++) {
1043
 
                const dict_field_t*     field;
1044
 
                const dict_col_t*       col;
1045
 
                const upd_field_t*      uf;
1046
 
 
1047
 
                field = dict_index_get_nth_field(index, i);
1048
 
                col = dict_field_get_col(field);
1049
 
                uf = upd_get_field_by_field_no(
1050
 
                        update, dict_col_get_clust_pos(col, clust_index));
1051
 
 
1052
 
                if (uf) {
1053
 
                        row_upd_index_replace_new_col_val(
1054
 
                                dtuple_get_nth_field(entry, i),
1055
 
                                field, col, uf, heap, zip_size);
1056
 
                }
1057
 
        }
1058
 
}
1059
 
 
1060
 
/***************************************************************
1061
 
Replaces the new column values stored in the update vector. */
1062
 
UNIV_INTERN
1063
 
void
1064
 
row_upd_replace(
1065
 
/*============*/
1066
 
        dtuple_t*               row,    /* in/out: row where replaced,
1067
 
                                        indexed by col_no;
1068
 
                                        the clustered index record must be
1069
 
                                        covered by a lock or a page latch to
1070
 
                                        prevent deletion (rollback or purge) */
1071
 
        row_ext_t**             ext,    /* out, own: NULL, or externally
1072
 
                                        stored column prefixes */
1073
 
        const dict_index_t*     index,  /* in: clustered index */
1074
 
        const upd_t*            update, /* in: an update vector built for the
1075
 
                                        clustered index */
1076
 
        mem_heap_t*             heap)   /* in: memory heap */
1077
 
{
1078
 
        ulint                   col_no;
1079
 
        ulint                   i;
1080
 
        ulint                   n_cols;
1081
 
        ulint                   n_ext_cols;
1082
 
        ulint*                  ext_cols;
1083
 
        const dict_table_t*     table;
1084
 
 
1085
 
        ut_ad(row);
1086
 
        ut_ad(ext);
1087
 
        ut_ad(index);
1088
 
        ut_ad(dict_index_is_clust(index));
1089
 
        ut_ad(update);
1090
 
        ut_ad(heap);
1091
 
 
1092
 
        n_cols = dtuple_get_n_fields(row);
1093
 
        table = index->table;
1094
 
        ut_ad(n_cols == dict_table_get_n_cols(table));
1095
 
 
1096
 
        ext_cols = mem_heap_alloc(heap, n_cols * sizeof *ext_cols);
1097
 
        n_ext_cols = 0;
1098
 
 
1099
 
        dtuple_set_info_bits(row, update->info_bits);
1100
 
 
1101
 
        for (col_no = 0; col_no < n_cols; col_no++) {
1102
 
 
1103
 
                const dict_col_t*       col
1104
 
                        = dict_table_get_nth_col(table, col_no);
1105
 
                const ulint             clust_pos
1106
 
                        = dict_col_get_clust_pos(col, index);
1107
 
                dfield_t*               dfield;
1108
 
 
1109
 
                if (UNIV_UNLIKELY(clust_pos == ULINT_UNDEFINED)) {
1110
 
 
1111
 
                        continue;
1112
 
                }
1113
 
 
1114
 
                dfield = dtuple_get_nth_field(row, col_no);
 
973
        for (j = 0; j < dict_index_get_n_fields(index); j++) {
 
974
 
 
975
                ulint           clust_pos;
 
976
                dict_field_t*   field = dict_index_get_nth_field(index, j);
 
977
 
 
978
                clust_pos = dict_col_get_clust_pos(field->col, clust_index);
1115
979
 
1116
980
                for (i = 0; i < upd_get_n_fields(update); i++) {
1117
981
 
1118
 
                        const upd_field_t*      upd_field
1119
 
                                = upd_get_nth_field(update, i);
1120
 
 
1121
 
                        if (upd_field->field_no != clust_pos) {
1122
 
 
1123
 
                                continue;
 
982
                        upd_field = upd_get_nth_field(update, i);
 
983
 
 
984
                        if (upd_field->field_no == clust_pos) {
 
985
 
 
986
                                dfield = dtuple_get_nth_field(entry, j);
 
987
 
 
988
                                new_val = &(upd_field->new_val);
 
989
 
 
990
                                dfield_set_data(dfield, new_val->data,
 
991
                                                new_val->len);
 
992
                                if (heap && new_val->len != UNIV_SQL_NULL) {
 
993
                                        dfield->data = mem_heap_alloc(
 
994
                                                heap, new_val->len);
 
995
                                        ut_memcpy(dfield->data, new_val->data,
 
996
                                                  new_val->len);
 
997
                                }
 
998
 
 
999
                                if (field->prefix_len > 0
 
1000
                                    && new_val->len != UNIV_SQL_NULL) {
 
1001
 
 
1002
                                        const dict_col_t*       col
 
1003
                                                = dict_field_get_col(field);
 
1004
 
 
1005
                                        dfield->len
 
1006
                                                = dtype_get_at_most_n_mbchars(
 
1007
                                                        col->prtype,
 
1008
                                                        col->mbminlen,
 
1009
                                                        col->mbmaxlen,
 
1010
                                                        field->prefix_len,
 
1011
                                                        new_val->len,
 
1012
                                                        new_val->data);
 
1013
                                }
1124
1014
                        }
1125
 
 
1126
 
                        dfield_copy_data(dfield, &upd_field->new_val);
1127
 
                        break;
1128
 
                }
1129
 
 
1130
 
                if (dfield_is_ext(dfield) && col->ord_part) {
1131
 
                        ext_cols[n_ext_cols++] = col_no;
1132
 
                }
1133
 
        }
1134
 
 
1135
 
        if (n_ext_cols) {
1136
 
                *ext = row_ext_create(n_ext_cols, ext_cols, row,
1137
 
                                      dict_table_zip_size(table), heap);
1138
 
        } else {
1139
 
                *ext = NULL;
 
1015
                }
1140
1016
        }
1141
1017
}
1142
1018
 
1145
1021
This function is fast if the update vector is short or the number of ordering
1146
1022
fields in the index is small. Otherwise, this can be quadratic.
1147
1023
NOTE: we compare the fields as binary strings! */
1148
 
UNIV_INTERN
 
1024
 
1149
1025
ibool
1150
1026
row_upd_changes_ord_field_binary(
1151
1027
/*=============================*/
1153
1029
                                an ordering field in the index record;
1154
1030
                                NOTE: the fields are compared as binary
1155
1031
                                strings */
1156
 
        const dtuple_t* row,    /* in: old value of row, or NULL if the
 
1032
        dtuple_t*       row,    /* in: old value of row, or NULL if the
1157
1033
                                row and the data values in update are not
1158
1034
                                known when this function is called, e.g., at
1159
1035
                                compile time */
1160
1036
        dict_index_t*   index,  /* in: index of the record */
1161
 
        const upd_t*    update) /* in: update vector for the row; NOTE: the
 
1037
        upd_t*          update) /* in: update vector for the row; NOTE: the
1162
1038
                                field numbers in this MUST be clustered index
1163
1039
                                positions! */
1164
1040
{
1188
1064
 
1189
1065
                for (j = 0; j < n_upd_fields; j++) {
1190
1066
 
1191
 
                        const upd_field_t*      upd_field
 
1067
                        upd_field_t*    upd_field
1192
1068
                                = upd_get_nth_field(update, j);
1193
1069
 
1194
1070
                        /* Note that if the index field is a column prefix
1214
1090
/***************************************************************
1215
1091
Checks if an update vector changes an ordering field of an index record.
1216
1092
NOTE: we compare the fields as binary strings! */
1217
 
UNIV_INTERN
 
1093
 
1218
1094
ibool
1219
1095
row_upd_changes_some_index_ord_field_binary(
1220
1096
/*========================================*/
1221
 
                                        /* out: TRUE if update vector
1222
 
                                        may change an ordering field
1223
 
                                        in an index record */
1224
 
        const dict_table_t*     table,  /* in: table */
1225
 
        const upd_t*            update) /* in: update vector for the row */
 
1097
                                /* out: TRUE if update vector may change
 
1098
                                an ordering field in an index record */
 
1099
        dict_table_t*   table,  /* in: table */
 
1100
        upd_t*          update) /* in: update vector for the row */
1226
1101
{
1227
1102
        upd_field_t*    upd_field;
1228
1103
        dict_index_t*   index;
1256
1131
                                /* out: TRUE if changes */
1257
1132
        dtuple_t*       entry,  /* in: index entry */
1258
1133
        dict_index_t*   index,  /* in: index of entry */
1259
 
        const upd_t*    update, /* in: update vector for the row */
 
1134
        upd_t*          update, /* in: update vector for the row */
1260
1135
        ulint           n)      /* in: how many first fields to check */
1261
1136
{
1262
1137
        ulint           n_upd_fields;
1317
1192
                data = rec_get_nth_field(rec, offsets,
1318
1193
                                         column->field_nos[SYM_CLUST_FIELD_NO],
1319
1194
                                         &len);
1320
 
                if (len == UNIV_SQL_NULL) {
1321
 
                        len = UNIV_SQL_NULL;
1322
 
                }
1323
1195
                eval_node_copy_and_alloc_val(column, data, len);
1324
1196
 
1325
1197
                column = UT_LIST_GET_NEXT(col_var_list, column);
1333
1205
void
1334
1206
row_upd_eval_new_vals(
1335
1207
/*==================*/
1336
 
        upd_t*  update) /* in/out: update vector */
 
1208
        upd_t*  update) /* in: update vector */
1337
1209
{
1338
1210
        que_node_t*     exp;
1339
1211
        upd_field_t*    upd_field;
1362
1234
        upd_node_t*     node)   /* in: row update node */
1363
1235
{
1364
1236
        dict_index_t*   clust_index;
 
1237
        upd_t*          update;
1365
1238
        rec_t*          rec;
1366
1239
        mem_heap_t*     heap            = NULL;
1367
1240
        ulint           offsets_[REC_OFFS_NORMAL_SIZE];
1368
1241
        const ulint*    offsets;
1369
 
        rec_offs_init(offsets_);
 
1242
        *offsets_ = (sizeof offsets_) / sizeof *offsets_;
1370
1243
 
1371
1244
        ut_ad(node->pcur->latch_mode != BTR_NO_LATCHES);
1372
1245
 
1373
1246
        if (node->row != NULL) {
1374
1247
                mem_heap_empty(node->heap);
 
1248
                node->row = NULL;
1375
1249
        }
1376
1250
 
1377
1251
        clust_index = dict_table_get_first_index(node->table);
1381
1255
        offsets = rec_get_offsets(rec, clust_index, offsets_,
1382
1256
                                  ULINT_UNDEFINED, &heap);
1383
1257
        node->row = row_build(ROW_COPY_DATA, clust_index, rec, offsets,
1384
 
                              NULL, &node->ext, node->heap);
 
1258
                              node->heap);
 
1259
        node->ext_vec = mem_heap_alloc(node->heap, sizeof(ulint)
 
1260
                                       * rec_offs_n_fields(offsets));
1385
1261
        if (node->is_delete) {
1386
 
                node->upd_row = NULL;
1387
 
                node->upd_ext = NULL;
 
1262
                update = NULL;
1388
1263
        } else {
1389
 
                node->upd_row = dtuple_copy(node->row, node->heap);
1390
 
                row_upd_replace(node->upd_row, &node->upd_ext,
1391
 
                                clust_index, node->update, node->heap);
 
1264
                update = node->update;
1392
1265
        }
1393
1266
 
 
1267
        node->n_ext_vec = btr_push_update_extern_fields(node->ext_vec,
 
1268
                                                        offsets, update);
1394
1269
        if (UNIV_LIKELY_NULL(heap)) {
1395
1270
                mem_heap_free(heap);
1396
1271
        }
1426
1301
        heap = mem_heap_create(1024);
1427
1302
 
1428
1303
        /* Build old index entry */
1429
 
        entry = row_build_index_entry(node->row, node->ext, index, heap);
1430
 
        ut_a(entry);
 
1304
        entry = row_build_index_entry(node->row, index, heap);
1431
1305
 
1432
1306
        log_free_check();
1433
1307
        mtr_start(&mtr);
1466
1340
                                                           thr, &mtr);
1467
1341
                        if (err == DB_SUCCESS && check_ref) {
1468
1342
 
1469
 
                                ulint*  offsets = rec_get_offsets(
1470
 
                                        rec, index, NULL,
1471
 
                                        ULINT_UNDEFINED, &heap);
1472
1343
                                /* NOTE that the following call loses
1473
1344
                                the position of pcur ! */
1474
1345
                                err = row_upd_check_references_constraints(
1475
1346
                                        node, &pcur, index->table,
1476
 
                                        index, offsets, thr, &mtr);
 
1347
                                        index, thr, &mtr);
 
1348
                                if (err != DB_SUCCESS) {
 
1349
 
 
1350
                                        goto close_cur;
 
1351
                                }
1477
1352
                        }
 
1353
 
1478
1354
                }
1479
1355
        }
1480
 
 
 
1356
close_cur:
1481
1357
        btr_pcur_close(&pcur);
1482
1358
        mtr_commit(&mtr);
1483
1359
 
1484
1360
        if (node->is_delete || err != DB_SUCCESS) {
1485
1361
 
1486
 
                goto func_exit;
 
1362
                mem_heap_free(heap);
 
1363
 
 
1364
                return(err);
1487
1365
        }
1488
1366
 
1489
1367
        /* Build a new index entry */
1490
 
        entry = row_build_index_entry(node->upd_row, node->upd_ext,
1491
 
                                      index, heap);
1492
 
        ut_a(entry);
 
1368
        row_upd_index_replace_new_col_vals(entry, index, node->update, NULL);
1493
1369
 
1494
1370
        /* Insert new index entry */
1495
 
        err = row_ins_index_entry(index, entry, 0, TRUE, thr);
 
1371
        err = row_ins_index_entry(index, entry, NULL, 0, thr);
1496
1372
 
1497
 
func_exit:
1498
1373
        mem_heap_free(heap);
1499
1374
 
1500
1375
        return(err);
1512
1387
        upd_node_t*     node,   /* in: row update node */
1513
1388
        que_thr_t*      thr)    /* in: query thread */
1514
1389
{
 
1390
        ulint   err;
 
1391
 
1515
1392
        ut_ad((node->state == UPD_NODE_UPDATE_ALL_SEC)
1516
1393
              || (node->state == UPD_NODE_UPDATE_SOME_SEC));
1517
 
        ut_ad(!dict_index_is_clust(node->index));
 
1394
        ut_ad(!(node->index->type & DICT_CLUSTERED));
1518
1395
 
1519
1396
        if (node->state == UPD_NODE_UPDATE_ALL_SEC
1520
1397
            || row_upd_changes_ord_field_binary(node->row, node->index,
1521
1398
                                                node->update)) {
1522
 
                return(row_upd_sec_index_entry(node, thr));
 
1399
                err = row_upd_sec_index_entry(node, thr);
 
1400
 
 
1401
                return(err);
1523
1402
        }
1524
1403
 
1525
1404
        return(DB_SUCCESS);
1552
1431
        ulint           err;
1553
1432
 
1554
1433
        ut_ad(node);
1555
 
        ut_ad(dict_index_is_clust(index));
 
1434
        ut_ad(index->type & DICT_CLUSTERED);
1556
1435
 
1557
1436
        trx = thr_get_trx(thr);
1558
1437
        table = node->table;
1560
1439
        btr_cur = btr_pcur_get_btr_cur(pcur);
1561
1440
 
1562
1441
        if (node->state != UPD_NODE_INSERT_CLUSTERED) {
1563
 
                rec_t*          rec;
1564
 
                dict_index_t*   index;
1565
 
                ulint           offsets_[REC_OFFS_NORMAL_SIZE];
1566
 
                ulint*          offsets;
1567
 
                rec_offs_init(offsets_);
 
1442
                ulint   offsets_[REC_OFFS_NORMAL_SIZE];
 
1443
                *offsets_ = (sizeof offsets_) / sizeof *offsets_;
1568
1444
 
1569
1445
                err = btr_cur_del_mark_set_clust_rec(BTR_NO_LOCKING_FLAG,
1570
1446
                                                     btr_cur, TRUE, thr, mtr);
1578
1454
                free those externally stored fields even if the delete marked
1579
1455
                record is removed from the index tree, or updated. */
1580
1456
 
1581
 
                rec = btr_cur_get_rec(btr_cur);
1582
 
                index = dict_table_get_first_index(table);
1583
 
                offsets = rec_get_offsets(rec, index, offsets_,
1584
 
                                          ULINT_UNDEFINED, &heap);
1585
1457
                btr_cur_mark_extern_inherited_fields(
1586
 
                        btr_cur_get_page_zip(btr_cur),
1587
 
                        rec, index, offsets, node->update, mtr);
 
1458
                        btr_cur_get_rec(btr_cur),
 
1459
                        rec_get_offsets(btr_cur_get_rec(btr_cur),
 
1460
                                        dict_table_get_first_index(table),
 
1461
                                        offsets_, ULINT_UNDEFINED, &heap),
 
1462
                        node->update, mtr);
1588
1463
                if (check_ref) {
1589
1464
                        /* NOTE that the following call loses
1590
1465
                        the position of pcur ! */
1591
1466
                        err = row_upd_check_references_constraints(
1592
 
                                node, pcur, table, index, offsets, thr, mtr);
 
1467
                                node, pcur, table, index, thr, mtr);
1593
1468
                        if (err != DB_SUCCESS) {
1594
1469
                                mtr_commit(mtr);
1595
1470
                                if (UNIV_LIKELY_NULL(heap)) {
1598
1473
                                return(err);
1599
1474
                        }
1600
1475
                }
 
1476
 
1601
1477
        }
1602
1478
 
1603
1479
        mtr_commit(mtr);
1607
1483
        }
1608
1484
        node->state = UPD_NODE_INSERT_CLUSTERED;
1609
1485
 
1610
 
        entry = row_build_index_entry(node->upd_row, node->upd_ext,
1611
 
                                      index, heap);
1612
 
        ut_a(entry);
 
1486
        entry = row_build_index_entry(node->row, index, heap);
 
1487
 
 
1488
        row_upd_index_replace_new_col_vals(entry, index, node->update, NULL);
1613
1489
 
1614
1490
        row_upd_index_entry_sys_field(entry, index, DATA_TRX_ID, trx->id);
1615
1491
 
1616
 
        if (node->upd_ext) {
1617
 
                /* If we return from a lock wait, for example, we may have
1618
 
                extern fields marked as not-owned in entry (marked in the
1619
 
                if-branch above). We must unmark them. */
1620
 
 
1621
 
                btr_cur_unmark_dtuple_extern_fields(entry);
1622
 
 
1623
 
                /* We must mark non-updated extern fields in entry as
1624
 
                inherited, so that a possible rollback will not free them. */
1625
 
 
1626
 
                btr_cur_mark_dtuple_inherited_extern(entry, node->update);
1627
 
        }
1628
 
 
1629
 
        err = row_ins_index_entry(index, entry,
1630
 
                                  node->upd_ext ? node->upd_ext->n_ext : 0,
1631
 
                                  TRUE, thr);
 
1492
        /* If we return from a lock wait, for example, we may have
 
1493
        extern fields marked as not-owned in entry (marked in the
 
1494
        if-branch above). We must unmark them. */
 
1495
 
 
1496
        btr_cur_unmark_dtuple_extern_fields(entry, node->ext_vec,
 
1497
                                            node->n_ext_vec);
 
1498
        /* We must mark non-updated extern fields in entry as inherited,
 
1499
        so that a possible rollback will not free them */
 
1500
 
 
1501
        btr_cur_mark_dtuple_inherited_extern(entry, node->ext_vec,
 
1502
                                             node->n_ext_vec,
 
1503
                                             node->update);
 
1504
 
 
1505
        err = row_ins_index_entry(index, entry, node->ext_vec,
 
1506
                                  node->n_ext_vec, thr);
1632
1507
        mem_heap_free(heap);
1633
1508
 
1634
1509
        return(err);
1648
1523
        que_thr_t*      thr,    /* in: query thread */
1649
1524
        mtr_t*          mtr)    /* in: mtr; gets committed here */
1650
1525
{
1651
 
        mem_heap_t*     heap    = NULL;
1652
1526
        big_rec_t*      big_rec = NULL;
1653
1527
        btr_pcur_t*     pcur;
1654
1528
        btr_cur_t*      btr_cur;
1655
1529
        ulint           err;
1656
1530
 
1657
1531
        ut_ad(node);
1658
 
        ut_ad(dict_index_is_clust(index));
 
1532
        ut_ad(index->type & DICT_CLUSTERED);
1659
1533
 
1660
1534
        pcur = node->pcur;
1661
1535
        btr_cur = btr_pcur_get_btr_cur(pcur);
1679
1553
 
1680
1554
        mtr_commit(mtr);
1681
1555
 
1682
 
        if (UNIV_LIKELY(err == DB_SUCCESS)) {
 
1556
        if (err == DB_SUCCESS) {
1683
1557
 
1684
 
                return(DB_SUCCESS);
 
1558
                return(err);
1685
1559
        }
1686
1560
 
1687
1561
        if (buf_LRU_buf_pool_running_out()) {
1705
1579
                                    dict_table_is_comp(index->table)));
1706
1580
 
1707
1581
        err = btr_cur_pessimistic_update(BTR_NO_LOCKING_FLAG, btr_cur,
1708
 
                                         &heap, &big_rec, node->update,
 
1582
                                         &big_rec, node->update,
1709
1583
                                         node->cmpl_info, thr, mtr);
1710
1584
        mtr_commit(mtr);
1711
1585
 
1712
1586
        if (err == DB_SUCCESS && big_rec) {
 
1587
                mem_heap_t*     heap            = NULL;
1713
1588
                ulint           offsets_[REC_OFFS_NORMAL_SIZE];
1714
1589
                rec_t*          rec;
1715
 
                rec_offs_init(offsets_);
 
1590
                *offsets_ = (sizeof offsets_) / sizeof *offsets_;
1716
1591
 
1717
1592
                mtr_start(mtr);
1718
1593
 
1719
1594
                ut_a(btr_pcur_restore_position(BTR_MODIFY_TREE, pcur, mtr));
1720
1595
                rec = btr_cur_get_rec(btr_cur);
1721
1596
                err = btr_store_big_rec_extern_fields(
1722
 
                        index, btr_cur_get_block(btr_cur), rec,
 
1597
                        index, rec,
1723
1598
                        rec_get_offsets(rec, index, offsets_,
1724
1599
                                        ULINT_UNDEFINED, &heap),
1725
 
                        big_rec, mtr);
 
1600
                         big_rec, mtr);
 
1601
                if (UNIV_LIKELY_NULL(heap)) {
 
1602
                        mem_heap_free(heap);
 
1603
                }
1726
1604
                mtr_commit(mtr);
1727
1605
        }
1728
1606
 
1729
 
        if (UNIV_LIKELY_NULL(heap)) {
1730
 
                mem_heap_free(heap);
1731
 
        }
1732
 
 
1733
1607
        if (big_rec) {
1734
1608
                dtuple_big_rec_free(big_rec);
1735
1609
        }
1747
1621
                                completed, else error code */
1748
1622
        upd_node_t*     node,   /* in: row update node */
1749
1623
        dict_index_t*   index,  /* in: clustered index */
1750
 
        ulint*          offsets,/* in/out: rec_get_offsets() for the
1751
 
                                record under the cursor */
1752
1624
        que_thr_t*      thr,    /* in: query thread */
1753
1625
        ibool           check_ref,/* in: TRUE if index may be referenced in
1754
1626
                                a foreign key constraint */
1759
1631
        ulint           err;
1760
1632
 
1761
1633
        ut_ad(node);
1762
 
        ut_ad(dict_index_is_clust(index));
 
1634
        ut_ad(index->type & DICT_CLUSTERED);
1763
1635
        ut_ad(node->is_delete);
1764
1636
 
1765
1637
        pcur = node->pcur;
1780
1652
 
1781
1653
                err = row_upd_check_references_constraints(node,
1782
1654
                                                           pcur, index->table,
1783
 
                                                           index, offsets,
1784
 
                                                           thr, mtr);
 
1655
                                                           index, thr, mtr);
 
1656
                if (err != DB_SUCCESS) {
 
1657
                        mtr_commit(mtr);
 
1658
 
 
1659
                        return(err);
 
1660
                }
1785
1661
        }
1786
1662
 
1787
1663
        mtr_commit(mtr);
1811
1687
        rec_t*          rec;
1812
1688
        mem_heap_t*     heap            = NULL;
1813
1689
        ulint           offsets_[REC_OFFS_NORMAL_SIZE];
1814
 
        ulint*          offsets;
1815
 
        rec_offs_init(offsets_);
 
1690
        const ulint*    offsets;
 
1691
        *offsets_ = (sizeof offsets_) / sizeof *offsets_;
1816
1692
 
1817
1693
        index = dict_table_get_first_index(node->table);
1818
1694
 
1875
1751
 
1876
1752
        if (!node->has_clust_rec_x_lock) {
1877
1753
                err = lock_clust_rec_modify_check_and_lock(
1878
 
                        0, btr_pcur_get_block(pcur),
1879
 
                        rec, index, offsets, thr);
 
1754
                        0, rec, index, offsets, thr);
1880
1755
                if (err != DB_SUCCESS) {
1881
1756
                        mtr_commit(mtr);
1882
1757
                        goto exit_func;
1886
1761
        /* NOTE: the following function calls will also commit mtr */
1887
1762
 
1888
1763
        if (node->is_delete) {
1889
 
                err = row_upd_del_mark_clust_rec(node, index, offsets,
1890
 
                                                 thr, check_ref, mtr);
 
1764
                err = row_upd_del_mark_clust_rec(node, index, thr, check_ref,
 
1765
                                                 mtr);
1891
1766
                if (err == DB_SUCCESS) {
1892
1767
                        node->state = UPD_NODE_UPDATE_ALL_SEC;
1893
1768
                        node->index = dict_table_get_next_index(index);
1902
1777
        /* If the update is made for MySQL, we already have the update vector
1903
1778
        ready, else we have to do some evaluation: */
1904
1779
 
1905
 
        if (UNIV_UNLIKELY(!node->in_mysql_interface)) {
 
1780
        if (!node->in_mysql_interface) {
1906
1781
                /* Copy the necessary columns from clust_rec and calculate the
1907
1782
                new values to set */
1908
1783
                row_upd_copy_columns(rec, offsets,
2023
1898
 
2024
1899
                if (node->row != NULL) {
2025
1900
                        node->row = NULL;
2026
 
                        node->ext = NULL;
2027
 
                        node->upd_row = NULL;
2028
 
                        node->upd_ext = NULL;
 
1901
                        node->n_ext_vec = 0;
2029
1902
                        mem_heap_empty(node->heap);
2030
1903
                }
2031
1904
 
2038
1911
/***************************************************************
2039
1912
Updates a row in a table. This is a high-level function used in SQL execution
2040
1913
graphs. */
2041
 
UNIV_INTERN
 
1914
 
2042
1915
que_thr_t*
2043
1916
row_upd_step(
2044
1917
/*=========*/
2153
2026
/*************************************************************************
2154
2027
Performs an in-place update for the current clustered index record in
2155
2028
select. */
2156
 
UNIV_INTERN
 
2029
 
2157
2030
void
2158
2031
row_upd_in_place_in_select(
2159
2032
/*=======================*/
2167
2040
        ulint           err;
2168
2041
        mem_heap_t*     heap            = NULL;
2169
2042
        ulint           offsets_[REC_OFFS_NORMAL_SIZE];
2170
 
        rec_offs_init(offsets_);
 
2043
        *offsets_ = (sizeof offsets_) / sizeof *offsets_;
2171
2044
 
2172
2045
        ut_ad(sel_node->select_will_do_update);
2173
2046
        ut_ad(sel_node->latch_mode == BTR_MODIFY_LEAF);
2204
2077
        err = btr_cur_update_in_place(BTR_NO_LOCKING_FLAG, btr_cur,
2205
2078
                                      node->update, node->cmpl_info,
2206
2079
                                      thr, mtr);
2207
 
        /* TODO: the above can fail with DB_ZIP_OVERFLOW if page_zip != NULL.
2208
 
        However, this function row_upd_in_place_in_select() is only invoked
2209
 
        when executing UPDATE statements of the built-in InnoDB SQL parser.
2210
 
        The built-in SQL is only used for InnoDB system tables, which
2211
 
        always are in the old, uncompressed format (ROW_FORMAT=REDUNDANT,
2212
 
        comp == FALSE, page_zip == NULL). */
2213
2080
        ut_ad(err == DB_SUCCESS);
2214
2081
}