Index: driver/utility.c =================================================================== --- driver/utility.c (revision 989) +++ driver/utility.c (working copy) @@ -85,6 +85,7 @@ MYSQL_RES *result= stmt->result; DESCREC *irrec; MYSQL_FIELD *field; + int capint32= stmt->dbc->flag & FLAG_COLUMN_SIZE_S32 ? 1 : 0; stmt->state= ST_EXECUTED; /* Mark set found */ @@ -113,6 +114,11 @@ } irrec->type_name= (SQLCHAR *) irrec->row.type_name; irrec->length= get_column_size(stmt, field); + irrec->octet_length= get_transfer_octet_length(stmt, field); + irrec->display_size= get_display_size(stmt, field); + /* prevent overflowing */ + if (!capint32 || irrec->octet_length < INT_MAX32) + irrec->octet_length+= test(field->charsetnr != BINARY_CHARSET_NUMBER); irrec->precision= 0; /* Set precision for all non-char/blob types */ switch (irrec->type) @@ -132,15 +138,6 @@ irrec->precision= (SQLSMALLINT) irrec->length; break; } - irrec->octet_length= get_transfer_octet_length(stmt, field) + - test(field->charsetnr != BINARY_CHARSET_NUMBER); - if (stmt->dbc->flag & FLAG_COLUMN_SIZE_S32) - { - if (irrec->length > INT_MAX32) - irrec->length= INT_MAX32; - if (irrec->octet_length > INT_MAX32) - irrec->octet_length= INT_MAX32; - } irrec->scale= max(0, (SQLSMALLINT) get_decimal_digits(stmt, field)); if ((field->flags & NOT_NULL_FLAG) && !(field->flags & TIMESTAMP_FLAG) && @@ -166,7 +163,6 @@ irrec->catalog_name= field->db; else irrec->catalog_name= stmt->dbc->database; - irrec->display_size= get_display_size(stmt, field); if (field->type == MYSQL_TYPE_DECIMAL || field->type == MYSQL_TYPE_NEWDECIMAL) irrec->fixed_prec_scale= SQL_TRUE; @@ -1133,7 +1128,10 @@ */ SQLLEN get_column_size(STMT *stmt __attribute__((unused)), MYSQL_FIELD *field) { + int capint32= stmt->dbc->flag & FLAG_COLUMN_SIZE_S32 ? 1 : 0; SQLLEN length= field->length; + if (capint32 && field->length > INT_MAX32) + length= INT_MAX32; switch (field->type) { case MYSQL_TYPE_TINY: @@ -1261,7 +1259,13 @@ */ SQLLEN get_transfer_octet_length(STMT *stmt, MYSQL_FIELD *field) { - SQLLEN length= field->length; + int capint32= stmt->dbc->flag & FLAG_COLUMN_SIZE_S32 ? 1 : 0; + SQLLEN length; + /* cap at INT_MAX32 due to signed value */ + if (field->length > INT_MAX32) + length= INT_MAX32; + else + length= field->length; switch (field->type) { case MYSQL_TYPE_TINY: @@ -1330,10 +1334,11 @@ case MYSQL_TYPE_LONG_BLOB: case MYSQL_TYPE_BLOB: case MYSQL_TYPE_GEOMETRY: - if (field->charsetnr == BINARY_CHARSET_NUMBER) - return length; - if (field->charsetnr != stmt->dbc->ansi_charset_info->number) - return length * stmt->dbc->ansi_charset_info->mbmaxlen; + if (field->charsetnr != stmt->dbc->ansi_charset_info->number && + field->charsetnr != BINARY_CHARSET_NUMBER) + length *= stmt->dbc->ansi_charset_info->mbmaxlen; + if (capint32 && length > INT_MAX32) + length= INT_MAX32; return length; } @@ -1352,6 +1357,7 @@ */ SQLLEN get_display_size(STMT *stmt __attribute__((unused)),MYSQL_FIELD *field) { + int capint32= stmt->dbc->flag & FLAG_COLUMN_SIZE_S32 ? 1 : 0; CHARSET_INFO *charset= get_charset(field->charsetnr, MYF(0)); unsigned int mbmaxlen= charset ? charset->mbmaxlen : 1; @@ -1418,10 +1424,16 @@ case MYSQL_TYPE_LONG_BLOB: case MYSQL_TYPE_BLOB: case MYSQL_TYPE_GEOMETRY: - if (field->charsetnr == BINARY_CHARSET_NUMBER) - return field->length * 2; - else - return field->length / mbmaxlen; + { + unsigned long length; + if (field->charsetnr == BINARY_CHARSET_NUMBER) + length= field->length * 2; + else + length= field->length / mbmaxlen; + if (capint32 && length > INT_MAX32) + length= INT_MAX32; + return length; + } } return SQL_NO_TOTAL; Index: test/my_result.c =================================================================== --- test/my_result.c (revision 989) +++ test/my_result.c (working copy) @@ -2025,6 +2025,7 @@ SQLULEN pcColSz; SQLCHAR szColName[MAX_NAME_LEN]; SQLSMALLINT pfSqlType, pcbScale, pfNullable; + SQLLEN display_size, octet_length; SET_DSN_OPTION(1 << 27); @@ -2041,6 +2042,14 @@ /* Size of LONGTEXT should have been capped to 1 << 31. */ is_num(pcColSz, 2147483647L); + /* also, check display size and octet length (see bug#30890) */ + ok_stmt(hstmt1, SQLColAttribute(hstmt1, 1, SQL_DESC_DISPLAY_SIZE, NULL, + 0, NULL, &display_size)); + ok_stmt(hstmt1, SQLColAttribute(hstmt1, 1, SQL_DESC_OCTET_LENGTH, NULL, + 0, NULL, &octet_length)); + is_num(display_size, 2147483647L); + is_num(octet_length, 2147483647L); + ok_stmt(hstmt1, SQLFreeStmt(hstmt1, SQL_CLOSE)); ok_sql(hstmt1, "DROP TABLE IF EXISTS t_bug13776");