1 | /***************************************************************************** |
2 | |
3 | Copyright (c) 1994, 2016, Oracle and/or its affiliates. All Rights Reserved. |
4 | Copyright (c) 2017, MariaDB Corporation. |
5 | |
6 | This program is free software; you can redistribute it and/or modify it under |
7 | the terms of the GNU General Public License as published by the Free Software |
8 | Foundation; version 2 of the License. |
9 | |
10 | This program is distributed in the hope that it will be useful, but WITHOUT |
11 | ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS |
12 | FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. |
13 | |
14 | You should have received a copy of the GNU General Public License along with |
15 | this program; if not, write to the Free Software Foundation, Inc., |
16 | 51 Franklin Street, Suite 500, Boston, MA 02110-1335 USA |
17 | |
18 | *****************************************************************************/ |
19 | |
20 | /********************************************************************//** |
21 | @file include/data0data.h |
22 | SQL data field and tuple |
23 | |
24 | Created 5/30/1994 Heikki Tuuri |
25 | *************************************************************************/ |
26 | |
27 | #ifndef data0data_h |
28 | #define data0data_h |
29 | |
30 | #include "univ.i" |
31 | |
32 | #include "data0types.h" |
33 | #include "data0type.h" |
34 | #include "mem0mem.h" |
35 | #include "dict0types.h" |
36 | |
37 | #include <ostream> |
38 | |
39 | /** Storage for overflow data in a big record, that is, a clustered |
40 | index record which needs external storage of data fields */ |
41 | struct big_rec_t; |
42 | struct upd_t; |
43 | |
44 | #ifdef UNIV_DEBUG |
45 | /*********************************************************************//** |
46 | Gets pointer to the type struct of SQL data field. |
47 | @return pointer to the type struct */ |
48 | UNIV_INLINE |
49 | dtype_t* |
50 | dfield_get_type( |
51 | /*============*/ |
52 | const dfield_t* field) /*!< in: SQL data field */ |
53 | MY_ATTRIBUTE((nonnull, warn_unused_result)); |
54 | /*********************************************************************//** |
55 | Gets pointer to the data in a field. |
56 | @return pointer to data */ |
57 | UNIV_INLINE |
58 | void* |
59 | dfield_get_data( |
60 | /*============*/ |
61 | const dfield_t* field) /*!< in: field */ |
62 | MY_ATTRIBUTE((nonnull, warn_unused_result)); |
63 | #else /* UNIV_DEBUG */ |
64 | # define dfield_get_type(field) (&(field)->type) |
65 | # define dfield_get_data(field) ((field)->data) |
66 | #endif /* UNIV_DEBUG */ |
67 | /*********************************************************************//** |
68 | Sets the type struct of SQL data field. */ |
69 | UNIV_INLINE |
70 | void |
71 | dfield_set_type( |
72 | /*============*/ |
73 | dfield_t* field, /*!< in: SQL data field */ |
74 | const dtype_t* type); /*!< in: pointer to data type struct */ |
75 | |
76 | /*********************************************************************//** |
77 | Gets length of field data. |
78 | @return length of data; UNIV_SQL_NULL if SQL null data */ |
79 | UNIV_INLINE |
80 | ulint |
81 | dfield_get_len( |
82 | /*===========*/ |
83 | const dfield_t* field) /*!< in: field */ |
84 | MY_ATTRIBUTE((nonnull, warn_unused_result)); |
85 | /*********************************************************************//** |
86 | Sets length in a field. */ |
87 | UNIV_INLINE |
88 | void |
89 | dfield_set_len( |
90 | /*===========*/ |
91 | dfield_t* field, /*!< in: field */ |
92 | ulint len) /*!< in: length or UNIV_SQL_NULL */ |
93 | MY_ATTRIBUTE((nonnull)); |
94 | /*********************************************************************//** |
95 | Determines if a field is SQL NULL |
96 | @return nonzero if SQL null data */ |
97 | UNIV_INLINE |
98 | ulint |
99 | dfield_is_null( |
100 | /*===========*/ |
101 | const dfield_t* field) /*!< in: field */ |
102 | MY_ATTRIBUTE((nonnull, warn_unused_result)); |
103 | /*********************************************************************//** |
104 | Determines if a field is externally stored |
105 | @return nonzero if externally stored */ |
106 | UNIV_INLINE |
107 | ulint |
108 | dfield_is_ext( |
109 | /*==========*/ |
110 | const dfield_t* field) /*!< in: field */ |
111 | MY_ATTRIBUTE((nonnull, warn_unused_result)); |
112 | /*********************************************************************//** |
113 | Sets the "external storage" flag */ |
114 | UNIV_INLINE |
115 | void |
116 | dfield_set_ext( |
117 | /*===========*/ |
118 | dfield_t* field) /*!< in/out: field */ |
119 | MY_ATTRIBUTE((nonnull)); |
120 | |
121 | /** Gets spatial status for "external storage" |
122 | @param[in,out] field field */ |
123 | UNIV_INLINE |
124 | spatial_status_t |
125 | dfield_get_spatial_status( |
126 | const dfield_t* field); |
127 | |
128 | /** Sets spatial status for "external storage" |
129 | @param[in,out] field field |
130 | @param[in] spatial_status spatial status */ |
131 | UNIV_INLINE |
132 | void |
133 | dfield_set_spatial_status( |
134 | dfield_t* field, |
135 | spatial_status_t spatial_status); |
136 | |
137 | /*********************************************************************//** |
138 | Sets pointer to the data and length in a field. */ |
139 | UNIV_INLINE |
140 | void |
141 | dfield_set_data( |
142 | /*============*/ |
143 | dfield_t* field, /*!< in: field */ |
144 | const void* data, /*!< in: data */ |
145 | ulint len) /*!< in: length or UNIV_SQL_NULL */ |
146 | MY_ATTRIBUTE((nonnull(1))); |
147 | /*********************************************************************//** |
148 | Sets pointer to the data and length in a field. */ |
149 | UNIV_INLINE |
150 | void |
151 | dfield_write_mbr( |
152 | /*=============*/ |
153 | dfield_t* field, /*!< in: field */ |
154 | const double* mbr) /*!< in: data */ |
155 | MY_ATTRIBUTE((nonnull(1))); |
156 | /*********************************************************************//** |
157 | Sets a data field to SQL NULL. */ |
158 | UNIV_INLINE |
159 | void |
160 | dfield_set_null( |
161 | /*============*/ |
162 | dfield_t* field) /*!< in/out: field */ |
163 | MY_ATTRIBUTE((nonnull)); |
164 | /**********************************************************************//** |
165 | Writes an SQL null field full of zeros. */ |
166 | UNIV_INLINE |
167 | void |
168 | data_write_sql_null( |
169 | /*================*/ |
170 | byte* data, /*!< in: pointer to a buffer of size len */ |
171 | ulint len) /*!< in: SQL null size in bytes */ |
172 | MY_ATTRIBUTE((nonnull)); |
173 | /*********************************************************************//** |
174 | Copies the data and len fields. */ |
175 | UNIV_INLINE |
176 | void |
177 | dfield_copy_data( |
178 | /*=============*/ |
179 | dfield_t* field1, /*!< out: field to copy to */ |
180 | const dfield_t* field2); /*!< in: field to copy from */ |
181 | |
182 | /*********************************************************************//** |
183 | Copies a data field to another. */ |
184 | UNIV_INLINE |
185 | void |
186 | dfield_copy( |
187 | /*========*/ |
188 | dfield_t* field1, /*!< out: field to copy to */ |
189 | const dfield_t* field2) /*!< in: field to copy from */ |
190 | MY_ATTRIBUTE((nonnull)); |
191 | /*********************************************************************//** |
192 | Copies the data pointed to by a data field. */ |
193 | UNIV_INLINE |
194 | void |
195 | dfield_dup( |
196 | /*=======*/ |
197 | dfield_t* field, /*!< in/out: data field */ |
198 | mem_heap_t* heap) /*!< in: memory heap where allocated */ |
199 | MY_ATTRIBUTE((nonnull)); |
200 | |
201 | /*********************************************************************//** |
202 | Tests if two data fields are equal. |
203 | If len==0, tests the data length and content for equality. |
204 | If len>0, tests the first len bytes of the content for equality. |
205 | @return TRUE if both fields are NULL or if they are equal */ |
206 | UNIV_INLINE |
207 | ibool |
208 | dfield_datas_are_binary_equal( |
209 | /*==========================*/ |
210 | const dfield_t* field1, /*!< in: field */ |
211 | const dfield_t* field2, /*!< in: field */ |
212 | ulint len) /*!< in: maximum prefix to compare, |
213 | or 0 to compare the whole field length */ |
214 | MY_ATTRIBUTE((nonnull, warn_unused_result)); |
215 | /*********************************************************************//** |
216 | Tests if dfield data length and content is equal to the given. |
217 | @return TRUE if equal */ |
218 | UNIV_INLINE |
219 | ibool |
220 | dfield_data_is_binary_equal( |
221 | /*========================*/ |
222 | const dfield_t* field, /*!< in: field */ |
223 | ulint len, /*!< in: data length or UNIV_SQL_NULL */ |
224 | const byte* data) /*!< in: data */ |
225 | MY_ATTRIBUTE((nonnull, warn_unused_result)); |
226 | /*********************************************************************//** |
227 | Gets number of fields in a data tuple. |
228 | @return number of fields */ |
229 | UNIV_INLINE |
230 | ulint |
231 | dtuple_get_n_fields( |
232 | /*================*/ |
233 | const dtuple_t* tuple) /*!< in: tuple */ |
234 | MY_ATTRIBUTE((nonnull, warn_unused_result)); |
235 | /** Gets number of virtual fields in a data tuple. |
236 | @param[in] tuple dtuple to check |
237 | @return number of fields */ |
238 | UNIV_INLINE |
239 | ulint |
240 | dtuple_get_n_v_fields( |
241 | const dtuple_t* tuple); |
242 | |
243 | #ifdef UNIV_DEBUG |
244 | /** Gets nth field of a tuple. |
245 | @param[in] tuple tuple |
246 | @param[in] n index of field |
247 | @return nth field */ |
248 | UNIV_INLINE |
249 | dfield_t* |
250 | dtuple_get_nth_field( |
251 | const dtuple_t* tuple, |
252 | ulint n); |
253 | /** Gets nth virtual field of a tuple. |
254 | @param[in] tuple tuple |
255 | @oaran[in] n the nth field to get |
256 | @return nth field */ |
257 | UNIV_INLINE |
258 | dfield_t* |
259 | dtuple_get_nth_v_field( |
260 | const dtuple_t* tuple, |
261 | ulint n); |
262 | #else /* UNIV_DEBUG */ |
263 | # define dtuple_get_nth_field(tuple, n) ((tuple)->fields + (n)) |
264 | # define dtuple_get_nth_v_field(tuple, n) ((tuple)->fields + (tuple)->n_fields + (n)) |
265 | #endif /* UNIV_DEBUG */ |
266 | /*********************************************************************//** |
267 | Gets info bits in a data tuple. |
268 | @return info bits */ |
269 | UNIV_INLINE |
270 | ulint |
271 | dtuple_get_info_bits( |
272 | /*=================*/ |
273 | const dtuple_t* tuple) /*!< in: tuple */ |
274 | MY_ATTRIBUTE((nonnull, warn_unused_result)); |
275 | /*********************************************************************//** |
276 | Sets info bits in a data tuple. */ |
277 | UNIV_INLINE |
278 | void |
279 | dtuple_set_info_bits( |
280 | /*=================*/ |
281 | dtuple_t* tuple, /*!< in: tuple */ |
282 | ulint info_bits) /*!< in: info bits */ |
283 | MY_ATTRIBUTE((nonnull)); |
284 | /*********************************************************************//** |
285 | Gets number of fields used in record comparisons. |
286 | @return number of fields used in comparisons in rem0cmp.* */ |
287 | UNIV_INLINE |
288 | ulint |
289 | dtuple_get_n_fields_cmp( |
290 | /*====================*/ |
291 | const dtuple_t* tuple) /*!< in: tuple */ |
292 | MY_ATTRIBUTE((nonnull, warn_unused_result)); |
293 | /*********************************************************************//** |
294 | Gets number of fields used in record comparisons. */ |
295 | UNIV_INLINE |
296 | void |
297 | dtuple_set_n_fields_cmp( |
298 | /*====================*/ |
299 | dtuple_t* tuple, /*!< in: tuple */ |
300 | ulint n_fields_cmp) /*!< in: number of fields used in |
301 | comparisons in rem0cmp.* */ |
302 | MY_ATTRIBUTE((nonnull)); |
303 | |
304 | /* Estimate the number of bytes that are going to be allocated when |
305 | creating a new dtuple_t object */ |
306 | #define DTUPLE_EST_ALLOC(n_fields) \ |
307 | (sizeof(dtuple_t) + (n_fields) * sizeof(dfield_t)) |
308 | |
309 | /** Creates a data tuple from an already allocated chunk of memory. |
310 | The size of the chunk must be at least DTUPLE_EST_ALLOC(n_fields). |
311 | The default value for number of fields used in record comparisons |
312 | for this tuple is n_fields. |
313 | @param[in,out] buf buffer to use |
314 | @param[in] buf_size buffer size |
315 | @param[in] n_fields number of field |
316 | @param[in] n_v_fields number of fields on virtual columns |
317 | @return created tuple (inside buf) */ |
318 | UNIV_INLINE |
319 | dtuple_t* |
320 | dtuple_create_from_mem( |
321 | void* buf, |
322 | ulint buf_size, |
323 | ulint n_fields, |
324 | ulint n_v_fields) |
325 | MY_ATTRIBUTE((nonnull, warn_unused_result)); |
326 | |
327 | /**********************************************************//** |
328 | Creates a data tuple to a memory heap. The default value for number |
329 | of fields used in record comparisons for this tuple is n_fields. |
330 | @return own: created tuple */ |
331 | UNIV_INLINE |
332 | dtuple_t* |
333 | dtuple_create( |
334 | /*==========*/ |
335 | mem_heap_t* heap, /*!< in: memory heap where the tuple |
336 | is created, DTUPLE_EST_ALLOC(n_fields) |
337 | bytes will be allocated from this heap */ |
338 | ulint n_fields)/*!< in: number of fields */ |
339 | MY_ATTRIBUTE((nonnull, malloc)); |
340 | |
341 | /** Initialize the virtual field data in a dtuple_t |
342 | @param[in,out] vrow dtuple contains the virtual fields */ |
343 | UNIV_INLINE |
344 | void |
345 | dtuple_init_v_fld( |
346 | const dtuple_t* vrow); |
347 | |
348 | /** Duplicate the virtual field data in a dtuple_t |
349 | @param[in,out] vrow dtuple contains the virtual fields |
350 | @param[in] heap heap memory to use */ |
351 | UNIV_INLINE |
352 | void |
353 | dtuple_dup_v_fld( |
354 | const dtuple_t* vrow, |
355 | mem_heap_t* heap); |
356 | |
357 | /** Creates a data tuple with possible virtual columns to a memory heap. |
358 | @param[in] heap memory heap where the tuple is created |
359 | @param[in] n_fields number of fields |
360 | @param[in] n_v_fields number of fields on virtual col |
361 | @return own: created tuple */ |
362 | UNIV_INLINE |
363 | dtuple_t* |
364 | dtuple_create_with_vcol( |
365 | mem_heap_t* heap, |
366 | ulint n_fields, |
367 | ulint n_v_fields); |
368 | |
369 | /*********************************************************************//** |
370 | Sets number of fields used in a tuple. Normally this is set in |
371 | dtuple_create, but if you want later to set it smaller, you can use this. */ |
372 | void |
373 | dtuple_set_n_fields( |
374 | /*================*/ |
375 | dtuple_t* tuple, /*!< in: tuple */ |
376 | ulint n_fields) /*!< in: number of fields */ |
377 | MY_ATTRIBUTE((nonnull)); |
378 | /** Copies a data tuple's virtaul fields to another. This is a shallow copy; |
379 | @param[in,out] d_tuple destination tuple |
380 | @param[in] s_tuple source tuple */ |
381 | UNIV_INLINE |
382 | void |
383 | dtuple_copy_v_fields( |
384 | dtuple_t* d_tuple, |
385 | const dtuple_t* s_tuple); |
386 | /*********************************************************************//** |
387 | Copies a data tuple to another. This is a shallow copy; if a deep copy |
388 | is desired, dfield_dup() will have to be invoked on each field. |
389 | @return own: copy of tuple */ |
390 | UNIV_INLINE |
391 | dtuple_t* |
392 | dtuple_copy( |
393 | /*========*/ |
394 | const dtuple_t* tuple, /*!< in: tuple to copy from */ |
395 | mem_heap_t* heap) /*!< in: memory heap |
396 | where the tuple is created */ |
397 | MY_ATTRIBUTE((nonnull, malloc)); |
398 | /**********************************************************//** |
399 | The following function returns the sum of data lengths of a tuple. The space |
400 | occupied by the field structs or the tuple struct is not counted. |
401 | @return sum of data lens */ |
402 | UNIV_INLINE |
403 | ulint |
404 | dtuple_get_data_size( |
405 | /*=================*/ |
406 | const dtuple_t* tuple, /*!< in: typed data tuple */ |
407 | ulint comp) /*!< in: nonzero=ROW_FORMAT=COMPACT */ |
408 | MY_ATTRIBUTE((nonnull)); |
409 | /*********************************************************************//** |
410 | Computes the number of externally stored fields in a data tuple. |
411 | @return number of fields */ |
412 | UNIV_INLINE |
413 | ulint |
414 | dtuple_get_n_ext( |
415 | /*=============*/ |
416 | const dtuple_t* tuple) /*!< in: tuple */ |
417 | MY_ATTRIBUTE((nonnull)); |
418 | /** Compare two data tuples. |
419 | @param[in] tuple1 first data tuple |
420 | @param[in] tuple2 second data tuple |
421 | @return positive, 0, negative if tuple1 is greater, equal, less, than tuple2, |
422 | respectively */ |
423 | int |
424 | dtuple_coll_cmp( |
425 | const dtuple_t* tuple1, |
426 | const dtuple_t* tuple2) |
427 | MY_ATTRIBUTE((warn_unused_result)); |
428 | /** Fold a prefix given as the number of fields of a tuple. |
429 | @param[in] tuple index record |
430 | @param[in] n_fields number of complete fields to fold |
431 | @param[in] n_bytes number of bytes to fold in the last field |
432 | @param[in] index_id index tree ID |
433 | @return the folded value */ |
434 | UNIV_INLINE |
435 | ulint |
436 | dtuple_fold( |
437 | const dtuple_t* tuple, |
438 | ulint n_fields, |
439 | ulint n_bytes, |
440 | index_id_t tree_id) |
441 | MY_ATTRIBUTE((warn_unused_result)); |
442 | /*******************************************************************//** |
443 | Sets types of fields binary in a tuple. */ |
444 | UNIV_INLINE |
445 | void |
446 | dtuple_set_types_binary( |
447 | /*====================*/ |
448 | dtuple_t* tuple, /*!< in: data tuple */ |
449 | ulint n) /*!< in: number of fields to set */ |
450 | MY_ATTRIBUTE((nonnull)); |
451 | /**********************************************************************//** |
452 | Checks if a dtuple contains an SQL null value. |
453 | @return TRUE if some field is SQL null */ |
454 | UNIV_INLINE |
455 | ibool |
456 | dtuple_contains_null( |
457 | /*=================*/ |
458 | const dtuple_t* tuple) /*!< in: dtuple */ |
459 | MY_ATTRIBUTE((nonnull, warn_unused_result)); |
460 | /**********************************************************//** |
461 | Checks that a data field is typed. Asserts an error if not. |
462 | @return TRUE if ok */ |
463 | ibool |
464 | dfield_check_typed( |
465 | /*===============*/ |
466 | const dfield_t* field) /*!< in: data field */ |
467 | MY_ATTRIBUTE((nonnull, warn_unused_result)); |
468 | /**********************************************************//** |
469 | Checks that a data tuple is typed. Asserts an error if not. |
470 | @return TRUE if ok */ |
471 | ibool |
472 | dtuple_check_typed( |
473 | /*===============*/ |
474 | const dtuple_t* tuple) /*!< in: tuple */ |
475 | MY_ATTRIBUTE((nonnull, warn_unused_result)); |
476 | #ifdef UNIV_DEBUG |
477 | /**********************************************************//** |
478 | Validates the consistency of a tuple which must be complete, i.e, |
479 | all fields must have been set. |
480 | @return TRUE if ok */ |
481 | ibool |
482 | dtuple_validate( |
483 | /*============*/ |
484 | const dtuple_t* tuple) /*!< in: tuple */ |
485 | MY_ATTRIBUTE((nonnull, warn_unused_result)); |
486 | #endif /* UNIV_DEBUG */ |
487 | /*************************************************************//** |
488 | Pretty prints a dfield value according to its data type. */ |
489 | void |
490 | dfield_print( |
491 | /*=========*/ |
492 | const dfield_t* dfield) /*!< in: dfield */ |
493 | MY_ATTRIBUTE((nonnull)); |
494 | /*************************************************************//** |
495 | Pretty prints a dfield value according to its data type. Also the hex string |
496 | is printed if a string contains non-printable characters. */ |
497 | void |
498 | dfield_print_also_hex( |
499 | /*==================*/ |
500 | const dfield_t* dfield) /*!< in: dfield */ |
501 | MY_ATTRIBUTE((nonnull)); |
502 | /**********************************************************//** |
503 | The following function prints the contents of a tuple. */ |
504 | void |
505 | dtuple_print( |
506 | /*=========*/ |
507 | FILE* f, /*!< in: output stream */ |
508 | const dtuple_t* tuple) /*!< in: tuple */ |
509 | MY_ATTRIBUTE((nonnull)); |
510 | |
511 | /** Print the contents of a tuple. |
512 | @param[out] o output stream |
513 | @param[in] field array of data fields |
514 | @param[in] n number of data fields */ |
515 | void |
516 | dfield_print( |
517 | std::ostream& o, |
518 | const dfield_t* field, |
519 | ulint n); |
520 | /** Print the contents of a tuple. |
521 | @param[out] o output stream |
522 | @param[in] tuple data tuple */ |
523 | void |
524 | dtuple_print( |
525 | std::ostream& o, |
526 | const dtuple_t* tuple); |
527 | |
528 | /** Print the contents of a tuple. |
529 | @param[out] o output stream |
530 | @param[in] tuple data tuple */ |
531 | inline |
532 | std::ostream& |
533 | operator<<(std::ostream& o, const dtuple_t& tuple) |
534 | { |
535 | dtuple_print(o, &tuple); |
536 | return(o); |
537 | } |
538 | |
539 | /**************************************************************//** |
540 | Moves parts of long fields in entry to the big record vector so that |
541 | the size of tuple drops below the maximum record size allowed in the |
542 | database. Moves data only from those fields which are not necessary |
543 | to determine uniquely the insertion place of the tuple in the index. |
544 | @return own: created big record vector, NULL if we are not able to |
545 | shorten the entry enough, i.e., if there are too many fixed-length or |
546 | short fields in entry or the index is clustered */ |
547 | big_rec_t* |
548 | dtuple_convert_big_rec( |
549 | /*===================*/ |
550 | dict_index_t* index, /*!< in: index */ |
551 | upd_t* upd, /*!< in/out: update vector */ |
552 | dtuple_t* entry, /*!< in/out: index entry */ |
553 | ulint* n_ext) /*!< in/out: number of |
554 | externally stored columns */ |
555 | MY_ATTRIBUTE((malloc, warn_unused_result)); |
556 | /**************************************************************//** |
557 | Puts back to entry the data stored in vector. Note that to ensure the |
558 | fields in entry can accommodate the data, vector must have been created |
559 | from entry with dtuple_convert_big_rec. */ |
560 | void |
561 | dtuple_convert_back_big_rec( |
562 | /*========================*/ |
563 | dict_index_t* index, /*!< in: index */ |
564 | dtuple_t* entry, /*!< in: entry whose data was put to vector */ |
565 | big_rec_t* vector) /*!< in, own: big rec vector; it is |
566 | freed in this function */ |
567 | MY_ATTRIBUTE((nonnull)); |
568 | /**************************************************************//** |
569 | Frees the memory in a big rec vector. */ |
570 | UNIV_INLINE |
571 | void |
572 | dtuple_big_rec_free( |
573 | /*================*/ |
574 | big_rec_t* vector) /*!< in, own: big rec vector; it is |
575 | freed in this function */ |
576 | MY_ATTRIBUTE((nonnull)); |
577 | |
578 | /*######################################################################*/ |
579 | |
580 | /** Structure for an SQL data field */ |
581 | struct dfield_t{ |
582 | void* data; /*!< pointer to data */ |
583 | unsigned ext:1; /*!< TRUE=externally stored, FALSE=local */ |
584 | unsigned spatial_status:2; |
585 | /*!< spatial status of externally stored field |
586 | in undo log for purge */ |
587 | unsigned len; /*!< data length; UNIV_SQL_NULL if SQL null */ |
588 | dtype_t type; /*!< type of data */ |
589 | |
590 | /** Create a deep copy of this object. |
591 | @param[in,out] heap memory heap in which the clone will be created |
592 | @return the cloned object */ |
593 | dfield_t* clone(mem_heap_t* heap) const; |
594 | |
595 | /** @return system field indicates history row */ |
596 | bool vers_history_row() const |
597 | { |
598 | ut_ad(type.vers_sys_end()); |
599 | if (type.mtype == DATA_FIXBINARY) { |
600 | ut_ad(len == sizeof timestamp_max_bytes); |
601 | return 0 != memcmp(data, timestamp_max_bytes, len); |
602 | } else { |
603 | ut_ad(type.mtype == DATA_INT); |
604 | ut_ad(len == sizeof trx_id_max_bytes); |
605 | return 0 != memcmp(data, trx_id_max_bytes, len); |
606 | } |
607 | ut_ad(0); |
608 | return false; |
609 | } |
610 | }; |
611 | |
612 | /** Structure for an SQL data tuple of fields (logical record) */ |
613 | struct dtuple_t { |
614 | ulint info_bits; /*!< info bits of an index record: |
615 | the default is 0; this field is used |
616 | if an index record is built from |
617 | a data tuple */ |
618 | ulint n_fields; /*!< number of fields in dtuple */ |
619 | ulint n_fields_cmp; /*!< number of fields which should |
620 | be used in comparison services |
621 | of rem0cmp.*; the index search |
622 | is performed by comparing only these |
623 | fields, others are ignored; the |
624 | default value in dtuple creation is |
625 | the same value as n_fields */ |
626 | dfield_t* fields; /*!< fields */ |
627 | ulint n_v_fields; /*!< number of virtual fields */ |
628 | dfield_t* v_fields; /*!< fields on virtual column */ |
629 | UT_LIST_NODE_T(dtuple_t) tuple_list; |
630 | /*!< data tuples can be linked into a |
631 | list using this field */ |
632 | #ifdef UNIV_DEBUG |
633 | ulint magic_n; /*!< magic number, used in |
634 | debug assertions */ |
635 | /** Value of dtuple_t::magic_n */ |
636 | # define DATA_TUPLE_MAGIC_N 65478679 |
637 | #endif /* UNIV_DEBUG */ |
638 | |
639 | /** Trim the tail of an index tuple before insert or update. |
640 | After instant ADD COLUMN, if the last fields of a clustered index tuple |
641 | match the 'default row', there will be no need to store them. |
642 | NOTE: A page latch in the index must be held, so that the index |
643 | may not lose 'instantness' before the trimmed tuple has been |
644 | inserted or updated. |
645 | @param[in] index index possibly with instantly added columns */ |
646 | void trim(const dict_index_t& index); |
647 | }; |
648 | |
649 | /** A slot for a field in a big rec vector */ |
650 | struct big_rec_field_t { |
651 | |
652 | /** Constructor. |
653 | @param[in] field_no_ the field number |
654 | @param[in] len_ the data length |
655 | @param[in] data_ the data */ |
656 | big_rec_field_t(ulint field_no_, ulint len_, const void* data_) |
657 | : field_no(field_no_), |
658 | len(len_), |
659 | data(data_) |
660 | {} |
661 | |
662 | ulint field_no; /*!< field number in record */ |
663 | ulint len; /*!< stored data length, in bytes */ |
664 | const void* data; /*!< stored data */ |
665 | }; |
666 | |
667 | /** Storage format for overflow data in a big record, that is, a |
668 | clustered index record which needs external storage of data fields */ |
669 | struct big_rec_t { |
670 | mem_heap_t* heap; /*!< memory heap from which |
671 | allocated */ |
672 | const ulint capacity; /*!< fields array size */ |
673 | ulint n_fields; /*!< number of stored fields */ |
674 | big_rec_field_t*fields; /*!< stored fields */ |
675 | |
676 | /** Constructor. |
677 | @param[in] max the capacity of the array of fields. */ |
678 | explicit big_rec_t(const ulint max) |
679 | : heap(0), |
680 | capacity(max), |
681 | n_fields(0), |
682 | fields(0) |
683 | {} |
684 | |
685 | /** Append one big_rec_field_t object to the end of array of fields */ |
686 | void append(const big_rec_field_t& field) |
687 | { |
688 | ut_ad(n_fields < capacity); |
689 | fields[n_fields] = field; |
690 | n_fields++; |
691 | } |
692 | |
693 | /** Allocate a big_rec_t object in the given memory heap, and for |
694 | storing n_fld number of fields. |
695 | @param[in] heap memory heap in which this object is allocated |
696 | @param[in] n_fld maximum number of fields that can be stored in |
697 | this object |
698 | @return the allocated object */ |
699 | static big_rec_t* alloc( |
700 | mem_heap_t* heap, |
701 | ulint n_fld); |
702 | }; |
703 | |
704 | #include "data0data.ic" |
705 | |
706 | #endif |
707 | |