1
/* - mode: c++ c-basic-offset: 2; indent-tabs-mode: nil; -*-
2
* vim:expandtab:shiftwidth=2:tabstop=2:smarttab:
4
* Copyright (C) 2008 MySQL
6
* This program is free software; you can redistribute it and/or modify
7
* it under the terms of the GNU General Public License as published by
8
* the Free Software Foundation; either version 2 of the License, or
9
* (at your option) any later version.
11
* This program is distributed in the hope that it will be useful,
12
* but WITHOUT ANY WARRANTY; without even the implied warranty of
13
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14
* GNU General Public License for more details.
16
* You should have received a copy of the GNU General Public License
17
* along with this program; if not, write to the Free Software
18
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
22
#include <drizzled/server_includes.h>
23
#include <drizzled/field/fstring.h>
24
#include <drizzled/error.h>
26
#define LONGLONG_TO_STRING_CONVERSION_BUFFER_SIZE 128
27
#define DECIMAL_TO_STRING_CONVERSION_BUFFER_SIZE 128
29
/****************************************************************************
31
** A string may be varchar or binary
32
****************************************************************************/
34
/* Copy a string and fill with space */
35
int Field_string::store(const char *from,uint32_t length, const CHARSET_INFO * const cs)
38
const char *well_formed_error_pos;
39
const char *cannot_convert_error_pos;
40
const char *from_end_pos;
42
/* See the comment for Field_long::store(int64_t) */
43
assert(table->in_use == current_session);
45
copy_length= well_formed_copy_nchars(field_charset,
46
(char*) ptr, field_length,
48
field_length / field_charset->mbmaxlen,
49
&well_formed_error_pos,
50
&cannot_convert_error_pos,
53
/* Append spaces if the string was shorter than the field. */
54
if (copy_length < field_length)
55
field_charset->cset->fill(field_charset,(char*) ptr+copy_length,
56
field_length-copy_length,
57
field_charset->pad_char);
59
if (check_string_copy_error(this, well_formed_error_pos,
60
cannot_convert_error_pos, from + length, cs))
63
return report_if_important_data(from_end_pos, from + length);
67
int Field_string::store(int64_t nr, bool unsigned_val)
71
const CHARSET_INFO * const cs= charset();
72
l= (cs->cset->int64_t10_to_str)(cs,buff,sizeof(buff),
73
unsigned_val ? 10 : -10, nr);
74
return Field_string::store(buff,(uint)l,cs);
78
double Field_string::val_real(void)
82
const CHARSET_INFO * const cs= charset();
85
result= my_strntod(cs,(char*) ptr,field_length,&end,&error);
86
if (!table->in_use->no_errors &&
87
(error || (field_length != (uint32_t)(end - (char*) ptr) &&
88
!check_if_only_end_space(cs, end,
89
(char*) ptr + field_length))))
91
char buf[DOUBLE_TO_STRING_CONVERSION_BUFFER_SIZE];
92
String tmp(buf, sizeof(buf), cs);
93
tmp.copy((char*) ptr, field_length, cs);
94
push_warning_printf(current_session, DRIZZLE_ERROR::WARN_LEVEL_WARN,
95
ER_TRUNCATED_WRONG_VALUE,
96
ER(ER_TRUNCATED_WRONG_VALUE),
97
"DOUBLE", tmp.c_ptr());
103
int64_t Field_string::val_int(void)
107
const CHARSET_INFO * const cs= charset();
110
result= my_strntoll(cs, (char*) ptr,field_length,10,&end,&error);
111
if (!table->in_use->no_errors &&
112
(error || (field_length != (uint32_t)(end - (char*) ptr) &&
113
!check_if_only_end_space(cs, end,
114
(char*) ptr + field_length))))
116
char buf[LONGLONG_TO_STRING_CONVERSION_BUFFER_SIZE];
117
String tmp(buf, sizeof(buf), cs);
118
tmp.copy((char*) ptr, field_length, cs);
119
push_warning_printf(current_session, DRIZZLE_ERROR::WARN_LEVEL_WARN,
120
ER_TRUNCATED_WRONG_VALUE,
121
ER(ER_TRUNCATED_WRONG_VALUE),
122
"INTEGER", tmp.c_ptr());
128
String *Field_string::val_str(String *val_buffer __attribute__((unused)),
131
/* See the comment for Field_long::store(int64_t) */
132
assert(table->in_use == current_session);
135
length= field_charset->cset->lengthsp(field_charset, (const char*) ptr, field_length);
136
val_ptr->set((const char*) ptr, length, field_charset);
142
my_decimal *Field_string::val_decimal(my_decimal *decimal_value)
144
int err= str2my_decimal(E_DEC_FATAL_ERROR, (char*) ptr, field_length,
145
charset(), decimal_value);
146
if (!table->in_use->no_errors && err)
148
char buf[DECIMAL_TO_STRING_CONVERSION_BUFFER_SIZE];
149
const CHARSET_INFO * const cs= charset();
150
String tmp(buf, sizeof(buf), cs);
151
tmp.copy((char*) ptr, field_length, cs);
152
push_warning_printf(current_session, DRIZZLE_ERROR::WARN_LEVEL_WARN,
153
ER_TRUNCATED_WRONG_VALUE,
154
ER(ER_TRUNCATED_WRONG_VALUE),
155
"DECIMAL", tmp.c_ptr());
158
return decimal_value;
162
int Field_string::cmp(const unsigned char *a_ptr, const unsigned char *b_ptr)
164
uint32_t a_len, b_len;
166
if (field_charset->mbmaxlen != 1)
168
uint32_t char_len= field_length/field_charset->mbmaxlen;
169
a_len= my_charpos(field_charset, a_ptr, a_ptr + field_length, char_len);
170
b_len= my_charpos(field_charset, b_ptr, b_ptr + field_length, char_len);
173
a_len= b_len= field_length;
175
We have to remove end space to be able to compare multi-byte-characters
176
like in latin_de 'ae' and 0xe4
178
return field_charset->coll->strnncollsp(field_charset,
185
void Field_string::sort_string(unsigned char *to,uint32_t length)
187
uint32_t tmp= my_strnxfrm(field_charset,
190
assert(tmp == length);
194
void Field_string::sql_type(String &res) const
196
Session *session= table->in_use;
197
const CHARSET_INFO * const cs= res.charset();
200
length= cs->cset->snprintf(cs,(char*) res.ptr(),
201
res.alloced_length(), "%s(%d)",
202
((type() == DRIZZLE_TYPE_VARCHAR &&
203
!session->variables.new_mode) ?
204
(has_charset() ? "varchar" : "varbinary") :
205
(has_charset() ? "char" : "binary")),
206
(int) field_length / charset()->mbmaxlen);
211
unsigned char *Field_string::pack(unsigned char *to, const unsigned char *from,
213
bool low_byte_first __attribute__((unused)))
215
uint32_t length= cmin(field_length,max_length);
216
uint32_t local_char_length= max_length/field_charset->mbmaxlen;
217
if (length > local_char_length)
218
local_char_length= my_charpos(field_charset, from, from+length,
220
set_if_smaller(length, local_char_length);
221
while (length && from[length-1] == field_charset->pad_char)
224
// Length always stored little-endian
225
*to++= (unsigned char) length;
226
if (field_length > 255)
227
*to++= (unsigned char) (length >> 8);
229
// Store the actual bytes of the string
230
memcpy(to, from, length);
236
Unpack a string field from row data.
238
This method is used to unpack a string field from a master whose size
239
of the field is less than that of the slave. Note that there can be a
240
variety of field types represented with this class. Certain types like
241
ENUM or SET are processed differently. Hence, the upper byte of the
242
@c param_data argument contains the result of field->real_type() from
245
@param to Destination of the data
246
@param from Source of the data
247
@param param_data Real type (upper) and length (lower) values
249
@return New pointer into memory based on from + length of the data
251
const unsigned char *
252
Field_string::unpack(unsigned char *to,
253
const unsigned char *from,
255
bool low_byte_first __attribute__((unused)))
257
uint32_t from_length=
258
param_data ? cmin(param_data & 0x00ff, field_length) : field_length;
261
if (from_length > 255)
263
length= uint2korr(from);
267
length= (uint) *from++;
269
memcpy(to, from, length);
270
// Pad the string with the pad character of the fields charset
271
memset(to + length, field_charset->pad_char, field_length - length);
277
Save the field metadata for string fields.
279
Saves the real type in the first byte and the field length in the
280
second byte of the field metadata array at index of *metadata_ptr and
283
@param metadata_ptr First byte of field metadata
285
@returns number of bytes written to metadata_ptr
287
int Field_string::do_save_field_metadata(unsigned char *metadata_ptr)
289
*metadata_ptr= real_type();
290
*(metadata_ptr + 1)= field_length;
296
Compare two packed keys
303
insert_or_update 1 if this is an insert or update
311
int Field_string::pack_cmp(const unsigned char *a, const unsigned char *b, uint32_t length,
312
bool insert_or_update)
314
uint32_t a_length, b_length;
317
a_length= uint2korr(a);
318
b_length= uint2korr(b);
324
a_length= (uint) *a++;
325
b_length= (uint) *b++;
327
return field_charset->coll->strnncollsp(field_charset,
335
Compare a packed key against row.
337
@param key Original key
338
@param length Key length. (May be less than field length)
339
@param insert_or_update 1 if this is an insert or update
349
int Field_string::pack_cmp(const unsigned char *key, uint32_t length,
350
bool insert_or_update)
352
uint32_t row_length, local_key_length;
356
local_key_length= uint2korr(key);
360
local_key_length= (uint) *key++;
362
/* Only use 'length' of key, not field_length */
364
while (end > ptr && end[-1] == ' ')
366
row_length= (uint) (end - ptr);
368
return field_charset->coll->strnncollsp(field_charset,
370
key, local_key_length,
375
uint32_t Field_string::packed_col_length(const unsigned char *data_ptr, uint32_t length)
378
return uint2korr(data_ptr)+2;
379
return (uint) *data_ptr + 1;
383
uint32_t Field_string::max_packed_col_length(uint32_t max_length)
385
return (max_length > 255 ? 2 : 1)+max_length;
389
uint32_t Field_string::get_key_image(unsigned char *buff,
391
imagetype type_arg __attribute__((unused)))
393
uint32_t bytes = my_charpos(field_charset, (char*) ptr,
394
(char*) ptr + field_length,
395
length / field_charset->mbmaxlen);
396
memcpy(buff, ptr, bytes);
398
field_charset->cset->fill(field_charset, (char*) buff + bytes,
399
length - bytes, field_charset->pad_char);
404
Field *Field_string::new_field(MEM_ROOT *root, Table *new_table, bool keep_type)
407
field= Field::new_field(root, new_table, keep_type);