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
21
#ifdef USE_PRAGMA_IMPLEMENTATION
22
#pragma implementation // gcc: Class implementation
25
#include <drizzled/server_includes.h>
26
#include <drizzled/field/fstring.h>
27
#include <drizzled/drizzled_error_messages.h>
29
#define LONGLONG_TO_STRING_CONVERSION_BUFFER_SIZE 128
30
#define DECIMAL_TO_STRING_CONVERSION_BUFFER_SIZE 128
32
/****************************************************************************
34
** A string may be varchar or binary
35
****************************************************************************/
37
/* Copy a string and fill with space */
38
int Field_string::store(const char *from,uint length, const CHARSET_INFO * const cs)
41
const char *well_formed_error_pos;
42
const char *cannot_convert_error_pos;
43
const char *from_end_pos;
45
/* See the comment for Field_long::store(long long) */
46
assert(table->in_use == current_thd);
48
copy_length= well_formed_copy_nchars(field_charset,
49
(char*) ptr, field_length,
51
field_length / field_charset->mbmaxlen,
52
&well_formed_error_pos,
53
&cannot_convert_error_pos,
56
/* Append spaces if the string was shorter than the field. */
57
if (copy_length < field_length)
58
field_charset->cset->fill(field_charset,(char*) ptr+copy_length,
59
field_length-copy_length,
60
field_charset->pad_char);
62
if (check_string_copy_error(this, well_formed_error_pos,
63
cannot_convert_error_pos, from + length, cs))
66
return report_if_important_data(from_end_pos, from + length);
70
int Field_string::store(int64_t nr, bool unsigned_val)
74
const CHARSET_INFO * const cs= charset();
75
l= (cs->cset->int64_t10_to_str)(cs,buff,sizeof(buff),
76
unsigned_val ? 10 : -10, nr);
77
return Field_string::store(buff,(uint)l,cs);
81
double Field_string::val_real(void)
85
const CHARSET_INFO * const cs= charset();
88
result= my_strntod(cs,(char*) ptr,field_length,&end,&error);
89
if (!table->in_use->no_errors &&
90
(error || (field_length != (uint32_t)(end - (char*) ptr) &&
91
!check_if_only_end_space(cs, end,
92
(char*) ptr + field_length))))
94
char buf[DOUBLE_TO_STRING_CONVERSION_BUFFER_SIZE];
95
String tmp(buf, sizeof(buf), cs);
96
tmp.copy((char*) ptr, field_length, cs);
97
push_warning_printf(current_thd, DRIZZLE_ERROR::WARN_LEVEL_WARN,
98
ER_TRUNCATED_WRONG_VALUE,
99
ER(ER_TRUNCATED_WRONG_VALUE),
100
"DOUBLE", tmp.c_ptr());
106
int64_t Field_string::val_int(void)
110
const CHARSET_INFO * const cs= charset();
113
result= my_strntoll(cs, (char*) ptr,field_length,10,&end,&error);
114
if (!table->in_use->no_errors &&
115
(error || (field_length != (uint32_t)(end - (char*) ptr) &&
116
!check_if_only_end_space(cs, end,
117
(char*) ptr + field_length))))
119
char buf[LONGLONG_TO_STRING_CONVERSION_BUFFER_SIZE];
120
String tmp(buf, sizeof(buf), cs);
121
tmp.copy((char*) ptr, field_length, cs);
122
push_warning_printf(current_thd, DRIZZLE_ERROR::WARN_LEVEL_WARN,
123
ER_TRUNCATED_WRONG_VALUE,
124
ER(ER_TRUNCATED_WRONG_VALUE),
125
"INTEGER", tmp.c_ptr());
131
String *Field_string::val_str(String *val_buffer __attribute__((unused)),
134
/* See the comment for Field_long::store(long long) */
135
assert(table->in_use == current_thd);
138
length= field_charset->cset->lengthsp(field_charset, (const char*) ptr, field_length);
139
val_ptr->set((const char*) ptr, length, field_charset);
145
my_decimal *Field_string::val_decimal(my_decimal *decimal_value)
147
int err= str2my_decimal(E_DEC_FATAL_ERROR, (char*) ptr, field_length,
148
charset(), decimal_value);
149
if (!table->in_use->no_errors && err)
151
char buf[DECIMAL_TO_STRING_CONVERSION_BUFFER_SIZE];
152
const CHARSET_INFO * const cs= charset();
153
String tmp(buf, sizeof(buf), cs);
154
tmp.copy((char*) ptr, field_length, cs);
155
push_warning_printf(current_thd, DRIZZLE_ERROR::WARN_LEVEL_WARN,
156
ER_TRUNCATED_WRONG_VALUE,
157
ER(ER_TRUNCATED_WRONG_VALUE),
158
"DECIMAL", tmp.c_ptr());
161
return decimal_value;
165
int Field_string::cmp(const uchar *a_ptr, const uchar *b_ptr)
169
if (field_charset->mbmaxlen != 1)
171
uint char_len= field_length/field_charset->mbmaxlen;
172
a_len= my_charpos(field_charset, a_ptr, a_ptr + field_length, char_len);
173
b_len= my_charpos(field_charset, b_ptr, b_ptr + field_length, char_len);
176
a_len= b_len= field_length;
178
We have to remove end space to be able to compare multi-byte-characters
179
like in latin_de 'ae' and 0xe4
181
return field_charset->coll->strnncollsp(field_charset,
188
void Field_string::sort_string(uchar *to,uint length)
190
uint tmp= my_strnxfrm(field_charset,
193
assert(tmp == length);
197
void Field_string::sql_type(String &res) const
199
THD *thd= table->in_use;
200
const CHARSET_INFO * const cs= res.charset();
203
length= cs->cset->snprintf(cs,(char*) res.ptr(),
204
res.alloced_length(), "%s(%d)",
205
((type() == DRIZZLE_TYPE_VARCHAR &&
206
!thd->variables.new_mode) ?
207
(has_charset() ? "varchar" : "varbinary") :
208
(has_charset() ? "char" : "binary")),
209
(int) field_length / charset()->mbmaxlen);
214
uchar *Field_string::pack(uchar *to, const uchar *from,
216
bool low_byte_first __attribute__((unused)))
218
uint length= min(field_length,max_length);
219
uint local_char_length= max_length/field_charset->mbmaxlen;
220
if (length > local_char_length)
221
local_char_length= my_charpos(field_charset, from, from+length,
223
set_if_smaller(length, local_char_length);
224
while (length && from[length-1] == field_charset->pad_char)
227
// Length always stored little-endian
228
*to++= (uchar) length;
229
if (field_length > 255)
230
*to++= (uchar) (length >> 8);
232
// Store the actual bytes of the string
233
memcpy(to, from, length);
239
Unpack a string field from row data.
241
This method is used to unpack a string field from a master whose size
242
of the field is less than that of the slave. Note that there can be a
243
variety of field types represented with this class. Certain types like
244
ENUM or SET are processed differently. Hence, the upper byte of the
245
@c param_data argument contains the result of field->real_type() from
248
@param to Destination of the data
249
@param from Source of the data
250
@param param_data Real type (upper) and length (lower) values
252
@return New pointer into memory based on from + length of the data
255
Field_string::unpack(uchar *to,
258
bool low_byte_first __attribute__((unused)))
261
param_data ? min(param_data & 0x00ff, field_length) : field_length;
264
if (from_length > 255)
266
length= uint2korr(from);
270
length= (uint) *from++;
272
memcpy(to, from, length);
273
// Pad the string with the pad character of the fields charset
274
memset(to + length, field_charset->pad_char, field_length - length);
280
Save the field metadata for string fields.
282
Saves the real type in the first byte and the field length in the
283
second byte of the field metadata array at index of *metadata_ptr and
286
@param metadata_ptr First byte of field metadata
288
@returns number of bytes written to metadata_ptr
290
int Field_string::do_save_field_metadata(uchar *metadata_ptr)
292
*metadata_ptr= real_type();
293
*(metadata_ptr + 1)= field_length;
299
Compare two packed keys
306
insert_or_update 1 if this is an insert or update
314
int Field_string::pack_cmp(const uchar *a, const uchar *b, uint length,
315
bool insert_or_update)
317
uint a_length, b_length;
320
a_length= uint2korr(a);
321
b_length= uint2korr(b);
327
a_length= (uint) *a++;
328
b_length= (uint) *b++;
330
return field_charset->coll->strnncollsp(field_charset,
338
Compare a packed key against row.
340
@param key Original key
341
@param length Key length. (May be less than field length)
342
@param insert_or_update 1 if this is an insert or update
352
int Field_string::pack_cmp(const uchar *key, uint length,
353
bool insert_or_update)
355
uint row_length, local_key_length;
359
local_key_length= uint2korr(key);
363
local_key_length= (uint) *key++;
365
/* Only use 'length' of key, not field_length */
367
while (end > ptr && end[-1] == ' ')
369
row_length= (uint) (end - ptr);
371
return field_charset->coll->strnncollsp(field_charset,
373
key, local_key_length,
378
uint Field_string::packed_col_length(const uchar *data_ptr, uint length)
381
return uint2korr(data_ptr)+2;
382
return (uint) *data_ptr + 1;
386
uint Field_string::max_packed_col_length(uint max_length)
388
return (max_length > 255 ? 2 : 1)+max_length;
392
uint Field_string::get_key_image(uchar *buff,
394
imagetype type_arg __attribute__((unused)))
396
uint bytes = my_charpos(field_charset, (char*) ptr,
397
(char*) ptr + field_length,
398
length / field_charset->mbmaxlen);
399
memcpy(buff, ptr, bytes);
401
field_charset->cset->fill(field_charset, (char*) buff + bytes,
402
length - bytes, field_charset->pad_char);
407
Field *Field_string::new_field(MEM_ROOT *root, Table *new_table, bool keep_type)
410
field= Field::new_field(root, new_table, keep_type);