summaryrefslogtreecommitdiff
path: root/sql/field.h
diff options
context:
space:
mode:
Diffstat (limited to 'sql/field.h')
-rw-r--r--sql/field.h324
1 files changed, 191 insertions, 133 deletions
diff --git a/sql/field.h b/sql/field.h
index c3a90dc0754..9604f3fe227 100644
--- a/sql/field.h
+++ b/sql/field.h
@@ -1,4 +1,7 @@
-/* Copyright (C) 2000-2006 MySQL AB
+#ifndef FIELD_INCLUDED
+#define FIELD_INCLUDED
+
+/* Copyright 2000-2008 MySQL AB, 2008 Sun Microsystems, Inc.
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
@@ -13,7 +16,6 @@
along with this program; if not, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */
-
/*
Because of the function new_field() all field classes that have static
variables must declare the size_of() member function.
@@ -29,6 +31,8 @@ const uint32 max_field_size= (uint32) 4294967295U;
class Send_field;
class Protocol;
class Create_field;
+class Relay_log_info;
+
struct st_cache_field;
int field_conv(Field *to,Field *from);
@@ -48,7 +52,8 @@ class Field
Field(const Item &); /* Prevent use of these */
void operator=(Field &);
public:
- static void *operator new(size_t size) {return sql_alloc(size); }
+ static void *operator new(size_t size) throw ()
+ { return sql_alloc(size); }
static void operator delete(void *ptr_arg, size_t size) { TRASH(ptr_arg, size); }
uchar *ptr; // Position to field in record
@@ -57,8 +62,8 @@ public:
Note that you can use table->in_use as replacement for current_thd member
only inside of val_*() and store() members (e.g. you can't use it in cons)
*/
- struct st_table *table; // Pointer for table
- struct st_table *orig_table; // Pointer to original table
+ TABLE *table; // Pointer for table
+ TABLE *orig_table; // Pointer to original table
const char **table_name, *field_name;
LEX_STRING comment;
/* Field is part of the following keys */
@@ -144,7 +149,7 @@ public:
virtual bool eq(Field *field)
{
return (ptr == field->ptr && null_ptr == field->null_ptr &&
- null_bit == field->null_bit);
+ null_bit == field->null_bit && field->type() == type());
}
virtual bool eq_def(Field *field);
@@ -161,7 +166,8 @@ public:
table, which is located on disk).
*/
virtual uint32 pack_length_in_rec() const { return pack_length(); }
- virtual int compatible_field_size(uint field_metadata);
+ virtual int compatible_field_size(uint field_metadata,
+ const Relay_log_info *);
virtual uint pack_length_from_metadata(uint field_metadata)
{ return field_metadata; }
/*
@@ -205,7 +211,7 @@ public:
memcpy(ptr, ptr + l_offset, pack_length());
if (null_ptr)
*null_ptr= ((*null_ptr & (uchar) ~null_bit) |
- null_ptr[l_offset] & null_bit);
+ (null_ptr[l_offset] & null_bit));
}
virtual bool binary() const { return 1; }
virtual bool zero_pack() const { return 1; }
@@ -297,12 +303,12 @@ public:
*/
virtual bool can_be_compared_as_longlong() const { return FALSE; }
virtual void free() {}
- virtual Field *new_field(MEM_ROOT *root, struct st_table *new_table,
+ virtual Field *new_field(MEM_ROOT *root, TABLE *new_table,
bool keep_type);
- virtual Field *new_key_field(MEM_ROOT *root, struct st_table *new_table,
+ virtual Field *new_key_field(MEM_ROOT *root, TABLE *new_table,
uchar *new_ptr, uchar *new_null_ptr,
uint new_null_bit);
- Field *clone(MEM_ROOT *mem_root, struct st_table *new_table);
+ Field *clone(MEM_ROOT *mem_root, TABLE *new_table);
inline void move_field(uchar *ptr_arg,uchar *null_ptr_arg,uchar null_bit_arg)
{
ptr=ptr_arg; null_ptr=null_ptr_arg; null_bit=null_bit_arg;
@@ -403,32 +409,11 @@ public:
DBUG_RETURN(result);
}
- virtual uchar *pack_key(uchar* to, const uchar *from,
- uint max_length, bool low_byte_first)
- {
- return pack(to, from, max_length, low_byte_first);
- }
- virtual uchar *pack_key_from_key_image(uchar* to, const uchar *from,
- uint max_length, bool low_byte_first)
- {
- return pack(to, from, max_length, low_byte_first);
- }
- virtual const uchar *unpack_key(uchar* to, const uchar *from,
- uint max_length, bool low_byte_first)
- {
- return unpack(to, from, max_length, low_byte_first);
- }
virtual uint packed_col_length(const uchar *to, uint length)
{ return length;}
virtual uint max_packed_col_length(uint max_length)
{ return max_length;}
- virtual int pack_cmp(const uchar *a,const uchar *b, uint key_length_arg,
- my_bool insert_or_update)
- { return cmp(a,b); }
- virtual int pack_cmp(const uchar *b, uint key_length_arg,
- my_bool insert_or_update)
- { return cmp(ptr,b); }
uint offset(uchar *record)
{
return (uint) (ptr - record);
@@ -468,6 +453,13 @@ public:
/* maximum possible display length */
virtual uint32 max_display_length()= 0;
+ /**
+ Whether a field being created is compatible with a existing one.
+
+ Used by the ALTER TABLE code to evaluate whether the new definition
+ of a table is compatible with the old definition so that it can
+ determine if data needs to be copied over (table data change).
+ */
virtual uint is_equal(Create_field *new_field);
/* convert decimal to longlong with overflow check */
longlong convert_decimal2longlong(const my_decimal *val, bool unsigned_flag,
@@ -528,11 +520,86 @@ private:
*/
virtual int do_save_field_metadata(uchar *metadata_ptr)
{ return 0; }
+
+protected:
+ /*
+ Helper function to pack()/unpack() int32 values
+ */
+ static void handle_int32(uchar *to, const uchar *from,
+ bool low_byte_first_from, bool low_byte_first_to)
+ {
+ int32 val;
+#ifdef WORDS_BIGENDIAN
+ if (low_byte_first_from)
+ val = sint4korr(from);
+ else
+#endif
+ longget(val, from);
+
+#ifdef WORDS_BIGENDIAN
+ if (low_byte_first_to)
+ int4store(to, val);
+ else
+#endif
+ longstore(to, val);
+ }
+
+ /*
+ Helper function to pack()/unpack() int64 values
+ */
+ static void handle_int64(uchar* to, const uchar *from,
+ bool low_byte_first_from, bool low_byte_first_to)
+ {
+ int64 val;
+#ifdef WORDS_BIGENDIAN
+ if (low_byte_first_from)
+ val = sint8korr(from);
+ else
+#endif
+ longlongget(val, from);
+
+#ifdef WORDS_BIGENDIAN
+ if (low_byte_first_to)
+ int8store(to, val);
+ else
+#endif
+ longlongstore(to, val);
+ }
+
+ uchar *pack_int32(uchar *to, const uchar *from, bool low_byte_first_to)
+ {
+ handle_int32(to, from, table->s->db_low_byte_first, low_byte_first_to);
+ return to + sizeof(int32);
+ }
+
+ const uchar *unpack_int32(uchar* to, const uchar *from,
+ bool low_byte_first_from)
+ {
+ handle_int32(to, from, low_byte_first_from, table->s->db_low_byte_first);
+ return from + sizeof(int32);
+ }
+
+ uchar *pack_int64(uchar* to, const uchar *from, bool low_byte_first_to)
+ {
+ handle_int64(to, from, table->s->db_low_byte_first, low_byte_first_to);
+ return to + sizeof(int64);
+ }
+
+ const uchar *unpack_int64(uchar* to, const uchar *from,
+ bool low_byte_first_from)
+ {
+ handle_int64(to, from, low_byte_first_from, table->s->db_low_byte_first);
+ return from + sizeof(int64);
+ }
};
class Field_num :public Field {
public:
+ /**
+ The scale of the Field's value, i.e. the number of digits to the right
+ of the decimal point.
+ */
const uint8 dec;
bool zerofill,unsigned_flag; // Purify cannot handle bit fields
Field_num(uchar *ptr_arg,uint32 len_arg, uchar *null_ptr_arg,
@@ -593,7 +660,8 @@ public:
class Field_longstr :public Field_str
{
protected:
- int report_if_important_data(const char *ptr, const char *end);
+ int report_if_important_data(const char *ptr, const char *end,
+ bool count_spaces);
public:
Field_longstr(uchar *ptr_arg, uint32 len_arg, uchar *null_ptr_arg,
uchar null_bit_arg, utype unireg_check_arg,
@@ -690,6 +758,11 @@ public:
Field_new_decimal(uint32 len_arg, bool maybe_null_arg,
const char *field_name_arg, uint8 dec_arg,
bool unsigned_arg);
+ /*
+ Create a field to hold a decimal value from an item.
+ Truncates the precision and/or scale if necessary.
+ */
+ static Field_new_decimal *new_decimal_field(const Item *item);
enum_field_types type() const { return MYSQL_TYPE_NEWDECIMAL;}
enum ha_base_keytype key_type() const { return HA_KEYTYPE_BINARY; }
Item_result result_type () const { return DECIMAL_RESULT; }
@@ -714,7 +787,8 @@ public:
uint32 pack_length() const { return (uint32) bin_size; }
uint pack_length_from_metadata(uint field_metadata);
uint row_pack_length() { return pack_length(); }
- int compatible_field_size(uint field_metadata);
+ int compatible_field_size(uint field_metadata,
+ const Relay_log_info *rli);
uint is_equal(Create_field *new_field);
virtual const uchar *unpack(uchar* to, const uchar *from,
uint param_data, bool low_byte_first);
@@ -914,43 +988,16 @@ public:
void sql_type(String &str) const;
uint32 max_display_length() { return MY_INT32_NUM_DECIMAL_DIGITS; }
virtual uchar *pack(uchar* to, const uchar *from,
- uint max_length, bool low_byte_first)
+ uint max_length __attribute__((unused)),
+ bool low_byte_first)
{
- int32 val;
-#ifdef WORDS_BIGENDIAN
- if (table->s->db_low_byte_first)
- val = sint4korr(from);
- else
-#endif
- longget(val, from);
-
-#ifdef WORDS_BIGENDIAN
- if (low_byte_first)
- int4store(to, val);
- else
-#endif
- longstore(to, val);
- return to + sizeof(val);
+ return pack_int32(to, from, low_byte_first);
}
-
virtual const uchar *unpack(uchar* to, const uchar *from,
- uint param_data, bool low_byte_first)
+ uint param_data __attribute__((unused)),
+ bool low_byte_first)
{
- int32 val;
-#ifdef WORDS_BIGENDIAN
- if (low_byte_first)
- val = sint4korr(from);
- else
-#endif
- longget(val, from);
-
-#ifdef WORDS_BIGENDIAN
- if (table->s->db_low_byte_first)
- int4store(to, val);
- else
-#endif
- longstore(to, val);
- return from + sizeof(val);
+ return unpack_int32(to, from, low_byte_first);
}
};
@@ -995,43 +1042,16 @@ public:
bool can_be_compared_as_longlong() const { return TRUE; }
uint32 max_display_length() { return 20; }
virtual uchar *pack(uchar* to, const uchar *from,
- uint max_length, bool low_byte_first)
+ uint max_length __attribute__((unused)),
+ bool low_byte_first)
{
- int64 val;
-#ifdef WORDS_BIGENDIAN
- if (table->s->db_low_byte_first)
- val = sint8korr(from);
- else
-#endif
- longlongget(val, from);
-
-#ifdef WORDS_BIGENDIAN
- if (low_byte_first)
- int8store(to, val);
- else
-#endif
- longlongstore(to, val);
- return to + sizeof(val);
+ return pack_int64(to, from, low_byte_first);
}
-
virtual const uchar *unpack(uchar* to, const uchar *from,
- uint param_data, bool low_byte_first)
+ uint param_data __attribute__((unused)),
+ bool low_byte_first)
{
- int64 val;
-#ifdef WORDS_BIGENDIAN
- if (low_byte_first)
- val = sint8korr(from);
- else
-#endif
- longlongget(val, from);
-
-#ifdef WORDS_BIGENDIAN
- if (table->s->db_low_byte_first)
- int8store(to, val);
- else
-#endif
- longlongstore(to, val);
- return from + sizeof(val);
+ return unpack_int64(to, from, low_byte_first);
}
};
#endif
@@ -1205,6 +1225,17 @@ public:
bool get_date(MYSQL_TIME *ltime,uint fuzzydate);
bool get_time(MYSQL_TIME *ltime);
timestamp_auto_set_type get_auto_set_type() const;
+ uchar *pack(uchar *to, const uchar *from,
+ uint max_length __attribute__((unused)), bool low_byte_first)
+ {
+ return pack_int32(to, from, low_byte_first);
+ }
+ const uchar *unpack(uchar* to, const uchar *from,
+ uint param_data __attribute__((unused)),
+ bool low_byte_first)
+ {
+ return unpack_int32(to, from, low_byte_first);
+ }
};
@@ -1259,6 +1290,17 @@ public:
void sql_type(String &str) const;
bool can_be_compared_as_longlong() const { return TRUE; }
bool zero_pack() const { return 1; }
+ uchar *pack(uchar* to, const uchar *from,
+ uint max_length __attribute__((unused)), bool low_byte_first)
+ {
+ return pack_int32(to, from, low_byte_first);
+ }
+ const uchar *unpack(uchar* to, const uchar *from,
+ uint param_data __attribute__((unused)),
+ bool low_byte_first)
+ {
+ return unpack_int32(to, from, low_byte_first);
+ }
};
@@ -1372,6 +1414,17 @@ public:
bool zero_pack() const { return 1; }
bool get_date(MYSQL_TIME *ltime,uint fuzzydate);
bool get_time(MYSQL_TIME *ltime);
+ uchar *pack(uchar* to, const uchar *from,
+ uint max_length __attribute__((unused)), bool low_byte_first)
+ {
+ return pack_int64(to, from, low_byte_first);
+ }
+ const uchar *unpack(uchar* to, const uchar *from,
+ uint param_data __attribute__((unused)),
+ bool low_byte_first)
+ {
+ return unpack_int64(to, from, low_byte_first);
+ }
};
@@ -1423,18 +1476,22 @@ public:
virtual const uchar *unpack(uchar* to, const uchar *from,
uint param_data, bool low_byte_first);
uint pack_length_from_metadata(uint field_metadata)
- { return (field_metadata & 0x00ff); }
+ {
+ DBUG_PRINT("debug", ("field_metadata: 0x%04x", field_metadata));
+ if (field_metadata == 0)
+ return row_pack_length();
+ return (((field_metadata >> 4) & 0x300) ^ 0x300) + (field_metadata & 0x00ff);
+ }
+ int compatible_field_size(uint field_metadata,
+ const Relay_log_info *rli);
uint row_pack_length() { return (field_length + 1); }
- int pack_cmp(const uchar *a,const uchar *b,uint key_length,
- my_bool insert_or_update);
- int pack_cmp(const uchar *b,uint key_length,my_bool insert_or_update);
uint packed_col_length(const uchar *to, uint length);
uint max_packed_col_length(uint max_length);
uint size_of() const { return sizeof(*this); }
enum_field_types real_type() const { return MYSQL_TYPE_STRING; }
bool has_charset(void) const
{ return charset() == &my_charset_bin ? FALSE : TRUE; }
- Field *new_field(MEM_ROOT *root, struct st_table *new_table, bool keep_type);
+ Field *new_field(MEM_ROOT *root, TABLE *new_table, bool keep_type);
virtual uint get_key_image(uchar *buff,uint length, imagetype type);
private:
int do_save_field_metadata(uchar *first_byte);
@@ -1501,16 +1558,8 @@ public:
void sql_type(String &str) const;
virtual uchar *pack(uchar *to, const uchar *from,
uint max_length, bool low_byte_first);
- uchar *pack_key(uchar *to, const uchar *from, uint max_length, bool low_byte_first);
- uchar *pack_key_from_key_image(uchar* to, const uchar *from,
- uint max_length, bool low_byte_first);
virtual const uchar *unpack(uchar* to, const uchar *from,
uint param_data, bool low_byte_first);
- const uchar *unpack_key(uchar* to, const uchar *from,
- uint max_length, bool low_byte_first);
- int pack_cmp(const uchar *a, const uchar *b, uint key_length,
- my_bool insert_or_update);
- int pack_cmp(const uchar *b, uint key_length,my_bool insert_or_update);
int cmp_binary(const uchar *a,const uchar *b, uint32 max_length=~0L);
int key_cmp(const uchar *,const uchar*);
int key_cmp(const uchar *str, uint length);
@@ -1521,8 +1570,8 @@ public:
enum_field_types real_type() const { return MYSQL_TYPE_VARCHAR; }
bool has_charset(void) const
{ return charset() == &my_charset_bin ? FALSE : TRUE; }
- Field *new_field(MEM_ROOT *root, struct st_table *new_table, bool keep_type);
- Field *new_key_field(MEM_ROOT *root, struct st_table *new_table,
+ Field *new_field(MEM_ROOT *root, TABLE *new_table, bool keep_type);
+ Field *new_key_field(MEM_ROOT *root, TABLE *new_table,
uchar *new_ptr, uchar *new_null_ptr,
uint new_null_bit);
uint is_equal(Create_field *new_field);
@@ -1534,8 +1583,16 @@ private:
class Field_blob :public Field_longstr {
protected:
+ /**
+ The number of bytes used to represent the length of the blob.
+ */
uint packlength;
- String value; // For temporaries
+
+ /**
+ The 'value'-object is a cache fronting the storage engine.
+ */
+ String value;
+
public:
Field_blob(uchar *ptr_arg, uchar *null_ptr_arg, uchar null_bit_arg,
enum utype unireg_check_arg, const char *field_name_arg,
@@ -1606,6 +1663,7 @@ public:
}
int reset(void) { bzero(ptr, packlength+sizeof(uchar*)); return 0; }
void reset_fields() { bzero((uchar*) &value,sizeof(value)); }
+ uint32 get_field_buffer_size(void) { return value.alloced_length(); }
#ifndef WORDS_BIGENDIAN
static
#endif
@@ -1677,17 +1735,8 @@ public:
}
virtual uchar *pack(uchar *to, const uchar *from,
uint max_length, bool low_byte_first);
- uchar *pack_key(uchar *to, const uchar *from,
- uint max_length, bool low_byte_first);
- uchar *pack_key_from_key_image(uchar* to, const uchar *from,
- uint max_length, bool low_byte_first);
virtual const uchar *unpack(uchar *to, const uchar *from,
uint param_data, bool low_byte_first);
- const uchar *unpack_key(uchar* to, const uchar *from,
- uint max_length, bool low_byte_first);
- int pack_cmp(const uchar *a, const uchar *b, uint key_length,
- my_bool insert_or_update);
- int pack_cmp(const uchar *b, uint key_length,my_bool insert_or_update);
uint packed_col_length(const uchar *col_ptr, uint length);
uint max_packed_col_length(uint max_length);
void free() { value.free(); }
@@ -1752,7 +1801,7 @@ public:
{
flags|=ENUM_FLAG;
}
- Field *new_field(MEM_ROOT *root, struct st_table *new_table, bool keep_type);
+ Field *new_field(MEM_ROOT *root, TABLE *new_table, bool keep_type);
enum_field_types type() const { return MYSQL_TYPE_STRING; }
enum Item_result cmp_type () const { return INT_RESULT; }
enum Item_result cast_to_int_type () const { return INT_RESULT; }
@@ -1781,6 +1830,7 @@ public:
CHARSET_INFO *sort_charset(void) const { return &my_charset_bin; }
private:
int do_save_field_metadata(uchar *first_byte);
+ uint is_equal(Create_field *new_field);
};
@@ -1851,9 +1901,12 @@ public:
virtual bool str_needs_quotes() { return TRUE; }
my_decimal *val_decimal(my_decimal *);
int cmp(const uchar *a, const uchar *b)
- {
- DBUG_ASSERT(ptr == a);
- return Field_bit::key_cmp(b, bytes_in_rec+test(bit_len));
+ {
+ DBUG_ASSERT(ptr == a || ptr == b);
+ if (ptr == a)
+ return Field_bit::key_cmp(b, bytes_in_rec+test(bit_len));
+ else
+ return Field_bit::key_cmp(a, bytes_in_rec+test(bit_len)) * -1;
}
int cmp_binary_offset(uint row_offset)
{ return cmp_offset(row_offset); }
@@ -1876,7 +1929,8 @@ public:
uint pack_length_from_metadata(uint field_metadata);
uint row_pack_length()
{ return (bytes_in_rec + ((bit_len > 0) ? 1 : 0)); }
- int compatible_field_size(uint field_metadata);
+ int compatible_field_size(uint field_metadata,
+ const Relay_log_info *rli);
void sql_type(String &str) const;
virtual uchar *pack(uchar *to, const uchar *from,
uint max_length, bool low_byte_first);
@@ -1884,7 +1938,7 @@ public:
uint param_data, bool low_byte_first);
virtual void set_default();
- Field *new_key_field(MEM_ROOT *root, struct st_table *new_table,
+ Field *new_key_field(MEM_ROOT *root, TABLE *new_table,
uchar *new_ptr, uchar *new_null_ptr,
uint new_null_bit);
void set_bit_ptr(uchar *bit_ptr_arg, uchar bit_ofs_arg)
@@ -1895,7 +1949,6 @@ public:
bool eq(Field *field)
{
return (Field::eq(field) &&
- field->type() == type() &&
bit_ptr == ((Field_bit *)field)->bit_ptr &&
bit_ofs == ((Field_bit *)field)->bit_ofs);
}
@@ -1905,6 +1958,7 @@ public:
Field::move_field_offset(ptr_diff);
bit_ptr= ADD_TO_PTR(bit_ptr, ptr_diff, uchar*);
}
+ void hash(ulong *nr, ulong *nr2);
private:
virtual size_t do_last_null_byte() const;
@@ -1993,7 +2047,7 @@ public:
A class for sending info to the client
*/
-class Send_field {
+class Send_field :public Sql_alloc {
public:
const char *db_name;
const char *table_name,*org_table_name;
@@ -2069,6 +2123,7 @@ int set_field_to_null_with_conversions(Field *field, bool no_conversions);
#define FIELDFLAG_NO_DEFAULT 16384 /* sql */
#define FIELDFLAG_SUM ((uint) 32768)// predit: +#fieldflag
#define FIELDFLAG_MAYBE_NULL ((uint) 32768)// sql
+#define FIELDFLAG_HEX_ESCAPE ((uint) 0x10000)
#define FIELDFLAG_PACK_SHIFT 3
#define FIELDFLAG_DEC_SHIFT 8
#define FIELDFLAG_MAX_DEC 31
@@ -2094,3 +2149,6 @@ int set_field_to_null_with_conversions(Field *field, bool no_conversions);
#define f_maybe_null(x) (x & FIELDFLAG_MAYBE_NULL)
#define f_no_default(x) (x & FIELDFLAG_NO_DEFAULT)
#define f_bit_as_char(x) ((x) & FIELDFLAG_TREAT_BIT_AS_CHAR)
+#define f_is_hex_escape(x) ((x) & FIELDFLAG_HEX_ESCAPE)
+
+#endif /* FIELD_INCLUDED */