1
/*****************************************************************************
3
Copyright (C) 1996, 2010, Innobase Oy. All Rights Reserved.
5
This program is free software; you can redistribute it and/or modify it under
6
the terms of the GNU General Public License as published by the Free Software
7
Foundation; version 2 of the License.
9
This program is distributed in the hope that it will be useful, but WITHOUT
10
ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
11
FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
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
17
*****************************************************************************/
19
/**************************************************//**
1
/******************************************************
21
2
General row routines
23
6
Created 4/20/1996 Heikki Tuuri
24
7
*******************************************************/
47
30
#include "read0read.h"
48
31
#include "ut0mem.h"
50
/*********************************************************************//**
33
/*************************************************************************
51
34
Gets the offset of trx id field, in bytes relative to the origin of
52
a clustered index record.
53
@return offset of DATA_TRX_ID */
35
a clustered index record. */
56
38
row_get_trx_id_offset(
57
39
/*==================*/
58
const rec_t* /*rec __attribute__((unused))*/,
60
dict_index_t* index, /*!< in: clustered index */
61
const ulint* offsets)/*!< in: rec_get_offsets(rec, index) */
40
/* out: offset of DATA_TRX_ID */
41
const rec_t* rec __attribute__((unused)),
43
dict_index_t* index, /* in: clustered index */
44
const ulint* offsets)/* in: rec_get_offsets(rec, index) */
79
/*****************************************************************//**
62
/*********************************************************************
80
63
When an insert or purge to a table is performed, this function builds
81
the entry to be inserted into or purged from an index on the table.
82
@return index entry which should be inserted or purged, or NULL if the
83
externally stored columns in the clustered index record are
84
unavailable and ext != NULL */
64
the entry to be inserted into or purged from an index on the table. */
87
67
row_build_index_entry(
88
68
/*==================*/
89
const dtuple_t* row, /*!< in: row which should be
69
/* out: index entry which should be
70
inserted or purged, or NULL if the
71
externally stored columns in the
72
clustered index record are unavailable
74
const dtuple_t* row, /* in: row which should be
90
75
inserted or purged */
91
row_ext_t* ext, /*!< in: externally stored column prefixes,
76
row_ext_t* ext, /* in: externally stored column prefixes,
93
dict_index_t* index, /*!< in: index on the table */
94
mem_heap_t* heap) /*!< in: memory heap from which the memory for
78
dict_index_t* index, /* in: index on the table */
79
mem_heap_t* heap) /* in: memory heap from which the memory for
95
80
the index entry is allocated */
158
143
len = dtype_get_at_most_n_mbchars(
159
col->prtype, col->mbminmaxlen,
160
ind_field->prefix_len, len, static_cast<const char *>(dfield_get_data(dfield)));
144
col->prtype, col->mbminlen, col->mbmaxlen,
145
ind_field->prefix_len, len, dfield_get_data(dfield));
161
146
dfield_set_len(dfield, len);
169
/*******************************************************************//**
154
/***********************************************************************
170
155
An inverse function to row_build_index_entry. Builds a row from a
171
record in a clustered index.
172
@return own: row built; see the NOTE below! */
156
record in a clustered index. */
177
ulint type, /*!< in: ROW_COPY_POINTERS or
161
/* out, own: row built;
162
see the NOTE below! */
163
ulint type, /* in: ROW_COPY_POINTERS or
178
164
ROW_COPY_DATA; the latter
179
165
copies also the data fields to
180
166
heap while the first only
181
167
places pointers to data fields
182
168
on the index page, and thus is
183
169
more efficient */
184
const dict_index_t* index, /*!< in: clustered index */
185
const rec_t* rec, /*!< in: record in the clustered
170
const dict_index_t* index, /* in: clustered index */
171
const rec_t* rec, /* in: record in the clustered
186
172
index; NOTE: in the case
187
173
ROW_COPY_POINTERS the data
188
174
fields in the row will point
191
177
this record must be at least
192
178
s-latched and the latch held
193
179
as long as the row dtuple is used! */
194
const ulint* offsets,/*!< in: rec_get_offsets(rec,index)
180
const ulint* offsets,/* in: rec_get_offsets(rec,index)
195
181
or NULL, in which case this function
196
182
will invoke rec_get_offsets() */
197
183
const dict_table_t* col_table,
198
/*!< in: table, to check which
184
/* in: table, to check which
199
185
externally stored columns
200
186
occur in the ordering columns
201
187
of an index, or NULL if
202
188
index->table should be
203
189
consulted instead */
204
row_ext_t** ext, /*!< out, own: cache of
190
row_ext_t** ext, /* out, own: cache of
205
191
externally stored column
206
192
prefixes, or NULL */
207
mem_heap_t* heap) /*!< in: memory heap from which
193
mem_heap_t* heap) /* in: memory heap from which
208
194
the memory needed is allocated */
234
220
if (type != ROW_COPY_POINTERS) {
235
221
/* Take a copy of rec to heap */
236
buf = static_cast<byte *>(mem_heap_alloc(heap, rec_offs_size(offsets)));
222
buf = mem_heap_alloc(heap, rec_offs_size(offsets));
237
223
rec = rec_copy(buf, rec, offsets);
238
224
/* Avoid a debug assertion in rec_offs_validate(). */
239
225
rec_offs_make_valid(rec, index, (ulint*) offsets);
295
281
ut_ad(dtuple_check_typed(row));
298
/* REDUNDANT and COMPACT formats store a local
299
768-byte prefix of each externally stored
300
column. No cache is needed. */
301
ut_ad(dict_table_get_format(index->table)
302
< DICT_TF_FORMAT_ZIP);
304
284
*ext = row_ext_create(j, ext_cols, row,
305
285
dict_table_zip_size(index->table),
318
/*******************************************************************//**
319
Converts an index record to a typed data tuple.
320
@return index entry built; does not set info_bits, and the data fields
321
in the entry will point directly to rec */
298
/***********************************************************************
299
Converts an index record to a typed data tuple. */
324
302
row_rec_to_index_entry_low(
325
303
/*=======================*/
326
const rec_t* rec, /*!< in: record in the index */
327
const dict_index_t* index, /*!< in: index */
328
const ulint* offsets,/*!< in: rec_get_offsets(rec, index) */
329
ulint* n_ext, /*!< out: number of externally
304
/* out: index entry built; does not
305
set info_bits, and the data fields in
306
the entry will point directly to rec */
307
const rec_t* rec, /* in: record in the index */
308
const dict_index_t* index, /* in: index */
309
const ulint* offsets,/* in: rec_get_offsets(rec, index) */
310
ulint* n_ext, /* out: number of externally
330
311
stored columns */
331
mem_heap_t* heap) /*!< in: memory heap from which
312
mem_heap_t* heap) /* in: memory heap from which
332
313
the memory needed is allocated */
376
/*******************************************************************//**
357
/***********************************************************************
377
358
Converts an index record to a typed data tuple. NOTE that externally
378
stored (often big) fields are NOT copied to heap.
379
@return own: index entry built; see the NOTE below! */
359
stored (often big) fields are NOT copied to heap. */
382
362
row_rec_to_index_entry(
383
363
/*===================*/
384
ulint type, /*!< in: ROW_COPY_DATA, or
364
/* out, own: index entry
365
built; see the NOTE below! */
366
ulint type, /* in: ROW_COPY_DATA, or
385
367
ROW_COPY_POINTERS: the former
386
368
copies also the data fields to
387
369
heap as the latter only places
388
370
pointers to data fields on the
390
const rec_t* rec, /*!< in: record in the index;
372
const rec_t* rec, /* in: record in the index;
391
373
NOTE: in the case
392
374
ROW_COPY_POINTERS the data
393
375
fields in the row will point
396
378
this record must be at least
397
379
s-latched and the latch held
398
380
as long as the dtuple is used! */
399
const dict_index_t* index, /*!< in: index */
400
ulint* offsets,/*!< in/out: rec_get_offsets(rec) */
401
ulint* n_ext, /*!< out: number of externally
381
const dict_index_t* index, /* in: index */
382
ulint* offsets,/* in/out: rec_get_offsets(rec) */
383
ulint* n_ext, /* out: number of externally
402
384
stored columns */
403
mem_heap_t* heap) /*!< in: memory heap from which
385
mem_heap_t* heap) /* in: memory heap from which
404
386
the memory needed is allocated */
412
394
if (type == ROW_COPY_DATA) {
413
395
/* Take a copy of rec to heap */
414
buf = static_cast<byte *>(mem_heap_alloc(heap, rec_offs_size(offsets)));
396
buf = mem_heap_alloc(heap, rec_offs_size(offsets));
415
397
rec = rec_copy(buf, rec, offsets);
416
398
/* Avoid a debug assertion in rec_offs_validate(). */
417
399
rec_offs_make_valid(rec, index, offsets);
428
/*******************************************************************//**
410
/***********************************************************************
429
411
Builds from a secondary index record a row reference with which we can
430
search the clustered index record.
431
@return own: row reference built; see the NOTE below! */
412
search the clustered index record. */
434
415
row_build_row_ref(
435
416
/*==============*/
436
ulint type, /*!< in: ROW_COPY_DATA, or ROW_COPY_POINTERS:
417
/* out, own: row reference built; see the
419
ulint type, /* in: ROW_COPY_DATA, or ROW_COPY_POINTERS:
437
420
the former copies also the data fields to
438
421
heap, whereas the latter only places pointers
439
422
to data fields on the index page */
440
dict_index_t* index, /*!< in: secondary index */
441
const rec_t* rec, /*!< in: record in the index;
423
dict_index_t* index, /* in: secondary index */
424
const rec_t* rec, /* in: record in the index;
442
425
NOTE: in the case ROW_COPY_POINTERS
443
426
the data fields in the row will point
444
427
directly into this record, therefore,
445
428
the buffer page of this record must be
446
429
at least s-latched and the latch held
447
430
as long as the row reference is used! */
448
mem_heap_t* heap) /*!< in: memory heap from which the memory
431
mem_heap_t* heap) /* in: memory heap from which the memory
449
432
needed is allocated */
451
434
dict_table_t* table;
538
/*******************************************************************//**
522
/***********************************************************************
539
523
Builds from a secondary index record a row reference with which we can
540
524
search the clustered index record. */
543
527
row_build_row_ref_in_tuple(
544
528
/*=======================*/
545
dtuple_t* ref, /*!< in/out: row reference built;
529
dtuple_t* ref, /* in/out: row reference built;
546
530
see the NOTE below! */
547
const rec_t* rec, /*!< in: record in the index;
531
const rec_t* rec, /* in: record in the index;
548
532
NOTE: the data fields in ref
549
533
will point directly into this
550
534
record, therefore, the buffer
552
536
least s-latched and the latch
553
537
held as long as the row
554
538
reference is used! */
555
const dict_index_t* index, /*!< in: secondary index */
556
ulint* offsets,/*!< in: rec_get_offsets(rec, index)
539
const dict_index_t* index, /* in: secondary index */
540
ulint* offsets,/* in: rec_get_offsets(rec, index)
558
trx_t* trx) /*!< in: transaction */
542
trx_t* trx) /* in: transaction */
560
544
const dict_index_t* clust_index;
561
545
dfield_t* dfield;
650
/***************************************************************//**
651
Searches the clustered index record for a row, if we have the row reference.
652
@return TRUE if found */
635
/***********************************************************************
636
From a row build a row reference with which we can search the clustered
640
row_build_row_ref_from_row(
641
/*=======================*/
642
dtuple_t* ref, /* in/out: row reference built;
644
ref must have the right number
646
const dict_table_t* table, /* in: table */
647
const dtuple_t* row) /* in: row
648
NOTE: the data fields in ref will point
649
directly into data of this row */
651
const dict_index_t* clust_index;
655
ut_ad(ref && table && row);
657
clust_index = dict_table_get_first_index(table);
659
ref_len = dict_index_get_n_unique(clust_index);
661
ut_ad(ref_len == dtuple_get_n_fields(ref));
663
for (i = 0; i < ref_len; i++) {
664
const dict_col_t* col;
665
const dict_field_t* field;
667
const dfield_t* dfield2;
669
dfield = dtuple_get_nth_field(ref, i);
671
field = dict_index_get_nth_field(clust_index, i);
673
col = dict_field_get_col(field);
675
dfield2 = dtuple_get_nth_field(row, dict_col_get_no(col));
677
dfield_copy(dfield, dfield2);
678
ut_ad(!dfield_is_ext(dfield));
680
if (field->prefix_len > 0 && !dfield_is_null(dfield)) {
682
ulint len = dfield_get_len(dfield);
684
len = dtype_get_at_most_n_mbchars(
685
col->prtype, col->mbminlen, col->mbmaxlen,
687
len, dfield_get_data(dfield));
689
dfield_set_len(dfield, len);
693
ut_ad(dtuple_check_typed(ref));
696
/*******************************************************************
697
Searches the clustered index record for a row, if we have the row reference. */
655
700
row_search_on_row_ref(
656
701
/*==================*/
657
btr_pcur_t* pcur, /*!< out: persistent cursor, which must
702
/* out: TRUE if found */
703
btr_pcur_t* pcur, /* out: persistent cursor, which must
658
704
be closed by the caller */
659
ulint mode, /*!< in: BTR_MODIFY_LEAF, ... */
660
const dict_table_t* table, /*!< in: table */
661
const dtuple_t* ref, /*!< in: row reference */
662
mtr_t* mtr) /*!< in/out: mtr */
705
ulint mode, /* in: BTR_MODIFY_LEAF, ... */
706
const dict_table_t* table, /* in: table */
707
const dtuple_t* ref, /* in: row reference */
708
mtr_t* mtr) /* in/out: mtr */
693
/*********************************************************************//**
739
/*************************************************************************
694
740
Fetches the clustered index record for a secondary index record. The latches
695
on the secondary index record are preserved.
696
@return record or NULL, if no record found */
741
on the secondary index record are preserved. */
699
744
row_get_clust_rec(
700
745
/*==============*/
701
ulint mode, /*!< in: BTR_MODIFY_LEAF, ... */
702
const rec_t* rec, /*!< in: record in a secondary index */
703
dict_index_t* index, /*!< in: secondary index */
704
dict_index_t** clust_index,/*!< out: clustered index */
705
mtr_t* mtr) /*!< in: mtr */
746
/* out: record or NULL, if no record found */
747
ulint mode, /* in: BTR_MODIFY_LEAF, ... */
748
const rec_t* rec, /* in: record in a secondary index */
749
dict_index_t* index, /* in: secondary index */
750
dict_index_t** clust_index,/* out: clustered index */
751
mtr_t* mtr) /* in: mtr */
707
753
mem_heap_t* heap;
732
778
return(clust_rec);
735
/***************************************************************//**
736
Searches an index record.
737
@return whether the record was found or buffered */
781
/*******************************************************************
782
Searches an index record. */
739
enum row_search_result
740
785
row_search_index_entry(
741
786
/*===================*/
742
dict_index_t* index, /*!< in: index */
743
const dtuple_t* entry, /*!< in: index entry */
744
ulint mode, /*!< in: BTR_MODIFY_LEAF, ... */
745
btr_pcur_t* pcur, /*!< in/out: persistent cursor, which must
787
/* out: TRUE if found */
788
dict_index_t* index, /* in: index */
789
const dtuple_t* entry, /* in: index entry */
790
ulint mode, /* in: BTR_MODIFY_LEAF, ... */
791
btr_pcur_t* pcur, /* in/out: persistent cursor, which must
746
792
be closed by the caller */
747
mtr_t* mtr) /*!< in: mtr */
793
mtr_t* mtr) /* in: mtr */
753
799
ut_ad(dtuple_check_typed(entry));
755
801
btr_pcur_open(index, entry, PAGE_CUR_LE, mode, pcur, mtr);
757
switch (btr_pcur_get_btr_cur(pcur)->flag) {
758
case BTR_CUR_DELETE_REF:
759
ut_a(mode & BTR_DELETE);
760
return(ROW_NOT_DELETED_REF);
762
case BTR_CUR_DEL_MARK_IBUF:
763
case BTR_CUR_DELETE_IBUF:
764
case BTR_CUR_INSERT_TO_IBUF:
765
return(ROW_BUFFERED);
768
case BTR_CUR_HASH_FAIL:
773
802
low_match = btr_pcur_get_low_match(pcur);
775
804
rec = btr_pcur_get_rec(pcur);
777
806
n_fields = dtuple_get_n_fields(entry);
779
if (page_rec_is_infimum(rec)) {
781
return(ROW_NOT_FOUND);
782
} else if (low_match != n_fields) {
784
return(ROW_NOT_FOUND);
808
return(!page_rec_is_infimum(rec) && low_match == n_fields);
790
#if !defined(BUILD_DRIZZLE)
811
#ifndef UNIV_HOTBACKUP
813
#if defined(BUILD_DRIZZLE)
814
# include <mysys/my_sys.h>
795
/*******************************************************************//**
819
/***********************************************************************
796
820
Formats the raw data in "data" (in InnoDB on-disk format) that is of
797
821
type DATA_INT using "prtype" and writes the result to "buf".
798
822
If the data is in unknown format, then nothing is written to "buf",
801
825
Not more than "buf_size" bytes are written to "buf".
802
826
The result is always '\0'-terminated (provided buf_size > 0) and the
803
827
number of bytes that were written to "buf" is returned (including the
805
@return number of bytes that were written */
828
terminating '\0'). */
808
831
row_raw_format_int(
809
832
/*===============*/
810
const char* data, /*!< in: raw data */
811
ulint data_len, /*!< in: raw data length
813
ulint prtype, /*!< in: precise type */
814
char* buf, /*!< out: output buffer */
815
ulint buf_size, /*!< in: output buffer size
817
ibool* format_in_hex) /*!< out: should the data be
833
/* out: number of bytes
835
const char* data, /* in: raw data */
836
ulint data_len, /* in: raw data length
838
ulint prtype, /* in: precise type */
839
char* buf, /* out: output buffer */
840
ulint buf_size, /* in: output buffer size
842
ibool* format_in_hex) /* out: should the data be
818
843
formated in hex */
856
881
Not more than "buf_size" bytes are written to "buf".
857
882
The result is always '\0'-terminated (provided buf_size > 0) and the
858
883
number of bytes that were written to "buf" is returned (including the
860
@return number of bytes that were written */
884
terminating '\0'). */
863
887
row_raw_format_str(
864
888
/*===============*/
865
const char* data, /*!< in: raw data */
866
ulint data_len, /*!< in: raw data length
868
ulint prtype, /*!< in: precise type */
869
char* buf, /*!< out: output buffer */
870
ulint buf_size, /*!< in: output buffer size
872
ibool* format_in_hex) /*!< out: should the data be
889
/* out: number of bytes
891
const char* data, /* in: raw data */
892
ulint data_len, /* in: raw data length
894
ulint prtype, /* in: precise type */
895
char* buf, /* out: output buffer */
896
ulint buf_size, /* in: output buffer size
898
ibool* format_in_hex) /* out: should the data be
873
899
formated in hex */
875
901
ulint charset_coll;
903
/*******************************************************************//**
929
/***********************************************************************
904
930
Formats the raw data in "data" (in InnoDB on-disk format) using
905
931
"dict_field" and writes the result to "buf".
906
932
Not more than "buf_size" bytes are written to "buf".
907
The result is always NUL-terminated (provided buf_size is positive) and the
933
The result is always '\0'-terminated (provided buf_size > 0) and the
908
934
number of bytes that were written to "buf" is returned (including the
910
@return number of bytes that were written */
935
terminating '\0'). */
915
const char* data, /*!< in: raw data */
916
ulint data_len, /*!< in: raw data length
940
/* out: number of bytes
942
const char* data, /* in: raw data */
943
ulint data_len, /* in: raw data length
918
const dict_field_t* dict_field, /*!< in: index field */
919
char* buf, /*!< out: output buffer */
920
ulint buf_size) /*!< in: output buffer size
945
const dict_field_t* dict_field, /* in: index field */
946
char* buf, /* out: output buffer */
947
ulint buf_size) /* in: output buffer size
926
953
ibool format_in_hex;
928
955
if (buf_size == 0) {
933
960
if (data_len == UNIV_SQL_NULL) {