my goal is to use MySQL prepared statements via TMySQLStatement to store ROOT objects as BLOBs in a mysql db. For this reason one should use the TMySQLStatement::SetBinary member function. Reflecting the BIND functionality of MySQL, this functions attaches to a preallocated buffer in memory. My question is the following: How safe is to use the TMessage::Buffer() and TMessage::BufferSize() to BIND via the above member function? In particular is it safe to assume that the buffer always starts at the same address regardless of the size of the object that gets serialized in the TBuffer or could a reallocation on a subsequent write make this starting address invalid? The solution I found was to provide to TBuffer a “large enough” preallocated buffer by using TMessage::SetBuffer() but I don’t like it since it requires keeping an eye on the size of the object that gets written in the buffer. Could you advice on a better solution? The ideal would be to have a TMySQLStatement::SetMessage(Int_t par, TMessage* msg) that handles this in a coherent way if possible. Thanks,
You should not care about buffer, provided into TSQLStatement::SetBinary() method. Statement creates intermediate buffer anyway and content of your buffer will be copied. Therefore, after SetBinary() call you can free/reallocate your buffer (TMessage object) immediately. Of course, such approach requires one additional memcpy, but avoids problems like you mention.
Practically, it is possible to implement method like TSQLStatment::SetMessage(). This save you one memcpy,
but requires double bookkeeping in the statement and introduces ownership problem. I recommend you to use SetBinary method as is.
I think I have to understand a little bit more the mechanism behind this. If TMySQLStatement::SetBinary attaches to a buffer which gets deleted afterwards as you say, then how can there be any guarantee that mutliple subsequent calls of TMySQLStatement::Process actually copy the desired data from this buffer, if it is deleted? Maybe I am mistaken but I assume here the the actual transaction form binded structures to mysql client-side socket happens essentially as an “atomic” (in this context) operation when the statement is actually executed. Looking into the code I see that indeed in TMySQLStatement::SetBinary the contents of the buffer get copied but what is needed according to my understanding is that the correct data get copied in every call to TMySQLStatement::Process. Is this the case? If yes, how is it possible to guaranntee that you copy the correct data if the binded buffer gets deleted? Thanks,
As I said, TMySQLStatement creates internal buffer, which is used in MySQL bind call. When you call SetBinary, you buffer will be copied in the internal buffer. If size of internal buffer too small, it will be reallocated and bind will be done again. Therefore, after SetBinary call it is does not matter, that are you doing with your buffer. Before each stmt->Process() call you should call SetBinary(), otherwise old values will be used. It is true also for SetInt(), SetDouble() and so on calls.