diff options
author | hf@deer.mysql.r18.ru <> | 2003-04-23 19:37:33 +0500 |
---|---|---|
committer | hf@deer.mysql.r18.ru <> | 2003-04-23 19:37:33 +0500 |
commit | ca0271471507cfa940337a7db63f415e504de768 (patch) | |
tree | ca16079f1d4f7eae6f2205e124d0c90afbec8409 /sql | |
parent | a3d08eaaf97c013569516294ae97b8118b3db0b0 (diff) | |
download | mariadb-git-ca0271471507cfa940337a7db63f415e504de768.tar.gz |
SCRUM
Protocol_cursor class and sql-common/ directory
Diffstat (limited to 'sql')
-rw-r--r-- | sql/Makefile.am | 6 | ||||
-rw-r--r-- | sql/mini_client.cc | 84 | ||||
-rw-r--r-- | sql/protocol.h | 26 | ||||
-rw-r--r-- | sql/protocol_cursor.cc | 143 |
4 files changed, 182 insertions, 77 deletions
diff --git a/sql/Makefile.am b/sql/Makefile.am index b1d9149ddf4..a4858ab2b38 100644 --- a/sql/Makefile.am +++ b/sql/Makefile.am @@ -83,9 +83,9 @@ mysqld_SOURCES = sql_lex.cc sql_handler.cc \ sql_load.cc mf_iocache.cc field_conv.cc sql_show.cc \ sql_udf.cc sql_analyse.cc sql_analyse.h sql_cache.cc \ slave.cc sql_repl.cc sql_union.cc sql_derived.cc \ - mini_client.cc mini_client_errors.c \ + mini_client.cc mini_client_errors.c pack.c\ stacktrace.c repl_failsafe.h repl_failsafe.cc sql_olap.cc\ - gstream.cc spatial.cc sql_help.cc + gstream.cc spatial.cc sql_help.cc protocol_cursor.cc gen_lex_hash_SOURCES = gen_lex_hash.cc gen_lex_hash_LDADD = $(LDADD) $(CXXLDFLAGS) @@ -102,6 +102,8 @@ AM_YFLAGS = -d link_sources: rm -f mini_client_errors.c @LN_CP_F@ ../libmysql/errmsg.c mini_client_errors.c + rm -f pack.c + @LN_CP_F@ ../sql-common/pack.c pack.c gen_lex_hash.o: gen_lex_hash.cc lex.h $(CXXCOMPILE) -c $(INCLUDES) $< diff --git a/sql/mini_client.cc b/sql/mini_client.cc index db3a51712f2..b4441ab910d 100644 --- a/sql/mini_client.cc +++ b/sql/mini_client.cc @@ -23,6 +23,7 @@ */ #include <my_global.h> + #ifdef HAVE_EXTERNAL_CLIENT /* my_pthread must be included early to be able to fix things */ @@ -80,8 +81,6 @@ void mc_end_server(MYSQL *mysql); static int mc_sock_connect(File s, const struct sockaddr *name, uint namelen, uint to); static void mc_free_old_query(MYSQL *mysql); static int mc_send_file_to_server(MYSQL *mysql, const char *filename); -static my_ulonglong mc_net_field_length_ll(uchar **packet); -static ulong mc_net_field_length(uchar **packet); static int mc_read_one_row(MYSQL *mysql,uint fields,MYSQL_ROW row, ulong *lengths); static MYSQL_DATA *mc_read_rows(MYSQL *mysql,MYSQL_FIELD *mysql_fields, @@ -1085,15 +1084,15 @@ int mc_mysql_read_query_result(MYSQL *mysql) mc_free_old_query(mysql); /* Free old result */ get_info: pos=(uchar*) mysql->net.read_pos; - if ((field_count= mc_net_field_length(&pos)) == 0) + if ((field_count= net_field_length(&pos)) == 0) { - mysql->affected_rows= mc_net_field_length_ll(&pos); - mysql->insert_id= mc_net_field_length_ll(&pos); + mysql->affected_rows= net_field_length_ll(&pos); + mysql->insert_id= net_field_length_ll(&pos); if (mysql->server_capabilities & CLIENT_TRANSACTIONS) { mysql->server_status=uint2korr(pos); pos+=2; } - if (pos < mysql->net.read_pos+length && mc_net_field_length(&pos)) + if (pos < mysql->net.read_pos+length && net_field_length(&pos)) mysql->info=(char*) pos; DBUG_RETURN(0); } @@ -1107,7 +1106,7 @@ get_info: if (!(mysql->server_status & SERVER_STATUS_AUTOCOMMIT)) mysql->server_status|= SERVER_STATUS_IN_TRANS; - mysql->extra_info= mc_net_field_length_ll(&pos); /* Maybe number of rec */ + mysql->extra_info= net_field_length_ll(&pos); /* Maybe number of rec */ if (!(fields=mc_read_rows(mysql,(MYSQL_FIELD*) 0,5))) DBUG_RETURN(-1); if (!(mysql->fields=mc_unpack_fields(fields,&mysql->field_alloc, @@ -1190,68 +1189,6 @@ err: DBUG_RETURN(result); } - -/* Get the length of next field. Change parameter to point at fieldstart */ -static ulong mc_net_field_length(uchar **packet) -{ - reg1 uchar *pos= *packet; - if (*pos < 251) - { - (*packet)++; - return (ulong) *pos; - } - if (*pos == 251) - { - (*packet)++; - return NULL_LENGTH; - } - if (*pos == 252) - { - (*packet)+=3; - return (ulong) uint2korr(pos+1); - } - if (*pos == 253) - { - (*packet)+=4; - return (ulong) uint3korr(pos+1); - } - (*packet)+=9; /* Must be 254 when here */ - return (ulong) uint4korr(pos+1); -} - -/* Same as above, but returns ulonglong values */ - -static my_ulonglong mc_net_field_length_ll(uchar **packet) -{ - reg1 uchar *pos= *packet; - if (*pos < 251) - { - (*packet)++; - return (my_ulonglong) *pos; - } - if (*pos == 251) - { - (*packet)++; - return (my_ulonglong) NULL_LENGTH; - } - if (*pos == 252) - { - (*packet)+=3; - return (my_ulonglong) uint2korr(pos+1); - } - if (*pos == 253) - { - (*packet)+=4; - return (my_ulonglong) uint3korr(pos+1); - } - (*packet)+=9; /* Must be 254 when here */ -#ifdef NO_CLIENT_LONGLONG - return (my_ulonglong) uint4korr(pos+1); -#else - return (my_ulonglong) uint8korr(pos+1); -#endif -} - /* Read all rows (fields or data) from server */ static MYSQL_DATA *mc_read_rows(MYSQL *mysql,MYSQL_FIELD *mysql_fields, @@ -1301,7 +1238,7 @@ static MYSQL_DATA *mc_read_rows(MYSQL *mysql,MYSQL_FIELD *mysql_fields, to= (char*) (cur->data+fields+1); for (field=0 ; field < fields ; field++) { - if ((len=(ulong) mc_net_field_length(&cp)) == NULL_LENGTH) + if ((len=(ulong) net_field_length(&cp)) == NULL_LENGTH) { /* null field */ cur->data[field] = 0; } @@ -1342,7 +1279,8 @@ static int mc_read_one_row(MYSQL *mysql,uint fields,MYSQL_ROW row, { uint field; ulong pkt_len,len; - uchar *pos,*prev_pos; + uchar *pos; + uchar *prev_pos; if ((pkt_len=mc_net_safe_read(mysql)) == packet_error) return -1; @@ -1352,7 +1290,7 @@ static int mc_read_one_row(MYSQL *mysql,uint fields,MYSQL_ROW row, pos=mysql->net.read_pos; for (field=0 ; field < fields ; field++) { - if ((len=(ulong) mc_net_field_length(&pos)) == NULL_LENGTH) + if ((len=(ulong) net_field_length(&pos)) == NULL_LENGTH) { /* null field */ row[field] = 0; *lengths++=0; @@ -1365,7 +1303,7 @@ static int mc_read_one_row(MYSQL *mysql,uint fields,MYSQL_ROW row, } if (prev_pos) *prev_pos=0; /* Terminate prev field */ - prev_pos=pos; + prev_pos= (uchar *)pos; } row[field]=(char*) prev_pos+1; /* End of last field */ *prev_pos=0; /* Terminate last field */ diff --git a/sql/protocol.h b/sql/protocol.h index 89b838ff6e4..dd644afd335 100644 --- a/sql/protocol.h +++ b/sql/protocol.h @@ -22,9 +22,9 @@ class i_string; class THD; -#ifdef EMBEDDED_LIBRARY typedef struct st_mysql_field MYSQL_FIELD; -#endif +typedef struct st_mysql_rows MYSQL_ROWS; + class Protocol { protected: @@ -135,6 +135,28 @@ public: virtual bool store(Field *field); }; +class Protocol_cursor :public Protocol_simple +{ +public: + MEM_ROOT *alloc; + MYSQL_FIELD *fields; + MYSQL_ROWS *data; + MYSQL_ROWS **prev_record; + ulong row_count; + + Protocol_cursor() {} + Protocol_cursor(THD *thd, MEM_ROOT *ini_alloc) :Protocol_simple(thd), alloc(ini_alloc) {} + bool prepare_for_send(List<Item> *item_list) + { + fields= NULL; + data= NULL; + prev_record= &data; + return Protocol_simple::prepare_for_send(item_list); + } + bool send_fields(List<Item> *list, uint flag); + bool write(); +}; + void send_warning(THD *thd, uint sql_errno, const char *err=0); void net_printf(THD *thd,uint sql_errno, ...); void send_ok(THD *thd, ha_rows affected_rows=0L, ulonglong id=0L, diff --git a/sql/protocol_cursor.cc b/sql/protocol_cursor.cc new file mode 100644 index 00000000000..19e3bb06d74 --- /dev/null +++ b/sql/protocol_cursor.cc @@ -0,0 +1,143 @@ +/* Copyright (C) 2000-2003 MySQL AB + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ + +/* + Low level functions for storing data to be send to the MySQL client + The actual communction is handled by the net_xxx functions in net_serv.cc +*/ + +#ifdef __GNUC__ +#pragma implementation // gcc: Class implementation +#endif + +#include "mysql_priv.h" +#include <mysql.h> + +bool Protocol_cursor::send_fields(List<Item> *list, uint flag) +{ + List_iterator_fast<Item> it(*list); + Item *item; + MYSQL_FIELD *field, *client_field; + + DBUG_ENTER("send_fields"); + if (prepare_for_send(list)) + return FALSE; + + fields= (MYSQL_FIELD *)alloc_root(alloc, sizeof(MYSQL_FIELD) * field_count); + if (!fields) + goto err; + + client_field= fields; + while ((item= it++)) + { + Send_field server_field; + item->make_field(&server_field); + + client_field->db= strdup_root(alloc, server_field.db_name); + client_field->table= strdup_root(alloc, server_field.table_name); + client_field->name= strdup_root(alloc, server_field.col_name); + client_field->org_table= strdup_root(alloc, server_field.org_table_name); + client_field->org_name= strdup_root(alloc, server_field.org_col_name); + client_field->length= server_field.length; + client_field->type= server_field.type; + client_field->flags= server_field.flags; + client_field->decimals= server_field.decimals; + client_field->db_length= strlen(client_field->db); + client_field->table_length= strlen(client_field->table); + client_field->name_length= strlen(client_field->name); + client_field->org_name_length= strlen(client_field->org_name); + client_field->org_table_length= strlen(client_field->org_table); + client_field->charsetnr= server_field.charsetnr; + + if (INTERNAL_NUM_FIELD(client_field)) + client_field->flags|= NUM_FLAG; + + if (flag & 2) + { + char buff[80]; + String tmp(buff, sizeof(buff), default_charset_info), *res; + + if (!(res=item->val_str(&tmp))) + client_field->def= strdup_root(alloc, ""); + else + client_field->def= strdup_root(alloc, tmp.ptr()); + } + else + client_field->def=0; + client_field->max_length= 0; + ++client_field; + } + + DBUG_RETURN(FALSE); + err: + send_error(thd, ER_OUT_OF_RESOURCES); /* purecov: inspected */ + DBUG_RETURN(TRUE); /* purecov: inspected */ +} + +/* Get the length of next field. Change parameter to point at fieldstart */ +bool Protocol_cursor::write() +{ + byte *cp= (byte *)packet->ptr(); + byte *end_pos= (byte *)packet->ptr() + packet->length(); + ulong len; + MYSQL_FIELD *cur_field= fields; + MYSQL_FIELD *fields_end= fields + field_count; + MYSQL_ROWS *new_record; + byte **data; + byte *to; + + new_record= (MYSQL_ROWS *)alloc_root(alloc, + sizeof(MYSQL_ROWS) + (field_count + 1)*sizeof(char *) + packet->length()); + if (!new_record) + goto err; + data= (byte **)(new_record + 1); + new_record->data= (char **)data; + + to= (byte *)(fields + field_count + 1); + + for (; cur_field < fields_end; ++cur_field, ++data) + { + if ((len=net_field_length((uchar **)&cp))) + { + *data= 0; + } + else + { + if ((long)len > (end_pos - cp)) + { +// TODO error signal send_error(thd, CR_MALFORMED_PACKET); + return TRUE; + } + memcpy(to,(char*) cp,len); + to[len]=0; + to+=len+1; + cp+=len; + if (cur_field->max_length < len) + cur_field->max_length=len; + } + } + + *prev_record= new_record; + prev_record= &new_record->next; + new_record->next= NULL; + row_count++; + return FALSE; + err: +// TODO error signal send_error(thd, ER_OUT_OF_RESOURCES); + return TRUE; +} + + |