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);
137
if (table->in_use->variables.sql_mode &
138
MODE_PAD_CHAR_TO_FULL_LENGTH)
139
length= my_charpos(field_charset, ptr, ptr + field_length, field_length);
141
length= field_charset->cset->lengthsp(field_charset, (const char*) ptr,
143
val_ptr->set((const char*) ptr, length, field_charset);
148
my_decimal *Field_string::val_decimal(my_decimal *decimal_value)
150
int err= str2my_decimal(E_DEC_FATAL_ERROR, (char*) ptr, field_length,
151
charset(), decimal_value);
152
if (!table->in_use->no_errors && err)
154
char buf[DECIMAL_TO_STRING_CONVERSION_BUFFER_SIZE];
155
const CHARSET_INFO * const cs= charset();
156
String tmp(buf, sizeof(buf), cs);
157
tmp.copy((char*) ptr, field_length, cs);
158
push_warning_printf(current_thd, DRIZZLE_ERROR::WARN_LEVEL_WARN,
159
ER_TRUNCATED_WRONG_VALUE,
160
ER(ER_TRUNCATED_WRONG_VALUE),
161
"DECIMAL", tmp.c_ptr());
164
return decimal_value;
168
int Field_string::cmp(const uchar *a_ptr, const uchar *b_ptr)
172
if (field_charset->mbmaxlen != 1)
174
uint char_len= field_length/field_charset->mbmaxlen;
175
a_len= my_charpos(field_charset, a_ptr, a_ptr + field_length, char_len);
176
b_len= my_charpos(field_charset, b_ptr, b_ptr + field_length, char_len);
179
a_len= b_len= field_length;
181
We have to remove end space to be able to compare multi-byte-characters
182
like in latin_de 'ae' and 0xe4
184
return field_charset->coll->strnncollsp(field_charset,
191
void Field_string::sort_string(uchar *to,uint length)
193
uint tmp= my_strnxfrm(field_charset,
196
assert(tmp == length);
200
void Field_string::sql_type(String &res) const
202
THD *thd= table->in_use;
203
const CHARSET_INFO * const cs= res.charset();
206
length= cs->cset->snprintf(cs,(char*) res.ptr(),
207
res.alloced_length(), "%s(%d)",
208
((type() == DRIZZLE_TYPE_VARCHAR &&
209
!thd->variables.new_mode) ?
210
(has_charset() ? "varchar" : "varbinary") :
211
(has_charset() ? "char" : "binary")),
212
(int) field_length / charset()->mbmaxlen);
217
uchar *Field_string::pack(uchar *to, const uchar *from,
219
bool low_byte_first __attribute__((unused)))
221
uint length= min(field_length,max_length);
222
uint local_char_length= max_length/field_charset->mbmaxlen;
223
if (length > local_char_length)
224
local_char_length= my_charpos(field_charset, from, from+length,
226
set_if_smaller(length, local_char_length);
227
while (length && from[length-1] == field_charset->pad_char)
230
// Length always stored little-endian
231
*to++= (uchar) length;
232
if (field_length > 255)
233
*to++= (uchar) (length >> 8);
235
// Store the actual bytes of the string
236
memcpy(to, from, length);
242
Unpack a string field from row data.
244
This method is used to unpack a string field from a master whose size
245
of the field is less than that of the slave. Note that there can be a
246
variety of field types represented with this class. Certain types like
247
ENUM or SET are processed differently. Hence, the upper byte of the
248
@c param_data argument contains the result of field->real_type() from
251
@param to Destination of the data
252
@param from Source of the data
253
@param param_data Real type (upper) and length (lower) values
255
@return New pointer into memory based on from + length of the data
258
Field_string::unpack(uchar *to,
261
bool low_byte_first __attribute__((unused)))
264
param_data ? min(param_data & 0x00ff, field_length) : field_length;
267
if (from_length > 255)
269
length= uint2korr(from);
273
length= (uint) *from++;
275
memcpy(to, from, length);
276
// Pad the string with the pad character of the fields charset
277
memset(to + length, field_charset->pad_char, field_length - length);
283
Save the field metadata for string fields.
285
Saves the real type in the first byte and the field length in the
286
second byte of the field metadata array at index of *metadata_ptr and
289
@param metadata_ptr First byte of field metadata
291
@returns number of bytes written to metadata_ptr
293
int Field_string::do_save_field_metadata(uchar *metadata_ptr)
295
*metadata_ptr= real_type();
296
*(metadata_ptr + 1)= field_length;
302
Compare two packed keys
309
insert_or_update 1 if this is an insert or update
317
int Field_string::pack_cmp(const uchar *a, const uchar *b, uint length,
318
bool insert_or_update)
320
uint a_length, b_length;
323
a_length= uint2korr(a);
324
b_length= uint2korr(b);
330
a_length= (uint) *a++;
331
b_length= (uint) *b++;
333
return field_charset->coll->strnncollsp(field_charset,
341
Compare a packed key against row.
343
@param key Original key
344
@param length Key length. (May be less than field length)
345
@param insert_or_update 1 if this is an insert or update
355
int Field_string::pack_cmp(const uchar *key, uint length,
356
bool insert_or_update)
358
uint row_length, local_key_length;
362
local_key_length= uint2korr(key);
366
local_key_length= (uint) *key++;
368
/* Only use 'length' of key, not field_length */
370
while (end > ptr && end[-1] == ' ')
372
row_length= (uint) (end - ptr);
374
return field_charset->coll->strnncollsp(field_charset,
376
key, local_key_length,
381
uint Field_string::packed_col_length(const uchar *data_ptr, uint length)
384
return uint2korr(data_ptr)+2;
385
return (uint) *data_ptr + 1;
389
uint Field_string::max_packed_col_length(uint max_length)
391
return (max_length > 255 ? 2 : 1)+max_length;
395
uint Field_string::get_key_image(uchar *buff,
397
imagetype type_arg __attribute__((unused)))
399
uint bytes = my_charpos(field_charset, (char*) ptr,
400
(char*) ptr + field_length,
401
length / field_charset->mbmaxlen);
402
memcpy(buff, ptr, bytes);
404
field_charset->cset->fill(field_charset, (char*) buff + bytes,
405
length - bytes, field_charset->pad_char);
410
Field *Field_string::new_field(MEM_ROOT *root, struct st_table *new_table,
414
field= Field::new_field(root, new_table, keep_type);