From 15b099cf025817b73732e39deb7ea3f9aa2c9fab Mon Sep 17 00:00:00 2001 From: unknown Date: Tue, 4 Feb 2003 18:50:48 -0800 Subject: [PATCH 01/11] Windows compile fixups (To be verified by respective devs) sql/field.cc: Windows - Cast (longlong -> uint) sql/item_uniq.h: Windows compile fix sql/sql_derived.cc: Windows - compile fix --- sql/field.cc | 2 +- sql/item_uniq.h | 2 +- sql/sql_derived.cc | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/sql/field.cc b/sql/field.cc index 7b21f179660..9697b6c158e 100644 --- a/sql/field.cc +++ b/sql/field.cc @@ -1913,7 +1913,7 @@ int Field_longlong::store(const char *from,uint len,CHARSET_INFO *cs) char *end; tmp= cs->scan(cs, from, from+len, MY_SEQ_SPACES); - len-= tmp; + len-= (uint)tmp; from+= tmp; my_errno=0; if (unsigned_flag) diff --git a/sql/item_uniq.h b/sql/item_uniq.h index ac004e747f8..5ffd10be7a5 100644 --- a/sql/item_uniq.h +++ b/sql/item_uniq.h @@ -50,7 +50,7 @@ public: fixed= 1; return 0; } - Item_sum *copy_or_same(THD* thd) + Item *copy_or_same(THD* thd) { return new Item_sum_unique_users(thd, *this); } diff --git a/sql/sql_derived.cc b/sql/sql_derived.cc index d1a232c35b6..ced3e3d4a98 100644 --- a/sql/sql_derived.cc +++ b/sql/sql_derived.cc @@ -71,7 +71,7 @@ int mysql_derived(THD *thd, LEX *lex, SELECT_LEX_UNIT *unit, TABLE_LIST *t) TABLE_LIST *tables= (TABLE_LIST *)sl->table_list.first; TMP_TABLE_PARAM tmp_table_param; bool is_union= sl->next_select() && sl->next_select()->linkage == UNION_TYPE; - bool is_subsel= sl->first_inner_unit(); + bool is_subsel= sl->first_inner_unit() ? 1: 0; SELECT_LEX_NODE *save_current_select= lex->current_select; DBUG_ENTER("mysql_derived"); From a7b46e40cce1162922a4449e13eebed418ee34f2 Mon Sep 17 00:00:00 2001 From: unknown Date: Tue, 4 Feb 2003 18:54:14 -0800 Subject: [PATCH 02/11] Conversion fix - bug report from PHP Added a new conversion bug test Changed options with default_options read from my.ini from [client] section More cleanups for better usage libmysql/libmysql.c: Conversion fix - bug report from PHP tests/client_test.c: Added a new conversion bug test Changed options with default_options read from my.ini from [client] section More cleanups for better usage --- libmysql/libmysql.c | 39 ++-- tests/client_test.c | 513 +++++++++++++++++++++++++++----------------- 2 files changed, 343 insertions(+), 209 deletions(-) diff --git a/libmysql/libmysql.c b/libmysql/libmysql.c index d9dde0689d0..62a18282ea6 100644 --- a/libmysql/libmysql.c +++ b/libmysql/libmysql.c @@ -163,6 +163,11 @@ void STDCALL mysql_thread_end() #define reset_sigpipe(mysql) #endif +#define map_to_size(A,L) {\ + char *tmp= (char *)&A;\ + memset(tmp+L,0,8-L);\ +} + static MYSQL* spawn_init(MYSQL* parent, const char* host, unsigned int port, const char* user, @@ -4686,13 +4691,13 @@ static void send_data_long(MYSQL_BIND *param, longlong value) *param->buffer= (uchar) value; break; case MYSQL_TYPE_SHORT: - int2store(buffer, (short)value); + int2store(buffer, value); break; case MYSQL_TYPE_LONG: - int4store(buffer, (int32)value); + int4store(buffer, value); break; case MYSQL_TYPE_LONGLONG: - int8store(buffer, (longlong)value); + int8store(buffer, value); break; case MYSQL_TYPE_FLOAT: { @@ -4726,13 +4731,13 @@ static void send_data_double(MYSQL_BIND *param, double value) *buffer= (uchar)value; break; case MYSQL_TYPE_SHORT: - int2store(buffer, (short)value); + int2store(buffer, value); break; case MYSQL_TYPE_LONG: - int4store(buffer, (int32)value); + int4store(buffer, value); break; case MYSQL_TYPE_LONGLONG: - int8store(buffer, (longlong)value); + int8store(buffer, value); break; case MYSQL_TYPE_FLOAT: { @@ -4873,24 +4878,24 @@ static void fetch_results(MYSQL_BIND *param, uint field_type, uchar **row) switch (field_type) { case MYSQL_TYPE_TINY: { - uchar value= (uchar) **row; - send_data_long(param,(longlong)value); - length= 1; + longlong value= (longlong) **row; + map_to_size(value,(length= 1)); + send_data_long(param,value); break; } case MYSQL_TYPE_SHORT: case MYSQL_TYPE_YEAR: { - short value= (short)sint2korr(*row); - send_data_long(param,(longlong)value); - length= 2; + longlong value= (longlong)sint2korr(*row); + map_to_size(value,(length= 2)); + send_data_long(param, value); break; } case MYSQL_TYPE_LONG: { - int32 value= (int32)sint4korr(*row); - send_data_long(param,(int32)value); - length= 4; + longlong value= (longlong)sint4korr(*row); + map_to_size(value,(length= 4)); + send_data_long(param,value); break; } case MYSQL_TYPE_LONGLONG: @@ -4904,7 +4909,7 @@ static void fetch_results(MYSQL_BIND *param, uint field_type, uchar **row) { float value; float4get(value,*row); - send_data_double(param,(double)value); + send_data_double(param,value); length= 4; break; } @@ -4912,7 +4917,7 @@ static void fetch_results(MYSQL_BIND *param, uint field_type, uchar **row) { double value; float8get(value,*row); - send_data_double(param,(double)value); + send_data_double(param,value); length= 8; break; } diff --git a/tests/client_test.c b/tests/client_test.c index dc91bf2cbf1..c2d81729f52 100644 --- a/tests/client_test.c +++ b/tests/client_test.c @@ -34,6 +34,9 @@ #include #include + +#define MAX_TEST_QUERY_LENGTH 300 /* MAX QUERY BUFFER LENGTH */ + /* set default options */ static char *opt_db=0; static char *opt_user=0; @@ -44,7 +47,7 @@ static unsigned int opt_port; static my_bool tty_password=0; static MYSQL *mysql=0; -static char query[255]; +static char query[MAX_TEST_QUERY_LENGTH]; static char current_db[]= "client_test_db"; static unsigned int test_count= 0; static unsigned int opt_count= 0; @@ -77,7 +80,7 @@ static double total_time; static void print_error(const char *msg) { - if (mysql) + if (mysql && mysql_errno(mysql)) { if (mysql->server_version) fprintf(stdout,"\n [MySQL-%s]",mysql->server_version); @@ -90,7 +93,7 @@ static void print_error(const char *msg) static void print_st_error(MYSQL_STMT *stmt, const char *msg) { - if (stmt) + if (stmt && mysql_stmt_errno(stmt)) { if (stmt->mysql && stmt->mysql->server_version) fprintf(stdout,"\n [MySQL-%s]",stmt->mysql->server_version); @@ -98,7 +101,7 @@ static void print_st_error(MYSQL_STMT *stmt, const char *msg) fprintf(stdout,"\n [MySQL]"); fprintf(stdout,"[%d] %s\n",mysql_stmt_errno(stmt), - mysql_stmt_error(stmt)); + mysql_stmt_error(stmt)); } else if (msg) fprintf(stderr, " [MySQL] %s\n", msg); } @@ -147,48 +150,53 @@ myassert(stmt != 0); \ #define mystmt_init_r(stmt) \ { \ +if (stmt == 0) \ + myerror(NULL);\ myassert(stmt == 0);\ } #define mytest(x) if (!x) {myerror(NULL);myassert(TRUE);} #define mytest_r(x) if (x) {myerror(NULL);myassert(TRUE);} -#define PREPARE(A,B) mysql_prepare(A,B,strlen(B)) - /******************************************************** * connect to the server * *********************************************************/ static void client_connect() { int rc; - char buff[255]; myheader_r("client_connect"); fprintf(stdout, "\n Establishig a connection ..."); + if (!(mysql = mysql_init(NULL))) { myerror("mysql_init() failed"); exit(0); } + if (!(mysql_real_connect(mysql,opt_host,opt_user, - opt_password, opt_db ? opt_db:"test", opt_port, - opt_unix_socket, 0))) + opt_password, opt_db ? opt_db:"test", opt_port, + opt_unix_socket, 0))) { myerror("connection failed"); mysql_close(mysql); fprintf(stdout,"\n Check the connection options using --help or -?\n"); exit(0); } + fprintf(stdout," OK"); /* set AUTOCOMMIT to ON*/ mysql_autocommit(mysql, TRUE); + fprintf(stdout, "\n Creating a test database '%s' ...", current_db); - strxmov(buff,"CREATE DATABASE IF NOT EXISTS ", current_db, NullS); - rc = mysql_query(mysql, buff); + strxmov(query,"CREATE DATABASE IF NOT EXISTS ", current_db, NullS); + + rc = mysql_query(mysql, query); myquery(rc); - strxmov(buff,"USE ", current_db, NullS); - rc = mysql_query(mysql, buff); + + strxmov(query,"USE ", current_db, NullS); + rc = mysql_query(mysql, query); myquery(rc); fprintf(stdout," OK"); @@ -203,11 +211,12 @@ static void client_disconnect() if (mysql) { - char buff[255]; fprintf(stdout, "\n droping the test database '%s' ...", current_db); - strxmov(buff,"DROP DATABASE IF EXISTS ", current_db, NullS); - mysql_query(mysql, buff); + strxmov(query,"DROP DATABASE IF EXISTS ", current_db, NullS); + + mysql_query(mysql, query); fprintf(stdout, " OK"); + fprintf(stdout, "\n closing the connection ..."); mysql_close(mysql); fprintf(stdout, " OK\n"); @@ -350,7 +359,8 @@ int my_process_result_set(MYSQL_RES *result) fputc('\n',stdout); row_count++; } - my_print_dashes(result); + if (row_count) + my_print_dashes(result); if (mysql_errno(mysql) != 0) fprintf(stderr, "\n\tmysql_fetch_row() failed\n"); @@ -363,35 +373,37 @@ int my_process_result_set(MYSQL_RES *result) /******************************************************** * process the stmt result set * *********************************************************/ +#define MAX_RES_FIELDS 50 +#define MAX_FIELD_DATA_SIZE 255 + uint my_process_stmt_result(MYSQL_STMT *stmt) { int field_count; uint row_count= 0; - MYSQL_BIND buffer[50]; + MYSQL_BIND buffer[MAX_RES_FIELDS]; MYSQL_FIELD *field; MYSQL_RES *result; - char data[50][255]; - ulong length[50]; - my_bool is_null[50]; + char data[MAX_RES_FIELDS][MAX_FIELD_DATA_SIZE]; + ulong length[MAX_RES_FIELDS]; + my_bool is_null[MAX_RES_FIELDS]; int rc, i; - if (!(result= mysql_prepare_result(stmt))) + if (!(result= mysql_prepare_result(stmt))) /* No meta info */ { while (!mysql_fetch(stmt)) row_count++; return row_count; } - field_count= mysql_num_fields(result); + field_count= min(mysql_num_fields(result), MAX_RES_FIELDS); for(i=0; i < field_count; i++) { buffer[i].buffer_type= MYSQL_TYPE_STRING; - buffer[i].buffer_length=50; - buffer[i].length=&length[i]; - buffer[i].buffer=(char*) data[i]; + buffer[i].buffer_length= MAX_FIELD_DATA_SIZE; + buffer[i].length= &length[i]; + buffer[i].buffer= (char*) data[i]; buffer[i].is_null= &is_null[i]; } - my_print_result_metadata(result); rc= mysql_bind_result(stmt,buffer); @@ -426,7 +438,9 @@ uint my_process_stmt_result(MYSQL_STMT *stmt) fputc('\n',stdout); row_count++; } - my_print_dashes(result); + if (row_count) + my_print_dashes(result); + fprintf(stdout,"\n\t%d %s returned\n", row_count, row_count == 1 ? "row" : "rows"); mysql_free_result(result); @@ -436,14 +450,14 @@ uint my_process_stmt_result(MYSQL_STMT *stmt) /******************************************************** * process the stmt result set * *********************************************************/ -uint my_stmt_result(const char *query, unsigned long length) +uint my_stmt_result(const char *buff, unsigned long length) { MYSQL_STMT *stmt; uint row_count; int rc; - fprintf(stdout,"\n\n %s", query); - stmt= mysql_prepare(mysql,query,length); + fprintf(stdout,"\n\n %s", buff); + stmt= mysql_prepare(mysql,buff,length); mystmt_init(stmt); rc = mysql_execute(stmt); @@ -463,7 +477,6 @@ static void verify_col_data(const char *table, const char *col, { MYSQL_RES *result; MYSQL_ROW row; - char query[255]; int rc, field= 1; if (table && col) @@ -528,11 +541,44 @@ static void verify_prepare_field(MYSQL_RES *result, static void verify_param_count(MYSQL_STMT *stmt, long exp_count) { long param_count= mysql_param_count(stmt); - fprintf(stdout,"\n total parameters in stmt: %ld (expected: %ld)", + fprintf(stdout,"\n total parameters in stmt: `%ld` (expected: `%ld`)", param_count, exp_count); myassert(param_count == exp_count); } +/* + Utility function to verify the total affected rows +*/ +static void verify_st_affected_rows(MYSQL_STMT *stmt, ulonglong exp_count) +{ + ulonglong affected_rows= mysql_stmt_affected_rows(stmt); + fprintf(stdout,"\n total affected rows: `%lld` (expected: `%lld`)", + affected_rows, exp_count); + myassert(affected_rows == exp_count); +} + +/* + Utility function to verify the total affected rows +*/ +static void verify_affected_rows(ulonglong exp_count) +{ + ulonglong affected_rows= mysql_affected_rows(mysql); + fprintf(stdout,"\n total affected rows: `%lld` (expected: `%lld`)", + affected_rows, exp_count); + myassert(affected_rows == exp_count); +} + +/* + Utility function to verify the total fields count +*/ +static void verify_field_count(MYSQL_RES *result, uint exp_count) +{ + uint field_count= mysql_num_fields(result); + fprintf(stdout,"\n total fields in the result set: `%d` (expected: `%d`)", + field_count, exp_count); + myassert(field_count == exp_count); +} + /******************************************************** * store result processing * @@ -683,7 +729,7 @@ static void test_tran_bdb() rc = mysql_commit(mysql); myquery(rc); - /* now insert the second row, and rollback the transaction */ + /* now insert the second row, and rollback the transaction */ rc = mysql_query(mysql,"INSERT INTO my_demo_transaction VALUES(20,'mysql')"); myquery(rc); @@ -761,7 +807,7 @@ static void test_tran_innodb() rc = mysql_commit(mysql); myquery(rc); - /* now insert the second row, and rollback the transaction */ + /* now insert the second row, and rollback the transaction */ rc = mysql_query(mysql,"INSERT INTO my_demo_transaction VALUES(20,'mysql')"); myquery(rc); @@ -826,32 +872,32 @@ static void test_prepare_simple() myquery(rc); /* alter table */ - strcpy(query,"ALTER TABLE test_prepare_simple ADD new char(20)"); - stmt = mysql_prepare(mysql, query, strlen(query)); + strmov(query,"ALTER TABLE test_prepare_simple ADD new char(20)"); + stmt = mysql_prepare(mysql, query, 70); mystmt_init(stmt); verify_param_count(stmt,0); mysql_stmt_close(stmt); /* insert */ - strcpy(query,"INSERT INTO test_prepare_simple VALUES(?,?)"); - stmt = mysql_prepare(mysql, query, strlen(query)); + strmov(query,"INSERT INTO test_prepare_simple VALUES(?,?)"); + stmt = mysql_prepare(mysql, query, 70); mystmt_init(stmt); verify_param_count(stmt,2); mysql_stmt_close(stmt); /* update */ - strcpy(query,"UPDATE test_prepare_simple SET id=? WHERE id=? AND name= ?"); - stmt = mysql_prepare(mysql, query, strlen(query)); + strmov(query,"UPDATE test_prepare_simple SET id=? WHERE id=? AND name= ?"); + stmt = mysql_prepare(mysql, query, 100); mystmt_init(stmt); verify_param_count(stmt,3); mysql_stmt_close(stmt); /* delete */ - strcpy(query,"DELETE FROM test_prepare_simple WHERE id=10"); - stmt = mysql_prepare(mysql, query, strlen(query)); + strmov(query,"DELETE FROM test_prepare_simple WHERE id=10"); + stmt = mysql_prepare(mysql, query, 60); mystmt_init(stmt); verify_param_count(stmt,0); @@ -861,8 +907,8 @@ static void test_prepare_simple() mysql_stmt_close(stmt); /* delete */ - strcpy(query,"DELETE FROM test_prepare_simple WHERE id=?"); - stmt = mysql_prepare(mysql, query, strlen(query)); + strmov(query,"DELETE FROM test_prepare_simple WHERE id=?"); + stmt = mysql_prepare(mysql, query, 50); mystmt_init(stmt); verify_param_count(stmt,1); @@ -872,8 +918,8 @@ static void test_prepare_simple() mysql_stmt_close(stmt); /* select */ - strcpy(query,"SELECT * FROM test_prepare_simple WHERE id=? AND name= ?"); - stmt = mysql_prepare(mysql, query, strlen(query)); + strmov(query,"SELECT * FROM test_prepare_simple WHERE id=? AND name= ?"); + stmt = mysql_prepare(mysql, query, 100); mystmt_init(stmt); verify_param_count(stmt,2); @@ -893,7 +939,7 @@ static void test_prepare_field_result() { MYSQL_STMT *stmt; MYSQL_RES *result; - int rc,param_count; + int rc; myheader("test_prepare_field_result"); @@ -909,7 +955,7 @@ static void test_prepare_field_result() myquery(rc); /* insert */ - strcpy(query,"SELECT int_c,var_c,date_c as date,ts_c,char_c FROM \ + strmov(query,"SELECT int_c,var_c,date_c as date,ts_c,char_c FROM \ test_prepare_field_result as t1 WHERE int_c=?"); stmt = mysql_prepare(mysql, query, strlen(query)); mystmt_init(stmt); @@ -933,9 +979,7 @@ static void test_prepare_field_result() verify_prepare_field(result,4,"char_c","char_c",MYSQL_TYPE_STRING, "t1","test_prepare_field_result",current_db); - param_count= mysql_num_fields(result); - fprintf(stdout,"\n\n total fields: `%d` (expected: `5`)", param_count); - myassert(param_count == 5); + verify_field_count(result, 5); mysql_free_result(result); mysql_stmt_close(stmt); } @@ -960,11 +1004,11 @@ static void test_prepare_syntax() rc = mysql_query(mysql,"CREATE TABLE test_prepare_syntax(id int, name varchar(50), extra int)"); myquery(rc); - strcpy(query,"INSERT INTO test_prepare_syntax VALUES(?"); + strmov(query,"INSERT INTO test_prepare_syntax VALUES(?"); stmt = mysql_prepare(mysql, query, strlen(query)); mystmt_init_r(stmt); - strcpy(query,"SELECT id,name FROM test_prepare_syntax WHERE id=? AND WHERE"); + strmov(query,"SELECT id,name FROM test_prepare_syntax WHERE id=? AND WHERE"); stmt = mysql_prepare(mysql, query, strlen(query)); mystmt_init_r(stmt); @@ -981,7 +1025,6 @@ static void test_prepare() { MYSQL_STMT *stmt; int rc, i; - char query[200]; int int_data, o_int_data; char str_data[50], data[50]; char tiny_data, o_tiny_data; @@ -1011,7 +1054,7 @@ static void test_prepare() myquery(rc); /* insert by prepare */ - strcpy(query,"INSERT INTO my_prepare VALUES(?,?,?,?,?,?,?)"); + strxmov(query,"INSERT INTO my_prepare VALUES(?,?,?,?,?,?,?)",NullS); stmt = mysql_prepare(mysql, query, strlen(query)); mystmt_init(stmt); @@ -1102,15 +1145,17 @@ static void test_prepare() rc = mysql_fetch(stmt); mystmt(stmt, rc); - fprintf(stdout, "\n tiny : %d (%lu)", tiny_data,length[0]); - fprintf(stdout, "\n short : %d (%lu)", small_data,length[3]); - fprintf(stdout, "\n int : %d (%lu)", int_data,length[2]); - fprintf(stdout, "\n big : %lld (%lu)", big_data,length[4]); + fprintf(stdout, "\n"); + + fprintf(stdout, "\n\t tiny : %d (%lu)", tiny_data,length[0]); + fprintf(stdout, "\n\t short : %d (%lu)", small_data,length[3]); + fprintf(stdout, "\n\t int : %d (%lu)", int_data,length[2]); + fprintf(stdout, "\n\t big : %lld (%lu)", big_data,length[4]); - fprintf(stdout, "\n float : %f (%lu)", real_data,length[5]); - fprintf(stdout, "\n double : %f (%lu)", double_data,length[6]); + fprintf(stdout, "\n\t float : %f (%lu)", real_data,length[5]); + fprintf(stdout, "\n\t double : %f (%lu)", double_data,length[6]); - fprintf(stdout, "\n str : %s (%lu)", str_data, length[1]); + fprintf(stdout, "\n\t str : %s (%lu)", str_data, length[1]); myassert(tiny_data == o_tiny_data); myassert(is_null[0] == 0); @@ -1156,7 +1201,7 @@ static void test_double_compare() { MYSQL_STMT *stmt; int rc; - char query[200],real_data[10], tiny_data; + char real_data[10], tiny_data; double double_data; MYSQL_RES *result; MYSQL_BIND bind[3]; @@ -1180,7 +1225,7 @@ static void test_double_compare() rc = mysql_query(mysql,"INSERT INTO test_double_compare VALUES(1,10.2,34.5)"); myquery(rc); - strcpy(query, "UPDATE test_double_compare SET col1=100 WHERE col1 = ? AND col2 = ? AND COL3 = ?"); + strmov(query, "UPDATE test_double_compare SET col1=100 WHERE col1 = ? AND col2 = ? AND COL3 = ?"); stmt = mysql_prepare(mysql,query, strlen(query)); mystmt_init(stmt); @@ -1213,8 +1258,7 @@ static void test_double_compare() rc = mysql_execute(stmt); mystmt(stmt, rc); - rc = (int)mysql_affected_rows(mysql); - fprintf(stdout,"\n total affected rows:%d",rc); + verify_affected_rows(0); mysql_stmt_close(stmt); @@ -1344,7 +1388,6 @@ static void test_fetch_null() { MYSQL_STMT *stmt; int rc; - const char query[100]; int i, nData; MYSQL_BIND bind[11]; ulong length[11]; @@ -1425,12 +1468,10 @@ static void test_select_version() { MYSQL_STMT *stmt; int rc; - const char query[100]; myheader("test_select_version"); - strmov((char *)query , "SELECT @@version"); - stmt = PREPARE(mysql, query); + stmt = mysql_prepare(mysql, "SELECT @@version", 30); mystmt_init(stmt); verify_param_count(stmt,0); @@ -1449,13 +1490,10 @@ static void test_select_simple() { MYSQL_STMT *stmt; int rc; - const char query[100]; myheader("test_select_simple"); - /* insert by prepare */ - strmov((char *)query, "SHOW TABLES FROM mysql"); - stmt = mysql_prepare(mysql, query, strlen(query)); + stmt = mysql_prepare(mysql, "SHOW TABLES FROM mysql", 50); mystmt_init(stmt); verify_param_count(stmt,0); @@ -1639,7 +1677,7 @@ static void test_select() /* string data */ nData=10; - strcpy(szData,(char *)"venu"); + strmov(szData,(char *)"venu"); bind[1].buffer_type=FIELD_TYPE_STRING; bind[1].buffer=(char *)szData; bind[1].buffer_length= 4; @@ -1750,7 +1788,7 @@ static void test_simple_update() rc = mysql_query(mysql,"INSERT INTO test_update VALUES(1,'MySQL',100)"); myquery(rc); - myassert(1 == mysql_affected_rows(mysql)); + verify_affected_rows(1); rc = mysql_commit(mysql); myquery(rc); @@ -1779,7 +1817,7 @@ static void test_simple_update() rc = mysql_execute(stmt); mystmt(stmt, rc); - myassert(1 == mysql_affected_rows(mysql)); + verify_affected_rows(1); mysql_stmt_close(stmt); @@ -2184,7 +2222,7 @@ static void test_simple_delete() rc = mysql_query(mysql,"INSERT INTO test_simple_delete VALUES(1,'MySQL',100)"); myquery(rc); - myassert(1 == mysql_affected_rows(mysql)); + verify_affected_rows(1); rc = mysql_commit(mysql); myquery(rc); @@ -2214,7 +2252,8 @@ static void test_simple_delete() rc = mysql_execute(stmt); mystmt(stmt, rc); - myassert(1 == mysql_affected_rows(mysql)); + + verify_affected_rows(1); mysql_stmt_close(stmt); @@ -2292,7 +2331,7 @@ static void test_update() rc = mysql_execute(stmt); mystmt(stmt, rc); - myassert(1 == mysql_affected_rows(mysql)); + verify_affected_rows(1); mysql_stmt_close(stmt); strmov(query,"UPDATE test_update SET col2=? WHERE col3=?"); @@ -2316,7 +2355,7 @@ static void test_update() rc = mysql_execute(stmt); mystmt(stmt, rc); - myassert(1 == mysql_affected_rows(mysql)); + verify_affected_rows(1); mysql_stmt_close(stmt); @@ -2394,7 +2433,6 @@ static void test_bind_result() { MYSQL_STMT *stmt; int rc; - char query[100]; int nData; ulong length, length1; char szData[100]; @@ -2440,8 +2478,7 @@ static void test_bind_result() bind[1].length= &length1; bind[1].is_null= &is_null[1]; - strmov(query , "SELECT * FROM test_bind_result"); - stmt = mysql_prepare(mysql, query, strlen(query)); + stmt = mysql_prepare(mysql, "SELECT * FROM test_bind_result", 50); mystmt_init(stmt); rc = mysql_bind_result(stmt,bind); @@ -2490,7 +2527,6 @@ static void test_bind_result_ext() { MYSQL_STMT *stmt; int rc, i; - const char query[100]; uchar t_data; short s_data; int i_data; @@ -2563,8 +2599,7 @@ static void test_bind_result_ext() bind[7].length= &bLength; bind[7].buffer_length= sizeof(bData); - strmov((char *)query , "SELECT * FROM test_bind_result"); - stmt = mysql_prepare(mysql, query, strlen(query)); + stmt = mysql_prepare(mysql, "select * from test_bind_result", 50); mystmt_init(stmt); rc = mysql_bind_result(stmt,bind); @@ -2614,11 +2649,10 @@ static void test_bind_result_ext1() MYSQL_STMT *stmt; uint i; int rc; - const char query[100]; char t_data[20]; float s_data; short i_data; - short b_data; + uchar b_data; int f_data; long bData; char d_data[20]; @@ -2655,7 +2689,6 @@ static void test_bind_result_ext1() bind[0].buffer_type=MYSQL_TYPE_STRING; bind[0].buffer=(char *) t_data; bind[0].buffer_length= sizeof(t_data); - bind[0].length= &length[0]; bind[1].buffer_type=MYSQL_TYPE_FLOAT; bind[1].buffer=(char *)&s_data; @@ -2684,8 +2717,7 @@ static void test_bind_result_ext1() bind[i].length= &length[i]; } - strmov((char *)query , "SELECT * FROM test_bind_result"); - stmt = mysql_prepare(mysql, query, strlen(query)); + stmt = mysql_prepare(mysql, "select * from test_bind_result", 50); mystmt_init(stmt); rc = mysql_bind_result(stmt,bind); @@ -2712,6 +2744,7 @@ static void test_bind_result_ext1() myassert(i_data == 3999); myassert(f_data == 2); myassert(strcmp(d_data,"58.89")==0); + myassert(b_data == 54); myassert(length[0] == 3); myassert(length[1] == 4); @@ -3399,13 +3432,19 @@ static void test_warnings() myheader("test_warnings"); + mysql_query(mysql, "DROP TABLE if exists test_non_exists"); + + rc = mysql_query(mysql, "DROP TABLE if exists test_non_exists"); + myquery(rc); + + fprintf(stdout, "\n total warnings: %d", mysql_warning_count(mysql)); rc = mysql_query(mysql,"SHOW WARNINGS"); myquery(rc); - result = mysql_use_result(mysql); + result = mysql_store_result(mysql); mytest(result); - my_process_result_set(result); + myassert(1 == my_process_result_set(result)); mysql_free_result(result); } @@ -3419,10 +3458,15 @@ static void test_errors() myheader("test_errors"); + mysql_query(mysql, "DROP TABLE if exists test_non_exists"); + + rc = mysql_query(mysql, "DROP TABLE test_non_exists"); + myquery_r(rc); + rc = mysql_query(mysql,"SHOW ERRORS"); myquery(rc); - result = mysql_use_result(mysql); + result = mysql_store_result(mysql); mytest(result); my_process_result_set(result); @@ -3438,12 +3482,11 @@ static void test_insert() { MYSQL_STMT *stmt; int rc; - char query[200]; char str_data[50]; char tiny_data; MYSQL_RES *result; MYSQL_BIND bind[2]; - ulong length[2]; + ulong length; myheader("test_insert"); @@ -3461,9 +3504,7 @@ static void test_insert() myquery(rc); /* insert by prepare */ - bzero(bind, sizeof(bind)); - strmov(query,"INSERT INTO test_prep_insert VALUES(?,?)"); - stmt = mysql_prepare(mysql, query, strlen(query)); + stmt = mysql_prepare(mysql, "INSERT INTO test_prep_insert VALUES(?,?)", 70); mystmt_init(stmt); verify_param_count(stmt,2); @@ -3472,12 +3513,14 @@ static void test_insert() bind[0].buffer_type=FIELD_TYPE_TINY; bind[0].buffer=(char *)&tiny_data; bind[0].is_null= 0; + bind[0].length= 0; /* string */ bind[1].buffer_type=FIELD_TYPE_STRING; bind[1].buffer=str_data; bind[1].buffer_length=sizeof(str_data);; bind[1].is_null= 0; + bind[1].length= &length; rc = mysql_bind_param(stmt,bind); mystmt(stmt, rc); @@ -3485,7 +3528,7 @@ static void test_insert() /* now, execute the prepared statement to insert 10 records.. */ for (tiny_data=0; tiny_data < 3; tiny_data++) { - length[1] = my_sprintf(str_data, (str_data, "MySQL%d",tiny_data)); + length = my_sprintf(str_data, (str_data, "MySQL%d",tiny_data)); rc = mysql_execute(stmt); mystmt(stmt, rc); } @@ -3516,7 +3559,6 @@ static void test_prepare_resultset() { MYSQL_STMT *stmt; int rc; - char query[200]; MYSQL_RES *result; myheader("test_prepare_resultset"); @@ -3534,8 +3576,7 @@ static void test_prepare_resultset() name varchar(50),extra double)"); myquery(rc); - strmov(query,"SELECT * FROM test_prepare_resultset"); - stmt = PREPARE(mysql, query); + stmt = mysql_prepare(mysql, "SELECT * FROM test_prepare_resultset", 60); mystmt_init(stmt); verify_param_count(stmt,0); @@ -3616,7 +3657,6 @@ static void test_stmt_close() MYSQL_STMT *stmt1, *stmt2, *stmt3, *stmt_x; MYSQL_BIND bind[1]; MYSQL_RES *result; - char query[100]; unsigned int count; int rc; @@ -3648,25 +3688,25 @@ static void test_stmt_close() myquery(rc); strmov(query,"ALTER TABLE test_stmt_close ADD name varchar(20)"); - stmt1= PREPARE(lmysql, query); + stmt1= mysql_prepare(lmysql, query, 70); mystmt_init(stmt1); verify_param_count(stmt1, 0); strmov(query,"INSERT INTO test_stmt_close(id) VALUES(?)"); - stmt_x= PREPARE(mysql, query); + stmt_x= mysql_prepare(mysql, query, 70); mystmt_init(stmt_x); verify_param_count(stmt_x, 1); strmov(query,"UPDATE test_stmt_close SET id=? WHERE id=?"); - stmt3= PREPARE(lmysql, query); + stmt3= mysql_prepare(lmysql, query, 70); mystmt_init(stmt3); verify_param_count(stmt3, 2); strmov(query,"SELECT * FROM test_stmt_close WHERE id=?"); - stmt2= PREPARE(lmysql, query); + stmt2= mysql_prepare(lmysql, query, 70); mystmt_init(stmt2); verify_param_count(stmt2, 1); @@ -3698,9 +3738,7 @@ static void test_stmt_close() rc = mysql_execute(stmt_x); mystmt(stmt_x, rc); - rc= (ulong)mysql_stmt_affected_rows(stmt_x); - fprintf(stdout,"\n total rows affected: %d", rc); - myassert (rc == 1); + verify_st_affected_rows(stmt_x, 1); rc= mysql_stmt_close(stmt_x); fprintf(stdout,"\n mysql_close_stmt(x) returned: %d", rc); @@ -3820,7 +3858,6 @@ static void test_insert_meta() { MYSQL_STMT *stmt; int rc; - char query[200]; MYSQL_RES *result; MYSQL_FIELD *field; @@ -3840,7 +3877,7 @@ static void test_insert_meta() myquery(rc); strmov(query,"INSERT INTO test_prep_insert VALUES(10,'venu1','test')"); - stmt = mysql_prepare(mysql, query, strlen(query)); + stmt = mysql_prepare(mysql, query, 70); mystmt_init(stmt); verify_param_count(stmt,0); @@ -3851,7 +3888,7 @@ static void test_insert_meta() mysql_stmt_close(stmt); strmov(query,"INSERT INTO test_prep_insert VALUES(?,'venu',?)"); - stmt = mysql_prepare(mysql, query, strlen(query)); + stmt = mysql_prepare(mysql, query, 70); mystmt_init(stmt); verify_param_count(stmt,2); @@ -3884,7 +3921,6 @@ static void test_update_meta() { MYSQL_STMT *stmt; int rc; - char query[200]; MYSQL_RES *result; MYSQL_FIELD *field; @@ -3904,7 +3940,7 @@ static void test_update_meta() myquery(rc); strmov(query,"UPDATE test_prep_update SET col1=10, col2='venu1' WHERE col3='test'"); - stmt = mysql_prepare(mysql, query, strlen(query)); + stmt = mysql_prepare(mysql, query, 100); mystmt_init(stmt); verify_param_count(stmt,0); @@ -3915,7 +3951,7 @@ static void test_update_meta() mysql_stmt_close(stmt); strmov(query,"UPDATE test_prep_update SET col1=?, col2='venu' WHERE col3=?"); - stmt = mysql_prepare(mysql, query, strlen(query)); + stmt = mysql_prepare(mysql, query, 100); mystmt_init(stmt); verify_param_count(stmt,2); @@ -3952,7 +3988,6 @@ static void test_select_meta() { MYSQL_STMT *stmt; int rc; - char query[200]; MYSQL_RES *result; MYSQL_FIELD *field; @@ -3972,7 +4007,7 @@ static void test_select_meta() myquery(rc); strmov(query,"SELECT * FROM test_prep_select WHERE col1=10"); - stmt = mysql_prepare(mysql, query, strlen(query)); + stmt = mysql_prepare(mysql, query, 70); mystmt_init(stmt); verify_param_count(stmt,0); @@ -3981,7 +4016,7 @@ static void test_select_meta() mytest_r(result); strmov(query,"SELECT col1, col3 from test_prep_select WHERE col1=? AND col3='test' AND col2= ?"); - stmt = mysql_prepare(mysql, query, strlen(query)); + stmt = mysql_prepare(mysql, query, 120); mystmt_init(stmt); verify_param_count(stmt,2); @@ -4170,9 +4205,7 @@ static void test_multi_stmt() rc = mysql_execute(stmt2); mystmt(stmt2, rc); - rc = (int)mysql_stmt_affected_rows(stmt2); - fprintf(stdout,"\n total rows affected(update): %d", rc); - myassert(rc == 1); + verify_st_affected_rows(stmt2, 1); rc = mysql_execute(stmt); mystmt(stmt, rc); @@ -4191,9 +4224,7 @@ static void test_multi_stmt() rc = mysql_execute(stmt1); mystmt(stmt1, rc); - rc = (int)mysql_stmt_affected_rows(stmt1); - fprintf(stdout,"\n total rows affected(delete): %d", rc); - myassert(rc == 1); + verify_st_affected_rows(stmt1, 1); mysql_stmt_close(stmt1); @@ -4219,11 +4250,11 @@ static void test_manual_sample() unsigned int param_count; MYSQL_STMT *stmt; short small_data; - int int_data, i; - char str_data[50], query[255]; + int int_data; + char str_data[50]; ulonglong affected_rows; MYSQL_BIND bind[3]; - my_bool is_null[3]; + my_bool is_null; myheader("test_manual_sample"); @@ -4271,24 +4302,24 @@ static void test_manual_sample() /* Bind the data for the parameters */ /* INTEGER PART */ - memset(bind,0,sizeof(bind)); bind[0].buffer_type= MYSQL_TYPE_LONG; bind[0].buffer= (char *)&int_data; + bind[0].is_null= 0; + bind[0].length= 0; /* STRING PART */ bind[1].buffer_type= MYSQL_TYPE_VAR_STRING; bind[1].buffer= (char *)str_data; bind[1].buffer_length= sizeof(str_data); + bind[1].is_null= 0; + bind[1].length= 0; /* SMALLINT PART */ bind[2].buffer_type= MYSQL_TYPE_SHORT; bind[2].buffer= (char *)&small_data; - - for (i= 0; i < (int) array_elements(bind); i++) - { - bind[i].is_null= &is_null[i]; - is_null[i]=0; - } + bind[2].is_null= &is_null; + bind[2].length= 0; + is_null= 0; /* Bind the buffers */ if (mysql_bind_param(stmt, bind)) @@ -4301,8 +4332,9 @@ static void test_manual_sample() /* Specify the data */ int_data= 10; /* integer */ strmov(str_data,"MySQL"); /* string */ + /* INSERT SMALLINT data as NULL */ - is_null[2]= 1; + is_null= 1; /* Execute the insert statement - 1*/ if (mysql_execute(stmt)) @@ -4326,7 +4358,7 @@ static void test_manual_sample() int_data= 1000; strmov(str_data,"The most popular open source database"); small_data= 1000; /* smallint */ - is_null[2]= 0; + is_null= 0; /* reset */ /* Execute the insert statement - 2*/ if (mysql_execute(stmt)) @@ -4484,7 +4516,8 @@ static void test_multi_query() if ((result= mysql_store_result(mysql))) my_process_result_set(result); else - fprintf(stdout,"OK, %d row(s) affected, %d warning(s)", exp_value, + fprintf(stdout,"OK, %lld row(s) affected, %d warning(s)", + mysql_affected_rows(mysql), mysql_warning_count(mysql)); exp_value= (uint) mysql_affected_rows(mysql); } @@ -4501,7 +4534,6 @@ static void test_store_result() { MYSQL_STMT *stmt; int rc; - const char query[100]; long nData; char szData[100]; MYSQL_BIND bind[2]; @@ -4545,8 +4577,7 @@ static void test_store_result() bind[1].is_null= &is_null[1]; length1= 0; - strmov((char *)query , "SELECT * FROM test_store_result"); - stmt = mysql_prepare(mysql, query, strlen(query)); + stmt = mysql_prepare(mysql, "SELECT * FROM test_store_result", 50); mystmt_init(stmt); rc = mysql_bind_result(stmt,bind); @@ -4726,7 +4757,6 @@ static void test_store_result2() bind[0].buffer= (char *) &nData; /* integer data */ bind[0].length= &length; bind[0].is_null= 0; - length= 0; strmov((char *)query , "SELECT col1 FROM test_store_result where col1= ?"); stmt = mysql_prepare(mysql, query, strlen(query)); @@ -4817,17 +4847,17 @@ static void test_subselect() myquery(rc); /* fetch */ - - bind[0].buffer_type=FIELD_TYPE_LONG; + bind[0].buffer_type= FIELD_TYPE_LONG; bind[0].buffer= (char *) &id; bind[0].length= &length; - bind[0],is_null= 0; - length=0; + bind[0].is_null= 0; + length= 0; strmov((char *)query , "SELECT ROW(1,7) IN (select id, id1 from test_sub2 WHERE id1=?)"); myassert(1 == my_stmt_result("SELECT ROW(1,7) IN (select id, id1 from test_sub2 WHERE id1=8)",100)); myassert(1 == my_stmt_result("SELECT ROW(1,7) IN (select id, id1 from test_sub2 WHERE id1=7)",100)); - stmt = mysql_prepare(mysql, query, strlen(query)); + + stmt = mysql_prepare(mysql, query, 150); mystmt_init(stmt); rc = mysql_bind_param(stmt,bind); @@ -4843,9 +4873,22 @@ static void test_subselect() rc = mysql_fetch(stmt); mystmt(stmt,rc); - fprintf(stdout,"\n row 1: %d(%lu)",id, length); + fprintf(stdout,"\n row 1: %d (%lu)",id, length); myassert(id == 1); + rc = mysql_fetch(stmt); + myassert(rc == MYSQL_NO_DATA); + + id= 8; + rc = mysql_execute(stmt); + mystmt(stmt, rc); + + rc = mysql_fetch(stmt); + mystmt(stmt,rc); + + fprintf(stdout,"\n row 1: %d (%lu)",id, length); + myassert(id == 0); + rc = mysql_fetch(stmt); myassert(rc == MYSQL_NO_DATA); @@ -4859,7 +4902,7 @@ static void test_subselect() */ static void test_bind_date_conv(uint row_count) { - MYSQL_STMT *stmt; + MYSQL_STMT *stmt= 0; uint rc, i, count= row_count; ulong length[4]; MYSQL_BIND bind[4]; @@ -5129,8 +5172,6 @@ static void test_pure_coverage() stmt = mysql_prepare(mysql,"insert into test_pure(c2) values(10)",100); mystmt_init(stmt); - verify_param_count(stmt, 0); - rc = mysql_bind_param(stmt, bind); mystmt_r(stmt, rc); @@ -5307,8 +5348,7 @@ static void test_open_direct() rc = mysql_execute(stmt); mystmt(stmt, rc); - fprintf(stdout, "\n total affected rows: %lld", mysql_stmt_affected_rows(stmt)); - myassert(1 == mysql_stmt_affected_rows(stmt)); + verify_st_affected_rows(stmt, 1); rc = mysql_query(mysql, "SELECT * FROM test_open_direct"); myquery(rc); @@ -5321,8 +5361,7 @@ static void test_open_direct() rc = mysql_execute(stmt); mystmt(stmt, rc); - fprintf(stdout, "\n total affected rows: %lld", mysql_stmt_affected_rows(stmt)); - myassert(1 == mysql_stmt_affected_rows(stmt)); + verify_st_affected_rows(stmt, 1); rc = mysql_query(mysql, "SELECT * FROM test_open_direct"); myquery(rc); @@ -5384,7 +5423,8 @@ static void test_fetch_nobuffs() myheader("test_fetch_nobuffs"); - stmt = mysql_prepare(mysql,"SELECT DATABASE(), CURRENT_USER(), CURRENT_DATE(), CURRENT_TIME()",100); + stmt = mysql_prepare(mysql,"SELECT DATABASE(), CURRENT_USER(), \ + CURRENT_DATE(), CURRENT_TIME()",100); mystmt_init(stmt); rc = mysql_execute(stmt); @@ -5393,7 +5433,8 @@ static void test_fetch_nobuffs() rc = 0; while (mysql_fetch(stmt) != MYSQL_NO_DATA) rc++; - fprintf(stdout, "\n total rows: %d", rc); + + fprintf(stdout, "\n total rows : %d", rc); myassert(rc == 1); bind[0].buffer_type= MYSQL_TYPE_STRING; @@ -5421,13 +5462,104 @@ static void test_fetch_nobuffs() fprintf(stdout, "\n CURRENT_DATE() : %s", str[2]); fprintf(stdout, "\n CURRENT_TIME() : %s", str[3]); } - fprintf(stdout, "\n total rows: %d", rc); + fprintf(stdout, "\n total rows : %d", rc); myassert(rc == 1); mysql_stmt_close(stmt); } -static struct my_option myctest_long_options[] = +/* + To test a misc bug +*/ +static void test_ushort_bug() +{ + MYSQL_STMT *stmt; + MYSQL_BIND bind[4]; + ushort short_value; + ulong long_value; + ulong s_length, l_length, ll_length, t_length; + ulonglong longlong_value; + int rc; + uchar tiny_value; + + myheader("test_ushort_bug"); + + rc= mysql_query(mysql,"DROP TABLE IF EXISTS test_ushort"); + myquery(rc); + + rc= mysql_query(mysql,"CREATE TABLE test_ushort(a smallint unsigned, \ + b smallint unsigned, \ + c smallint unsigned, \ + d smallint unsigned)"); + myquery(rc); + + rc= mysql_query(mysql,"INSERT INTO test_ushort VALUES(35999, 35999, 35999, 200)"); + myquery(rc); + + + stmt = mysql_prepare(mysql,"SELECT * FROM test_ushort",50); + mystmt_init(stmt); + + rc = mysql_execute(stmt); + mystmt(stmt, rc); + + bind[0].buffer_type= MYSQL_TYPE_SHORT; + bind[0].buffer= (char *)&short_value; + bind[0].is_null= 0; + bind[0].length= &s_length; + + bind[1].buffer_type= MYSQL_TYPE_LONG; + bind[1].buffer= (char *)&long_value; + bind[1].is_null= 0; + bind[1].length= &l_length; + + bind[2].buffer_type= MYSQL_TYPE_LONGLONG; + bind[2].buffer= (char *)&longlong_value; + bind[2].is_null= 0; + bind[2].length= &ll_length; + + bind[3].buffer_type= MYSQL_TYPE_TINY; + bind[3].buffer= (char *)&tiny_value; + bind[3].is_null= 0; + bind[3].length= &t_length; + + rc = mysql_bind_result(stmt, bind); + mystmt(stmt, rc); + + rc = mysql_fetch(stmt); + mystmt(stmt, rc); + + fprintf(stdout,"\n ushort: %d (%ld)", short_value, s_length); + fprintf(stdout,"\n ulong : %ld (%ld)", long_value, l_length); + fprintf(stdout,"\n ulong : %lld (%ld)", longlong_value, ll_length); + fprintf(stdout,"\n ulong : %d (%ld)", tiny_value, t_length); + + myassert(short_value == 35999); + myassert(s_length == 2); + + myassert(long_value == 35999); + myassert(l_length == 4); + + myassert(longlong_value == 35999); + myassert(ll_length == 8); + + myassert(tiny_value == 200); + myassert(t_length == 1); + + rc = mysql_fetch(stmt); + myassert(rc == MYSQL_NO_DATA); + + mysql_stmt_close(stmt); +} + +/* + Read and parse arguments and MySQL options from my.cnf +*/ + +static const char *client_test_load_default_groups[]= { "client", 0 }; +static char **defaults_argv; + +static struct my_option client_test_long_options[] = { {"help", '?', "Display this help and exit", 0, 0, 0, GET_NO_ARG, NO_ARG, 0, 0, 0, 0, 0, 0}, @@ -5447,10 +5579,18 @@ static struct my_option myctest_long_options[] = {"socket", 'S', "Socket file to use for connection", (char **) &opt_unix_socket, (char **) &opt_unix_socket, 0, GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0}, {"count", 't', "Number of times test to be executed", (char **) &opt_count, - (char **) &opt_count, 0, GET_UINT, REQUIRED_ARG, 0, 0, 0, 0, 0, 0}, + (char **) &opt_count, 0, GET_UINT, REQUIRED_ARG, 1, 0, 0, 0, 0, 0}, { 0, 0, 0, 0, 0, 0, GET_NO_ARG, NO_ARG, 0, 0, 0, 0, 0, 0} }; + +static void client_test_print_version(void) +{ + fprintf(stdout, "%s Distrib %s, for %s (%s)\n\n", + my_progname,MYSQL_SERVER_VERSION,SYSTEM_TYPE,MACHINE_TYPE); +} + + static void usage(void) { /* @@ -5464,25 +5604,13 @@ static void usage(void) puts("and you are welcome to modify and redistribute it under the GPL license\n"); puts(" Copyright (C) 1995-2003 MySQL AB "); puts("-----------------------------------------------------------------------\n"); - fprintf(stdout,"usage: %s [OPTIONS]\n\n", my_progname); - fprintf(stdout,"\ - -?, --help Display this help message and exit.\n\ - -D --database=... Database name to be used for test.\n\ - -h, --host=... Connect to host.\n\ - -p, --password[=...] Password to use when connecting to server.\n"); -#ifdef __WIN__ - fprintf(stdout,"\ - -W, --pipe Use named pipes to connect to server.\n"); -#endif - fprintf(stdout,"\ - -P, --port=... Port number to use for connection.\n\ - -S, --socket=... Socket file to use for connection.\n"); -#ifndef DONT_ALLOW_USER_CHANGE - fprintf(stdout,"\ - -u, --user=# User for login if not current user.\n"); -#endif - fprintf(stdout,"\ - -t, --count=... Execute the test count times.\n"); + client_test_print_version(); + fprintf(stdout,"Usage: %s [OPTIONS]\n\n", my_progname); + + my_print_help(client_test_long_options); + print_defaults("my", client_test_load_default_groups); + my_print_variables(client_test_long_options); + puts("***********************************************************************\n"); } @@ -5513,22 +5641,17 @@ get_one_option(int optid, const struct my_option *opt __attribute__((unused)), return 0; } -static const char *load_default_groups[]= { "client",0 }; - static void get_options(int argc, char **argv) { int ho_error; - load_defaults("my",load_default_groups,&argc,&argv); + load_defaults("my",client_test_load_default_groups,&argc,&argv); - if ((ho_error=handle_options(&argc,&argv, myctest_long_options, - get_one_option))) + if ((ho_error= handle_options(&argc,&argv, client_test_long_options, + get_one_option))) exit(ho_error); - /*free_defaults(argv);*/ if (tty_password) opt_password=get_tty_password(NullS); - if (!opt_count) - opt_count= 1; return; } @@ -5540,7 +5663,7 @@ static void print_test_output() { fprintf(stdout,"\n\n"); fprintf(stdout,"All '%d' tests were successful (in '%d' iterations)", - test_count-1, opt_count); + test_count-1, opt_count); fprintf(stdout,"\n Total execution time: %g SECS", total_time); if (opt_count > 1) fprintf(stdout," (Avg: %g SECS)", total_time/opt_count); @@ -5554,6 +5677,9 @@ static void print_test_output() int main(int argc, char **argv) { MY_INIT(argv[0]); + + load_defaults("my",client_test_load_default_groups,&argc,&argv); + defaults_argv= argv; get_options(argc,argv); client_connect(); /* connect to server */ @@ -5625,7 +5751,7 @@ int main(int argc, char **argv) test_prepare_resultset();/* prepare meta info test */ test_stmt_close(); /* mysql_stmt_close() test -- hangs */ test_prepare_field_result(); /* prepare meta info */ - test_multi_stmt(); /* multi stmt test -TODO*/ + test_multi_stmt(); /* multi stmt test */ test_multi_query(); /* test multi query execution */ test_store_result(); /* test the store_result */ test_store_result1(); /* test store result without buffers */ @@ -5640,13 +5766,16 @@ int main(int argc, char **argv) test_manual_sample(); /* sample in the manual */ test_pure_coverage(); /* keep pure coverage happy */ test_buffers(); /* misc buffer handling */ + test_ushort_bug(); /* test a simple conv bug from php */ end_time= time((time_t *)0); total_time+= difftime(end_time, start_time); + /* End of tests */ } client_disconnect(); /* disconnect from server */ + free_defaults(defaults_argv); print_test_output(); return(0); From e33d310bcb58273e2c515ab96d1e96cc91751f5c Mon Sep 17 00:00:00 2001 From: unknown Date: Wed, 5 Feb 2003 12:21:01 -0800 Subject: [PATCH 03/11] Fix stupid signed and unsigned conversion - When field and buffer types are different (Client receiving end) Added tests for singed and unsigned conversion (client_test.c) tests/client_test.c: Tests for singed and unsigned conversion libmysql/libmysql.c: Fix signed and unsigned conversion - When field and buffer types are different --- libmysql/libmysql.c | 38 ++++++---- tests/client_test.c | 180 ++++++++++++++++++++++++++++++++++++++++++-- 2 files changed, 197 insertions(+), 21 deletions(-) diff --git a/libmysql/libmysql.c b/libmysql/libmysql.c index 62a18282ea6..f456dcd37c4 100644 --- a/libmysql/libmysql.c +++ b/libmysql/libmysql.c @@ -163,11 +163,6 @@ void STDCALL mysql_thread_end() #define reset_sigpipe(mysql) #endif -#define map_to_size(A,L) {\ - char *tmp= (char *)&A;\ - memset(tmp+L,0,8-L);\ -} - static MYSQL* spawn_init(MYSQL* parent, const char* host, unsigned int port, const char* user, @@ -3967,6 +3962,7 @@ unsigned int alloc_stmt_fields(MYSQL_STMT *stmt) field->org_table= strdup_root(alloc,fields->org_table); field->name = strdup_root(alloc,fields->name); field->org_name = strdup_root(alloc,fields->org_name); + field->charsetnr= fields->charsetnr; field->length = fields->length; field->type = fields->type; field->flags = fields->flags; @@ -4871,31 +4867,38 @@ static void send_data_time(MYSQL_BIND *param, MYSQL_TIME ltime, /* Fetch data to buffers */ -static void fetch_results(MYSQL_BIND *param, uint field_type, uchar **row) +static void fetch_results(MYSQL_BIND *param, uint field_type, uchar **row, + my_bool field_is_unsigned) { ulong length; switch (field_type) { case MYSQL_TYPE_TINY: { - longlong value= (longlong) **row; - map_to_size(value,(length= 1)); - send_data_long(param,value); + char value= (char) **row; + longlong data= (field_is_unsigned) ? (longlong) (unsigned char) value: + (longlong) value; + send_data_long(param,data); + length= 1; break; } case MYSQL_TYPE_SHORT: case MYSQL_TYPE_YEAR: { - longlong value= (longlong)sint2korr(*row); - map_to_size(value,(length= 2)); - send_data_long(param, value); + short value= sint2korr(*row); + longlong data= (field_is_unsigned) ? (longlong) (unsigned short) value: + (longlong) value; + send_data_long(param,data); + length= 2; break; } case MYSQL_TYPE_LONG: { - longlong value= (longlong)sint4korr(*row); - map_to_size(value,(length= 4)); - send_data_long(param,value); + long value= sint4korr(*row); + longlong data= (field_is_unsigned) ? (longlong) (unsigned long) value: + (longlong) value; + send_data_long(param,data); + length= 4; break; } case MYSQL_TYPE_LONGLONG: @@ -5165,7 +5168,10 @@ static int stmt_fetch_row(MYSQL_STMT *stmt, uchar *row) if (field->type == bind->buffer_type) (*bind->fetch_result)(bind, &row); else - fetch_results(bind, field->type, &row); + { + my_bool field_is_unsigned= (field->flags & UNSIGNED_FLAG) ? 1: 0; + fetch_results(bind, field->type, &row, field_is_unsigned); + } } if (! ((bit<<=1) & 255)) { diff --git a/tests/client_test.c b/tests/client_test.c index c2d81729f52..0ba4b4e564c 100644 --- a/tests/client_test.c +++ b/tests/client_test.c @@ -166,7 +166,7 @@ static void client_connect() int rc; myheader_r("client_connect"); - fprintf(stdout, "\n Establishig a connection ..."); + fprintf(stdout, "\n Establishing a connection ..."); if (!(mysql = mysql_init(NULL))) { @@ -5529,10 +5529,10 @@ static void test_ushort_bug() rc = mysql_fetch(stmt); mystmt(stmt, rc); - fprintf(stdout,"\n ushort: %d (%ld)", short_value, s_length); - fprintf(stdout,"\n ulong : %ld (%ld)", long_value, l_length); - fprintf(stdout,"\n ulong : %lld (%ld)", longlong_value, ll_length); - fprintf(stdout,"\n ulong : %d (%ld)", tiny_value, t_length); + fprintf(stdout,"\n ushort : %d (%ld)", short_value, s_length); + fprintf(stdout,"\n ulong : %ld (%ld)", long_value, l_length); + fprintf(stdout,"\n longlong : %lld (%ld)", longlong_value, ll_length); + fprintf(stdout,"\n tinyint : %d (%ld)", tiny_value, t_length); myassert(short_value == 35999); myassert(s_length == 2); @@ -5552,6 +5552,174 @@ static void test_ushort_bug() mysql_stmt_close(stmt); } +/* + To test a misc smallint-signed conversion bug +*/ +static void test_sshort_bug() +{ + MYSQL_STMT *stmt; + MYSQL_BIND bind[4]; + short short_value; + long long_value; + ulong s_length, l_length, ll_length, t_length; + ulonglong longlong_value; + int rc; + uchar tiny_value; + + myheader("test_sshort_bug"); + + rc= mysql_query(mysql,"DROP TABLE IF EXISTS test_sshort"); + myquery(rc); + + rc= mysql_query(mysql,"CREATE TABLE test_sshort(a smallint signed, \ + b smallint signed, \ + c smallint unsigned, \ + d smallint unsigned)"); + myquery(rc); + + rc= mysql_query(mysql,"INSERT INTO test_sshort VALUES(-5999, -5999, 35999, 200)"); + myquery(rc); + + + stmt = mysql_prepare(mysql,"SELECT * FROM test_sshort",50); + mystmt_init(stmt); + + rc = mysql_execute(stmt); + mystmt(stmt, rc); + + bind[0].buffer_type= MYSQL_TYPE_SHORT; + bind[0].buffer= (char *)&short_value; + bind[0].is_null= 0; + bind[0].length= &s_length; + + bind[1].buffer_type= MYSQL_TYPE_LONG; + bind[1].buffer= (char *)&long_value; + bind[1].is_null= 0; + bind[1].length= &l_length; + + bind[2].buffer_type= MYSQL_TYPE_LONGLONG; + bind[2].buffer= (char *)&longlong_value; + bind[2].is_null= 0; + bind[2].length= &ll_length; + + bind[3].buffer_type= MYSQL_TYPE_TINY; + bind[3].buffer= (char *)&tiny_value; + bind[3].is_null= 0; + bind[3].length= &t_length; + + rc = mysql_bind_result(stmt, bind); + mystmt(stmt, rc); + + rc = mysql_fetch(stmt); + mystmt(stmt, rc); + + fprintf(stdout,"\n sshort : %d (%ld)", short_value, s_length); + fprintf(stdout,"\n slong : %ld (%ld)", long_value, l_length); + fprintf(stdout,"\n longlong : %lld (%ld)", longlong_value, ll_length); + fprintf(stdout,"\n tinyint : %d (%ld)", tiny_value, t_length); + + myassert(short_value == -5999); + myassert(s_length == 2); + + myassert(long_value == -5999); + myassert(l_length == 4); + + myassert(longlong_value == 35999); + myassert(ll_length == 8); + + myassert(tiny_value == 200); + myassert(t_length == 1); + + rc = mysql_fetch(stmt); + myassert(rc == MYSQL_NO_DATA); + + mysql_stmt_close(stmt); +} + +/* + To test a misc tinyint-signed conversion bug +*/ +static void test_stiny_bug() +{ + MYSQL_STMT *stmt; + MYSQL_BIND bind[4]; + short short_value; + long long_value; + ulong s_length, l_length, ll_length, t_length; + ulonglong longlong_value; + int rc; + uchar tiny_value; + + myheader("test_stiny_bug"); + + rc= mysql_query(mysql,"DROP TABLE IF EXISTS test_stiny"); + myquery(rc); + + rc= mysql_query(mysql,"CREATE TABLE test_stiny(a tinyint signed, \ + b tinyint signed, \ + c tinyint unsigned, \ + d tinyint unsigned)"); + myquery(rc); + + rc= mysql_query(mysql,"INSERT INTO test_stiny VALUES(-128, -127, 255, 0)"); + myquery(rc); + + + stmt = mysql_prepare(mysql,"SELECT * FROM test_stiny",50); + mystmt_init(stmt); + + rc = mysql_execute(stmt); + mystmt(stmt, rc); + + bind[0].buffer_type= MYSQL_TYPE_SHORT; + bind[0].buffer= (char *)&short_value; + bind[0].is_null= 0; + bind[0].length= &s_length; + + bind[1].buffer_type= MYSQL_TYPE_LONG; + bind[1].buffer= (char *)&long_value; + bind[1].is_null= 0; + bind[1].length= &l_length; + + bind[2].buffer_type= MYSQL_TYPE_LONGLONG; + bind[2].buffer= (char *)&longlong_value; + bind[2].is_null= 0; + bind[2].length= &ll_length; + + bind[3].buffer_type= MYSQL_TYPE_TINY; + bind[3].buffer= (char *)&tiny_value; + bind[3].is_null= 0; + bind[3].length= &t_length; + + rc = mysql_bind_result(stmt, bind); + mystmt(stmt, rc); + + rc = mysql_fetch(stmt); + mystmt(stmt, rc); + + fprintf(stdout,"\n sshort : %d (%ld)", short_value, s_length); + fprintf(stdout,"\n slong : %ld (%ld)", long_value, l_length); + fprintf(stdout,"\n longlong : %lld (%ld)", longlong_value, ll_length); + fprintf(stdout,"\n tinyint : %d (%ld)", tiny_value, t_length); + + myassert(short_value == -128); + myassert(s_length == 2); + + myassert(long_value == -127); + myassert(l_length == 4); + + myassert(longlong_value == 255); + myassert(ll_length == 8); + + myassert(tiny_value == 0); + myassert(t_length == 1); + + rc = mysql_fetch(stmt); + myassert(rc == MYSQL_NO_DATA); + + mysql_stmt_close(stmt); +} + /* Read and parse arguments and MySQL options from my.cnf */ @@ -5767,6 +5935,8 @@ int main(int argc, char **argv) test_pure_coverage(); /* keep pure coverage happy */ test_buffers(); /* misc buffer handling */ test_ushort_bug(); /* test a simple conv bug from php */ + test_sshort_bug(); /* test a simple conv bug from php */ + test_stiny_bug(); /* test a simple conv bug from php */ end_time= time((time_t *)0); total_time+= difftime(end_time, start_time); From f459327f3382cf7f1e5d1d2b8b356bb040394c46 Mon Sep 17 00:00:00 2001 From: unknown Date: Wed, 5 Feb 2003 22:29:42 -0800 Subject: [PATCH 04/11] Added all new changes (To be incorporated to main manual before the release) --- Docs/prepare.texi | 556 ++++++++++++++++++++++++++++++++++++---------- 1 file changed, 435 insertions(+), 121 deletions(-) diff --git a/Docs/prepare.texi b/Docs/prepare.texi index 7a526800213..0b515012980 100755 --- a/Docs/prepare.texi +++ b/Docs/prepare.texi @@ -117,6 +117,8 @@ * C Prepared statement datatypes:: * C Prepared statements function overview:: * C Prepared statement functions:: +* multiple queries:: +* date handling:: @end menu @node C Prepared statements, C Prepared statement datatypes, MySQL prepared statements, MySQL prepared statements @@ -160,8 +162,10 @@ Prepared statements mainly uses the following two @code{MYSQL_STMT} and @sp 1 @table @code -@tindex MYSQL C type +@tindex MYSQL_STMT C type + @item MYSQL_STMT + This structure represents a statement handle to prepared statements.It is used for all statement related functions. @@ -178,11 +182,14 @@ the system resources. @sp 1 @tindex MYSQL_BIND C type + @item MYSQL_BIND -This structure is used in order to bind parameter buffers inorder to -send the parameters data to @code{mysql_execute()} call; as well as to -bind row buffers to fetch the result set data using @code{mysql_fetch()}. -@end table + +This structure is used in order to bind parameter +buffers(@code{mysql_bind_param()}) inorder to the parameters data to +@code{mysql_execute()} call; as well as to bind row +buffers(@code{mysql_bind_result()}) to fetch the result set data using +@code{mysql_fetch()}. @sp 1 @@ -191,6 +198,7 @@ The @code{MYSQL_BIND} structure contains the members listed here: @table @code + @item enum enum_field_types buffer_type [input] The type of the buffer. The @code{type} value must be one of the following: @@ -202,6 +210,10 @@ The type of the buffer. The @code{type} value must be one of the following: @item @code{MYSQL_TYPE_LONGLONG} @item @code{MYSQL_TYPE_FLOAT} @item @code{MYSQL_TYPE_DOUBLE} +@item @code{MYSQL_TYPE_TIME} +@item @code{MYSQL_TYPE_DATE} +@item @code{MYSQL_TYPE_DATETIME} +@item @code{MYSQL_TYPE_TIMESTAMP} @item @code{MYSQL_TYPE_STRING} @item @code{MYSQL_TYPE_VAR_STRING} @item @code{MYSQL_TYPE_TINY_BLOB} @@ -218,49 +230,62 @@ data when the structure is used for result set bind. @sp 1 +@item unsigned long buffer_length [input] +Length of the @code{*buffer} in bytes. For character and binary C data, +the buffer_length specifies the length of the @code{*buffer} to be used +as a parameter data in case if it is used with @code{mysql_bind_param()} +or to return that many bytes when fetching results when this is used +with @code{mysql_bind_result()}. + + @item long *length [input/output] Pointer to the buffer for the parameter's length. When the structure is used as a input parameter data binding, then this argument points to a -buffer that, when @code{mysql_execute()} is called, contains one of the -following: - -@itemize @bullet -@item -The length of the parameter value stored in *buffer. This is ignored -except for character or binary C data. -@item -MYSQL_NULL_DATA. The parameter value is NULL. -@item -MYSQL_LONG_DATA. The parameter value is a long data and is supplied in -chunks through @code{mysql_send_long_data()}. -@end itemize +buffer that, when @code{mysql_execute()} is called, contains the length +of the parameter value stored in *buffer. This is ignored except for +character or binary C data. If the length is a null pointer, then the protocol assumes that all -input parameter values are non-NULL and that character and binary data -are null terminated. - +character and binary data are null terminated. When this structure is used in output binding, then @code{mysql_fetch()} -return the following values in the length buffer: +return the the length of the data that is returned. -@itemize @bullet -@item -The length of the data that is returned -@item -MYSQL_NULL_DATA, indicating the data returned is a NULL data. -@end itemize +@sp 1 +@item bool *is_null [input/output] +Indicates if the parameter data is NULL or fetched data is NULL. +@end table -@c @item bool is_null [input] -@c To indicate the parameter data is NULL. This is same as supplying -@c MYSQL_NULL_DATA, -1 as the length in length pointer. +@sp 1 +@tindex MySQL C type -@c @item bool is_long_data [input] -@c To indicate the parameter data is a long data, and the data will be -@c supplied in chunks through @code{mysql_send_long_data()}.This is also -@c same as supplying MYSQL_LONG_DATA, -2 as the length in length pointer. -@c @end table +@item MYSQL_TIME + +This structure is used to send and receive DATE, TIME and +TIMESTAMP data directly to/from server. + +@sp 1 + +@noindent +The @code{MYSQL_TIME} structure contains the members listed here: + +@multitable @columnfractions .20 .20 .68 + +@item @strong{Member} @tab @strong{Type} @tab @strong{Description} + +@item @code{year} @tab unsigned int @tab Year. +@item @code{month} @tab unsigned int @tab Month of the year. +@item @code{day} @tab unsigned int @tab Day of the month. +@item @code{hour} @tab unsigned int @tab Hour of the day(TIME). +@item @code{minute} @tab unsigned int @tab Minute of the hour. +@item @code{second} @tab unsigned int @tab Second of the minute. +@item @code{neg} @tab my_bool @tab A boolean flag to +indicate if the time is negative. +@item @code{second_part} @tab unsigned long @tab Fraction part of the +second(not yet used) +@end multitable @end table @@ -289,7 +314,10 @@ are described in greater detail in the later section. @item @strong{mysql_stmt_affected_rows()} @tab Returns the number of rows changes/deleted/inserted by the last UPDATE,DELETE,or INSERT query -@item @strong{mysql_bind_result()} @tab Binds application data buffers to columns in the resultset. +@item @strong{mysql_bind_result()} @tab Binds application data buffers +to columns in the resultset. + +@item @strong{mysql_stmt_store_result()} @tab Retrieves the complete result set to the client @item @strong{mysql_fetch()} @tab Fetches the next rowset of data from the result set and returns data for all bound columns. @@ -315,6 +343,7 @@ are described in greater detail in the later section. @end multitable @sp 1 + Call @code{mysql_prepare()} to prepare and initialize the statement handle, then call @code{mysql_bind_param()} to supply the parameters data, and then call @code{mysql_execute()} to execute the query. You can @@ -421,7 +450,7 @@ You can get the statement error code and message using @code{mysql_stmt_errno()} and @code{mysql_stmt_error()} respectively. -@node C Prepared statement functions, , C Prepared statements function overview, MySQL prepared statements +@node C Prepared statement functions, multiple queries, C Prepared statements function overview, MySQL prepared statements @subsection C Prepared Statement Function Descriptions You need to use the following functions when you want to prepare and @@ -429,21 +458,24 @@ execute the queries. @menu -* mysql_prepare:: -* mysql_param_count:: -* mysql_prepare_result:: -* mysql_bind_param:: -* mysql_execute:: -* mysql_stmt_affected_rows:: -* mysql_bind_result:: -* mysql_fetch:: -* mysql_send_long_data:: -* mysql_stmt_close:: -* mysql_stmt_errno:: -* mysql_stmt_error:: -* mysql_commit:: -* mysql_rollback:: -* mysql_autocommit:: +* mysql_prepare:: @code{mysql_prepare()} +* mysql_param_count:: @code{mysql_param_count()} +* mysql_prepare_result:: @code{mysql_prepare_result()} +* mysql_bind_param:: @code{mysql_bind_param()} +* mysql_execute:: @code{mysql_execute()} +* mysql_stmt_affected_rows:: @code{mysql_stmt_affected_rows()} +* mysql_bind_result:: @code{mysql_bind_result()} +* mysql_stmt_store_result:: @code{mysql_stmt_store_result()} +* mysql_fetch:: @code{mysql_fetch()} +* mysql_send_long_data:: @code{mysql_send_long_data()} +* mysql_stmt_close:: @code{mysql_stmt_close()} +* mysql_stmt_errno:: @code{mysql_stmt_errno()} +* mysql_stmt_error:: @code{mysql_stmt_error()} +* mysql_commit:: @code{mysql_commit()} +* mysql_rollback:: @code{mysql_rollback()} +* mysql_autocommit:: @code{mysql_autocommit()} +* mysql_more_results:: @code{mysql_more_results()} +* mysql_next_result:: @code{mysql_next_result()} @end menu @node mysql_prepare, mysql_param_count, C Prepared statement functions, C Prepared statement functions @@ -488,6 +520,18 @@ occured. @subsubheading Errors +@item CR_COMMANDS_OUT_OF_SYNC +Commands were executed in an improper order +@item CR_OUT_OF_MEMORY +Out of memory +@item CR_SERVER_GONE_ERROR +The MySQL server has gone away +@item CR_SERVER_LOST +The connection to the server was lost during the query +@item CR_UNKNOWN_ERROR +An unkown error occured +@end table + If the prepare is not successful, i.e. when @code{mysql_prepare()} returned a NULL statement, errors can be obtained by calling @code{mysql_error()}. @@ -573,6 +617,11 @@ the prepared query. @subsubheading Errors +@item CR_OUT_OF_MEMOR +Out of memory +@item CR_UNKNOWN_ERROR +An unknown error occured + None @@ -611,6 +660,14 @@ MYSQL_TYPE_LONGLONG MYSQL_TYPE_FLOAT @item MYSQL_TYPE_DOUBLE +@item +MYSQL_TYPE_TIME +@item +MYSQL_TYPE_DATE +@item +MYSQL_TYPE_DATETIME +@item +MYSQL_TYPE_TIMESTAMP @item MYSQL_TYPE_STRING @item @@ -639,6 +696,10 @@ buffer type is non string or binary @item CR_UNSUPPORTED_PARAM_TYPE The conversion is not supported, possibly the buffer_type is illegal or its not from the above list of supported types. +@item CR_OUT_OF_MEMOR +Out of memory +@item CR_UNKNOWN_ERROR +An unknown error occured @end table @subsubheading Example @@ -677,12 +738,10 @@ how to fetch the statement binary data, refer to @ref{mysql_fetch}. @code{mysql_execute()} returns the following return values: @multitable @columnfractions .30 .65 -@item @strong{Return Value} @tab @strong{Description} -@item MYSQL_SUCCESS, 0 @tab Successful -@item MYSQL_STATUS_ERROR, 1 @tab Error occured. Error code and +@item @strong{Return Value} @tab @strong{Description} +@item 0 @tab Successful +@item 1 @tab Error occured. Error code and message can be obtained by calling @code{mysql_stmt_errno()} and @code{mysql_stmt_error()}. -@item MYSQL_NEED_DATA, 99 @tab One of the parameter buffer is -indicating the data suppy in chunks, and the supply is not yet complete. @end multitable @@ -693,10 +752,16 @@ indicating the data suppy in chunks, and the supply is not yet complete. No query prepared prior to execution @item CR_ALL_PARAMS_NOT_BOUND Not all parameters data is supplied -@item CR_SERVER_GONE_ERROR -The MySQL server has gone away -@item CR_UNKNOWN_ERROR -An unkown error occured +@item CR_COMMANDS_OUT_OF_SYNC +Commands were executed in an improper order. +@item CR_OUT_OF_MEMORY +Out of memory. +@item CR_SERVER_GONE_ERROR +The MySQL server has gone away. +@item CR_SERVER_LOST +The connection to the server was lost during the query. +@item CR_UNKNOWN_ERROR +An unknown error occurred. @end table @@ -714,7 +779,9 @@ ulonglong affected_rows; long length; unsigned int param_count; int int_data; +short small_data; char str_data[50], query[255]; +my_bool is_null; /* Set autocommit mode to true */ mysql_autocommit(mysql, 1); @@ -735,8 +802,8 @@ char str_data[50], query[255]; @} /* Prepare a insert query with 3 parameters */ - strcpy(query, "INSERT INTO test_table(col1,col2,col3) values(?,?,?)"); - if(!(stmt = mysql_prepare(mysql,query,strlen(query)))) + strmov(query, "INSERT INTO test_table(col1,col2,col3) values(?,?,?)"); + if(!(stmt = mysql_prepare(mysql, query, strlen(query)))) @{ fprintf(stderr, "\n prepare, insert failed"); fprintf(stderr, "\n %s", mysql_error(mysql)); @@ -757,19 +824,25 @@ char str_data[50], query[255]; /* Bind the data for the parameters */ /* INTEGER PART */ - memset(bind,0,sizeof(bind)); bind[0].buffer_type= MYSQL_TYPE_LONG; - bind[0].buffer= (void *)&int_data; - + bind[0].buffer= (char *)&int_data; + bind[0].is_null= 0; + bind[0].length= 0; + /* STRING PART */ bind[1].buffer_type= MYSQL_TYPE_VAR_STRING; - bind[1].buffer= (void *)str_data; + bind[1].buffer= (char *)str_data; bind[1].buffer_length= sizeof(str_data); - + bind[1].is_null= 0; + bind[1].length= 0; + /* SMALLINT PART */ bind[2].buffer_type= MYSQL_TYPE_SHORT; - bind[2].buffer= (void *)&small_data; - bind[2].length= (long *)&length; + bind[2].buffer= (char *)&small_data; + bind[2].is_null= &is_null; + bind[2].length= 0; + is_null= 0; + /* Bind the buffers */ if (mysql_bind_param(stmt, bind)) @@ -782,8 +855,9 @@ char str_data[50], query[255]; /* Specify the data */ int_data= 10; /* integer */ strcpy(str_data,"MySQL"); /* string */ + /* INSERT SMALLINT data as NULL */ - length= MYSQL_NULL_DATA; + is_null= 1; /* Execute the insert statement - 1*/ if (mysql_execute(stmt)) @@ -808,8 +882,8 @@ char str_data[50], query[255]; int_data= 1000; strcpy(str_data,"The most popular open source database"); small_data= 1000; /* smallint */ - length= 0; - + is_null= 0; /* reset NULL */ + /* Execute the insert statement - 2*/ if (mysql_execute(stmt)) @{ @@ -843,7 +917,7 @@ char str_data[50], query[255]; fprintf(stderr, "\n %s", mysql_error(mysql)); exit(0); @} - fprintf(stdout, "Success, MySQL prepared statements are working great !!!"); + fprintf(stdout, "Success, MySQL prepared statements are working!!!"); @end example @@ -885,7 +959,7 @@ from @ref{mysql_execute,mysql_execute()}. -@node mysql_bind_result, mysql_fetch, mysql_stmt_affected_rows, C Prepared statement functions +@node mysql_bind_result, mysql_stmt_store_result, mysql_stmt_affected_rows, C Prepared statement functions @subsubsection @code{mysql_bind_result()} @findex @code{mysql_bind_result()} @@ -894,7 +968,7 @@ from @ref{mysql_execute,mysql_execute()}. @subsubheading Description -@code{mysql_bind_result()} is ised to associate, or bind, columns in the +@code{mysql_bind_result()} is used to associate, or bind, columns in the resultset to data buffers and length buffers. When @code{mysql_fetch()} is called to fetch data, the MySQL client protocol returns the data for the bound columns in the specified buffers. @@ -937,6 +1011,14 @@ MYSQL_TYPE_LONGLONG MYSQL_TYPE_FLOAT @item MYSQL_TYPE_DOUBLE +@item +MYSQL_TYPE_TIME +@item +MYSQL_TYPE_DATE +@item +MYSQL_TYPE_DATETIME +@item +MYSQL_TYPE_TIMESTAMP @item MYSQL_TYPE_STRING @item @@ -956,12 +1038,17 @@ MYSQL_TYPE_LONG_BLOB Zero if the bind was successful. Non-zero if an error occured. @subsubheading Errors + @table @code @item CR_NO_PREPARE_STMT No prepared statement exists @item CR_UNSUPPORTED_PARAM_TYPE The conversion is not supported, possibly the buffer_type is illegal or its not from the list of supported types. +@item CR_OUT_OF_MEMOR +Out of memory +@item CR_UNKNOWN_ERROR +An unknown error occured @end table @subsubheading Example @@ -971,7 +1058,53 @@ For the usage of @code{mysql_bind_result()} refer to the Example from -@node mysql_fetch, mysql_send_long_data, mysql_bind_result, C Prepared statement functions + +@node mysql_stmt_store_result, mysql_fetch, mysql_bind_result, C Prepared statement functions +@subsubsection @code{mysql_stmt_store_result()} + +@findex code{mysql_stmt_store_result()} + +@code{int mysql_stmt_store_result(MYSQL_STMT *stmt)} + +@subsubheading Description + +You must call @code{mysql_stmt_store_result()} for every query that +successfully retrieves +data(@code{SELECT},@code{SHOW},@code{DESCRIBE},@code{EXPLAIN}), and only +if you want to buffer the complete result set by the client, so that the +subsequent @code{mysql_fetch()} call returns buffered data. + +@sp 1 + +You don't have to call @code{mysql_stmt_store_result()} for other +queries, but it will not harm or cause any notable performance in all +cases.You can detect if the query didn't have a result set by checking +if @code{mysql_prepare_result()} returns 0. For more information refer +to @ref{mysql_prepare_result}. + +@subsubheading Return Values + +@code{Zero} if the results are buffered successfully or @code{Non Zero} in case of an error. + + +@subsubheading Errors + +@table @code +@item CR_COMMANDS_OUT_OF_SYNC +Commands were executed in an improper order. +@item CR_OUT_OF_MEMORY +Out of memory. +@item CR_SERVER_GONE_ERROR +The MySQL server has gone away. +@item CR_SERVER_LOST +The connection to the server was lost during the query. +@item CR_UNKNOWN_ERROR +An unknown error occurred. +@end table + + + +@node mysql_fetch, mysql_send_long_data, mysql_stmt_store_result, C Prepared statement functions @subsubsection @code{mysql_fetch()} @findex code{mysql_fetch()} @@ -982,7 +1115,9 @@ For the usage of @code{mysql_bind_result()} refer to the Example from @code{mysql_fetch()} returns the next rowset in the result set. It can be called only while the result set exists i.e. after a call to -@code{mysql_execute()} that creates a result set. +@code{mysql_execute()} that creates a result set or after +@code{mysql_stmt_store_result()}, which is called after +@code{mysql_execute()} to buffer the entire resultset. @sp 1 @@ -994,11 +1129,12 @@ set and the lengths are returned to the length pointer. Note that, all columns must be bound by the application. @sp 1 -If the data fetched is a NULL data, then the length buffer will have a -value of @strong{MYSQL_NULL_DATA}, -1, else it will have the length of -the data being fetched based on the buffer type specified by the -application. All numeric, float and double types have the -fixed length(in bytes) as listed below: +If the data fetched is a NULL data, then the @code{is_null} value from +@code{MYSQL_BIND} contains TRUE, 1, else the data and its length is +returned to @code{*buffer} and @code{*length} variables based on the +buffer type specified by the application. All numeric, float and double +types have the fixed length(in bytes) as listed below: + @multitable @columnfractions .10 .30 @item @strong{Type} @tab @strong{Length} @@ -1008,6 +1144,10 @@ fixed length(in bytes) as listed below: @item MYSQL_TYPE_FLOAT @tab 4 @item MYSQL_TYPE_LONGLONG @tab 8 @item MYSQL_TYPE_DOUBLE @tab 8 +@item MYSQL_TYPE_TIME @tab sizeof(MYSQL_TIME) +@item MYSQL_TYPE_DATE @tab sizeof(MYSQL_TIME) +@item MYSQL_TYPE_DATETIME @tab sizeof(MYSQL_TIME) +@item MYSQL_TYPE_TIMESTAMP @tab sizeof(MYSQL_TIME) @item MYSQL_TYPE_STRING @tab data length @item MYSQL_TYPE_VAR_STRING @tab data_length @item MYSQL_TYPE_BLOB @tab data_length @@ -1023,21 +1163,31 @@ where @code{*data_length} is nothing but the 'Actual length of the data'. @multitable @columnfractions .30 .65 @item @strong{Return Value} @tab @strong{Description} -@item MYSQL_SUCCESS, 0 @tab Successful, the data has been +@item 0 @tab Successful, the data has been fetched to application data buffers. -@item MYSQL_STATUS_ERROR, 1 @tab Error occured. Error code and +@item 1 @tab Error occured. Error code and message can be obtained by calling @code{mysql_stmt_errno()} and @code{mysql_stmt_error()}. -@item MYSQL_NO_DATA, 100 @tab No more rows/data exists +@item 100, MYSQL_NO_DATA @tab No more rows/data exists @end multitable @subsubheading Errors @table @code +@item CR_COMMANDS_OUT_OF_SYNC +Commands were executed in an improper order. +@item CR_OUT_OF_MEMORY +Out of memory. +@item CR_SERVER_GONE_ERROR +The MySQL server has gone away. +@item CR_SERVER_LOST +The connection to the server was lost during the query. +@item CR_UNKNOWN_ERROR +An unknown error occurred. @item CR_UNSUPPORTED_PARAM_TYPE -If the field type is DATE,DATETIME,TIME,or TIMESTAMP; and the -application buffer type is non string based. +If the buffer type is MYSQL_TYPE_DATE,DATETIME,TIME,or TIMESTAMP; and if +the field type is not DATE, TIME, DATETIME or TIMESTAMP. @item -All other un-supported conversions are returned from +All other unsupported conversion errors are returned from @code{mysql_bind_result()}. @end table @@ -1054,6 +1204,7 @@ MYSQL_RES *result; int int_data; long int_length, str_length; char str_data[50]; +my_bool is_null[2]; query= "SELECT col1, col2 FROM test_table WHERE col1= 10)"); if (!(stmt= mysql_prepare(&mysql, query, strlen(query))) @@ -1082,19 +1233,20 @@ char str_data[50]; /* Execute the SELECT query */ if (mysql_execute(stmt)) @{ - fprintf(stderr, "\n execute didn't retuned expected return code, MYSQL_NEED_DATA"); + fprintf(stderr, "\n execute failed"); + fprintf(stderr, "\n %s", mysql_stmt_error(stmt)); exit(0); @} /* Bind the result data buffers */ - bzero(bind, 0, sizeof(bind)); - bind[0].buffer_type= MYSQL_TYPE_LONG; - bind[0].buffer= (void *)&int_data; + bind[0].buffer= (char *)&int_data; + bind[0].is_null= &is_null[0]; bind[0].length= &int_length; bind[1].buffer_type= MYSQL_TYPE_VAR_STRING; bind[1].buffer= (void *)str_data; + bind[1].is_null= &is_null[1]; bind[1].length= &str_length; if (mysql_bind_result(stmt, bind)) @@ -1111,9 +1263,17 @@ char str_data[50]; fprintf(stderr, "\n %s", mysql_stmt_error(stmt)); exit(0); @} + + if (is_null[0]) + fprintf(stdout, "\n Col1 data is NULL"); + else + fprintf(stdout, "\n Col1: %d, length: %ld", int_data, int_length); - fprintf(stdout, "\n int_data: %d, length: %ld", int_data, int_length); - fprintf(stdout, "\n str_data: %s, length: %ld", str_data, str_length); + if (is_null[1]) + fprintf(stdout, "\n Col2 data is NULL"); + else + fprintf(stdout, "\n Col2: %s, length: %ld", str_data, str_length); + /* call mysql_fetch again */ if (mysql_fetch(stmt) |= MYSQL_NO_DATA) @@ -1122,7 +1282,7 @@ char str_data[50]; exit(0); @} - /* Free the prepare result */ + /* Free the prepare result meta information */ mysql_free_result(result); /* Free the statement handle */ @@ -1144,7 +1304,7 @@ char str_data[50]; @findex @code{mysql_send_long_data()}. @code{int mysql_send_long_data(MYSQL_STMT *stmt, unsigned int -parameter_number, const char *data, ulong length, my_bool is_last_data)} +parameter_number, const char *data, ulong length)} @subsubheading Description @@ -1156,13 +1316,7 @@ binary data type. @sp 1 The @code{data} is a pointer to buffer containing the actual data for the parameter represendted by @code{parameter_number}. The @code{length} -indicates the amount of data to be sent in bytes, and @code{is_last_data} is a -boolean flag to indicate the end of the data. If it is != 0, then the -current call will be the end of the data, else it waits for the -application to send all data. If the application doesn't ended the data -supply from @code{mysql_send_long_data()}, then the -@code{mysql_execute()} will return @strong{MYSQL_NEED_DATA}. - +indicates the amount of data to be sent in bytes. @subsubheading Return Values @@ -1176,10 +1330,14 @@ occured. @table @code @item CR_INVALID_PARAMETER_NO Invalid parameter number +@item CR_COMMANDS_OUT_OF_SYNC +Commands were executed in an improper order. @item CR_SERVER_GONE_ERROR The MySQL server has gone away +@item CR_OUT_OF_MEMOR +Out of memory @item CR_UNKNOWN_ERROR -An unkown error occured +An unknown error occured @end table @subsubheading Example @@ -1200,9 +1358,7 @@ long length; memset(bind, 0, sizeof(bind)); bind[0].buffer_type= MYSQL_TYPE_STRING; bind[0].length= &length; - - /* Indicate that the data supply is in CHUNKS */ - length= MYSQL_LONG_DATA; + bind[0].is_null= 0; /* Bind the buffers */ if (mysql_bind_param(stmt, bind)) @@ -1212,22 +1368,16 @@ long length; exit(0); @} - /* Execute the insert statement - It should return MYSQL_NEED_DATA */ - if (mysql_execute(stmt) != MYSQL_NEED_DATA) - @{ - fprintf(stderr, "\n execute didn't retuned expected return code, MYSQL_NEED_DATA"); - exit(0); - @} - /* Supply data in chunks to server */ - if (!mysql_send_long_data(stmt,1,"MySQL",5,0)) + if (!mysql_send_long_data(stmt,1,"MySQL",5)) @{ fprintf(stderr, "\n send_long_data failed"); fprintf(stderr, "\n %s", mysql_stmt_error(stmt)); exit(0); @} - /* Supply the last piece of data */ - if (mysql_send_long_data(stmt,1," - The most popular open source database",40,1)) + + /* Supply the next piece of data */ + if (mysql_send_long_data(stmt,1," - The most popular open source database",40)) @{ fprintf(stderr, "\n send_long_data failed"); fprintf(stderr, "\n %s", mysql_stmt_error(stmt)); @@ -1258,7 +1408,10 @@ long length; @subsubheading Description Closes the prepared statement. @code{mysql_stmt_close()} also -deallocates the statement handle pointed to by @code{stmt}. +deallocates the statement handle pointed to by @code{stmt}. + +If the current query results are pending or un-read; this cancels the +query results; so that next call can be executed. @subsubheading Return Values @@ -1398,7 +1551,7 @@ None. -@node mysql_autocommit, , mysql_rollback, C Prepared statement functions +@node mysql_autocommit, mysql_more_results, mysql_rollback, C Prepared statement functions @subsubsection @code{mysql_autocommit()} @@ -1418,5 +1571,166 @@ Zero if successful. Non-zero if an error occured @subsubheading Errors None. + + +@node mysql_more_results, mysql_next_result, mysql_autocommit, C Prepared statement functions +@subsubsection @code{mysql_more_results()} + + +@findex @code{mysql_more_results()}. + +@code{my_bool mysql_more_results(MYSQL *mysql)} + +@subsubheading Description + +Returns true if more results exists from the currently executed query, +and the application must call @code{mysql_next_result()} to fetch the +results. + + +@subsubheading Return Values + +@code{TRUE} if more results exists. @code{FALSE} if no more results exists. + +@subsubheading Errors + +None. + + +@node mysql_next_result, , mysql_more_results, C Prepared statement functions +@subsubsection @code{mysql_next_result()} + + +@findex @code{mysql_next_result()}. + +@code{int mysql_next_result(MYSQL *mysql)} + +@subsubheading Description + +If more query results exists, then @code{mysql_next_result()} reads the +next query results and returns the status back to application. + +@subsubheading Return Values + +Zero if successful. Non-zero if an error occured + +@subsubheading Errors + +None. + + + +@node multiple queries, date handling, C Prepared statement functions, MySQL prepared statements +@subsection Handling multiple query executions + + +From version 4.1 and above, MySQL supports the multi query execution +using the single command. In order to do this, you must set the client flag +@code{CLIENT_MULTI_QUERIES} option during the connection. + +@sp 1 + +By default @code{mysql_query()} or @code{mysql_real_query()} returns +only the first query status and the subsequent queries status can +be processed using @code{mysql_more_results()} and +@code{mysql_next_result()}. + + +@example + + /* Connect to server with option CLIENT_MULTI_QUERIES */ + mysql_real_query(..., CLIENT_MULTI_QUERIES); + + /* Now execute multiple queries */ + mysql_query(mysql,"DROP TABLE IF EXISTS test_table;\ + CREATE TABLE test_table(id int);\ + INSERT INTO test_table VALUES(10);\ + UPDATE test_table SET id=20 WHERE id=10;\ + SELECT * FROM test_table;\ + DROP TABLE test_table"; + while (mysql_more_results(mysql)) + { + /* Process all results */ + mysql_next_result(mysql); + ... + printf("total affected rows: %lld", mysql_affected_rows(mysql)); + ... + if ((result= mysql_store_result(mysql)) + { + /* Returned a result set, process it */ + } + } + +@end example + + + +@node date handling, , multiple queries, MySQL prepared statements +@subsection Handling DATE, TIME and TIMESTAMP + +Using the new binary protocol from MySQL 4.1 and above, one can send and +receive the DATE, TIME and TIMESTAMP data using the @code{MYSQL_TIME} +structure. + +@code{MYSQL_TIME} structure consites of the following members: + +@itemize @bullet +@item year +@item month +@item day +@item hour +@item minute +@item second +@item second_part +@end itemize + + +In order to send the data, one must use the prepared statements through +@code{mysql_prepare()} and @code{mysql_execute()}; and must bind the +parameter using type as @code{MYSQL_TYPE_DATE} inorder to process date +value, @code{MYSQL_TYPE_TIME} for time and @code{MYSQL_TYPE_DATETIME} or +@code{MYSQL_TYPE_TIMESTAMP} for datetime/timestamp using +@code{mysql_bind_param()} when sending and @code{mysql_bind_results()} +while receiving the data. + +@sp 1 +Here is a simple example; which inserts the DATE, TIME and TIMESTAMP data. + +@example + +MYSQL_TIME ts; +MYSQL_BIND bind[3]; +MYSQL_STMT *stmt; + + strmov(query, "INSERT INTO test_table(date_field, time_field, + timestamp_field) VALUES(?,?,?"); + + stmt= mysql_prepare(mysql, query, strlen(query))); + + /* setup input buffers for all 3 parameters */ + bind[0].buffer_type= MYSQL_TYPE_DATE; + bind[0].buffer= (char *)&ts; + bind[0].is_null= 0; + bind[0].length= 0; + .. + bind[1]= bind[2]= bind[0]; + .. + + mysql_bind_param(stmt, bind); + + /* supply the data to be sent is the ts structure */ + ts.year= 2002; + ts.month= 02; + ts.day= 03; + + ts.hour= 10; + ts.minute= 45; + ts.second= 20; + + mysql_execute(stmt); + .. + +@end example + @bye From dfb188898487e2407910b5e84bb4ef2de0ecf218 Mon Sep 17 00:00:00 2001 From: unknown Date: Thu, 6 Feb 2003 14:47:56 -0800 Subject: [PATCH 05/11] Fix compilation errors reported by Lenz on misc platforms --- libmysql/libmysql.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/libmysql/libmysql.c b/libmysql/libmysql.c index f456dcd37c4..bb40d757166 100644 --- a/libmysql/libmysql.c +++ b/libmysql/libmysql.c @@ -2038,7 +2038,7 @@ Try also with PIPE or TCP/IP } sock_addr.sin_port = (ushort) htons((ushort) port); if (my_connect(sock,(struct sockaddr *) &sock_addr, sizeof(sock_addr), - mysql->options.connect_timeout) <0) + mysql->options.connect_timeout)) { DBUG_PRINT("error",("Got error %d on connect to '%s'",socket_errno,host)); net->last_errno= CR_CONN_HOST_ERROR; @@ -4727,13 +4727,13 @@ static void send_data_double(MYSQL_BIND *param, double value) *buffer= (uchar)value; break; case MYSQL_TYPE_SHORT: - int2store(buffer, value); + int2store(buffer, (short)value); break; case MYSQL_TYPE_LONG: - int4store(buffer, value); + int4store(buffer, (long)value); break; case MYSQL_TYPE_LONGLONG: - int8store(buffer, value); + int8store(buffer, (longlong)value); break; case MYSQL_TYPE_FLOAT: { From 10b7dea8461d4549adec3be1625416e6a4d20cda Mon Sep 17 00:00:00 2001 From: unknown Date: Tue, 11 Feb 2003 15:39:14 +0400 Subject: [PATCH 06/11] For more OpenGIS compatibility, these symbols are now synomims to GEOMETRY type: POINT, LINESTRING, POLYGON, MULTIPOINT, MULTIPOLYGON, MULTILINESTRING --- sql/lex.h | 12 ++++++------ sql/sql_yacc.yy | 22 ++++++++++++++++++++++ 2 files changed, 28 insertions(+), 6 deletions(-) diff --git a/sql/lex.h b/sql/lex.h index b17d3313c3f..135721a563c 100644 --- a/sql/lex.h +++ b/sql/lex.h @@ -222,6 +222,7 @@ static SYMBOL symbols[] = { { "LEVEL", SYM(LEVEL_SYM),0,0}, { "LIKE", SYM(LIKE),0,0}, { "LINES", SYM(LINES),0,0}, + { "LINESTRING", SYM(LINESTRING),0,0}, { "LIMIT", SYM(LIMIT),0,0}, { "LOAD", SYM(LOAD),0,0}, { "LOCAL", SYM(LOCAL_SYM),0,0}, @@ -261,6 +262,9 @@ static SYMBOL symbols[] = { { "MODE", SYM(MODE_SYM),0,0}, { "MODIFY", SYM(MODIFY_SYM),0,0}, { "MONTH", SYM(MONTH_SYM),0,0}, + { "MULTILINESTRING", SYM(MULTILINESTRING),0,0}, + { "MULTIPOINT", SYM(MULTIPOINT),0,0}, + { "MULTIPOLYGON", SYM(MULTIPOLYGON),0,0}, { "MRG_MYISAM", SYM(MERGE_SYM),0,0}, { "MYISAM", SYM(MYISAM_SYM),0,0}, { "NATURAL", SYM(NATURAL),0,0}, @@ -286,6 +290,8 @@ static SYMBOL symbols[] = { { "PACK_KEYS", SYM(PACK_KEYS_SYM),0,0}, { "PARTIAL", SYM(PARTIAL),0,0}, { "PASSWORD", SYM(PASSWORD),0,0}, + { "POINT", SYM(POINT),0,0}, + { "POLYGON", SYM(POLYGON),0,0}, { "PURGE", SYM(PURGE),0,0}, { "PRECISION", SYM(PRECISION),0,0}, { "PREV", SYM(PREV_SYM),0,0}, @@ -503,7 +509,6 @@ static SYMBOL sql_functions[] = { { "LENGTH", SYM(FUNC_ARG1),0,CREATE_FUNC(create_func_length)}, { "LN", SYM(FUNC_ARG1),0,CREATE_FUNC(create_func_ln)}, { "LINEFROMTEXT", SYM(LINEFROMTEXT),0,0}, - { "LINESTRING", SYM(LINESTRING),0,0}, { "LOAD_FILE", SYM(FUNC_ARG1),0,CREATE_FUNC(create_load_file)}, { "LOCATE", SYM(LOCATE),0,0}, { "LOG", SYM(LOG_SYM),0,0}, @@ -522,9 +527,6 @@ static SYMBOL sql_functions[] = { { "MLINEFROMTEXT", SYM(MLINEFROMTEXT),0,0}, { "MPOINTFROMTEXT", SYM(MPOINTFROMTEXT),0,0}, { "MPOLYFROMTEXT", SYM(MPOLYFROMTEXT),0,0}, - { "MULTILINESTRING", SYM(MULTILINESTRING),0,0}, - { "MULTIPOINT", SYM(MULTIPOINT),0,0}, - { "MULTIPOLYGON", SYM(MULTIPOLYGON),0,0}, { "MONTHNAME", SYM(FUNC_ARG1),0,CREATE_FUNC(create_func_monthname)}, { "NOW", SYM(NOW_SYM),0,0}, { "NULLIF", SYM(FUNC_ARG2),0,CREATE_FUNC(create_func_nullif)}, @@ -539,11 +541,9 @@ static SYMBOL sql_functions[] = { { "PERIOD_ADD", SYM(FUNC_ARG2),0,CREATE_FUNC(create_func_period_add)}, { "PERIOD_DIFF", SYM(FUNC_ARG2),0,CREATE_FUNC(create_func_period_diff)}, { "PI", SYM(FUNC_ARG0),0,CREATE_FUNC(create_func_pi)}, - { "POINT", SYM(FUNC_ARG2),0,CREATE_FUNC(create_func_point)}, { "POINTFROMTEXT", SYM(POINTFROMTEXT),0,0}, { "POINTN", SYM(FUNC_ARG2),0,CREATE_FUNC(create_func_pointn)}, { "POLYFROMTEXT", SYM(POLYFROMTEXT),0,0}, - { "POLYGON", SYM(POLYGON),0,0}, { "POSITION", SYM(POSITION_SYM),0,0}, { "POW", SYM(FUNC_ARG2),0,CREATE_FUNC(create_func_pow)}, { "POWER", SYM(FUNC_ARG2),0,CREATE_FUNC(create_func_pow)}, diff --git a/sql/sql_yacc.yy b/sql/sql_yacc.yy index e40053f512a..898bde8659e 100644 --- a/sql/sql_yacc.yy +++ b/sql/sql_yacc.yy @@ -484,6 +484,7 @@ bool my_yyoverflow(short **a, YYSTYPE **b,int *yystacksize); %token NOW_SYM %token PASSWORD %token POINTFROMTEXT +%token POINT %token POLYFROMTEXT %token POLYGON %token POSITION_SYM @@ -1144,6 +1145,18 @@ type: $$=FIELD_TYPE_BLOB; } | GEOMETRY_SYM { Lex->charset=&my_charset_bin; $$=FIELD_TYPE_GEOMETRY; } + | POINT { Lex->charset=&my_charset_bin; + $$=FIELD_TYPE_GEOMETRY; } + | MULTIPOINT { Lex->charset=&my_charset_bin; + $$=FIELD_TYPE_GEOMETRY; } + | LINESTRING { Lex->charset=&my_charset_bin; + $$=FIELD_TYPE_GEOMETRY; } + | MULTILINESTRING { Lex->charset=&my_charset_bin; + $$=FIELD_TYPE_GEOMETRY; } + | POLYGON { Lex->charset=&my_charset_bin; + $$=FIELD_TYPE_GEOMETRY; } + | MULTIPOLYGON { Lex->charset=&my_charset_bin; + $$=FIELD_TYPE_GEOMETRY; } | MEDIUMBLOB { Lex->charset=&my_charset_bin; $$=FIELD_TYPE_MEDIUM_BLOB; } | LONGBLOB { Lex->charset=&my_charset_bin; @@ -2276,6 +2289,8 @@ simple_expr: { $$= new Item_func_password($3); } | PASSWORD '(' expr ',' expr ')' { $$= new Item_func_password($3,$5); } + | POINT '(' expr ',' expr ')' + { $$= new Item_func_point($3,$5); } | POINTFROMTEXT '(' expr ')' { $$= new Item_func_geometry_from_text($3); } | POINTFROMTEXT '(' expr ',' expr ')' @@ -3919,6 +3934,7 @@ keyword: | FIRST_SYM {} | FIXED_SYM {} | FLUSH_SYM {} + | GEOMETRY_SYM {} | GRANTS {} | GLOBAL_SYM {} | HEAP_SYM {} @@ -3935,6 +3951,7 @@ keyword: | IO_THREAD {} | LAST_SYM {} | LEVEL_SYM {} + | LINESTRING {} | LOCAL_SYM {} | LOCKS_SYM {} | LOGS_SYM {} @@ -3957,6 +3974,9 @@ keyword: | MODIFY_SYM {} | MODE_SYM {} | MONTH_SYM {} + | MULTILINESTRING {} + | MULTIPOINT {} + | MULTIPOLYGON {} | MYISAM_SYM {} | NATIONAL_SYM {} | NCHAR_SYM {} @@ -3969,6 +3989,8 @@ keyword: | PACK_KEYS_SYM {} | PARTIAL {} | PASSWORD {} + | POINT {} + | POLYGON {} | PREV_SYM {} | PROCESS {} | PROCESSLIST_SYM {} From 1ee953481a9a768b3dc164927d57e6417e08658e Mon Sep 17 00:00:00 2001 From: unknown Date: Tue, 11 Feb 2003 16:03:00 +0400 Subject: [PATCH 07/11] lex.h: New synonyms for spatial functions for compatibility with http://www.opengis.org/testing/sfsql/sqltsch.sql sql/lex.h: New synonyms for spatial functions for compatibility with http://www.opengis.org/testing/sfsql/sqltsch.sql --- sql/lex.h | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/sql/lex.h b/sql/lex.h index 135721a563c..599f940b8fc 100644 --- a/sql/lex.h +++ b/sql/lex.h @@ -509,6 +509,7 @@ static SYMBOL sql_functions[] = { { "LENGTH", SYM(FUNC_ARG1),0,CREATE_FUNC(create_func_length)}, { "LN", SYM(FUNC_ARG1),0,CREATE_FUNC(create_func_ln)}, { "LINEFROMTEXT", SYM(LINEFROMTEXT),0,0}, + { "LINESTRINGFROMTEXT",SYM(LINEFROMTEXT),0,0}, { "LOAD_FILE", SYM(FUNC_ARG1),0,CREATE_FUNC(create_load_file)}, { "LOCATE", SYM(LOCATE),0,0}, { "LOG", SYM(LOG_SYM),0,0}, @@ -528,6 +529,8 @@ static SYMBOL sql_functions[] = { { "MPOINTFROMTEXT", SYM(MPOINTFROMTEXT),0,0}, { "MPOLYFROMTEXT", SYM(MPOLYFROMTEXT),0,0}, { "MONTHNAME", SYM(FUNC_ARG1),0,CREATE_FUNC(create_func_monthname)}, + { "MULTILINESTRINGFROMTEXT",SYM(MLINEFROMTEXT),0,0}, + { "MULTIPOLYGONFROMTEXT",SYM(MPOLYFROMTEXT),0,0}, { "NOW", SYM(NOW_SYM),0,0}, { "NULLIF", SYM(FUNC_ARG2),0,CREATE_FUNC(create_func_nullif)}, { "NUMGEOMETRIES", SYM(FUNC_ARG1),0,CREATE_FUNC(create_func_numgeometries)}, @@ -544,6 +547,7 @@ static SYMBOL sql_functions[] = { { "POINTFROMTEXT", SYM(POINTFROMTEXT),0,0}, { "POINTN", SYM(FUNC_ARG2),0,CREATE_FUNC(create_func_pointn)}, { "POLYFROMTEXT", SYM(POLYFROMTEXT),0,0}, + { "POLYGONFROMTEXT", SYM(POLYFROMTEXT),0,0}, { "POSITION", SYM(POSITION_SYM),0,0}, { "POW", SYM(FUNC_ARG2),0,CREATE_FUNC(create_func_pow)}, { "POWER", SYM(FUNC_ARG2),0,CREATE_FUNC(create_func_pow)}, From b98903d27006c2db7fd1b1f298062d61c5d83d0d Mon Sep 17 00:00:00 2001 From: unknown Date: Tue, 11 Feb 2003 16:37:37 +0400 Subject: [PATCH 08/11] lex.h: Typo fix sql/lex.h: Typo fix --- sql/lex.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/sql/lex.h b/sql/lex.h index 599f940b8fc..119d127190e 100644 --- a/sql/lex.h +++ b/sql/lex.h @@ -534,7 +534,7 @@ static SYMBOL sql_functions[] = { { "NOW", SYM(NOW_SYM),0,0}, { "NULLIF", SYM(FUNC_ARG2),0,CREATE_FUNC(create_func_nullif)}, { "NUMGEOMETRIES", SYM(FUNC_ARG1),0,CREATE_FUNC(create_func_numgeometries)}, - { "NUMINTERIORRING", SYM(FUNC_ARG1),0,CREATE_FUNC(create_func_numinteriorring)}, + { "NUMINTERIORRINGS", SYM(FUNC_ARG1),0,CREATE_FUNC(create_func_numinteriorring)}, { "NUMPOINTS", SYM(FUNC_ARG1),0,CREATE_FUNC(create_func_numpoints)}, { "OCTET_LENGTH", SYM(FUNC_ARG1),0,CREATE_FUNC(create_func_length)}, { "OCT", SYM(FUNC_ARG1),0,CREATE_FUNC(create_func_oct)}, From 4b04c84f095e8ba4801321978a9719fe72e6810b Mon Sep 17 00:00:00 2001 From: unknown Date: Tue, 11 Feb 2003 16:51:02 +0400 Subject: [PATCH 09/11] gis.txt: Updates according to last changes Docs/gis.txt: Updates according to last changes --- Docs/gis.txt | 15 ++++++++++++++- 1 file changed, 14 insertions(+), 1 deletion(-) diff --git a/Docs/gis.txt b/Docs/gis.txt index d80a200d5a6..3556949d516 100644 --- a/Docs/gis.txt +++ b/Docs/gis.txt @@ -496,18 +496,28 @@ built GEOMETRY value. * |*LineFromText(lineStringTaggedText String [,SRID Integer]):LineString *| - constructs a LineString + . |*LineStringFromText()*| - synonym for LineFromText(). + * |*PolyFromText(polygonTaggedText String [,SRID Integer]):Polygon *|- constructs a Polygon + |*PolygonFromText()*| - synonym for PolyFromText(). + * |*MPointFromText(multiPointTaggedText String [,SRID Integer]):MultiPoint *| - constructs a MultiPoint + |*MultiPointFromText()*| - synonym for MPointFromText(). + * |*MLineFromText(multiLineStringTaggedText String [,SRID Integer]):MultiLineString *| - constructs a MultiLineString + |*MultiLineStringFromText()*| - synonym for MLineFromText(). + * |*MPolyFromText(multiPolygonTaggedText String [,SRID Integer]):MultiPolygon *| - constructs a MultiPolygon + |*MultiPolygonFromText()*| - synonym for MPolyFromText(). + * |*GeomCollFromText(geometryCollectionTaggedText String [,SRID Integer]):GeomCollection *| - constructs a GeometryCollection @@ -844,7 +854,10 @@ implementation of several spatial field types correspondent to every instansiable object subclass. For example a *Point* type is proposed to restrict data stored in a field of this type to only Point OpenGIS subclass. MySQL provides an implementation of single GEOMETRY type which -doesn't restrict objects to certain OpenGIS subclass. +doesn't restrict objects to certain OpenGIS subclass. Other proposed +spatial field types are mapped into GEOMETRY type, so all these types +can be used as a symonym for GEOMETRY: POINT, MULTIPOINT, LINESTRING, +MULTILINESTRING, POLYGON, MULTIPOLYGON. 9.2 No additional Metadata Views From f3282731343b6cc6cb4679ac15b40e205b710256 Mon Sep 17 00:00:00 2001 From: unknown Date: Wed, 12 Feb 2003 19:50:49 +0400 Subject: [PATCH 10/11] rt_index.c: Bug fix myisam/rt_index.c: Bug fix --- myisam/rt_index.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/myisam/rt_index.c b/myisam/rt_index.c index d55d01fa4a3..ad0d593ee0a 100644 --- a/myisam/rt_index.c +++ b/myisam/rt_index.c @@ -503,7 +503,7 @@ static int rtree_insert_level(MI_INFO *info, uint keynr, uchar *key, return res; } - switch ((res = rtree_insert_req(info, &keyinfo[keynr], key, key_length, + switch ((res = rtree_insert_req(info, keyinfo, key, key_length, old_root, &new_page, ins_level, 0))) { case 0: /* root was not split */ From c5040dddee0e84076ec7860a9e8ce5df0ced581d Mon Sep 17 00:00:00 2001 From: unknown Date: Wed, 12 Feb 2003 19:53:30 +0200 Subject: [PATCH 11/11] Fixed a bug in mysqld_safe, when it earlier could have removed a socket from another, still living MySQL server. --- scripts/mysqld_safe.sh | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/scripts/mysqld_safe.sh b/scripts/mysqld_safe.sh index febc7b8e595..e937789e6ef 100644 --- a/scripts/mysqld_safe.sh +++ b/scripts/mysqld_safe.sh @@ -270,7 +270,6 @@ echo "Starting $MYSQLD daemon with databases from $DATADIR" echo "`date +'%y%m%d %H:%M:%S mysqld started'`" >> $err_log while true do - rm -f $MYSQL_UNIX_PORT $pid_file # Some extra safety if test -z "$args" then $NOHUP_NICENESS $ledir/$MYSQLD $defaults --basedir=$MY_BASEDIR_VERSION --datadir=$DATADIR $USER_OPTION --pid-file=$pid_file @MYSQLD_DEFAULT_SWITCHES@ >> $err_log 2>&1 @@ -309,7 +308,7 @@ do I=`expr $I + 1` done fi - + rm -f $MYSQL_UNIX_PORT $pid_file # Some extra safety echo "`date +'%y%m%d %H:%M:%S'` mysqld restarted" | tee -a $err_log done