mirror of
https://github.com/MariaDB/server.git
synced 2025-01-21 06:22:28 +01:00
0028e8d1ee
Add innodb_locks.lock_data column and some relevant tests. For record locks this column represents the ordering fields of the locked row in a human readable, SQL-valid, format. Approved by: Marko
292 lines
5.4 KiB
Text
292 lines
5.4 KiB
Text
/***********************************************************************
|
|
Memory primitives
|
|
|
|
(c) 1994, 1995 Innobase Oy
|
|
|
|
Created 5/30/1994 Heikki Tuuri
|
|
************************************************************************/
|
|
|
|
#include "ut0byte.h"
|
|
#include "mach0data.h"
|
|
|
|
UNIV_INLINE
|
|
void*
|
|
ut_memcpy(void* dest, const void* sour, ulint n)
|
|
{
|
|
return(memcpy(dest, sour, n));
|
|
}
|
|
|
|
UNIV_INLINE
|
|
void*
|
|
ut_memmove(void* dest, const void* sour, ulint n)
|
|
{
|
|
return(memmove(dest, sour, n));
|
|
}
|
|
|
|
UNIV_INLINE
|
|
int
|
|
ut_memcmp(const void* str1, const void* str2, ulint n)
|
|
{
|
|
return(memcmp(str1, str2, n));
|
|
}
|
|
|
|
UNIV_INLINE
|
|
char*
|
|
ut_strcpy(char* dest, const char* sour)
|
|
{
|
|
return(strcpy(dest, sour));
|
|
}
|
|
|
|
UNIV_INLINE
|
|
ulint
|
|
ut_strlen(const char* str)
|
|
{
|
|
return(strlen(str));
|
|
}
|
|
|
|
UNIV_INLINE
|
|
int
|
|
ut_strcmp(const char* str1, const char* str2)
|
|
{
|
|
return(strcmp(str1, str2));
|
|
}
|
|
|
|
/**************************************************************************
|
|
Compute strlen(ut_strcpyq(str, q)). */
|
|
UNIV_INLINE
|
|
ulint
|
|
ut_strlenq(
|
|
/*=======*/
|
|
/* out: length of the string when quoted */
|
|
const char* str, /* in: null-terminated string */
|
|
char q) /* in: the quote character */
|
|
{
|
|
ulint len;
|
|
|
|
for (len = 0; *str; len++, str++) {
|
|
if (*str == q) {
|
|
len++;
|
|
}
|
|
}
|
|
|
|
return(len);
|
|
}
|
|
|
|
/**************************************************************************
|
|
Converts a raw binary data to a '\0'-terminated hex string. The output is
|
|
truncated if there is not enough space in "hex", make sure "hex_size" is at
|
|
least (2 * raw_size + 1) if you do not want this to happen. Returns the
|
|
actual number of characters written to "hex" (including the '\0'). */
|
|
UNIV_INLINE
|
|
ulint
|
|
ut_raw_to_hex(
|
|
/*==========*/
|
|
/* out: number of chars written */
|
|
const void* raw, /* in: raw data */
|
|
ulint raw_size, /* in: "raw" length in bytes */
|
|
char* hex, /* out: hex string */
|
|
ulint hex_size) /* in: "hex" size in bytes */
|
|
{
|
|
|
|
#ifdef WORDS_BIGENDIAN
|
|
|
|
#define MK_UINT16(a, b) (((uint16) (a)) << 8 | (uint16) (b))
|
|
|
|
#define UINT16_GET_A(u) ((unsigned char) ((u) >> 8))
|
|
#define UINT16_GET_B(u) ((unsigned char) ((u) & 0xFF))
|
|
|
|
#else /* WORDS_BIGENDIAN */
|
|
|
|
#define MK_UINT16(a, b) (((uint16) (b)) << 8 | (uint16) (a))
|
|
|
|
#define UINT16_GET_A(u) ((unsigned char) ((u) & 0xFF))
|
|
#define UINT16_GET_B(u) ((unsigned char) ((u) >> 8))
|
|
|
|
#endif /* WORDS_BIGENDIAN */
|
|
|
|
#define MK_ALL_UINT16_WITH_A(a) \
|
|
MK_UINT16(a, '0'), \
|
|
MK_UINT16(a, '1'), \
|
|
MK_UINT16(a, '2'), \
|
|
MK_UINT16(a, '3'), \
|
|
MK_UINT16(a, '4'), \
|
|
MK_UINT16(a, '5'), \
|
|
MK_UINT16(a, '6'), \
|
|
MK_UINT16(a, '7'), \
|
|
MK_UINT16(a, '8'), \
|
|
MK_UINT16(a, '9'), \
|
|
MK_UINT16(a, 'A'), \
|
|
MK_UINT16(a, 'B'), \
|
|
MK_UINT16(a, 'C'), \
|
|
MK_UINT16(a, 'D'), \
|
|
MK_UINT16(a, 'E'), \
|
|
MK_UINT16(a, 'F')
|
|
|
|
static const uint16 hex_map[256] = {
|
|
MK_ALL_UINT16_WITH_A('0'),
|
|
MK_ALL_UINT16_WITH_A('1'),
|
|
MK_ALL_UINT16_WITH_A('2'),
|
|
MK_ALL_UINT16_WITH_A('3'),
|
|
MK_ALL_UINT16_WITH_A('4'),
|
|
MK_ALL_UINT16_WITH_A('5'),
|
|
MK_ALL_UINT16_WITH_A('6'),
|
|
MK_ALL_UINT16_WITH_A('7'),
|
|
MK_ALL_UINT16_WITH_A('8'),
|
|
MK_ALL_UINT16_WITH_A('9'),
|
|
MK_ALL_UINT16_WITH_A('A'),
|
|
MK_ALL_UINT16_WITH_A('B'),
|
|
MK_ALL_UINT16_WITH_A('C'),
|
|
MK_ALL_UINT16_WITH_A('D'),
|
|
MK_ALL_UINT16_WITH_A('E'),
|
|
MK_ALL_UINT16_WITH_A('F')
|
|
};
|
|
const unsigned char* rawc;
|
|
ulint read_bytes;
|
|
ulint write_bytes;
|
|
ulint i;
|
|
|
|
rawc = (const unsigned char*) raw;
|
|
|
|
if (hex_size == 0) {
|
|
|
|
return(0);
|
|
}
|
|
|
|
if (hex_size <= 2 * raw_size) {
|
|
|
|
read_bytes = hex_size / 2;
|
|
write_bytes = hex_size;
|
|
} else {
|
|
|
|
read_bytes = raw_size;
|
|
write_bytes = 2 * raw_size + 1;
|
|
}
|
|
|
|
#define LOOP_READ_BYTES(ASSIGN) \
|
|
for (i = 0; i < read_bytes; i++) { \
|
|
ASSIGN; \
|
|
hex += 2; \
|
|
rawc++; \
|
|
}
|
|
|
|
if (ut_align_offset(hex, 2) == 0) {
|
|
|
|
LOOP_READ_BYTES(
|
|
*(uint16*) hex = hex_map[*rawc]
|
|
);
|
|
} else {
|
|
|
|
LOOP_READ_BYTES(
|
|
*hex = UINT16_GET_A(hex_map[*rawc]);
|
|
*(hex + 1) = UINT16_GET_B(hex_map[*rawc])
|
|
);
|
|
}
|
|
|
|
if (hex_size <= 2 * raw_size && hex_size % 2 == 0) {
|
|
|
|
hex--;
|
|
}
|
|
|
|
*hex = '\0';
|
|
|
|
return(write_bytes);
|
|
}
|
|
|
|
/***********************************************************************
|
|
Adds single quotes to the start and end of string and escapes any quotes
|
|
by doubling them. Returns the number of bytes that were written to "buf"
|
|
(including the terminating '\0'). If buf_size is too small then the
|
|
trailing bytes from "str" are discarded. */
|
|
UNIV_INLINE
|
|
ulint
|
|
ut_str_sql_format(
|
|
/*==============*/
|
|
/* out: number of bytes
|
|
that were written */
|
|
const char* str, /* in: string */
|
|
ulint str_len, /* in: string length in bytes */
|
|
char* buf, /* out: output buffer */
|
|
ulint buf_size) /* in: output buffer size
|
|
in bytes */
|
|
{
|
|
ulint str_i;
|
|
ulint buf_i;
|
|
|
|
buf_i = 0;
|
|
|
|
switch (buf_size) {
|
|
case 3:
|
|
|
|
if (str_len == 0) {
|
|
|
|
buf[buf_i] = '\'';
|
|
buf_i++;
|
|
buf[buf_i] = '\'';
|
|
buf_i++;
|
|
}
|
|
/* FALLTHROUGH */
|
|
case 2:
|
|
case 1:
|
|
|
|
buf[buf_i] = '\0';
|
|
buf_i++;
|
|
/* FALLTHROUGH */
|
|
case 0:
|
|
|
|
return(buf_i);
|
|
}
|
|
|
|
/* buf_size >= 4 */
|
|
|
|
buf[0] = '\'';
|
|
buf_i = 1;
|
|
|
|
for (str_i = 0; str_i < str_len; str_i++) {
|
|
|
|
char ch;
|
|
|
|
if (buf_size - buf_i == 2) {
|
|
|
|
break;
|
|
}
|
|
|
|
ch = str[str_i];
|
|
|
|
switch (ch) {
|
|
case '\0':
|
|
|
|
if (UNIV_UNLIKELY(buf_size - buf_i < 4)) {
|
|
|
|
goto func_exit;
|
|
}
|
|
buf[buf_i] = '\\';
|
|
buf_i++;
|
|
buf[buf_i] = '0';
|
|
buf_i++;
|
|
break;
|
|
case '\'':
|
|
case '\\':
|
|
|
|
if (UNIV_UNLIKELY(buf_size - buf_i < 4)) {
|
|
|
|
goto func_exit;
|
|
}
|
|
buf[buf_i] = ch;
|
|
buf_i++;
|
|
/* FALLTHROUGH */
|
|
default:
|
|
|
|
buf[buf_i] = ch;
|
|
buf_i++;
|
|
}
|
|
}
|
|
|
|
func_exit:
|
|
|
|
buf[buf_i] = '\'';
|
|
buf_i++;
|
|
buf[buf_i] = '\0';
|
|
buf_i++;
|
|
|
|
return(buf_i);
|
|
}
|