lib_sql.cc 31 KB
Newer Older
1 2 3 4 5 6 7 8 9 10 11 12 13
/*
 * Copyright (c)  2000
 * SWsoft  company
 *
 * This material is provided "as is", with absolutely no warranty expressed
 * or implied. Any use is at your own risk.
 *
 * Permission to use or copy this software for any purpose is hereby granted 
 * without fee, provided the above notices are retained on all copies.
 * Permission to modify the code and to distribute modified code is granted,
 * provided the above notices are retained, and a notice that the code was
 * modified is included with the above copyright notice.
 *
unknown's avatar
unknown committed
14 15 16

  This code was modified by the MySQL team
*/
17

unknown's avatar
unknown committed
18 19 20 21
/*
  The following is needed to not cause conflicts when we include mysqld.cc
*/

22 23 24 25
#define main main1
#define mysql_unix_port mysql_inix_port1
#define mysql_port mysql_port1

26 27
extern "C"
{
unknown's avatar
unknown committed
28
  extern unsigned long max_allowed_packet, net_buffer_length;
29 30
}

31
#include "../sql/mysqld.cc"
32

unknown's avatar
unknown committed
33
C_MODE_START
unknown's avatar
unknown committed
34

35
#include <mysql.h>
unknown's avatar
unknown committed
36
#undef ER
37
#include "errmsg.h"
unknown's avatar
SCRUM  
unknown committed
38
#include <sql_common.h>
39
#include "embedded_priv.h"
unknown's avatar
unknown committed
40

41 42
extern unsigned int mysql_server_last_errno;
extern char mysql_server_last_error[MYSQL_ERRMSG_SIZE];
43 44 45
static my_bool emb_read_query_result(MYSQL *mysql);


46 47 48 49 50 51 52 53 54
extern "C" void unireg_clear(int exit_code)
{
  DBUG_ENTER("unireg_clear");
  clean_up(!opt_help && (exit_code || !opt_bootstrap)); /* purecov: inspected */
  my_end(opt_endinfo ? MY_CHECK_ERROR | MY_GIVE_INFO : 0);
  DBUG_VOID_RETURN;
}


55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74
/*
  Reads error information from the MYSQL_DATA and puts
  it into proper MYSQL members

  SYNOPSIS
    embedded_get_error()
    mysql        connection handler
    data         query result

  NOTES
    after that function error information will be accessible
       with usual functions like mysql_error()
    data is my_free-d in this function
    most of the data is stored in data->embedded_info structure
*/

void embedded_get_error(MYSQL *mysql, MYSQL_DATA *data)
{
  NET *net= &mysql->net;
  struct embedded_query_result *ei= data->embedded_info;
unknown's avatar
unknown committed
75 76
  net->last_errno= ei->last_errno;
  strmake(net->last_error, ei->info, sizeof(net->last_error)-1);
77
  memcpy(net->sqlstate, ei->sqlstate, sizeof(net->sqlstate));
78
  mysql->server_status= ei->server_status;
79
  my_free(data, MYF(0));
80 81
}

unknown's avatar
unknown committed
82
static my_bool
unknown's avatar
SCRUM  
unknown committed
83
emb_advanced_command(MYSQL *mysql, enum enum_server_command command,
84 85
		     const uchar *header, ulong header_length,
		     const uchar *arg, ulong arg_length, my_bool skip_check,
86
                     MYSQL_STMT *stmt)
87
{
88
  my_bool result= 1;
89
  THD *thd=(THD *) mysql->thd;
unknown's avatar
unknown committed
90
  NET *net= &mysql->net;
91 92 93 94 95 96 97 98 99
  my_bool stmt_skip= stmt ? stmt->state != MYSQL_STMT_INIT_DONE : FALSE;

  if (!thd)
  {
    /* Do "reconnect" if possible */
    if (mysql_reconnect(mysql) || stmt_skip)
      return 1;
    thd= (THD *) mysql->thd;
  }
100

101
#if defined(ENABLED_PROFILING)
102 103 104
  thd->profiling.start_new_query();
#endif

105
  thd->clear_data_list();
106 107 108
  /* Check that we are calling the client functions in right order */
  if (mysql->status != MYSQL_STATUS_READY)
  {
109
    set_mysql_error(mysql, CR_COMMANDS_OUT_OF_SYNC, unknown_sqlstate);
110 111 112 113
    return 1;
  }

  /* Clear result variables */
unknown's avatar
unknown committed
114
  thd->clear_error();
Marc Alff's avatar
Marc Alff committed
115
  thd->stmt_da->reset_diagnostics_area();
116
  mysql->affected_rows= ~(my_ulonglong) 0;
unknown's avatar
SCRUM  
unknown committed
117
  mysql->field_count= 0;
118
  net_clear_error(net);
unknown's avatar
unknown committed
119
  thd->current_stmt= stmt;
120

121
  thd->store_globals();				// Fix if more than one connect
unknown's avatar
unknown committed
122 123 124 125 126 127
  /* 
     We have to call free_old_query before we start to fill mysql->fields 
     for new query. In the case of embedded server we collect field data
     during query execution (not during data retrieval as it is in remote
     client). So we have to call free_old_query here
  */
unknown's avatar
SCRUM  
unknown committed
128
  free_old_query(mysql);
unknown's avatar
unknown committed
129 130 131 132

  thd->extra_length= arg_length;
  thd->extra_data= (char *)arg;
  if (header)
unknown's avatar
SCRUM  
unknown committed
133 134 135 136 137
  {
    arg= header;
    arg_length= header_length;
  }

138
  result= dispatch_command(command, thd, (char *) arg, arg_length);
139
  thd->cur_data= 0;
140
  thd->mysys_var= NULL;
unknown's avatar
unknown committed
141

unknown's avatar
SCRUM  
unknown committed
142
  if (!skip_check)
143
    result= thd->is_error() ? -1 : 0;
144

145 146
  thd->mysys_var= 0;

147
#if defined(ENABLED_PROFILING)
148 149
  thd->profiling.finish_current_query();
#endif
150
  return result;
151 152
}

153
static void emb_flush_use_result(MYSQL *mysql, my_bool)
unknown's avatar
unknown committed
154
{
155 156
  THD *thd= (THD*) mysql->thd;
  if (thd->cur_data)
unknown's avatar
unknown committed
157
  {
158 159 160 161 162 163 164
    free_rows(thd->cur_data);
    thd->cur_data= 0;
  }
  else if (thd->first_data)
  {
    MYSQL_DATA *data= thd->first_data;
    thd->first_data= data->embedded_info->next;
unknown's avatar
unknown committed
165 166 167 168
    free_rows(data);
  }
}

169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184

/*
  reads dataset from the next query result

  SYNOPSIS
  emb_read_rows()
  mysql		connection handle
  other parameters are not used

  NOTES
    It just gets next MYSQL_DATA from the result's queue

  RETURN
    pointer to MYSQL_DATA with the coming recordset
*/

unknown's avatar
unknown committed
185
static MYSQL_DATA *
unknown's avatar
SCRUM  
unknown committed
186
emb_read_rows(MYSQL *mysql, MYSQL_FIELD *mysql_fields __attribute__((unused)),
unknown's avatar
SCRUM  
unknown committed
187
	      unsigned int fields __attribute__((unused)))
unknown's avatar
SCRUM  
unknown committed
188
{
189 190 191
  MYSQL_DATA *result= ((THD*)mysql->thd)->cur_data;
  ((THD*)mysql->thd)->cur_data= 0;
  if (result->embedded_info->last_errno)
unknown's avatar
SCRUM  
unknown committed
192
  {
193 194 195 196
    embedded_get_error(mysql, result);
    return NULL;
  }
  *result->embedded_info->prev_ptr= NULL;
unknown's avatar
SCRUM  
unknown committed
197 198 199
  return result;
}

200

unknown's avatar
unknown committed
201
static MYSQL_FIELD *emb_list_fields(MYSQL *mysql)
unknown's avatar
SCRUM  
unknown committed
202
{
203 204 205 206 207 208
  MYSQL_DATA *res;
  if (emb_read_query_result(mysql))
    return 0;
  res= ((THD*) mysql->thd)->cur_data;
  ((THD*) mysql->thd)->cur_data= 0;
  mysql->field_alloc= res->alloc;
209
  my_free(res,MYF(0));
210
  mysql->status= MYSQL_STATUS_READY;
unknown's avatar
SCRUM  
unknown committed
211 212 213
  return mysql->fields;
}

unknown's avatar
unknown committed
214
static my_bool emb_read_prepare_result(MYSQL *mysql, MYSQL_STMT *stmt)
unknown's avatar
SCRUM  
unknown committed
215
{
216 217 218
  THD *thd= (THD*) mysql->thd;
  MYSQL_DATA *res;

unknown's avatar
SCRUM  
unknown committed
219 220
  stmt->stmt_id= thd->client_stmt_id;
  stmt->param_count= thd->client_param_count;
221
  stmt->field_count= 0;
Marc Alff's avatar
Marc Alff committed
222
  mysql->warning_count= thd->warning_info->statement_warn_count();
unknown's avatar
SCRUM  
unknown committed
223

224
  if (thd->first_data)
unknown's avatar
SCRUM  
unknown committed
225
  {
226 227 228 229 230 231
    if (emb_read_query_result(mysql))
      return 1;
    stmt->field_count= mysql->field_count;
    mysql->status= MYSQL_STATUS_READY;
    res= thd->cur_data;
    thd->cur_data= NULL;
unknown's avatar
SCRUM  
unknown committed
232 233 234 235
    if (!(mysql->server_status & SERVER_STATUS_AUTOCOMMIT))
      mysql->server_status|= SERVER_STATUS_IN_TRANS;

    stmt->fields= mysql->fields;
236
    stmt->mem_root= res->alloc;
unknown's avatar
SCRUM  
unknown committed
237
    mysql->fields= NULL;
238
    my_free(res,MYF(0));
unknown's avatar
SCRUM  
unknown committed
239
  }
unknown's avatar
SCRUM  
unknown committed
240

unknown's avatar
SCRUM  
unknown committed
241 242 243 244 245 246 247 248 249
  return 0;
}

/**************************************************************************
  Get column lengths of the current row
  If one uses mysql_use_result, res->lengths contains the length information,
  else the lengths are calculated from the offset between pointers.
**************************************************************************/

unknown's avatar
unknown committed
250 251
static void emb_fetch_lengths(ulong *to, MYSQL_ROW column,
			      unsigned int field_count)
unknown's avatar
SCRUM  
unknown committed
252 253 254 255 256 257 258
{ 
  MYSQL_ROW end;

  for (end=column + field_count; column != end ; column++,to++)
    *to= *column ? *(uint *)((*column) - sizeof(uint)) : 0;
}

259
static my_bool emb_read_query_result(MYSQL *mysql)
unknown's avatar
SCRUM  
unknown committed
260
{
261 262 263 264 265 266 267 268 269 270 271 272 273 274
  THD *thd= (THD*) mysql->thd;
  MYSQL_DATA *res= thd->first_data;
  DBUG_ASSERT(!thd->cur_data);
  thd->first_data= res->embedded_info->next;
  if (res->embedded_info->last_errno &&
      !res->embedded_info->fields_list)
  {
    embedded_get_error(mysql, res);
    return 1;
  }

  mysql->warning_count= res->embedded_info->warning_count;
  mysql->server_status= res->embedded_info->server_status;
  mysql->field_count= res->fields;
275 276 277 278 279
  if (!(mysql->fields= res->embedded_info->fields_list))
  {
    mysql->affected_rows= res->embedded_info->affected_rows;
    mysql->insert_id= res->embedded_info->insert_id;
  }
280
  net_clear_error(&mysql->net);
281 282 283 284 285 286 287
  mysql->info= 0;

  if (res->embedded_info->info[0])
  {
    strmake(mysql->info_buffer, res->embedded_info->info, MYSQL_ERRMSG_SIZE-1);
    mysql->info= mysql->info_buffer;
  }
unknown's avatar
SCRUM  
unknown committed
288

289 290
  if (res->embedded_info->fields_list)
  {
unknown's avatar
SCRUM  
unknown committed
291
    mysql->status=MYSQL_STATUS_GET_RESULT;
292 293 294
    thd->cur_data= res;
  }
  else
295
    my_free(res, MYF(0));
unknown's avatar
SCRUM  
unknown committed
296 297 298 299

  return 0;
}

unknown's avatar
unknown committed
300
static int emb_stmt_execute(MYSQL_STMT *stmt)
unknown's avatar
SCRUM  
unknown committed
301 302
{
  DBUG_ENTER("emb_stmt_execute");
303
  uchar header[5];
304
  THD *thd;
305
  my_bool res;
306

307
  int4store(header, stmt->stmt_id);
308
  header[4]= (uchar) stmt->flags;
309
  thd= (THD*)stmt->mysql->thd;
unknown's avatar
SCRUM  
unknown committed
310
  thd->client_param_count= stmt->param_count;
unknown's avatar
SCRUM:  
unknown committed
311
  thd->client_params= stmt->params;
312

313
  res= test(emb_advanced_command(stmt->mysql, COM_STMT_EXECUTE, 0, 0,
314
                                 header, sizeof(header), 1, stmt) ||
315
            emb_read_query_result(stmt->mysql));
316 317
  stmt->affected_rows= stmt->mysql->affected_rows;
  stmt->insert_id= stmt->mysql->insert_id;
318
  stmt->server_status= stmt->mysql->server_status;
319
  if (res)
unknown's avatar
SCRUM  
unknown committed
320 321
  {
    NET *net= &stmt->mysql->net;
322
    set_stmt_errmsg(stmt, net);
unknown's avatar
SCRUM  
unknown committed
323 324 325 326 327
    DBUG_RETURN(1);
  }
  DBUG_RETURN(0);
}

328
int emb_read_binary_rows(MYSQL_STMT *stmt)
unknown's avatar
SCRUM:  
unknown committed
329
{
330 331
  MYSQL_DATA *data;
  if (!(data= emb_read_rows(stmt->mysql, 0, 0)))
unknown's avatar
unknown committed
332
  {
333
    set_stmt_errmsg(stmt, &stmt->mysql->net);
334
    return 1;
unknown's avatar
unknown committed
335
  }
336 337
  stmt->result= *data;
  my_free((char *) data, MYF(0));
338
  set_stmt_errmsg(stmt, &stmt->mysql->net);
339
  return 0;
unknown's avatar
SCRUM:  
unknown committed
340 341
}

342 343 344 345 346 347 348 349 350 351
int emb_read_rows_from_cursor(MYSQL_STMT *stmt)
{
  MYSQL *mysql= stmt->mysql;
  THD *thd= (THD*) mysql->thd;
  MYSQL_DATA *res= thd->first_data;
  DBUG_ASSERT(!thd->first_data->embedded_info->next);
  thd->first_data= 0;
  if (res->embedded_info->last_errno)
  {
    embedded_get_error(mysql, res);
352
    set_stmt_errmsg(stmt, &mysql->net);
353 354 355 356 357 358
    return 1;
  }

  thd->cur_data= res;
  mysql->warning_count= res->embedded_info->warning_count;
  mysql->server_status= res->embedded_info->server_status;
359
  net_clear_error(&mysql->net);
360 361 362 363

  return emb_read_binary_rows(stmt);
}

unknown's avatar
unknown committed
364
int emb_unbuffered_fetch(MYSQL *mysql, char **row)
unknown's avatar
SCRUM  
unknown committed
365
{
366 367 368 369 370 371 372 373
  THD *thd= (THD*) mysql->thd;
  MYSQL_DATA *data= thd->cur_data;
  if (data && data->embedded_info->last_errno)
  {
    embedded_get_error(mysql, data);
    thd->cur_data= 0;
    return 1;
  }
unknown's avatar
SCRUM  
unknown committed
374 375 376 377 378
  if (!data || !data->data)
  {
    *row= NULL;
    if (data)
    {
379 380
      thd->cur_data= thd->first_data;
      thd->first_data= data->embedded_info->next;
unknown's avatar
SCRUM  
unknown committed
381 382 383 384 385 386 387 388 389 390 391
      free_rows(data);
    }
  }
  else
  {
    *row= (char *)data->data->data;
    data->data= data->data->next;
  }
  return 0;
}

unknown's avatar
unknown committed
392
static void emb_free_embedded_thd(MYSQL *mysql)
unknown's avatar
SCRUM  
unknown committed
393 394
{
  THD *thd= (THD*)mysql->thd;
395
  thd->clear_data_list();
unknown's avatar
unknown committed
396
  thread_count--;
397
  thd->store_globals();
398
  thd->unlink();
unknown's avatar
SCRUM  
unknown committed
399
  delete thd;
400
  my_pthread_setspecific_ptr(THR_THD,  0);
401
  mysql->thd=0;
unknown's avatar
SCRUM  
unknown committed
402 403
}

unknown's avatar
Rename:  
unknown committed
404
static const char * emb_read_statistics(MYSQL *mysql)
unknown's avatar
unknown committed
405 406
{
  THD *thd= (THD*)mysql->thd;
Marc Alff's avatar
Marc Alff committed
407
  return thd->is_error() ? thd->stmt_da->message() : "";
unknown's avatar
unknown committed
408 409
}

unknown's avatar
unknown committed
410

411
static MYSQL_RES * emb_store_result(MYSQL *mysql)
unknown's avatar
unknown committed
412 413 414 415
{
  return mysql_store_result(mysql);
}

416 417 418 419 420 421 422
int emb_read_change_user_result(MYSQL *mysql, 
				char *buff __attribute__((unused)),
				const char *passwd __attribute__((unused)))
{
  return mysql_errno(mysql);
}

unknown's avatar
SCRUM  
unknown committed
423 424
MYSQL_METHODS embedded_methods= 
{
425
  emb_read_query_result,
unknown's avatar
SCRUM  
unknown committed
426 427
  emb_advanced_command,
  emb_read_rows,
428
  emb_store_result,
unknown's avatar
SCRUM  
unknown committed
429
  emb_fetch_lengths, 
unknown's avatar
unknown committed
430
  emb_flush_use_result,
unknown's avatar
SCRUM  
unknown committed
431
  emb_list_fields,
unknown's avatar
SCRUM  
unknown committed
432
  emb_read_prepare_result,
unknown's avatar
SCRUM:  
unknown committed
433
  emb_stmt_execute,
unknown's avatar
SCRUM  
unknown committed
434
  emb_read_binary_rows,
unknown's avatar
SCRUM  
unknown committed
435
  emb_unbuffered_fetch,
unknown's avatar
unknown committed
436
  emb_free_embedded_thd,
unknown's avatar
Rename:  
unknown committed
437
  emb_read_statistics,
438 439 440
  emb_read_query_result,
  emb_read_change_user_result,
  emb_read_rows_from_cursor
unknown's avatar
SCRUM  
unknown committed
441 442
};

443 444 445 446 447 448 449 450 451 452 453 454 455 456 457 458 459 460 461 462 463 464 465 466 467 468
/*
  Make a copy of array and the strings array points to
*/

char **copy_arguments(int argc, char **argv)
{
  uint length= 0;
  char **from, **res, **end= argv+argc;

  for (from=argv ; from != end ; from++)
    length+= strlen(*from);

  if ((res= (char**) my_malloc(sizeof(argv)*(argc+1)+length+argc,
			       MYF(MY_WME))))
  {
    char **to= res, *to_str= (char*) (res+argc+1);
    for (from=argv ; from != end ;)
    {
      *to++= to_str;
      to_str= strmov(to_str, *from++)+1;
    }
    *to= 0;					// Last ptr should be null
  }
  return res;
}

unknown's avatar
unknown committed
469
char **		copy_arguments_ptr= 0;
unknown's avatar
unknown committed
470

471
int init_embedded_server(int argc, char **argv, char **groups)
unknown's avatar
unknown committed
472
{
unknown's avatar
unknown committed
473 474 475 476
  /*
    This mess is to allow people to call the init function without
    having to mess with a fake argv
   */
unknown's avatar
unknown committed
477 478 479 480 481
  int *argcp;
  char ***argvp;
  int fake_argc = 1;
  char *fake_argv[] = { (char *)"", 0 };
  const char *fake_groups[] = { "server", "embedded", 0 };
482
  my_bool acl_error;
unknown's avatar
unknown committed
483 484
  if (argc)
  {
unknown's avatar
unknown committed
485 486
    argcp= &argc;
    argvp= (char***) &argv;
unknown's avatar
unknown committed
487 488 489
  }
  else
  {
unknown's avatar
unknown committed
490 491
    argcp= &fake_argc;
    argvp= (char ***) &fake_argv;
unknown's avatar
unknown committed
492 493
  }
  if (!groups)
unknown's avatar
unknown committed
494
    groups= (char**) fake_groups;
unknown's avatar
unknown committed
495

496
  my_progname= (char *)"mysql_embedded";
unknown's avatar
unknown committed
497

498 499 500 501 502 503
  /*
    Perform basic logger initialization logger. Should be called after
    MY_INIT, as it initializes mutexes. Log tables are inited later.
  */
  logger.init_base();

Marc Alff's avatar
Marc Alff committed
504 505 506 507 508 509 510 511 512 513 514 515 516
  orig_argc= *argcp;
  orig_argv= *argvp;
  load_defaults("my", (const char **)groups, argcp, argvp);
  defaults_argc= *argcp;
  defaults_argv= *argvp;
  remaining_argc= argc;
  remaining_argv= argv;

  /* Must be initialized early for comparison of options name */
  system_charset_info= &my_charset_utf8_general_ci;
  sys_var_init();

  if (init_common_variables())
unknown's avatar
unknown committed
517 518 519 520
  {
    mysql_server_end();
    return 1;
  }
521 522 523

  mysql_data_home= mysql_real_data_home;
  mysql_data_home_len= mysql_real_data_home_len;
unknown's avatar
unknown committed
524 525 526 527 528 529 530 531 532 533 534 535 536 537 538 539 540 541 542 543 544
    
  /* Get default temporary directory */
  opt_mysql_tmpdir=getenv("TMPDIR");	/* Use this if possible */
#if defined( __WIN__) || defined(OS2)
  if (!opt_mysql_tmpdir)
    opt_mysql_tmpdir=getenv("TEMP");
  if (!opt_mysql_tmpdir)
    opt_mysql_tmpdir=getenv("TMP");
#endif
  if (!opt_mysql_tmpdir || !opt_mysql_tmpdir[0])
    opt_mysql_tmpdir=(char*) P_tmpdir;		/* purecov: inspected */

  umask(((~my_umask) & 0666));
  if (init_server_components())
  {
    mysql_server_end();
    return 1;
  }

  error_handler_hook = my_message_sql;

545
  acl_error= 0;
unknown's avatar
SCRUM:  
unknown committed
546
#ifndef NO_EMBEDDED_ACCESS_CHECKS
547
  if (!(acl_error= acl_init(opt_noacl)) &&
548
      !opt_noacl)
549
    (void) grant_init();
550 551
#endif
  if (acl_error || my_tz_init((THD *)0, default_tz_name, opt_bootstrap))
unknown's avatar
unknown committed
552 553 554 555
  {
    mysql_server_end();
    return 1;
  }
unknown's avatar
SCRUM:  
unknown committed
556

unknown's avatar
unknown committed
557 558 559 560
  init_max_user_conn();
  init_update_queries();

#ifdef HAVE_DLOPEN
unknown's avatar
SCRUM:  
unknown committed
561
#ifndef NO_EMBEDDED_ACCESS_CHECKS
unknown's avatar
unknown committed
562
  if (!opt_noacl)
unknown's avatar
SCRUM:  
unknown committed
563
#endif
unknown's avatar
unknown committed
564 565 566 567 568
    udf_init();
#endif

  (void) thr_setconcurrency(concurrency);	// 10 by default

569
  start_handle_manager();
unknown's avatar
unknown committed
570

571 572 573 574 575
  // FIXME initialize binlog_filter and rpl_filter if not already done
  //       corresponding delete is in clean_up()
  if(!binlog_filter) binlog_filter = new Rpl_filter;
  if(!rpl_filter) rpl_filter = new Rpl_filter;

unknown's avatar
unknown committed
576 577 578 579 580 581 582 583 584
  if (opt_init_file)
  {
    if (read_init_file(opt_init_file))
    {
      mysql_server_end();
      return 1;
    }
  }

585
  execute_ddl_log_recovery();
unknown's avatar
unknown committed
586 587 588
  return 0;
}

589
void end_embedded_server()
590
{
unknown's avatar
unknown committed
591 592
  my_free((char*) copy_arguments_ptr, MYF(MY_ALLOW_ZERO_PTR));
  copy_arguments_ptr=0;
unknown's avatar
unknown committed
593
  clean_up(0);
unknown's avatar
unknown committed
594 595
}

596

597
void init_embedded_mysql(MYSQL *mysql, int client_flag)
598
{
599
  THD *thd = (THD *)mysql->thd;
600
  thd->mysql= mysql;
unknown's avatar
unknown committed
601
  mysql->server_version= server_version;
602
  init_alloc_root(&mysql->field_alloc, 8192, 0);
603
}
604

605 606 607 608 609 610 611 612 613 614 615
/**
  @brief Initialize a new THD for a connection in the embedded server

  @param client_flag  Client capabilities which this thread supports
  @return pointer to the created THD object

  @todo
  This function copies code from several places in the server, including
  create_new_thread(), and prepare_new_connection_state().  This should
  be refactored to avoid code duplication.
*/
616
void *create_embedded_thd(int client_flag)
617 618
{
  THD * thd= new THD;
unknown's avatar
unknown committed
619
  thd->thread_id= thd->variables.pseudo_thread_id= thread_id++;
620

621
  thd->thread_stack= (char*) &thd;
622 623 624
  if (thd->store_globals())
  {
    fprintf(stderr,"store_globals failed.\n");
625
    goto err;
626
  }
627
  lex_start(thd);
628

unknown's avatar
unknown committed
629
  /* TODO - add init_connect command execution */
630

631
  if (thd->variables.max_join_size == HA_POS_ERROR)
632
    thd->variables.option_bits |= OPTION_BIG_SELECTS;
633 634 635 636
  thd->proc_info=0;				// Remove 'login'
  thd->command=COM_SLEEP;
  thd->version=refresh_version;
  thd->set_time();
637
  thd->init_for_queries();
638
  thd->client_capabilities= client_flag;
639
  thd->real_id= pthread_self();
640

641 642
  thd->db= NULL;
  thd->db_length= 0;
unknown's avatar
SCRUM:  
unknown committed
643
#ifndef NO_EMBEDDED_ACCESS_CHECKS
644 645
  thd->security_ctx->db_access= DB_ACLS;
  thd->security_ctx->master_access= ~NO_ACCESS;
unknown's avatar
SCRUM:  
unknown committed
646
#endif
647 648 649 650
  thd->cur_data= 0;
  thd->first_data= 0;
  thd->data_tail= &thd->first_data;
  bzero((char*) &thd->net, sizeof(thd->net));
unknown's avatar
SCRUM  
unknown committed
651

unknown's avatar
unknown committed
652
  thread_count++;
653
  threads.append(thd);
654
  thd->mysys_var= 0;
655
  return thd;
656 657 658
err:
  delete(thd);
  return NULL;
659
}
660

661

662
#ifdef NO_EMBEDDED_ACCESS_CHECKS
663
int check_embedded_connection(MYSQL *mysql, const char *db)
664
{
665
  int result;
666
  THD *thd= (THD*)mysql->thd;
667 668
  thd_init_client_charset(thd, mysql->charset->number);
  thd->update_charset();
unknown's avatar
unknown committed
669
  Security_context *sctx= thd->security_ctx;
670 671
  sctx->host_or_ip= sctx->host= (char*) my_localhost;
  strmake(sctx->priv_host, (char*) my_localhost,  MAX_HOSTNAME-1);
672
  sctx->priv_user= sctx->user= my_strdup(mysql->user, MYF(0));
673
  result= check_user(thd, COM_CONNECT, NULL, 0, db, true);
674
  thd->protocol->end_statement();
675 676
  emb_read_query_result(mysql);
  return result;
677 678 679
}

#else
680
int check_embedded_connection(MYSQL *mysql, const char *db)
unknown's avatar
SCRUM:  
unknown committed
681 682
{
  THD *thd= (THD*)mysql->thd;
683
  Security_context *sctx= thd->security_ctx;
unknown's avatar
SCRUM:  
unknown committed
684 685 686 687
  int result;
  char scramble_buff[SCRAMBLE_LENGTH];
  int passwd_len;

688 689
  thd_init_client_charset(thd, mysql->charset->number);
  thd->update_charset();
690 691
  if (mysql->options.client_ip)
  {
692 693
    sctx->host= my_strdup(mysql->options.client_ip, MYF(0));
    sctx->ip= my_strdup(sctx->host, MYF(0));
694 695
  }
  else
696 697
    sctx->host= (char*)my_localhost;
  sctx->host_or_ip= sctx->host;
unknown's avatar
SCRUM:  
unknown committed
698

699
  if (acl_check_host(sctx->host, sctx->ip))
unknown's avatar
SCRUM:  
unknown committed
700 701 702 703 704
  {
    result= ER_HOST_NOT_PRIVILEGED;
    goto err;
  }

705
  sctx->user= my_strdup(mysql->user, MYF(0));
unknown's avatar
SCRUM:  
unknown committed
706 707 708 709 710 711 712 713 714 715 716
  if (mysql->passwd && mysql->passwd[0])
  {
    memset(thd->scramble, 55, SCRAMBLE_LENGTH); // dummy scramble
    thd->scramble[SCRAMBLE_LENGTH]= 0;
    scramble(scramble_buff, thd->scramble, mysql->passwd);
    passwd_len= SCRAMBLE_LENGTH;
  }
  else
    passwd_len= 0;

  if((result= check_user(thd, COM_CONNECT, 
717
			 scramble_buff, passwd_len, db, true)))
unknown's avatar
SCRUM:  
unknown committed
718 719 720 721 722 723
     goto err;

  return 0;
err:
  {
    NET *net= &mysql->net;
Marc Alff's avatar
Marc Alff committed
724 725
    strmake(net->last_error, thd->stmt_da->message(),
            sizeof(net->last_error)-1);
726
    memcpy(net->sqlstate,
Marc Alff's avatar
Marc Alff committed
727
           mysql_errno_to_sqlstate(thd->stmt_da->sql_errno()),
728
           sizeof(net->sqlstate)-1);
unknown's avatar
SCRUM:  
unknown committed
729 730 731 732 733
  }
  return result;
}
#endif

734
C_MODE_END
735

unknown's avatar
unknown committed
736 737 738 739 740 741 742 743 744 745 746 747 748 749 750
void THD::clear_data_list()
{
  while (first_data)
  {
    MYSQL_DATA *data= first_data;
    first_data= data->embedded_info->next;
    free_rows(data);
  }
  data_tail= &first_data;
  free_rows(cur_data);
  cur_data= 0;
}

void THD::clear_error()
{
Marc Alff's avatar
Marc Alff committed
751 752
  if (stmt_da->is_error())
    stmt_da->reset_diagnostics_area();
unknown's avatar
unknown committed
753 754
}

755 756 757 758 759 760 761 762 763 764 765 766 767
static char *dup_str_aux(MEM_ROOT *root, const char *from, uint length,
			 CHARSET_INFO *fromcs, CHARSET_INFO *tocs)
{
  uint32 dummy32;
  uint dummy_err;
  char *result;

  /* 'tocs' is set 0 when client issues SET character_set_results=NULL */
  if (tocs && String::needs_conversion(0, fromcs, tocs, &dummy32))
  {
    uint new_len= (tocs->mbmaxlen * length) / fromcs->mbminlen + 1;
    result= (char *)alloc_root(root, new_len);
    length= copy_and_convert(result, new_len,
unknown's avatar
unknown committed
768
                             tocs, from, length, fromcs, &dummy_err);
769 770 771 772 773 774 775 776 777 778 779 780
  }
  else
  {
    result= (char *)alloc_root(root, length + 1);
    memcpy(result, from, length);
  }

  result[length]= 0;
  return result;
}


781 782 783 784 785 786 787 788 789 790 791 792 793 794 795 796 797 798 799 800 801 802 803 804 805 806 807 808 809 810 811 812 813 814
/*
  creates new result and hooks it to the list

  SYNOPSIS
  alloc_new_dataset()

  NOTES
    allocs the MYSQL_DATA + embedded_query_result couple
    to store the next query result,
    links these two and attach it to the THD::data_tail

  RETURN
    pointer to the newly created query result
*/

MYSQL_DATA *THD::alloc_new_dataset()
{
  MYSQL_DATA *data;
  struct embedded_query_result *emb_data;
  if (!my_multi_malloc(MYF(MY_WME | MY_ZEROFILL),
                       &data, sizeof(*data),
                       &emb_data, sizeof(*emb_data),
                       NULL))
    return NULL;

  emb_data->prev_ptr= &data->data;
  cur_data= data;
  *data_tail= data;
  data_tail= &emb_data->next;
  data->embedded_info= emb_data;
  return data;
}


815 816 817
/**
  Stores server_status and warning_count in the current
  query result structures.
818

819
  @param thd            current thread
820

821
  @note Should be called after we get the recordset-result.
822 823
*/

824
static
825
bool
Marc Alff's avatar
Marc Alff committed
826
write_eof_packet(THD *thd, uint server_status, uint statement_warn_count)
827
{
828
  if (!thd->mysql)            // bootstrap file handling
829
    return FALSE;
830 831 832 833 834 835 836
  /*
    The following test should never be true, but it's better to do it
    because if 'is_fatal_error' is set the server is not going to execute
    other queries (see the if test in dispatch_command / COM_QUERY)
  */
  if (thd->is_fatal_error)
    thd->server_status&= ~SERVER_MORE_RESULTS_EXISTS;
837
  thd->cur_data->embedded_info->server_status= server_status;
838 839 840 841 842
  /*
    Don't send warn count during SP execution, as the warn_list
    is cleared between substatements, and mysqltest gets confused
  */
  thd->cur_data->embedded_info->warning_count=
Marc Alff's avatar
Marc Alff committed
843
    (thd->spcont ? 0 : min(statement_warn_count, 65535));
844
  return FALSE;
845 846 847 848 849 850 851 852 853 854 855 856 857 858 859 860 861 862 863 864 865 866 867 868 869 870 871 872 873 874
}


/*
  allocs new query result and initialises Protocol::alloc

  SYNOPSIS
  Protocol::begin_dataset()

  RETURN
    0 if success
    1 if memory allocation failed
*/

int Protocol::begin_dataset()
{
  MYSQL_DATA *data= thd->alloc_new_dataset();
  if (!data)
    return 1;
  alloc= &data->alloc;
  init_alloc_root(alloc,8192,0);	/* Assume rowlength < 8192 */
  alloc->min_malloc=sizeof(MYSQL_ROWS);
  return 0;
}


/*
  remove last row of current recordset

  SYNOPSIS
unknown's avatar
unknown committed
875
  Protocol_text::remove_last_row()
876 877 878 879 880 881 882

  NOTES
    does the loop from the beginning of the current recordset to
    the last record and cuts it off.
    Not supposed to be frequently called.
*/

unknown's avatar
unknown committed
883
void Protocol_text::remove_last_row()
884 885 886
{
  MYSQL_DATA *data= thd->cur_data;
  MYSQL_ROWS **last_row_hook= &data->data;
887
  my_ulonglong count= data->rows;
unknown's avatar
unknown committed
888
  DBUG_ENTER("Protocol_text::remove_last_row");
889 890 891 892 893 894 895 896 897 898 899
  while (--count)
    last_row_hook= &(*last_row_hook)->next;

  *last_row_hook= 0;
  data->embedded_info->prev_ptr= last_row_hook;
  data->rows--;

  DBUG_VOID_RETURN;
}


900
bool Protocol::send_result_set_metadata(List<Item> *list, uint flags)
unknown's avatar
unknown committed
901 902 903
{
  List_iterator_fast<Item> it(*list);
  Item                     *item;
unknown's avatar
SCRUM  
unknown committed
904 905
  MYSQL_FIELD              *client_field;
  MEM_ROOT                 *field_alloc;
906 907
  CHARSET_INFO             *thd_cs= thd->variables.character_set_results;
  CHARSET_INFO             *cs= system_charset_info;
908
  MYSQL_DATA               *data;
909
  DBUG_ENTER("send_result_set_metadata");
unknown's avatar
unknown committed
910

911
  if (!thd->mysql)            // bootstrap file handling
unknown's avatar
unknown committed
912 913
    DBUG_RETURN(0);

914 915 916 917 918 919 920 921 922
  if (begin_dataset())
    goto err;

  data= thd->cur_data;
  data->fields= field_count= list->elements;
  field_alloc= &data->alloc;

  if (!(client_field= data->embedded_info->fields_list= 
	(MYSQL_FIELD*)alloc_root(field_alloc, sizeof(MYSQL_FIELD)*field_count)))
unknown's avatar
unknown committed
923 924 925 926 927 928 929
    goto err;

  while ((item= it++))
  {
    Send_field server_field;
    item->make_field(&server_field);

930 931 932 933
    /* Keep things compatible for old clients */
    if (server_field.type == MYSQL_TYPE_VARCHAR)
      server_field.type= MYSQL_TYPE_VAR_STRING;

934
    client_field->db= dup_str_aux(field_alloc, server_field.db_name,
unknown's avatar
unknown committed
935
                                  strlen(server_field.db_name), cs, thd_cs);
936
    client_field->table= dup_str_aux(field_alloc, server_field.table_name,
unknown's avatar
unknown committed
937
                                     strlen(server_field.table_name), cs, thd_cs);
938
    client_field->name= dup_str_aux(field_alloc, server_field.col_name,
unknown's avatar
unknown committed
939
                                    strlen(server_field.col_name), cs, thd_cs);
940
    client_field->org_table= dup_str_aux(field_alloc, server_field.org_table_name,
unknown's avatar
unknown committed
941
                                         strlen(server_field.org_table_name), cs, thd_cs);
942
    client_field->org_name= dup_str_aux(field_alloc, server_field.org_col_name,
unknown's avatar
unknown committed
943
                                        strlen(server_field.org_col_name), cs, thd_cs);
944 945 946 947 948 949 950 951
    if (item->collation.collation == &my_charset_bin || thd_cs == NULL)
    {
      /* No conversion */
      client_field->charsetnr= server_field.charsetnr;
      client_field->length= server_field.length;
    }
    else
    {
952
      uint max_char_len;
953 954
      /* With conversion */
      client_field->charsetnr= thd_cs->number;
955 956 957 958 959
      max_char_len= (server_field.type >= (int) MYSQL_TYPE_TINY_BLOB &&
                     server_field.type <= (int) MYSQL_TYPE_BLOB) ?
                     server_field.length / item->collation.collation->mbminlen :
                     server_field.length / item->collation.collation->mbmaxlen;
      client_field->length= max_char_len * thd_cs->mbmaxlen;
960
    }
unknown's avatar
unknown committed
961 962 963
    client_field->type=   server_field.type;
    client_field->flags= server_field.flags;
    client_field->decimals= server_field.decimals;
964 965 966 967 968
    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);
unknown's avatar
SCRUM  
unknown committed
969

970
    client_field->catalog= dup_str_aux(field_alloc, "def", 3, cs, thd_cs);
unknown's avatar
SCRUM  
unknown committed
971
    client_field->catalog_length= 3;
unknown's avatar
unknown committed
972

973
    if (IS_NUM(client_field->type))
unknown's avatar
unknown committed
974 975
      client_field->flags|= NUM_FLAG;

976
    if (flags & (int) Protocol::SEND_DEFAULTS)
unknown's avatar
unknown committed
977 978 979 980 981
    {
      char buff[80];
      String tmp(buff, sizeof(buff), default_charset_info), *res;

      if (!(res=item->val_str(&tmp)))
unknown's avatar
SCRUM  
unknown committed
982 983
      {
	client_field->def_length= 0;
984
	client_field->def= strmake_root(field_alloc, "",0);
unknown's avatar
SCRUM  
unknown committed
985
      }
unknown's avatar
unknown committed
986
      else
unknown's avatar
SCRUM  
unknown committed
987
      {
988
	client_field->def_length= res->length();
989 990
	client_field->def= strmake_root(field_alloc, res->ptr(),
					client_field->def_length);
unknown's avatar
SCRUM  
unknown committed
991
      }
unknown's avatar
unknown committed
992 993 994 995 996 997
    }
    else
      client_field->def=0;
    client_field->max_length= 0;
    ++client_field;
  }
998 999

  if (flags & SEND_EOF)
Marc Alff's avatar
Marc Alff committed
1000 1001
    write_eof_packet(thd, thd->server_status,
                     thd->warning_info->statement_warn_count());
unknown's avatar
unknown committed
1002

1003
  DBUG_RETURN(prepare_for_send(list->elements));
unknown's avatar
unknown committed
1004
 err:
unknown's avatar
unknown committed
1005
  my_error(ER_OUT_OF_RESOURCES, MYF(0));        /* purecov: inspected */
unknown's avatar
SCRUM  
unknown committed
1006
  DBUG_RETURN(1);				/* purecov: inspected */
unknown's avatar
unknown committed
1007 1008
}

unknown's avatar
SCRUM  
unknown committed
1009
bool Protocol::write()
unknown's avatar
unknown committed
1010
{
unknown's avatar
unknown committed
1011 1012 1013
  if (!thd->mysql)            // bootstrap file handling
    return false;

unknown's avatar
SCRUM  
unknown committed
1014 1015
  *next_field= 0;
  return false;
unknown's avatar
unknown committed
1016
}
1017

unknown's avatar
unknown committed
1018
bool Protocol_binary::write()
unknown's avatar
SCRUM:  
unknown committed
1019 1020
{
  MYSQL_ROWS *cur;
1021
  MYSQL_DATA *data= thd->cur_data;
unknown's avatar
SCRUM:  
unknown committed
1022 1023

  data->rows++;
1024 1025
  if (!(cur= (MYSQL_ROWS *)alloc_root(alloc,
                                      sizeof(MYSQL_ROWS)+packet->length())))
unknown's avatar
SCRUM:  
unknown committed
1026 1027 1028 1029 1030
  {
    my_error(ER_OUT_OF_RESOURCES,MYF(0));
    return true;
  }
  cur->data= (MYSQL_ROW)(((char *)cur) + sizeof(MYSQL_ROWS));
unknown's avatar
SCRUM  
unknown committed
1031
  memcpy(cur->data, packet->ptr()+1, packet->length()-1);
1032
  cur->length= packet->length();       /* To allow us to do sanity checks */
unknown's avatar
SCRUM:  
unknown committed
1033

1034 1035
  *data->embedded_info->prev_ptr= cur;
  data->embedded_info->prev_ptr= &cur->next;
unknown's avatar
SCRUM  
unknown committed
1036 1037
  cur->next= 0;
  
unknown's avatar
SCRUM:  
unknown committed
1038 1039 1040
  return false;
}

1041 1042 1043 1044 1045 1046 1047 1048 1049 1050 1051 1052 1053 1054 1055

/**
  Embedded library implementation of OK response.

  This function is used by the server to write 'OK' packet to
  the "network" when the server is compiled as an embedded library.
  Since there is no network in the embedded configuration,
  a different implementation is necessary.
  Instead of marshalling response parameters to a network representation
  and then writing it to the socket, here we simply copy the data to the
  corresponding client-side connection structures. 

  @sa Server implementation of net_send_ok in protocol.cc for
  description of the arguments.

1056 1057 1058
  @return
    @retval TRUE An error occurred
    @retval FALSE Success
1059 1060
*/

1061
bool
1062
net_send_ok(THD *thd,
Marc Alff's avatar
Marc Alff committed
1063 1064
            uint server_status, uint statement_warn_count,
            ulonglong affected_rows, ulonglong id, const char *message)
1065
{
1066
  DBUG_ENTER("emb_net_send_ok");
1067 1068
  MYSQL_DATA *data;
  MYSQL *mysql= thd->mysql;
1069

unknown's avatar
unknown committed
1070
  if (!mysql)            // bootstrap file handling
1071
    DBUG_RETURN(FALSE);
1072
  if (!(data= thd->alloc_new_dataset()))
Marc Alff's avatar
Marc Alff committed
1073
    DBUG_RETURN(TRUE);
1074 1075
  data->embedded_info->affected_rows= affected_rows;
  data->embedded_info->insert_id= id;
1076
  if (message)
1077 1078 1079
    strmake(data->embedded_info->info, message,
            sizeof(data->embedded_info->info)-1);

Marc Alff's avatar
Marc Alff committed
1080
  bool error= write_eof_packet(thd, server_status, statement_warn_count);
1081
  thd->cur_data= 0;
1082
  DBUG_RETURN(error);
1083 1084
}

1085 1086 1087 1088 1089 1090

/**
  Embedded library implementation of EOF response.

  @sa net_send_ok

1091 1092 1093
  @return
    @retval TRUE  An error occurred
    @retval FALSE Success
1094 1095
*/

1096
bool
Marc Alff's avatar
Marc Alff committed
1097
net_send_eof(THD *thd, uint server_status, uint statement_warn_count)
1098
{
Marc Alff's avatar
Marc Alff committed
1099
  bool error= write_eof_packet(thd, server_status, statement_warn_count);
1100
  thd->cur_data= 0;
1101
  return error;
1102 1103
}

1104

Marc Alff's avatar
Marc Alff committed
1105 1106
bool net_send_error_packet(THD *thd, uint sql_errno, const char *err,
                           const char *sqlstate)
1107
{
1108 1109 1110
  uint error;
  uchar converted_err[MYSQL_ERRMSG_SIZE];
  uint32 converted_err_len;
1111 1112 1113 1114 1115 1116
  MYSQL_DATA *data= thd->cur_data;
  struct embedded_query_result *ei;

  if (!thd->mysql)            // bootstrap file handling
  {
    fprintf(stderr, "ERROR: %d  %s\n", sql_errno, err);
1117
    return TRUE;
1118 1119 1120 1121
  }

  if (!data)
    data= thd->alloc_new_dataset();
1122

1123
  ei= data->embedded_info;
1124
  ei->last_errno= sql_errno;
1125 1126 1127 1128 1129 1130
  converted_err_len= convert_error_message((char*)converted_err,
                                           sizeof(converted_err),
                                           thd->variables.character_set_results,
                                           err, strlen(err),
                                           system_charset_info, &error);
  strmake(ei->info, (const char*) converted_err, sizeof(ei->info)-1);
Marc Alff's avatar
Marc Alff committed
1131
  strmov(ei->sqlstate, sqlstate);
1132
  ei->server_status= thd->server_status;
1133
  thd->cur_data= 0;
1134
  return FALSE;
1135 1136 1137
}


unknown's avatar
unknown committed
1138
void Protocol_text::prepare_for_resend()
unknown's avatar
SCRUM  
unknown committed
1139
{
unknown's avatar
SCRUM  
unknown committed
1140
  MYSQL_ROWS *cur;
1141
  MYSQL_DATA *data= thd->cur_data;
unknown's avatar
SCRUM  
unknown committed
1142 1143
  DBUG_ENTER("send_data");

unknown's avatar
unknown committed
1144 1145 1146
  if (!thd->mysql)            // bootstrap file handling
    DBUG_VOID_RETURN;

unknown's avatar
SCRUM  
unknown committed
1147
  data->rows++;
unknown's avatar
SCRUM  
unknown committed
1148 1149 1150 1151 1152 1153 1154
  if (!(cur= (MYSQL_ROWS *)alloc_root(alloc, sizeof(MYSQL_ROWS)+(field_count + 1) * sizeof(char *))))
  {
    my_error(ER_OUT_OF_RESOURCES,MYF(0));
    DBUG_VOID_RETURN;
  }
  cur->data= (MYSQL_ROW)(((char *)cur) + sizeof(MYSQL_ROWS));

1155 1156
  *data->embedded_info->prev_ptr= cur;
  data->embedded_info->prev_ptr= &cur->next;
unknown's avatar
SCRUM  
unknown committed
1157
  next_field=cur->data;
1158
  next_mysql_field= data->embedded_info->fields_list;
1159 1160 1161
#ifndef DBUG_OFF
  field_pos= 0;
#endif
1162

unknown's avatar
SCRUM  
unknown committed
1163 1164 1165
  DBUG_VOID_RETURN;
}

unknown's avatar
unknown committed
1166
bool Protocol_text::store_null()
unknown's avatar
SCRUM  
unknown committed
1167 1168 1169 1170 1171 1172
{
  *(next_field++)= NULL;
  ++next_mysql_field;
  return false;
}

1173
bool Protocol::net_store_data(const uchar *from, size_t length)
unknown's avatar
SCRUM  
unknown committed
1174
{
unknown's avatar
unknown committed
1175
  char *field_buf;
unknown's avatar
unknown committed
1176
  if (!thd->mysql)            // bootstrap file handling
1177
    return FALSE;
unknown's avatar
unknown committed
1178

1179 1180
  if (!(field_buf= (char*) alloc_root(alloc, length + sizeof(uint) + 1)))
    return TRUE;
unknown's avatar
unknown committed
1181 1182
  *(uint *)field_buf= length;
  *next_field= field_buf + sizeof(uint);
1183
  memcpy((uchar*) *next_field, from, length);
unknown's avatar
SCRUM  
unknown committed
1184
  (*next_field)[length]= 0;
unknown's avatar
SCRUM  
unknown committed
1185 1186 1187 1188
  if (next_mysql_field->max_length < length)
    next_mysql_field->max_length=length;
  ++next_field;
  ++next_mysql_field;
1189
  return FALSE;
unknown's avatar
SCRUM  
unknown committed
1190 1191
}

unknown's avatar
unknown committed
1192 1193 1194
#if defined(_MSC_VER) && _MSC_VER < 1400
#define vsnprintf _vsnprintf
#endif
1195

unknown's avatar
merging  
unknown committed
1196
int vprint_msg_to_log(enum loglevel level __attribute__((unused)),
1197 1198 1199 1200 1201
                       const char *format, va_list argsi)
{
  vsnprintf(mysql_server_last_error, sizeof(mysql_server_last_error),
           format, argsi);
  mysql_server_last_errno= CR_UNKNOWN_ERROR;
unknown's avatar
merging  
unknown committed
1202
  return 0;
1203
}
1204 1205 1206 1207 1208 1209 1210 1211 1212 1213 1214 1215 1216 1217 1218 1219 1220 1221 1222 1223 1224 1225 1226 1227


bool Protocol::net_store_data(const uchar *from, size_t length,
                              CHARSET_INFO *from_cs, CHARSET_INFO *to_cs)
{
  uint conv_length= to_cs->mbmaxlen * length / from_cs->mbminlen;
  uint dummy_error;
  char *field_buf;
  if (!thd->mysql)            // bootstrap file handling
    return false;

  if (!(field_buf= (char*) alloc_root(alloc, conv_length + sizeof(uint) + 1)))
    return true;
  *next_field= field_buf + sizeof(uint);
  length= copy_and_convert(*next_field, conv_length, to_cs,
                           (const char*) from, length, from_cs, &dummy_error);
  *(uint *) field_buf= length;
  (*next_field)[length]= 0;
  if (next_mysql_field->max_length < length)
    next_mysql_field->max_length= length;
  ++next_field;
  ++next_mysql_field;
  return false;
}