00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021 #include <config.h>
00022 #include <boost/lexical_cast.hpp>
00023 #include <drizzled/field/enum.h>
00024 #include <drizzled/error.h>
00025 #include <drizzled/table.h>
00026 #include <drizzled/session.h>
00027 #include <drizzled/typelib.h>
00028
00029 #include <sstream>
00030 #include <string>
00031
00032 namespace drizzled
00033 {
00034
00035
00036
00037
00038
00039
00040
00041 void Field_enum::store_type(uint64_t value)
00042 {
00043 value--;
00044
00045 #ifdef WORDS_BIGENDIAN
00046 if (getTable()->getShare()->db_low_byte_first)
00047 {
00048 int4store(ptr, (unsigned short) value);
00049 }
00050 else
00051 #endif
00052 longstore(ptr, (unsigned short) value);
00053 }
00054
00060 int Field_enum::store(const char *from, uint32_t length, const CHARSET_INFO * const)
00061 {
00062 uint32_t tmp;
00063
00064 ASSERT_COLUMN_MARKED_FOR_WRITE;
00065
00066
00067 length= field_charset->cset->lengthsp(field_charset, from, length);
00068 tmp= typelib->find_type2(from, length, field_charset);
00069 if (! tmp)
00070 {
00071 if (length < 6)
00072 {
00073
00074
00075 std::stringstream ss;
00076 ss << from;
00077 ss >> tmp;
00078
00079 if (tmp == 0 || tmp > typelib->count)
00080 {
00081 my_error(ER_INVALID_ENUM_VALUE, MYF(ME_FATALERROR), from);
00082 return 1;
00083 }
00084 }
00085 else
00086 {
00087 my_error(ER_INVALID_ENUM_VALUE, MYF(ME_FATALERROR), from);
00088 return 1;
00089 }
00090 }
00091 store_type((uint64_t) tmp);
00092 return 0;
00093 }
00094
00095 int Field_enum::store(double from)
00096 {
00097 return Field_enum::store((int64_t) from, false);
00098 }
00099
00107 int Field_enum::store(int64_t from, bool)
00108 {
00109 ASSERT_COLUMN_MARKED_FOR_WRITE;
00110
00111 if (from <= 0 || (uint64_t) from > typelib->count)
00112 {
00113
00114 std::string tmp(boost::lexical_cast<std::string>(from));
00115
00116 my_error(ER_INVALID_ENUM_VALUE, MYF(ME_FATALERROR), tmp.c_str());
00117 return 1;
00118 }
00119 store_type((uint64_t) (uint32_t) from);
00120 return 0;
00121 }
00122
00123 double Field_enum::val_real(void) const
00124 {
00125 return (double) Field_enum::val_int();
00126 }
00127
00128 int64_t Field_enum::val_int(void) const
00129 {
00130 ASSERT_COLUMN_MARKED_FOR_READ;
00131
00132 uint16_t tmp;
00133 #ifdef WORDS_BIGENDIAN
00134 if (getTable()->getShare()->db_low_byte_first)
00135 tmp= sint4korr(ptr);
00136 else
00137 #endif
00138 longget(tmp,ptr);
00139 return ((int64_t) tmp) + 1;
00140 }
00141
00142 String *Field_enum::val_str(String *, String *val_ptr) const
00143 {
00144 uint32_t tmp=(uint32_t) Field_enum::val_int();
00145
00146 ASSERT_COLUMN_MARKED_FOR_READ;
00147
00148 if (not tmp || tmp > typelib->count)
00149 {
00150 val_ptr->set("", 0, field_charset);
00151 }
00152 else
00153 {
00154 val_ptr->set((const char*) typelib->type_names[tmp-1], typelib->type_lengths[tmp-1], field_charset);
00155 }
00156
00157 return val_ptr;
00158 }
00159
00160 int Field_enum::cmp(const unsigned char *a_ptr, const unsigned char *b_ptr)
00161 {
00162 unsigned char *old= ptr;
00163 ptr= (unsigned char*) a_ptr;
00164 uint64_t a= Field_enum::val_int();
00165 ptr= (unsigned char*) b_ptr;
00166 uint64_t b= Field_enum::val_int();
00167 ptr= old;
00168 return (a < b) ? -1 : (a > b) ? 1 : 0;
00169 }
00170
00171 void Field_enum::sort_string(unsigned char *to,uint32_t )
00172 {
00173 uint64_t value=Field_enum::val_int()-1;
00174 to+=pack_length() -1;
00175 for (uint32_t i=0 ; i < pack_length() ; i++)
00176 {
00177 *to-- = (unsigned char) (value & 255);
00178 value>>=8;
00179 }
00180 }
00181
00182 void Field_enum::sql_type(String &res) const
00183 {
00184 char buffer[255];
00185 String enum_item(buffer, sizeof(buffer), res.charset());
00186
00187 res.length(0);
00188 res.append(STRING_WITH_LEN("enum("));
00189
00190 bool flag=0;
00191 uint32_t *len= typelib->type_lengths;
00192 for (const char **pos= typelib->type_names; *pos; pos++, len++)
00193 {
00194 size_t dummy_errors;
00195 if (flag)
00196 res.append(',');
00197
00198 enum_item.copy(*pos, *len, charset(), res.charset(), &dummy_errors);
00199 append_unescaped(&res, enum_item.c_ptr(), enum_item.length());
00200 flag= 1;
00201 }
00202 res.append(')');
00203 }
00204
00205 Field *Field_enum::new_field(memory::Root *root, Table *new_table,
00206 bool keep_type)
00207 {
00208 Field_enum *res= (Field_enum*) Field::new_field(root, new_table, keep_type);
00209 if (res)
00210 {
00211 res->typelib= typelib->copy_typelib(root);
00212 }
00213 return res;
00214 }
00215
00216 }