Sunday, October 11, 2009

It's not a bug...

... it's a feature! Really! I'm talking about my last post where I jumped to the conclusion that I had a bug in a particular line of code. In fact, that line of code is correct - the bug lies elsewhere. Let me explain.

As I stated before, there is no way (at least I never found a way to) use storage object with SQL Compact command parameters. To overcome this limitation the code must allocate the full size of the BLOB data on the binding buffer (which is not very efficient, but it's a viable solution). The problem with this is that the code has to know the size of the BLOB and adjust the binding buffer accordingly. If you use ADO .NET then you know how this issue is solved: the developer must create SqlCeParameters with the given maximum size of the parameter data. The whole purpose of this code is to avoid this situation and let the OLE DB library handle that chore for you.

Command parameter information is requested when you prepare a command and this is the reason why you see the dreaded 1024 constant in the code (the value is pretty arbitrary, by the way). This was the value I chose to represent the default value of the BLOB just to assume a value for it's length. The code then expects that you call SetParam for each parameter and explicitly set its size then. When the command is executed, the whole set of command parameters is looped through in order to get the size of the new binding buffer. If the new binding buffer is larger than the previous one it gets reallocated. And this is exactly where the bug was: the existing buffers were not being deleted and an obvious memory leaked was being created (the complaint reason from the reader who sent me the email message thet prompted me to look at this issue again).

To prove that the memory leak issue is gone in the new code, I set up a very simple demo project where three JPG images are inserted into a sample database table. The images are inserted using a SQL INSERT command and the code is arranged so that the images are processed in an increasing size order. This way you can actually see how the binding buffer increases.

Incidentally, the real bug was on the CCommand::BindParameters method where the m_pBuffer and m_pBindStatus arrays are allocated. These must be freed if non null before allocation.

Sample code: BigParams.zip (789 KB)

Note that the sample application expects both the sdf and jpg files on the \Storage Card\Temp directory. You can change this by editing the BigParamsFrame.cpp file.

1 comment:

Unknown said...

I am trying to use your OLE DB Client library from the BigParams.zip project and I am running into some build errors. I basically just downloaded the BigParams program and unzipped it and opened the solution file. When I do a clean build I get the following errors:

Error 1 fatal error C1083: Cannot open include file: 'atlapp.h': No such file or directory c:\users\susan\documents\downloads\bigparams\wmtypes\stdafx.h 29 wmtypes
Error 2 fatal error C1083: Cannot open include file: 'RefCount.h': No such file or directory c:\users\susan\documents\downloads\bigparams\oledbclient\oledbcli.h 13 OleDbClient
Error 3 fatal error C1083: Cannot open include file: 'atlapp.h': No such file or directory c:\users\susan\documents\downloads\bigparams\bigparams\stdafx.h 15 BigParams

Can you give me some help getting this working? I really just want to use the OleDbClient stuff it that is OK.