~drizzle-trunk/drizzle/development

« back to all changes in this revision

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

  • Committer: Brian Aker
  • Date: 2009-03-20 18:52:05 UTC
  • mfrom: (950.1.1 mordred)
  • Revision ID: brian@tangent.org-20090320185205-g7o6kq17r25b6odf
Merge Monty

Show diffs side-by-side

added added

removed removed

Lines of Context:
1
1
/*****************************************************************************
2
2
 
3
 
Copyright (c) 1996, 2010, Innobase Oy. All Rights Reserved.
 
3
Copyright (c) 1996, 2009, Innobase Oy. All Rights Reserved.
4
4
 
5
5
This program is free software; you can redistribute it and/or modify it under
6
6
the terms of the GNU General Public License as published by the Free Software
11
11
FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
12
12
 
13
13
You should have received a copy of the GNU General Public License along with
14
 
this program; if not, write to the Free Software Foundation, Inc., 51 Franklin
15
 
St, Fifth Floor, Boston, MA 02110-1301 USA
 
14
this program; if not, write to the Free Software Foundation, Inc., 59 Temple
 
15
Place, Suite 330, Boston, MA 02111-1307 USA
16
16
 
17
17
*****************************************************************************/
18
18
 
19
 
/**************************************************//**
20
 
@file row/row0upd.c
 
19
/******************************************************
21
20
Update of a row
22
21
 
23
22
Created 12/27/1996 Heikki Tuuri
30
29
#endif
31
30
 
32
31
#include "dict0dict.h"
33
 
#include "trx0undo.h"
34
 
#include "rem0rec.h"
35
 
#ifndef UNIV_HOTBACKUP
36
32
#include "dict0boot.h"
37
33
#include "dict0crea.h"
38
34
#include "mach0data.h"
 
35
#include "trx0undo.h"
39
36
#include "btr0btr.h"
40
37
#include "btr0cur.h"
41
38
#include "que0que.h"
92
89
searched delete is obviously to keep the x-latch for several
93
90
steps of query graph execution. */
94
91
 
95
 
/*************************************************************************
96
 
IMPORTANT NOTE: Any operation that generates redo MUST check that there
97
 
is enough space in the redo log before for that operation. This is
98
 
done by calling log_free_check(). The reason for checking the
99
 
availability of the redo log space before the start of the operation is
100
 
that we MUST not hold any synchonization objects when performing the
101
 
check.
102
 
If you make a change in this module make sure that no codepath is
103
 
introduced where a call to log_free_check() is bypassed. */
104
 
 
105
 
/*************************************************************************
106
 
IMPORTANT NOTE: Any operation that generates redo MUST check that there
107
 
is enough space in the redo log before for that operation. This is
108
 
done by calling log_free_check(). The reason for checking the
109
 
availability of the redo log space before the start of the operation is
110
 
that we MUST not hold any synchonization objects when performing the
111
 
check.
112
 
If you make a change in this module make sure that no codepath is
113
 
introduced where a call to log_free_check() is bypassed. */
114
 
 
115
 
/***********************************************************//**
 
92
/***************************************************************
116
93
Checks if an update vector changes some of the first ordering fields of an
117
94
index record. This is only used in foreign key checks and we can assume
118
 
that index does not contain column prefixes.
119
 
@return TRUE if changes */
 
95
that index does not contain column prefixes. */
120
96
static
121
97
ibool
122
98
row_upd_changes_first_fields_binary(
123
99
/*================================*/
124
 
        dtuple_t*       entry,  /*!< in: old value of index entry */
125
 
        dict_index_t*   index,  /*!< in: index of entry */
126
 
        const upd_t*    update, /*!< in: update vector for the row */
127
 
        ulint           n);     /*!< in: how many first fields to check */
128
 
 
129
 
 
130
 
/*********************************************************************//**
 
100
                                /* out: TRUE if changes */
 
101
        dtuple_t*       entry,  /* in: old value of index entry */
 
102
        dict_index_t*   index,  /* in: index of entry */
 
103
        const upd_t*    update, /* in: update vector for the row */
 
104
        ulint           n);     /* in: how many first fields to check */
 
105
 
 
106
 
 
107
/*************************************************************************
131
108
Checks if index currently is mentioned as a referenced index in a foreign
132
 
key constraint.
133
 
 
134
 
NOTE that since we do not hold dict_operation_lock when leaving the
135
 
function, it may be that the referencing table has been dropped when
136
 
we leave this function: this function is only for heuristic use!
137
 
 
138
 
@return TRUE if referenced */
 
109
key constraint. */
139
110
static
140
111
ibool
141
112
row_upd_index_is_referenced(
142
113
/*========================*/
143
 
        dict_index_t*   index,  /*!< in: index */
144
 
        trx_t*          trx)    /*!< in: transaction */
 
114
                                /* out: TRUE if referenced; NOTE that since
 
115
                                we do not hold dict_operation_lock
 
116
                                when leaving the function, it may be that
 
117
                                the referencing table has been dropped when
 
118
                                we leave this function: this function is only
 
119
                                for heuristic use! */
 
120
        dict_index_t*   index,  /* in: index */
 
121
        trx_t*          trx)    /* in: transaction */
145
122
{
146
123
        dict_table_t*   table           = index->table;
147
124
        dict_foreign_t* foreign;
178
155
        return(is_referenced);
179
156
}
180
157
 
181
 
/*********************************************************************//**
 
158
/*************************************************************************
182
159
Checks if possible foreign key constraints hold after a delete of the record
183
 
under pcur.
184
 
 
185
 
NOTE that this function will temporarily commit mtr and lose the
186
 
pcur position!
187
 
 
188
 
@return DB_SUCCESS or an error code */
 
160
under pcur. NOTE that this function will temporarily commit mtr and lose the
 
161
pcur position! */
189
162
static
190
163
ulint
191
164
row_upd_check_references_constraints(
192
165
/*=================================*/
193
 
        upd_node_t*     node,   /*!< in: row update node */
194
 
        btr_pcur_t*     pcur,   /*!< in: cursor positioned on a record; NOTE: the
 
166
                                /* out: DB_SUCCESS or an error code */
 
167
        upd_node_t*     node,   /* in: row update node */
 
168
        btr_pcur_t*     pcur,   /* in: cursor positioned on a record; NOTE: the
195
169
                                cursor position is lost in this function! */
196
 
        dict_table_t*   table,  /*!< in: table in question */
197
 
        dict_index_t*   index,  /*!< in: index of the cursor */
198
 
        ulint*          offsets,/*!< in/out: rec_get_offsets(pcur.rec, index) */
199
 
        que_thr_t*      thr,    /*!< in: query thread */
200
 
        mtr_t*          mtr)    /*!< in: mtr */
 
170
        dict_table_t*   table,  /* in: table in question */
 
171
        dict_index_t*   index,  /* in: index of the cursor */
 
172
        ulint*          offsets,/* in/out: rec_get_offsets(pcur.rec, index) */
 
173
        que_thr_t*      thr,    /* in: query thread */
 
174
        mtr_t*          mtr)    /* in: mtr */
201
175
{
202
176
        dict_foreign_t* foreign;
203
177
        mem_heap_t*     heap;
302
276
        return(err);
303
277
}
304
278
 
305
 
/*********************************************************************//**
306
 
Creates an update node for a query graph.
307
 
@return own: update node */
 
279
/*************************************************************************
 
280
Creates an update node for a query graph. */
308
281
UNIV_INTERN
309
282
upd_node_t*
310
283
upd_node_create(
311
284
/*============*/
312
 
        mem_heap_t*     heap)   /*!< in: mem heap where created */
 
285
                                /* out, own: update node */
 
286
        mem_heap_t*     heap)   /* in: mem heap where created */
313
287
{
314
288
        upd_node_t*     node;
315
289
 
339
313
 
340
314
        return(node);
341
315
}
342
 
#endif /* !UNIV_HOTBACKUP */
343
316
 
344
 
/*********************************************************************//**
 
317
/*************************************************************************
345
318
Updates the trx id and roll ptr field in a clustered index record in database
346
319
recovery. */
347
320
UNIV_INTERN
348
321
void
349
322
row_upd_rec_sys_fields_in_recovery(
350
323
/*===============================*/
351
 
        rec_t*          rec,    /*!< in/out: record */
352
 
        page_zip_des_t* page_zip,/*!< in/out: compressed page, or NULL */
353
 
        const ulint*    offsets,/*!< in: array returned by rec_get_offsets() */
354
 
        ulint           pos,    /*!< in: TRX_ID position in rec */
355
 
        trx_id_t        trx_id, /*!< in: transaction id */
356
 
        roll_ptr_t      roll_ptr)/*!< in: roll ptr of the undo log record */
 
324
        rec_t*          rec,    /* in/out: record */
 
325
        page_zip_des_t* page_zip,/* in/out: compressed page, or NULL */
 
326
        const ulint*    offsets,/* in: array returned by rec_get_offsets() */
 
327
        ulint           pos,    /* in: TRX_ID position in rec */
 
328
        dulint          trx_id, /* in: transaction id */
 
329
        dulint          roll_ptr)/* in: roll ptr of the undo log record */
357
330
{
358
331
        ut_ad(rec_offs_validate(rec, NULL, offsets));
359
332
 
374
347
        }
375
348
}
376
349
 
377
 
#ifndef UNIV_HOTBACKUP
378
 
/*********************************************************************//**
 
350
/*************************************************************************
379
351
Sets the trx id or roll ptr field of a clustered index entry. */
380
352
UNIV_INTERN
381
353
void
382
354
row_upd_index_entry_sys_field(
383
355
/*==========================*/
384
 
        const dtuple_t* entry,  /*!< in: index entry, where the memory buffers
 
356
        const dtuple_t* entry,  /* in: index entry, where the memory buffers
385
357
                                for sys fields are already allocated:
386
358
                                the function just copies the new values to
387
359
                                them */
388
 
        dict_index_t*   index,  /*!< in: clustered index */
389
 
        ulint           type,   /*!< in: DATA_TRX_ID or DATA_ROLL_PTR */
390
 
        ib_uint64_t     val)    /*!< in: value to write */
 
360
        dict_index_t*   index,  /* in: clustered index */
 
361
        ulint           type,   /* in: DATA_TRX_ID or DATA_ROLL_PTR */
 
362
        dulint          val)    /* in: value to write */
391
363
{
392
364
        dfield_t*       dfield;
393
365
        byte*           field;
408
380
        }
409
381
}
410
382
 
411
 
/***********************************************************//**
 
383
/***************************************************************
412
384
Returns TRUE if row update changes size of some field in index or if some
413
 
field to be updated is stored externally in rec or update.
414
 
@return TRUE if the update changes the size of some field in index or
415
 
the field is external in rec or update */
 
385
field to be updated is stored externally in rec or update. */
416
386
UNIV_INTERN
417
387
ibool
418
388
row_upd_changes_field_size_or_external(
419
389
/*===================================*/
420
 
        dict_index_t*   index,  /*!< in: index */
421
 
        const ulint*    offsets,/*!< in: rec_get_offsets(rec, index) */
422
 
        const upd_t*    update) /*!< in: update vector */
 
390
                                /* out: TRUE if the update changes the size of
 
391
                                some field in index or the field is external
 
392
                                in rec or update */
 
393
        dict_index_t*   index,  /* in: index */
 
394
        const ulint*    offsets,/* in: rec_get_offsets(rec, index) */
 
395
        const upd_t*    update) /* in: update vector */
423
396
{
424
397
        const upd_field_t*      upd_field;
425
398
        const dfield_t*         new_val;
445
418
 
446
419
                        new_len = dict_col_get_sql_null_size(
447
420
                                dict_index_get_nth_col(index,
448
 
                                                       upd_field->field_no),
449
 
                                0);
 
421
                                                       upd_field->field_no));
450
422
                }
451
423
 
452
424
                old_len = rec_offs_nth_size(offsets, upd_field->field_no);
473
445
 
474
446
        return(FALSE);
475
447
}
476
 
#endif /* !UNIV_HOTBACKUP */
477
448
 
478
 
/***********************************************************//**
 
449
/***************************************************************
479
450
Replaces the new column values stored in the update vector to the record
480
451
given. No field size changes are allowed. */
481
452
UNIV_INTERN
482
453
void
483
454
row_upd_rec_in_place(
484
455
/*=================*/
485
 
        rec_t*          rec,    /*!< in/out: record where replaced */
486
 
        dict_index_t*   index,  /*!< in: the index the record belongs to */
487
 
        const ulint*    offsets,/*!< in: array returned by rec_get_offsets() */
488
 
        const upd_t*    update, /*!< in: update vector */
489
 
        page_zip_des_t* page_zip)/*!< in: compressed page with enough space
 
456
        rec_t*          rec,    /* in/out: record where replaced */
 
457
        dict_index_t*   index,  /* in: the index the record belongs to */
 
458
        const ulint*    offsets,/* in: array returned by rec_get_offsets() */
 
459
        const upd_t*    update, /* in: update vector */
 
460
        page_zip_des_t* page_zip)/* in: compressed page with enough space
490
461
                                available, or NULL */
491
462
{
492
463
        const upd_field_t*      upd_field;
520
491
        }
521
492
}
522
493
 
523
 
#ifndef UNIV_HOTBACKUP
524
 
/*********************************************************************//**
 
494
/*************************************************************************
525
495
Writes into the redo log the values of trx id and roll ptr and enough info
526
 
to determine their positions within a clustered index record.
527
 
@return new pointer to mlog */
 
496
to determine their positions within a clustered index record. */
528
497
UNIV_INTERN
529
498
byte*
530
499
row_upd_write_sys_vals_to_log(
531
500
/*==========================*/
532
 
        dict_index_t*   index,  /*!< in: clustered index */
533
 
        trx_t*          trx,    /*!< in: transaction */
534
 
        roll_ptr_t      roll_ptr,/*!< in: roll ptr of the undo log record */
535
 
        byte*           log_ptr,/*!< pointer to a buffer of size > 20 opened
 
501
                                /* out: new pointer to mlog */
 
502
        dict_index_t*   index,  /* in: clustered index */
 
503
        trx_t*          trx,    /* in: transaction */
 
504
        dulint          roll_ptr,/* in: roll ptr of the undo log record */
 
505
        byte*           log_ptr,/* pointer to a buffer of size > 20 opened
536
506
                                in mlog */
537
 
        mtr_t*          mtr __attribute__((unused))) /*!< in: mtr */
 
507
        mtr_t*          mtr __attribute__((unused))) /* in: mtr */
538
508
{
539
509
        ut_ad(dict_index_is_clust(index));
540
510
        ut_ad(mtr);
546
516
        trx_write_roll_ptr(log_ptr, roll_ptr);
547
517
        log_ptr += DATA_ROLL_PTR_LEN;
548
518
 
549
 
        log_ptr += mach_ull_write_compressed(log_ptr, trx->id);
 
519
        log_ptr += mach_dulint_write_compressed(log_ptr, trx->id);
550
520
 
551
521
        return(log_ptr);
552
522
}
553
 
#endif /* !UNIV_HOTBACKUP */
554
523
 
555
 
/*********************************************************************//**
556
 
Parses the log data of system field values.
557
 
@return log data end or NULL */
 
524
/*************************************************************************
 
525
Parses the log data of system field values. */
558
526
UNIV_INTERN
559
527
byte*
560
528
row_upd_parse_sys_vals(
561
529
/*===================*/
562
 
        byte*           ptr,    /*!< in: buffer */
563
 
        byte*           end_ptr,/*!< in: buffer end */
564
 
        ulint*          pos,    /*!< out: TRX_ID position in record */
565
 
        trx_id_t*       trx_id, /*!< out: trx id */
566
 
        roll_ptr_t*     roll_ptr)/*!< out: roll ptr */
 
530
                        /* out: log data end or NULL */
 
531
        byte*   ptr,    /* in: buffer */
 
532
        byte*   end_ptr,/* in: buffer end */
 
533
        ulint*  pos,    /* out: TRX_ID position in record */
 
534
        dulint* trx_id, /* out: trx id */
 
535
        dulint* roll_ptr)/* out: roll ptr */
567
536
{
568
537
        ptr = mach_parse_compressed(ptr, end_ptr, pos);
569
538
 
580
549
        *roll_ptr = trx_read_roll_ptr(ptr);
581
550
        ptr += DATA_ROLL_PTR_LEN;
582
551
 
583
 
        ptr = mach_ull_parse_compressed(ptr, end_ptr, trx_id);
 
552
        ptr = mach_dulint_parse_compressed(ptr, end_ptr, trx_id);
584
553
 
585
554
        return(ptr);
586
555
}
587
556
 
588
 
#ifndef UNIV_HOTBACKUP
589
 
/***********************************************************//**
 
557
/***************************************************************
590
558
Writes to the redo log the new values of the fields occurring in the index. */
591
559
UNIV_INTERN
592
560
void
593
561
row_upd_index_write_log(
594
562
/*====================*/
595
 
        const upd_t*    update, /*!< in: update vector */
596
 
        byte*           log_ptr,/*!< in: pointer to mlog buffer: must
 
563
        const upd_t*    update, /* in: update vector */
 
564
        byte*           log_ptr,/* in: pointer to mlog buffer: must
597
565
                                contain at least MLOG_BUF_MARGIN bytes
598
566
                                of free space; the buffer is closed
599
567
                                within this function */
600
 
        mtr_t*          mtr)    /*!< in: mtr into whose log to write */
 
568
        mtr_t*          mtr)    /* in: mtr into whose log to write */
601
569
{
602
570
        const upd_field_t*      upd_field;
603
571
        const dfield_t*         new_val;
656
624
 
657
625
        mlog_close(mtr, log_ptr);
658
626
}
659
 
#endif /* !UNIV_HOTBACKUP */
660
627
 
661
 
/*********************************************************************//**
662
 
Parses the log data written by row_upd_index_write_log.
663
 
@return log data end or NULL */
 
628
/*************************************************************************
 
629
Parses the log data written by row_upd_index_write_log. */
664
630
UNIV_INTERN
665
631
byte*
666
632
row_upd_index_parse(
667
633
/*================*/
668
 
        byte*           ptr,    /*!< in: buffer */
669
 
        byte*           end_ptr,/*!< in: buffer end */
670
 
        mem_heap_t*     heap,   /*!< in: memory heap where update vector is
 
634
                                /* out: log data end or NULL */
 
635
        byte*           ptr,    /* in: buffer */
 
636
        byte*           end_ptr,/* in: buffer end */
 
637
        mem_heap_t*     heap,   /* in: memory heap where update vector is
671
638
                                built */
672
 
        upd_t**         update_out)/*!< out: update vector */
 
639
        upd_t**         update_out)/* out: update vector */
673
640
{
674
641
        upd_t*          update;
675
642
        upd_field_t*    upd_field;
737
704
        return(ptr);
738
705
}
739
706
 
740
 
#ifndef UNIV_HOTBACKUP
741
 
/***************************************************************//**
 
707
/*******************************************************************
742
708
Builds an update vector from those fields which in a secondary index entry
743
709
differ from a record that has the equal ordering fields. NOTE: we compare
744
 
the fields as binary strings!
745
 
@return own: update vector of differing fields */
 
710
the fields as binary strings! */
746
711
UNIV_INTERN
747
712
upd_t*
748
713
row_upd_build_sec_rec_difference_binary(
749
714
/*====================================*/
750
 
        dict_index_t*   index,  /*!< in: index */
751
 
        const dtuple_t* entry,  /*!< in: entry to insert */
752
 
        const rec_t*    rec,    /*!< in: secondary index record */
753
 
        trx_t*          trx,    /*!< in: transaction */
754
 
        mem_heap_t*     heap)   /*!< in: memory heap from which allocated */
 
715
                                /* out, own: update vector of differing
 
716
                                fields */
 
717
        dict_index_t*   index,  /* in: index */
 
718
        const dtuple_t* entry,  /* in: entry to insert */
 
719
        const rec_t*    rec,    /* in: secondary index record */
 
720
        trx_t*          trx,    /* in: transaction */
 
721
        mem_heap_t*     heap)   /* in: memory heap from which allocated */
755
722
{
756
723
        upd_field_t*    upd_field;
757
724
        const dfield_t* dfield;
807
774
        return(update);
808
775
}
809
776
 
810
 
/***************************************************************//**
 
777
/*******************************************************************
811
778
Builds an update vector from those fields, excluding the roll ptr and
812
779
trx id fields, which in an index entry differ from a record that has
813
 
the equal ordering fields. NOTE: we compare the fields as binary strings!
814
 
@return own: update vector of differing fields, excluding roll ptr and
815
 
trx id */
 
780
the equal ordering fields. NOTE: we compare the fields as binary strings! */
816
781
UNIV_INTERN
817
782
upd_t*
818
783
row_upd_build_difference_binary(
819
784
/*============================*/
820
 
        dict_index_t*   index,  /*!< in: clustered index */
821
 
        const dtuple_t* entry,  /*!< in: entry to insert */
822
 
        const rec_t*    rec,    /*!< in: clustered index record */
823
 
        trx_t*          trx,    /*!< in: transaction */
824
 
        mem_heap_t*     heap)   /*!< in: memory heap from which allocated */
 
785
                                /* out, own: update vector of differing
 
786
                                fields, excluding roll ptr and trx id */
 
787
        dict_index_t*   index,  /* in: clustered index */
 
788
        const dtuple_t* entry,  /* in: entry to insert */
 
789
        const rec_t*    rec,    /* in: clustered index record */
 
790
        trx_t*          trx,    /* in: transaction */
 
791
        mem_heap_t*     heap)   /* in: memory heap from which allocated */
825
792
{
826
793
        upd_field_t*    upd_field;
827
794
        const dfield_t* dfield;
884
851
        return(update);
885
852
}
886
853
 
887
 
/***********************************************************//**
 
854
/***************************************************************
888
855
Fetch a prefix of an externally stored column.  This is similar
889
856
to row_ext_lookup(), but the row_ext_t holds the old values
890
 
of the column and must not be poisoned with the new values.
891
 
@return BLOB prefix */
 
857
of the column and must not be poisoned with the new values. */
892
858
static
893
859
byte*
894
860
row_upd_ext_fetch(
895
861
/*==============*/
896
 
        const byte*     data,           /*!< in: 'internally' stored part of the
 
862
                                        /* out: BLOB prefix */
 
863
        const byte*     data,           /* in: 'internally' stored part of the
897
864
                                        field containing also the reference to
898
865
                                        the external part */
899
 
        ulint           local_len,      /*!< in: length of data, in bytes */
900
 
        ulint           zip_size,       /*!< in: nonzero=compressed BLOB
 
866
        ulint           local_len,      /* in: length of data, in bytes */
 
867
        ulint           zip_size,       /* in: nonzero=compressed BLOB
901
868
                                        page size, zero for uncompressed
902
869
                                        BLOBs */
903
 
        ulint*          len,            /*!< in: length of prefix to fetch;
 
870
        ulint*          len,            /* in: length of prefix to fetch;
904
871
                                        out: fetched length of the prefix */
905
 
        mem_heap_t*     heap)           /*!< in: heap where to allocate */
 
872
        mem_heap_t*     heap)           /* in: heap where to allocate */
906
873
{
907
874
        byte*   buf = mem_heap_alloc(heap, *len);
908
875
 
915
882
        return(buf);
916
883
}
917
884
 
918
 
/***********************************************************//**
 
885
/***************************************************************
919
886
Replaces the new column value stored in the update vector in
920
887
the given index entry field. */
921
888
static
922
889
void
923
890
row_upd_index_replace_new_col_val(
924
891
/*==============================*/
925
 
        dfield_t*               dfield, /*!< in/out: data field
 
892
        dfield_t*               dfield, /* in/out: data field
926
893
                                        of the index entry */
927
 
        const dict_field_t*     field,  /*!< in: index field */
928
 
        const dict_col_t*       col,    /*!< in: field->col */
929
 
        const upd_field_t*      uf,     /*!< in: update field */
930
 
        mem_heap_t*             heap,   /*!< in: memory heap for allocating
 
894
        const dict_field_t*     field,  /* in: index field */
 
895
        const dict_col_t*       col,    /* in: field->col */
 
896
        const upd_field_t*      uf,     /* in: update field */
 
897
        mem_heap_t*             heap,   /* in: memory heap for allocating
931
898
                                        and copying the new value */
932
 
        ulint                   zip_size)/*!< in: compressed page
 
899
        ulint                   zip_size)/* in: compressed page
933
900
                                         size of the table, or 0 */
934
901
{
935
902
        ulint           len;
959
926
                }
960
927
 
961
928
                len = dtype_get_at_most_n_mbchars(col->prtype,
962
 
                                                  col->mbminmaxlen,
 
929
                                                  col->mbminlen, col->mbmaxlen,
963
930
                                                  field->prefix_len, len,
964
931
                                                  (const char*) data);
965
932
 
1008
975
        }
1009
976
}
1010
977
 
1011
 
/***********************************************************//**
 
978
/***************************************************************
1012
979
Replaces the new column values stored in the update vector to the index entry
1013
980
given. */
1014
981
UNIV_INTERN
1015
982
void
1016
983
row_upd_index_replace_new_col_vals_index_pos(
1017
984
/*=========================================*/
1018
 
        dtuple_t*       entry,  /*!< in/out: index entry where replaced;
 
985
        dtuple_t*       entry,  /* in/out: index entry where replaced;
1019
986
                                the clustered index record must be
1020
987
                                covered by a lock or a page latch to
1021
988
                                prevent deletion (rollback or purge) */
1022
 
        dict_index_t*   index,  /*!< in: index; NOTE that this may also be a
 
989
        dict_index_t*   index,  /* in: index; NOTE that this may also be a
1023
990
                                non-clustered index */
1024
 
        const upd_t*    update, /*!< in: an update vector built for the index so
 
991
        const upd_t*    update, /* in: an update vector built for the index so
1025
992
                                that the field number in an upd_field is the
1026
993
                                index position */
1027
994
        ibool           order_only,
1028
 
                                /*!< in: if TRUE, limit the replacement to
 
995
                                /* in: if TRUE, limit the replacement to
1029
996
                                ordering fields of index; note that this
1030
997
                                does not work for non-clustered indexes. */
1031
 
        mem_heap_t*     heap)   /*!< in: memory heap for allocating and
 
998
        mem_heap_t*     heap)   /* in: memory heap for allocating and
1032
999
                                copying the new values */
1033
1000
{
1034
1001
        ulint           i;
1062
1029
        }
1063
1030
}
1064
1031
 
1065
 
/***********************************************************//**
 
1032
/***************************************************************
1066
1033
Replaces the new column values stored in the update vector to the index entry
1067
1034
given. */
1068
1035
UNIV_INTERN
1069
1036
void
1070
1037
row_upd_index_replace_new_col_vals(
1071
1038
/*===============================*/
1072
 
        dtuple_t*       entry,  /*!< in/out: index entry where replaced;
 
1039
        dtuple_t*       entry,  /* in/out: index entry where replaced;
1073
1040
                                the clustered index record must be
1074
1041
                                covered by a lock or a page latch to
1075
1042
                                prevent deletion (rollback or purge) */
1076
 
        dict_index_t*   index,  /*!< in: index; NOTE that this may also be a
 
1043
        dict_index_t*   index,  /* in: index; NOTE that this may also be a
1077
1044
                                non-clustered index */
1078
 
        const upd_t*    update, /*!< in: an update vector built for the
 
1045
        const upd_t*    update, /* in: an update vector built for the
1079
1046
                                CLUSTERED index so that the field number in
1080
1047
                                an upd_field is the clustered index position */
1081
 
        mem_heap_t*     heap)   /*!< in: memory heap for allocating and
 
1048
        mem_heap_t*     heap)   /* in: memory heap for allocating and
1082
1049
                                copying the new values */
1083
1050
{
1084
1051
        ulint                   i;
1107
1074
        }
1108
1075
}
1109
1076
 
1110
 
/***********************************************************//**
 
1077
/***************************************************************
1111
1078
Replaces the new column values stored in the update vector. */
1112
1079
UNIV_INTERN
1113
1080
void
1114
1081
row_upd_replace(
1115
1082
/*============*/
1116
 
        dtuple_t*               row,    /*!< in/out: row where replaced,
 
1083
        dtuple_t*               row,    /* in/out: row where replaced,
1117
1084
                                        indexed by col_no;
1118
1085
                                        the clustered index record must be
1119
1086
                                        covered by a lock or a page latch to
1120
1087
                                        prevent deletion (rollback or purge) */
1121
 
        row_ext_t**             ext,    /*!< out, own: NULL, or externally
 
1088
        row_ext_t**             ext,    /* out, own: NULL, or externally
1122
1089
                                        stored column prefixes */
1123
 
        const dict_index_t*     index,  /*!< in: clustered index */
1124
 
        const upd_t*            update, /*!< in: an update vector built for the
 
1090
        const dict_index_t*     index,  /* in: clustered index */
 
1091
        const upd_t*            update, /* in: an update vector built for the
1125
1092
                                        clustered index */
1126
 
        mem_heap_t*             heap)   /*!< in: memory heap */
 
1093
        mem_heap_t*             heap)   /* in: memory heap */
1127
1094
{
1128
1095
        ulint                   col_no;
1129
1096
        ulint                   i;
1190
1157
        }
1191
1158
}
1192
1159
 
1193
 
/***********************************************************//**
 
1160
/***************************************************************
1194
1161
Checks if an update vector changes an ordering field of an index record.
1195
 
 
1196
1162
This function is fast if the update vector is short or the number of ordering
1197
1163
fields in the index is small. Otherwise, this can be quadratic.
1198
 
NOTE: we compare the fields as binary strings!
1199
 
@return TRUE if update vector changes an ordering field in the index record */
 
1164
NOTE: we compare the fields as binary strings! */
1200
1165
UNIV_INTERN
1201
1166
ibool
1202
1167
row_upd_changes_ord_field_binary(
1203
1168
/*=============================*/
1204
 
        const dtuple_t* row,    /*!< in: old value of row, or NULL if the
 
1169
                                /* out: TRUE if update vector changes
 
1170
                                an ordering field in the index record;
 
1171
                                NOTE: the fields are compared as binary
 
1172
                                strings */
 
1173
        const dtuple_t* row,    /* in: old value of row, or NULL if the
1205
1174
                                row and the data values in update are not
1206
1175
                                known when this function is called, e.g., at
1207
1176
                                compile time */
1208
 
        dict_index_t*   index,  /*!< in: index of the record */
1209
 
        const upd_t*    update) /*!< in: update vector for the row; NOTE: the
 
1177
        dict_index_t*   index,  /* in: index of the record */
 
1178
        const upd_t*    update) /* in: update vector for the row; NOTE: the
1210
1179
                                field numbers in this MUST be clustered index
1211
1180
                                positions! */
1212
1181
{
1259
1228
        return(FALSE);
1260
1229
}
1261
1230
 
1262
 
/***********************************************************//**
 
1231
/***************************************************************
1263
1232
Checks if an update vector changes an ordering field of an index record.
1264
 
NOTE: we compare the fields as binary strings!
1265
 
@return TRUE if update vector may change an ordering field in an index
1266
 
record */
 
1233
NOTE: we compare the fields as binary strings! */
1267
1234
UNIV_INTERN
1268
1235
ibool
1269
1236
row_upd_changes_some_index_ord_field_binary(
1270
1237
/*========================================*/
1271
 
        const dict_table_t*     table,  /*!< in: table */
1272
 
        const upd_t*            update) /*!< in: update vector for the row */
 
1238
                                        /* out: TRUE if update vector
 
1239
                                        may change an ordering field
 
1240
                                        in an index record */
 
1241
        const dict_table_t*     table,  /* in: table */
 
1242
        const upd_t*            update) /* in: update vector for the row */
1273
1243
{
1274
1244
        upd_field_t*    upd_field;
1275
1245
        dict_index_t*   index;
1292
1262
        return(FALSE);
1293
1263
}
1294
1264
 
1295
 
/***********************************************************//**
 
1265
/***************************************************************
1296
1266
Checks if an update vector changes some of the first ordering fields of an
1297
1267
index record. This is only used in foreign key checks and we can assume
1298
 
that index does not contain column prefixes.
1299
 
@return TRUE if changes */
 
1268
that index does not contain column prefixes. */
1300
1269
static
1301
1270
ibool
1302
1271
row_upd_changes_first_fields_binary(
1303
1272
/*================================*/
1304
 
        dtuple_t*       entry,  /*!< in: index entry */
1305
 
        dict_index_t*   index,  /*!< in: index of entry */
1306
 
        const upd_t*    update, /*!< in: update vector for the row */
1307
 
        ulint           n)      /*!< in: how many first fields to check */
 
1273
                                /* out: TRUE if changes */
 
1274
        dtuple_t*       entry,  /* in: index entry */
 
1275
        dict_index_t*   index,  /* in: index of entry */
 
1276
        const upd_t*    update, /* in: update vector for the row */
 
1277
        ulint           n)      /* in: how many first fields to check */
1308
1278
{
1309
1279
        ulint           n_upd_fields;
1310
1280
        ulint           i, j;
1346
1316
        return(FALSE);
1347
1317
}
1348
1318
 
1349
 
/*********************************************************************//**
 
1319
/*************************************************************************
1350
1320
Copies the column values from a record. */
1351
1321
UNIV_INLINE
1352
1322
void
1353
1323
row_upd_copy_columns(
1354
1324
/*=================*/
1355
 
        rec_t*          rec,    /*!< in: record in a clustered index */
1356
 
        const ulint*    offsets,/*!< in: array returned by rec_get_offsets() */
1357
 
        sym_node_t*     column) /*!< in: first column in a column list, or
 
1325
        rec_t*          rec,    /* in: record in a clustered index */
 
1326
        const ulint*    offsets,/* in: array returned by rec_get_offsets() */
 
1327
        sym_node_t*     column) /* in: first column in a column list, or
1358
1328
                                NULL */
1359
1329
{
1360
1330
        byte*   data;
1364
1334
                data = rec_get_nth_field(rec, offsets,
1365
1335
                                         column->field_nos[SYM_CLUST_FIELD_NO],
1366
1336
                                         &len);
 
1337
                if (len == UNIV_SQL_NULL) {
 
1338
                        len = UNIV_SQL_NULL;
 
1339
                }
1367
1340
                eval_node_copy_and_alloc_val(column, data, len);
1368
1341
 
1369
1342
                column = UT_LIST_GET_NEXT(col_var_list, column);
1370
1343
        }
1371
1344
}
1372
1345
 
1373
 
/*********************************************************************//**
 
1346
/*************************************************************************
1374
1347
Calculates the new values for fields to update. Note that row_upd_copy_columns
1375
1348
must have been called first. */
1376
1349
UNIV_INLINE
1377
1350
void
1378
1351
row_upd_eval_new_vals(
1379
1352
/*==================*/
1380
 
        upd_t*  update) /*!< in/out: update vector */
 
1353
        upd_t*  update) /* in/out: update vector */
1381
1354
{
1382
1355
        que_node_t*     exp;
1383
1356
        upd_field_t*    upd_field;
1397
1370
        }
1398
1371
}
1399
1372
 
1400
 
/***********************************************************//**
 
1373
/***************************************************************
1401
1374
Stores to the heap the row on which the node->pcur is positioned. */
1402
1375
static
1403
1376
void
1404
1377
row_upd_store_row(
1405
1378
/*==============*/
1406
 
        upd_node_t*     node)   /*!< in: row update node */
 
1379
        upd_node_t*     node)   /* in: row update node */
1407
1380
{
1408
1381
        dict_index_t*   clust_index;
1409
1382
        rec_t*          rec;
1410
1383
        mem_heap_t*     heap            = NULL;
1411
 
        row_ext_t**     ext;
1412
1384
        ulint           offsets_[REC_OFFS_NORMAL_SIZE];
1413
1385
        const ulint*    offsets;
1414
1386
        rec_offs_init(offsets_);
1425
1397
 
1426
1398
        offsets = rec_get_offsets(rec, clust_index, offsets_,
1427
1399
                                  ULINT_UNDEFINED, &heap);
1428
 
 
1429
 
        if (dict_table_get_format(node->table) >= DICT_TF_FORMAT_ZIP) {
1430
 
                /* In DYNAMIC or COMPRESSED format, there is no prefix
1431
 
                of externally stored columns in the clustered index
1432
 
                record. Build a cache of column prefixes. */
1433
 
                ext = &node->ext;
1434
 
        } else {
1435
 
                /* REDUNDANT and COMPACT formats store a local
1436
 
                768-byte prefix of each externally stored column.
1437
 
                No cache is needed. */
1438
 
                ext = NULL;
1439
 
                node->ext = NULL;
1440
 
        }
1441
 
 
1442
1400
        node->row = row_build(ROW_COPY_DATA, clust_index, rec, offsets,
1443
 
                              NULL, ext, node->heap);
 
1401
                              NULL, &node->ext, node->heap);
1444
1402
        if (node->is_delete) {
1445
1403
                node->upd_row = NULL;
1446
1404
                node->upd_ext = NULL;
1455
1413
        }
1456
1414
}
1457
1415
 
1458
 
/***********************************************************//**
1459
 
Updates a secondary index entry of a row.
1460
 
@return DB_SUCCESS if operation successfully completed, else error
1461
 
code or DB_LOCK_WAIT */
 
1416
/***************************************************************
 
1417
Updates a secondary index entry of a row. */
1462
1418
static
1463
1419
ulint
1464
1420
row_upd_sec_index_entry(
1465
1421
/*====================*/
1466
 
        upd_node_t*     node,   /*!< in: row update node */
1467
 
        que_thr_t*      thr)    /*!< in: query thread */
 
1422
                                /* out: DB_SUCCESS if operation successfully
 
1423
                                completed, else error code or DB_LOCK_WAIT */
 
1424
        upd_node_t*     node,   /* in: row update node */
 
1425
        que_thr_t*      thr)    /* in: query thread */
1468
1426
{
1469
 
        mtr_t                   mtr;
1470
 
        const rec_t*            rec;
1471
 
        btr_pcur_t              pcur;
1472
 
        mem_heap_t*             heap;
1473
 
        dtuple_t*               entry;
1474
 
        dict_index_t*           index;
1475
 
        btr_cur_t*              btr_cur;
1476
 
        ibool                   referenced;
1477
 
        ulint                   err     = DB_SUCCESS;
1478
 
        trx_t*                  trx     = thr_get_trx(thr);
1479
 
        ulint                   mode    = BTR_MODIFY_LEAF;
1480
 
        enum row_search_result  search_result;
 
1427
        ibool           check_ref;
 
1428
        ibool           found;
 
1429
        dict_index_t*   index;
 
1430
        dtuple_t*       entry;
 
1431
        btr_pcur_t      pcur;
 
1432
        btr_cur_t*      btr_cur;
 
1433
        mem_heap_t*     heap;
 
1434
        rec_t*          rec;
 
1435
        ulint           err     = DB_SUCCESS;
 
1436
        mtr_t           mtr;
 
1437
        trx_t*          trx     = thr_get_trx(thr);
1481
1438
 
1482
1439
        index = node->index;
1483
1440
 
1484
 
        referenced = row_upd_index_is_referenced(index, trx);
 
1441
        check_ref = row_upd_index_is_referenced(index, trx);
1485
1442
 
1486
1443
        heap = mem_heap_create(1024);
1487
1444
 
1489
1446
        entry = row_build_index_entry(node->row, node->ext, index, heap);
1490
1447
        ut_a(entry);
1491
1448
 
 
1449
        log_free_check();
1492
1450
        mtr_start(&mtr);
1493
1451
 
1494
 
        /* Set the query thread, so that ibuf_insert_low() will be
1495
 
        able to invoke thd_get_trx(). */
1496
 
        btr_pcur_get_btr_cur(&pcur)->thr = thr;
1497
 
 
1498
 
        /* We can only try to use the insert/delete buffer to buffer
1499
 
        delete-mark operations if the index we're modifying has no foreign
1500
 
        key constraints referring to it. */
1501
 
        if (!referenced) {
1502
 
                mode |= BTR_DELETE_MARK;
1503
 
        }
1504
 
 
1505
 
        search_result = row_search_index_entry(index, entry, mode,
1506
 
                                               &pcur, &mtr);
1507
 
 
 
1452
        found = row_search_index_entry(index, entry, BTR_MODIFY_LEAF, &pcur,
 
1453
                                       &mtr);
1508
1454
        btr_cur = btr_pcur_get_btr_cur(&pcur);
1509
1455
 
1510
1456
        rec = btr_cur_get_rec(btr_cur);
1511
1457
 
1512
 
        switch (search_result) {
1513
 
        case ROW_NOT_DELETED_REF:       /* should only occur for BTR_DELETE */
1514
 
                ut_error;
1515
 
                break;
1516
 
        case ROW_BUFFERED:
1517
 
                /* Entry was delete marked already. */
1518
 
                break;
1519
 
 
1520
 
        case ROW_NOT_FOUND:
 
1458
        if (UNIV_UNLIKELY(!found)) {
1521
1459
                fputs("InnoDB: error in sec index entry update in\n"
1522
1460
                      "InnoDB: ", stderr);
1523
1461
                dict_index_name_print(stderr, trx, index);
1534
1472
                fputs("\n"
1535
1473
                      "InnoDB: Submit a detailed bug report"
1536
1474
                      " to http://bugs.mysql.com\n", stderr);
1537
 
                break;
1538
 
        case ROW_FOUND:
 
1475
        } else {
1539
1476
                /* Delete mark the old index record; it can already be
1540
1477
                delete marked if we return after a lock wait in
1541
1478
                row_ins_index_entry below */
1542
1479
 
1543
 
                if (!rec_get_deleted_flag(
1544
 
                        rec, dict_table_is_comp(index->table))) {
1545
 
 
1546
 
                        err = btr_cur_del_mark_set_sec_rec(
1547
 
                                0, btr_cur, TRUE, thr, &mtr);
1548
 
 
1549
 
                        if (err == DB_SUCCESS && referenced) {
1550
 
 
1551
 
                                ulint*  offsets;
1552
 
 
1553
 
                                offsets = rec_get_offsets(
1554
 
                                        rec, index, NULL, ULINT_UNDEFINED,
1555
 
                                        &heap);
1556
 
 
 
1480
                if (!rec_get_deleted_flag(rec,
 
1481
                                          dict_table_is_comp(index->table))) {
 
1482
                        err = btr_cur_del_mark_set_sec_rec(0, btr_cur, TRUE,
 
1483
                                                           thr, &mtr);
 
1484
                        if (err == DB_SUCCESS && check_ref) {
 
1485
 
 
1486
                                ulint*  offsets = rec_get_offsets(
 
1487
                                        rec, index, NULL,
 
1488
                                        ULINT_UNDEFINED, &heap);
1557
1489
                                /* NOTE that the following call loses
1558
1490
                                the position of pcur ! */
1559
1491
                                err = row_upd_check_references_constraints(
1561
1493
                                        index, offsets, thr, &mtr);
1562
1494
                        }
1563
1495
                }
1564
 
                break;
1565
1496
        }
1566
1497
 
1567
1498
        btr_pcur_close(&pcur);
1586
1517
        return(err);
1587
1518
}
1588
1519
 
1589
 
/***********************************************************//**
 
1520
/***************************************************************
1590
1521
Updates the secondary index record if it is changed in the row update or
1591
 
deletes it if this is a delete.
1592
 
@return DB_SUCCESS if operation successfully completed, else error
1593
 
code or DB_LOCK_WAIT */
1594
 
static
 
1522
deletes it if this is a delete. */
 
1523
UNIV_INLINE
1595
1524
ulint
1596
1525
row_upd_sec_step(
1597
1526
/*=============*/
1598
 
        upd_node_t*     node,   /*!< in: row update node */
1599
 
        que_thr_t*      thr)    /*!< in: query thread */
 
1527
                                /* out: DB_SUCCESS if operation successfully
 
1528
                                completed, else error code or DB_LOCK_WAIT */
 
1529
        upd_node_t*     node,   /* in: row update node */
 
1530
        que_thr_t*      thr)    /* in: query thread */
1600
1531
{
1601
1532
        ut_ad((node->state == UPD_NODE_UPDATE_ALL_SEC)
1602
1533
              || (node->state == UPD_NODE_UPDATE_SOME_SEC));
1611
1542
        return(DB_SUCCESS);
1612
1543
}
1613
1544
 
1614
 
/***********************************************************//**
 
1545
/***************************************************************
1615
1546
Marks the clustered index record deleted and inserts the updated version
1616
1547
of the record to the index. This function should be used when the ordering
1617
1548
fields of the clustered index record change. This should be quite rare in
1618
 
database applications.
1619
 
@return DB_SUCCESS if operation successfully completed, else error
1620
 
code or DB_LOCK_WAIT */
 
1549
database applications. */
1621
1550
static
1622
1551
ulint
1623
1552
row_upd_clust_rec_by_insert(
1624
1553
/*========================*/
1625
 
        upd_node_t*     node,   /*!< in: row update node */
1626
 
        dict_index_t*   index,  /*!< in: clustered index of the record */
1627
 
        que_thr_t*      thr,    /*!< in: query thread */
1628
 
        ibool           referenced,/*!< in: TRUE if index may be referenced in
 
1554
                                /* out: DB_SUCCESS if operation successfully
 
1555
                                completed, else error code or DB_LOCK_WAIT */
 
1556
        upd_node_t*     node,   /* in: row update node */
 
1557
        dict_index_t*   index,  /* in: clustered index of the record */
 
1558
        que_thr_t*      thr,    /* in: query thread */
 
1559
        ibool           check_ref,/* in: TRUE if index may be referenced in
1629
1560
                                a foreign key constraint */
1630
 
        mtr_t*          mtr)    /*!< in: mtr; gets committed here */
 
1561
        mtr_t*          mtr)    /* in: mtr; gets committed here */
1631
1562
{
1632
1563
        mem_heap_t*     heap    = NULL;
1633
1564
        btr_pcur_t*     pcur;
1636
1567
        dict_table_t*   table;
1637
1568
        dtuple_t*       entry;
1638
1569
        ulint           err;
1639
 
        ibool           change_ownership = FALSE;
1640
1570
 
1641
1571
        ut_ad(node);
1642
1572
        ut_ad(dict_index_is_clust(index));
1669
1599
                index = dict_table_get_first_index(table);
1670
1600
                offsets = rec_get_offsets(rec, index, offsets_,
1671
1601
                                          ULINT_UNDEFINED, &heap);
1672
 
                change_ownership = btr_cur_mark_extern_inherited_fields(
1673
 
                        btr_cur_get_page_zip(btr_cur), rec, index, offsets,
1674
 
                        node->update, mtr);
1675
 
                if (referenced) {
 
1602
                btr_cur_mark_extern_inherited_fields(
 
1603
                        btr_cur_get_page_zip(btr_cur),
 
1604
                        rec, index, offsets, node->update, mtr);
 
1605
                if (check_ref) {
1676
1606
                        /* NOTE that the following call loses
1677
1607
                        the position of pcur ! */
1678
 
 
1679
1608
                        err = row_upd_check_references_constraints(
1680
1609
                                node, pcur, table, index, offsets, thr, mtr);
1681
 
 
1682
1610
                        if (err != DB_SUCCESS) {
1683
 
 
1684
1611
                                mtr_commit(mtr);
1685
 
 
1686
1612
                                if (UNIV_LIKELY_NULL(heap)) {
1687
1613
                                        mem_heap_free(heap);
1688
1614
                                }
1689
 
 
1690
1615
                                return(err);
1691
1616
                        }
1692
1617
                }
1705
1630
 
1706
1631
        row_upd_index_entry_sys_field(entry, index, DATA_TRX_ID, trx->id);
1707
1632
 
1708
 
        if (change_ownership) {
 
1633
        if (node->upd_ext) {
1709
1634
                /* If we return from a lock wait, for example, we may have
1710
1635
                extern fields marked as not-owned in entry (marked in the
1711
 
                if-branch above). We must unmark them, take the ownership
1712
 
                back. */
 
1636
                if-branch above). We must unmark them. */
1713
1637
 
1714
1638
                btr_cur_unmark_dtuple_extern_fields(entry);
1715
1639
 
1727
1651
        return(err);
1728
1652
}
1729
1653
 
1730
 
/***********************************************************//**
 
1654
/***************************************************************
1731
1655
Updates a clustered index record of a row when the ordering fields do
1732
 
not change.
1733
 
@return DB_SUCCESS if operation successfully completed, else error
1734
 
code or DB_LOCK_WAIT */
 
1656
not change. */
1735
1657
static
1736
1658
ulint
1737
1659
row_upd_clust_rec(
1738
1660
/*==============*/
1739
 
        upd_node_t*     node,   /*!< in: row update node */
1740
 
        dict_index_t*   index,  /*!< in: clustered index */
1741
 
        que_thr_t*      thr,    /*!< in: query thread */
1742
 
        mtr_t*          mtr)    /*!< in: mtr; gets committed here */
 
1661
                                /* out: DB_SUCCESS if operation successfully
 
1662
                                completed, else error code or DB_LOCK_WAIT */
 
1663
        upd_node_t*     node,   /* in: row update node */
 
1664
        dict_index_t*   index,  /* in: clustered index */
 
1665
        que_thr_t*      thr,    /* in: query thread */
 
1666
        mtr_t*          mtr)    /* in: mtr; gets committed here */
1743
1667
{
1744
1668
        mem_heap_t*     heap    = NULL;
1745
1669
        big_rec_t*      big_rec = NULL;
1830
1754
        return(err);
1831
1755
}
1832
1756
 
1833
 
/***********************************************************//**
1834
 
Delete marks a clustered index record.
1835
 
@return DB_SUCCESS if operation successfully completed, else error code */
 
1757
/***************************************************************
 
1758
Delete marks a clustered index record. */
1836
1759
static
1837
1760
ulint
1838
1761
row_upd_del_mark_clust_rec(
1839
1762
/*=======================*/
1840
 
        upd_node_t*     node,   /*!< in: row update node */
1841
 
        dict_index_t*   index,  /*!< in: clustered index */
1842
 
        ulint*          offsets,/*!< in/out: rec_get_offsets() for the
 
1763
                                /* out: DB_SUCCESS if operation successfully
 
1764
                                completed, else error code */
 
1765
        upd_node_t*     node,   /* in: row update node */
 
1766
        dict_index_t*   index,  /* in: clustered index */
 
1767
        ulint*          offsets,/* in/out: rec_get_offsets() for the
1843
1768
                                record under the cursor */
1844
 
        que_thr_t*      thr,    /*!< in: query thread */
1845
 
        ibool           referenced,
1846
 
                                /*!< in: TRUE if index may be referenced in
 
1769
        que_thr_t*      thr,    /* in: query thread */
 
1770
        ibool           check_ref,/* in: TRUE if index may be referenced in
1847
1771
                                a foreign key constraint */
1848
 
        mtr_t*          mtr)    /*!< in: mtr; gets committed here */
 
1772
        mtr_t*          mtr)    /* in: mtr; gets committed here */
1849
1773
{
1850
1774
        btr_pcur_t*     pcur;
1851
1775
        btr_cur_t*      btr_cur;
1868
1792
 
1869
1793
        err = btr_cur_del_mark_set_clust_rec(BTR_NO_LOCKING_FLAG,
1870
1794
                                             btr_cur, TRUE, thr, mtr);
1871
 
        if (err == DB_SUCCESS && referenced) {
 
1795
        if (err == DB_SUCCESS && check_ref) {
1872
1796
                /* NOTE that the following call loses the position of pcur ! */
1873
1797
 
1874
 
                err = row_upd_check_references_constraints(
1875
 
                        node, pcur, index->table, index, offsets, thr, mtr);
 
1798
                err = row_upd_check_references_constraints(node,
 
1799
                                                           pcur, index->table,
 
1800
                                                           index, offsets,
 
1801
                                                           thr, mtr);
1876
1802
        }
1877
1803
 
1878
1804
        mtr_commit(mtr);
1880
1806
        return(err);
1881
1807
}
1882
1808
 
1883
 
/***********************************************************//**
1884
 
Updates the clustered index record.
1885
 
@return DB_SUCCESS if operation successfully completed, DB_LOCK_WAIT
1886
 
in case of a lock wait, else error code */
 
1809
/***************************************************************
 
1810
Updates the clustered index record. */
1887
1811
static
1888
1812
ulint
1889
1813
row_upd_clust_step(
1890
1814
/*===============*/
1891
 
        upd_node_t*     node,   /*!< in: row update node */
1892
 
        que_thr_t*      thr)    /*!< in: query thread */
 
1815
                                /* out: DB_SUCCESS if operation successfully
 
1816
                                completed, DB_LOCK_WAIT in case of a lock wait,
 
1817
                                else error code */
 
1818
        upd_node_t*     node,   /* in: row update node */
 
1819
        que_thr_t*      thr)    /* in: query thread */
1893
1820
{
1894
1821
        dict_index_t*   index;
1895
1822
        btr_pcur_t*     pcur;
1896
1823
        ibool           success;
 
1824
        ibool           check_ref;
1897
1825
        ulint           err;
1898
1826
        mtr_t*          mtr;
1899
1827
        mtr_t           mtr_buf;
1901
1829
        mem_heap_t*     heap            = NULL;
1902
1830
        ulint           offsets_[REC_OFFS_NORMAL_SIZE];
1903
1831
        ulint*          offsets;
1904
 
        ibool           referenced;
1905
1832
        rec_offs_init(offsets_);
1906
1833
 
1907
1834
        index = dict_table_get_first_index(node->table);
1908
1835
 
1909
 
        referenced = row_upd_index_is_referenced(index, thr_get_trx(thr));
 
1836
        check_ref = row_upd_index_is_referenced(index, thr_get_trx(thr));
1910
1837
 
1911
1838
        pcur = node->pcur;
1912
1839
 
1939
1866
        then we have to free the file segments of the index tree associated
1940
1867
        with the index */
1941
1868
 
1942
 
        if (node->is_delete && node->table->id == DICT_INDEXES_ID) {
 
1869
        if (node->is_delete
 
1870
            && ut_dulint_cmp(node->table->id, DICT_INDEXES_ID) == 0) {
1943
1871
 
1944
1872
                dict_drop_index_tree(btr_pcur_get_rec(pcur), mtr);
1945
1873
 
1975
1903
        /* NOTE: the following function calls will also commit mtr */
1976
1904
 
1977
1905
        if (node->is_delete) {
1978
 
                err = row_upd_del_mark_clust_rec(
1979
 
                        node, index, offsets, thr, referenced, mtr);
1980
 
 
 
1906
                err = row_upd_del_mark_clust_rec(node, index, offsets,
 
1907
                                                 thr, check_ref, mtr);
1981
1908
                if (err == DB_SUCCESS) {
1982
1909
                        node->state = UPD_NODE_UPDATE_ALL_SEC;
1983
1910
                        node->index = dict_table_get_next_index(index);
2025
1952
                choosing records to update. MySQL solves now the problem
2026
1953
                externally! */
2027
1954
 
2028
 
                err = row_upd_clust_rec_by_insert(
2029
 
                        node, index, thr, referenced, mtr);
2030
 
 
 
1955
                err = row_upd_clust_rec_by_insert(node, index, thr, check_ref,
 
1956
                                                  mtr);
2031
1957
                if (err != DB_SUCCESS) {
2032
1958
 
2033
1959
                        return(err);
2050
1976
        return(err);
2051
1977
}
2052
1978
 
2053
 
/***********************************************************//**
 
1979
/***************************************************************
2054
1980
Updates the affected index records of a row. When the control is transferred
2055
1981
to this node, we assume that we have a persistent cursor which was on a
2056
 
record, and the position of the cursor is stored in the cursor.
2057
 
@return DB_SUCCESS if operation successfully completed, else error
2058
 
code or DB_LOCK_WAIT */
 
1982
record, and the position of the cursor is stored in the cursor. */
2059
1983
static
2060
1984
ulint
2061
1985
row_upd(
2062
1986
/*====*/
2063
 
        upd_node_t*     node,   /*!< in: row update node */
2064
 
        que_thr_t*      thr)    /*!< in: query thread */
 
1987
                                /* out: DB_SUCCESS if operation successfully
 
1988
                                completed, else error code or DB_LOCK_WAIT */
 
1989
        upd_node_t*     node,   /* in: row update node */
 
1990
        que_thr_t*      thr)    /* in: query thread */
2065
1991
{
2066
1992
        ulint   err     = DB_SUCCESS;
2067
1993
 
2084
2010
        if (node->state == UPD_NODE_UPDATE_CLUSTERED
2085
2011
            || node->state == UPD_NODE_INSERT_CLUSTERED) {
2086
2012
 
2087
 
                log_free_check();
2088
2013
                err = row_upd_clust_step(node, thr);
2089
2014
 
2090
2015
                if (err != DB_SUCCESS) {
2099
2024
        }
2100
2025
 
2101
2026
        while (node->index != NULL) {
2102
 
 
2103
 
                log_free_check();
2104
2027
                err = row_upd_sec_step(node, thr);
2105
2028
 
2106
2029
                if (err != DB_SUCCESS) {
2129
2052
        return(err);
2130
2053
}
2131
2054
 
2132
 
/***********************************************************//**
 
2055
/***************************************************************
2133
2056
Updates a row in a table. This is a high-level function used in SQL execution
2134
 
graphs.
2135
 
@return query thread to run next or NULL */
 
2057
graphs. */
2136
2058
UNIV_INTERN
2137
2059
que_thr_t*
2138
2060
row_upd_step(
2139
2061
/*=========*/
2140
 
        que_thr_t*      thr)    /*!< in: query thread */
 
2062
                                /* out: query thread to run next or NULL */
 
2063
        que_thr_t*      thr)    /* in: query thread */
2141
2064
{
2142
2065
        upd_node_t*     node;
2143
2066
        sel_node_t*     sel_node;
2243
2166
 
2244
2167
        return(thr);
2245
2168
}
2246
 
#endif /* !UNIV_HOTBACKUP */