Index: test/my_result.c =================================================================== --- test/my_result.c (revision 977) +++ 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"); Index: driver/myutil.h =================================================================== --- driver/myutil.h (revision 977) +++ driver/myutil.h (working copy) @@ -168,10 +168,10 @@ void translate_error(char *save_state,myodbc_errid errid,uint mysql_err); SQLSMALLINT get_sql_data_type(STMT *stmt, MYSQL_FIELD *field, char *buff); -SQLLEN get_column_size(STMT *stmt, MYSQL_FIELD *field); +SQLLEN get_column_size(STMT *stmt, MYSQL_FIELD *field, int capint32); SQLLEN get_decimal_digits(STMT *stmt, MYSQL_FIELD *field); -SQLLEN get_transfer_octet_length(STMT *stmt, MYSQL_FIELD *field); -SQLLEN get_display_size(STMT *stmt, MYSQL_FIELD *field); +SQLLEN get_transfer_octet_length(STMT *stmt, MYSQL_FIELD *field, int capint32); +SQLLEN get_display_size(STMT *stmt, MYSQL_FIELD *field, int capint32); SQLSMALLINT get_dticode_from_concise_type(SQLSMALLINT concise_type); SQLSMALLINT get_concise_type_from_datetime_code(SQLSMALLINT dticode); SQLSMALLINT get_concise_type_from_interval_code(SQLSMALLINT dticode); Index: driver/utility.c =================================================================== --- driver/utility.c (revision 977) +++ 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 */ @@ -112,7 +113,12 @@ break; } irrec->type_name= (SQLCHAR *) irrec->row.type_name; - irrec->length= get_column_size(stmt, field); + irrec->length= get_column_size(stmt, field, capint32); + irrec->octet_length= get_transfer_octet_length(stmt, field, capint32); + irrec->display_size= get_display_size(stmt, field, capint32); + /* 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; @@ -1131,9 +1127,12 @@ @return The column size of the field */ -SQLLEN get_column_size(STMT *stmt __attribute__((unused)), MYSQL_FIELD *field) +SQLLEN get_column_size(STMT *stmt __attribute__((unused)), + MYSQL_FIELD *field, int capint32) { SQLLEN length= field->length; + if (capint32 && field->length > INT_MAX32) + length= INT_MAX32; switch (field->type) { case MYSQL_TYPE_TINY: @@ -1259,9 +1258,14 @@ @return The transfer octet length */ -SQLLEN get_transfer_octet_length(STMT *stmt, MYSQL_FIELD *field) +SQLLEN get_transfer_octet_length(STMT *stmt, MYSQL_FIELD *field, int capint32) { - SQLLEN length= field->length; + 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; } @@ -1350,7 +1355,8 @@ @return The display size */ -SQLLEN get_display_size(STMT *stmt __attribute__((unused)),MYSQL_FIELD *field) +SQLLEN get_display_size(STMT *stmt __attribute__((unused)),MYSQL_FIELD *field, + int capint32) { 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: driver/catalog.c =================================================================== --- driver/catalog.c (revision 977) +++ driver/catalog.c (working copy) @@ -704,6 +704,7 @@ MYSQL_ROW table_row; unsigned long rows= 0, next_row= 0, *lengths; char *db= NULL; + int capint32= stmt->dbc->flag & FLAG_COLUMN_SIZE_S32 ? 1 : 0; CLEAR_STMT_ERROR(hstmt); my_SQLFreeStmt(hstmt, MYSQL_RESET); @@ -799,11 +800,11 @@ } /* COLUMN_SIZE */ - sprintf(buff, "%ld", get_column_size(stmt, field)); + sprintf(buff, "%ld", get_column_size(stmt, field, capint32)); row[6]= strdup_root(alloc, buff); /* BUFFER_LENGTH */ - sprintf(buff, "%ld", get_transfer_octet_length(stmt, field)); + sprintf(buff, "%ld", get_transfer_octet_length(stmt, field, capint32)); row[7]= strdup_root(alloc, buff); if (is_char_sql_type(type) || is_wchar_sql_type(type) || @@ -1393,6 +1394,7 @@ MEM_ROOT *alloc; uint field_count; my_bool primary_key; + int capint32= stmt->dbc->flag & FLAG_COLUMN_SIZE_S32 ? 1 : 0; CLEAR_STMT_ERROR(hstmt); @@ -1445,9 +1447,9 @@ row[3]= strdup_root(alloc,buff); sprintf(buff,"%d",type); row[2]= strdup_root(alloc,buff); - sprintf(buff, "%ld", get_column_size(stmt, field)); + sprintf(buff, "%ld", get_column_size(stmt, field, capint32)); row[4]= strdup_root(alloc,buff); - sprintf(buff, "%ld", get_transfer_octet_length(stmt, field)); + sprintf(buff, "%ld", get_transfer_octet_length(stmt, field, capint32)); row[5]= strdup_root(alloc,buff); { SQLLEN digits= get_decimal_digits(stmt, field); @@ -1521,9 +1523,9 @@ row[3]= strdup_root(alloc,buff); sprintf(buff,"%d",type); row[2]= strdup_root(alloc,buff); - sprintf(buff,"%ld", get_column_size(stmt, field)); + sprintf(buff,"%ld", get_column_size(stmt, field, capint32)); row[4]= strdup_root(alloc,buff); - sprintf(buff,"%ld", get_transfer_octet_length(stmt, field)); + sprintf(buff,"%ld", get_transfer_octet_length(stmt, field, capint32)); row[5]= strdup_root(alloc,buff); { SQLLEN digits= get_decimal_digits(stmt, field);