Commit message: Bug#25988681: USE-AFTER-FREE IN MYSQL_STMT_CLOSE()

Description: If mysql_stmt_close() encountered error,
             it recorded error in prepared statement
             but then frees memory assigned to prepared
             statement. If mysql_stmt_error() is used
             to get error information, it will result
             into use after free.

             In all cases where mysql_stmt_close() can
             fail, error would have been set by
             cli_advanced_command in MYSQL structure.

Solution: Don't copy error from MYSQL using set_stmt_errmsg.
          There is no automated way to test the fix since
          it is in mysql_stmt_close() which does not expect
          any reply from server.

Reviewed-By: Georgi Kodinov <georgi.kodinov@oracle.com>
Reviewed-By: Ramil Kalimullin <ramil.kalimullin@oracle.com>
CVE: CVE-2017-3635
CWE: NVD-CWE-noinfo
Vulnerability description: Vulnerability in the MySQL Connectors component of Oracle MySQL (subcomponent: Connector/C). Supported versions that are affected are 6.1.10 and earlier. Difficult to exploit vulnerability allows low privileged attacker with network access via multiple protocols to compromise MySQL Connectors. Successful attacks of this vulnerability can result in unauthorized ability to cause a hang or frequently repeatable crash (complete DOS) of MySQL Connectors. Note: The documentation has also been updated for the correct way to use mysql_stmt_close(). Please see: https://dev.mysql.com/doc/refman/5.7/en/mysql-stmt-execute.html,  https://dev.mysql.com/doc/refman/5.7/en/mysql-stmt-fetch.html, https://dev.mysql.com/doc/refman/5.7/en/mysql-stmt-close.html, https://dev.mysql.com/doc/refman/5.7/en/mysql-stmt-error.html, https://dev.mysql.com/doc/refman/5.7/en/mysql-stmt-errno.html, and  https://dev.mysql.com/doc/refman/5.7/en/mysql-stmt-sqlstate.html. CVSS 3.0 Base Score 5.3 (Availability impacts). CVSS Vector: (CVSS:3.0/AV:N/AC:H/PR:L/UI:N/S:U/C:N/I:N/A:H).

Project: mysql-server
File: libmysql.c

mysql_list_processes(MYSQL *mysql)
{
  MYSQL_DATA *fields;
  uint field_count;
  uchar *pos;
  DBUG_ENTER("mysql_list_processes");

  LINT_INIT(fields);
  if (simple_command(mysql,COM_PROCESS_INFO,0,0,0))
    DBUG_RETURN(0);
  free_old_query(mysql);
  pos=(uchar*) mysql->net.read_pos;
  field_count=(uint) net_field_length(&pos);
  if (!(fields = (*mysql->methods->read_rows)(mysql,(MYSQL_FIELD*) 0,
					      protocol_41(mysql) ? 7 : 5)))
    DBUG_RETURN(NULL);
  if (!(mysql->fields=unpack_fields(mysql, fields,&mysql->field_alloc,field_count,0,
				    mysql->server_capabilities)))
    DBUG_RETURN(0);
  mysql->status=MYSQL_STATUS_GET_RESULT;
  mysql->field_count=field_count;
  DBUG_RETURN(mysql_store_result(mysql));
}

Project: mysql-server
File: libmysql.c

static void store_param_int32(NET *net, MYSQL_BIND *param)
{
  int32 value= *(int32*) param->buffer;
  int4store(net->write_pos,value);
  net->write_pos+=4;
}

Project: mysql-server
File: libmysql.c

mysql_data_seek(MYSQL_RES *result, my_ulonglong row)
{
  MYSQL_ROWS	*tmp=0;
  DBUG_PRINT("info",("mysql_data_seek(%ld)",(long) row));
  if (result->data)
    for (tmp=result->data->data; row-- && tmp ; tmp = tmp->next) ;
  result->current_row=0;
  result->data_cursor = tmp;
}

Project: mysql-server
File: libmysql.c

mysql_stat(MYSQL *mysql)
{
  DBUG_ENTER("mysql_stat");
  if (simple_command(mysql,COM_STATISTICS,0,0,0))
    DBUG_RETURN(mysql->net.last_error);
  DBUG_RETURN((*mysql->methods->read_statistics)(mysql));
}

Project: mysql-server
File: libmysql.c

mysql_query(MYSQL *mysql, const char *query)
{
  return mysql_real_query(mysql,query, (uint) strlen(query));
}

Project: mysql-server
File: libmysql.c

my_bool STDCALL mysql_eof(MYSQL_RES *res)
{
  return res->eof;
}

Project: mysql-server
File: libmysql.c

static void fetch_result_double(MYSQL_BIND *param,
                                MYSQL_FIELD *field __attribute__((unused)),
                                uchar **row)
{
  double value;
  float8get(value,*row);
  doublestore(param->buffer, value);
  *row+= 8;
}

Project: mysql-server
File: libmysql.c

mysql_stmt_result_metadata(MYSQL_STMT *stmt)
{
  MYSQL_RES *result;
  DBUG_ENTER("mysql_stmt_result_metadata");

  /*
    stmt->fields is only defined if stmt->field_count is not null;
    stmt->field_count is initialized in prepare.
  */
  if (!stmt->field_count)
     DBUG_RETURN(0);

  if (!(result=(MYSQL_RES*) my_malloc(sizeof(*result),
                                      MYF(MY_WME | MY_ZEROFILL))))
  {
    set_stmt_error(stmt, CR_OUT_OF_MEMORY, unknown_sqlstate, NULL);
    DBUG_RETURN(0);
  }

  result->methods=	stmt->mysql->methods;
  result->eof=		1;                      /* Marker for buffered */
  result->fields=	stmt->fields;
  result->field_count=	stmt->field_count;
  /* The rest of members of 'result' was bzeroed inside malloc */
  DBUG_RETURN(result);
}

Project: mysql-server
File: libmysql.c

MYSQL_ROW_OFFSET STDCALL mysql_row_tell(MYSQL_RES *res)
{
  return res->data_cursor;
}

Project: mysql-server
File: libmysql.c

static void skip_result_string(MYSQL_BIND *param __attribute__((unused)),
			       MYSQL_FIELD *field,
			       uchar **row)

{
  ulong length= net_field_length(row);
  (*row)+= length;
  if (field->max_length < length)
    field->max_length= length;
}

Project: mysql-server
File: libmysql.c

mysql_stmt_prepare(MYSQL_STMT *stmt, const char *query, ulong length)
{
  MYSQL *mysql= stmt->mysql;
  DBUG_ENTER("mysql_stmt_prepare");

  if (!mysql)
  {
    /* mysql can be reset in mysql_close called from mysql_reconnect */
    set_stmt_error(stmt, CR_SERVER_LOST, unknown_sqlstate, NULL);
    DBUG_RETURN(1);
  }

  /*
    Reset the last error in any case: that would clear the statement
    if the previous prepare failed.
  */
  stmt->last_errno= 0;
  stmt->last_error[0]= '\0';

  if ((int) stmt->state > (int) MYSQL_STMT_INIT_DONE)
  {
    /* This is second prepare with another statement */
    uchar buff[MYSQL_STMT_HEADER];               /* 4 bytes - stmt id */

    if (reset_stmt_handle(stmt, RESET_LONG_DATA | RESET_STORE_RESULT))
      DBUG_RETURN(1);
    /*
      These members must be reset for API to
      function in case of error or misuse.
    */
    stmt->bind_param_done= stmt->bind_result_done= FALSE;
    stmt->param_count= stmt->field_count= 0;
    free_root(&stmt->mem_root, MYF(MY_KEEP_PREALLOC));
    free_root(&stmt->extension->fields_mem_root, MYF(0));

    int4store(buff, stmt->stmt_id);

    /*
      Close statement in server

      If there was a 'use' result from another statement, or from
      mysql_use_result it won't be freed in mysql_stmt_free_result and
      we should get 'Commands out of sync' here.
    */
    stmt->state= MYSQL_STMT_INIT_DONE;
    if (stmt_command(mysql, COM_STMT_CLOSE, buff, 4, stmt))
    {
      set_stmt_errmsg(stmt, &mysql->net);
      DBUG_RETURN(1);
    }
  }

  if (stmt_command(mysql, COM_STMT_PREPARE, (const uchar*) query, length, stmt))
  {
    set_stmt_errmsg(stmt, &mysql->net);
    DBUG_RETURN(1);
  }

  if ((*mysql->methods->read_prepare_result)(mysql, stmt))
  {
    set_stmt_errmsg(stmt, &mysql->net);
    DBUG_RETURN(1);
  }

  /*
    alloc_root will return valid address even in case when param_count
    and field_count are zero. Thus we should never rely on stmt->bind
    or stmt->params when checking for existence of placeholders or
    result set.
  */
  if (!(stmt->params= (MYSQL_BIND *) alloc_root(&stmt->mem_root,
						sizeof(MYSQL_BIND)*
                                                (stmt->param_count +
                                                 stmt->field_count))))
  {
    set_stmt_error(stmt, CR_OUT_OF_MEMORY, unknown_sqlstate, NULL);
    DBUG_RETURN(1);
  }
  stmt->bind= stmt->params + stmt->param_count;
  stmt->state= MYSQL_STMT_PREPARE_DONE;
  DBUG_PRINT("info", ("Parameter count: %u", stmt->param_count));
  DBUG_RETURN(0);
}

Project: mysql-server
File: libmysql.c

mysql_stmt_row_tell(MYSQL_STMT *stmt)
{
  DBUG_ENTER("mysql_stmt_row_tell");

  DBUG_RETURN(stmt->data_cursor);
}

Project: mysql-server
File: libmysql.c

void set_stmt_error(MYSQL_STMT * stmt, int errcode,
                    const char *sqlstate, const char *err)
{
  DBUG_ENTER("set_stmt_error");
  DBUG_PRINT("enter", ("error: %d '%s'", errcode, ER(errcode)));
  DBUG_ASSERT(stmt != 0);

  if (err == 0)
    err= ER(errcode);

  stmt->last_errno= errcode;
  strmov(stmt->last_error, ER(errcode));
  strmov(stmt->sqlstate, sqlstate);

  DBUG_VOID_RETURN;
}

Project: mysql-server
File: libmysql.c

static void read_binary_time(MYSQL_TIME *tm, uchar **pos)
{
  /* net_field_length will set pos to the first byte of data */
  uint length= net_field_length(pos);

  if (length)
  {
    uchar *to= *pos;
    tm->neg=    to[0];

    tm->day=    (ulong) sint4korr(to+1);
    tm->hour=   (uint) to[5];
    tm->minute= (uint) to[6];
    tm->second= (uint) to[7];
    tm->second_part= (length > 8) ? (ulong) sint4korr(to+8) : 0;
    tm->year= tm->month= 0;
    if (tm->day)
    {
      /* Convert days to hours at once */
      tm->hour+= tm->day*24;
      tm->day= 0;
    }
    tm->time_type= MYSQL_TIMESTAMP_TIME;

    *pos+= length;
  }
  else
    set_zero_time(tm, MYSQL_TIMESTAMP_TIME);
}

Project: mysql-server
File: libmysql.c

my_bool STDCALL mysql_read_query_result(MYSQL *mysql)
{
  return (*mysql->methods->read_query_result)(mysql);
}

Project: mysql-server
File: libmysql.c

mysql_connect(MYSQL *mysql,const char *host,
	      const char *user, const char *passwd)
{
  MYSQL *res;
  mysql=mysql_init(mysql);			/* Make it thread safe */
  {
    DBUG_ENTER("mysql_connect");
    if (!(res=mysql_real_connect(mysql,host,user,passwd,NullS,0,NullS,0)))
    {
      if (mysql->free_me)
	my_free(mysql);
    }
    mysql->reconnect= 1;
    DBUG_RETURN(res);
  }
}

Project: mysql-server
File: libmysql.c

my_ulonglong STDCALL mysql_stmt_num_rows(MYSQL_STMT *stmt)
{
  DBUG_ENTER("mysql_stmt_num_rows");

  DBUG_RETURN(stmt->result.rows);
}

Project: mysql-server
File: libmysql.c

static void fetch_result_int32(MYSQL_BIND *param,
                               MYSQL_FIELD *field __attribute__((unused)),
                               uchar **row)
{
  my_bool field_is_unsigned= test(field->flags & UNSIGNED_FLAG);
  uint32 data= (uint32) sint4korr(*row);
  longstore(param->buffer, data);
  *param->error= param->is_unsigned != field_is_unsigned && data > INT_MAX32;
  *row+= 4;
}

Project: mysql-server
File: libmysql.c

void read_user_name(char *name)
{
  DBUG_ENTER("read_user_name");
  if (geteuid() == 0)
    (void) strmov(name,"root");		/* allow use of surun */
  else
  {
#ifdef HAVE_GETPWUID
    struct passwd *skr;
    const char *str;
    if ((str=getlogin()) == NULL)
    {
      if ((skr=getpwuid(geteuid())) != NULL)
	str=skr->pw_name;
      else if (!(str=getenv("USER")) && !(str=getenv("LOGNAME")) &&
	       !(str=getenv("LOGIN")))
	str="UNKNOWN_USER";
    }
    (void) strmake(name,str,USERNAME_LENGTH);
#elif HAVE_CUSERID
    (void) cuserid(name);
#else
    strmov(name,"UNKNOWN_USER");
#endif
  }
  DBUG_VOID_RETURN;
}

Project: mysql-server
File: libmysql.c

static my_bool store_param(MYSQL_STMT *stmt, MYSQL_BIND *param)
{
  NET *net= &stmt->mysql->net;
  DBUG_ENTER("store_param");
  DBUG_PRINT("enter",("type: %d  buffer: 0x%lx  length: %lu  is_null: %d",
		      param->buffer_type,
		      (long) (param->buffer ? param->buffer : NullS),
                      *param->length, *param->is_null));

  if (*param->is_null)
    store_param_null(net, param);
  else
  {
    /*
      Param->length should ALWAYS point to the correct length for the type
      Either to the length pointer given by the user or param->buffer_length
    */
    if ((my_realloc_str(net, *param->length)))
    {
      set_stmt_errmsg(stmt, net);
      DBUG_RETURN(1);
    }
    (*param->store_param_func)(net, param);
  }
  DBUG_RETURN(0);
}

Project: mysql-server
File: libmysql.c

MYSQL_FIELD * STDCALL mysql_fetch_field_direct(MYSQL_RES *res,uint fieldnr)
{
  return &(res)->fields[fieldnr];
}

Project: mysql-server
File: libmysql.c

static void skip_result_with_length(MYSQL_BIND *param __attribute__((unused)),
				    MYSQL_FIELD *field __attribute__((unused)),
				    uchar **row)

{
  ulong length= net_field_length(row);
  (*row)+= length;
}

Project: mysql-server
File: libmysql.c

MYSQL_PARAMETERS *STDCALL mysql_get_parameters(void)
{
  return &mysql_internal_parameters;
}

Project: mysql-server
File: libmysql.c

static void store_param_int64(NET *net, MYSQL_BIND *param)
{
  longlong value= *(longlong*) param->buffer;
  int8store(net->write_pos,value);
  net->write_pos+= 8;
}

Project: mysql-server
File: libmysql.c

static void store_param_float(NET *net, MYSQL_BIND *param)
{
  float value= *(float*) param->buffer;
  float4store(net->write_pos, value);
  net->write_pos+= 4;
}

Project: mysql-server
File: libmysql.c

mysql_create_db(MYSQL *mysql, const char *db)
{
  DBUG_ENTER("mysql_createdb");
  DBUG_PRINT("enter",("db: %s",db));
  DBUG_RETURN(simple_command(mysql,COM_CREATE_DB,db, (ulong) strlen(db),0));
}

Project: mysql-server
File: libmysql.c

static void store_param_type(unsigned char **pos, MYSQL_BIND *param)
{
  uint typecode= param->buffer_type | (param->is_unsigned ? 32768 : 0);
  int2store(*pos, typecode);
  *pos+= 2;
}

Project: mysql-server
File: libmysql.c

static void fetch_result_short(MYSQL_BIND *param, MYSQL_FIELD *field,
                               uchar **row)
{
  my_bool field_is_unsigned= test(field->flags & UNSIGNED_FLAG);
  ushort data= (ushort) sint2korr(*row);
  shortstore(param->buffer, data);
  *param->error= param->is_unsigned != field_is_unsigned && data > INT_MAX16;
  *row+= 2;
}

Project: mysql-server
File: libmysql.c

static void store_param_tinyint(NET *net, MYSQL_BIND *param)
{
  *(net->write_pos++)= *(uchar *) param->buffer;
}

Project: mysql-server
File: libmysql.c

static void stmt_clear_error(MYSQL_STMT *stmt)
{
  if (stmt->last_errno)
  {
    stmt->last_errno= 0;
    stmt->last_error[0]= '\0';
    strmov(stmt->sqlstate, not_error_sqlstate);
  }
}

Project: mysql-server
File: libmysql.c

int STDCALL mysql_stmt_execute(MYSQL_STMT *stmt)
{
  MYSQL *mysql= stmt->mysql;
  DBUG_ENTER("mysql_stmt_execute");

  if (!mysql)
  {
    /* Error is already set in mysql_detatch_stmt_list */
    DBUG_RETURN(1);
  }

  if (reset_stmt_handle(stmt, RESET_STORE_RESULT | RESET_CLEAR_ERROR))
    DBUG_RETURN(1);
  /*
    No need to check for stmt->state: if the statement wasn't
    prepared we'll get 'unknown statement handler' error from server.
  */
  if (mysql->methods->stmt_execute(stmt))
    DBUG_RETURN(1);
  stmt->state= MYSQL_STMT_EXECUTE_DONE;
  if (mysql->field_count)
  {
    reinit_result_set_metadata(stmt);
    prepare_to_fetch_result(stmt);
  }
  DBUG_RETURN(test(stmt->last_errno));
}

Project: mysql-server
File: libmysql.c

my_bool STDCALL mysql_thread_init()
{
  return my_thread_init();
}

Project: mysql-server
File: libmysql.c

my_bool STDCALL mysql_autocommit(MYSQL * mysql, my_bool auto_mode)
{
  DBUG_ENTER("mysql_autocommit");
  DBUG_PRINT("enter", ("mode : %d", auto_mode));

  DBUG_RETURN((my_bool) mysql_real_query(mysql, auto_mode ?
                                         "set autocommit=1":"set autocommit=0",
                                         16));
}

Project: mysql-server
File: libmysql.c

static void fetch_result_tinyint(MYSQL_BIND *param, MYSQL_FIELD *field,
                                 uchar **row)
{
  my_bool field_is_unsigned= test(field->flags & UNSIGNED_FLAG);
  uchar data= **row;
  *(uchar *)param->buffer= data;
  *param->error= param->is_unsigned != field_is_unsigned && data > INT_MAX8;
  (*row)++;
}

Project: mysql-server
File: libmysql.c

static int default_local_infile_init(void **ptr, const char *filename,
             void *userdata __attribute__ ((unused)))
{
  default_local_infile_data *data;
  char tmp_name[FN_REFLEN];

  if (!(*ptr= data= ((default_local_infile_data *)
		     my_malloc(sizeof(default_local_infile_data),  MYF(0)))))
    return 1; /* out of memory */

  data->error_msg[0]= 0;
  data->error_num=    0;
  data->filename= filename;

  fn_format(tmp_name, filename, "", "", MY_UNPACK_FILENAME);
  if ((data->fd = my_open(tmp_name, O_RDONLY, MYF(0))) < 0)
  {
    data->error_num= my_errno;
    my_snprintf(data->error_msg, sizeof(data->error_msg)-1,
                EE(EE_FILENOTFOUND), tmp_name, data->error_num);
    return 1;
  }
  return 0; /* ok */
}

Project: mysql-server
File: libmysql.c

mysql_real_escape_string(MYSQL *mysql, char *to,const char *from,
			 ulong length)
{
  if (mysql->server_status & SERVER_STATUS_NO_BACKSLASH_ESCAPES)
    return (uint) escape_quotes_for_mysql(mysql->charset, to, 0, from, length);
  return (uint) escape_string_for_mysql(mysql->charset, to, 0, from, length);
}

Project: mysql-server
File: libmysql.c

mysql_escape_string(char *to,const char *from,ulong length)
{
  return (uint) escape_string_for_mysql(default_charset_info, to, 0, from, length);
}

Project: mysql-server
File: libmysql.c

static void store_param_date(NET *net, MYSQL_BIND *param)
{
  MYSQL_TIME tm= *((MYSQL_TIME *) param->buffer);
  tm.hour= tm.minute= tm.second= tm.second_part= 0;
  net_store_datetime(net, &tm);
}

Project: mysql-server
File: libmysql.c

my_ulonglong STDCALL mysql_insert_id(MYSQL *mysql)
{
  return mysql->insert_id;
}

Project: mysql-server
File: libmysql.c

stmt_read_row_no_data(MYSQL_STMT *stmt  __attribute__((unused)),
                      unsigned char **row  __attribute__((unused)))
{
  return MYSQL_NO_DATA;
}

Project: mysql-server
File: libmysql.c

my_bool STDCALL mysql_stmt_attr_set(MYSQL_STMT *stmt,
                                    enum enum_stmt_attr_type attr_type,
                                    const void *value)
{
  switch (attr_type) {
  case STMT_ATTR_UPDATE_MAX_LENGTH:
    stmt->update_max_length= value ? *(const my_bool*) value : 0;
    break;
  case STMT_ATTR_CURSOR_TYPE:
  {
    ulong cursor_type;
    cursor_type= value ? *(ulong*) value : 0UL;
    if (cursor_type > (ulong) CURSOR_TYPE_READ_ONLY)
      goto err_not_implemented;
    stmt->flags= cursor_type;
    break;
  }
  case STMT_ATTR_PREFETCH_ROWS:
  {
    ulong prefetch_rows= value ? *(ulong*) value : DEFAULT_PREFETCH_ROWS;
    if (value == 0)
      return TRUE;
    stmt->prefetch_rows= prefetch_rows;
    break;
  }
  default:
    goto err_not_implemented;
  }
  return FALSE;
err_not_implemented:
  set_stmt_error(stmt, CR_NOT_IMPLEMENTED, unknown_sqlstate, NULL);
  return TRUE;
}

Project: mysql-server
File: libmysql.c

void STDCALL mysql_thread_end()
{
  my_thread_end();
}

Project: mysql-server
File: libmysql.c

mysql_hex_string(char *to, const char *from, ulong length)
{
  char *to0= to;
  const char *end;
            
  for (end= from + length; from < end; from++)
  {
    *to++= _dig_vec_upper[((unsigned char) *from) >> 4];
    *to++= _dig_vec_upper[((unsigned char) *from) & 0x0F];
  }
  *to= '\0';
  return (ulong) (to-to0);
}

Project: mysql-server
File: libmysql.c

void STDCALL mysql_server_end()
{
  if (!mysql_client_init)
    return;

  mysql_client_plugin_deinit();

#ifdef EMBEDDED_LIBRARY
  end_embedded_server();
#endif
  finish_client_errs();
  vio_end();

  /* If library called my_init(), free memory allocated by it */
  if (!org_my_init_done)
  {
    my_end(0);
  }
  else
  {
    free_charsets();
    mysql_thread_end();
  }

  mysql_client_init= org_my_init_done= 0;
}

Project: mysql-server
File: libmysql.c

my_bool STDCALL mysql_stmt_reset(MYSQL_STMT *stmt)
{
  DBUG_ENTER("mysql_stmt_reset");
  DBUG_ASSERT(stmt != 0);
  if (!stmt->mysql)
  {
    /* mysql can be reset in mysql_close called from mysql_reconnect */
    set_stmt_error(stmt, CR_SERVER_LOST, unknown_sqlstate, NULL);
    DBUG_RETURN(1);
  }
  /* Reset the client and server sides of the prepared statement */
  DBUG_RETURN(reset_stmt_handle(stmt,
                                RESET_SERVER_SIDE | RESET_LONG_DATA |
                                RESET_CLEAR_ERROR));
}

Project: mysql-server
File: libmysql.c

mysql_set_local_infile_handler(MYSQL *mysql,
                               int (*local_infile_init)(void **, const char *,
                               void *),
                               int (*local_infile_read)(void *, char *, uint),
                               void (*local_infile_end)(void *),
                               int (*local_infile_error)(void *, char *, uint),
                               void *userdata)
{
  mysql->options.local_infile_init=  local_infile_init;
  mysql->options.local_infile_read=  local_infile_read;
  mysql->options.local_infile_end=   local_infile_end;
  mysql->options.local_infile_error= local_infile_error;
  mysql->options.local_infile_userdata = userdata;
}

Project: mysql-server
File: libmysql.c

const char *STDCALL mysql_stmt_error(MYSQL_STMT * stmt)
{
  DBUG_ENTER("mysql_stmt_error");
  DBUG_RETURN(stmt->last_error);
}

Project: mysql-server
File: libmysql.c

static void fetch_result_time(MYSQL_BIND *param,
                              MYSQL_FIELD *field __attribute__((unused)),
                              uchar **row)
{
  MYSQL_TIME *tm= (MYSQL_TIME *)param->buffer;
  read_binary_time(tm, row);
}

Project: mysql-server
File: libmysql.c

MYSQL_FIELD * STDCALL mysql_fetch_fields(MYSQL_RES *res)
{
  return (res)->fields;
}

Project: mysql-server
File: libmysql.c

static void stmt_update_metadata(MYSQL_STMT *stmt, MYSQL_ROWS *data)
{
  MYSQL_BIND  *my_bind, *end;
  MYSQL_FIELD *field;
  uchar *null_ptr, bit;
  uchar *row= (uchar*) data->data;
#ifndef DBUG_OFF
  uchar *row_end= row + data->length;
#endif

  null_ptr= row;
  row+= (stmt->field_count+9)/8;		/* skip null bits */
  bit= 4;					/* first 2 bits are reserved */

  /* Go through all fields and calculate metadata */
  for (my_bind= stmt->bind, end= my_bind + stmt->field_count, field= stmt->fields ;
       my_bind < end ;
       my_bind++, field++)
  {
    if (!(*null_ptr & bit))
      (*my_bind->skip_result)(my_bind, field, &row);
    DBUG_ASSERT(row <= row_end);
    if (!((bit<<=1) & 255))
    {
      bit= 1;					/* To next uchar */
      null_ptr++;
    }
  }
}

Project: mysql-server
File: libmysql.c

const char * STDCALL mysql_character_set_name(MYSQL *mysql)
{
  return mysql->charset->csname;
}

Project: mysql-server
File: libmysql.c

ulong STDCALL mysql_get_client_version(void)
{
  return MYSQL_VERSION_ID;
}

Project: mysql-server
File: libmysql.c

unsigned int STDCALL mysql_stmt_field_count(MYSQL_STMT *stmt)
{
  return stmt->field_count;
}

Project: mysql-server
File: libmysql.c

my_bool STDCALL mysql_stmt_bind_result(MYSQL_STMT *stmt, MYSQL_BIND *my_bind)
{
  MYSQL_BIND *param, *end;
  MYSQL_FIELD *field;
  ulong       bind_count= stmt->field_count;
  uint        param_count= 0;
  DBUG_ENTER("mysql_stmt_bind_result");
  DBUG_PRINT("enter",("field_count: %lu", bind_count));

  if (!bind_count)
  {
    int errorcode= (int) stmt->state < (int) MYSQL_STMT_PREPARE_DONE ?
                   CR_NO_PREPARE_STMT : CR_NO_STMT_METADATA;
    set_stmt_error(stmt, errorcode, unknown_sqlstate, NULL);
    DBUG_RETURN(1);
  }

  /*
    We only need to check that stmt->field_count - if it is not null
    stmt->bind was initialized in mysql_stmt_prepare
    stmt->bind overlaps with bind if mysql_stmt_bind_param
    is called from mysql_stmt_store_result.
  */

  if (stmt->bind != my_bind)
    memcpy((char*) stmt->bind, (char*) my_bind,
           sizeof(MYSQL_BIND) * bind_count);

  for (param= stmt->bind, end= param + bind_count, field= stmt->fields ;
       param < end ;
       param++, field++)
  {
    DBUG_PRINT("info",("buffer_type: %u  field_type: %u",
                       (uint) param->buffer_type, (uint) field->type));
    /*
      Set param->is_null to point to a dummy variable if it's not set.
      This is to make the execute code easier
    */
    if (!param->is_null)
      param->is_null= &param->is_null_value;

    if (!param->length)
      param->length= &param->length_value;

    if (!param->error)
      param->error= &param->error_value;

    param->param_number= param_count++;
    param->offset= 0;

    if (setup_one_fetch_function(param, field))
    {
      strmov(stmt->sqlstate, unknown_sqlstate);
      sprintf(stmt->last_error,
              ER(stmt->last_errno= CR_UNSUPPORTED_PARAM_TYPE),
              field->type, param_count);
      DBUG_RETURN(1);
    }
  }
  stmt->bind_result_done= BIND_RESULT_DONE;
  if (stmt->mysql->options.report_data_truncation)
    stmt->bind_result_done|= REPORT_DATA_TRUNCATION;

  DBUG_RETURN(0);
}

Project: mysql-server
File: libmysql.c

void set_stmt_errmsg(MYSQL_STMT *stmt, NET *net)
{
  DBUG_ENTER("set_stmt_errmsg");
  DBUG_PRINT("enter", ("error: %d/%s '%s'",
                       net->last_errno,
                       net->sqlstate,
                       net->last_error));
  DBUG_ASSERT(stmt != 0);

  stmt->last_errno= net->last_errno;
  if (net->last_error && net->last_error[0])
    strmov(stmt->last_error, net->last_error);
  strmov(stmt->sqlstate, net->sqlstate);

  DBUG_VOID_RETURN;
}

Project: mysql-server
File: libmysql.c

ulong STDCALL mysql_stmt_param_count(MYSQL_STMT * stmt)
{
  DBUG_ENTER("mysql_stmt_param_count");
  DBUG_RETURN(stmt->param_count);
}

Project: mysql-server
File: libmysql.c

mysql_get_host_info(MYSQL *mysql)
{
  return(mysql->host_info);
}

Project: mysql-server
File: libmysql.c

MYSQL_RES * STDCALL mysql_use_result(MYSQL *mysql)
{
  return (*mysql->methods->use_result)(mysql);
}

Project: mysql-server
File: libmysql.c

static void store_param_double(NET *net, MYSQL_BIND *param)
{
  double value= *(double*) param->buffer;
  float8store(net->write_pos, value);
  net->write_pos+= 8;
}

Project: mysql-server
File: libmysql.c

static void fetch_long_with_conversion(MYSQL_BIND *param, MYSQL_FIELD *field,
                                       longlong value, my_bool is_unsigned)
{
  char *buffer= (char *)param->buffer;

  switch (param->buffer_type) {
  case MYSQL_TYPE_NULL: /* do nothing */
    break;
  case MYSQL_TYPE_TINY:
    *param->error= IS_TRUNCATED(value, param->is_unsigned,
                                INT_MIN8, INT_MAX8, UINT_MAX8);
    *(uchar *)param->buffer= (uchar) value;
    break;
  case MYSQL_TYPE_SHORT:
    *param->error= IS_TRUNCATED(value, param->is_unsigned,
                                INT_MIN16, INT_MAX16, UINT_MAX16);
    shortstore(buffer, (short) value);
    break;
  case MYSQL_TYPE_LONG:
    *param->error= IS_TRUNCATED(value, param->is_unsigned,
                                INT_MIN32, INT_MAX32, UINT_MAX32);
    longstore(buffer, (int32) value);
    break;
  case MYSQL_TYPE_LONGLONG:
    longlongstore(buffer, value);
    *param->error= param->is_unsigned != is_unsigned && value < 0;
    break;
  case MYSQL_TYPE_FLOAT:
  {
    /*
      We need to mark the local variable volatile to
      workaround Intel FPU executive precision feature.
      (See http://gcc.gnu.org/bugzilla/show_bug.cgi?id=323 for details)
    */
    volatile float data;
    if (is_unsigned)
    {
      data= (float) ulonglong2double(value);
      *param->error= ((ulonglong) value) != ((ulonglong) data);
    }
    else
    {
      data= (float)value;
      *param->error= value != ((longlong) data);
    }
    floatstore(buffer, data);
    break;
  }
  case MYSQL_TYPE_DOUBLE:
  {
    volatile double data;
    if (is_unsigned)
    {
      data= ulonglong2double(value);
      *param->error= ((ulonglong) value) != ((ulonglong) data);
    }
    else
    {
      data= (double)value;
      *param->error= value != ((longlong) data);
    }
    doublestore(buffer, data);
    break;
  }
  case MYSQL_TYPE_TIME:
  case MYSQL_TYPE_DATE:
  case MYSQL_TYPE_TIMESTAMP:
  case MYSQL_TYPE_DATETIME:
  {
    int error;
    value= number_to_datetime(value, (MYSQL_TIME *) buffer, TIME_FUZZY_DATE,
                              &error);
    *param->error= test(error);
    break;
  }
  default:
  {
    uchar buff[22];                              /* Enough for longlong */
    uchar *end= (uchar*) longlong10_to_str(value, (char*) buff,
                                           is_unsigned ? 10: -10);
    /* Resort to string conversion which supports all typecodes */
    uint length= (uint) (end-buff);

    if (field->flags & ZEROFILL_FLAG && length < field->length &&
        field->length < 21)
    {
      bmove_upp(buff+field->length,buff+length, length);
      bfill(buff, field->length - length,'0');
      length= field->length;
    }
    fetch_string_with_conversion(param, (char*) buff, length);
    break;
  }
  }
}

Project: mysql-server
File: libmysql.c

mysql_list_fields(MYSQL *mysql, const char *table, const char *wild)
{
  MYSQL_RES   *result;
  MYSQL_FIELD *fields;
  char	     buff[258],*end;
  DBUG_ENTER("mysql_list_fields");
  DBUG_PRINT("enter",("table: '%s'  wild: '%s'",table,wild ? wild : ""));

  end=strmake(strmake(buff, table,128)+1,wild ? wild : "",128);
  free_old_query(mysql);
  if (simple_command(mysql, COM_FIELD_LIST, (uchar*) buff,
                     (ulong) (end-buff), 1) ||
      !(fields= (*mysql->methods->list_fields)(mysql)))
    DBUG_RETURN(NULL);

  if (!(result = (MYSQL_RES *) my_malloc(sizeof(MYSQL_RES),
					 MYF(MY_WME | MY_ZEROFILL))))
    DBUG_RETURN(NULL);

  result->methods= mysql->methods;
  result->field_alloc=mysql->field_alloc;
  mysql->fields=0;
  result->field_count = mysql->field_count;
  result->fields= fields;
  result->eof=1;
  DBUG_RETURN(result);
}

Project: mysql-server
File: libmysql.c

void mysql_set_local_infile_default(MYSQL *mysql)
{
  mysql->options.local_infile_init=  default_local_infile_init;
  mysql->options.local_infile_read=  default_local_infile_read;
  mysql->options.local_infile_end=   default_local_infile_end;
  mysql->options.local_infile_error= default_local_infile_error;
}

Project: mysql-server
File: libmysql.c

static void fetch_result_float(MYSQL_BIND *param,
                               MYSQL_FIELD *field __attribute__((unused)),
                               uchar **row)
{
  float value;
  float4get(value,*row);
  floatstore(param->buffer, value);
  *row+= 4;
}

Project: mysql-server
File: libmysql.c

int STDCALL mysql_stmt_fetch(MYSQL_STMT *stmt)
{
  int rc;
  uchar *row;
  DBUG_ENTER("mysql_stmt_fetch");

  if ((rc= (*stmt->read_row_func)(stmt, &row)) ||
      ((rc= stmt_fetch_row(stmt, row)) && rc != MYSQL_DATA_TRUNCATED))
  {
    stmt->state= MYSQL_STMT_PREPARE_DONE;       /* XXX: this is buggy */
    stmt->read_row_func= (rc == MYSQL_NO_DATA) ? 
      stmt_read_row_no_data : stmt_read_row_no_result_set;
  }
  else
  {
    /* This is to know in mysql_stmt_fetch_column that data was fetched */
    stmt->state= MYSQL_STMT_FETCH_DONE;
  }
  DBUG_RETURN(rc);
}

Project: mysql-server
File: libmysql.c

my_bool STDCALL mysql_stmt_free_result(MYSQL_STMT *stmt)
{
  DBUG_ENTER("mysql_stmt_free_result");

  /* Free the client side and close the server side cursor if there is one */
  DBUG_RETURN(reset_stmt_handle(stmt, RESET_LONG_DATA | RESET_STORE_RESULT |
                                RESET_CLEAR_ERROR));
}

Project: mysql-server
File: libmysql.c

static void update_stmt_fields(MYSQL_STMT *stmt)
{
  MYSQL_FIELD *field= stmt->mysql->fields;
  MYSQL_FIELD *field_end= field + stmt->field_count;
  MYSQL_FIELD *stmt_field= stmt->fields;
  MYSQL_BIND *my_bind= stmt->bind_result_done ? stmt->bind : 0;

  if (stmt->field_count != stmt->mysql->field_count)
  {
    /*
      The tables used in the statement were altered,
      and the query now returns a different number of columns.
      There is no way to continue without reallocating the bind
      array:
      - if the number of columns increased, mysql_stmt_fetch()
      will write beyond allocated memory
      - if the number of columns decreased, some user-bound
      buffers will be left unassigned without user knowing
      that.
    */
    set_stmt_error(stmt, CR_NEW_STMT_METADATA, unknown_sqlstate, NULL);
    return;
  }

  for (; field < field_end; ++field, ++stmt_field)
  {
    stmt_field->charsetnr= field->charsetnr;
    stmt_field->length   = field->length;
    stmt_field->type     = field->type;
    stmt_field->flags    = field->flags;
    stmt_field->decimals = field->decimals;
    if (my_bind)
    {
      /* Ignore return value: it should be 0 if bind_result succeeded. */
      (void) setup_one_fetch_function(my_bind++, stmt_field);
    }
  }
}

Project: mysql-server
File: libmysql.c

my_bool STDCALL mysql_commit(MYSQL * mysql)
{
  DBUG_ENTER("mysql_commit");
  DBUG_RETURN((my_bool) mysql_real_query(mysql, "commit", 6));
}

Project: mysql-server
File: libmysql.c

static void reinit_result_set_metadata(MYSQL_STMT *stmt)
{
  /* Server has sent result set metadata */
  if (stmt->field_count == 0)
  {
    /*
      This is 'SHOW'/'EXPLAIN'-like query. Current implementation of
      prepared statements can't send result set metadata for these queries
      on prepare stage. Read it now.
    */

    stmt->field_count= stmt->mysql->field_count;

    alloc_stmt_fields(stmt);
  }
  else
  {
    /*
      Update result set metadata if it for some reason changed between
      prepare and execute, i.e.:
      - in case of 'SELECT ?' we don't know column type unless data was
      supplied to mysql_stmt_execute, so updated column type is sent
      now.
      - if data dictionary changed between prepare and execute, for
      example a table used in the query was altered.
      Note, that now (4.1.3) we always send metadata in reply to
      COM_STMT_EXECUTE (even if it is not necessary), so either this or
      previous branch always works.
      TODO: send metadata only when it's really necessary and add a warning
      'Metadata changed' when it's sent twice.
    */
    update_stmt_fields(stmt);
  }
}

Project: mysql-server
File: libmysql.c

mysql_set_server_option(MYSQL *mysql, enum enum_mysql_set_option option)
{
  uchar buff[2];
  DBUG_ENTER("mysql_set_server_option");
  int2store(buff, (uint) option);
  DBUG_RETURN(simple_command(mysql, COM_SET_OPTION, buff, sizeof(buff), 0));
}

Project: mysql-server
File: libmysql.c

static int stmt_fetch_row(MYSQL_STMT *stmt, uchar *row)
{
  MYSQL_BIND  *my_bind, *end;
  MYSQL_FIELD *field;
  uchar *null_ptr, bit;
  int truncation_count= 0;
  /*
    Precondition: if stmt->field_count is zero or row is NULL, read_row_*
    function must return no data.
  */
  DBUG_ASSERT(stmt->field_count);
  DBUG_ASSERT(row);

  if (!stmt->bind_result_done)
  {
    /* If output parameters were not bound we should just return success */
    return 0;
  }

  null_ptr= row;
  row+= (stmt->field_count+9)/8;		/* skip null bits */
  bit= 4;					/* first 2 bits are reserved */

  /* Copy complete row to application buffers */
  for (my_bind= stmt->bind, end= my_bind + stmt->field_count,
         field= stmt->fields ;
       my_bind < end ;
       my_bind++, field++)
  {
    *my_bind->error= 0;
    if (*null_ptr & bit)
    {
      /*
        We should set both row_ptr and is_null to be able to see
        nulls in mysql_stmt_fetch_column. This is because is_null may point
        to user data which can be overwritten between mysql_stmt_fetch and
        mysql_stmt_fetch_column, and in this case nullness of column will be
        lost. See mysql_stmt_fetch_column for details.
      */
      my_bind->row_ptr= NULL;
      *my_bind->is_null= 1;
    }
    else
    {
      *my_bind->is_null= 0;
      my_bind->row_ptr= row;
      (*my_bind->fetch_result)(my_bind, field, &row);
      truncation_count+= *my_bind->error;
    }
    if (!((bit<<=1) & 255))
    {
      bit= 1;					/* To next uchar */
      null_ptr++;
    }
  }
  if (truncation_count && (stmt->bind_result_done & REPORT_DATA_TRUNCATION))
    return MYSQL_DATA_TRUNCATED;
  return 0;
}

Project: mysql-server
File: libmysql.c

static int default_local_infile_read(void *ptr, char *buf, uint buf_len)
{
  int count;
  default_local_infile_data*data = (default_local_infile_data *) ptr;

  if ((count= (int) my_read(data->fd, (uchar *) buf, buf_len, MYF(0))) < 0)
  {
    data->error_num= EE_READ; /* the errmsg for not entire file read */
    my_snprintf(data->error_msg, sizeof(data->error_msg)-1,
		EE(EE_READ),
		data->filename, my_errno);
  }
  return count;
}

Project: mysql-server
File: libmysql.c

uint STDCALL mysql_thread_safe(void)
{
  return 1;
}

Project: mysql-server
File: libmysql.c

my_bool STDCALL mysql_stmt_close(MYSQL_STMT *stmt)
{
  MYSQL *mysql= stmt->mysql;
  int rc= 0;
  DBUG_ENTER("mysql_stmt_close");

  free_root(&stmt->result.alloc, MYF(0));
  free_root(&stmt->mem_root, MYF(0));
  free_root(&stmt->extension->fields_mem_root, MYF(0));

  if (mysql)
  {
    mysql->stmts= list_delete(mysql->stmts, &stmt->list);
    /*
      Clear NET error state: if the following commands come through
      successfully, connection will still be usable for other commands.
    */
    net_clear_error(&mysql->net);
    if ((int) stmt->state > (int) MYSQL_STMT_INIT_DONE)
    {
      uchar buff[MYSQL_STMT_HEADER];             /* 4 bytes - stmt id */

      if (mysql->unbuffered_fetch_owner == &stmt->unbuffered_fetch_cancelled)
        mysql->unbuffered_fetch_owner= 0;
      if (mysql->status != MYSQL_STATUS_READY)
      {
        /*
          Flush result set of the connection. If it does not belong
          to this statement, set a warning.
        */
        (*mysql->methods->flush_use_result)(mysql, TRUE);
        if (mysql->unbuffered_fetch_owner)
          *mysql->unbuffered_fetch_owner= TRUE;
        mysql->status= MYSQL_STATUS_READY;
      }
      int4store(buff, stmt->stmt_id);
      /*
        If stmt_command failed, it would have already raised
        error using set_mysql_error. Caller should use
        mysql_error() or mysql_errno() to find out details.
        Memory allocated for stmt will be released regardless
        of the error.
      */
      rc= stmt_command(mysql, COM_STMT_CLOSE, buff, 4, stmt);
    }
  }

  my_free(stmt->extension);
  my_free(stmt);

  DBUG_RETURN(test(rc));
}

Project: mysql-server
File: libmysql.c

static void read_binary_datetime(MYSQL_TIME *tm, uchar **pos)
{
  uint length= net_field_length(pos);

  if (length)
  {
    uchar *to= *pos;

    tm->neg=    0;
    tm->year=   (uint) sint2korr(to);
    tm->month=  (uint) to[2];
    tm->day=    (uint) to[3];

    if (length > 4)
    {
      tm->hour=   (uint) to[4];
      tm->minute= (uint) to[5];
      tm->second= (uint) to[6];
    }
    else
      tm->hour= tm->minute= tm->second= 0;
    tm->second_part= (length > 7) ? (ulong) sint4korr(to+7) : 0;
    tm->time_type= MYSQL_TIMESTAMP_DATETIME;

    *pos+= length;
  }
  else
    set_zero_time(tm, MYSQL_TIMESTAMP_DATETIME);
}

Project: mysql-server
File: libmysql.c

static my_bool setup_one_fetch_function(MYSQL_BIND *param, MYSQL_FIELD *field)
{
  DBUG_ENTER("setup_one_fetch_function");

  /* Setup data copy functions for the different supported types */
  switch (param->buffer_type) {
  case MYSQL_TYPE_NULL: /* for dummy binds */
    /*
      It's not binary compatible with anything the server can return:
      no need to setup fetch_result, as it'll be reset anyway
    */
    *param->length= 0;
    break;
  case MYSQL_TYPE_TINY:
    param->fetch_result= fetch_result_tinyint;
    *param->length= 1;
    break;
  case MYSQL_TYPE_SHORT:
  case MYSQL_TYPE_YEAR:
    param->fetch_result= fetch_result_short;
    *param->length= 2;
    break;
  case MYSQL_TYPE_INT24:
  case MYSQL_TYPE_LONG:
    param->fetch_result= fetch_result_int32;
    *param->length= 4;
    break;
  case MYSQL_TYPE_LONGLONG:
    param->fetch_result= fetch_result_int64;
    *param->length= 8;
    break;
  case MYSQL_TYPE_FLOAT:
    param->fetch_result= fetch_result_float;
    *param->length= 4;
    break;
  case MYSQL_TYPE_DOUBLE:
    param->fetch_result= fetch_result_double;
    *param->length= 8;
    break;
  case MYSQL_TYPE_TIME:
    param->fetch_result= fetch_result_time;
    *param->length= sizeof(MYSQL_TIME);
    break;
  case MYSQL_TYPE_DATE:
    param->fetch_result= fetch_result_date;
    *param->length= sizeof(MYSQL_TIME);
    break;
  case MYSQL_TYPE_DATETIME:
  case MYSQL_TYPE_TIMESTAMP:
    param->fetch_result= fetch_result_datetime;
    *param->length= sizeof(MYSQL_TIME);
    break;
  case MYSQL_TYPE_TINY_BLOB:
  case MYSQL_TYPE_MEDIUM_BLOB:
  case MYSQL_TYPE_LONG_BLOB:
  case MYSQL_TYPE_BLOB:
  case MYSQL_TYPE_BIT:
    DBUG_ASSERT(param->buffer_length != 0);
    param->fetch_result= fetch_result_bin;
    break;
  case MYSQL_TYPE_VAR_STRING:
  case MYSQL_TYPE_STRING:
  case MYSQL_TYPE_DECIMAL:
  case MYSQL_TYPE_NEWDECIMAL:
  case MYSQL_TYPE_NEWDATE:
    DBUG_ASSERT(param->buffer_length != 0);
    param->fetch_result= fetch_result_str;
    break;
  default:
    DBUG_PRINT("error", ("Unknown param->buffer_type: %u",
                         (uint) param->buffer_type));
    DBUG_RETURN(TRUE);
  }
  if (! is_binary_compatible(param->buffer_type, field->type))
    param->fetch_result= fetch_result_with_conversion;

  /* Setup skip_result functions (to calculate max_length) */
  param->skip_result= skip_result_fixed;
  switch (field->type) {
  case MYSQL_TYPE_NULL: /* for dummy binds */
    param->pack_length= 0;
    field->max_length= 0;
    break;
  case MYSQL_TYPE_TINY:
    param->pack_length= 1;
    field->max_length= 4;                     /* as in '-127' */
    break;
  case MYSQL_TYPE_YEAR:
  case MYSQL_TYPE_SHORT:
    param->pack_length= 2;
    field->max_length= 6;                     /* as in '-32767' */
    break;
  case MYSQL_TYPE_INT24:
    field->max_length= 9;  /* as in '16777216' or in '-8388607' */
    param->pack_length= 4;
    break;
  case MYSQL_TYPE_LONG:
    field->max_length= 11;                    /* '-2147483647' */
    param->pack_length= 4;
    break;
  case MYSQL_TYPE_LONGLONG:
    field->max_length= 21;                    /* '18446744073709551616' */
    param->pack_length= 8;
    break;
  case MYSQL_TYPE_FLOAT:
    param->pack_length= 4;
    field->max_length= MAX_DOUBLE_STRING_REP_LENGTH;
    break;
  case MYSQL_TYPE_DOUBLE:
    param->pack_length= 8;
    field->max_length= MAX_DOUBLE_STRING_REP_LENGTH;
    break;
  case MYSQL_TYPE_TIME:
    field->max_length= 15;                    /* 19:23:48.123456 */
    param->skip_result= skip_result_with_length;
    break;
  case MYSQL_TYPE_DATE:
    field->max_length= 10;                    /* 2003-11-11 */
    param->skip_result= skip_result_with_length;
    break;
  case MYSQL_TYPE_DATETIME:
  case MYSQL_TYPE_TIMESTAMP:
    param->skip_result= skip_result_with_length;
    field->max_length= MAX_DATE_STRING_REP_LENGTH;
    break;
  case MYSQL_TYPE_DECIMAL:
  case MYSQL_TYPE_NEWDECIMAL:
  case MYSQL_TYPE_ENUM:
  case MYSQL_TYPE_SET:
  case MYSQL_TYPE_GEOMETRY:
  case MYSQL_TYPE_TINY_BLOB:
  case MYSQL_TYPE_MEDIUM_BLOB:
  case MYSQL_TYPE_LONG_BLOB:
  case MYSQL_TYPE_BLOB:
  case MYSQL_TYPE_VAR_STRING:
  case MYSQL_TYPE_STRING:
  case MYSQL_TYPE_BIT:
  case MYSQL_TYPE_NEWDATE:
    param->skip_result= skip_result_string;
    break;
  default:
    DBUG_PRINT("error", ("Unknown field->type: %u", (uint) field->type));
    DBUG_RETURN(TRUE);
  }
  DBUG_RETURN(FALSE);
}

Project: mysql-server
File: libmysql.c

mysql_shutdown(MYSQL *mysql, enum mysql_enum_shutdown_level shutdown_level)
{
  uchar level[1];
  DBUG_ENTER("mysql_shutdown");
  level[0]= (uchar) shutdown_level;
  DBUG_RETURN(simple_command(mysql, COM_SHUTDOWN, level, 1, 0));
}

Project: mysql-server
File: libmysql.c

mysql_debug(const char *debug __attribute__((unused)))
{
#ifndef DBUG_OFF
  char	*env;
  if (debug)
  {
    DBUG_PUSH(debug);
  }
  else if ((env = getenv("MYSQL_DEBUG")))
  {
    DBUG_PUSH(env);
#if !defined(_WINVER) && !defined(WINVER)
    puts("\n-------------------------------------------------------");
    puts("MYSQL_DEBUG found. libmysql started with the following:");
    puts(env);
    puts("-------------------------------------------------------\n");
#else
    {
      char buff[80];
      buff[sizeof(buff)-1]= 0;
      strxnmov(buff,sizeof(buff)-1,"libmysql: ", env, NullS);
      MessageBox((HWND) 0,"Debugging variable MYSQL_DEBUG used",buff,MB_OK);
    }
#endif
  }
#endif
}

Project: mysql-server
File: libmysql.c

static my_bool execute(MYSQL_STMT *stmt, char *packet, ulong length)
{
  MYSQL *mysql= stmt->mysql;
  NET	*net= &mysql->net;
  uchar buff[4 /* size of stmt id */ +
             5 /* execution flags */];
  my_bool res;
  DBUG_ENTER("execute");
  DBUG_DUMP("packet", (uchar *) packet, length);

  int4store(buff, stmt->stmt_id);		/* Send stmt id to server */
  buff[4]= (char) stmt->flags;
  int4store(buff+5, 1);                         /* iteration count */

  res= test(cli_advanced_command(mysql, COM_STMT_EXECUTE, buff, sizeof(buff),
                                 (uchar*) packet, length, 1, stmt) ||
            (*mysql->methods->read_query_result)(mysql));
  stmt->affected_rows= mysql->affected_rows;
  stmt->server_status= mysql->server_status;
  stmt->insert_id= mysql->insert_id;
  if (res)
  {
    /* 
      Don't set stmt error if stmt->mysql is NULL, as the error in this case 
      has already been set by mysql_prune_stmt_list(). 
    */
    if (stmt->mysql)
      set_stmt_errmsg(stmt, net);
    DBUG_RETURN(1);
  }
  else if (mysql->status == MYSQL_STATUS_GET_RESULT)
    stmt->mysql->status= MYSQL_STATUS_STATEMENT_GET_RESULT;
  DBUG_RETURN(0);
}

Project: mysql-server
File: libmysql.c

mysql_get_client_info(void)
{
  return (char*) MYSQL_SERVER_VERSION;
}

Project: mysql-server
File: libmysql.c

static void store_param_str(NET *net, MYSQL_BIND *param)
{
  /* param->length is always set in mysql_stmt_bind_param */
  ulong length= *param->length;
  uchar *to= net_store_length(net->write_pos, length);
  memcpy(to, param->buffer, length);
  net->write_pos= to+length;
}

Project: mysql-server
File: libmysql.c

int cli_stmt_execute(MYSQL_STMT *stmt)
{
  DBUG_ENTER("cli_stmt_execute");

  if (stmt->param_count)
  {
    MYSQL *mysql= stmt->mysql;
    NET        *net= &mysql->net;
    MYSQL_BIND *param, *param_end;
    char       *param_data;
    ulong length;
    uint null_count;
    my_bool    result;

    if (!stmt->bind_param_done)
    {
      set_stmt_error(stmt, CR_PARAMS_NOT_BOUND, unknown_sqlstate, NULL);
      DBUG_RETURN(1);
    }
    if (mysql->status != MYSQL_STATUS_READY ||
        mysql->server_status & SERVER_MORE_RESULTS_EXISTS)
    {
      set_stmt_error(stmt, CR_COMMANDS_OUT_OF_SYNC, unknown_sqlstate, NULL);
      DBUG_RETURN(1);
    }

    if (net->vio)
      net_clear(net, 1);          /* Sets net->write_pos */
    else
    {
      set_stmt_errmsg(stmt, net);
      DBUG_RETURN(1);             
    }

    /* Reserve place for null-marker bytes */
    null_count= (stmt->param_count+7) /8;
    if (my_realloc_str(net, null_count + 1))
    {
      set_stmt_errmsg(stmt, net);
      DBUG_RETURN(1);
    }
    bzero((char*) net->write_pos, null_count);
    net->write_pos+= null_count;
    param_end= stmt->params + stmt->param_count;

    /* In case if buffers (type) altered, indicate to server */
    *(net->write_pos)++= (uchar) stmt->send_types_to_server;
    if (stmt->send_types_to_server)
    {
      if (my_realloc_str(net, 2 * stmt->param_count))
      {
        set_stmt_errmsg(stmt, net);
        DBUG_RETURN(1);
      }
      /*
	Store types of parameters in first in first package
	that is sent to the server.
      */
      for (param= stmt->params;	param < param_end ; param++)
        store_param_type(&net->write_pos, param);
    }

    for (param= stmt->params; param < param_end; param++)
    {
      /* check if mysql_stmt_send_long_data() was used */
      if (param->long_data_used)
	param->long_data_used= 0;	/* Clear for next execute call */
      else if (store_param(stmt, param))
	DBUG_RETURN(1);
    }
    length= (ulong) (net->write_pos - net->buff);
    /* TODO: Look into avoding the following memdup */
    if (!(param_data= my_memdup(net->buff, length, MYF(0))))
    {
      set_stmt_error(stmt, CR_OUT_OF_MEMORY, unknown_sqlstate, NULL);
      DBUG_RETURN(1);
    }
    result= execute(stmt, param_data, length);
    stmt->send_types_to_server=0;
    my_free(param_data);
    DBUG_RETURN(result);
  }
  DBUG_RETURN((int) execute(stmt,0,0));
}

Project: mysql-server
File: libmysql.c

mysql_get_proto_info(MYSQL *mysql)
{
  return (mysql->protocol_version);
}

Project: mysql-server
File: libmysql.c

uint STDCALL mysql_warning_count(MYSQL *mysql)
{
  return mysql->warning_count;
}

Project: mysql-server
File: libmysql.c

mysql_drop_db(MYSQL *mysql, const char *db)
{
  DBUG_ENTER("mysql_drop_db");
  DBUG_PRINT("enter",("db: %s",db));
  DBUG_RETURN(simple_command(mysql,COM_DROP_DB,db,(ulong) strlen(db),0));
}

Project: mysql-server
File: libmysql.c

default_local_infile_error(void *ptr, char *error_msg, uint error_msg_len)
{
  default_local_infile_data *data = (default_local_infile_data *) ptr;
  if (data)					/* If not error on open */
  {
    strmake(error_msg, data->error_msg, error_msg_len);
    return data->error_num;
  }
  /* This can only happen if we got error on malloc of handle */
  strmov(error_msg, ER(CR_OUT_OF_MEMORY));
  return CR_OUT_OF_MEMORY;
}

Project: mysql-server
File: libmysql.c

static void net_store_datetime(NET *net, MYSQL_TIME *tm)
{
  char buff[MAX_DATETIME_REP_LENGTH], *pos;
  uint length;

  pos= buff+1;

  int2store(pos, tm->year);
  pos[2]= (uchar) tm->month;
  pos[3]= (uchar) tm->day;
  pos[4]= (uchar) tm->hour;
  pos[5]= (uchar) tm->minute;
  pos[6]= (uchar) tm->second;
  int4store(pos+7, tm->second_part);
  if (tm->second_part)
    length= 11;
  else if (tm->hour || tm->minute || tm->second)
    length= 7;
  else if (tm->year || tm->month || tm->day)
    length= 4;
  else
    length= 0;
  buff[0]= (char) length++;
  memcpy((char *)net->write_pos, buff, length);
  net->write_pos+= length;
}

Project: mysql-server
File: libmysql.c

mysql_refresh(MYSQL *mysql,uint options)
{
  uchar bits[1];
  DBUG_ENTER("mysql_refresh");
  bits[0]= (uchar) options;
  DBUG_RETURN(simple_command(mysql, COM_REFRESH, bits, 1, 0));
}

Project: mysql-server
File: libmysql.c

append_wild(char *to, char *end, const char *wild)
{
  end-=5;					/* Some extra */
  if (wild && wild[0])
  {
    to=strmov(to," like '");
    while (*wild && to < end)
    {
      if (*wild == '\\' || *wild == '\'')
	*to++='\\';
      *to++= *wild++;
    }
    if (*wild)					/* Too small buffer */
      *to++='%';				/* Nicer this way */
    to[0]='\'';
    to[1]=0;
  }
}

Project: mysql-server
File: libmysql.c

my_bool STDCALL mysql_rollback(MYSQL * mysql)
{
  DBUG_ENTER("mysql_rollback");
  DBUG_RETURN((my_bool) mysql_real_query(mysql, "rollback", 8));
}

Project: mysql-server
File: libmysql.c

void my_net_local_init(NET *net)
{
  net->max_packet=   (uint) net_buffer_length;
  my_net_set_read_timeout(net, CLIENT_NET_READ_TIMEOUT);
  my_net_set_write_timeout(net, CLIENT_NET_WRITE_TIMEOUT);
  net->retry_count=  1;
  net->max_packet_size= max(net_buffer_length, max_allowed_packet);
}

Project: mysql-server
File: libmysql.c

static void fetch_result_with_conversion(MYSQL_BIND *param, MYSQL_FIELD *field,
                                         uchar **row)
{
  enum enum_field_types field_type= field->type;
  uint field_is_unsigned= field->flags & UNSIGNED_FLAG;

  switch (field_type) {
  case MYSQL_TYPE_TINY:
  {
    uchar value= **row;
    /* sic: we need to cast to 'signed char' as 'char' may be unsigned */
    longlong data= field_is_unsigned ? (longlong) value :
                                       (longlong) (signed char) value;
    fetch_long_with_conversion(param, field, data, 0);
    *row+= 1;
    break;
  }
  case MYSQL_TYPE_SHORT:
  case MYSQL_TYPE_YEAR:
  {
    short value= sint2korr(*row);
    longlong data= field_is_unsigned ? (longlong) (unsigned short) value :
                                       (longlong) value;
    fetch_long_with_conversion(param, field, data, 0);
    *row+= 2;
    break;
  }
  case MYSQL_TYPE_INT24: /* mediumint is sent as 4 bytes int */
  case MYSQL_TYPE_LONG:
  {
    int32 value= sint4korr(*row);
    longlong data= field_is_unsigned ? (longlong) (uint32) value :
                                       (longlong) value;
    fetch_long_with_conversion(param, field, data, 0);
    *row+= 4;
    break;
  }
  case MYSQL_TYPE_LONGLONG:
  {
    longlong value= (longlong)sint8korr(*row);
    fetch_long_with_conversion(param, field, value,
                               field->flags & UNSIGNED_FLAG);
    *row+= 8;
    break;
  }
  case MYSQL_TYPE_FLOAT:
  {
    float value;
    float4get(value,*row);
    fetch_float_with_conversion(param, field, value, MY_GCVT_ARG_FLOAT);
    *row+= 4;
    break;
  }
  case MYSQL_TYPE_DOUBLE:
  {
    double value;
    float8get(value,*row);
    fetch_float_with_conversion(param, field, value, MY_GCVT_ARG_DOUBLE);
    *row+= 8;
    break;
  }
  case MYSQL_TYPE_DATE:
  {
    MYSQL_TIME tm;

    read_binary_date(&tm, row);
    fetch_datetime_with_conversion(param, field, &tm);
    break;
  }
  case MYSQL_TYPE_TIME:
  {
    MYSQL_TIME tm;

    read_binary_time(&tm, row);
    fetch_datetime_with_conversion(param, field, &tm);
    break;
  }
  case MYSQL_TYPE_DATETIME:
  case MYSQL_TYPE_TIMESTAMP:
  {
    MYSQL_TIME tm;

    read_binary_datetime(&tm, row);
    fetch_datetime_with_conversion(param, field, &tm);
    break;
  }
  default:
  {
    ulong length= net_field_length(row);
    fetch_string_with_conversion(param, (char*) *row, length);
    *row+= length;
    break;
  }
  }
}

Project: mysql-server
File: libmysql.c

static void fetch_result_datetime(MYSQL_BIND *param,
                                  MYSQL_FIELD *field __attribute__((unused)),
                                  uchar **row)
{
  MYSQL_TIME *tm= (MYSQL_TIME *)param->buffer;
  read_binary_datetime(tm, row);
}

Project: mysql-server
File: libmysql.c

my_ulonglong STDCALL mysql_affected_rows(MYSQL *mysql)
{
  return mysql->affected_rows;
}

Project: mysql-server
File: libmysql.c

my_bool STDCALL mysql_more_results(MYSQL *mysql)
{
  my_bool res;
  DBUG_ENTER("mysql_more_results");

  res= ((mysql->server_status & SERVER_MORE_RESULTS_EXISTS) ? 1: 0);
  DBUG_PRINT("exit",("More results exists ? %d", res));
  DBUG_RETURN(res);
}

Project: mysql-server
File: libmysql.c

stmt_read_row_from_cursor(MYSQL_STMT *stmt, unsigned char **row)
{
  if (stmt->data_cursor)
    return stmt_read_row_buffered(stmt, row);
  if (stmt->server_status & SERVER_STATUS_LAST_ROW_SENT)
    stmt->server_status &= ~SERVER_STATUS_LAST_ROW_SENT;
  else
  {
    MYSQL *mysql= stmt->mysql;
    NET *net= &mysql->net;
    MYSQL_DATA *result= &stmt->result;
    uchar buff[4 /* statement id */ +
               4 /* number of rows to fetch */];

    free_root(&result->alloc, MYF(MY_KEEP_PREALLOC));
    result->data= NULL;
    result->rows= 0;
    /* Send row request to the server */
    int4store(buff, stmt->stmt_id);
    int4store(buff + 4, stmt->prefetch_rows); /* number of rows to fetch */
    if ((*mysql->methods->advanced_command)(mysql, COM_STMT_FETCH,
                                            buff, sizeof(buff), (uchar*) 0, 0,
                                            1, stmt))
    {
      /* 
        Don't set stmt error if stmt->mysql is NULL, as the error in this case 
        has already been set by mysql_prune_stmt_list(). 
      */
      if (stmt->mysql)
        set_stmt_errmsg(stmt, net);
      return 1;
    }
    if ((*mysql->methods->read_rows_from_cursor)(stmt))
      return 1;
    stmt->server_status= mysql->server_status;

    stmt->data_cursor= result->data;
    return stmt_read_row_buffered(stmt, row);
  }
  *row= 0;
  return MYSQL_NO_DATA;
}

Project: mysql-server
File: libmysql.c

mysql_row_seek(MYSQL_RES *result, MYSQL_ROW_OFFSET row)
{
  MYSQL_ROW_OFFSET return_value=result->data_cursor;
  result->current_row= 0;
  result->data_cursor= row;
  return return_value;
}

Project: mysql-server
File: libmysql.c

mysql_stmt_data_seek(MYSQL_STMT *stmt, my_ulonglong row)
{
  MYSQL_ROWS *tmp= stmt->result.data;
  DBUG_ENTER("mysql_stmt_data_seek");
  DBUG_PRINT("enter",("row id to seek: %ld",(long) row));

  for (; tmp && row; --row, tmp= tmp->next)
    ;
  stmt->data_cursor= tmp;
  if (!row && tmp)
  {
       /*  Rewind the counter */
    stmt->read_row_func= stmt_read_row_buffered;
    stmt->state= MYSQL_STMT_EXECUTE_DONE;
  }
  DBUG_VOID_RETURN;
}

Project: mysql-server
File: libmysql.c

const char *STDCALL mysql_stmt_sqlstate(MYSQL_STMT * stmt)
{
  DBUG_ENTER("mysql_stmt_sqlstate");
  DBUG_RETURN(stmt->sqlstate);
}

Project: mysql-server
File: libmysql.c

mysql_field_seek(MYSQL_RES *result, MYSQL_FIELD_OFFSET field_offset)
{
  MYSQL_FIELD_OFFSET return_value=result->current_field;
  result->current_field=field_offset;
  return return_value;
}

Project: mysql-server
File: libmysql.c

static void store_param_short(NET *net, MYSQL_BIND *param)
{
  short value= *(short*) param->buffer;
  int2store(net->write_pos,value);
  net->write_pos+=2;
}

Project: mysql-server
File: libmysql.c

my_bool	STDCALL mysql_change_user(MYSQL *mysql, const char *user,
				  const char *passwd, const char *db)
{
  int rc;
  CHARSET_INFO *saved_cs= mysql->charset;
  char *saved_user= mysql->user;
  char *saved_passwd= mysql->passwd;
  char *saved_db= mysql->db;

  DBUG_ENTER("mysql_change_user");

  /* Get the connection-default character set. */

  if (mysql_init_character_set(mysql))
  {
    mysql->charset= saved_cs;
    DBUG_RETURN(TRUE);
  }

  /* Use an empty string instead of NULL. */

  mysql->user= (char*)(user ? user : "");
  mysql->passwd= (char*)(passwd ? passwd : "");
  mysql->db= 0;

  rc= run_plugin_auth(mysql, 0, 0, 0, db);

  /*
    The server will close all statements no matter was the attempt
    to change user successful or not.
  */
  mysql_detach_stmt_list(&mysql->stmts, "mysql_change_user");
  if (rc == 0)
  {
    /* Free old connect information */
    my_free(saved_user);
    my_free(saved_passwd);
    my_free(saved_db);

    /* alloc new connect information */
    mysql->user= my_strdup(mysql->user, MYF(MY_WME));
    mysql->passwd= my_strdup(mysql->passwd, MYF(MY_WME));
    mysql->db= db ? my_strdup(db, MYF(MY_WME)) : 0;
  }
  else
  {
    mysql->charset= saved_cs;
    mysql->user= saved_user;
    mysql->passwd= saved_passwd;
    mysql->db= saved_db;
  }

  DBUG_RETURN(rc);
}

Project: mysql-server
File: libmysql.c

int cli_unbuffered_fetch(MYSQL *mysql, char **row)
{
  if (packet_error == cli_safe_read(mysql))
    return 1;

  *row= ((mysql->net.read_pos[0] == 254) ? NULL :
	 (char*) (mysql->net.read_pos+1));
  return 0;
}

Project: mysql-server
File: libmysql.c

const char *cli_read_statistics(MYSQL *mysql)
{
  mysql->net.read_pos[mysql->packet_length]=0;	/* End of stat string */
  if (!mysql->net.read_pos[0])
  {
    set_mysql_error(mysql, CR_WRONG_HOST_INFO, unknown_sqlstate);
    return mysql->net.last_error;
  }
  return (char*) mysql->net.read_pos;
}

Project: mysql-server
File: libmysql.c

myodbc_remove_escape(MYSQL *mysql,char *name)
{
  char *to;
#ifdef USE_MB
  my_bool use_mb_flag=use_mb(mysql->charset);
  char *UNINIT_VAR(end);
  if (use_mb_flag)
    for (end=name; *end ; end++) ;
#endif

  for (to=name ; *name ; name++)
  {
#ifdef USE_MB
    int l;
    if (use_mb_flag && (l = my_ismbchar( mysql->charset, name , end ) ) )
    {
      while (l--)
	*to++ = *name++;
      name--;
      continue;
    }
#endif
    if (*name == '\\' && name[1])
      name++;
    *to++= *name;
  }
  *to=0;
}

Project: mysql-server
File: libmysql.c

MYSQL_FIELD *cli_list_fields(MYSQL *mysql)
{
  MYSQL_DATA *query;
  if (!(query= cli_read_rows(mysql,(MYSQL_FIELD*) 0, 
			     protocol_41(mysql) ? 8 : 6)))
    return NULL;

  mysql->field_count= (uint) query->rows;
  return unpack_fields(mysql, query,&mysql->field_alloc,
		       mysql->field_count, 1, mysql->server_capabilities);
}

Project: mysql-server
File: libmysql.c

static void store_param_datetime(NET *net, MYSQL_BIND *param)
{
  MYSQL_TIME *tm= (MYSQL_TIME *) param->buffer;
  net_store_datetime(net, tm);
}

Project: mysql-server
File: libmysql.c

static void skip_result_fixed(MYSQL_BIND *param,
			      MYSQL_FIELD *field __attribute__((unused)),
			      uchar **row)

{
  (*row)+= param->pack_length;
}

Project: mysql-server
File: libmysql.c

mysql_stmt_row_seek(MYSQL_STMT *stmt, MYSQL_ROW_OFFSET row)
{
  MYSQL_ROW_OFFSET offset= stmt->data_cursor;
  DBUG_ENTER("mysql_stmt_row_seek");

  stmt->data_cursor= row;
  DBUG_RETURN(offset);
}

Project: mysql-server
File: libmysql.c

static void fetch_float_with_conversion(MYSQL_BIND *param, MYSQL_FIELD *field,
                                        double value, my_gcvt_arg_type type)
{
  char *buffer= (char *)param->buffer;
  double val64 = (value < 0 ? -floor(-value) : floor(value));

  switch (param->buffer_type) {
  case MYSQL_TYPE_NULL: /* do nothing */
    break;
  case MYSQL_TYPE_TINY:
    /*
      We need to _store_ data in the buffer before the truncation check to
      workaround Intel FPU executive precision feature.
      (See http://gcc.gnu.org/bugzilla/show_bug.cgi?id=323 for details)
      Sic: AFAIU it does not guarantee to work.
    */
    if (param->is_unsigned)
      *buffer= (uint8) value;
    else
      *buffer= (int8) value;
    *param->error= val64 != (param->is_unsigned ? (double)((uint8) *buffer) :
                                                  (double)((int8) *buffer));
    break;
  case MYSQL_TYPE_SHORT:
    if (param->is_unsigned)
    {
      ushort data= (ushort) value;
      shortstore(buffer, data);
    }
    else
    {
      short data= (short) value;
      shortstore(buffer, data);
    }
    *param->error= val64 != (param->is_unsigned ? (double) (*(ushort*) buffer):
                                                  (double) (*(short*) buffer));
    break;
  case MYSQL_TYPE_LONG:
    if (param->is_unsigned)
    {
      uint32 data= (uint32) value;
      longstore(buffer, data);
    }
    else
    {
      int32 data= (int32) value;
      longstore(buffer, data);
    }
    *param->error= val64 != (param->is_unsigned ? (double) (*(uint32*) buffer):
                                                  (double) (*(int32*) buffer));
      break;
  case MYSQL_TYPE_LONGLONG:
    if (param->is_unsigned)
    {
      ulonglong data= (ulonglong) value;
      longlongstore(buffer, data);
    }
    else
    {
      longlong data= (longlong) value;
      longlongstore(buffer, data);
    }
    *param->error= val64 != (param->is_unsigned ?
                             ulonglong2double(*(ulonglong*) buffer) :
                             (double) (*(longlong*) buffer));
    break;
  case MYSQL_TYPE_FLOAT:
  {
    float data= (float) value;
    floatstore(buffer, data);
    *param->error= (*(float*) buffer) != value;
    break;
  }
  case MYSQL_TYPE_DOUBLE:
  {
    doublestore(buffer, value);
    break;
  }
  default:
  {
    /*
      Resort to fetch_string_with_conversion: this should handle
      floating point -> string conversion nicely, honor all typecodes
      and param->offset possibly set in mysql_stmt_fetch_column
    */
    char buff[FLOATING_POINT_BUFFER];
    size_t len;
    if (field->decimals >= NOT_FIXED_DEC)
      len= my_gcvt(value, type,
                   (int) min(sizeof(buff)-1, param->buffer_length),
                   buff, NULL);
    else
      len= my_fcvt(value, (int) field->decimals, buff, NULL);

    if (field->flags & ZEROFILL_FLAG && len < field->length &&
        field->length < MAX_DOUBLE_STRING_REP_LENGTH - 1)
    {
      bmove_upp((uchar*) buff + field->length, (uchar*) buff + len,
                len);
      bfill((char*) buff, field->length - len, '0');
      len= field->length;
    }
    fetch_string_with_conversion(param, buff, len);

    break;
  }
  }
}

Project: mysql-server
File: libmysql.c

void STDCALL mysql_get_character_set_info(MYSQL *mysql, MY_CHARSET_INFO *csinfo)
{
  csinfo->number   = mysql->charset->number;
  csinfo->state    = mysql->charset->state;
  csinfo->csname   = mysql->charset->csname;
  csinfo->name     = mysql->charset->name;
  csinfo->comment  = mysql->charset->comment;
  csinfo->mbminlen = mysql->charset->mbminlen;
  csinfo->mbmaxlen = mysql->charset->mbmaxlen;

  if (mysql->options.charset_dir)
    csinfo->dir = mysql->options.charset_dir;
  else
    csinfo->dir = charsets_dir;
}

Project: mysql-server
File: libmysql.c

my_bool STDCALL mysql_stmt_attr_get(MYSQL_STMT *stmt,
                                    enum enum_stmt_attr_type attr_type,
                                    void *value)
{
  switch (attr_type) {
  case STMT_ATTR_UPDATE_MAX_LENGTH:
    *(my_bool*) value= stmt->update_max_length;
    break;
  case STMT_ATTR_CURSOR_TYPE:
    *(ulong*) value= stmt->flags;
    break;
  case STMT_ATTR_PREFETCH_ROWS:
    *(ulong*) value= stmt->prefetch_rows;
    break;
  default:
    return TRUE;
  }
  return FALSE;
}

Project: mysql-server
File: libmysql.c

static my_bool is_binary_compatible(enum enum_field_types type1,
                                    enum enum_field_types type2)
{
  static const enum enum_field_types
    range1[]= { MYSQL_TYPE_SHORT, MYSQL_TYPE_YEAR, MYSQL_TYPE_NULL },
    range2[]= { MYSQL_TYPE_INT24, MYSQL_TYPE_LONG, MYSQL_TYPE_NULL },
    range3[]= { MYSQL_TYPE_DATETIME, MYSQL_TYPE_TIMESTAMP, MYSQL_TYPE_NULL },
    range4[]= { MYSQL_TYPE_ENUM, MYSQL_TYPE_SET, MYSQL_TYPE_TINY_BLOB,
                MYSQL_TYPE_MEDIUM_BLOB, MYSQL_TYPE_LONG_BLOB, MYSQL_TYPE_BLOB,
                MYSQL_TYPE_VAR_STRING, MYSQL_TYPE_STRING, MYSQL_TYPE_GEOMETRY,
                MYSQL_TYPE_DECIMAL, MYSQL_TYPE_NULL };
  static const enum enum_field_types
   *range_list[]= { range1, range2, range3, range4 },
   **range_list_end= range_list + sizeof(range_list)/sizeof(*range_list);
   const enum enum_field_types **range, *type;

  if (type1 == type2)
    return TRUE;
  for (range= range_list; range != range_list_end; ++range)
  {
    /* check that both type1 and type2 are in the same range */
    my_bool type1_found= FALSE, type2_found= FALSE;
    for (type= *range; *type != MYSQL_TYPE_NULL; type++)
    {
      type1_found|= type1 == *type;
      type2_found|= type2 == *type;
    }
    if (type1_found || type2_found)
      return type1_found && type2_found;
  }
  return FALSE;
}

Project: mysql-server
File: libmysql.c

mysql_list_dbs(MYSQL *mysql, const char *wild)
{
  char buff[255];
  DBUG_ENTER("mysql_list_dbs");

  append_wild(strmov(buff,"show databases"),buff+sizeof(buff),wild);
  if (mysql_query(mysql,buff))
    DBUG_RETURN(0);
  DBUG_RETURN (mysql_store_result(mysql));
}

Project: mysql-server
File: libmysql.c

static void fetch_string_with_conversion(MYSQL_BIND *param, char *value,
                                         uint length)
{
  char *buffer= (char *)param->buffer;
  int err= 0;
  char *endptr= value + length;

  /*
    This function should support all target buffer types: the rest
    of conversion functions can delegate conversion to it.
  */
  switch (param->buffer_type) {
  case MYSQL_TYPE_NULL: /* do nothing */
    break;
  case MYSQL_TYPE_TINY:
  {
    longlong data= my_strtoll10(value, &endptr, &err);
    *param->error= (IS_TRUNCATED(data, param->is_unsigned,
                                 INT_MIN8, INT_MAX8, UINT_MAX8) || err > 0);
    *buffer= (uchar) data;
    break;
  }
  case MYSQL_TYPE_SHORT:
  {
    longlong data= my_strtoll10(value, &endptr, &err);
    *param->error= (IS_TRUNCATED(data, param->is_unsigned,
                                 INT_MIN16, INT_MAX16, UINT_MAX16) || err > 0);
    shortstore(buffer, (short) data);
    break;
  }
  case MYSQL_TYPE_LONG:
  {
    longlong data= my_strtoll10(value, &endptr, &err);
    *param->error= (IS_TRUNCATED(data, param->is_unsigned,
                                 INT_MIN32, INT_MAX32, UINT_MAX32) || err > 0);
    longstore(buffer, (int32) data);
    break;
  }
  case MYSQL_TYPE_LONGLONG:
  {
    longlong data= my_strtoll10(value, &endptr, &err);
    *param->error= param->is_unsigned ? err != 0 :
                                       (err > 0 || (err == 0 && data < 0));
    longlongstore(buffer, data);
    break;
  }
  case MYSQL_TYPE_FLOAT:
  {
    double data= my_strntod(&my_charset_latin1, value, length, &endptr, &err);
    float fdata= (float) data;
    *param->error= (fdata != data) | test(err);
    floatstore(buffer, fdata);
    break;
  }
  case MYSQL_TYPE_DOUBLE:
  {
    double data= my_strntod(&my_charset_latin1, value, length, &endptr, &err);
    *param->error= test(err);
    doublestore(buffer, data);
    break;
  }
  case MYSQL_TYPE_TIME:
  {
    MYSQL_TIME *tm= (MYSQL_TIME *)buffer;
    str_to_time(value, length, tm, &err);
    *param->error= test(err);
    break;
  }
  case MYSQL_TYPE_DATE:
  case MYSQL_TYPE_DATETIME:
  case MYSQL_TYPE_TIMESTAMP:
  {
    MYSQL_TIME *tm= (MYSQL_TIME *)buffer;
    (void) str_to_datetime(value, length, tm, TIME_FUZZY_DATE, &err);
    *param->error= test(err) && (param->buffer_type == MYSQL_TYPE_DATE &&
                                 tm->time_type != MYSQL_TIMESTAMP_DATE);
    break;
  }
  case MYSQL_TYPE_TINY_BLOB:
  case MYSQL_TYPE_MEDIUM_BLOB:
  case MYSQL_TYPE_LONG_BLOB:
  case MYSQL_TYPE_BLOB:
  case MYSQL_TYPE_DECIMAL:
  case MYSQL_TYPE_NEWDECIMAL:
  default:
  {
    /*
      Copy column data to the buffer taking into account offset,
      data length and buffer length.
    */
    char *start= value + param->offset;
    char *end= value + length;
    ulong copy_length;
    if (start < end)
    {
      copy_length= end - start;
      /* We've got some data beyond offset: copy up to buffer_length bytes */
      if (param->buffer_length)
        memcpy(buffer, start, min(copy_length, param->buffer_length));
    }
    else
      copy_length= 0;
    if (copy_length < param->buffer_length)
      buffer[copy_length]= '\0';
    *param->error= copy_length > param->buffer_length;
    /*
      param->length will always contain length of entire column;
      number of copied bytes may be way different:
    */
    *param->length= length;
    break;
  }
  }
}

Project: mysql-server
File: libmysql.c

int STDCALL mysql_stmt_fetch_column(MYSQL_STMT *stmt, MYSQL_BIND *my_bind,
                                    uint column, ulong offset)
{
  MYSQL_BIND *param= stmt->bind+column;
  DBUG_ENTER("mysql_stmt_fetch_column");

  if ((int) stmt->state < (int) MYSQL_STMT_FETCH_DONE)
  {
    set_stmt_error(stmt, CR_NO_DATA, unknown_sqlstate, NULL);
    DBUG_RETURN(1);
  }
  if (column >= stmt->field_count)
  {
    set_stmt_error(stmt, CR_INVALID_PARAMETER_NO, unknown_sqlstate, NULL);
    DBUG_RETURN(1);
  }

  if (!my_bind->error)
    my_bind->error= &my_bind->error_value;
  *my_bind->error= 0;
  if (param->row_ptr)
  {
    MYSQL_FIELD *field= stmt->fields+column;
    uchar *row= param->row_ptr;
    my_bind->offset= offset;
    if (my_bind->is_null)
      *my_bind->is_null= 0;
    if (my_bind->length) /* Set the length if non char/binary types */
      *my_bind->length= *param->length;
    else
      my_bind->length= &param->length_value;       /* Needed for fetch_result() */
    fetch_result_with_conversion(my_bind, field, &row);
  }
  else
  {
    if (my_bind->is_null)
      *my_bind->is_null= 1;
  }
  DBUG_RETURN(0);
}

Project: mysql-server
File: libmysql.c

int STDCALL mysql_next_result(MYSQL *mysql)
{
  DBUG_ENTER("mysql_next_result");

  if (mysql->status != MYSQL_STATUS_READY)
  {
    set_mysql_error(mysql, CR_COMMANDS_OUT_OF_SYNC, unknown_sqlstate);
    DBUG_RETURN(1);
  }

  net_clear_error(&mysql->net);
  mysql->affected_rows= ~(my_ulonglong) 0;

  if (mysql->server_status & SERVER_MORE_RESULTS_EXISTS)
    DBUG_RETURN((*mysql->methods->next_result)(mysql));

  DBUG_RETURN(-1);				/* No more results */
}

Project: mysql-server
File: libmysql.c

stmt_read_row_no_result_set(MYSQL_STMT *stmt  __attribute__((unused)),
                      unsigned char **row  __attribute__((unused)))
{
  set_stmt_error(stmt, CR_NO_RESULT_SET, unknown_sqlstate, NULL);
  return 1;
}

Project: mysql-server
File: libmysql.c

my_ulonglong STDCALL mysql_stmt_insert_id(MYSQL_STMT *stmt)
{
  return stmt->insert_id;
}

Project: mysql-server
File: libmysql.c

mysql_fetch_field(MYSQL_RES *result)
{
  if (result->current_field >= result->field_count)
    return(NULL);
  return &result->fields[result->current_field++];
}

Project: mysql-server
File: libmysql.c

static void store_param_time(NET *net, MYSQL_BIND *param)
{
  MYSQL_TIME *tm= (MYSQL_TIME *) param->buffer;
  char buff[MAX_TIME_REP_LENGTH], *pos;
  uint length;

  pos= buff+1;
  pos[0]= tm->neg ? 1: 0;
  int4store(pos+1, tm->day);
  pos[5]= (uchar) tm->hour;
  pos[6]= (uchar) tm->minute;
  pos[7]= (uchar) tm->second;
  int4store(pos+8, tm->second_part);
  if (tm->second_part)
    length= 12;
  else if (tm->hour || tm->minute || tm->second || tm->day)
    length= 8;
  else
    length= 0;
  buff[0]= (char) length++;
  memcpy((char *)net->write_pos, buff, length);
  net->write_pos+= length;
}

Project: mysql-server
File: libmysql.c

int cli_read_binary_rows(MYSQL_STMT *stmt)
{
  ulong      pkt_len;
  uchar      *cp;
  MYSQL      *mysql= stmt->mysql;
  MYSQL_DATA *result= &stmt->result;
  MYSQL_ROWS *cur, **prev_ptr= &result->data;
  NET        *net;

  DBUG_ENTER("cli_read_binary_rows");

  if (!mysql)
  {
    set_stmt_error(stmt, CR_SERVER_LOST, unknown_sqlstate, NULL);
    DBUG_RETURN(1);
  }

  net = &mysql->net;

  while ((pkt_len= cli_safe_read(mysql)) != packet_error)
  {
    cp= net->read_pos;
    if (cp[0] != 254 || pkt_len >= 8)
    {
      if (!(cur= (MYSQL_ROWS*) alloc_root(&result->alloc,
                                          sizeof(MYSQL_ROWS) + pkt_len - 1)))
      {
        set_stmt_error(stmt, CR_OUT_OF_MEMORY, unknown_sqlstate, NULL);
        goto err;
      }
      cur->data= (MYSQL_ROW) (cur+1);
      *prev_ptr= cur;
      prev_ptr= &cur->next;
      memcpy((char *) cur->data, (char *) cp+1, pkt_len-1);
      cur->length= pkt_len;		/* To allow us to do sanity checks */
      result->rows++;
    }
    else
    {
      /* end of data */
      *prev_ptr= 0;
      mysql->warning_count= uint2korr(cp+1);
      mysql->server_status= uint2korr(cp+3);
      DBUG_PRINT("info",("status: %u  warning_count: %u",
                         mysql->server_status, mysql->warning_count));
      DBUG_RETURN(0);
    }
  }
  set_stmt_errmsg(stmt, net);

err:
  DBUG_RETURN(1);
}

Project: mysql-server
File: libmysql.c

unsigned int STDCALL mysql_field_count(MYSQL *mysql)
{
  return mysql->field_count;
}

Project: mysql-server
File: libmysql.c

my_bool STDCALL mysql_stmt_bind_param(MYSQL_STMT *stmt, MYSQL_BIND *my_bind)
{
  uint count=0;
  MYSQL_BIND *param, *end;
  DBUG_ENTER("mysql_stmt_bind_param");

  if (!stmt->param_count)
  {
    if ((int) stmt->state < (int) MYSQL_STMT_PREPARE_DONE)
    {
      set_stmt_error(stmt, CR_NO_PREPARE_STMT, unknown_sqlstate, NULL);
      DBUG_RETURN(1);
    }
    DBUG_RETURN(0);
  }

  /* Allocated on prepare */
  memcpy((char*) stmt->params, (char*) my_bind,
	 sizeof(MYSQL_BIND) * stmt->param_count);

  for (param= stmt->params, end= param+stmt->param_count;
       param < end ;
       param++)
  {
    param->param_number= count++;
    param->long_data_used= 0;

    /* If param->is_null is not set, then the value can never be NULL */
    if (!param->is_null)
      param->is_null= &int_is_null_false;

    /* Setup data copy functions for the different supported types */
    switch (param->buffer_type) {
    case MYSQL_TYPE_NULL:
      param->is_null= &int_is_null_true;
      break;
    case MYSQL_TYPE_TINY:
      /* Force param->length as this is fixed for this type */
      param->length= &param->buffer_length;
      param->buffer_length= 1;
      param->store_param_func= store_param_tinyint;
      break;
    case MYSQL_TYPE_SHORT:
      param->length= &param->buffer_length;
      param->buffer_length= 2;
      param->store_param_func= store_param_short;
      break;
    case MYSQL_TYPE_LONG:
      param->length= &param->buffer_length;
      param->buffer_length= 4;
      param->store_param_func= store_param_int32;
      break;
    case MYSQL_TYPE_LONGLONG:
      param->length= &param->buffer_length;
      param->buffer_length= 8;
      param->store_param_func= store_param_int64;
      break;
    case MYSQL_TYPE_FLOAT:
      param->length= &param->buffer_length;
      param->buffer_length= 4;
      param->store_param_func= store_param_float;
      break;
    case MYSQL_TYPE_DOUBLE:
      param->length= &param->buffer_length;
      param->buffer_length= 8;
      param->store_param_func= store_param_double;
      break;
    case MYSQL_TYPE_TIME:
      param->store_param_func= store_param_time;
      param->buffer_length= MAX_TIME_REP_LENGTH;
      break;
    case MYSQL_TYPE_DATE:
      param->store_param_func= store_param_date;
      param->buffer_length= MAX_DATE_REP_LENGTH;
      break;
    case MYSQL_TYPE_DATETIME:
    case MYSQL_TYPE_TIMESTAMP:
      param->store_param_func= store_param_datetime;
      param->buffer_length= MAX_DATETIME_REP_LENGTH;
      break;
    case MYSQL_TYPE_TINY_BLOB:
    case MYSQL_TYPE_MEDIUM_BLOB:
    case MYSQL_TYPE_LONG_BLOB:
    case MYSQL_TYPE_BLOB:
    case MYSQL_TYPE_VARCHAR:
    case MYSQL_TYPE_VAR_STRING:
    case MYSQL_TYPE_STRING:
    case MYSQL_TYPE_DECIMAL:
    case MYSQL_TYPE_NEWDECIMAL:
      param->store_param_func= store_param_str;
      /*
        For variable length types user must set either length or
        buffer_length.
      */
      break;
    default:
      strmov(stmt->sqlstate, unknown_sqlstate);
      sprintf(stmt->last_error,
	      ER(stmt->last_errno= CR_UNSUPPORTED_PARAM_TYPE),
	      param->buffer_type, count);
      DBUG_RETURN(1);
    }
    /*
      If param->length is not given, change it to point to buffer_length.
      This way we can always use *param->length to get the length of data
    */
    if (!param->length)
      param->length= &param->buffer_length;
  }
  /* We have to send/resend type information to MySQL */
  stmt->send_types_to_server= TRUE;
  stmt->bind_param_done= TRUE;
  DBUG_RETURN(0);
}

Project: mysql-server
File: libmysql.c

void read_user_name(char *name)
{
  char *str=getenv("USER");		/* ODBC will send user variable */
  strmake(name,str ? str : "ODBC", USERNAME_LENGTH);
}

Project: mysql-server
File: libmysql.c

mysql_list_tables(MYSQL *mysql, const char *wild)
{
  char buff[255];
  DBUG_ENTER("mysql_list_tables");

  append_wild(strmov(buff,"show tables"),buff+sizeof(buff),wild);
  if (mysql_query(mysql,buff))
    DBUG_RETURN(0);
  DBUG_RETURN (mysql_store_result(mysql));
}

Project: mysql-server
File: libmysql.c

uint STDCALL mysql_stmt_errno(MYSQL_STMT * stmt)
{
  DBUG_ENTER("mysql_stmt_errno");
  DBUG_RETURN(stmt->last_errno);
}

Project: mysql-server
File: libmysql.c

static void fetch_result_int64(MYSQL_BIND *param,
                               MYSQL_FIELD *field __attribute__((unused)),
                               uchar **row)
{
  my_bool field_is_unsigned= test(field->flags & UNSIGNED_FLAG);
  ulonglong data= (ulonglong) sint8korr(*row);
  *param->error= param->is_unsigned != field_is_unsigned && data > LONGLONG_MAX;
  longlongstore(param->buffer, data);
  *row+= 8;
}

Project: mysql-server
File: libmysql.c

static void fetch_result_date(MYSQL_BIND *param,
                              MYSQL_FIELD *field __attribute__((unused)),
                              uchar **row)
{
  MYSQL_TIME *tm= (MYSQL_TIME *)param->buffer;
  read_binary_date(tm, row);
}

Project: mysql-server
File: libmysql.c

my_pipe_sig_handler(int sig __attribute__((unused)))
{
  DBUG_PRINT("info",("Hit by signal %d",sig));
#ifdef SIGNAL_HANDLER_RESET_ON_DELIVERY
  (void) signal(SIGPIPE, my_pipe_sig_handler);
#endif
}

Project: mysql-server
File: libmysql.c

int STDCALL mysql_stmt_store_result(MYSQL_STMT *stmt)
{
  MYSQL *mysql= stmt->mysql;
  MYSQL_DATA *result= &stmt->result;
  DBUG_ENTER("mysql_stmt_store_result");

  if (!mysql)
  {
    /* mysql can be reset in mysql_close called from mysql_reconnect */
    set_stmt_error(stmt, CR_SERVER_LOST, unknown_sqlstate, NULL);
    DBUG_RETURN(1);
  }

  if (!stmt->field_count)
    DBUG_RETURN(0);

  if ((int) stmt->state < (int) MYSQL_STMT_EXECUTE_DONE)
  {
    set_stmt_error(stmt, CR_COMMANDS_OUT_OF_SYNC, unknown_sqlstate, NULL);
    DBUG_RETURN(1);
  }

  if (stmt->last_errno)
  {
    /* An attempt to use an invalid statement handle. */
    DBUG_RETURN(1);
  }

  if (mysql->status == MYSQL_STATUS_READY &&
      stmt->server_status & SERVER_STATUS_CURSOR_EXISTS)
  {
    /*
      Server side cursor exist, tell server to start sending the rows
    */
    NET *net= &mysql->net;
    uchar buff[4 /* statement id */ +
               4 /* number of rows to fetch */];

    /* Send row request to the server */
    int4store(buff, stmt->stmt_id);
    int4store(buff + 4, (int)~0); /* number of rows to fetch */
    if (cli_advanced_command(mysql, COM_STMT_FETCH, buff, sizeof(buff),
                             (uchar*) 0, 0, 1, stmt))
    {
      /* 
        Don't set stmt error if stmt->mysql is NULL, as the error in this case 
        has already been set by mysql_prune_stmt_list(). 
      */
      if (stmt->mysql)
        set_stmt_errmsg(stmt, net);
      DBUG_RETURN(1);
    }
  }
  else if (mysql->status != MYSQL_STATUS_STATEMENT_GET_RESULT)
  {
    set_stmt_error(stmt, CR_COMMANDS_OUT_OF_SYNC, unknown_sqlstate, NULL);
    DBUG_RETURN(1);
  }

  if (stmt->update_max_length && !stmt->bind_result_done)
  {
    /*
      We must initalize the bind structure to be able to calculate
      max_length
    */
    MYSQL_BIND  *my_bind, *end;
    MYSQL_FIELD *field;
    bzero((char*) stmt->bind, sizeof(*stmt->bind)* stmt->field_count);

    for (my_bind= stmt->bind, end= my_bind + stmt->field_count,
           field= stmt->fields;
	 my_bind < end ;
	 my_bind++, field++)
    {
      my_bind->buffer_type= MYSQL_TYPE_NULL;
      my_bind->buffer_length=1;
    }

    if (mysql_stmt_bind_result(stmt, stmt->bind))
      DBUG_RETURN(1);
    stmt->bind_result_done= 0;			/* No normal bind done */
  }

  if ((*mysql->methods->read_binary_rows)(stmt))
  {
    free_root(&result->alloc, MYF(MY_KEEP_PREALLOC));
    result->data= NULL;
    result->rows= 0;
    mysql->status= MYSQL_STATUS_READY;
    DBUG_RETURN(1);
  }

  /* Assert that if there was a cursor, all rows have been fetched */
  DBUG_ASSERT(mysql->status != MYSQL_STATUS_READY ||
              (mysql->server_status & SERVER_STATUS_LAST_ROW_SENT));

  if (stmt->update_max_length)
  {
    MYSQL_ROWS *cur= result->data;
    for(; cur; cur=cur->next)
      stmt_update_metadata(stmt, cur);
  }

  stmt->data_cursor= result->data;
  mysql->affected_rows= stmt->affected_rows= result->rows;
  stmt->read_row_func= stmt_read_row_buffered;
  mysql->unbuffered_fetch_owner= 0;             /* set in stmt_execute */
  mysql->status= MYSQL_STATUS_READY;		/* server is ready */
  DBUG_RETURN(0); /* Data buffered, must be fetched with mysql_stmt_fetch() */
}

Project: mysql-server
File: libmysql.c

static void alloc_stmt_fields(MYSQL_STMT *stmt)
{
  MYSQL_FIELD *fields, *field, *end;
  MEM_ROOT *fields_mem_root= &stmt->extension->fields_mem_root;
  MYSQL *mysql= stmt->mysql;

  DBUG_ASSERT(stmt->field_count);

  free_root(fields_mem_root, MYF(0));

  /*
    Get the field information for non-select statements
    like SHOW and DESCRIBE commands
  */
  if (!(stmt->fields= (MYSQL_FIELD *) alloc_root(fields_mem_root,
						 sizeof(MYSQL_FIELD) *
						 stmt->field_count)) ||
      !(stmt->bind= (MYSQL_BIND *) alloc_root(fields_mem_root,
					      sizeof(MYSQL_BIND) *
					      stmt->field_count)))
  {
    set_stmt_error(stmt, CR_OUT_OF_MEMORY, unknown_sqlstate, NULL);
    return;
  }

  for (fields= mysql->fields, end= fields+stmt->field_count,
	 field= stmt->fields;
       field && fields < end; fields++, field++)
  {
    *field= *fields; /* To copy all numeric parts. */
    field->catalog=   strmake_root(fields_mem_root,
                                   fields->catalog,
                                   fields->catalog_length);
    field->db=        strmake_root(fields_mem_root,
                                   fields->db,
                                   fields->db_length);
    field->table=     strmake_root(fields_mem_root,
                                   fields->table,
                                   fields->table_length);
    field->org_table= strmake_root(fields_mem_root,
                                   fields->org_table,
                                   fields->org_table_length);
    field->name=      strmake_root(fields_mem_root,
                                   fields->name,
                                   fields->name_length);
    field->org_name=  strmake_root(fields_mem_root,
                                   fields->org_name,
                                   fields->org_name_length);
    if (fields->def)
    {
      field->def= strmake_root(fields_mem_root,
                               fields->def,
                               fields->def_length);
      field->def_length= fields->def_length;
    }
    else
    {
      field->def= NULL;
      field->def_length= 0;
    }
    field->extension= 0; /* Avoid dangling links. */
    field->max_length= 0; /* max_length is set in mysql_stmt_store_result() */
  }
}

Project: mysql-server
File: libmysql.c

my_bool cli_read_prepare_result(MYSQL *mysql, MYSQL_STMT *stmt)
{
  uchar *pos;
  uint field_count, param_count;
  ulong packet_length;
  MYSQL_DATA *fields_data;
  DBUG_ENTER("cli_read_prepare_result");

  if ((packet_length= cli_safe_read(mysql)) == packet_error)
    DBUG_RETURN(1);
  mysql->warning_count= 0;

  pos= (uchar*) mysql->net.read_pos;
  stmt->stmt_id= uint4korr(pos+1); pos+= 5;
  /* Number of columns in result set */
  field_count=   uint2korr(pos);   pos+= 2;
  /* Number of placeholders in the statement */
  param_count=   uint2korr(pos);   pos+= 2;
  if (packet_length >= 12)
    mysql->warning_count= uint2korr(pos+1);

  if (param_count != 0)
  {
    MYSQL_DATA *param_data;

    /* skip parameters data: we don't support it yet */
    if (!(param_data= (*mysql->methods->read_rows)(mysql, (MYSQL_FIELD*)0, 7)))
      DBUG_RETURN(1);
    free_rows(param_data);
  }

  if (field_count != 0)
  {
    if (!(mysql->server_status & SERVER_STATUS_AUTOCOMMIT))
      mysql->server_status|= SERVER_STATUS_IN_TRANS;

    if (!(fields_data= (*mysql->methods->read_rows)(mysql,(MYSQL_FIELD*)0,7)))
      DBUG_RETURN(1);
    if (!(stmt->fields= unpack_fields(mysql, fields_data,&stmt->mem_root,
				      field_count,0,
				      mysql->server_capabilities)))
      DBUG_RETURN(1);
  }
  stmt->field_count=  field_count;
  stmt->param_count=  (ulong) param_count;
  DBUG_PRINT("exit",("field_count: %u  param_count: %u  warning_count: %u",
                     field_count, param_count, (uint) mysql->warning_count));

  DBUG_RETURN(0);
}

Project: mysql-server
File: libmysql.c

static void fetch_datetime_with_conversion(MYSQL_BIND *param,
                                           MYSQL_FIELD *field,
                                           MYSQL_TIME *my_time)
{
  switch (param->buffer_type) {
  case MYSQL_TYPE_NULL: /* do nothing */
    break;
  case MYSQL_TYPE_DATE:
    *(MYSQL_TIME *)(param->buffer)= *my_time;
    *param->error= my_time->time_type != MYSQL_TIMESTAMP_DATE;
    break;
  case MYSQL_TYPE_TIME:
    *(MYSQL_TIME *)(param->buffer)= *my_time;
    *param->error= my_time->time_type != MYSQL_TIMESTAMP_TIME;
    break;
  case MYSQL_TYPE_DATETIME:
  case MYSQL_TYPE_TIMESTAMP:
    *(MYSQL_TIME *)(param->buffer)= *my_time;
    /* No error: time and date are compatible with datetime */
    break;
  case MYSQL_TYPE_YEAR:
    shortstore(param->buffer, my_time->year);
    *param->error= 1;
    break;
  case MYSQL_TYPE_FLOAT:
  case MYSQL_TYPE_DOUBLE:
  {
    ulonglong value= TIME_to_ulonglong(my_time);
    fetch_float_with_conversion(param, field,
                                ulonglong2double(value), MY_GCVT_ARG_DOUBLE);
    break;
  }
  case MYSQL_TYPE_TINY:
  case MYSQL_TYPE_SHORT:
  case MYSQL_TYPE_INT24:
  case MYSQL_TYPE_LONG:
  case MYSQL_TYPE_LONGLONG:
  {
    longlong value= (longlong) TIME_to_ulonglong(my_time);
    fetch_long_with_conversion(param, field, value, TRUE);
    break;
  }
  default:
  {
    /*
      Convert time value  to string and delegate the rest to
      fetch_string_with_conversion:
    */
    char buff[MAX_DATE_STRING_REP_LENGTH];
    uint length= my_TIME_to_str(my_time, buff);
    /* Resort to string conversion */
    fetch_string_with_conversion(param, (char *)buff, length);
    break;
  }
  }
}

Project: mysql-server
File: libmysql.c

static int stmt_read_row_buffered(MYSQL_STMT *stmt, unsigned char **row)
{
  if (stmt->data_cursor)
  {
    *row= (uchar *) stmt->data_cursor->data;
    stmt->data_cursor= stmt->data_cursor->next;
    return 0;
  }
  *row= 0;
  return MYSQL_NO_DATA;
}

Project: mysql-server
File: libmysql.c

mysql_kill(MYSQL *mysql,ulong pid)
{
  uchar buff[4];
  DBUG_ENTER("mysql_kill");
  int4store(buff,pid);
  DBUG_RETURN(simple_command(mysql,COM_PROCESS_KILL,buff,sizeof(buff),0));
}

Project: mysql-server
File: libmysql.c

static void read_binary_date(MYSQL_TIME *tm, uchar **pos)
{
  uint length= net_field_length(pos);

  if (length)
  {
    uchar *to= *pos;
    tm->year =  (uint) sint2korr(to);
    tm->month=  (uint) to[2];
    tm->day= (uint) to[3];

    tm->hour= tm->minute= tm->second= 0;
    tm->second_part= 0;
    tm->neg= 0;
    tm->time_type= MYSQL_TIMESTAMP_DATE;

    *pos+= length;
  }
  else
    set_zero_time(tm, MYSQL_TIMESTAMP_DATE);
}

Project: mysql-server
File: libmysql.c

ulong STDCALL mysql_thread_id(MYSQL *mysql)
{
  return (mysql)->thread_id;
}

Project: mysql-server
File: libmysql.c

static int stmt_read_row_unbuffered(MYSQL_STMT *stmt, unsigned char **row)
{
  int rc= 1;
  MYSQL *mysql= stmt->mysql;
  /*
    This function won't be called if stmt->field_count is zero
    or execution wasn't done: this is ensured by mysql_stmt_execute.
  */
  if (!mysql)
  {
    set_stmt_error(stmt, CR_SERVER_LOST, unknown_sqlstate, NULL);
    return 1;
  }
  if (mysql->status != MYSQL_STATUS_STATEMENT_GET_RESULT)
  {
    set_stmt_error(stmt, stmt->unbuffered_fetch_cancelled ?
                   CR_FETCH_CANCELED : CR_COMMANDS_OUT_OF_SYNC,
                   unknown_sqlstate, NULL);
    goto error;
  }
  if ((*mysql->methods->unbuffered_fetch)(mysql, (char**) row))
  {
    set_stmt_errmsg(stmt, &mysql->net);
    /*
      If there was an error, there are no more pending rows:
      reset statement status to not hang up in following
      mysql_stmt_close (it will try to flush result set before
      closing the statement).
    */
    mysql->status= MYSQL_STATUS_READY;
    goto error;
  }
  if (!*row)
  {
    mysql->status= MYSQL_STATUS_READY;
    rc= MYSQL_NO_DATA;
    goto error;
  }
  return 0;
error:
  if (mysql->unbuffered_fetch_owner == &stmt->unbuffered_fetch_cancelled)
    mysql->unbuffered_fetch_owner= 0;
  return rc;
}

Project: mysql-server
File: libmysql.c

static void default_local_infile_end(void *ptr)
{
  default_local_infile_data *data= (default_local_infile_data *) ptr;
  if (data)					/* If not error on open */
  {
    if (data->fd >= 0)
      my_close(data->fd, MYF(MY_WME));
    my_free(ptr);
  }
}

Project: mysql-server
File: libmysql.c

mysql_get_server_info(MYSQL *mysql)
{
  return((char*) mysql->server_version);
}

Project: mysql-server
File: libmysql.c

my_bool STDCALL mysql_embedded(void)
{
#ifdef EMBEDDED_LIBRARY
  return 1;
#else
  return 0;
#endif
}

Project: mysql-server
File: libmysql.c

mysql_stmt_param_metadata(MYSQL_STMT *stmt)
{
  DBUG_ENTER("mysql_stmt_param_metadata");

  if (!stmt->param_count)
    DBUG_RETURN(0);

  /*
    TODO: Fix this when server sends the information.
    Till then keep a dummy prototype.
  */
  DBUG_RETURN(0); 
}

Project: mysql-server
File: libmysql.c

static void fetch_result_bin(MYSQL_BIND *param,
                             MYSQL_FIELD *field __attribute__((unused)),
                             uchar **row)
{
  ulong length= net_field_length(row);
  ulong copy_length= min(length, param->buffer_length);
  memcpy(param->buffer, (char *)*row, copy_length);
  *param->length= length;
  *param->error= copy_length < length;
  *row+= length;
}

Project: mysql-server
File: libmysql.c

mysql_ping(MYSQL *mysql)
{
  int res;
  DBUG_ENTER("mysql_ping");
  res= simple_command(mysql,COM_PING,0,0,0);
  if (res == CR_SERVER_LOST && mysql->reconnect)
    res= simple_command(mysql,COM_PING,0,0,0);
  DBUG_RETURN(res);
}

Project: mysql-server
File: libmysql.c

const char *STDCALL mysql_info(MYSQL *mysql)
{
  return mysql->info;
}

Project: mysql-server
File: libmysql.c

int STDCALL mysql_stmt_next_result(MYSQL_STMT *stmt)
{
  MYSQL *mysql= stmt->mysql;
  int rc;
  DBUG_ENTER("mysql_stmt_next_result");

  if (!mysql)
    DBUG_RETURN(1);

  if (stmt->last_errno)
    DBUG_RETURN(stmt->last_errno);

  if (mysql->server_status & SERVER_MORE_RESULTS_EXISTS)
  {
    if (reset_stmt_handle(stmt, RESET_STORE_RESULT))
      DBUG_RETURN(1);
  }

  rc= mysql_next_result(mysql);

  if (rc)
  {
    set_stmt_errmsg(stmt, &mysql->net);
    DBUG_RETURN(rc);
  }

  if (mysql->status == MYSQL_STATUS_GET_RESULT)
    mysql->status= MYSQL_STATUS_STATEMENT_GET_RESULT;

  stmt->state= MYSQL_STMT_EXECUTE_DONE;
  stmt->bind_result_done= FALSE;
  stmt->field_count= mysql->field_count;

  if (mysql->field_count)
  {
    alloc_stmt_fields(stmt);
    prepare_to_fetch_result(stmt);
  }

  DBUG_RETURN(0);
}

Project: mysql-server
File: libmysql.c

static void store_param_null(NET *net, MYSQL_BIND *param)
{
  uint pos= param->param_number;
  net->buff[pos/8]|=  (uchar) (1 << (pos & 7));
}

Project: mysql-server
File: libmysql.c

const char *STDCALL mysql_sqlstate(MYSQL *mysql)
{
  return mysql ? mysql->net.sqlstate : cant_connect_sqlstate;
}

Project: mysql-server
File: libmysql.c

my_ulonglong STDCALL mysql_stmt_affected_rows(MYSQL_STMT *stmt)
{
  return stmt->affected_rows;
}

Project: mysql-server
File: libmysql.c

static my_bool my_realloc_str(NET *net, ulong length)
{
  ulong buf_length= (ulong) (net->write_pos - net->buff);
  my_bool res=0;
  DBUG_ENTER("my_realloc_str");
  if (buf_length + length > net->max_packet)
  {
    res= net_realloc(net, buf_length + length);
    if (res)
    {
      if (net->last_errno == ER_OUT_OF_RESOURCES)
        net->last_errno= CR_OUT_OF_MEMORY;
      else if (net->last_errno == ER_NET_PACKET_TOO_LARGE)
        net->last_errno= CR_NET_PACKET_TOO_LARGE;
      strmov(net->sqlstate, unknown_sqlstate);
      strmov(net->last_error, ER(net->last_errno));
    }
    net->write_pos= net->buff+ buf_length;
  }
  DBUG_RETURN(res);
}

Project: mysql-server
File: libmysql.c

mysql_stmt_send_long_data(MYSQL_STMT *stmt, uint param_number,
		     const char *data, ulong length)
{
  MYSQL_BIND *param;
  DBUG_ENTER("mysql_stmt_send_long_data");
  DBUG_ASSERT(stmt != 0);
  DBUG_PRINT("enter",("param no: %d  data: 0x%lx, length : %ld",
		      param_number, (long) data, length));

  /*
    We only need to check for stmt->param_count, if it's not null
    prepare was done.
  */
  if (param_number >= stmt->param_count)
  {
    set_stmt_error(stmt, CR_INVALID_PARAMETER_NO, unknown_sqlstate, NULL);
    DBUG_RETURN(1);
  }

  param= stmt->params+param_number;
  if (!IS_LONGDATA(param->buffer_type))
  {
    /* Long data handling should be used only for string/binary types */
    strmov(stmt->sqlstate, unknown_sqlstate);
    sprintf(stmt->last_error, ER(stmt->last_errno= CR_INVALID_BUFFER_USE),
	    param->param_number);
    DBUG_RETURN(1);
  }

  /*
    Send long data packet if there is data or we're sending long data
    for the first time.
  */
  if (length || param->long_data_used == 0)
  {
    MYSQL *mysql= stmt->mysql;
    /* Packet header: stmt id (4 bytes), param no (2 bytes) */
    uchar buff[MYSQL_LONG_DATA_HEADER];

    int4store(buff, stmt->stmt_id);
    int2store(buff + 4, param_number);
    param->long_data_used= 1;

    /*
      Note that we don't get any ok packet from the server in this case
      This is intentional to save bandwidth.
    */
    if ((*mysql->methods->advanced_command)(mysql, COM_STMT_SEND_LONG_DATA,
                                            buff, sizeof(buff), (uchar*) data,
                                            length, 1, stmt))
    {
      /* 
        Don't set stmt error if stmt->mysql is NULL, as the error in this case 
        has already been set by mysql_prune_stmt_list(). 
      */
      if (stmt->mysql)
        set_stmt_errmsg(stmt, &mysql->net);
      DBUG_RETURN(1);
    }
  }
  DBUG_RETURN(0);
}

Project: mysql-server
File: libmysql.c

int STDCALL mysql_server_init(int argc __attribute__((unused)),
			      char **argv __attribute__((unused)),
			      char **groups __attribute__((unused)))
{
  int result= 0;
  if (!mysql_client_init)
  {
    mysql_client_init=1;
    org_my_init_done=my_init_done;
    if (my_init())				/* Will init threads */
      return 1;
    init_client_errs();
    if (mysql_client_plugin_init())
      return 1;
    if (!mysql_port)
    {
      char *env;
      struct servent *serv_ptr __attribute__((unused));

      mysql_port = MYSQL_PORT;

      /*
        if builder specifically requested a default port, use that
        (even if it coincides with our factory default).
        only if they didn't do we check /etc/services (and, failing
        on that, fall back to the factory default of 3306).
        either default can be overridden by the environment variable
        MYSQL_TCP_PORT, which in turn can be overridden with command
        line options.
      */

#if MYSQL_PORT_DEFAULT == 0
      if ((serv_ptr= getservbyname("mysql", "tcp")))
        mysql_port= (uint) ntohs((ushort) serv_ptr->s_port);
#endif
      if ((env= getenv("MYSQL_TCP_PORT")))
        mysql_port=(uint) atoi(env);
    }

    if (!mysql_unix_port)
    {
      char *env;
#ifdef __WIN__
      mysql_unix_port = (char*) MYSQL_NAMEDPIPE;
#else
      mysql_unix_port = (char*) MYSQL_UNIX_ADDR;
#endif
      if ((env = getenv("MYSQL_UNIX_PORT")))
	mysql_unix_port = env;
    }
    mysql_debug(NullS);
#if defined(SIGPIPE) && !defined(__WIN__)
    (void) signal(SIGPIPE, SIG_IGN);
#endif
#ifdef EMBEDDED_LIBRARY
    if (argc > -1)
       result= init_embedded_server(argc, argv, groups);
#endif
  }
  else
    result= (int)my_thread_init();         /* Init if new thread */
  return result;
}

Project: mysql-server
File: libmysql.c

mysql_dump_debug_info(MYSQL *mysql)
{
  DBUG_ENTER("mysql_dump_debug_info");
  DBUG_RETURN(simple_command(mysql,COM_DEBUG,0,0,0));
}

Project: mysql-server
File: libmysql.c

mysql_stmt_init(MYSQL *mysql)
{
  MYSQL_STMT *stmt;
  DBUG_ENTER("mysql_stmt_init");

  if (!(stmt=
          (MYSQL_STMT *) my_malloc(sizeof (MYSQL_STMT),
                                   MYF(MY_WME | MY_ZEROFILL))) ||
      !(stmt->extension=
          (MYSQL_STMT_EXT *) my_malloc(sizeof (MYSQL_STMT_EXT),
                                       MYF(MY_WME | MY_ZEROFILL))))
  {
    set_mysql_error(mysql, CR_OUT_OF_MEMORY, unknown_sqlstate);
    my_free(stmt);
    DBUG_RETURN(NULL);
  }

  init_alloc_root(&stmt->mem_root, 2048, 2048);
  init_alloc_root(&stmt->result.alloc, 4096, 4096);
  stmt->result.alloc.min_malloc= sizeof(MYSQL_ROWS);
  mysql->stmts= list_add(mysql->stmts, &stmt->list);
  stmt->list.data= stmt;
  stmt->state= MYSQL_STMT_INIT_DONE;
  stmt->mysql= mysql;
  stmt->read_row_func= stmt_read_row_no_result_set;
  stmt->prefetch_rows= DEFAULT_PREFETCH_ROWS;
  strmov(stmt->sqlstate, not_error_sqlstate);
  /* The rest of statement members was bzeroed inside malloc */

  init_alloc_root(&stmt->extension->fields_mem_root, 2048, 0);

  DBUG_RETURN(stmt);
}

Project: mysql-server
File: libmysql.c

MYSQL_FIELD_OFFSET STDCALL mysql_field_tell(MYSQL_RES *res)
{
  return (res)->current_field;
}

Project: mysql-server
File: libmysql.c

static my_bool reset_stmt_handle(MYSQL_STMT *stmt, uint flags)
{
  /* If statement hasn't been prepared there is nothing to reset */
  if ((int) stmt->state > (int) MYSQL_STMT_INIT_DONE)
  {
    MYSQL *mysql= stmt->mysql;
    MYSQL_DATA *result= &stmt->result;

    /*
      Reset stored result set if so was requested or it's a part
      of cursor fetch.
    */
    if (flags & RESET_STORE_RESULT)
    {
      /* Result buffered */
      free_root(&result->alloc, MYF(MY_KEEP_PREALLOC));
      result->data= NULL;
      result->rows= 0;
      stmt->data_cursor= NULL;
    }
    if (flags & RESET_LONG_DATA)
    {
      MYSQL_BIND *param= stmt->params, *param_end= param + stmt->param_count;
      /* Clear long_data_used flags */
      for (; param < param_end; param++)
        param->long_data_used= 0;
    }
    stmt->read_row_func= stmt_read_row_no_result_set;
    if (mysql)
    {
      if ((int) stmt->state > (int) MYSQL_STMT_PREPARE_DONE)
      {
        if (mysql->unbuffered_fetch_owner == &stmt->unbuffered_fetch_cancelled)
          mysql->unbuffered_fetch_owner= 0;
        if (stmt->field_count && mysql->status != MYSQL_STATUS_READY)
        {
          /* There is a result set and it belongs to this statement */
          (*mysql->methods->flush_use_result)(mysql, FALSE);
          if (mysql->unbuffered_fetch_owner)
            *mysql->unbuffered_fetch_owner= TRUE;
          mysql->status= MYSQL_STATUS_READY;
        }
      }
      if (flags & RESET_SERVER_SIDE)
      {
        /*
          Reset the server side statement and close the server side
          cursor if it exists.
        */
        uchar buff[MYSQL_STMT_HEADER]; /* packet header: 4 bytes for stmt id */
        int4store(buff, stmt->stmt_id);
        if ((*mysql->methods->advanced_command)(mysql, COM_STMT_RESET, buff,
                                                sizeof(buff), 0, 0, 0, stmt))
        {
          set_stmt_errmsg(stmt, &mysql->net);
          stmt->state= MYSQL_STMT_INIT_DONE;
          return 1;
        }
      }
    }
    if (flags & RESET_CLEAR_ERROR)
      stmt_clear_error(stmt);
    stmt->state= MYSQL_STMT_PREPARE_DONE;
  }
  return 0;
}

Project: mysql-server
File: libmysql.c

static void fetch_result_str(MYSQL_BIND *param,
                             MYSQL_FIELD *field __attribute__((unused)),
                             uchar **row)
{
  ulong length= net_field_length(row);
  ulong copy_length= min(length, param->buffer_length);
  memcpy(param->buffer, (char *)*row, copy_length);
  /* Add an end null if there is room in the buffer */
  if (copy_length != param->buffer_length)
    ((uchar *)param->buffer)[copy_length]= '\0';
  *param->length= length;			/* return total length */
  *param->error= copy_length < length;
  *row+= length;
}

Project: mysql-server
File: libmysql.c

my_bool handle_local_infile(MYSQL *mysql, const char *net_filename)
{
  my_bool result= 1;
  uint packet_length=MY_ALIGN(mysql->net.max_packet-16,IO_SIZE);
  NET *net= &mysql->net;
  int readcount;
  void *li_ptr;          /* pass state to local_infile functions */
  char *buf;		/* buffer to be filled by local_infile_read */
  struct st_mysql_options *options= &mysql->options;
  DBUG_ENTER("handle_local_infile");

  /* check that we've got valid callback functions */
  if (!(options->local_infile_init &&
	options->local_infile_read &&
	options->local_infile_end &&
	options->local_infile_error))
  {
    /* if any of the functions is invalid, set the default */
    mysql_set_local_infile_default(mysql);
  }

  /* copy filename into local memory and allocate read buffer */
  if (!(buf=my_malloc(packet_length, MYF(0))))
  {
    set_mysql_error(mysql, CR_OUT_OF_MEMORY, unknown_sqlstate);
    DBUG_RETURN(1);
  }

  /* initialize local infile (open file, usually) */
  if ((*options->local_infile_init)(&li_ptr, net_filename,
    options->local_infile_userdata))
  {
    (void) my_net_write(net,(const uchar*) "",0); /* Server needs one packet */
    net_flush(net);
    strmov(net->sqlstate, unknown_sqlstate);
    net->last_errno=
      (*options->local_infile_error)(li_ptr,
                                     net->last_error,
                                     sizeof(net->last_error)-1);
    goto err;
  }

  /* read blocks of data from local infile callback */
  while ((readcount =
	  (*options->local_infile_read)(li_ptr, buf,
					packet_length)) > 0)
  {
    if (my_net_write(net, (uchar*) buf, readcount))
    {
      DBUG_PRINT("error",
		 ("Lost connection to MySQL server during LOAD DATA of local file"));
      set_mysql_error(mysql, CR_SERVER_LOST, unknown_sqlstate);
      goto err;
    }
  }

  /* Send empty packet to mark end of file */
  if (my_net_write(net, (const uchar*) "", 0) || net_flush(net))
  {
    set_mysql_error(mysql, CR_SERVER_LOST, unknown_sqlstate);
    goto err;
  }

  if (readcount < 0)
  {
    net->last_errno=
      (*options->local_infile_error)(li_ptr,
                                     net->last_error,
                                     sizeof(net->last_error)-1);
    goto err;
  }

  result=0;					/* Ok */

err:
  /* free up memory allocated with _init, usually */
  (*options->local_infile_end)(li_ptr);
  my_free(buf);
  DBUG_RETURN(result);
}

Project: mysql-server
File: libmysql.c

static void prepare_to_fetch_result(MYSQL_STMT *stmt)
{
  if (stmt->server_status & SERVER_STATUS_CURSOR_EXISTS)
  {
    stmt->mysql->status= MYSQL_STATUS_READY;
    stmt->read_row_func= stmt_read_row_from_cursor;
  }
  else if (stmt->flags & CURSOR_TYPE_READ_ONLY)
  {
    /*
      This is a single-row result set, a result set with no rows, EXPLAIN,
      SHOW VARIABLES, or some other command which either a) bypasses the
      cursors framework in the server and writes rows directly to the
      network or b) is more efficient if all (few) result set rows are
      precached on client and server's resources are freed.
    */
    mysql_stmt_store_result(stmt);
  }
  else
  {
    stmt->mysql->unbuffered_fetch_owner= &stmt->unbuffered_fetch_cancelled;
    stmt->unbuffered_fetch_cancelled= FALSE;
    stmt->read_row_func= stmt_read_row_unbuffered;
  }
}