1/*****************************************************************************
2
3Copyright (c) 1994, 2016, Oracle and/or its affiliates. All Rights Reserved.
4
5This program is free software; you can redistribute it and/or modify
6it under the terms of the GNU General Public License, version 2.0,
7as published by the Free Software Foundation.
8
9This program is also distributed with certain software (including
10but not limited to OpenSSL) that is licensed under separate terms,
11as designated in a particular file or component or in included license
12documentation.  The authors of MySQL hereby grant you an additional
13permission to link the program and your derivative works with the
14separately licensed software that they have included with MySQL.
15
16This program is distributed in the hope that it will be useful,
17but WITHOUT ANY WARRANTY; without even the implied warranty of
18MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
19GNU General Public License, version 2.0, for more details.
20
21You should have received a copy of the GNU General Public License along with
22this program; if not, write to the Free Software Foundation, Inc.,
2351 Franklin Street, Suite 500, Boston, MA 02110-1335 USA
24
25*****************************************************************************/
26
27/********************************************************************//**
28@file include/data0data.ic
29SQL data field and tuple
30
31Created 5/30/1994 Heikki Tuuri
32*************************************************************************/
33
34#include "mem0mem.h"
35#include "ut0rnd.h"
36
37#ifdef UNIV_DEBUG
38/** Dummy variable to catch access to uninitialized fields.  In the
39debug version, dtuple_create() will make all fields of dtuple_t point
40to data_error. */
41extern byte data_error;
42
43/*********************************************************************//**
44Gets pointer to the type struct of SQL data field.
45@return	pointer to the type struct */
46UNIV_INLINE
47dtype_t*
48dfield_get_type(
49/*============*/
50	const dfield_t*	field)	/*!< in: SQL data field */
51{
52	ut_ad(field);
53
54	return((dtype_t*) &(field->type));
55}
56#endif /* UNIV_DEBUG */
57
58/*********************************************************************//**
59Sets the type struct of SQL data field. */
60UNIV_INLINE
61void
62dfield_set_type(
63/*============*/
64	dfield_t*	field,	/*!< in: SQL data field */
65	const dtype_t*	type)	/*!< in: pointer to data type struct */
66{
67	ut_ad(field != NULL);
68	ut_ad(type != NULL);
69
70	field->type = *type;
71}
72
73#ifdef UNIV_DEBUG
74/*********************************************************************//**
75Gets pointer to the data in a field.
76@return	pointer to data */
77UNIV_INLINE
78void*
79dfield_get_data(
80/*============*/
81	const dfield_t* field)	/*!< in: field */
82{
83	ut_ad(field);
84	ut_ad((field->len == UNIV_SQL_NULL)
85	      || (field->data != &data_error));
86
87	return((void*) field->data);
88}
89#endif /* UNIV_DEBUG */
90
91/*********************************************************************//**
92Gets length of field data.
93@return	length of data; UNIV_SQL_NULL if SQL null data */
94UNIV_INLINE
95ulint
96dfield_get_len(
97/*===========*/
98	const dfield_t*	field)	/*!< in: field */
99{
100	ut_ad(field);
101	ut_ad((field->len == UNIV_SQL_NULL)
102	      || (field->data != &data_error));
103
104	return(field->len);
105}
106
107/*********************************************************************//**
108Sets length in a field. */
109UNIV_INLINE
110void
111dfield_set_len(
112/*===========*/
113	dfield_t*	field,	/*!< in: field */
114	ulint		len)	/*!< in: length or UNIV_SQL_NULL */
115{
116	ut_ad(field);
117#ifdef UNIV_VALGRIND_DEBUG
118	if (len != UNIV_SQL_NULL) UNIV_MEM_ASSERT_RW(field->data, len);
119#endif /* UNIV_VALGRIND_DEBUG */
120
121	field->ext = 0;
122	field->len = len;
123}
124
125/*********************************************************************//**
126Determines if a field is SQL NULL
127@return	nonzero if SQL null data */
128UNIV_INLINE
129ulint
130dfield_is_null(
131/*===========*/
132	const dfield_t* field)	/*!< in: field */
133{
134	ut_ad(field);
135
136	return(field->len == UNIV_SQL_NULL);
137}
138
139/*********************************************************************//**
140Determines if a field is externally stored
141@return	nonzero if externally stored */
142UNIV_INLINE
143ulint
144dfield_is_ext(
145/*==========*/
146	const dfield_t* field)	/*!< in: field */
147{
148	ut_ad(field);
149
150	return(field->ext);
151}
152
153/*********************************************************************//**
154Sets the "external storage" flag */
155UNIV_INLINE
156void
157dfield_set_ext(
158/*===========*/
159	dfield_t*	field)	/*!< in/out: field */
160{
161	ut_ad(field);
162
163	field->ext = 1;
164}
165
166/*********************************************************************//**
167Sets pointer to the data and length in a field. */
168UNIV_INLINE
169void
170dfield_set_data(
171/*============*/
172	dfield_t*	field,	/*!< in: field */
173	const void*	data,	/*!< in: data */
174	ulint		len)	/*!< in: length or UNIV_SQL_NULL */
175{
176	ut_ad(field);
177
178#ifdef UNIV_VALGRIND_DEBUG
179	if (len != UNIV_SQL_NULL) UNIV_MEM_ASSERT_RW(data, len);
180#endif /* UNIV_VALGRIND_DEBUG */
181	field->data = (void*) data;
182	field->ext = 0;
183	field->len = len;
184}
185
186/*********************************************************************//**
187Sets a data field to SQL NULL. */
188UNIV_INLINE
189void
190dfield_set_null(
191/*============*/
192	dfield_t*	field)	/*!< in/out: field */
193{
194	dfield_set_data(field, NULL, UNIV_SQL_NULL);
195}
196
197/*********************************************************************//**
198Copies the data and len fields. */
199UNIV_INLINE
200void
201dfield_copy_data(
202/*=============*/
203	dfield_t*	field1,	/*!< out: field to copy to */
204	const dfield_t*	field2)	/*!< in: field to copy from */
205{
206	ut_ad(field1 != NULL);
207	ut_ad(field2 != NULL);
208
209	field1->data = field2->data;
210	field1->len = field2->len;
211	field1->ext = field2->ext;
212}
213
214/*********************************************************************//**
215Copies a data field to another. */
216UNIV_INLINE
217void
218dfield_copy(
219/*========*/
220	dfield_t*	field1,	/*!< out: field to copy to */
221	const dfield_t*	field2)	/*!< in: field to copy from */
222{
223	*field1 = *field2;
224}
225
226/*********************************************************************//**
227Copies the data pointed to by a data field. */
228UNIV_INLINE
229void
230dfield_dup(
231/*=======*/
232	dfield_t*	field,	/*!< in/out: data field */
233	mem_heap_t*	heap)	/*!< in: memory heap where allocated */
234{
235	if (!dfield_is_null(field)) {
236		UNIV_MEM_ASSERT_RW(field->data, field->len);
237		field->data = mem_heap_dup(heap, field->data, field->len);
238	}
239}
240
241#ifndef UNIV_HOTBACKUP
242/*********************************************************************//**
243Tests if two data fields are equal.
244If len==0, tests the data length and content for equality.
245If len>0, tests the first len bytes of the content for equality.
246@return	TRUE if both fields are NULL or if they are equal */
247UNIV_INLINE
248ibool
249dfield_datas_are_binary_equal(
250/*==========================*/
251	const dfield_t*	field1,	/*!< in: field */
252	const dfield_t*	field2,	/*!< in: field */
253	ulint		len)	/*!< in: maximum prefix to compare,
254				or 0 to compare the whole field length */
255{
256	ulint	len2 = len;
257
258	if (field1->len == UNIV_SQL_NULL || len == 0 || field1->len < len) {
259		len = field1->len;
260	}
261
262	if (field2->len == UNIV_SQL_NULL || len2 == 0 || field2->len < len2) {
263		len2 = field2->len;
264	}
265
266	return(len == len2
267	       && (len == UNIV_SQL_NULL
268		   || !memcmp(field1->data, field2->data, len)));
269}
270
271/*********************************************************************//**
272Tests if dfield data length and content is equal to the given.
273@return	TRUE if equal */
274UNIV_INLINE
275ibool
276dfield_data_is_binary_equal(
277/*========================*/
278	const dfield_t*	field,	/*!< in: field */
279	ulint		len,	/*!< in: data length or UNIV_SQL_NULL */
280	const byte*	data)	/*!< in: data */
281{
282	return(len == dfield_get_len(field)
283	       && (len == UNIV_SQL_NULL
284		   || !memcmp(dfield_get_data(field), data, len)));
285}
286#endif /* !UNIV_HOTBACKUP */
287
288/*********************************************************************//**
289Gets info bits in a data tuple.
290@return	info bits */
291UNIV_INLINE
292ulint
293dtuple_get_info_bits(
294/*=================*/
295	const dtuple_t*	tuple)	/*!< in: tuple */
296{
297	ut_ad(tuple);
298
299	return(tuple->info_bits);
300}
301
302/*********************************************************************//**
303Sets info bits in a data tuple. */
304UNIV_INLINE
305void
306dtuple_set_info_bits(
307/*=================*/
308	dtuple_t*	tuple,		/*!< in: tuple */
309	ulint		info_bits)	/*!< in: info bits */
310{
311	ut_ad(tuple);
312
313	tuple->info_bits = info_bits;
314}
315
316/*********************************************************************//**
317Gets number of fields used in record comparisons.
318@return	number of fields used in comparisons in rem0cmp.* */
319UNIV_INLINE
320ulint
321dtuple_get_n_fields_cmp(
322/*====================*/
323	const dtuple_t*	tuple)	/*!< in: tuple */
324{
325	ut_ad(tuple);
326
327	return(tuple->n_fields_cmp);
328}
329
330/*********************************************************************//**
331Sets number of fields used in record comparisons. */
332UNIV_INLINE
333void
334dtuple_set_n_fields_cmp(
335/*====================*/
336	dtuple_t*	tuple,		/*!< in: tuple */
337	ulint		n_fields_cmp)	/*!< in: number of fields used in
338					comparisons in rem0cmp.* */
339{
340	ut_ad(tuple);
341	ut_ad(n_fields_cmp <= tuple->n_fields);
342
343	tuple->n_fields_cmp = n_fields_cmp;
344}
345
346/*********************************************************************//**
347Gets number of fields in a data tuple.
348@return	number of fields */
349UNIV_INLINE
350ulint
351dtuple_get_n_fields(
352/*================*/
353	const dtuple_t*	tuple)	/*!< in: tuple */
354{
355	ut_ad(tuple);
356
357	return(tuple->n_fields);
358}
359
360#ifdef UNIV_DEBUG
361/*********************************************************************//**
362Gets nth field of a tuple.
363@return	nth field */
364UNIV_INLINE
365dfield_t*
366dtuple_get_nth_field(
367/*=================*/
368	const dtuple_t*	tuple,	/*!< in: tuple */
369	ulint		n)	/*!< in: index of field */
370{
371	ut_ad(tuple);
372	ut_ad(n < tuple->n_fields);
373
374	return((dfield_t*) tuple->fields + n);
375}
376#endif /* UNIV_DEBUG */
377
378/**********************************************************//**
379Creates a data tuple from an already allocated chunk of memory.
380The size of the chunk must be at least DTUPLE_EST_ALLOC(n_fields).
381The default value for number of fields used in record comparisons
382for this tuple is n_fields.
383@return	created tuple (inside buf) */
384UNIV_INLINE
385dtuple_t*
386dtuple_create_from_mem(
387/*===================*/
388	void*	buf,		/*!< in, out: buffer to use */
389	ulint	buf_size,	/*!< in: buffer size */
390	ulint	n_fields)	/*!< in: number of fields */
391{
392	dtuple_t*	tuple;
393
394	ut_ad(buf != NULL);
395	ut_a(buf_size >= DTUPLE_EST_ALLOC(n_fields));
396
397	tuple = (dtuple_t*) buf;
398	tuple->info_bits = 0;
399	tuple->n_fields = n_fields;
400	tuple->n_fields_cmp = n_fields;
401	tuple->fields = (dfield_t*) &tuple[1];
402
403#ifdef UNIV_DEBUG
404	tuple->magic_n = DATA_TUPLE_MAGIC_N;
405
406	{	/* In the debug version, initialize fields to an error value */
407		ulint	i;
408
409		for (i = 0; i < n_fields; i++) {
410			dfield_t*       field;
411
412			field = dtuple_get_nth_field(tuple, i);
413
414			dfield_set_len(field, UNIV_SQL_NULL);
415			field->data = &data_error;
416			dfield_get_type(field)->mtype = DATA_ERROR;
417		}
418	}
419#endif
420	UNIV_MEM_ASSERT_W(tuple->fields, n_fields * sizeof *tuple->fields);
421	UNIV_MEM_INVALID(tuple->fields, n_fields * sizeof *tuple->fields);
422	return(tuple);
423}
424
425/**********************************************************//**
426Creates a data tuple to a memory heap. The default value for number
427of fields used in record comparisons for this tuple is n_fields.
428@return	own: created tuple */
429UNIV_INLINE
430dtuple_t*
431dtuple_create(
432/*==========*/
433	mem_heap_t*	heap,	/*!< in: memory heap where the tuple
434				is created, DTUPLE_EST_ALLOC(n_fields)
435				bytes will be allocated from this heap */
436	ulint		n_fields) /*!< in: number of fields */
437{
438	void*		buf;
439	ulint		buf_size;
440	dtuple_t*	tuple;
441
442	ut_ad(heap);
443
444	buf_size = DTUPLE_EST_ALLOC(n_fields);
445	buf = mem_heap_alloc(heap, buf_size);
446
447	tuple = dtuple_create_from_mem(buf, buf_size, n_fields);
448
449	return(tuple);
450}
451
452/*********************************************************************//**
453Copies a data tuple to another.  This is a shallow copy; if a deep copy
454is desired, dfield_dup() will have to be invoked on each field.
455@return	own: copy of tuple */
456UNIV_INLINE
457dtuple_t*
458dtuple_copy(
459/*========*/
460	const dtuple_t*	tuple,	/*!< in: tuple to copy from */
461	mem_heap_t*	heap)	/*!< in: memory heap
462				where the tuple is created */
463{
464	ulint		n_fields	= dtuple_get_n_fields(tuple);
465	dtuple_t*	new_tuple	= dtuple_create(heap, n_fields);
466	ulint		i;
467
468	for (i = 0; i < n_fields; i++) {
469		dfield_copy(dtuple_get_nth_field(new_tuple, i),
470			    dtuple_get_nth_field(tuple, i));
471	}
472
473	return(new_tuple);
474}
475
476/**********************************************************//**
477The following function returns the sum of data lengths of a tuple. The space
478occupied by the field structs or the tuple struct is not counted. Neither
479is possible space in externally stored parts of the field.
480@return	sum of data lengths */
481UNIV_INLINE
482ulint
483dtuple_get_data_size(
484/*=================*/
485	const dtuple_t*	tuple,	/*!< in: typed data tuple */
486	ulint		comp)	/*!< in: nonzero=ROW_FORMAT=COMPACT  */
487{
488	const dfield_t*	field;
489	ulint		n_fields;
490	ulint		len;
491	ulint		i;
492	ulint		sum	= 0;
493
494	ut_ad(tuple);
495	ut_ad(dtuple_check_typed(tuple));
496	ut_ad(tuple->magic_n == DATA_TUPLE_MAGIC_N);
497
498	n_fields = tuple->n_fields;
499
500	for (i = 0; i < n_fields; i++) {
501		field = dtuple_get_nth_field(tuple,  i);
502		len = dfield_get_len(field);
503
504		if (len == UNIV_SQL_NULL) {
505			len = dtype_get_sql_null_size(dfield_get_type(field),
506						      comp);
507		}
508
509		sum += len;
510	}
511
512	return(sum);
513}
514
515/*********************************************************************//**
516Computes the number of externally stored fields in a data tuple.
517@return	number of externally stored fields */
518UNIV_INLINE
519ulint
520dtuple_get_n_ext(
521/*=============*/
522	const dtuple_t*	tuple)	/*!< in: tuple */
523{
524	ulint	n_ext		= 0;
525	ulint	n_fields	= tuple->n_fields;
526	ulint	i;
527
528	ut_ad(tuple);
529	ut_ad(dtuple_check_typed(tuple));
530	ut_ad(tuple->magic_n == DATA_TUPLE_MAGIC_N);
531
532	for (i = 0; i < n_fields; i++) {
533		n_ext += dtuple_get_nth_field(tuple, i)->ext;
534	}
535
536	return(n_ext);
537}
538
539/*******************************************************************//**
540Sets types of fields binary in a tuple. */
541UNIV_INLINE
542void
543dtuple_set_types_binary(
544/*====================*/
545	dtuple_t*	tuple,	/*!< in: data tuple */
546	ulint		n)	/*!< in: number of fields to set */
547{
548	dtype_t*	dfield_type;
549	ulint		i;
550
551	for (i = 0; i < n; i++) {
552		dfield_type = dfield_get_type(dtuple_get_nth_field(tuple, i));
553		dtype_set(dfield_type, DATA_BINARY, 0, 0);
554	}
555}
556
557/************************************************************//**
558Folds a prefix given as the number of fields of a tuple.
559@return	the folded value */
560UNIV_INLINE
561ulint
562dtuple_fold(
563/*========*/
564	const dtuple_t*	tuple,	/*!< in: the tuple */
565	ulint		n_fields,/*!< in: number of complete fields to fold */
566	ulint		n_bytes,/*!< in: number of bytes to fold in an
567				incomplete last field */
568	index_id_t	tree_id)/*!< in: index tree id */
569{
570	const dfield_t*	field;
571	ulint		i;
572	const byte*	data;
573	ulint		len;
574	ulint		fold;
575
576	ut_ad(tuple);
577	ut_ad(tuple->magic_n == DATA_TUPLE_MAGIC_N);
578	ut_ad(dtuple_check_typed(tuple));
579
580	fold = ut_fold_ull(tree_id);
581
582	for (i = 0; i < n_fields; i++) {
583		field = dtuple_get_nth_field(tuple, i);
584
585		data = (const byte*) dfield_get_data(field);
586		len = dfield_get_len(field);
587
588		if (len != UNIV_SQL_NULL) {
589			fold = ut_fold_ulint_pair(fold,
590						  ut_fold_binary(data, len));
591		}
592	}
593
594	if (n_bytes > 0) {
595		field = dtuple_get_nth_field(tuple, i);
596
597		data = (const byte*) dfield_get_data(field);
598		len = dfield_get_len(field);
599
600		if (len != UNIV_SQL_NULL) {
601			if (len > n_bytes) {
602				len = n_bytes;
603			}
604
605			fold = ut_fold_ulint_pair(fold,
606						  ut_fold_binary(data, len));
607		}
608	}
609
610	return(fold);
611}
612
613/**********************************************************************//**
614Writes an SQL null field full of zeros. */
615UNIV_INLINE
616void
617data_write_sql_null(
618/*================*/
619	byte*	data,	/*!< in: pointer to a buffer of size len */
620	ulint	len)	/*!< in: SQL null size in bytes */
621{
622	memset(data, 0, len);
623}
624
625/**********************************************************************//**
626Checks if a dtuple contains an SQL null value.
627@return	TRUE if some field is SQL null */
628UNIV_INLINE
629ibool
630dtuple_contains_null(
631/*=================*/
632	const dtuple_t*	tuple)	/*!< in: dtuple */
633{
634	ulint	n;
635	ulint	i;
636
637	n = dtuple_get_n_fields(tuple);
638
639	for (i = 0; i < n; i++) {
640		if (dfield_is_null(dtuple_get_nth_field(tuple, i))) {
641
642			return(TRUE);
643		}
644	}
645
646	return(FALSE);
647}
648
649/**************************************************************//**
650Frees the memory in a big rec vector. */
651UNIV_INLINE
652void
653dtuple_big_rec_free(
654/*================*/
655	big_rec_t*	vector)	/*!< in, own: big rec vector; it is
656				freed in this function */
657{
658	mem_heap_free(vector->heap);
659}
660