diff options
author | unknown <venu@myvenu.com> | 2002-11-22 10:20:14 -0800 |
---|---|---|
committer | unknown <venu@myvenu.com> | 2002-11-22 10:20:14 -0800 |
commit | bd6df955e327b52b393f4a6f7fd61c2ed9751a85 (patch) | |
tree | 1db1bf4593b745f0c12c8cb09b5934c136c3e073 /sql | |
parent | 1049175831a4aa145f64e912388cc6079d7f5789 (diff) | |
parent | 7eafe60b3641e3d1c9067181bce7f465cfc742e8 (diff) | |
download | mariadb-git-bd6df955e327b52b393f4a6f7fd61c2ed9751a85.tar.gz |
protocol merge
libmysql/errmsg.c:
Auto merged
sql/item.h:
Auto merged
sql/mysql_priv.h:
Auto merged
sql/sql_class.h:
Auto merged
sql/sql_error.cc:
Auto merged
Diffstat (limited to 'sql')
-rw-r--r-- | sql/item.cc | 17 | ||||
-rw-r--r-- | sql/item.h | 13 | ||||
-rw-r--r-- | sql/mysql_priv.h | 2 | ||||
-rw-r--r-- | sql/sql_class.h | 3 | ||||
-rw-r--r-- | sql/sql_error.cc | 2 | ||||
-rw-r--r-- | sql/sql_prepare.cc | 317 |
6 files changed, 188 insertions, 166 deletions
diff --git a/sql/item.cc b/sql/item.cc index 48ec11d02c2..cd321488548 100644 --- a/sql/item.cc +++ b/sql/item.cc @@ -315,32 +315,27 @@ void Item_param::set_null() void Item_param::set_int(longlong i) { int_value=(longlong)i; - item_result_type = INT_RESULT; item_type = INT_ITEM; } void Item_param::set_double(double value) { real_value=value; - item_result_type = REAL_RESULT; item_type = REAL_ITEM; } -void Item_param::set_value(const char *str, uint length, CHARSET_INFO *cs) +void Item_param::set_value(const char *str, uint length) { - str_value.set(str,length,cs); - item_result_type = STRING_RESULT; + str_value.set(str,length,thd_charset()); item_type = STRING_ITEM; } -void Item_param::set_longdata(const char *str, ulong length, CHARSET_INFO *cs) -{ - /* TODO: Fix this for binary handling by making use of - buffer_type.. - */ - str_value.append(str,length); +void Item_param::set_longdata(const char *str, ulong length) +{ + str_value.append(str,length); + long_data_supplied= 1; } diff --git a/sql/item.h b/sql/item.h index 5eeaa22a2a2..e1d02c61804 100644 --- a/sql/item.h +++ b/sql/item.h @@ -186,8 +186,8 @@ public: Item_param(char *name_par=0) { name= name_par ? name_par : (char*) "?"; - long_data_supplied = false; - item_type = STRING_ITEM; + long_data_supplied= false; + item_type= STRING_ITEM; item_result_type = STRING_RESULT; } enum Type type() const { return item_type; } @@ -199,12 +199,13 @@ public: void set_null(); void set_int(longlong i); void set_double(double i); - void set_value(const char *str, uint length, CHARSET_INFO *cs); - void set_long_str(const char *str, ulong length, CHARSET_INFO *cs); - void set_long_binary(const char *str, ulong length, CHARSET_INFO *cs); - void set_longdata(const char *str, ulong length, CHARSET_INFO *cs); + void set_value(const char *str, uint length); + void set_long_str(const char *str, ulong length); + void set_long_binary(const char *str, ulong length); + void set_longdata(const char *str, ulong length); void set_long_end(); void reset() {} + void (*setup_param_func)(Item_param *param, uchar **pos); enum Item_result result_type () const { return item_result_type; } Item *new_item() { return new Item_param(name); } diff --git a/sql/mysql_priv.h b/sql/mysql_priv.h index 058e6b4ee95..3ba88d493bd 100644 --- a/sql/mysql_priv.h +++ b/sql/mysql_priv.h @@ -512,7 +512,7 @@ int mysqld_show_column_types(THD *thd); int mysqld_help (THD *thd, const char *text); /* sql_prepare.cc */ -int compare_prep_stmt(PREP_STMT *a, PREP_STMT *b, void *not_used); +int compare_prep_stmt(void *not_used, PREP_STMT *stmt, ulong *key); void free_prep_stmt(PREP_STMT *stmt, TREE_FREE mode, void *not_used); bool mysql_stmt_prepare(THD *thd, char *packet, uint packet_length); void mysql_stmt_execute(THD *thd, char *packet); diff --git a/sql/sql_class.h b/sql/sql_class.h index acdf2471ba8..599a0572a8a 100644 --- a/sql/sql_class.h +++ b/sql/sql_class.h @@ -325,7 +325,7 @@ typedef struct st_prep_stmt uint param_count; uint last_errno; char last_error[MYSQL_ERRMSG_SIZE]; - bool error_in_prepare, long_data_used; + bool error_in_prepare, long_data_used, param_inited; } PREP_STMT; @@ -510,7 +510,6 @@ public: bool safe_to_cache_query; bool volatile killed; bool prepare_command; - Item_param *params; // Pointer to array of params /* If we do a purge of binary logs, log index info of the threads diff --git a/sql/sql_error.cc b/sql/sql_error.cc index 0740dc428f0..d2735073461 100644 --- a/sql/sql_error.cc +++ b/sql/sql_error.cc @@ -127,7 +127,7 @@ static const char *warning_level_names[]= {"Note", "Warning", "Error", "?"}; my_bool mysqld_show_warnings(THD *thd, ulong levels_to_show) { List<Item> field_list; - DBUG_ENTER("mysqld_show_errors"); + DBUG_ENTER("mysqld_show_warnings"); field_list.push_back(new Item_empty_string("Level", 7)); field_list.push_back(new Item_int("Code",0,4)); diff --git a/sql/sql_prepare.cc b/sql/sql_prepare.cc index 08377a10501..4bc66778ffb 100644 --- a/sql/sql_prepare.cc +++ b/sql/sql_prepare.cc @@ -30,10 +30,11 @@ Prepare: Prepare-execute: - Server gets the command 'COM_EXECUTE' to execute the - previously prepared query. - - If there is are any parameters, then replace the markers with the - data supplied by client with the following format: - [types_specified(0/1)][type][length][data] .. [type][length].. + previously prepared query. If there is any param markers; then client + will send the data in the following format: + [null_bits][types_specified(0/1)][[length][data]][[length][data] .. [length][data]. + - Replace the param items with this new data. If it is a first execute + or types altered by client; then setup the conversion routines. - Execute the query without re-parsing and send back the results to client @@ -53,33 +54,9 @@ Long data handling: #include <assert.h> // for DEBUG_ASSERT() #include <m_ctype.h> // for isspace() -extern int yyparse(void); -static ulong get_param_length(uchar **packet); -static uint get_buffer_type(uchar **packet); -static bool param_is_null(uchar **packet); -static bool setup_param_fields(THD *thd,List<Item> ¶ms); -static uchar* setup_param_field(Item_param *item_param, uchar *pos, - uint buffer_type); -static void setup_longdata_field(Item_param *item_param, uchar *pos); -static bool setup_longdata(THD *thd,List<Item> ¶ms); -static bool send_prepare_results(PREP_STMT *stmt); -static bool parse_prepare_query(PREP_STMT *stmt, char *packet, uint length); -static bool mysql_send_insert_fields(PREP_STMT *stmt, TABLE_LIST *table_list, - List<Item> &fields, - List<List_item> &values_list, - thr_lock_type lock_type); -static bool mysql_test_insert_fields(PREP_STMT *stmt, TABLE_LIST *table_list, - List<Item> &fields, - List<List_item> &values_list, - thr_lock_type lock_type); -static bool mysql_test_upd_fields(PREP_STMT *stmt, TABLE_LIST *table_list, - List<Item> &fields, List<Item> &values, - COND *conds,thr_lock_type lock_type); -static bool mysql_test_select_fields(PREP_STMT *stmt, TABLE_LIST *tables, - List<Item> &fields, List<Item> &values, - COND *conds, ORDER *order, ORDER *group, - Item *having,thr_lock_type lock_type); +#define IS_PARAM_NULL(pos, param_no) pos[param_no/8] & (1 << param_no & 7) +extern int yyparse(void); /* Find prepared statement in thd @@ -114,9 +91,9 @@ static PREP_STMT *find_prepared_statement(THD *thd, ulong stmt_id, Compare two prepared statements; Used to find a prepared statement */ -int compare_prep_stmt(PREP_STMT *a, PREP_STMT *b, void *not_used) +int compare_prep_stmt(void *not_used, PREP_STMT *stmt, ulong *key) { - return (a->stmt_id < b->stmt_id) ? -1 : (a->stmt_id == b->stmt_id) ? 0 : 1; + return (stmt->stmt_id == *key) ? 0 : (stmt->stmt_id < *key) ? -1 : 1; } @@ -132,22 +109,23 @@ int compare_prep_stmt(PREP_STMT *a, PREP_STMT *b, void *not_used) */ void free_prep_stmt(PREP_STMT *stmt, TREE_FREE mode, void *not_used) -{ - free_root(&stmt->mem_root, MYF(0)); +{ free_items(stmt->free_list); + free_root(&stmt->mem_root, MYF(0)); } /* Send prepared stmt info to client after prepare */ -bool send_prep_stmt(PREP_STMT *stmt, uint columns) +static bool send_prep_stmt(PREP_STMT *stmt, uint columns) { + NET *net=&stmt->thd->net; char buff[8]; int4store(buff, stmt->stmt_id); int2store(buff+4, columns); int2store(buff+6, stmt->param_count); - return my_net_write(&stmt->thd->net, buff, sizeof(buff)); + return (my_net_write(net, buff, sizeof(buff)) || net_flush(net)); } /* @@ -156,43 +134,15 @@ bool send_prep_stmt(PREP_STMT *stmt, uint columns) TODO: Not yet ready */ -bool send_item_params(PREP_STMT *stmt) +static bool send_item_params(PREP_STMT *stmt) { +#if 0 char buff[1]; buff[0]=0; - return my_net_write(&stmt->thd->net, buff, sizeof(buff)); -} - - - -/* - Read the buffer type, this happens only first time -*/ - -static uint get_buffer_type(uchar **packet) -{ - reg1 uchar *pos= *packet; - (*packet)+= 2; - return (uint) uint2korr(pos); -} - - -/* - Check for NULL param data - - RETURN VALUES - 0 Value was not NULL - 1 Value was NULL -*/ - -static bool param_is_null(uchar **packet) -{ - reg1 uchar *pos= *packet; - if (*pos == 251) - { - (*packet)++; + if (my_net_write(&stmt->thd->net, buff, sizeof(buff))) return 1; - } + send_eof(stmt->thd); +#endif return 0; } @@ -222,60 +172,103 @@ static ulong get_param_length(uchar **packet) (*packet)+=9; // Must be 254 when here return (ulong) uint4korr(pos+1); } + /* + Setup param conversion routines -/* - Read and return the data for parameters supplied by client + setup_param_xx() + param Parameter Item + pos Input data buffer + + All these functions reads the data from pos and sets up that data + through 'param' and advances the buffer position to predifined + length position. + + Make a note that the NULL handling is examined at first execution + (i.e. when input types altered) and for all subsequent executions + we don't read any values for this. + + RETURN VALUES + */ -static uchar* setup_param_field(Item_param *item_param, - uchar *pos, uint buffer_type) +static void setup_param_tiny(Item_param *param, uchar **pos) { - if (param_is_null(&pos)) - { - item_param->set_null(); - return(pos); - } - switch (buffer_type) { + param->set_int((longlong)(**pos)); + *pos+= 1; +} + +static void setup_param_short(Item_param *param, uchar **pos) +{ + param->set_int((longlong)sint2korr(*pos)); + *pos+= 2; +} + +static void setup_param_int32(Item_param *param, uchar **pos) +{ + param->set_int((longlong)sint4korr(*pos)); + *pos+= 4; +} + +static void setup_param_int64(Item_param *param, uchar **pos) +{ + param->set_int((longlong)sint8korr(*pos)); + *pos+= 8; +} + +static void setup_param_float(Item_param *param, uchar **pos) +{ + float data; + float4get(data,*pos); + param->set_double((double) data); + *pos+= 4; +} + +static void setup_param_double(Item_param *param, uchar **pos) +{ + double data; + float8get(data,*pos); + param->set_double((double) data); + *pos+= 8; +} + +static void setup_param_str(Item_param *param, uchar **pos) +{ + ulong len=get_param_length(pos); + param->set_value((const char *)*pos, len); + *pos+=len; +} + +static void setup_param_functions(Item_param *param, uchar read_pos) +{ + switch (read_pos) { case FIELD_TYPE_TINY: - item_param->set_int((longlong)(*pos)); - pos += 1; + param->setup_param_func= setup_param_tiny; + param->item_result_type = INT_RESULT; break; case FIELD_TYPE_SHORT: - item_param->set_int((longlong)sint2korr(pos)); - pos += 2; - break; - case FIELD_TYPE_INT24: - item_param->set_int((longlong)sint4korr(pos)); - pos += 3; + param->setup_param_func= setup_param_short; + param->item_result_type = INT_RESULT; break; case FIELD_TYPE_LONG: - item_param->set_int((longlong)sint4korr(pos)); - pos += 4; + param->setup_param_func= setup_param_int32; + param->item_result_type = INT_RESULT; break; case FIELD_TYPE_LONGLONG: - item_param->set_int((longlong)sint8korr(pos)); - pos += 8; + param->setup_param_func= setup_param_int64; + param->item_result_type = INT_RESULT; break; case FIELD_TYPE_FLOAT: - float data; - float4get(data,pos); - item_param->set_double((double) data); - pos += 4; + param->setup_param_func= setup_param_float; + param->item_result_type = REAL_RESULT; break; case FIELD_TYPE_DOUBLE: - double j; - float8get(j,pos) - item_param->set_double(j); - pos += 8; + param->setup_param_func= setup_param_double; + param->item_result_type = REAL_RESULT; break; default: - { - ulong len=get_param_length(&pos); - item_param->set_value((const char*)pos,len,current_thd->thd_charset); - pos+=len; - } + param->setup_param_func= setup_param_str; + param->item_result_type = STRING_RESULT; } - return(pos); } /* @@ -283,42 +276,45 @@ static uchar* setup_param_field(Item_param *item_param, from client .. */ -static bool setup_param_fields(THD *thd, PREP_STMT *stmt) -{ - DBUG_ENTER("setup_param_fields"); -#ifdef READY_TO_BE_USED - Item_param *item_param; - ulong param_count=0; - uchar *pos=(uchar*) thd->net.read_pos+1;// skip command type +static bool setup_params_data(THD *thd, PREP_STMT *stmt) +{ + List<Item> ¶ms= thd->lex.param_list; + List_iterator<Item> param_iterator(params); + Item_param *param; + DBUG_ENTER("setup_params_data"); - - if (*pos++) // No types supplied, read only param data - { - while ((item_param=(Item_param *)it++) && - (param_count++ < stmt->param_count)) - { - if (item_param->long_data_supplied) - continue; + uchar *pos=(uchar*) thd->net.read_pos+1+MYSQL_STMT_HEADER; //skip header + uchar *read_pos= pos+(stmt->param_count+7) / 8; //skip null bits + ulong param_no; - if (!(pos=setup_param_field(item_param,pos,item_param->buffer_type))) - DBUG_RETURN(1); + if (*read_pos++) //types supplied / first execute + { + /* + First execute or types altered by the client, setup the + conversion routines for all parameters (one time) + */ + while ((param= (Item_param *)param_iterator++)) + { + if (!param->long_data_supplied) + { + setup_param_functions(param,*read_pos); + read_pos+= 2; + } } - } - else // Types supplied, read and store it along with param data + param_iterator.rewind(); + } + param_no= 0; + while ((param= (Item_param *)param_iterator++)) { - while ((item_param=(Item_param *)it++) && - (param_count++ < thd->param_count)) + if (!param->long_data_supplied) { - if (item_param->long_data_supplied) - continue; - - if (!(pos=setup_param_field(item_param,pos, - item_param->buffer_type= - (enum_field_types) get_buffer_type(&pos)))) - DBUG_RETURN(1); + if (IS_PARAM_NULL(pos,param_no)) + param->maybe_null=param->null_value=1; + else + param->setup_param_func(param,&read_pos); } + param_no++; } -#endif DBUG_RETURN(0); } @@ -583,6 +579,8 @@ static bool send_prepare_results(PREP_STMT *stmt) Rest fall through to default category, no parsing for non-DML statements */ + if (send_prep_stmt(stmt, 0)) + goto abort; } } DBUG_RETURN(0); @@ -597,7 +595,7 @@ abort: */ static bool parse_prepare_query(PREP_STMT *stmt, - char *packet, uint length) + char *packet, uint length) { bool error= 1; THD *thd= stmt->thd; @@ -607,6 +605,7 @@ static bool parse_prepare_query(PREP_STMT *stmt, mysql_init_query(thd); thd->prepare_command=true; thd->safe_to_cache_query= 0; + thd->lex.param_count=0; LEX *lex=lex_start(thd, (uchar*) packet, length); if (!yyparse() && !thd->fatal_error) @@ -615,6 +614,25 @@ static bool parse_prepare_query(PREP_STMT *stmt, DBUG_RETURN(error); } +/* + Initialize parameter items in statement +*/ +static bool init_param_items(THD *thd, PREP_STMT *stmt) +{ +#if TO_BE_TESTED + Item_param **to; + if (!(to= (Item_param *) + my_malloc(sizeof(Item_param*) * stmt->param_count, MYF(MY_WME)))) + return 1; + List<Item> ¶ms= thd->lex.param_list; + List_iterator<Item> param_iterator(params); + while ((to++ = (Item_param *)param_iterator++)) + { + DBUG_PRINT("info",("param: %lx", to)); + } + return 0; +#endif +} /* Parse the query and send the total number of parameters @@ -648,10 +666,15 @@ bool mysql_stmt_prepare(THD *thd, char *packet, uint packet_length) goto err; if (!(specialflag & SPECIAL_NO_PRIOR)) - my_pthread_setprio(pthread_self(),WAIT_PRIOR); - - stmt.mem_root= thd->mem_root; + my_pthread_setprio(pthread_self(),WAIT_PRIOR); +#if 0 + if (init_param_items(thd, &stmt)) + goto err; +#endif + stmt.mem_root= thd->mem_root; + tree_insert(&thd->prepared_statements, (void *)&stmt, 0, (void *)0); thd->mem_root= thd_root; // restore main mem_root + thd->last_prepared_stmt= &stmt; DBUG_RETURN(0); err: @@ -685,11 +708,11 @@ void mysql_stmt_execute(THD *thd, char *packet) /* Check if we got an error when sending long data */ if (stmt->error_in_prepare) { - send_error(thd); + send_error(thd, stmt->last_errno, stmt->last_error); DBUG_VOID_RETURN; } - if (stmt->param_count && setup_param_fields(thd, stmt)) + if (stmt->param_count && setup_params_data(thd, stmt)) DBUG_VOID_RETURN; MEM_ROOT thd_root= thd->mem_root; @@ -705,6 +728,8 @@ void mysql_stmt_execute(THD *thd, char *packet) */ mysql_execute_command(thd); + thd->last_prepared_stmt= stmt; + if (!(specialflag & SPECIAL_NO_PRIOR)) my_pthread_setprio(pthread_self(), WAIT_PRIOR); @@ -768,8 +793,10 @@ void mysql_stmt_close(THD *thd, char *packet) send_error(thd); DBUG_VOID_RETURN; } + stmt->param= 0; + my_free((char *)stmt->param, MYF(MY_ALLOW_ZERO_PTR)); /* Will call free_prep_stmt() */ - tree_delete(&thd->prepared_statements, (void*) stmt, NULL); + tree_delete(&thd->prepared_statements, (void*) &stmt, (void *)0); thd->last_prepared_stmt=0; DBUG_VOID_RETURN; } @@ -800,17 +827,16 @@ void mysql_stmt_get_longdata(THD *thd, char *pos, ulong packet_length) DBUG_ENTER("mysql_stmt_get_longdata"); /* The following should never happen */ - if (packet_length < 9) + if (packet_length < MYSQL_LONG_DATA_HEADER+1) { my_error(ER_WRONG_ARGUMENTS, MYF(0), "get_longdata"); DBUG_VOID_RETURN; } - pos++; // skip command type at first position ulong stmt_id= uint4korr(pos); uint param_number= uint2korr(pos+4); uint param_type= uint2korr(pos+6); - pos+=8; // Point to data + pos+=MYSQL_LONG_DATA_HEADER; // Point to data if (!(stmt=find_prepared_statement(thd, stmt_id, "get_longdata"))) { @@ -829,7 +855,8 @@ void mysql_stmt_get_longdata(THD *thd, char *pos, ulong packet_length) sprintf(stmt->last_error, ER(ER_WRONG_ARGUMENTS), "get_longdata"); DBUG_VOID_RETURN; } - stmt->param[param_number].set_longdata(pos, packet_length-9, current_thd->thd_charset); + stmt->param[param_number].set_longdata(pos, packet_length-9); stmt->long_data_used= 1; DBUG_VOID_RETURN; } + |