1
1
/* ****************************************************************************
2
2
3
- Copyright (c) 1997, 2016 , Oracle and/or its affiliates. All Rights Reserved.
3
+ Copyright (c) 1997, 2017 , Oracle and/or its affiliates. All Rights Reserved.
4
4
Copyright (c) 2017, 2018, MariaDB Corporation.
5
5
6
6
This program is free software; you can redistribute it and/or modify it under
@@ -45,24 +45,31 @@ Created 2/6/1997 Heikki Tuuri
45
45
#include " lock0lock.h"
46
46
#include " row0mysql.h"
47
47
48
- /* * Check whether all non-virtual columns in a virtual index match that of in
49
- the cluster index
50
- @param[in] index the secondary index
51
- @param[in] row the cluster index row in dtuple form
52
- @param[in] ext externally stored column prefix or NULL
53
- @param[in] ientry the secondary index entry
54
- @param[in,out] heap heap used to build virtual dtuple
55
- @param[in,out] n_non_v_col number of non-virtual columns in the index
56
- @return true if all matches, false otherwise */
48
+ /* * Check whether all non-virtual index fields are equal.
49
+ @param[in] index the secondary index
50
+ @param[in] a first index entry to compare
51
+ @param[in] b second index entry to compare
52
+ @return whether all non-virtual fields are equal */
57
53
static
58
54
bool
59
- row_vers_non_vc_match (
60
- dict_index_t * index,
61
- const dtuple_t * row,
62
- const row_ext_t * ext,
63
- const dtuple_t * ientry,
64
- mem_heap_t * heap,
65
- ulint* n_non_v_col);
55
+ row_vers_non_virtual_fields_equal (
56
+ const dict_index_t * index,
57
+ const dfield_t * a,
58
+ const dfield_t * b)
59
+ {
60
+ const dict_field_t * end = &index->fields [index->n_fields ];
61
+
62
+ for (const dict_field_t * ifield = index->fields ; ifield != end;
63
+ ifield++) {
64
+ if (!dict_col_is_virtual (ifield->col )
65
+ && cmp_dfield_dfield (a++, b++)) {
66
+ return false ;
67
+ }
68
+ }
69
+
70
+ return true ;
71
+ }
72
+
66
73
/* * Determine if an active transaction has inserted or modified a secondary
67
74
index record.
68
75
@param[in] clust_rec clustered index record
@@ -233,15 +240,29 @@ row_vers_impl_x_locked_low(
233
240
}
234
241
235
242
if (!cur_vrow) {
236
- ulint n_non_v_col = 0 ;
243
+ /* Build index entry out of row */
244
+ entry = row_build_index_entry (row, ext, index,
245
+ heap);
246
+
247
+ /* entry could only be NULL (the
248
+ clustered index record could contain
249
+ BLOB pointers that are NULL) if we
250
+ were accessing a freshly inserted
251
+ record before it was fully inserted.
252
+ prev_version cannot possibly be such
253
+ an incomplete record, because its
254
+ transaction would have to be committed
255
+ in order for later versions of the
256
+ record to be able to exist. */
257
+ ut_ad (entry);
237
258
238
259
/* If the indexed virtual columns has changed,
239
260
there must be log record to generate vrow.
240
261
Otherwise, it is not changed, so no need
241
262
to compare */
242
- if (row_vers_non_vc_match (
243
- index, row, ext, ientry, heap ,
244
- &n_non_v_col) == 0 ) {
263
+ if (! row_vers_non_virtual_fields_equal (
264
+ index ,
265
+ ientry-> fields , entry-> fields ) ) {
245
266
if (rec_del != vers_del) {
246
267
break ;
247
268
}
@@ -411,61 +432,6 @@ row_vers_must_preserve_del_marked(
411
432
return (!purge_sys->view .changes_visible (trx_id, name));
412
433
}
413
434
414
- /* * Check whether all non-virtual columns in a virtual index match that of in
415
- the cluster index
416
- @param[in] index the secondary index
417
- @param[in] row the cluster index row in dtuple form
418
- @param[in] ext externally stored column prefix or NULL
419
- @param[in] ientry the secondary index entry
420
- @param[in,out] heap heap used to build virtual dtuple
421
- @param[in,out] n_non_v_col number of non-virtual columns in the index
422
- @return true if all matches, false otherwise */
423
- static
424
- bool
425
- row_vers_non_vc_match (
426
- dict_index_t * index,
427
- const dtuple_t * row,
428
- const row_ext_t * ext,
429
- const dtuple_t * ientry,
430
- mem_heap_t * heap,
431
- ulint* n_non_v_col)
432
- {
433
- const dfield_t * field1;
434
- dfield_t * field2;
435
- ulint n_fields = dtuple_get_n_fields (ientry);
436
- ulint ret = true ;
437
-
438
- *n_non_v_col = 0 ;
439
-
440
- /* Build index entry out of row */
441
- dtuple_t * nentry = row_build_index_entry (row, ext, index, heap);
442
-
443
- for (ulint i = 0 ; i < n_fields; i++) {
444
- const dict_field_t * ind_field = dict_index_get_nth_field (
445
- index, i);
446
-
447
- const dict_col_t * col = ind_field->col ;
448
-
449
- /* Only check non-virtual columns */
450
- if (dict_col_is_virtual (col)) {
451
- continue ;
452
- }
453
-
454
- if (ret) {
455
- field1 = dtuple_get_nth_field (ientry, i);
456
- field2 = dtuple_get_nth_field (nentry, i);
457
-
458
- if (cmp_dfield_dfield (field1, field2) != 0 ) {
459
- ret = false ;
460
- }
461
- }
462
-
463
- (*n_non_v_col)++;
464
- }
465
-
466
- return (ret);
467
- }
468
-
469
435
/* * build virtual column value from current cluster index record data
470
436
@param[in,out] row the cluster index row in dtuple form
471
437
@param[in] clust_index clustered index
@@ -616,8 +582,7 @@ that of current cluster index record, which is recreated from information
616
582
stored in undo log
617
583
@param[in] in_purge called by purge thread
618
584
@param[in] rec record in the clustered index
619
- @param[in] row the cluster index row in dtuple form
620
- @param[in] ext externally stored column prefix or NULL
585
+ @param[in] icentry the index entry built from a cluster row
621
586
@param[in] clust_index cluster index
622
587
@param[in] clust_offsets offsets on the cluster record
623
588
@param[in] index the secondary index
633
598
row_vers_vc_matches_cluster (
634
599
bool in_purge,
635
600
const rec_t * rec,
636
- const dtuple_t * row,
637
- row_ext_t * ext,
601
+ const dtuple_t * icentry,
638
602
dict_index_t * clust_index,
639
603
ulint* clust_offsets,
640
604
dict_index_t * index,
@@ -659,15 +623,27 @@ row_vers_vc_matches_cluster(
659
623
dfield_t * field2;
660
624
ulint i;
661
625
662
- tuple_heap = mem_heap_create (1024 );
663
-
664
626
/* First compare non-virtual columns (primary keys) */
665
- if (!row_vers_non_vc_match (index, row, ext, ientry, tuple_heap,
666
- &n_non_v_col)) {
667
- mem_heap_free (tuple_heap);
668
- return (false );
627
+ ut_ad (index->n_fields == n_fields);
628
+ ut_ad (n_fields == dtuple_get_n_fields (icentry));
629
+ {
630
+ const dfield_t * a = ientry->fields ;
631
+ const dfield_t * b = icentry->fields ;
632
+
633
+ for (const dict_field_t *ifield = index->fields ,
634
+ *const end = &index->fields [index->n_fields ];
635
+ ifield != end; ifield++, a++, b++) {
636
+ if (!dict_col_is_virtual (ifield->col )) {
637
+ if (cmp_dfield_dfield (a, b)) {
638
+ return false ;
639
+ }
640
+ n_non_v_col++;
641
+ }
642
+ }
669
643
}
670
644
645
+ tuple_heap = mem_heap_create (1024 );
646
+
671
647
ut_ad (n_fields > n_non_v_col);
672
648
673
649
*vrow = dtuple_create_with_vcol (v_heap ? v_heap : tuple_heap, 0 , num_v);
@@ -936,27 +912,28 @@ row_vers_old_has_index_entry(
936
912
entry = row_build_index_entry (
937
913
row, ext, index, heap);
938
914
if (entry && !dtuple_coll_cmp (ientry, entry)) {
939
-
940
- mem_heap_free (heap);
941
-
942
- if (v_heap) {
943
- mem_heap_free (v_heap);
944
- }
945
-
946
- return (TRUE );
915
+ goto safe_to_purge;
947
916
}
948
917
} else {
949
- if (row_vers_vc_matches_cluster (
950
- also_curr, rec, row, ext, clust_index,
951
- clust_offsets, index, ientry, roll_ptr,
952
- trx_id, NULL , &vrow, mtr)) {
953
- mem_heap_free (heap);
954
-
955
- if (v_heap) {
956
- mem_heap_free (v_heap);
957
- }
958
-
959
- return (TRUE );
918
+ /* Build index entry out of row */
919
+ entry = row_build_index_entry (row, ext, index, heap);
920
+ /* entry could only be NULL if
921
+ the clustered index record is an uncommitted
922
+ inserted record whose BLOBs have not been
923
+ written yet. The secondary index record
924
+ can be safely removed, because it cannot
925
+ possibly refer to this incomplete
926
+ clustered index record. (Insert would
927
+ always first be completed for the
928
+ clustered index record, then proceed to
929
+ secondary indexes.) */
930
+
931
+ if (entry && row_vers_vc_matches_cluster (
932
+ also_curr, rec, entry,
933
+ clust_index, clust_offsets,
934
+ index, ientry, roll_ptr,
935
+ trx_id, NULL , &vrow, mtr)) {
936
+ goto safe_to_purge;
960
937
}
961
938
}
962
939
clust_offsets = rec_get_offsets (rec, clust_index, NULL ,
@@ -989,7 +966,7 @@ row_vers_old_has_index_entry(
989
966
a different binary value in a char field, but the
990
967
collation identifies the old and new value anyway! */
991
968
if (entry && !dtuple_coll_cmp (ientry, entry)) {
992
-
969
+ safe_to_purge:
993
970
mem_heap_free (heap);
994
971
995
972
if (v_heap) {
@@ -1086,13 +1063,7 @@ row_vers_old_has_index_entry(
1086
1063
and new value anyway! */
1087
1064
1088
1065
if (entry && !dtuple_coll_cmp (ientry, entry)) {
1089
-
1090
- mem_heap_free (heap);
1091
- if (v_heap) {
1092
- mem_heap_free (v_heap);
1093
- }
1094
-
1095
- return (TRUE );
1066
+ goto safe_to_purge;
1096
1067
}
1097
1068
}
1098
1069
0 commit comments