~drizzle-trunk/drizzle/development

« back to all changes in this revision

Viewing changes to drizzled/field/fstring.cc

  • Committer: Monty Taylor
  • Date: 2008-09-16 00:00:48 UTC
  • mto: This revision was merged to the branch mainline in revision 391.
  • Revision ID: monty@inaugust.com-20080916000048-3rvrv3gv9l0ad3gs
Fixed copyright headers in drizzled/

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/* - mode: c; c-basic-offset: 2; indent-tabs-mode: nil; -*-
 
2
 *  vim:expandtab:shiftwidth=2:tabstop=2:smarttab:
 
3
 *
 
4
 *  Copyright (C) 2008 MySQL
 
5
 *
 
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.
 
10
 *
 
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.
 
15
 *
 
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
 
19
 */
 
20
 
 
21
#ifdef USE_PRAGMA_IMPLEMENTATION
 
22
#pragma implementation                          // gcc: Class implementation
 
23
#endif
 
24
 
 
25
#include <drizzled/server_includes.h>
 
26
#include <drizzled/field/fstring.h>
 
27
#include <drizzled/drizzled_error_messages.h>
 
28
 
 
29
#define LONGLONG_TO_STRING_CONVERSION_BUFFER_SIZE 128
 
30
#define DECIMAL_TO_STRING_CONVERSION_BUFFER_SIZE 128
 
31
 
 
32
/****************************************************************************
 
33
** string type
 
34
** A string may be varchar or binary
 
35
****************************************************************************/
 
36
 
 
37
/* Copy a string and fill with space */
 
38
int Field_string::store(const char *from,uint length, const CHARSET_INFO * const cs)
 
39
{
 
40
  uint copy_length;
 
41
  const char *well_formed_error_pos;
 
42
  const char *cannot_convert_error_pos;
 
43
  const char *from_end_pos;
 
44
 
 
45
  /* See the comment for Field_long::store(long long) */
 
46
  assert(table->in_use == current_thd);
 
47
 
 
48
  copy_length= well_formed_copy_nchars(field_charset,
 
49
                                       (char*) ptr, field_length,
 
50
                                       cs, from, length,
 
51
                                       field_length / field_charset->mbmaxlen,
 
52
                                       &well_formed_error_pos,
 
53
                                       &cannot_convert_error_pos,
 
54
                                       &from_end_pos);
 
55
 
 
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);
 
61
 
 
62
  if (check_string_copy_error(this, well_formed_error_pos,
 
63
                              cannot_convert_error_pos, from + length, cs))
 
64
    return 2;
 
65
 
 
66
  return report_if_important_data(from_end_pos, from + length);
 
67
}
 
68
 
 
69
 
 
70
int Field_string::store(int64_t nr, bool unsigned_val)
 
71
{
 
72
  char buff[64];
 
73
  int  l;
 
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);
 
78
}
 
79
 
 
80
 
 
81
double Field_string::val_real(void)
 
82
{
 
83
  int error;
 
84
  char *end;
 
85
  const CHARSET_INFO * const cs= charset();
 
86
  double result;
 
87
  
 
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))))
 
93
  {
 
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());
 
101
  }
 
102
  return result;
 
103
}
 
104
 
 
105
 
 
106
int64_t Field_string::val_int(void)
 
107
{
 
108
  int error;
 
109
  char *end;
 
110
  const CHARSET_INFO * const cs= charset();
 
111
  int64_t result;
 
112
 
 
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))))
 
118
  {
 
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());
 
126
  }
 
127
  return result;
 
128
}
 
129
 
 
130
 
 
131
String *Field_string::val_str(String *val_buffer __attribute__((unused)),
 
132
                              String *val_ptr)
 
133
{
 
134
  /* See the comment for Field_long::store(long long) */
 
135
  assert(table->in_use == current_thd);
 
136
  uint length;
 
137
 
 
138
  length= field_charset->cset->lengthsp(field_charset, (const char*) ptr, field_length);
 
139
  val_ptr->set((const char*) ptr, length, field_charset);
 
140
 
 
141
  return val_ptr;
 
142
}
 
143
 
 
144
 
 
145
my_decimal *Field_string::val_decimal(my_decimal *decimal_value)
 
146
{
 
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)
 
150
  {
 
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());
 
159
  }
 
160
 
 
161
  return decimal_value;
 
162
}
 
163
 
 
164
 
 
165
int Field_string::cmp(const uchar *a_ptr, const uchar *b_ptr)
 
166
{
 
167
  uint a_len, b_len;
 
168
 
 
169
  if (field_charset->mbmaxlen != 1)
 
170
  {
 
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);
 
174
  }
 
175
  else
 
176
    a_len= b_len= field_length;
 
177
  /*
 
178
    We have to remove end space to be able to compare multi-byte-characters
 
179
    like in latin_de 'ae' and 0xe4
 
180
  */
 
181
  return field_charset->coll->strnncollsp(field_charset,
 
182
                                          a_ptr, a_len,
 
183
                                          b_ptr, b_len,
 
184
                                          0);
 
185
}
 
186
 
 
187
 
 
188
void Field_string::sort_string(uchar *to,uint length)
 
189
{
 
190
  uint tmp= my_strnxfrm(field_charset,
 
191
                                 to, length,
 
192
                                 ptr, field_length);
 
193
  assert(tmp == length);
 
194
}
 
195
 
 
196
 
 
197
void Field_string::sql_type(String &res) const
 
198
{
 
199
  THD *thd= table->in_use;
 
200
  const CHARSET_INFO * const cs= res.charset();
 
201
  uint32_t length;
 
202
 
 
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);
 
210
  res.length(length);
 
211
}
 
212
 
 
213
 
 
214
uchar *Field_string::pack(uchar *to, const uchar *from,
 
215
                          uint max_length,
 
216
                          bool low_byte_first __attribute__((unused)))
 
217
{
 
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,
 
222
                                  local_char_length);
 
223
  set_if_smaller(length, local_char_length);
 
224
  while (length && from[length-1] == field_charset->pad_char)
 
225
    length--;
 
226
 
 
227
  // Length always stored little-endian
 
228
  *to++= (uchar) length;
 
229
  if (field_length > 255)
 
230
    *to++= (uchar) (length >> 8);
 
231
 
 
232
  // Store the actual bytes of the string
 
233
  memcpy(to, from, length);
 
234
  return to+length;
 
235
}
 
236
 
 
237
 
 
238
/**
 
239
   Unpack a string field from row data.
 
240
 
 
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
 
246
   the master.
 
247
 
 
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
 
251
 
 
252
   @return  New pointer into memory based on from + length of the data
 
253
*/
 
254
const uchar *
 
255
Field_string::unpack(uchar *to,
 
256
                     const uchar *from,
 
257
                     uint param_data,
 
258
                     bool low_byte_first __attribute__((unused)))
 
259
{
 
260
  uint from_length=
 
261
    param_data ? min(param_data & 0x00ff, field_length) : field_length;
 
262
  uint length;
 
263
 
 
264
  if (from_length > 255)
 
265
  {
 
266
    length= uint2korr(from);
 
267
    from+= 2;
 
268
  }
 
269
  else
 
270
    length= (uint) *from++;
 
271
 
 
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);
 
275
  return from+length;
 
276
}
 
277
 
 
278
 
 
279
/**
 
280
   Save the field metadata for string fields.
 
281
 
 
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
 
284
   *(metadata_ptr + 1).
 
285
 
 
286
   @param   metadata_ptr   First byte of field metadata
 
287
 
 
288
   @returns number of bytes written to metadata_ptr
 
289
*/
 
290
int Field_string::do_save_field_metadata(uchar *metadata_ptr)
 
291
{
 
292
  *metadata_ptr= real_type();
 
293
  *(metadata_ptr + 1)= field_length;
 
294
  return 2;
 
295
}
 
296
 
 
297
 
 
298
/*
 
299
  Compare two packed keys
 
300
 
 
301
  SYNOPSIS
 
302
    pack_cmp()
 
303
     a                  New key
 
304
     b                  Original key
 
305
     length             Key length
 
306
     insert_or_update   1 if this is an insert or update
 
307
 
 
308
  RETURN
 
309
    < 0   a < b
 
310
    0     a = b
 
311
    > 0   a > b
 
312
*/
 
313
 
 
314
int Field_string::pack_cmp(const uchar *a, const uchar *b, uint length,
 
315
                           bool insert_or_update)
 
316
{
 
317
  uint a_length, b_length;
 
318
  if (length > 255)
 
319
  {
 
320
    a_length= uint2korr(a);
 
321
    b_length= uint2korr(b);
 
322
    a+= 2;
 
323
    b+= 2;
 
324
  }
 
325
  else
 
326
  {
 
327
    a_length= (uint) *a++;
 
328
    b_length= (uint) *b++;
 
329
  }
 
330
  return field_charset->coll->strnncollsp(field_charset,
 
331
                                          a, a_length,
 
332
                                          b, b_length,
 
333
                                          insert_or_update);
 
334
}
 
335
 
 
336
 
 
337
/**
 
338
  Compare a packed key against row.
 
339
 
 
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
 
343
 
 
344
  @return
 
345
    < 0   row < key
 
346
  @return
 
347
    0     row = key
 
348
  @return
 
349
    > 0   row > key
 
350
*/
 
351
 
 
352
int Field_string::pack_cmp(const uchar *key, uint length,
 
353
                           bool insert_or_update)
 
354
{
 
355
  uint row_length, local_key_length;
 
356
  uchar *end;
 
357
  if (length > 255)
 
358
  {
 
359
    local_key_length= uint2korr(key);
 
360
    key+= 2;
 
361
  }
 
362
  else
 
363
    local_key_length= (uint) *key++;
 
364
  
 
365
  /* Only use 'length' of key, not field_length */
 
366
  end= ptr + length;
 
367
  while (end > ptr && end[-1] == ' ')
 
368
    end--;
 
369
  row_length= (uint) (end - ptr);
 
370
 
 
371
  return field_charset->coll->strnncollsp(field_charset,
 
372
                                          ptr, row_length,
 
373
                                          key, local_key_length,
 
374
                                          insert_or_update);
 
375
}
 
376
 
 
377
 
 
378
uint Field_string::packed_col_length(const uchar *data_ptr, uint length)
 
379
{
 
380
  if (length > 255)
 
381
    return uint2korr(data_ptr)+2;
 
382
  return (uint) *data_ptr + 1;
 
383
}
 
384
 
 
385
 
 
386
uint Field_string::max_packed_col_length(uint max_length)
 
387
{
 
388
  return (max_length > 255 ? 2 : 1)+max_length;
 
389
}
 
390
 
 
391
 
 
392
uint Field_string::get_key_image(uchar *buff,
 
393
                                 uint length,
 
394
                                 imagetype type_arg __attribute__((unused)))
 
395
{
 
396
  uint bytes = my_charpos(field_charset, (char*) ptr,
 
397
                          (char*) ptr + field_length,
 
398
                          length / field_charset->mbmaxlen);
 
399
  memcpy(buff, ptr, bytes);
 
400
  if (bytes < length)
 
401
    field_charset->cset->fill(field_charset, (char*) buff + bytes,
 
402
                              length - bytes, field_charset->pad_char);
 
403
  return bytes;
 
404
}
 
405
 
 
406
 
 
407
Field *Field_string::new_field(MEM_ROOT *root, Table *new_table, bool keep_type)
 
408
{
 
409
  Field *field;
 
410
  field= Field::new_field(root, new_table, keep_type);
 
411
  return field;
 
412
}
 
413
 
 
414