11
11
FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
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
17
17
*****************************************************************************/
19
/**************************************************//**
19
/******************************************************
21
20
General row routines
23
22
Created 4/20/1996 Heikki Tuuri
47
46
#include "read0read.h"
48
47
#include "ut0mem.h"
50
/*********************************************************************//**
49
/*************************************************************************
51
50
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 */
51
a clustered index record. */
56
54
row_get_trx_id_offset(
57
55
/*==================*/
56
/* out: offset of DATA_TRX_ID */
58
57
const rec_t* rec __attribute__((unused)),
60
dict_index_t* index, /*!< in: clustered index */
61
const ulint* offsets)/*!< in: rec_get_offsets(rec, index) */
59
dict_index_t* index, /* in: clustered index */
60
const ulint* offsets)/* in: rec_get_offsets(rec, index) */
79
/*****************************************************************//**
78
/*********************************************************************
80
79
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 */
80
the entry to be inserted into or purged from an index on the table. */
87
83
row_build_index_entry(
88
84
/*==================*/
89
const dtuple_t* row, /*!< in: row which should be
85
/* out: index entry which should be
86
inserted or purged, or NULL if the
87
externally stored columns in the
88
clustered index record are unavailable
90
const dtuple_t* row, /* in: row which should be
90
91
inserted or purged */
91
row_ext_t* ext, /*!< in: externally stored column prefixes,
92
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
94
dict_index_t* index, /* in: index on the table */
95
mem_heap_t* heap) /* in: memory heap from which the memory for
95
96
the index entry is allocated */
158
159
len = dtype_get_at_most_n_mbchars(
159
col->prtype, col->mbminmaxlen,
160
col->prtype, col->mbminlen, col->mbmaxlen,
160
161
ind_field->prefix_len, len, dfield_get_data(dfield));
161
162
dfield_set_len(dfield, len);
169
/*******************************************************************//**
170
/***********************************************************************
170
171
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! */
172
record in a clustered index. */
177
ulint type, /*!< in: ROW_COPY_POINTERS or
177
/* out, own: row built;
178
see the NOTE below! */
179
ulint type, /* in: ROW_COPY_POINTERS or
178
180
ROW_COPY_DATA; the latter
179
181
copies also the data fields to
180
182
heap while the first only
181
183
places pointers to data fields
182
184
on the index page, and thus is
183
185
more efficient */
184
const dict_index_t* index, /*!< in: clustered index */
185
const rec_t* rec, /*!< in: record in the clustered
186
const dict_index_t* index, /* in: clustered index */
187
const rec_t* rec, /* in: record in the clustered
186
188
index; NOTE: in the case
187
189
ROW_COPY_POINTERS the data
188
190
fields in the row will point
191
193
this record must be at least
192
194
s-latched and the latch held
193
195
as long as the row dtuple is used! */
194
const ulint* offsets,/*!< in: rec_get_offsets(rec,index)
196
const ulint* offsets,/* in: rec_get_offsets(rec,index)
195
197
or NULL, in which case this function
196
198
will invoke rec_get_offsets() */
197
199
const dict_table_t* col_table,
198
/*!< in: table, to check which
200
/* in: table, to check which
199
201
externally stored columns
200
202
occur in the ordering columns
201
203
of an index, or NULL if
202
204
index->table should be
203
205
consulted instead */
204
row_ext_t** ext, /*!< out, own: cache of
206
row_ext_t** ext, /* out, own: cache of
205
207
externally stored column
206
208
prefixes, or NULL */
207
mem_heap_t* heap) /*!< in: memory heap from which
209
mem_heap_t* heap) /* in: memory heap from which
208
210
the memory needed is allocated */
295
297
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
300
*ext = row_ext_create(j, ext_cols, row,
305
301
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 */
314
/***********************************************************************
315
Converts an index record to a typed data tuple. */
324
318
row_rec_to_index_entry_low(
325
319
/*=======================*/
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
320
/* out: index entry built; does not
321
set info_bits, and the data fields in
322
the entry will point directly to rec */
323
const rec_t* rec, /* in: record in the index */
324
const dict_index_t* index, /* in: index */
325
const ulint* offsets,/* in: rec_get_offsets(rec, index) */
326
ulint* n_ext, /* out: number of externally
330
327
stored columns */
331
mem_heap_t* heap) /*!< in: memory heap from which
328
mem_heap_t* heap) /* in: memory heap from which
332
329
the memory needed is allocated */
376
/*******************************************************************//**
373
/***********************************************************************
377
374
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! */
375
stored (often big) fields are NOT copied to heap. */
382
378
row_rec_to_index_entry(
383
379
/*===================*/
384
ulint type, /*!< in: ROW_COPY_DATA, or
380
/* out, own: index entry
381
built; see the NOTE below! */
382
ulint type, /* in: ROW_COPY_DATA, or
385
383
ROW_COPY_POINTERS: the former
386
384
copies also the data fields to
387
385
heap as the latter only places
388
386
pointers to data fields on the
390
const rec_t* rec, /*!< in: record in the index;
388
const rec_t* rec, /* in: record in the index;
391
389
NOTE: in the case
392
390
ROW_COPY_POINTERS the data
393
391
fields in the row will point
396
394
this record must be at least
397
395
s-latched and the latch held
398
396
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
397
const dict_index_t* index, /* in: index */
398
ulint* offsets,/* in/out: rec_get_offsets(rec) */
399
ulint* n_ext, /* out: number of externally
402
400
stored columns */
403
mem_heap_t* heap) /*!< in: memory heap from which
401
mem_heap_t* heap) /* in: memory heap from which
404
402
the memory needed is allocated */
428
/*******************************************************************//**
426
/***********************************************************************
429
427
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! */
428
search the clustered index record. */
434
431
row_build_row_ref(
435
432
/*==============*/
436
ulint type, /*!< in: ROW_COPY_DATA, or ROW_COPY_POINTERS:
433
/* out, own: row reference built; see the
435
ulint type, /* in: ROW_COPY_DATA, or ROW_COPY_POINTERS:
437
436
the former copies also the data fields to
438
437
heap, whereas the latter only places pointers
439
438
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;
439
dict_index_t* index, /* in: secondary index */
440
const rec_t* rec, /* in: record in the index;
442
441
NOTE: in the case ROW_COPY_POINTERS
443
442
the data fields in the row will point
444
443
directly into this record, therefore,
445
444
the buffer page of this record must be
446
445
at least s-latched and the latch held
447
446
as long as the row reference is used! */
448
mem_heap_t* heap) /*!< in: memory heap from which the memory
447
mem_heap_t* heap) /* in: memory heap from which the memory
449
448
needed is allocated */
451
450
dict_table_t* table;
538
/*******************************************************************//**
538
/***********************************************************************
539
539
Builds from a secondary index record a row reference with which we can
540
540
search the clustered index record. */
543
543
row_build_row_ref_in_tuple(
544
544
/*=======================*/
545
dtuple_t* ref, /*!< in/out: row reference built;
545
dtuple_t* ref, /* in/out: row reference built;
546
546
see the NOTE below! */
547
const rec_t* rec, /*!< in: record in the index;
547
const rec_t* rec, /* in: record in the index;
548
548
NOTE: the data fields in ref
549
549
will point directly into this
550
550
record, therefore, the buffer
552
552
least s-latched and the latch
553
553
held as long as the row
554
554
reference is used! */
555
const dict_index_t* index, /*!< in: secondary index */
556
ulint* offsets,/*!< in: rec_get_offsets(rec, index)
555
const dict_index_t* index, /* in: secondary index */
556
ulint* offsets,/* in: rec_get_offsets(rec, index)
558
trx_t* trx) /*!< in: transaction */
558
trx_t* trx) /* in: transaction */
560
560
const dict_index_t* clust_index;
561
561
dfield_t* dfield;
650
/***************************************************************//**
651
Searches the clustered index record for a row, if we have the row reference.
652
@return TRUE if found */
651
/***********************************************************************
652
From a row build a row reference with which we can search the clustered
656
row_build_row_ref_from_row(
657
/*=======================*/
658
dtuple_t* ref, /* in/out: row reference built;
660
ref must have the right number
662
const dict_table_t* table, /* in: table */
663
const dtuple_t* row) /* in: row
664
NOTE: the data fields in ref will point
665
directly into data of this row */
667
const dict_index_t* clust_index;
671
ut_ad(ref && table && row);
673
clust_index = dict_table_get_first_index(table);
675
ref_len = dict_index_get_n_unique(clust_index);
677
ut_ad(ref_len == dtuple_get_n_fields(ref));
679
for (i = 0; i < ref_len; i++) {
680
const dict_col_t* col;
681
const dict_field_t* field;
683
const dfield_t* dfield2;
685
dfield = dtuple_get_nth_field(ref, i);
687
field = dict_index_get_nth_field(clust_index, i);
689
col = dict_field_get_col(field);
691
dfield2 = dtuple_get_nth_field(row, dict_col_get_no(col));
693
dfield_copy(dfield, dfield2);
694
ut_ad(!dfield_is_ext(dfield));
696
if (field->prefix_len > 0 && !dfield_is_null(dfield)) {
698
ulint len = dfield_get_len(dfield);
700
len = dtype_get_at_most_n_mbchars(
701
col->prtype, col->mbminlen, col->mbmaxlen,
703
len, dfield_get_data(dfield));
705
dfield_set_len(dfield, len);
709
ut_ad(dtuple_check_typed(ref));
712
/*******************************************************************
713
Searches the clustered index record for a row, if we have the row reference. */
655
716
row_search_on_row_ref(
656
717
/*==================*/
657
btr_pcur_t* pcur, /*!< out: persistent cursor, which must
718
/* out: TRUE if found */
719
btr_pcur_t* pcur, /* out: persistent cursor, which must
658
720
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 */
721
ulint mode, /* in: BTR_MODIFY_LEAF, ... */
722
const dict_table_t* table, /* in: table */
723
const dtuple_t* ref, /* in: row reference */
724
mtr_t* mtr) /* in/out: mtr */
693
/*********************************************************************//**
755
/*************************************************************************
694
756
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 */
757
on the secondary index record are preserved. */
699
760
row_get_clust_rec(
700
761
/*==============*/
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 */
762
/* out: record or NULL, if no record found */
763
ulint mode, /* in: BTR_MODIFY_LEAF, ... */
764
const rec_t* rec, /* in: record in a secondary index */
765
dict_index_t* index, /* in: secondary index */
766
dict_index_t** clust_index,/* out: clustered index */
767
mtr_t* mtr) /* in: mtr */
707
769
mem_heap_t* heap;
732
794
return(clust_rec);
735
/***************************************************************//**
736
Searches an index record.
737
@return whether the record was found or buffered */
797
/*******************************************************************
798
Searches an index record. */
739
enum row_search_result
740
801
row_search_index_entry(
741
802
/*===================*/
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
803
/* out: TRUE if found */
804
dict_index_t* index, /* in: index */
805
const dtuple_t* entry, /* in: index entry */
806
ulint mode, /* in: BTR_MODIFY_LEAF, ... */
807
btr_pcur_t* pcur, /* in/out: persistent cursor, which must
746
808
be closed by the caller */
747
mtr_t* mtr) /*!< in: mtr */
809
mtr_t* mtr) /* in: mtr */
753
815
ut_ad(dtuple_check_typed(entry));
755
817
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
818
low_match = btr_pcur_get_low_match(pcur);
775
820
rec = btr_pcur_get_rec(pcur);
777
822
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);
824
return(!page_rec_is_infimum(rec) && low_match == n_fields);
790
#if !defined(BUILD_DRIZZLE)
795
/*******************************************************************//**
827
#ifndef UNIV_HOTBACKUP
831
/***********************************************************************
796
832
Formats the raw data in "data" (in InnoDB on-disk format) that is of
797
833
type DATA_INT using "prtype" and writes the result to "buf".
798
834
If the data is in unknown format, then nothing is written to "buf",
801
837
Not more than "buf_size" bytes are written to "buf".
802
838
The result is always '\0'-terminated (provided buf_size > 0) and the
803
839
number of bytes that were written to "buf" is returned (including the
805
@return number of bytes that were written */
840
terminating '\0'). */
808
843
row_raw_format_int(
809
844
/*===============*/
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
845
/* out: number of bytes
847
const char* data, /* in: raw data */
848
ulint data_len, /* in: raw data length
850
ulint prtype, /* in: precise type */
851
char* buf, /* out: output buffer */
852
ulint buf_size, /* in: output buffer size
854
ibool* format_in_hex) /* out: should the data be
818
855
formated in hex */
856
893
Not more than "buf_size" bytes are written to "buf".
857
894
The result is always '\0'-terminated (provided buf_size > 0) and the
858
895
number of bytes that were written to "buf" is returned (including the
860
@return number of bytes that were written */
896
terminating '\0'). */
863
899
row_raw_format_str(
864
900
/*===============*/
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
901
/* out: number of bytes
903
const char* data, /* in: raw data */
904
ulint data_len, /* in: raw data length
906
ulint prtype, /* in: precise type */
907
char* buf, /* out: output buffer */
908
ulint buf_size, /* in: output buffer size
910
ibool* format_in_hex) /* out: should the data be
873
911
formated in hex */
875
913
ulint charset_coll;
903
/*******************************************************************//**
941
/***********************************************************************
904
942
Formats the raw data in "data" (in InnoDB on-disk format) using
905
943
"dict_field" and writes the result to "buf".
906
944
Not more than "buf_size" bytes are written to "buf".
907
The result is always NUL-terminated (provided buf_size is positive) and the
945
The result is always '\0'-terminated (provided buf_size > 0) and the
908
946
number of bytes that were written to "buf" is returned (including the
910
@return number of bytes that were written */
947
terminating '\0'). */
915
const char* data, /*!< in: raw data */
916
ulint data_len, /*!< in: raw data length
952
/* out: number of bytes
954
const char* data, /* in: raw data */
955
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
957
const dict_field_t* dict_field, /* in: index field */
958
char* buf, /* out: output buffer */
959
ulint buf_size) /* in: output buffer size
926
965
ibool format_in_hex;
928
967
if (buf_size == 0) {
933
972
if (data_len == UNIV_SQL_NULL) {