~drizzle-trunk/drizzle/development

« back to all changes in this revision

Viewing changes to drizzled/field/fstring.cc

  • Committer: Monty Taylor
  • Date: 2009-09-30 07:01:32 UTC
  • mto: This revision was merged to the branch mainline in revision 1184.
  • Revision ID: mordred@inaugust.com-20090930070132-b1ol1xu1rpajdddy
Small namespace cleanup.

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
 
 
22
 
#include <drizzled/server_includes.h>
23
 
#include <drizzled/field/fstring.h>
24
 
#include <drizzled/error.h>
25
 
 
26
 
#define LONGLONG_TO_STRING_CONVERSION_BUFFER_SIZE 128
27
 
#define DECIMAL_TO_STRING_CONVERSION_BUFFER_SIZE 128
28
 
 
29
 
/****************************************************************************
30
 
** string type
31
 
** A string may be varchar or binary
32
 
****************************************************************************/
33
 
 
34
 
/* Copy a string and fill with space */
35
 
int Field_string::store(const char *from,uint32_t length, const CHARSET_INFO * const cs)
36
 
{
37
 
  uint32_t copy_length;
38
 
  const char *well_formed_error_pos;
39
 
  const char *cannot_convert_error_pos;
40
 
  const char *from_end_pos;
41
 
 
42
 
  /* See the comment for Field_long::store(int64_t) */
43
 
  assert(table->in_use == current_session);
44
 
 
45
 
  copy_length= well_formed_copy_nchars(field_charset,
46
 
                                       (char*) ptr, field_length,
47
 
                                       cs, from, length,
48
 
                                       field_length / field_charset->mbmaxlen,
49
 
                                       &well_formed_error_pos,
50
 
                                       &cannot_convert_error_pos,
51
 
                                       &from_end_pos);
52
 
 
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);
58
 
 
59
 
  if (check_string_copy_error(this, well_formed_error_pos,
60
 
                              cannot_convert_error_pos, from + length, cs))
61
 
    return 2;
62
 
 
63
 
  return report_if_important_data(from_end_pos, from + length);
64
 
}
65
 
 
66
 
 
67
 
int Field_string::store(int64_t nr, bool unsigned_val)
68
 
{
69
 
  char buff[64];
70
 
  int  l;
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);
75
 
}
76
 
 
77
 
 
78
 
double Field_string::val_real(void)
79
 
{
80
 
  int error;
81
 
  char *end;
82
 
  const CHARSET_INFO * const cs= charset();
83
 
  double result;
84
 
  
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))))
90
 
  {
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());
98
 
  }
99
 
  return result;
100
 
}
101
 
 
102
 
 
103
 
int64_t Field_string::val_int(void)
104
 
{
105
 
  int error;
106
 
  char *end;
107
 
  const CHARSET_INFO * const cs= charset();
108
 
  int64_t result;
109
 
 
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))))
115
 
  {
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());
123
 
  }
124
 
  return result;
125
 
}
126
 
 
127
 
 
128
 
String *Field_string::val_str(String *val_buffer __attribute__((unused)),
129
 
                              String *val_ptr)
130
 
{
131
 
  /* See the comment for Field_long::store(int64_t) */
132
 
  assert(table->in_use == current_session);
133
 
  uint32_t length;
134
 
 
135
 
  length= field_charset->cset->lengthsp(field_charset, (const char*) ptr, field_length);
136
 
  val_ptr->set((const char*) ptr, length, field_charset);
137
 
 
138
 
  return val_ptr;
139
 
}
140
 
 
141
 
 
142
 
my_decimal *Field_string::val_decimal(my_decimal *decimal_value)
143
 
{
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)
147
 
  {
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());
156
 
  }
157
 
 
158
 
  return decimal_value;
159
 
}
160
 
 
161
 
 
162
 
int Field_string::cmp(const unsigned char *a_ptr, const unsigned char *b_ptr)
163
 
{
164
 
  uint32_t a_len, b_len;
165
 
 
166
 
  if (field_charset->mbmaxlen != 1)
167
 
  {
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);
171
 
  }
172
 
  else
173
 
    a_len= b_len= field_length;
174
 
  /*
175
 
    We have to remove end space to be able to compare multi-byte-characters
176
 
    like in latin_de 'ae' and 0xe4
177
 
  */
178
 
  return field_charset->coll->strnncollsp(field_charset,
179
 
                                          a_ptr, a_len,
180
 
                                          b_ptr, b_len,
181
 
                                          0);
182
 
}
183
 
 
184
 
 
185
 
void Field_string::sort_string(unsigned char *to,uint32_t length)
186
 
{
187
 
  uint32_t tmp= my_strnxfrm(field_charset,
188
 
                                 to, length,
189
 
                                 ptr, field_length);
190
 
  assert(tmp == length);
191
 
}
192
 
 
193
 
 
194
 
void Field_string::sql_type(String &res) const
195
 
{
196
 
  Session *session= table->in_use;
197
 
  const CHARSET_INFO * const cs= res.charset();
198
 
  uint32_t length;
199
 
 
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);
207
 
  res.length(length);
208
 
}
209
 
 
210
 
 
211
 
unsigned char *Field_string::pack(unsigned char *to, const unsigned char *from,
212
 
                          uint32_t max_length,
213
 
                          bool low_byte_first __attribute__((unused)))
214
 
{
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,
219
 
                                  local_char_length);
220
 
  set_if_smaller(length, local_char_length);
221
 
  while (length && from[length-1] == field_charset->pad_char)
222
 
    length--;
223
 
 
224
 
  // Length always stored little-endian
225
 
  *to++= (unsigned char) length;
226
 
  if (field_length > 255)
227
 
    *to++= (unsigned char) (length >> 8);
228
 
 
229
 
  // Store the actual bytes of the string
230
 
  memcpy(to, from, length);
231
 
  return to+length;
232
 
}
233
 
 
234
 
 
235
 
/**
236
 
   Unpack a string field from row data.
237
 
 
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
243
 
   the master.
244
 
 
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
248
 
 
249
 
   @return  New pointer into memory based on from + length of the data
250
 
*/
251
 
const unsigned char *
252
 
Field_string::unpack(unsigned char *to,
253
 
                     const unsigned char *from,
254
 
                     uint32_t param_data,
255
 
                     bool low_byte_first __attribute__((unused)))
256
 
{
257
 
  uint32_t from_length=
258
 
    param_data ? cmin(param_data & 0x00ff, field_length) : field_length;
259
 
  uint32_t length;
260
 
 
261
 
  if (from_length > 255)
262
 
  {
263
 
    length= uint2korr(from);
264
 
    from+= 2;
265
 
  }
266
 
  else
267
 
    length= (uint) *from++;
268
 
 
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);
272
 
  return from+length;
273
 
}
274
 
 
275
 
 
276
 
/**
277
 
   Save the field metadata for string fields.
278
 
 
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
281
 
   *(metadata_ptr + 1).
282
 
 
283
 
   @param   metadata_ptr   First byte of field metadata
284
 
 
285
 
   @returns number of bytes written to metadata_ptr
286
 
*/
287
 
int Field_string::do_save_field_metadata(unsigned char *metadata_ptr)
288
 
{
289
 
  *metadata_ptr= real_type();
290
 
  *(metadata_ptr + 1)= field_length;
291
 
  return 2;
292
 
}
293
 
 
294
 
 
295
 
/*
296
 
  Compare two packed keys
297
 
 
298
 
  SYNOPSIS
299
 
    pack_cmp()
300
 
     a                  New key
301
 
     b                  Original key
302
 
     length             Key length
303
 
     insert_or_update   1 if this is an insert or update
304
 
 
305
 
  RETURN
306
 
    < 0   a < b
307
 
    0     a = b
308
 
    > 0   a > b
309
 
*/
310
 
 
311
 
int Field_string::pack_cmp(const unsigned char *a, const unsigned char *b, uint32_t length,
312
 
                           bool insert_or_update)
313
 
{
314
 
  uint32_t a_length, b_length;
315
 
  if (length > 255)
316
 
  {
317
 
    a_length= uint2korr(a);
318
 
    b_length= uint2korr(b);
319
 
    a+= 2;
320
 
    b+= 2;
321
 
  }
322
 
  else
323
 
  {
324
 
    a_length= (uint) *a++;
325
 
    b_length= (uint) *b++;
326
 
  }
327
 
  return field_charset->coll->strnncollsp(field_charset,
328
 
                                          a, a_length,
329
 
                                          b, b_length,
330
 
                                          insert_or_update);
331
 
}
332
 
 
333
 
 
334
 
/**
335
 
  Compare a packed key against row.
336
 
 
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
340
 
 
341
 
  @return
342
 
    < 0   row < key
343
 
  @return
344
 
    0     row = key
345
 
  @return
346
 
    > 0   row > key
347
 
*/
348
 
 
349
 
int Field_string::pack_cmp(const unsigned char *key, uint32_t length,
350
 
                           bool insert_or_update)
351
 
{
352
 
  uint32_t row_length, local_key_length;
353
 
  unsigned char *end;
354
 
  if (length > 255)
355
 
  {
356
 
    local_key_length= uint2korr(key);
357
 
    key+= 2;
358
 
  }
359
 
  else
360
 
    local_key_length= (uint) *key++;
361
 
  
362
 
  /* Only use 'length' of key, not field_length */
363
 
  end= ptr + length;
364
 
  while (end > ptr && end[-1] == ' ')
365
 
    end--;
366
 
  row_length= (uint) (end - ptr);
367
 
 
368
 
  return field_charset->coll->strnncollsp(field_charset,
369
 
                                          ptr, row_length,
370
 
                                          key, local_key_length,
371
 
                                          insert_or_update);
372
 
}
373
 
 
374
 
 
375
 
uint32_t Field_string::packed_col_length(const unsigned char *data_ptr, uint32_t length)
376
 
{
377
 
  if (length > 255)
378
 
    return uint2korr(data_ptr)+2;
379
 
  return (uint) *data_ptr + 1;
380
 
}
381
 
 
382
 
 
383
 
uint32_t Field_string::max_packed_col_length(uint32_t max_length)
384
 
{
385
 
  return (max_length > 255 ? 2 : 1)+max_length;
386
 
}
387
 
 
388
 
 
389
 
uint32_t Field_string::get_key_image(unsigned char *buff,
390
 
                                 uint32_t length,
391
 
                                 imagetype type_arg __attribute__((unused)))
392
 
{
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);
397
 
  if (bytes < length)
398
 
    field_charset->cset->fill(field_charset, (char*) buff + bytes,
399
 
                              length - bytes, field_charset->pad_char);
400
 
  return bytes;
401
 
}
402
 
 
403
 
 
404
 
Field *Field_string::new_field(MEM_ROOT *root, Table *new_table, bool keep_type)
405
 
{
406
 
  Field *field;
407
 
  field= Field::new_field(root, new_table, keep_type);
408
 
  return field;
409
 
}
410
 
 
411