/****************************************************** MySQL interface for Innobase (C) 2001 Innobase Oy Created 1/23/2001 Heikki Tuuri *******************************************************/ /*********************************************************************** Stores a variable-length field (like VARCHAR) length to dest, in the MySQL format. No real var implemented in MySQL yet! */ UNIV_INLINE byte* row_mysql_store_var_len( /*====================*/ /* out: dest + 2 */ byte* dest, /* in: where to store */ ulint len __attribute__((unused))) /* in: length, must fit in two bytes */ { ut_ad(len < 256 * 256); /* mach_write_to_2_little_endian(dest, len); return(dest + 2); */ return(dest); /* No real var implemented in MySQL yet! */ } /*********************************************************************** Reads a MySQL format variable-length field (like VARCHAR) length and returns pointer to the field data. No real var implemented in MySQL yet! */ UNIV_INLINE byte* row_mysql_read_var_ref( /*===================*/ /* out: field + 2 */ ulint* len, /* out: variable-length field length; does not work yet! */ byte* field) /* in: field */ { /* *len = mach_read_from_2_little_endian(field); return(field + 2); */ UT_NOT_USED(len); return(field); /* No real var implemented in MySQL yet! */ } /****************************************************************** Stores a non-SQL-NULL field given in the MySQL format in the Innobase format. */ UNIV_INLINE void row_mysql_store_col_in_innobase_format( /*===================================*/ dfield_t* dfield, /* in/out: dfield */ byte* buf, /* in/out: buffer for the converted value; this must be at least col_len long! */ byte* mysql_data, /* in: MySQL column value, not SQL NULL; NOTE that dfield may also get a pointer to mysql_data, therefore do not discard this as long as dfield is used! */ ulint col_len, /* in: MySQL column length */ ulint type, /* in: data type */ bool comp, /* in: TRUE=compact format */ ulint is_unsigned) /* in: != 0 if unsigned integer type */ { byte* ptr = mysql_data; if (type == DATA_INT) { /* Store integer data in Innobase in a big-endian format, sign bit negated */ ptr = buf + col_len; for (;;) { ptr--; *ptr = *mysql_data; if (ptr == buf) { break; } mysql_data++; } if (!is_unsigned) { *ptr = (byte) (*ptr ^ 128); } } else if (type == DATA_VARCHAR || type == DATA_VARMYSQL || type == DATA_BINARY) { /* Remove trailing spaces. */ /* Handle UCS2 strings differently. */ ulint mbminlen = dtype_get_mbminlen( dfield_get_type(dfield)); ptr = row_mysql_read_var_ref(&col_len, mysql_data); if (mbminlen == 2) { /* space=0x0020 */ /* Trim "half-chars", just in case. */ col_len &= ~1; while (col_len >= 2 && ptr[col_len - 2] == 0x00 && ptr[col_len - 1] == 0x20) { col_len -= 2; } } else { ut_a(mbminlen == 1); /* space=0x20 */ while (col_len > 0 && ptr[col_len - 1] == 0x20) { col_len--; } } } else if (comp && type == DATA_MYSQL && dtype_get_mbminlen(dfield_get_type(dfield)) == 1 && dtype_get_mbmaxlen(dfield_get_type(dfield)) > 1) { /* We assume that this CHAR field is encoded in a variable-length character set where spaces have 1:1 correspondence to 0x20 bytes, such as UTF-8. Consider a CHAR(n) field, a field of n characters. It will contain between n*mbminlen and n*mbmaxlen bytes. We will try to truncate it to n bytes by stripping space padding. If the field contains single-byte characters only, it will be truncated to n characters. Consider a CHAR(5) field containing the string ".a " where "." denotes a 3-byte character represented by the bytes "$%&". After our stripping, the string will be stored as "$%&a " (5 bytes). The string ".abc " will be stored as "$%&abc" (6 bytes). The space padding will be restored in row0sel.c, function row_sel_field_store_in_mysql_format(). */ ulint n_chars; dtype_t* dtype = dfield_get_type(dfield); ut_a(!(dtype_get_len(dtype) % dtype_get_mbmaxlen(dtype))); n_chars = dtype_get_len(dtype) / dtype_get_mbmaxlen(dtype); /* Strip space padding. */ while (col_len > n_chars && ptr[col_len - 1] == 0x20) { col_len--; } } else if (type == DATA_BLOB) { ptr = row_mysql_read_blob_ref(&col_len, mysql_data, col_len); } dfield_set_data(dfield, ptr, col_len); }