List:MySQL ODBC« Previous MessageNext Message »
From:Ian Klassen Date:April 20 2005 9:59pm
Subject:MyODBC and BLOB's
View as plain text  
Hello,

I was able to track down the problem with extending the net buffer to handle BLOB's.  In
the functions copy_rowdata and batch_insert a MYSQL object is created by copying an
existing MYSQL object from a STMT object (stmt).  

The problem is that when the buffer is extended, only the original is updated to point to
the newly allocated memory.  I have updated these two functions to use MYSQL pointers
instead and all is fine.  

Will this fix cause some other problems?

Ian

static SQLRETURN batch_insert(STMT FAR *stmt, SQLUSMALLINT irow,
			      DYNAMIC_STRING *ext_query)
{
  MYSQL_RES    *result= stmt->result;
  SQLUINTEGER  insert_count= 1;
  SQLUINTEGER  count= 0;
  SQLINTEGER   length;
  NET	       *net;
  SQLUSMALLINT ncol;
  SQLCHAR      *to;
  ulong        query_length= 0;
  my_bool      break_insert= FALSE;
  MYSQL*       mysql= &stmt->dbc->mysql ;
  PARAM_BIND   param;

  if (!irow && stmt->stmt_options.rows_in_set > 1) /* batch wise */
  {
    insert_count= stmt->stmt_options.rows_in_set;
    query_length= ext_query->length;
  }

  do
  {
    if (break_insert)
    {
      /*
	If query exceeded its length, then set the query
	from begining..
      */
      ext_query->length= query_length;
    }
    while (count < insert_count)
    {
      net= &(mysql->net);
      to = net->buff;

	  dynstr_append_mem(ext_query,"(", 1);

      for (ncol= 0; ncol < result->field_count; ncol++)
      {
	SQLUINTEGER transfer_length,precision,display_size;
	MYSQL_FIELD *field= mysql_fetch_field_direct(result,ncol);
	BIND	    *bind= stmt->bind+ncol;

	param.SqlType= unireg_to_sql_datatype(stmt,field,0,
					      &transfer_length,&precision,
					      &display_size);
	param.CType = bind->fCType;
	param.buffer= (gptr) bind->rgbValue+count*bind->cbValueMax;

	if (param.buffer)
	{
	  if (bind->pcbValue)
	  {
	    if (*bind->pcbValue == SQL_NTS)
	      length= strlen(param.buffer);
      else if (*bind->pcbValue == SQL_COLUMN_IGNORE)
	      length= SQL_NULL_DATA;
	    else length= *bind->pcbValue;
	  }
	  else length= bind->cbValueMax;
	}
	else length= SQL_NULL_DATA;
	param.actual_len= &length;

	if (copy_rowdata(stmt,param,&net,&to) != SQL_SUCCESS)
	  return(SQL_ERROR);

      } /* END OF for (ncol= 0; ncol < result->field_count; ncol++) */

      length= (uint) ((char *)to - (char*) net->buff);
      dynstr_append_mem(ext_query, (char*) net->buff, length-1);
      dynstr_append_mem(ext_query, "),", 2);
      count++;
      if (ext_query->length+length >= net_buffer_length)
      {
	break_insert= TRUE;
	break;
      }
    }  /* END OF while(count < insert_count) */

    ext_query->str[--ext_query->length]= '\0';

    if (exec_stmt_query(stmt, ext_query->str, ext_query->length) !=
	SQL_SUCCESS)
      return(SQL_ERROR);

  } while (break_insert && count < insert_count);

  stmt->affected_rows= stmt->dbc->mysql.affected_rows= insert_count;
  if (stmt->stmt_options.rowStatusPtr)
  {
    for (count= insert_count; count--;)
      stmt->stmt_options.rowStatusPtr[count]= SQL_ROW_ADDED;
  }
  return(SQL_SUCCESS);
}

static SQLRETURN copy_rowdata(STMT FAR *stmt, PARAM_BIND  param,
			      NET **net, SQLCHAR **to)
{
  SQLCHAR *orig_to= *to;
  MYSQL* mysql= &stmt->dbc->mysql;
  SQLUINTEGER length= *(param.actual_len)+1;

  DBUG_PRINT("copy_rowdata",("buffer: '%s', length: %d, actual: %d", *to, length,
sizeof(**to)));

  if (!(*to= (SQLCHAR *) extend_buffer(*net,(char*) *to,length)))
    return set_error(stmt,MYERR_S1001,NULL,4001);

  if (!(*to= (SQLCHAR*) insert_param(mysql, (char*) *to, &param)))
    return set_error(stmt,MYERR_S1001,NULL,4001);

   /* We have to remove zero bytes or we have problems! */
  while ((*to > orig_to) && (*((*to) - 1) == (SQLCHAR) 0)) (*to)--;

  /* insert "," */
  param.SqlType= SQL_INTEGER;
  param.CType= SQL_C_CHAR;
  param.buffer= (gptr) ",";
  *param.actual_len= 1;

  if (!(*to= (SQLCHAR*) insert_param(mysql,(char*) *to, &param)))
    return set_error(stmt,MYERR_S1001,NULL,4001);

  return(SQL_SUCCESS);
}
Thread
MyODBC and BLOB'sIan Klassen20 Apr