diff options
author | unknown <konstantin@mysql.com> | 2004-12-16 03:15:06 +0300 |
---|---|---|
committer | unknown <konstantin@mysql.com> | 2004-12-16 03:15:06 +0300 |
commit | 7845f99abf1d36e972970c0fc9431956a8f4b63a (patch) | |
tree | 056f73f48d150d91c8d24bee3a927dec746492bb /tests | |
parent | 79bf1ca8d919a0d4f91b0fa0382de3d43dd06d0f (diff) | |
download | mariadb-git-7845f99abf1d36e972970c0fc9431956a8f4b63a.tar.gz |
Data truncation reporting implementation (libmysql) + post review
fixes. Still to do:
- deploy my_strtoll10 in limbysql.c
- add mysql_options option to switch MYSQL_DATA_TRUNCATED on and off.
include/my_time.h:
More calls are shared between client and server (libmysql now performs
more intelligent date->number and number->date conversions).
TODO: rename those which are not starting with 'my_'
include/mysql.h:
MYSQL_BIND:
- more elaborated comment
- some of the ex-private members were given public names -
it's sometimes convenient to set bind->error to &bind->error_value.
However Monty questions the idea, so it should be given
more thought in future.
- added new members to support data truncation.
Added new return value of mysql_stmt_fetch, MYSQL_DATA_TRUNCATED.
libmysql/libmysql.c:
- added support for data truncation during fetch
- implementation for is_binary_compatible: now conversion functions
are used less frequently
- we now use number_to_datetime and TIME_to_ulonglong for date->number and
number->date conversions
sql-common/my_time.c:
- added implementation of date->number and number->date calls shared
between client and server (moved from time.cc).
sql/field.cc:
- implemented Field_time::store_time() to better support date->time
conversions in prepared mode. After-review fixes.
sql/field.h:
- Field::store_time now returns int
sql/mysql_priv.h:
- removed date->number and number->date conversion functions headers
(moved to my_time.h)
sql/time.cc:
- removed implementation of date->number and number->date conversion
functions (moved to my_time.c)
tests/client_test.c:
- added a test case for data truncation; other test cases adjusted.
- fixed my_process_stmt_result to set STMT_ATTR_UPDATE_MAX_LENGTH (tables
are now printed out prettier).
Diffstat (limited to 'tests')
-rw-r--r-- | tests/client_test.c | 366 |
1 files changed, 311 insertions, 55 deletions
diff --git a/tests/client_test.c b/tests/client_test.c index 979c1563c02..e63580ce031 100644 --- a/tests/client_test.c +++ b/tests/client_test.c @@ -517,16 +517,18 @@ int my_process_stmt_result(MYSQL_STMT *stmt) buffer[i].buffer= (void *) data[i]; buffer[i].is_null= &is_null[i]; } - my_print_result_metadata(result); rc= mysql_stmt_bind_result(stmt, buffer); check_execute(stmt, rc); + rc= 1; + mysql_stmt_attr_set(stmt, STMT_ATTR_UPDATE_MAX_LENGTH, (void*)&rc); rc= mysql_stmt_store_result(stmt); check_execute(stmt, rc); + my_print_result_metadata(result); mysql_field_seek(result, 0); - while (mysql_stmt_fetch(stmt) == 0) + while ((rc= mysql_stmt_fetch(stmt)) == 0) { if (!opt_silent) { @@ -559,6 +561,7 @@ int my_process_stmt_result(MYSQL_STMT *stmt) } row_count++; } + DIE_UNLESS(rc == MYSQL_NO_DATA); if (!opt_silent) { if (row_count) @@ -1876,6 +1879,7 @@ static void test_fetch_null() myquery(rc); /* fetch */ + bzero(bind, sizeof(bind)); for (i= 0; i < (int) array_elements(bind); i++) { bind[i].buffer_type= MYSQL_TYPE_LONG; @@ -2941,11 +2945,13 @@ static void test_long_data_str1() bind[0].buffer= (void *) &data; /* this buffer won't be altered */ bind[0].buffer_length= 16; bind[0].length= &blob_length; + bind[0].error= &bind[0].error_value; rc= mysql_stmt_bind_result(stmt, bind); data[16]= 0; rc= mysql_stmt_fetch(stmt); - DIE_UNLESS(rc == 0); + DIE_UNLESS(rc == MYSQL_DATA_TRUNCATED); + DIE_UNLESS(bind[0].error_value); DIE_UNLESS(strlen(data) == 16); DIE_UNLESS(blob_length == max_blob_length); @@ -3308,10 +3314,10 @@ static void test_bind_result() /* fetch */ + bzero(bind, sizeof(bind)); bind[0].buffer_type= MYSQL_TYPE_LONG; bind[0].buffer= (void *) &nData; /* integer data */ bind[0].is_null= &is_null[0]; - bind[0].length= 0; bind[1].buffer_type= MYSQL_TYPE_STRING; bind[1].buffer= szData; /* string data */ @@ -3402,6 +3408,7 @@ static void test_bind_result_ext() rc= mysql_commit(mysql); myquery(rc); + bzero(bind, sizeof(bind)); for (i= 0; i < (int) array_elements(bind); i++) { bind[i].length= &length[i]; @@ -3520,37 +3527,46 @@ static void test_bind_result_ext1() rc= mysql_commit(mysql); myquery(rc); + bzero(bind, sizeof(bind)); bind[0].buffer_type= MYSQL_TYPE_STRING; bind[0].buffer= (void *) t_data; bind[0].buffer_length= sizeof(t_data); + bind[0].error= &bind[0].error_value; bind[1].buffer_type= MYSQL_TYPE_FLOAT; bind[1].buffer= (void *)&s_data; bind[1].buffer_length= 0; + bind[1].error= &bind[1].error_value; bind[2].buffer_type= MYSQL_TYPE_SHORT; bind[2].buffer= (void *)&i_data; bind[2].buffer_length= 0; + bind[2].error= &bind[2].error_value; bind[3].buffer_type= MYSQL_TYPE_TINY; bind[3].buffer= (void *)&b_data; bind[3].buffer_length= 0; + bind[3].error= &bind[3].error_value; bind[4].buffer_type= MYSQL_TYPE_LONG; bind[4].buffer= (void *)&f_data; bind[4].buffer_length= 0; + bind[4].error= &bind[4].error_value; bind[5].buffer_type= MYSQL_TYPE_STRING; bind[5].buffer= (void *)d_data; bind[5].buffer_length= sizeof(d_data); + bind[5].error= &bind[5].error_value; bind[6].buffer_type= MYSQL_TYPE_LONG; bind[6].buffer= (void *)&bData; bind[6].buffer_length= 0; + bind[6].error= &bind[6].error_value; bind[7].buffer_type= MYSQL_TYPE_DOUBLE; bind[7].buffer= (void *)&szData; bind[7].buffer_length= 0; + bind[7].error= &bind[7].error_value; for (i= 0; i < array_elements(bind); i++) { @@ -3568,7 +3584,8 @@ static void test_bind_result_ext1() check_execute(stmt, rc); rc= mysql_stmt_fetch(stmt); - check_execute(stmt, rc); + DIE_UNLESS(rc == MYSQL_DATA_TRUNCATED); + DIE_UNLESS(bind[4].error_value == 1); if (!opt_silent) { @@ -3803,6 +3820,7 @@ static void test_fetch_date() rc= mysql_commit(mysql); myquery(rc); + bzero(bind, sizeof(bind)); for (i= 0; i < array_elements(bind); i++) { bind[i].is_null= &is_null[i]; @@ -4605,8 +4623,6 @@ static void test_set_variable() get_bind[1].buffer_type= MYSQL_TYPE_LONG; get_bind[1].buffer= (void *)&get_count; - get_bind[1].is_null= 0; - get_bind[1].length= 0; rc= mysql_stmt_execute(stmt1); check_execute(stmt1, rc); @@ -5522,6 +5538,7 @@ static void test_store_result() myquery(rc); /* fetch */ + bzero(bind, sizeof(bind)); bind[0].buffer_type= MYSQL_TYPE_LONG; bind[0].buffer= (void *) &nData; /* integer data */ bind[0].length= &length; @@ -5988,7 +6005,7 @@ static void test_bind_date_conv(uint row_count) for (count= 0; count < row_count; count++) { rc= mysql_stmt_fetch(stmt); - check_execute(stmt, rc); + DIE_UNLESS(rc == 0 || rc == MYSQL_DATA_TRUNCATED); if (!opt_silent) fprintf(stdout, "\n"); @@ -6004,14 +6021,8 @@ static void test_bind_date_conv(uint row_count) DIE_UNLESS(tm[i].day == 0 || tm[i].day == day+count); DIE_UNLESS(tm[i].hour == 0 || tm[i].hour == hour+count); -#ifdef NOT_USED - /* - minute causes problems from date<->time, don't assert, instead - validate separatly in another routine - */ DIE_UNLESS(tm[i].minute == 0 || tm[i].minute == minute+count); DIE_UNLESS(tm[i].second == 0 || tm[i].second == sec+count); -#endif DIE_UNLESS(tm[i].second_part == 0 || tm[i].second_part == second_part+count); } @@ -6242,13 +6253,15 @@ static void test_buffers() rc= mysql_stmt_execute(stmt); check_execute(stmt, rc); - bzero(buffer, 20); /* Avoid overruns in printf() */ + bzero(buffer, sizeof(buffer)); /* Avoid overruns in printf() */ + bzero(bind, sizeof(bind)); bind[0].length= &length; bind[0].is_null= &is_null; bind[0].buffer_length= 1; bind[0].buffer_type= MYSQL_TYPE_STRING; bind[0].buffer= (void *)buffer; + bind[0].error= &bind[0].error_value; rc= mysql_stmt_bind_result(stmt, bind); check_execute(stmt, rc); @@ -6258,7 +6271,8 @@ static void test_buffers() buffer[1]= 'X'; rc= mysql_stmt_fetch(stmt); - check_execute(stmt, rc); + DIE_UNLESS(rc == MYSQL_DATA_TRUNCATED); + DIE_UNLESS(bind[0].error_value); if (!opt_silent) fprintf(stdout, "\n data: %s (%lu)", buffer, length); DIE_UNLESS(buffer[0] == 'M'); @@ -6292,7 +6306,8 @@ static void test_buffers() check_execute(stmt, rc); rc= mysql_stmt_fetch(stmt); - check_execute(stmt, rc); + DIE_UNLESS(rc == MYSQL_DATA_TRUNCATED); + DIE_UNLESS(bind[0].error_value); if (!opt_silent) fprintf(stdout, "\n data: %s (%lu)", buffer, length); DIE_UNLESS(strncmp(buffer, "Popula", 6) == 0); @@ -6429,10 +6444,9 @@ static void test_fetch_nobuffs() fprintf(stdout, "\n total rows : %d", rc); DIE_UNLESS(rc == 1); + bzero(bind, sizeof(MYSQL_BIND)); bind[0].buffer_type= MYSQL_TYPE_STRING; bind[0].buffer= (void *)str[0]; - bind[0].is_null= 0; - bind[0].length= 0; bind[0].buffer_length= sizeof(str[0]); bind[1]= bind[2]= bind[3]= bind[0]; bind[1].buffer= (void *)str[1]; @@ -6489,7 +6503,8 @@ static void test_ushort_bug() d smallint unsigned)"); myquery(rc); - rc= mysql_query(mysql, "INSERT INTO test_ushort VALUES(35999, 35999, 35999, 200)"); + rc= mysql_query(mysql, + "INSERT INTO test_ushort VALUES(35999, 35999, 35999, 200)"); myquery(rc); @@ -6499,24 +6514,23 @@ static void test_ushort_bug() rc= mysql_stmt_execute(stmt); check_execute(stmt, rc); + bzero(bind, sizeof(bind)); bind[0].buffer_type= MYSQL_TYPE_SHORT; bind[0].buffer= (void *)&short_value; - bind[0].is_null= 0; + bind[0].is_unsigned= TRUE; bind[0].length= &s_length; bind[1].buffer_type= MYSQL_TYPE_LONG; bind[1].buffer= (void *)&long_value; - bind[1].is_null= 0; bind[1].length= &l_length; bind[2].buffer_type= MYSQL_TYPE_LONGLONG; bind[2].buffer= (void *)&longlong_value; - bind[2].is_null= 0; bind[2].length= &ll_length; bind[3].buffer_type= MYSQL_TYPE_TINY; bind[3].buffer= (void *)&tiny_value; - bind[3].is_null= 0; + bind[3].is_unsigned= TRUE; bind[3].length= &t_length; rc= mysql_stmt_bind_result(stmt, bind); @@ -6586,24 +6600,22 @@ static void test_sshort_bug() rc= mysql_stmt_execute(stmt); check_execute(stmt, rc); + bzero(bind, sizeof(bind)); bind[0].buffer_type= MYSQL_TYPE_SHORT; bind[0].buffer= (void *)&short_value; - bind[0].is_null= 0; bind[0].length= &s_length; bind[1].buffer_type= MYSQL_TYPE_LONG; bind[1].buffer= (void *)&long_value; - bind[1].is_null= 0; bind[1].length= &l_length; bind[2].buffer_type= MYSQL_TYPE_LONGLONG; bind[2].buffer= (void *)&longlong_value; - bind[2].is_null= 0; bind[2].length= &ll_length; bind[3].buffer_type= MYSQL_TYPE_TINY; bind[3].buffer= (void *)&tiny_value; - bind[3].is_null= 0; + bind[3].is_unsigned= TRUE; bind[3].length= &t_length; rc= mysql_stmt_bind_result(stmt, bind); @@ -6673,24 +6685,21 @@ static void test_stiny_bug() rc= mysql_stmt_execute(stmt); check_execute(stmt, rc); + bzero(bind, sizeof(bind)); bind[0].buffer_type= MYSQL_TYPE_SHORT; bind[0].buffer= (void *)&short_value; - bind[0].is_null= 0; bind[0].length= &s_length; bind[1].buffer_type= MYSQL_TYPE_LONG; bind[1].buffer= (void *)&long_value; - bind[1].is_null= 0; bind[1].length= &l_length; bind[2].buffer_type= MYSQL_TYPE_LONGLONG; bind[2].buffer= (void *)&longlong_value; - bind[2].is_null= 0; bind[2].length= &ll_length; bind[3].buffer_type= MYSQL_TYPE_TINY; bind[3].buffer= (void *)&tiny_value; - bind[3].is_null= 0; bind[3].length= &t_length; rc= mysql_stmt_bind_result(stmt, bind); @@ -6783,10 +6792,10 @@ static void test_field_misc() rc= mysql_stmt_execute(stmt); check_execute(stmt, rc); + bzero(bind, sizeof(bind)); bind[0].buffer_type= MYSQL_TYPE_STRING; bind[0].buffer= table_type; bind[0].length= &type_length; - bind[0].is_null= 0; bind[0].buffer_length= NAME_LEN; rc= mysql_stmt_bind_result(stmt, bind); @@ -6857,10 +6866,10 @@ static void test_field_misc() DIE_UNLESS(1 == my_process_stmt_result(stmt)); verify_prepare_field(result, 0, - "@@max_allowed_packet", "", /* field and its org name */ + "@@max_allowed_packet", "", /* field and its org name */ MYSQL_TYPE_LONGLONG, /* field type */ "", "", /* table and its org name */ - "", 10, 0); /* db name, length */ + "", 10, 0); /* db name, length */ mysql_free_result(result); mysql_stmt_close(stmt); @@ -7093,11 +7102,10 @@ static void test_frm_bug() rc= mysql_stmt_execute(stmt); check_execute(stmt, rc); + bzero(bind, sizeof(bind)); bind[0].buffer_type= MYSQL_TYPE_STRING; bind[0].buffer= data_dir; bind[0].buffer_length= FN_REFLEN; - bind[0].is_null= 0; - bind[0].length= 0; bind[1]= bind[0]; rc= mysql_stmt_bind_result(stmt, bind); @@ -7828,17 +7836,13 @@ static void test_fetch_seek() stmt= mysql_simple_prepare(mysql, "select * from t1"); check_stmt(stmt); + bzero(bind, sizeof(bind)); bind[0].buffer_type= MYSQL_TYPE_LONG; bind[0].buffer= (void *)&c1; - bind[0].buffer_length= 0; - bind[0].is_null= 0; - bind[0].length= 0; bind[1].buffer_type= MYSQL_TYPE_STRING; bind[1].buffer= (void *)c2; bind[1].buffer_length= sizeof(c2); - bind[1].is_null= 0; - bind[1].length= 0; bind[2]= bind[1]; bind[2].buffer= (void *)c3; @@ -7928,6 +7932,7 @@ static void test_fetch_offset() stmt= mysql_simple_prepare(mysql, "select * from t1"); check_stmt(stmt); + bzero(bind, sizeof(bind)); bind[0].buffer_type= MYSQL_TYPE_STRING; bind[0].buffer= (void *)data; bind[0].buffer_length= 11; @@ -8014,6 +8019,7 @@ static void test_fetch_column() stmt= mysql_simple_prepare(mysql, "select * from t1 order by c2 desc"); check_stmt(stmt); + bzero(bind, sizeof(bind)); bind[0].buffer_type= MYSQL_TYPE_LONG; bind[0].buffer= (void *)&bc1; bind[0].buffer_length= 0; @@ -8261,10 +8267,9 @@ static void test_free_result() stmt= mysql_simple_prepare(mysql, "select * from test_free_result"); check_stmt(stmt); + bzero(bind, sizeof(bind)); bind[0].buffer_type= MYSQL_TYPE_LONG; bind[0].buffer= (void *)&bc1; - bind[0].buffer_length= 0; - bind[0].is_null= 0; bind[0].length= &bl1; rc= mysql_stmt_execute(stmt); @@ -8342,6 +8347,7 @@ static void test_free_store_result() stmt= mysql_simple_prepare(mysql, "select * from test_free_result"); check_stmt(stmt); + bzero(bind, sizeof(bind)); bind[0].buffer_type= MYSQL_TYPE_LONG; bind[0].buffer= (void *)&bc1; bind[0].buffer_length= 0; @@ -8732,10 +8738,6 @@ static void test_bug1500() rc= my_process_stmt_result(stmt); DIE_UNLESS(rc == 1); - /* - FIXME If we comment out next string server will crash too :( - This is another manifestation of bug #1663 - */ mysql_stmt_close(stmt); /* This should work too */ @@ -8906,7 +8908,7 @@ static void test_subqueries() int rc, i; const char *query= "SELECT (SELECT SUM(a+b) FROM t2 where t1.b=t2.b GROUP BY t1.a LIMIT 1) as scalar_s, exists (select 1 from t2 where t2.a/2=t1.a) as exists_s, a in (select a+3 from t2) as in_s, (a-1, b-1) in (select a, b from t2) as in_row_s FROM t1, (select a x, b y from t2) tt WHERE x=a"; - myheader("test_subquery"); + myheader("test_subqueries"); rc= mysql_query(mysql, "DROP TABLE IF EXISTS t1, t2"); myquery(rc); @@ -8957,7 +8959,7 @@ static void test_distinct() const char *query= "SELECT 2+count(distinct b), group_concat(a) FROM t1 group by a"; - myheader("test_subquery"); + myheader("test_distinct"); rc= mysql_query(mysql, "DROP TABLE IF EXISTS t1"); myquery(rc); @@ -9755,7 +9757,7 @@ static void test_bug3035() { MYSQL_STMT *stmt; int rc; - MYSQL_BIND bind_array[12]; + MYSQL_BIND bind_array[12], *bind= bind_array, *bind_end= bind + 12; int8 int8_val; uint8 uint8_val; int16 int16_val; @@ -9808,6 +9810,9 @@ static void test_bug3035() bzero(bind_array, sizeof(bind_array)); + for (bind= bind_array; bind < bind_end; bind++) + bind->error= &bind->error_value; + bind_array[0].buffer_type= MYSQL_TYPE_TINY; bind_array[0].buffer= (void *) &int8_val; @@ -9913,7 +9918,15 @@ static void test_bug3035() DIE_UNLESS(!strcmp(ulonglong_as_string, "0")); rc= mysql_stmt_fetch(stmt); - check_execute(stmt, rc); + + if (!opt_silent) + { + printf("Truncation mask: "); + for (bind= bind_array; bind < bind_end; bind++) + printf("%d", (int) bind->error_value); + printf("\n"); + } + DIE_UNLESS(rc == MYSQL_DATA_TRUNCATED); DIE_UNLESS(int8_val == int8_max); DIE_UNLESS(uint8_val == uint8_max); @@ -10180,12 +10193,12 @@ static void test_union_param() /* bind parameters */ bind[0].buffer_type= MYSQL_TYPE_STRING; - bind[0].buffer= my_val; + bind[0].buffer= (char*) &my_val; bind[0].buffer_length= 4; bind[0].length= &my_length; bind[0].is_null= (char*)&my_null; bind[1].buffer_type= MYSQL_TYPE_STRING; - bind[1].buffer= my_val; + bind[1].buffer= (char*) &my_val; bind[1].buffer_length= 4; bind[1].length= &my_length; bind[1].is_null= (char*)&my_null; @@ -11898,7 +11911,7 @@ static void test_datetime_ranges() rc= mysql_stmt_execute(stmt); check_execute(stmt, rc); - DIE_UNLESS(mysql_warning_count(mysql) != 2); + DIE_UNLESS(mysql_warning_count(mysql) == 2); verify_col_data("t1", "day_ovfl", "838:59:59"); verify_col_data("t1", "day", "828:30:30"); @@ -12047,6 +12060,248 @@ static void test_conversion() } +static void test_truncation() +{ + MYSQL_STMT *stmt; + const char *stmt_text; + int rc; + MYSQL_BIND *bind_array, *bind; + + myheader("test_truncation"); + + /* Prepare the test table */ + rc= mysql_query(mysql, "drop table if exists t1"); + myquery(rc); + + stmt_text= "create table t1 (" + "i8 tinyint, ui8 tinyint unsigned, " + "i16 smallint, i16_1 smallint, " + "ui16 smallint unsigned, i32 int, i32_1 int, " + "d double, d_1 double, ch char(30), ch_1 char(30), " + "tx text, tx_1 text, ch_2 char(30) " + ")"; + rc= mysql_real_query(mysql, stmt_text, strlen(stmt_text)); + myquery(rc); + stmt_text= "insert into t1 VALUES (" + "-10, " /* i8 */ + "200, " /* ui8 */ + "32000, " /* i16 */ + "-32767, " /* i16_1 */ + "64000, " /* ui16 */ + "1073741824, " /* i32 */ + "1073741825, " /* i32_1 */ + "123.456, " /* d */ + "-12345678910, " /* d_1 */ + "'111111111111111111111111111111',"/* ch */ + "'abcdef', " /* ch_1 */ + "'12345 ', " /* tx */ + "'12345.67 ', " /* tx_1 */ + "'12345.67abc'" /* ch_2 */ + ")"; + rc= mysql_real_query(mysql, stmt_text, strlen(stmt_text)); + myquery(rc); + + stmt_text= "select i8 c1, i8 c2, ui8 c3, i16_1 c4, ui16 c5, " + " i16 c6, ui16 c7, i32 c8, i32_1 c9, i32_1 c10, " + " d c11, d_1 c12, d_1 c13, ch c14, ch_1 c15, tx c16, " + " tx_1 c17, ch_2 c18 " + "from t1"; + + stmt= mysql_stmt_init(mysql); + rc= mysql_stmt_prepare(stmt, stmt_text, strlen(stmt_text)); + check_execute(stmt, rc); + rc= mysql_stmt_execute(stmt); + check_execute(stmt, rc); + uint bind_count= (uint) mysql_stmt_field_count(stmt); + + /*************** Fill in the bind structure and bind it **************/ + bind_array= malloc(sizeof(MYSQL_BIND) * bind_count); + bzero(bind_array, sizeof(MYSQL_BIND) * bind_count); + for (bind= bind_array; bind < bind_array + bind_count; bind++) + bind->error= &bind->error_value; + bind= bind_array; + + bind->buffer= malloc(sizeof(uint8)); + bind->buffer_type= MYSQL_TYPE_TINY; + bind->is_unsigned= TRUE; + + DIE_UNLESS(++bind < bind_array + bind_count); + bind->buffer= malloc(sizeof(uint32)); + bind->buffer_type= MYSQL_TYPE_LONG; + bind->is_unsigned= TRUE; + + DIE_UNLESS(++bind < bind_array + bind_count); + bind->buffer= malloc(sizeof(int8)); + bind->buffer_type= MYSQL_TYPE_TINY; + + DIE_UNLESS(++bind < bind_array + bind_count); + bind->buffer= malloc(sizeof(uint16)); + bind->buffer_type= MYSQL_TYPE_SHORT; + bind->is_unsigned= TRUE; + + DIE_UNLESS(++bind < bind_array + bind_count); + bind->buffer= malloc(sizeof(int16)); + bind->buffer_type= MYSQL_TYPE_SHORT; + + DIE_UNLESS(++bind < bind_array + bind_count); + bind->buffer= malloc(sizeof(uint16)); + bind->buffer_type= MYSQL_TYPE_SHORT; + bind->is_unsigned= TRUE; + + DIE_UNLESS(++bind < bind_array + bind_count); + bind->buffer= malloc(sizeof(int8)); + bind->buffer_type= MYSQL_TYPE_TINY; + bind->is_unsigned= TRUE; + + DIE_UNLESS(++bind < bind_array + bind_count); + bind->buffer= malloc(sizeof(float)); + bind->buffer_type= MYSQL_TYPE_FLOAT; + + DIE_UNLESS(++bind < bind_array + bind_count); + bind->buffer= malloc(sizeof(float)); + bind->buffer_type= MYSQL_TYPE_FLOAT; + + DIE_UNLESS(++bind < bind_array + bind_count); + bind->buffer= malloc(sizeof(double)); + bind->buffer_type= MYSQL_TYPE_DOUBLE; + + DIE_UNLESS(++bind < bind_array + bind_count); + bind->buffer= malloc(sizeof(longlong)); + bind->buffer_type= MYSQL_TYPE_LONGLONG; + + DIE_UNLESS(++bind < bind_array + bind_count); + bind->buffer= malloc(sizeof(ulonglong)); + bind->buffer_type= MYSQL_TYPE_LONGLONG; + bind->is_unsigned= TRUE; + + DIE_UNLESS(++bind < bind_array + bind_count); + bind->buffer= malloc(sizeof(longlong)); + bind->buffer_type= MYSQL_TYPE_LONGLONG; + + DIE_UNLESS(++bind < bind_array + bind_count); + bind->buffer= malloc(sizeof(longlong)); + bind->buffer_type= MYSQL_TYPE_LONGLONG; + + DIE_UNLESS(++bind < bind_array + bind_count); + bind->buffer= malloc(sizeof(longlong)); + bind->buffer_type= MYSQL_TYPE_LONGLONG; + + DIE_UNLESS(++bind < bind_array + bind_count); + bind->buffer= malloc(sizeof(longlong)); + bind->buffer_type= MYSQL_TYPE_LONGLONG; + + DIE_UNLESS(++bind < bind_array + bind_count); + bind->buffer= malloc(sizeof(double)); + bind->buffer_type= MYSQL_TYPE_DOUBLE; + + DIE_UNLESS(++bind < bind_array + bind_count); + bind->buffer= malloc(sizeof(double)); + bind->buffer_type= MYSQL_TYPE_DOUBLE; + + rc= mysql_stmt_bind_result(stmt, bind_array); + check_execute(stmt, rc); + rc= mysql_stmt_fetch(stmt); + DIE_UNLESS(rc == MYSQL_DATA_TRUNCATED); + + /*************** Verify truncation results ***************************/ + bind= bind_array; + + /* signed tiny -> tiny */ + DIE_UNLESS(*bind->error && * (int8*) bind->buffer == -10); + + /* signed tiny -> uint32 */ + DIE_UNLESS(++bind < bind_array + bind_count); + DIE_UNLESS(*bind->error && * (int32*) bind->buffer == -10); + + /* unsigned tiny -> tiny */ + DIE_UNLESS(++bind < bind_array + bind_count); + DIE_UNLESS(*bind->error && * (uint8*) bind->buffer == 200); + + /* short -> ushort */ + DIE_UNLESS(++bind < bind_array + bind_count); + DIE_UNLESS(*bind->error && * (int16*) bind->buffer == -32767); + + /* ushort -> short */ + DIE_UNLESS(++bind < bind_array + bind_count); + DIE_UNLESS(*bind->error && * (uint16*) bind->buffer == 64000); + + /* short -> ushort (no truncation, data is in the range of target type) */ + DIE_UNLESS(++bind < bind_array + bind_count); + DIE_UNLESS(! *bind->error && * (uint16*) bind->buffer == 32000); + + /* ushort -> utiny */ + DIE_UNLESS(++bind < bind_array + bind_count); + DIE_UNLESS(*bind->error && * (int8*) bind->buffer == 0); + + /* int -> float: no truncation, the number is a power of two */ + DIE_UNLESS(++bind < bind_array + bind_count); + DIE_UNLESS(! *bind->error && * (float*) bind->buffer == 1073741824); + + /* int -> float: truncation, not enough bits in float */ + DIE_UNLESS(++bind < bind_array + bind_count); + /* do nothing: due to a gcc bug result here is not predictable */ + + /* int -> double: no truncation */ + DIE_UNLESS(++bind < bind_array + bind_count); + DIE_UNLESS(! *bind->error && * (double*) bind->buffer == 1073741825); + + /* double -> longlong: fractional part is lost */ + DIE_UNLESS(++bind < bind_array + bind_count); + DIE_UNLESS(*bind->error && * (longlong*) bind->buffer == 123); + + /* double -> ulonglong, negative fp number to unsigned integer */ + DIE_UNLESS(++bind < bind_array + bind_count); + /* Value in the buffer is not defined: don't test it */ + DIE_UNLESS(*bind->error); + + /* double -> longlong, negative fp number to signed integer: no loss */ + DIE_UNLESS(++bind < bind_array + bind_count); + DIE_UNLESS(! *bind->error && * (longlong*) bind->buffer == LL(-12345678910)); + + /* big numeric string -> number */ + DIE_UNLESS(++bind < bind_array + bind_count); + DIE_UNLESS(*bind->error); + + /* junk string -> number */ + DIE_UNLESS(++bind < bind_array + bind_count); + DIE_UNLESS(*bind->error && *(longlong*) bind->buffer == 0); + + /* string with trailing spaces -> number */ + DIE_UNLESS(++bind < bind_array + bind_count); + DIE_UNLESS(! *bind->error && *(longlong*) bind->buffer == 12345); + + /* string with trailing spaces -> double */ + DIE_UNLESS(++bind < bind_array + bind_count); + DIE_UNLESS(! *bind->error && *(double*) bind->buffer == 12345.67); + + /* string with trailing junk -> double */ + DIE_UNLESS(++bind < bind_array + bind_count); + /* + XXX: There must be a truncation error: but it's not the way the server + behaves, so let's leave it for now. + */ + DIE_UNLESS(*(double*) bind->buffer == 12345.67); + /* + TODO: string -> double, double -> time, double -> string (truncation + errors are not supported here yet) + longlong -> time/date/datetime + date -> time, date -> timestamp, date -> number + time -> string, time -> date, time -> timestamp, + number -> date string -> date + */ + /*************** Cleanup *********************************************/ + + mysql_stmt_close(stmt); + + for (bind= bind_array; bind < bind_array + bind_count; bind++) + free(bind->buffer); + free(bind_array); + + rc= mysql_query(mysql, "drop table t1"); + myquery(rc); +} + + /* Read and parse arguments and MySQL options from my.cnf */ @@ -12260,6 +12515,7 @@ static struct my_tests_st my_tests[]= { { "test_view_insert_fields", test_view_insert_fields }, { "test_basic_cursors", test_basic_cursors }, { "test_cursors_with_union", test_cursors_with_union }, + { "test_truncation", test_truncation }, { 0, 0 } }; |