From: Martin Hansson Date: December 14 2010 12:43pm Subject: bzr commit into mysql-trunk-bugfixing branch (martin.hansson:3255) Bug#58918 List-Archive: http://lists.mysql.com/commits/126754 X-Bug: 58918 MIME-Version: 1.0 Content-Type: multipart/mixed; boundary="===============0498203442==" --===============0498203442== MIME-Version: 1.0 Content-Type: text/plain; charset="us-ascii" Content-Transfer-Encoding: 7bit Content-Disposition: inline #At file:///data0/martin/bzrroot/refactoring-Field_clone/n-mr-o-t/ based on revid:tor.didriksen@stripped 3255 Martin Hansson 2010-12-14 Bug#58918: Add a clone member function to the Field class for better duplication The patch removes all copying of Field objects using memcpy() and replaces it with virtual clone() and clone(MEM_ROOT*) member functions that rely on the copy constructor. An operator new (MEM_ROOT*) is also implemented. The sole purpose of the Field::size_of() member function was to support the memcpy and it is now removed. @ sql/field.cc Removal of memcpy() based duplication. @ sql/field.h New implementation of clone() member functions. Removal of size_of() member functions @ sql/item.cc Removal of memcpy() based duplication. modified: sql/field.cc sql/field.h sql/item.cc === modified file 'sql/field.cc' --- a/sql/field.cc 2010-11-17 16:04:35 +0000 +++ b/sql/field.cc 2010-12-14 12:43:21 +0000 @@ -1812,8 +1812,8 @@ bool Field::optimize_range(uint idx, uin Field *Field::new_field(MEM_ROOT *root, TABLE *new_table, bool keep_type __attribute__((unused))) { - Field *tmp; - if (!(tmp= (Field*) memdup_root(root,(char*) this,size_of()))) + Field *tmp= clone(root); + if (tmp == NULL) return 0; if (tmp->table->maybe_null) @@ -1849,8 +1849,8 @@ Field *Field::new_key_field(MEM_ROOT *ro Field *Field::clone(MEM_ROOT *root, TABLE *new_table) { - Field *tmp; - if ((tmp= (Field*) memdup_root(root,(char*) this,size_of()))) + Field *tmp= clone(root); + if (tmp != NULL) { tmp->init(new_table); tmp->move_field_offset((my_ptrdiff_t) (new_table->record[0] - === modified file 'sql/field.h' --- a/sql/field.h 2010-11-19 19:27:31 +0000 +++ b/sql/field.h 2010-12-14 12:43:21 +0000 @@ -16,11 +16,6 @@ along with this program; if not, write to the Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ -/* - Because of the function new_field() all field classes that have static - variables must declare the size_of() member function. -*/ - #ifdef USE_PRAGMA_INTERFACE #pragma interface /* gcc class implementation */ #endif @@ -84,8 +79,12 @@ class Field Field(const Item &); /* Prevent use of these */ void operator=(Field &); public: + /* To do: inherit Sql_alloc and get these for free */ static void *operator new(size_t size) throw () { return sql_alloc(size); } + static void *operator new(size_t size, MEM_ROOT *mem_root) throw () { + return alloc_root(mem_root, size); + } static void operator delete(void *ptr_arg, size_t size) { TRASH(ptr_arg, size); } uchar *ptr; // Position to field in record @@ -267,7 +266,6 @@ public: in str and restore it with set() if needed */ virtual void sql_type(String &str) const =0; - virtual uint size_of() const =0; // For new field inline bool is_null(my_ptrdiff_t row_offset= 0) { return null_ptr ? (null_ptr[row_offset] & null_bit ? 1 : 0) : table->null_row; } inline bool is_real_null(my_ptrdiff_t row_offset= 0) @@ -339,6 +337,29 @@ public: uchar *new_ptr, uchar *new_null_ptr, uint new_null_bit); Field *clone(MEM_ROOT *mem_root, TABLE *new_table); + + /** + Makes a shallow copy of the Field object. + + @note This method must be overridden in all concrete subclasses. Several + of the Field subclasses are concrete even though they are not leaf + classes, so the compiler will not always catch this. + + @retval NULL If memory allocation failed. + */ + virtual Field *clone() const =0; + + /** + Makes a shallow copy of the Field object. + + @note This method must be overridden in all concrete subclasses. Several + of the Field subclasses are concrete even though they are not leaf + classes, so the compiler will not always catch this. + + @param mem_root MEM_ROOT to use for memory allocation. + @retval NULL If memory allocation failed. + */ + virtual Field *clone(MEM_ROOT *mem_root) const =0; 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; @@ -735,7 +756,6 @@ public: friend class Create_field; void make_field(Send_field *); uint decimals() const { return (uint) dec; } - uint size_of() const { return sizeof(*this); } bool eq_def(Field *field); int store_decimal(const my_decimal *); my_decimal *val_decimal(my_decimal *); @@ -780,7 +800,6 @@ public: int store(longlong nr, bool unsigned_val)=0; int store_decimal(const my_decimal *); int store(const char *to,uint length,CHARSET_INFO *cs)=0; - uint size_of() const { return sizeof(*this); } uint repertoire(void) const { return my_charset_repertoire(field_charset); @@ -835,7 +854,6 @@ public: my_decimal *val_decimal(my_decimal *); int truncate(double *nr, double max_length); uint32 max_display_length() { return field_length; } - uint size_of() const { return sizeof(*this); } virtual const uchar *unpack(uchar* to, const uchar *from, uint param_data, bool low_byte_first); virtual uchar *pack(uchar* to, const uchar *from, @@ -868,6 +886,14 @@ public: void overflow(bool negative); bool zero_pack() const { return 0; } void sql_type(String &str) const; + Field_decimal *clone(MEM_ROOT *mem_root) const { + DBUG_ASSERT(type() == MYSQL_TYPE_DECIMAL); + return new (mem_root) Field_decimal(*this); + } + Field_decimal *clone() const { + DBUG_ASSERT(type() == MYSQL_TYPE_DECIMAL); + return new Field_decimal(*this); + } virtual const uchar *unpack(uchar* to, const uchar *from, uint param_data, bool low_byte_first) { @@ -922,13 +948,20 @@ public: bool zero_pack() const { return 0; } void sql_type(String &str) const; uint32 max_display_length() { return field_length; } - uint size_of() const { return sizeof(*this); } uint32 pack_length() const { return (uint32) bin_size; } uint pack_length_from_metadata(uint field_metadata); uint row_pack_length() { return pack_length(); } bool compatible_field_size(uint field_metadata, Relay_log_info *rli, uint16 mflags, int *order_var); uint is_equal(Create_field *new_field); + Field_new_decimal *clone(MEM_ROOT *mem_root) const { + DBUG_ASSERT(type() == MYSQL_TYPE_NEWDECIMAL); + return new (mem_root) Field_new_decimal(*this); + } + Field_new_decimal *clone() const { + DBUG_ASSERT(type() == MYSQL_TYPE_NEWDECIMAL); + return new Field_new_decimal(*this); + } virtual const uchar *unpack(uchar* to, const uchar *from, uint param_data, bool low_byte_first); static Field *create_from_item (Item *); @@ -962,7 +995,14 @@ public: uint32 pack_length() const { return 1; } void sql_type(String &str) const; uint32 max_display_length() { return 4; } - + Field_tiny *clone(MEM_ROOT *mem_root) const { + DBUG_ASSERT(type() == MYSQL_TYPE_TINY); + return new (mem_root) Field_tiny(*this); + } + Field_tiny *clone() const { + DBUG_ASSERT(type() == MYSQL_TYPE_TINY); + return new Field_tiny(*this); + } virtual uchar *pack(uchar* to, const uchar *from, uint max_length, bool low_byte_first) { @@ -1011,7 +1051,14 @@ public: uint32 pack_length() const { return 2; } void sql_type(String &str) const; uint32 max_display_length() { return 6; } - + Field_short *clone(MEM_ROOT *mem_root) const { + DBUG_ASSERT(type() == MYSQL_TYPE_SHORT); + return new (mem_root) Field_short(*this); + } + Field_short *clone() const { + DBUG_ASSERT(type() == MYSQL_TYPE_SHORT); + return new Field_short(*this); + } virtual uchar *pack(uchar* to, const uchar *from, uint max_length, bool low_byte_first) { @@ -1052,7 +1099,14 @@ public: uint32 pack_length() const { return 3; } void sql_type(String &str) const; uint32 max_display_length() { return 8; } - + Field_medium *clone(MEM_ROOT *mem_root) const { + DBUG_ASSERT(type() == MYSQL_TYPE_INT24); + return new (mem_root) Field_medium(*this); + } + Field_medium *clone() const { + DBUG_ASSERT(type() == MYSQL_TYPE_INT24); + return new Field_medium(*this); + } virtual uchar *pack(uchar* to, const uchar *from, uint max_length, bool low_byte_first) { @@ -1099,6 +1153,14 @@ public: uint32 pack_length() const { return 4; } void sql_type(String &str) const; uint32 max_display_length() { return MY_INT32_NUM_DECIMAL_DIGITS; } + Field_long *clone(MEM_ROOT *mem_root) const { + DBUG_ASSERT(type() == MYSQL_TYPE_LONG); + return new (mem_root) Field_long(*this); + } + Field_long *clone() const { + DBUG_ASSERT(type() == MYSQL_TYPE_LONG); + return new Field_long(*this); + } virtual uchar *pack(uchar* to, const uchar *from, uint max_length __attribute__((unused)), bool low_byte_first) @@ -1153,6 +1215,14 @@ public: void sql_type(String &str) const; bool can_be_compared_as_longlong() const { return TRUE; } uint32 max_display_length() { return 20; } + Field_longlong *clone(MEM_ROOT *mem_root) const { + DBUG_ASSERT(type() == MYSQL_TYPE_LONGLONG); + return new (mem_root) Field_longlong(*this); + } + Field_longlong *clone() const { + DBUG_ASSERT(type() == MYSQL_TYPE_LONGLONG); + return new Field_longlong(*this); + } virtual uchar *pack(uchar* to, const uchar *from, uint max_length __attribute__((unused)), bool low_byte_first) @@ -1199,6 +1269,14 @@ public: uint32 pack_length() const { return sizeof(float); } uint row_pack_length() { return pack_length(); } void sql_type(String &str) const; + Field_float *clone(MEM_ROOT *mem_root) const { + DBUG_ASSERT(type() == MYSQL_TYPE_FLOAT); + return new (mem_root) Field_float(*this); + } + Field_float *clone() const { + DBUG_ASSERT(type() == MYSQL_TYPE_FLOAT); + return new Field_float(*this); + } private: int do_save_field_metadata(uchar *first_byte); }; @@ -1239,6 +1317,14 @@ public: uint32 pack_length() const { return sizeof(double); } uint row_pack_length() { return pack_length(); } void sql_type(String &str) const; + Field_double *clone(MEM_ROOT *mem_root) const { + DBUG_ASSERT(type() == MYSQL_TYPE_DOUBLE); + return new (mem_root) Field_double(*this); + } + Field_double *clone() const { + DBUG_ASSERT(type() == MYSQL_TYPE_DOUBLE); + return new Field_double(*this); + } private: int do_save_field_metadata(uchar *first_byte); }; @@ -1272,8 +1358,15 @@ public: void sort_string(uchar *buff, uint length) {} uint32 pack_length() const { return 0; } void sql_type(String &str) const; - uint size_of() const { return sizeof(*this); } uint32 max_display_length() { return 4; } + Field_null *clone(MEM_ROOT *mem_root) const { + DBUG_ASSERT(type() == MYSQL_TYPE_NULL); + return new (mem_root) Field_null(*this); + } + Field_null *clone() const { + DBUG_ASSERT(type() == MYSQL_TYPE_NULL); + return new Field_null(*this); + } }; @@ -1343,6 +1436,14 @@ public: bool get_date(MYSQL_TIME *ltime,uint fuzzydate); bool get_time(MYSQL_TIME *ltime); timestamp_auto_set_type get_auto_set_type() const; + Field_timestamp *clone(MEM_ROOT *mem_root) const { + DBUG_ASSERT(type() == MYSQL_TYPE_TIMESTAMP); + return new (mem_root) Field_timestamp(*this); + } + Field_timestamp *clone() const { + DBUG_ASSERT(type() == MYSQL_TYPE_TIMESTAMP); + return new Field_timestamp(*this); + } uchar *pack(uchar *to, const uchar *from, uint max_length __attribute__((unused)), bool low_byte_first) { @@ -1375,6 +1476,14 @@ public: bool send_binary(Protocol *protocol); void sql_type(String &str) const; bool can_be_compared_as_longlong() const { return TRUE; } + Field_year *clone(MEM_ROOT *mem_root) const { + DBUG_ASSERT(type() == MYSQL_TYPE_YEAR); + return new (mem_root) Field_year(*this); + } + Field_year *clone() const { + DBUG_ASSERT(type() == MYSQL_TYPE_YEAR); + return new Field_year(*this); + } }; @@ -1413,6 +1522,14 @@ public: void sql_type(String &str) const; bool can_be_compared_as_longlong() const { return TRUE; } bool zero_pack() const { return 1; } + Field_date *clone(MEM_ROOT *mem_root) const { + DBUG_ASSERT(type() == MYSQL_TYPE_DATE); + return new (mem_root) Field_date(*this); + } + Field_date *clone() const { + DBUG_ASSERT(type() == MYSQL_TYPE_DATE); + return new Field_date(*this); + } uchar *pack(uchar* to, const uchar *from, uint max_length __attribute__((unused)), bool low_byte_first) { @@ -1465,6 +1582,16 @@ public: bool zero_pack() const { return 1; } bool get_date(MYSQL_TIME *ltime,uint fuzzydate); bool get_time(MYSQL_TIME *ltime); + Field_newdate *clone(MEM_ROOT *mem_root) const { + DBUG_ASSERT(type() == MYSQL_TYPE_DATE); + DBUG_ASSERT(real_type() == MYSQL_TYPE_NEWDATE); + return new (mem_root) Field_newdate(*this); + } + Field_newdate *clone() const { + DBUG_ASSERT(type() == MYSQL_TYPE_DATE); + DBUG_ASSERT(real_type() == MYSQL_TYPE_NEWDATE); + return new Field_newdate(*this); + } }; @@ -1505,6 +1632,14 @@ public: void sql_type(String &str) const; bool can_be_compared_as_longlong() const { return TRUE; } bool zero_pack() const { return 1; } + Field_time *clone(MEM_ROOT *mem_root) const { + DBUG_ASSERT(type() == MYSQL_TYPE_TIME); + return new (mem_root) Field_time(*this); + } + Field_time *clone() const { + DBUG_ASSERT(type() == MYSQL_TYPE_TIME); + return new Field_time(*this); + } }; @@ -1552,6 +1687,14 @@ public: bool zero_pack() const { return 1; } bool get_date(MYSQL_TIME *ltime,uint fuzzydate); bool get_time(MYSQL_TIME *ltime); + Field_datetime *clone(MEM_ROOT *mem_root) const { + DBUG_ASSERT(type() == MYSQL_TYPE_DATETIME); + return new (mem_root) Field_datetime(*this); + } + Field_datetime *clone() const { + DBUG_ASSERT(type() == MYSQL_TYPE_DATETIME); + return new Field_datetime(*this); + } uchar *pack(uchar* to, const uchar *from, uint max_length __attribute__((unused)), bool low_byte_first) { @@ -1629,11 +1772,18 @@ public: 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, TABLE *new_table, bool keep_type); + Field_string *clone(MEM_ROOT *mem_root) const { + DBUG_ASSERT(real_type() == MYSQL_TYPE_STRING); + return new (mem_root) Field_string(*this); + } + Field_string *clone() const { + DBUG_ASSERT(real_type() == MYSQL_TYPE_STRING); + return new Field_string(*this); + } virtual uint get_key_image(uchar *buff,uint length, imagetype type); private: int do_save_field_metadata(uchar *first_byte); @@ -1709,7 +1859,6 @@ public: uint packed_col_length(const uchar *to, uint length); uint max_packed_col_length(uint max_length); uint32 data_length(); - uint size_of() const { return sizeof(*this); } enum_field_types real_type() const { return MYSQL_TYPE_VARCHAR; } bool has_charset(void) const { return charset() == &my_charset_bin ? FALSE : TRUE; } @@ -1717,6 +1866,16 @@ public: Field *new_key_field(MEM_ROOT *root, TABLE *new_table, uchar *new_ptr, uchar *new_null_ptr, uint new_null_bit); + Field_varstring *clone(MEM_ROOT *mem_root) const { + DBUG_ASSERT(type() == MYSQL_TYPE_VARCHAR); + DBUG_ASSERT(real_type() == MYSQL_TYPE_VARCHAR); + return new (mem_root) Field_varstring(*this); + } + Field_varstring *clone() const { + DBUG_ASSERT(type() == MYSQL_TYPE_VARCHAR); + DBUG_ASSERT(real_type() == MYSQL_TYPE_VARCHAR); + return new Field_varstring(*this); + } uint is_equal(Create_field *new_field); void hash(ulong *nr, ulong *nr2); private: @@ -1877,6 +2036,14 @@ public: memcpy(ptr+packlength, &tmp, sizeof(char*)); return 0; } + Field_blob *clone(MEM_ROOT *mem_root) const { + DBUG_ASSERT(type() == MYSQL_TYPE_BLOB); + return new (mem_root) Field_blob(*this); + } + Field_blob *clone() const { + DBUG_ASSERT(type() == MYSQL_TYPE_BLOB); + return new Field_blob(*this); + } virtual uchar *pack(uchar *to, const uchar *from, uint max_length, bool low_byte_first); virtual const uchar *unpack(uchar *to, const uchar *from, @@ -1886,7 +2053,6 @@ public: void free() { value.free(); } inline void clear_temporary() { bzero((uchar*) &value,sizeof(value)); } friend int field_conv(Field *to,Field *from); - uint size_of() const { return sizeof(*this); } bool has_charset(void) const { return charset() == &my_charset_bin ? FALSE : TRUE; } uint32 max_display_length(); @@ -1923,9 +2089,16 @@ public: int store(double nr); int store(longlong nr, bool unsigned_val); int store_decimal(const my_decimal *); - uint size_of() const { return sizeof(*this); } int reset(void) { return !maybe_null() || Field_blob::reset(); } geometry_type get_geometry_type() { return geom_type; }; + Field_geom *clone(MEM_ROOT *mem_root) const { + DBUG_ASSERT(type() == MYSQL_TYPE_GEOMETRY); + return new (mem_root) Field_geom(*this); + } + Field_geom *clone() const { + DBUG_ASSERT(type() == MYSQL_TYPE_GEOMETRY); + return new Field_geom(*this); + } }; #endif /*HAVE_SPATIAL*/ @@ -1964,7 +2137,6 @@ public: uint32 pack_length() const { return (uint32) packlength; } void store_type(ulonglong value); void sql_type(String &str) const; - uint size_of() const { return sizeof(*this); } enum_field_types real_type() const { return MYSQL_TYPE_ENUM; } uint pack_length_from_metadata(uint field_metadata) { return (field_metadata & 0x00ff); } @@ -1975,7 +2147,14 @@ public: bool has_charset(void) const { return TRUE; } /* enum and set are sorted as integers */ CHARSET_INFO *sort_charset(void) const { return &my_charset_bin; } - + Field_enum *clone(MEM_ROOT *mem_root) const { + DBUG_ASSERT(real_type() == MYSQL_TYPE_ENUM); + return new (mem_root) Field_enum(*this); + } + Field_enum *clone() const { + DBUG_ASSERT(real_type() == MYSQL_TYPE_ENUM); + return new Field_enum(*this); + } virtual uchar *pack(uchar *to, const uchar *from, uint max_length, bool low_byte_first); virtual const uchar *unpack(uchar *to, const uchar *from, @@ -2004,12 +2183,19 @@ public: int store(const char *to,uint length,CHARSET_INFO *charset); int store(double nr) { return Field_set::store((longlong) nr, FALSE); } int store(longlong nr, bool unsigned_val); - virtual bool zero_pack() const { return 1; } String *val_str(String*,String *); void sql_type(String &str) const; enum_field_types real_type() const { return MYSQL_TYPE_SET; } bool has_charset(void) const { return TRUE; } + Field_set *clone(MEM_ROOT *mem_root) const { + DBUG_ASSERT(real_type() == MYSQL_TYPE_SET); + return new (mem_root) Field_set(*this); + } + Field_set *clone() const { + DBUG_ASSERT(real_type() == MYSQL_TYPE_SET); + return new Field_set(*this); + } }; @@ -2041,7 +2227,6 @@ public: uint32 key_length() const { return (uint32) (field_length + 7) / 8; } uint32 max_data_length() const { return (field_length + 7) / 8; } uint32 max_display_length() { return field_length; } - uint size_of() const { return sizeof(*this); } Item_result result_type () const { return INT_RESULT; } int reset(void) { bzero(ptr, bytes_in_rec); @@ -2117,7 +2302,14 @@ public: bit_ptr= ADD_TO_PTR(bit_ptr, ptr_diff, uchar*); } void hash(ulong *nr, ulong *nr2); - + Field_bit *clone(MEM_ROOT *mem_root) const { + DBUG_ASSERT(type() == MYSQL_TYPE_BIT); + return new (mem_root) Field_bit(*this); + } + Field_bit *clone() const { + DBUG_ASSERT(type() == MYSQL_TYPE_BIT); + return new Field_bit(*this); + } private: virtual size_t do_last_null_byte() const; int do_save_field_metadata(uchar *first_byte); @@ -2137,12 +2329,15 @@ public: uchar null_bit_arg, enum utype unireg_check_arg, const char *field_name_arg); enum ha_base_keytype key_type() const { return HA_KEYTYPE_BINARY; } - uint size_of() const { return sizeof(*this); } int store(const char *to, uint length, CHARSET_INFO *charset); int store(double nr) { return Field_bit::store(nr); } int store(longlong nr, bool unsigned_val) { return Field_bit::store(nr, unsigned_val); } void sql_type(String &str) const; + Field_bit_as_char *clone(MEM_ROOT *mem_root) const { + return new (mem_root) Field_bit_as_char(*this); + } + Field_bit_as_char *clone() const { return new Field_bit_as_char(*this); } }; === modified file 'sql/item.cc' --- a/sql/item.cc 2010-11-29 16:27:58 +0000 +++ b/sql/item.cc 2010-12-14 12:43:21 +0000 @@ -6984,9 +6984,11 @@ bool Item_default_value::fix_fields(THD my_error(ER_NO_DEFAULT_FOR_FIELD, MYF(0), field_arg->field->field_name); goto error; } - if (!(def_field= (Field*) sql_alloc(field_arg->field->size_of()))) + + def_field= field_arg->field->clone(); + if (def_field == NULL) goto error; - memcpy(def_field, field_arg->field, field_arg->field->size_of()); + def_field->move_field_offset((my_ptrdiff_t) (def_field->table->s->default_values - def_field->table->record[0])); @@ -7127,10 +7129,10 @@ bool Item_insert_value::fix_fields(THD * if (field_arg->field->table->insert_values) { - Field *def_field= (Field*) sql_alloc(field_arg->field->size_of()); + Field *def_field= field_arg->field->clone(); if (!def_field) return TRUE; - memcpy(def_field, field_arg->field, field_arg->field->size_of()); + def_field->move_field_offset((my_ptrdiff_t) (def_field->table->insert_values - def_field->table->record[0])); --===============0498203442== MIME-Version: 1.0 Content-Type: text/bzr-bundle; charset="us-ascii"; name="bzr/martin.hansson@stripped" Content-Transfer-Encoding: 7bit Content-Disposition: inline # Bazaar merge directive format 2 (Bazaar 0.90) # revision_id: martin.hansson@stripped\ # ljz7x1cpziuiso48 # target_branch: file:///data0/martin/bzrroot/refactoring-\ # Field_clone/n-mr-o-t/ # testament_sha1: 245e45a71fc2a401b5be876ea4dba2d6fb8fd768 # timestamp: 2010-12-14 13:43:25 +0100 # base_revision_id: tor.didriksen@stripped\ # hex6tudypt2kr3m4 # # Begin bundle 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 --===============0498203442==--