From: Date: April 4 2005 7:31pm Subject: bk commit into 5.0 tree (heikki:1.1863) BUG#9526 List-Archive: http://lists.mysql.com/internals/23632 X-Bug: 9526 Message-Id: <200504041731.j34HVGsZ000087@hundin.mysql.fi> Below is the list of changes that have just been committed into a local 5.0 repository of heikki. When heikki does a push these changes will be propagated to the main repository and, within 24 hours after the push, to the public repository. For information on how to access the public repository see http://dev.mysql.com/doc/mysql/en/installing-source-tree.html ChangeSet 1.1863 05/04/04 20:31:04 heikki@stripped +2 -0 ha_innodb.cc, row0sel.c: Fix Bug #9526 in 5.0: MySQL ENUM and SET columns are internally actually unsigned integer types; we must take care that old tables still treat ENUM and SET (incorrectly) as a character string, while new created tables treat it correctly as an unsigned integer sql/ha_innodb.cc 1.185 05/04/04 20:29:30 heikki@stripped +42 -20 Fix Bug #9526 in 5.0: MySQL ENUM and SET columns are internally actually unsigned integer types; we must take care that old tables still treat ENUM and SET (incorrectly) as a character string, while new created tables treat it correctly as an unsigned integer innobase/row/row0sel.c 1.81 05/04/04 20:29:11 heikki@stripped +6 -2 Fix Bug #9526 in 5.0: MySQL ENUM and SET columns are internally actually unsigned integer types; we must take care that old tables still treat ENUM and SET (incorrectly) as a character string, while new created tables treat it correctly as an unsigned integer # This is a BitKeeper patch. What follows are the unified diffs for the # set of deltas contained in the patch. The rest of the patch, the part # that BitKeeper cares about, is below these diffs. # User: heikki # Host: hundin.mysql.fi # Root: /home/heikki/mysql-5.0 --- 1.80/innobase/row/row0sel.c Wed Mar 16 14:27:06 2005 +++ 1.81/innobase/row/row0sel.c Mon Apr 4 20:29:11 2005 @@ -2145,12 +2145,16 @@ } if (dtype_get_mysql_type(dfield_get_type(dfield)) - == DATA_MYSQL_TRUE_VARCHAR) { + == DATA_MYSQL_TRUE_VARCHAR + && dfield_get_type(dfield)->mtype != DATA_INT) { /* In a MySQL key value format, a true VARCHAR is always preceded by 2 bytes of a length field. dfield_get_type(dfield)->len returns the maximum 'payload' len in bytes. That does not include the - 2 bytes that tell the actual data length. */ + 2 bytes that tell the actual data length. + + We added the check != DATA_INT to make sure we do + not treat MySQL ENUM or SET as a true VARCHAR! */ data_len += 2; data_field_len += 2; --- 1.184/sql/ha_innodb.cc Mon Apr 4 19:47:15 2005 +++ 1.185/sql/ha_innodb.cc Mon Apr 4 20:29:30 2005 @@ -2271,13 +2271,43 @@ ulint get_innobase_type_from_mysql_type( /*==============================*/ - /* out: DATA_BINARY, DATA_VARCHAR, ... */ - Field* field) /* in: MySQL field */ + /* out: DATA_BINARY, DATA_VARCHAR, ... */ + ulint* unsigned_flag, /* out: DATA_UNSIGNED if an 'unsigned type'; + at least ENUM and SET, and unsigned integer + types are 'unsigned types' */ + Field* field) /* in: MySQL field */ { /* The following asserts try to check that the MySQL type code fits in 8 bits: this is used in ibuf and also when DATA_NOT_NULL is ORed to the type */ + DBUG_ASSERT((ulint)FIELD_TYPE_STRING < 256); + DBUG_ASSERT((ulint)FIELD_TYPE_VAR_STRING < 256); + DBUG_ASSERT((ulint)FIELD_TYPE_DOUBLE < 256); + DBUG_ASSERT((ulint)FIELD_TYPE_FLOAT < 256); + DBUG_ASSERT((ulint)FIELD_TYPE_DECIMAL < 256); + + if (field->flags & UNSIGNED_FLAG) { + + *unsigned_flag = DATA_UNSIGNED; + } else { + *unsigned_flag = 0; + } + + if (field->real_type() == FIELD_TYPE_ENUM + || field->real_type() == FIELD_TYPE_SET) { + + /* MySQL has field->type() a string type for these, but the + data is actually internally stored as an unsigned integer + code! */ + + *unsigned_flag = DATA_UNSIGNED; /* MySQL has its own unsigned + flag set to zero, even though + internally this is an unsigned + integer type */ + return(DATA_INT); + } + switch (field->type()) { /* NOTE that we only allow string types in DATA_MYSQL and DATA_VARMYSQL */ @@ -2313,8 +2343,6 @@ case FIELD_TYPE_DATETIME: case FIELD_TYPE_YEAR: case FIELD_TYPE_NEWDATE: - case FIELD_TYPE_ENUM: - case FIELD_TYPE_SET: case FIELD_TYPE_TIME: case FIELD_TYPE_TIMESTAMP: return(DATA_INT); @@ -2686,7 +2714,7 @@ get_field_offset(table, field); templ->mysql_col_len = (ulint) field->pack_length(); - templ->type = get_innobase_type_from_mysql_type(field); + templ->type = index->table->cols[i].type.mtype; templ->mysql_type = (ulint)field->type(); if (templ->mysql_type == DATA_MYSQL_TRUE_VARCHAR) { @@ -2698,8 +2726,8 @@ index->table->cols[i].type.prtype); templ->mbminlen = index->table->cols[i].type.mbminlen; templ->mbmaxlen = index->table->cols[i].type.mbmaxlen; - templ->is_unsigned = (ulint) (field->flags & UNSIGNED_FLAG); - + templ->is_unsigned = index->table->cols[i].type.prtype + & DATA_UNSIGNED; if (templ->type == DATA_BLOB) { prebuilt->templ_contains_blob = TRUE; } @@ -2962,7 +2990,6 @@ byte* buf; upd_field_t* ufield; ulint col_type; - ulint is_unsigned; ulint n_changed = 0; dfield_t dfield; uint i; @@ -2998,8 +3025,7 @@ field_mysql_type = field->type(); - col_type = get_innobase_type_from_mysql_type(field); - is_unsigned = (ulint) (field->flags & UNSIGNED_FLAG); + col_type = prebuilt->table->cols[i].type.mtype; switch (col_type) { @@ -3072,8 +3098,7 @@ } ufield->exp = NULL; - ufield->field_no = - (prebuilt->table->cols + i)->clust_pos; + ufield->field_no = prebuilt->table->cols[i].clust_pos; n_changed++; } } @@ -3932,19 +3957,14 @@ for (i = 0; i < n_cols; i++) { field = form->field[i]; - col_type = get_innobase_type_from_mysql_type(field); + col_type = get_innobase_type_from_mysql_type(&unsigned_type, + field); if (field->null_ptr) { nulls_allowed = 0; } else { nulls_allowed = DATA_NOT_NULL; } - if (field->flags & UNSIGNED_FLAG) { - unsigned_type = DATA_UNSIGNED; - } else { - unsigned_type = 0; - } - if (field->binary()) { binary_type = DATA_BINARY_TYPE; } else { @@ -4021,6 +4041,7 @@ ulint ind_type; ulint col_type; ulint prefix_len; + ulint is_unsigned; ulint i; ulint j; @@ -4070,7 +4091,8 @@ ut_a(j < form->s->fields); - col_type = get_innobase_type_from_mysql_type(key_part->field); + col_type = get_innobase_type_from_mysql_type( + &is_unsigned, key_part->field); if (DATA_BLOB == col_type || (key_part->length < field->pack_length()