1
/*****************************************************************************
3
Copyright (c) 1996, 2009, 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., 59 Temple
15
Place, Suite 330, Boston, MA 02111-1307 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
/*==================*/
40
/* out: offset of DATA_TRX_ID */
58
41
const rec_t* rec __attribute__((unused)),
60
dict_index_t* index, /*!< in: clustered index */
61
const ulint* offsets)/*!< in: rec_get_offsets(rec, index) */
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 */
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 */
312
/*******************************************************************//**
313
Converts an index record to a typed data tuple.
314
@return index entry built; does not set info_bits, and the data fields
315
in the entry will point directly to rec */
298
/***********************************************************************
299
Converts an index record to a typed data tuple. */
318
302
row_rec_to_index_entry_low(
319
303
/*=======================*/
320
const rec_t* rec, /*!< in: record in the index */
321
const dict_index_t* index, /*!< in: index */
322
const ulint* offsets,/*!< in: rec_get_offsets(rec, index) */
323
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
324
311
stored columns */
325
mem_heap_t* heap) /*!< in: memory heap from which
312
mem_heap_t* heap) /* in: memory heap from which
326
313
the memory needed is allocated */
370
/*******************************************************************//**
357
/***********************************************************************
371
358
Converts an index record to a typed data tuple. NOTE that externally
372
stored (often big) fields are NOT copied to heap.
373
@return own: index entry built; see the NOTE below! */
359
stored (often big) fields are NOT copied to heap. */
376
362
row_rec_to_index_entry(
377
363
/*===================*/
378
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
379
367
ROW_COPY_POINTERS: the former
380
368
copies also the data fields to
381
369
heap as the latter only places
382
370
pointers to data fields on the
384
const rec_t* rec, /*!< in: record in the index;
372
const rec_t* rec, /* in: record in the index;
385
373
NOTE: in the case
386
374
ROW_COPY_POINTERS the data
387
375
fields in the row will point
390
378
this record must be at least
391
379
s-latched and the latch held
392
380
as long as the dtuple is used! */
393
const dict_index_t* index, /*!< in: index */
394
ulint* offsets,/*!< in/out: rec_get_offsets(rec) */
395
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
396
384
stored columns */
397
mem_heap_t* heap) /*!< in: memory heap from which
385
mem_heap_t* heap) /* in: memory heap from which
398
386
the memory needed is allocated */
422
/*******************************************************************//**
410
/***********************************************************************
423
411
Builds from a secondary index record a row reference with which we can
424
search the clustered index record.
425
@return own: row reference built; see the NOTE below! */
412
search the clustered index record. */
428
415
row_build_row_ref(
429
416
/*==============*/
430
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:
431
420
the former copies also the data fields to
432
421
heap, whereas the latter only places pointers
433
422
to data fields on the index page */
434
dict_index_t* index, /*!< in: secondary index */
435
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;
436
425
NOTE: in the case ROW_COPY_POINTERS
437
426
the data fields in the row will point
438
427
directly into this record, therefore,
439
428
the buffer page of this record must be
440
429
at least s-latched and the latch held
441
430
as long as the row reference is used! */
442
mem_heap_t* heap) /*!< in: memory heap from which the memory
431
mem_heap_t* heap) /* in: memory heap from which the memory
443
432
needed is allocated */
445
434
dict_table_t* table;
533
/*******************************************************************//**
522
/***********************************************************************
534
523
Builds from a secondary index record a row reference with which we can
535
524
search the clustered index record. */
538
527
row_build_row_ref_in_tuple(
539
528
/*=======================*/
540
dtuple_t* ref, /*!< in/out: row reference built;
529
dtuple_t* ref, /* in/out: row reference built;
541
530
see the NOTE below! */
542
const rec_t* rec, /*!< in: record in the index;
531
const rec_t* rec, /* in: record in the index;
543
532
NOTE: the data fields in ref
544
533
will point directly into this
545
534
record, therefore, the buffer
547
536
least s-latched and the latch
548
537
held as long as the row
549
538
reference is used! */
550
const dict_index_t* index, /*!< in: secondary index */
551
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)
553
trx_t* trx) /*!< in: transaction */
542
trx_t* trx) /* in: transaction */
555
544
const dict_index_t* clust_index;
556
545
dfield_t* dfield;
646
/***************************************************************//**
647
Searches the clustered index record for a row, if we have the row reference.
648
@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. */
651
700
row_search_on_row_ref(
652
701
/*==================*/
653
btr_pcur_t* pcur, /*!< out: persistent cursor, which must
702
/* out: TRUE if found */
703
btr_pcur_t* pcur, /* out: persistent cursor, which must
654
704
be closed by the caller */
655
ulint mode, /*!< in: BTR_MODIFY_LEAF, ... */
656
const dict_table_t* table, /*!< in: table */
657
const dtuple_t* ref, /*!< in: row reference */
658
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 */
689
/*********************************************************************//**
739
/*************************************************************************
690
740
Fetches the clustered index record for a secondary index record. The latches
691
on the secondary index record are preserved.
692
@return record or NULL, if no record found */
741
on the secondary index record are preserved. */
695
744
row_get_clust_rec(
696
745
/*==============*/
697
ulint mode, /*!< in: BTR_MODIFY_LEAF, ... */
698
const rec_t* rec, /*!< in: record in a secondary index */
699
dict_index_t* index, /*!< in: secondary index */
700
dict_index_t** clust_index,/*!< out: clustered index */
701
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 */
703
753
mem_heap_t* heap;
728
778
return(clust_rec);
731
/***************************************************************//**
732
Searches an index record.
733
@return TRUE if found */
781
/*******************************************************************
782
Searches an index record. */
736
785
row_search_index_entry(
737
786
/*===================*/
738
dict_index_t* index, /*!< in: index */
739
const dtuple_t* entry, /*!< in: index entry */
740
ulint mode, /*!< in: BTR_MODIFY_LEAF, ... */
741
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
742
792
be closed by the caller */
743
mtr_t* mtr) /*!< in: mtr */
793
mtr_t* mtr) /* in: mtr */
758
808
return(!page_rec_is_infimum(rec) && low_match == n_fields);
761
#if !defined(BUILD_DRIZZLE)
811
#ifndef UNIV_HOTBACKUP
813
#if defined(BUILD_DRIZZLE)
814
# include <mysys/my_sys.h>
766
/*******************************************************************//**
819
/***********************************************************************
767
820
Formats the raw data in "data" (in InnoDB on-disk format) that is of
768
821
type DATA_INT using "prtype" and writes the result to "buf".
769
822
If the data is in unknown format, then nothing is written to "buf",
772
825
Not more than "buf_size" bytes are written to "buf".
773
826
The result is always '\0'-terminated (provided buf_size > 0) and the
774
827
number of bytes that were written to "buf" is returned (including the
776
@return number of bytes that were written */
828
terminating '\0'). */
779
831
row_raw_format_int(
780
832
/*===============*/
781
const char* data, /*!< in: raw data */
782
ulint data_len, /*!< in: raw data length
784
ulint prtype, /*!< in: precise type */
785
char* buf, /*!< out: output buffer */
786
ulint buf_size, /*!< in: output buffer size
788
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
789
843
formated in hex */
827
881
Not more than "buf_size" bytes are written to "buf".
828
882
The result is always '\0'-terminated (provided buf_size > 0) and the
829
883
number of bytes that were written to "buf" is returned (including the
831
@return number of bytes that were written */
884
terminating '\0'). */
834
887
row_raw_format_str(
835
888
/*===============*/
836
const char* data, /*!< in: raw data */
837
ulint data_len, /*!< in: raw data length
839
ulint prtype, /*!< in: precise type */
840
char* buf, /*!< out: output buffer */
841
ulint buf_size, /*!< in: output buffer size
843
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
844
899
formated in hex */
846
901
ulint charset_coll;
874
/*******************************************************************//**
929
/***********************************************************************
875
930
Formats the raw data in "data" (in InnoDB on-disk format) using
876
931
"dict_field" and writes the result to "buf".
877
932
Not more than "buf_size" bytes are written to "buf".
878
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
879
934
number of bytes that were written to "buf" is returned (including the
881
@return number of bytes that were written */
935
terminating '\0'). */
886
const char* data, /*!< in: raw data */
887
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
889
const dict_field_t* dict_field, /*!< in: index field */
890
char* buf, /*!< out: output buffer */
891
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
897
953
ibool format_in_hex;
899
955
if (buf_size == 0) {
904
960
if (data_len == UNIV_SQL_NULL) {