lib_sql.cc 30.5 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.
 *
14 15 16

  This code was modified by the MySQL team
*/
17

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"
{
monty@mysql.com's avatar
monty@mysql.com committed
28
  extern unsigned long max_allowed_packet, net_buffer_length;
29 30
}

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

33
C_MODE_START
serg@serg.mylan's avatar
serg@serg.mylan committed
34

35
#include <mysql.h>
hf@deer.(none)'s avatar
hf@deer.(none) committed
36
#undef ER
37
#include "errmsg.h"
hf@deer.(none)'s avatar
SCRUM  
hf@deer.(none) committed
38
#include <sql_common.h>
39
#include "embedded_priv.h"
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;
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
}

82
static my_bool
hf@deer.(none)'s avatar
SCRUM  
hf@deer.(none) 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;
hf@deer.(none)'s avatar
hf@deer.(none) 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 */
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;
hf@deer.(none)'s avatar
SCRUM  
hf@deer.(none) committed
117
  mysql->field_count= 0;
118
  net_clear_error(net);
119
  thd->current_stmt= stmt;
120

121
  thd->store_globals();				// Fix if more than one connect
122
  lex_start(thd);
hf@deer.(none)'s avatar
hf@deer.(none) committed
123 124 125 126 127 128
  /* 
     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
  */
hf@deer.(none)'s avatar
SCRUM  
hf@deer.(none) committed
129
  free_old_query(mysql);
hf@deer.(none)'s avatar
hf@deer.(none) committed
130 131 132 133

  thd->extra_length= arg_length;
  thd->extra_data= (char *)arg;
  if (header)
hf@deer.(none)'s avatar
SCRUM  
hf@deer.(none) committed
134 135 136 137 138
  {
    arg= header;
    arg_length= header_length;
  }

139
  result= dispatch_command(command, thd, (char *) arg, arg_length);
140
  thd->cur_data= 0;
monty@hundin.mysql.fi's avatar
monty@hundin.mysql.fi committed
141

hf@deer.(none)'s avatar
SCRUM  
hf@deer.(none) 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)
154
{
155 156
  THD *thd= (THD*) mysql->thd;
  if (thd->cur_data)
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;
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
*/

185
static MYSQL_DATA *
hf@deer.(none)'s avatar
SCRUM  
hf@deer.(none) committed
186
emb_read_rows(MYSQL *mysql, MYSQL_FIELD *mysql_fields __attribute__((unused)),
hf@deer.(none)'s avatar
SCRUM  
hf@deer.(none) committed
187
	      unsigned int fields __attribute__((unused)))
hf@deer.(none)'s avatar
SCRUM  
hf@deer.(none) 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)
hf@deer.(none)'s avatar
SCRUM  
hf@deer.(none) committed
192
  {
193 194 195 196
    embedded_get_error(mysql, result);
    return NULL;
  }
  *result->embedded_info->prev_ptr= NULL;
hf@deer.(none)'s avatar
SCRUM  
hf@deer.(none) committed
197 198 199
  return result;
}

200

201
static MYSQL_FIELD *emb_list_fields(MYSQL *mysql)
hf@deer.(none)'s avatar
SCRUM  
hf@deer.(none) 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;
hf@deer.(none)'s avatar
SCRUM  
hf@deer.(none) committed
211 212 213
  return mysql->fields;
}

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

hf@deer.(none)'s avatar
SCRUM  
hf@deer.(none) 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();
hf@deer.(none)'s avatar
SCRUM  
hf@deer.(none) committed
223

224
  if (thd->first_data)
hf@deer.(none)'s avatar
SCRUM  
hf@deer.(none) 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;
hf@deer.(none)'s avatar
SCRUM  
hf@deer.(none) 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;
hf@deer.(none)'s avatar
SCRUM  
hf@deer.(none) committed
237
    mysql->fields= NULL;
238
    my_free(res,MYF(0));
hf@deer.(none)'s avatar
SCRUM  
hf@deer.(none) committed
239
  }
hf@deer.(none)'s avatar
SCRUM  
hf@deer.(none) committed
240

hf@deer.(none)'s avatar
SCRUM  
hf@deer.(none) 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.
**************************************************************************/

250 251
static void emb_fetch_lengths(ulong *to, MYSQL_ROW column,
			      unsigned int field_count)
hf@deer.(none)'s avatar
SCRUM  
hf@deer.(none) 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)
hf@deer.(none)'s avatar
SCRUM  
hf@deer.(none) 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;
  }
hf@deer.(none)'s avatar
SCRUM  
hf@deer.(none) committed
288

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

  return 0;
}

300
static int emb_stmt_execute(MYSQL_STMT *stmt)
hf@deer.(none)'s avatar
SCRUM  
hf@deer.(none) 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;
hf@deer.(none)'s avatar
SCRUM  
hf@deer.(none) committed
310
  thd->client_param_count= stmt->param_count;
hf@deer.(none)'s avatar
hf@deer.(none) 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)
hf@deer.(none)'s avatar
SCRUM  
hf@deer.(none) committed
320 321
  {
    NET *net= &stmt->mysql->net;
322
    set_stmt_errmsg(stmt, net);
hf@deer.(none)'s avatar
SCRUM  
hf@deer.(none) committed
323 324 325 326 327
    DBUG_RETURN(1);
  }
  DBUG_RETURN(0);
}

328
int emb_read_binary_rows(MYSQL_STMT *stmt)
hf@deer.(none)'s avatar
hf@deer.(none) committed
329
{
330 331
  MYSQL_DATA *data;
  if (!(data= emb_read_rows(stmt->mysql, 0, 0)))
332
  {
333
    set_stmt_errmsg(stmt, &stmt->mysql->net);
334
    return 1;
335
  }
336 337
  stmt->result= *data;
  my_free((char *) data, MYF(0));
338
  set_stmt_errmsg(stmt, &stmt->mysql->net);
339
  return 0;
hf@deer.(none)'s avatar
hf@deer.(none) 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);
}

364
int emb_unbuffered_fetch(MYSQL *mysql, char **row)
hf@deer.(none)'s avatar
SCRUM  
hf@deer.(none) 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;
  }
hf@deer.(none)'s avatar
SCRUM  
hf@deer.(none) 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;
hf@deer.(none)'s avatar
SCRUM  
hf@deer.(none) 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;
}

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

konstantin@oak.local's avatar
konstantin@oak.local committed
404
static const char * emb_read_statistics(MYSQL *mysql)
hf@deer.(none)'s avatar
hf@deer.(none) committed
405 406
{
  THD *thd= (THD*)mysql->thd;
Marc Alff's avatar
Marc Alff committed
407
  return thd->is_error() ? thd->stmt_da->message() : "";
hf@deer.(none)'s avatar
hf@deer.(none) committed
408 409
}

410

411
static MYSQL_RES * emb_store_result(MYSQL *mysql)
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);
}

hf@deer.(none)'s avatar
SCRUM  
hf@deer.(none) committed
423 424
MYSQL_METHODS embedded_methods= 
{
425
  emb_read_query_result,
hf@deer.(none)'s avatar
SCRUM  
hf@deer.(none) committed
426 427
  emb_advanced_command,
  emb_read_rows,
428
  emb_store_result,
hf@deer.(none)'s avatar
SCRUM  
hf@deer.(none) committed
429
  emb_fetch_lengths, 
430
  emb_flush_use_result,
hf@deer.(none)'s avatar
SCRUM  
hf@deer.(none) committed
431
  emb_list_fields,
hf@deer.(none)'s avatar
SCRUM  
hf@deer.(none) committed
432
  emb_read_prepare_result,
hf@deer.(none)'s avatar
hf@deer.(none) committed
433
  emb_stmt_execute,
hf@deer.(none)'s avatar
SCRUM  
hf@deer.(none) committed
434
  emb_read_binary_rows,
hf@deer.(none)'s avatar
SCRUM  
hf@deer.(none) committed
435
  emb_unbuffered_fetch,
hf@deer.(none)'s avatar
hf@deer.(none) committed
436
  emb_free_embedded_thd,
konstantin@oak.local's avatar
konstantin@oak.local committed
437
  emb_read_statistics,
438 439 440
  emb_read_query_result,
  emb_read_change_user_result,
  emb_read_rows_from_cursor
hf@deer.(none)'s avatar
SCRUM  
hf@deer.(none) 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;
}

serg@serg.mylan's avatar
serg@serg.mylan committed
469
char **		copy_arguments_ptr= 0;
470

471
int init_embedded_server(int argc, char **argv, char **groups)
hf@genie.(none)'s avatar
hf@genie.(none) committed
472
{
473 474 475 476
  /*
    This mess is to allow people to call the init function without
    having to mess with a fake argv
   */
hf@genie.(none)'s avatar
hf@genie.(none) 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;
hf@genie.(none)'s avatar
hf@genie.(none) committed
483 484
  if (argc)
  {
485 486
    argcp= &argc;
    argvp= (char***) &argv;
hf@genie.(none)'s avatar
hf@genie.(none) committed
487 488 489
  }
  else
  {
490 491
    argcp= &fake_argc;
    argvp= (char ***) &fake_argv;
hf@genie.(none)'s avatar
hf@genie.(none) committed
492 493
  }
  if (!groups)
494
    groups= (char**) fake_groups;
hf@genie.(none)'s avatar
hf@genie.(none) committed
495

496
  my_progname= (char *)"mysql_embedded";
hf@genie.(none)'s avatar
hf@genie.(none) 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();

hf@deer.(none)'s avatar
hf@deer.(none) committed
504
  if (init_common_variables("my", *argcp, *argvp, (const char **)groups))
hf@genie.(none)'s avatar
hf@genie.(none) committed
505 506 507 508 509 510 511 512 513 514 515 516 517 518 519 520 521 522 523 524 525 526 527 528 529
  {
    mysql_server_end();
    return 1;
  }
    
  /* 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;

530
  acl_error= 0;
hf@deer.(none)'s avatar
hf@deer.(none) committed
531
#ifndef NO_EMBEDDED_ACCESS_CHECKS
532
  if (!(acl_error= acl_init(opt_noacl)) &&
533
      !opt_noacl)
534
    (void) grant_init();
535 536
#endif
  if (acl_error || my_tz_init((THD *)0, default_tz_name, opt_bootstrap))
hf@genie.(none)'s avatar
hf@genie.(none) committed
537 538 539 540
  {
    mysql_server_end();
    return 1;
  }
hf@deer.(none)'s avatar
hf@deer.(none) committed
541

hf@genie.(none)'s avatar
hf@genie.(none) committed
542 543 544 545
  init_max_user_conn();
  init_update_queries();

#ifdef HAVE_DLOPEN
hf@deer.(none)'s avatar
hf@deer.(none) committed
546
#ifndef NO_EMBEDDED_ACCESS_CHECKS
hf@genie.(none)'s avatar
hf@genie.(none) committed
547
  if (!opt_noacl)
hf@deer.(none)'s avatar
hf@deer.(none) committed
548
#endif
hf@genie.(none)'s avatar
hf@genie.(none) committed
549 550 551 552 553
    udf_init();
#endif

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

554
  start_handle_manager();
hf@genie.(none)'s avatar
hf@genie.(none) committed
555

556 557 558 559 560
  // 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;

hf@deer.(none)'s avatar
hf@deer.(none) committed
561 562 563 564 565 566 567 568 569
  if (opt_init_file)
  {
    if (read_init_file(opt_init_file))
    {
      mysql_server_end();
      return 1;
    }
  }

570
  execute_ddl_log_recovery();
hf@genie.(none)'s avatar
hf@genie.(none) committed
571 572 573
  return 0;
}

574
void end_embedded_server()
575
{
576 577
  my_free((char*) copy_arguments_ptr, MYF(MY_ALLOW_ZERO_PTR));
  copy_arguments_ptr=0;
578
  clean_up(0);
tim@black.box's avatar
tim@black.box committed
579 580
}

581

582
void init_embedded_mysql(MYSQL *mysql, int client_flag)
583
{
584
  THD *thd = (THD *)mysql->thd;
585
  thd->mysql= mysql;
hf@deer.(none)'s avatar
hf@deer.(none) committed
586
  mysql->server_version= server_version;
587
  init_alloc_root(&mysql->field_alloc, 8192, 0);
588
}
589

590 591 592 593 594 595 596 597 598 599 600
/**
  @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.
*/
601
void *create_embedded_thd(int client_flag)
602 603
{
  THD * thd= new THD;
604
  thd->thread_id= thd->variables.pseudo_thread_id= thread_id++;
605

606
  thd->thread_stack= (char*) &thd;
607 608 609
  if (thd->store_globals())
  {
    fprintf(stderr,"store_globals failed.\n");
610
    goto err;
611
  }
612
  lex_start(thd);
613

614
  /* TODO - add init_connect command execution */
615

616 617
  if (thd->variables.max_join_size == HA_POS_ERROR)
    thd->options |= OPTION_BIG_SELECTS;
618 619 620 621
  thd->proc_info=0;				// Remove 'login'
  thd->command=COM_SLEEP;
  thd->version=refresh_version;
  thd->set_time();
622
  thd->init_for_queries();
623
  thd->client_capabilities= client_flag;
624
  thd->real_id= pthread_self();
625

626 627
  thd->db= NULL;
  thd->db_length= 0;
hf@deer.(none)'s avatar
hf@deer.(none) committed
628
#ifndef NO_EMBEDDED_ACCESS_CHECKS
629 630
  thd->security_ctx->db_access= DB_ACLS;
  thd->security_ctx->master_access= ~NO_ACCESS;
hf@deer.(none)'s avatar
hf@deer.(none) committed
631
#endif
632 633 634 635
  thd->cur_data= 0;
  thd->first_data= 0;
  thd->data_tail= &thd->first_data;
  bzero((char*) &thd->net, sizeof(thd->net));
hf@deer.(none)'s avatar
SCRUM  
hf@deer.(none) committed
636

hf@deer.(none)'s avatar
hf@deer.(none) committed
637
  thread_count++;
638
  threads.append(thd);
639
  thd->mysys_var= 0;
640
  return thd;
641 642 643
err:
  delete(thd);
  return NULL;
644
}
645

646

647
#ifdef NO_EMBEDDED_ACCESS_CHECKS
648
int check_embedded_connection(MYSQL *mysql, const char *db)
649
{
650
  int result;
651
  THD *thd= (THD*)mysql->thd;
652 653
  thd_init_client_charset(thd, mysql->charset->number);
  thd->update_charset();
bell@sanja.is.com.ua's avatar
bell@sanja.is.com.ua committed
654
  Security_context *sctx= thd->security_ctx;
655 656
  sctx->host_or_ip= sctx->host= (char*) my_localhost;
  strmake(sctx->priv_host, (char*) my_localhost,  MAX_HOSTNAME-1);
657
  sctx->priv_user= sctx->user= my_strdup(mysql->user, MYF(0));
658
  result= check_user(thd, COM_CONNECT, NULL, 0, db, true);
659
  thd->protocol->end_statement();
660 661
  emb_read_query_result(mysql);
  return result;
662 663 664
}

#else
665
int check_embedded_connection(MYSQL *mysql, const char *db)
hf@deer.(none)'s avatar
hf@deer.(none) committed
666 667
{
  THD *thd= (THD*)mysql->thd;
668
  Security_context *sctx= thd->security_ctx;
hf@deer.(none)'s avatar
hf@deer.(none) committed
669 670 671 672
  int result;
  char scramble_buff[SCRAMBLE_LENGTH];
  int passwd_len;

673 674
  thd_init_client_charset(thd, mysql->charset->number);
  thd->update_charset();
675 676
  if (mysql->options.client_ip)
  {
677 678
    sctx->host= my_strdup(mysql->options.client_ip, MYF(0));
    sctx->ip= my_strdup(sctx->host, MYF(0));
679 680
  }
  else
681 682
    sctx->host= (char*)my_localhost;
  sctx->host_or_ip= sctx->host;
hf@deer.(none)'s avatar
hf@deer.(none) committed
683

684
  if (acl_check_host(sctx->host, sctx->ip))
hf@deer.(none)'s avatar
hf@deer.(none) committed
685 686 687 688 689
  {
    result= ER_HOST_NOT_PRIVILEGED;
    goto err;
  }

690
  sctx->user= my_strdup(mysql->user, MYF(0));
hf@deer.(none)'s avatar
hf@deer.(none) committed
691 692 693 694 695 696 697 698 699 700 701
  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, 
702
			 scramble_buff, passwd_len, db, true)))
hf@deer.(none)'s avatar
hf@deer.(none) committed
703 704 705 706 707 708
     goto err;

  return 0;
err:
  {
    NET *net= &mysql->net;
Marc Alff's avatar
Marc Alff committed
709 710
    strmake(net->last_error, thd->stmt_da->message(),
            sizeof(net->last_error)-1);
711
    memcpy(net->sqlstate,
Marc Alff's avatar
Marc Alff committed
712
           mysql_errno_to_sqlstate(thd->stmt_da->sql_errno()),
713
           sizeof(net->sqlstate)-1);
hf@deer.(none)'s avatar
hf@deer.(none) committed
714 715 716 717 718
  }
  return result;
}
#endif

719
C_MODE_END
720

serg@serg.mylan's avatar
serg@serg.mylan committed
721 722 723 724 725 726 727 728 729 730 731 732 733 734
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;
}


735 736 737 738 739 740 741 742 743 744 745 746 747
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,
hf@deer.(none)'s avatar
hf@deer.(none) committed
748
                             tocs, from, length, fromcs, &dummy_err);
749 750 751 752 753 754 755 756 757 758 759 760
  }
  else
  {
    result= (char *)alloc_root(root, length + 1);
    memcpy(result, from, length);
  }

  result[length]= 0;
  return result;
}


761 762 763 764 765 766 767 768 769 770 771 772 773 774 775 776 777 778 779 780 781 782 783 784 785 786 787 788 789 790 791 792 793 794
/*
  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;
}


795 796 797
/**
  Stores server_status and warning_count in the current
  query result structures.
798

799
  @param thd            current thread
800

801
  @note Should be called after we get the recordset-result.
802 803
*/

804
static
805
bool
Marc Alff's avatar
Marc Alff committed
806
write_eof_packet(THD *thd, uint server_status, uint statement_warn_count)
807
{
808
  if (!thd->mysql)            // bootstrap file handling
809
    return FALSE;
810 811 812 813 814 815 816
  /*
    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;
817
  thd->cur_data->embedded_info->server_status= server_status;
818 819 820 821 822
  /*
    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
823
    (thd->spcont ? 0 : min(statement_warn_count, 65535));
824
  return FALSE;
825 826 827 828 829 830 831 832 833 834 835 836 837 838 839 840 841 842 843 844 845 846 847 848 849 850 851 852 853 854
}


/*
  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
855
  Protocol_text::remove_last_row()
856 857 858 859 860 861 862

  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.
*/

863
void Protocol_text::remove_last_row()
864 865 866
{
  MYSQL_DATA *data= thd->cur_data;
  MYSQL_ROWS **last_row_hook= &data->data;
867
  my_ulonglong count= data->rows;
868
  DBUG_ENTER("Protocol_text::remove_last_row");
869 870 871 872 873 874 875 876 877 878 879
  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;
}


880
bool Protocol::send_result_set_metadata(List<Item> *list, uint flags)
hf@deer.mysql.r18.ru's avatar
hf@deer.mysql.r18.ru committed
881 882 883
{
  List_iterator_fast<Item> it(*list);
  Item                     *item;
hf@deer.(none)'s avatar
SCRUM  
hf@deer.(none) committed
884 885
  MYSQL_FIELD              *client_field;
  MEM_ROOT                 *field_alloc;
886 887
  CHARSET_INFO             *thd_cs= thd->variables.character_set_results;
  CHARSET_INFO             *cs= system_charset_info;
888
  MYSQL_DATA               *data;
889
  DBUG_ENTER("send_result_set_metadata");
hf@deer.mysql.r18.ru's avatar
hf@deer.mysql.r18.ru committed
890

891
  if (!thd->mysql)            // bootstrap file handling
hf@deer.(none)'s avatar
hf@deer.(none) committed
892 893
    DBUG_RETURN(0);

894 895 896 897 898 899 900 901 902
  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)))
hf@deer.mysql.r18.ru's avatar
hf@deer.mysql.r18.ru committed
903 904 905 906 907 908 909
    goto err;

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

910 911 912 913
    /* Keep things compatible for old clients */
    if (server_field.type == MYSQL_TYPE_VARCHAR)
      server_field.type= MYSQL_TYPE_VAR_STRING;

914
    client_field->db= dup_str_aux(field_alloc, server_field.db_name,
hf@deer.(none)'s avatar
hf@deer.(none) committed
915
                                  strlen(server_field.db_name), cs, thd_cs);
916
    client_field->table= dup_str_aux(field_alloc, server_field.table_name,
hf@deer.(none)'s avatar
hf@deer.(none) committed
917
                                     strlen(server_field.table_name), cs, thd_cs);
918
    client_field->name= dup_str_aux(field_alloc, server_field.col_name,
hf@deer.(none)'s avatar
hf@deer.(none) committed
919
                                    strlen(server_field.col_name), cs, thd_cs);
920
    client_field->org_table= dup_str_aux(field_alloc, server_field.org_table_name,
hf@deer.(none)'s avatar
hf@deer.(none) committed
921
                                         strlen(server_field.org_table_name), cs, thd_cs);
922
    client_field->org_name= dup_str_aux(field_alloc, server_field.org_col_name,
hf@deer.(none)'s avatar
hf@deer.(none) committed
923
                                        strlen(server_field.org_col_name), cs, thd_cs);
924 925 926 927 928 929 930 931
    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
    {
932
      uint max_char_len;
933 934
      /* With conversion */
      client_field->charsetnr= thd_cs->number;
935 936 937 938 939
      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;
940
    }
hf@deer.mysql.r18.ru's avatar
hf@deer.mysql.r18.ru committed
941 942 943
    client_field->type=   server_field.type;
    client_field->flags= server_field.flags;
    client_field->decimals= server_field.decimals;
944 945 946 947 948
    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);
hf@deer.(none)'s avatar
SCRUM  
hf@deer.(none) committed
949

950
    client_field->catalog= dup_str_aux(field_alloc, "def", 3, cs, thd_cs);
hf@deer.(none)'s avatar
SCRUM  
hf@deer.(none) committed
951
    client_field->catalog_length= 3;
952

953
    if (IS_NUM(client_field->type))
hf@deer.mysql.r18.ru's avatar
hf@deer.mysql.r18.ru committed
954 955
      client_field->flags|= NUM_FLAG;

956
    if (flags & (int) Protocol::SEND_DEFAULTS)
hf@deer.mysql.r18.ru's avatar
hf@deer.mysql.r18.ru committed
957 958 959 960 961
    {
      char buff[80];
      String tmp(buff, sizeof(buff), default_charset_info), *res;

      if (!(res=item->val_str(&tmp)))
hf@deer.(none)'s avatar
SCRUM  
hf@deer.(none) committed
962 963
      {
	client_field->def_length= 0;
964
	client_field->def= strmake_root(field_alloc, "",0);
hf@deer.(none)'s avatar
SCRUM  
hf@deer.(none) committed
965
      }
hf@deer.mysql.r18.ru's avatar
hf@deer.mysql.r18.ru committed
966
      else
hf@deer.(none)'s avatar
SCRUM  
hf@deer.(none) committed
967
      {
968
	client_field->def_length= res->length();
969 970
	client_field->def= strmake_root(field_alloc, res->ptr(),
					client_field->def_length);
hf@deer.(none)'s avatar
SCRUM  
hf@deer.(none) committed
971
      }
hf@deer.mysql.r18.ru's avatar
hf@deer.mysql.r18.ru committed
972 973 974 975 976 977
    }
    else
      client_field->def=0;
    client_field->max_length= 0;
    ++client_field;
  }
978 979

  if (flags & SEND_EOF)
Marc Alff's avatar
Marc Alff committed
980 981
    write_eof_packet(thd, thd->server_status,
                     thd->warning_info->statement_warn_count());
hf@deer.mysql.r18.ru's avatar
hf@deer.mysql.r18.ru committed
982

983
  DBUG_RETURN(prepare_for_send(list->elements));
hf@deer.mysql.r18.ru's avatar
hf@deer.mysql.r18.ru committed
984
 err:
bell@sanja.is.com.ua's avatar
bell@sanja.is.com.ua committed
985
  my_error(ER_OUT_OF_RESOURCES, MYF(0));        /* purecov: inspected */
hf@deer.mysql.r18.ru's avatar
SCRUM  
hf@deer.mysql.r18.ru committed
986
  DBUG_RETURN(1);				/* purecov: inspected */
hf@deer.mysql.r18.ru's avatar
hf@deer.mysql.r18.ru committed
987 988
}

hf@deer.mysql.r18.ru's avatar
SCRUM  
hf@deer.mysql.r18.ru committed
989
bool Protocol::write()
hf@genie.(none)'s avatar
hf@genie.(none) committed
990
{
hf@deer.(none)'s avatar
hf@deer.(none) committed
991 992 993
  if (!thd->mysql)            // bootstrap file handling
    return false;

hf@deer.mysql.r18.ru's avatar
SCRUM  
hf@deer.mysql.r18.ru committed
994 995
  *next_field= 0;
  return false;
hf@genie.(none)'s avatar
hf@genie.(none) committed
996
}
997

998
bool Protocol_binary::write()
hf@deer.(none)'s avatar
hf@deer.(none) committed
999 1000
{
  MYSQL_ROWS *cur;
1001
  MYSQL_DATA *data= thd->cur_data;
hf@deer.(none)'s avatar
hf@deer.(none) committed
1002 1003

  data->rows++;
1004 1005
  if (!(cur= (MYSQL_ROWS *)alloc_root(alloc,
                                      sizeof(MYSQL_ROWS)+packet->length())))
hf@deer.(none)'s avatar
hf@deer.(none) committed
1006 1007 1008 1009 1010
  {
    my_error(ER_OUT_OF_RESOURCES,MYF(0));
    return true;
  }
  cur->data= (MYSQL_ROW)(((char *)cur) + sizeof(MYSQL_ROWS));
hf@deer.(none)'s avatar
SCRUM  
hf@deer.(none) committed
1011
  memcpy(cur->data, packet->ptr()+1, packet->length()-1);
1012
  cur->length= packet->length();       /* To allow us to do sanity checks */
hf@deer.(none)'s avatar
hf@deer.(none) committed
1013

1014 1015
  *data->embedded_info->prev_ptr= cur;
  data->embedded_info->prev_ptr= &cur->next;
hf@deer.(none)'s avatar
SCRUM  
hf@deer.(none) committed
1016 1017
  cur->next= 0;
  
hf@deer.(none)'s avatar
hf@deer.(none) committed
1018 1019 1020
  return false;
}

1021 1022 1023 1024 1025 1026 1027 1028 1029 1030 1031 1032 1033 1034 1035

/**
  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.

1036 1037 1038
  @return
    @retval TRUE An error occurred
    @retval FALSE Success
1039 1040
*/

1041
bool
1042
net_send_ok(THD *thd,
Marc Alff's avatar
Marc Alff committed
1043 1044
            uint server_status, uint statement_warn_count,
            ulonglong affected_rows, ulonglong id, const char *message)
1045
{
1046
  DBUG_ENTER("emb_net_send_ok");
1047 1048
  MYSQL_DATA *data;
  MYSQL *mysql= thd->mysql;
1049

hf@deer.(none)'s avatar
hf@deer.(none) committed
1050
  if (!mysql)            // bootstrap file handling
1051
    DBUG_RETURN(FALSE);
1052
  if (!(data= thd->alloc_new_dataset()))
Marc Alff's avatar
Marc Alff committed
1053
    DBUG_RETURN(TRUE);
1054 1055
  data->embedded_info->affected_rows= affected_rows;
  data->embedded_info->insert_id= id;
1056
  if (message)
1057 1058 1059
    strmake(data->embedded_info->info, message,
            sizeof(data->embedded_info->info)-1);

Marc Alff's avatar
Marc Alff committed
1060
  bool error= write_eof_packet(thd, server_status, statement_warn_count);
1061
  thd->cur_data= 0;
1062
  DBUG_RETURN(error);
1063 1064
}

1065 1066 1067 1068 1069 1070

/**
  Embedded library implementation of EOF response.

  @sa net_send_ok

1071 1072 1073
  @return
    @retval TRUE  An error occurred
    @retval FALSE Success
1074 1075
*/

1076
bool
Marc Alff's avatar
Marc Alff committed
1077
net_send_eof(THD *thd, uint server_status, uint statement_warn_count)
1078
{
Marc Alff's avatar
Marc Alff committed
1079
  bool error= write_eof_packet(thd, server_status, statement_warn_count);
1080
  thd->cur_data= 0;
1081
  return error;
1082 1083
}

1084

Marc Alff's avatar
Marc Alff committed
1085 1086
bool net_send_error_packet(THD *thd, uint sql_errno, const char *err,
                           const char *sqlstate)
1087
{
1088 1089 1090
  uint error;
  uchar converted_err[MYSQL_ERRMSG_SIZE];
  uint32 converted_err_len;
1091 1092 1093 1094 1095 1096
  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);
1097
    return TRUE;
1098 1099 1100 1101
  }

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

1103
  ei= data->embedded_info;
1104
  ei->last_errno= sql_errno;
1105 1106 1107 1108 1109 1110
  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
1111
  strmov(ei->sqlstate, sqlstate);
1112
  ei->server_status= thd->server_status;
1113
  thd->cur_data= 0;
1114
  return FALSE;
1115 1116 1117
}


1118
void Protocol_text::prepare_for_resend()
hf@deer.mysql.r18.ru's avatar
SCRUM  
hf@deer.mysql.r18.ru committed
1119
{
hf@deer.(none)'s avatar
SCRUM  
hf@deer.(none) committed
1120
  MYSQL_ROWS *cur;
1121
  MYSQL_DATA *data= thd->cur_data;
hf@deer.mysql.r18.ru's avatar
SCRUM  
hf@deer.mysql.r18.ru committed
1122 1123
  DBUG_ENTER("send_data");

1124 1125 1126
  if (!thd->mysql)            // bootstrap file handling
    DBUG_VOID_RETURN;

hf@deer.(none)'s avatar
SCRUM  
hf@deer.(none) committed
1127
  data->rows++;
hf@deer.mysql.r18.ru's avatar
SCRUM  
hf@deer.mysql.r18.ru committed
1128 1129 1130 1131 1132 1133 1134
  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));

1135 1136
  *data->embedded_info->prev_ptr= cur;
  data->embedded_info->prev_ptr= &cur->next;
hf@deer.mysql.r18.ru's avatar
SCRUM  
hf@deer.mysql.r18.ru committed
1137
  next_field=cur->data;
1138
  next_mysql_field= data->embedded_info->fields_list;
1139 1140 1141
#ifndef DBUG_OFF
  field_pos= 0;
#endif
1142

hf@deer.mysql.r18.ru's avatar
SCRUM  
hf@deer.mysql.r18.ru committed
1143 1144 1145
  DBUG_VOID_RETURN;
}

1146
bool Protocol_text::store_null()
hf@deer.mysql.r18.ru's avatar
SCRUM  
hf@deer.mysql.r18.ru committed
1147 1148 1149 1150 1151 1152
{
  *(next_field++)= NULL;
  ++next_mysql_field;
  return false;
}

1153
bool Protocol::net_store_data(const uchar *from, size_t length)
hf@deer.mysql.r18.ru's avatar
SCRUM  
hf@deer.mysql.r18.ru committed
1154
{
hf@deer.(none)'s avatar
hf@deer.(none) committed
1155
  char *field_buf;
hf@deer.(none)'s avatar
hf@deer.(none) committed
1156
  if (!thd->mysql)            // bootstrap file handling
1157
    return FALSE;
hf@deer.(none)'s avatar
hf@deer.(none) committed
1158

1159 1160
  if (!(field_buf= (char*) alloc_root(alloc, length + sizeof(uint) + 1)))
    return TRUE;
hf@deer.(none)'s avatar
hf@deer.(none) committed
1161 1162
  *(uint *)field_buf= length;
  *next_field= field_buf + sizeof(uint);
1163
  memcpy((uchar*) *next_field, from, length);
hf@deer.(none)'s avatar
SCRUM  
hf@deer.(none) committed
1164
  (*next_field)[length]= 0;
hf@deer.mysql.r18.ru's avatar
SCRUM  
hf@deer.mysql.r18.ru committed
1165 1166 1167 1168
  if (next_mysql_field->max_length < length)
    next_mysql_field->max_length=length;
  ++next_field;
  ++next_mysql_field;
1169
  return FALSE;
hf@deer.mysql.r18.ru's avatar
SCRUM  
hf@deer.mysql.r18.ru committed
1170 1171
}

1172 1173 1174
#if defined(_MSC_VER) && _MSC_VER < 1400
#define vsnprintf _vsnprintf
#endif
1175

1176
int vprint_msg_to_log(enum loglevel level __attribute__((unused)),
1177 1178 1179 1180 1181
                       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;
1182
  return 0;
1183
}
1184 1185 1186 1187 1188 1189 1190 1191 1192 1193 1194 1195 1196 1197 1198 1199 1200 1201 1202 1203 1204 1205 1206 1207


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;
}