~drizzle-trunk/drizzle/development

« back to all changes in this revision

Viewing changes to drizzled/field/set.cc

Merged build changes from Antony.

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/field/set.h>
 
26
 
 
27
/*
 
28
   set type.
 
29
   This is a string which can have a collection of different values.
 
30
   Each string value is separated with a ','.
 
31
   For example "One,two,five"
 
32
   If one uses this string in a number context one gets the bits as a int64_t
 
33
   number.
 
34
*/
 
35
 
 
36
const char field_separator=',';
 
37
 
 
38
int Field_set::store(const char *from,uint length,CHARSET_INFO *cs)
 
39
{
 
40
  bool got_warning= 0;
 
41
  int err= 0;
 
42
  char *not_used;
 
43
  uint not_used2;
 
44
  uint32_t not_used_offset;
 
45
  char buff[STRING_BUFFER_USUAL_SIZE];
 
46
  String tmpstr(buff,sizeof(buff), &my_charset_bin);
 
47
 
 
48
  /* Convert character set if necessary */
 
49
  if (String::needs_conversion(length, cs, field_charset, &not_used_offset))
 
50
  { 
 
51
    uint dummy_errors;
 
52
    tmpstr.copy(from, length, cs, field_charset, &dummy_errors);
 
53
    from= tmpstr.ptr();
 
54
    length=  tmpstr.length();
 
55
  }
 
56
  uint64_t tmp= find_set(typelib, from, length, field_charset,
 
57
                          &not_used, &not_used2, &got_warning);
 
58
  if (!tmp && length && length < 22)
 
59
  {
 
60
    /* This is for reading numbers with LOAD DATA INFILE */
 
61
    char *end;
 
62
    tmp=my_strntoull(cs,from,length,10,&end,&err);
 
63
    if (err || end != from+length ||
 
64
        tmp > (uint64_t) (((int64_t) 1 << typelib->count) - (int64_t) 1))
 
65
    {
 
66
      tmp=0;      
 
67
      set_warning(MYSQL_ERROR::WARN_LEVEL_WARN, ER_WARN_DATA_TRUNCATED, 1);
 
68
    }
 
69
  }
 
70
  else if (got_warning)
 
71
    set_warning(MYSQL_ERROR::WARN_LEVEL_WARN, ER_WARN_DATA_TRUNCATED, 1);
 
72
  store_type(tmp);
 
73
  return err;
 
74
}
 
75
 
 
76
 
 
77
int Field_set::store(int64_t nr,
 
78
                     bool unsigned_val __attribute__((unused)))
 
79
{
 
80
  int error= 0;
 
81
  uint64_t max_nr= set_bits(uint64_t, typelib->count);
 
82
  if ((uint64_t) nr > max_nr)
 
83
  {
 
84
    nr&= max_nr;
 
85
    set_warning(MYSQL_ERROR::WARN_LEVEL_WARN, ER_WARN_DATA_TRUNCATED, 1);
 
86
    error=1;
 
87
  }
 
88
  store_type((uint64_t) nr);
 
89
  return error;
 
90
}
 
91
 
 
92
 
 
93
String *Field_set::val_str(String *val_buffer,
 
94
                           String *val_ptr __attribute__((unused)))
 
95
{
 
96
  uint64_t tmp=(uint64_t) Field_enum::val_int();
 
97
  uint bitnr=0;
 
98
 
 
99
  val_buffer->length(0);
 
100
  val_buffer->set_charset(field_charset);
 
101
  while (tmp && bitnr < (uint) typelib->count)
 
102
  {
 
103
    if (tmp & 1)
 
104
    {
 
105
      if (val_buffer->length())
 
106
        val_buffer->append(&field_separator, 1, &my_charset_latin1);
 
107
      String str(typelib->type_names[bitnr],
 
108
                 typelib->type_lengths[bitnr],
 
109
                 field_charset);
 
110
      val_buffer->append(str);
 
111
    }
 
112
    tmp>>=1;
 
113
    bitnr++;
 
114
  }
 
115
  return val_buffer;
 
116
}
 
117
 
 
118
 
 
119
void Field_set::sql_type(String &res) const
 
120
{
 
121
  char buffer[255];
 
122
  String set_item(buffer, sizeof(buffer), res.charset());
 
123
 
 
124
  res.length(0);
 
125
  res.append(STRING_WITH_LEN("set("));
 
126
 
 
127
  bool flag=0;
 
128
  uint *len= typelib->type_lengths;
 
129
  for (const char **pos= typelib->type_names; *pos; pos++, len++)
 
130
  {
 
131
    uint dummy_errors;
 
132
    if (flag)
 
133
      res.append(',');
 
134
    /* convert to res.charset() == utf8, then quote */
 
135
    set_item.copy(*pos, *len, charset(), res.charset(), &dummy_errors);
 
136
    append_unescaped(&res, set_item.ptr(), set_item.length());
 
137
    flag= 1;
 
138
  }
 
139
  res.append(')');
 
140
}
 
141