On Fri, 2003-12-26 at 19:26, Angus March wrote:
> I'm trying to use the API to write to a MEDIUMBLOB, but I'm getting a very
> vague error: something about a problem "near '' on line 1". I'm forumating
> the query string w/
> 
> sprintf(query, "INSERT INTO support_files (session_id,file_type,file_body)
> VALUES (%ld,%ld,", sessionID,fileType);
> 
> Then w/calls to things like memcpy, and unformatted reads from a stream, I
> append the blob to the end of that, and finalize it w/a ')'. I'm very
> careful about what I do w/my pointers, and not to use string-handling
> functions on the blob data. I also use mysql_real_query(), which is where
> the error is returned. From what I can tell from the on-line documentation,
> this is the right way to handle blobs. I also tried:
> 
> sprintf(query, "INSERT INTO support_files (session_id,file_type,file_body)
> VALUES (%ld,%ld,0)", sessionID,fileType); //exact same as before, but the
> blob is a mere '0'
> 
> Is this right? I can use a char * to point to binary data, can't I?
>     I'm running Linux RH9, if that makes a difference.

If you are using MySQL 4.1, it would be a lot easier to use "Prepared
SQL statements" as outlined in section 11.1.4 of the manual, which
allows you to pass variable parts of queries in a length-specified
binary format, rather than requiring that all the data in the query be
escaped for MySQL.  

Short of using 4.1, you could do something like you've done above with
sprintf but, but with the whole query.  I find it a little easier to be
sure that the whole query is valid by having the entire query in a
single string rather than trying to build the query by appending
successive parts.  In this case, you can also test that the query works
with data that doesn't need to be escaped without butchering your code
(you can just change the format string in the snprintf to some literal
data to verify that it works.

 -->8-----pseudo-code------8<----
char *blob_data = "some big buffer of blob data";
unsigned long blob_data_length = you-should-know-this-value;
blob_data_escaped = (char *) malloc(blob_data_length * 2+1);
escaped_length = mysql_real_escape_string(
                       (MYSQL *) mysql, 
                       (char *) blob_data_escaped, 
                       (const char *) blob_data, 
                       (unsigned long) blob_data_length);
/*
  blob_data_escaped[escaped_length] should be the only null byte
  in blob_data_escaped now, so the snprintf below should work just
  fine
 */

query_length = some-huge-amount-that-can-hold-
               escaped_length-plus-the-rest-of-the-query;
query = (char *)malloc(query_length);

snprintf(query, 
    query_length, 
    "insert into s (i,f,b) values (%d, %f, '%s')",
    some_integer,
    some_float,
    blob_data);
 -->8-----pseudo-code------8<----

See the query string?  Other than the fact it contains the printf escape
sequences, it's a syntacticly correct query, closing parens and all. 
You could change that to:

snprintf(query, 
    query_length, 
    "insert into s (i,f,b) values (%d, %f, '%s')",
    1,
    2.0,
    "blob\\'test\\0has embedded null byte");

to make sure the query is syntacticly correct.  If you print out the
query (so you know what it is), then try pasting it into the mysql
client, you should be able to run it without problems (as a way to test
where there are problems with it).  The C library functions that print
stuff out are bound by the same string-interpretation limits that the
MySQL library is, so if your query comes up short, or syntacticly
incorrect due to those limitations, you'll see it.

You could also abstract this out the pseudo-code I've provided above to
a function that formats a query for you if you give it all the data
values and the lengths of the input buffers and whatnot (thereby making
it work somewhat more like the prepared statement support in 4.1).

(BTW, you should get in the habit of using snprintf rather than sprintf,
if your platform supports it, in order to avoid buffer overruns).

-- 
Andy Bakun <[EMAIL PROTECTED]>


-- 
MySQL General Mailing List
For list archives: http://lists.mysql.com/mysql
To unsubscribe:    http://lists.mysql.com/[EMAIL PROTECTED]

Reply via email to