SQLite 3.6.23.1 wrapper + connector

Rory McGuire rmcguire at neonova.co.za
Mon Jul 19 23:56:45 PDT 2010


On Tue, 20 Jul 2010 01:37:10 +0200, awishformore <awishformore at gmail.com>  
wrote:

> Am 19.07.2010 21:34, schrieb Rory McGuire:
>> On Mon, 19 Jul 2010 20:39:35 +0200, awishformore
>> <awishformore at gmail.com> wrote:
>>
>>> Am 19.07.2010 17:50, schrieb Johannes Pfau:
>>>> On 19.07.2010 00:44, awishformore wrote:
>>>>> Hello there.
>>>>>
>>>>> I've converted the .h file of the latest SQLite version to .d and I
>>>>> thought I'd let the world know (as suggested on IRC ;). Maybe it will
>>>>> save someone some work.
>>>>>
>>>>> I've also written a nice connector class that wraps all the C  
>>>>> functions
>>>>> for convenient use in your application. It's very basic, but I will
>>>>> probably add more features (like automatic preparation of statements
>>>>> and
>>>>> automatic caching of several prepared statements) later.
>>>>>
>>>>> For the time being both files are included in the download:
>>>>> http://nexunity.com/sqlite4d.rar
>>>>>
>>>>> I'm pretty new to this kind of stuff, so what I did to get it to work
>>>>> was compiling the latest SQLite dll from source with dmc and then  
>>>>> link
>>>>> the .obj file into my app ( http://nexunity.com/sqlite3.obj ).
>>>>>
>>>>> I'm sure there is a better way like compiling it as static lib (dmc
>>>>> complained about no entry point) or having some kind of other file to
>>>>> link into your app in order for it to compile and then use the dll. I
>>>>> however couldn't figure it out and it works for me. Don't hesitate to
>>>>> teach me nonetheless.
>>>>>
>>>>> Any kind of feedback is always appreciated.
>>>>>
>>>>> Greetings, Max.
>>>> Nice work!
>>>>
>>>> I'm by no means an expert in d, but I wonder whether the following in
>>>> the connector could cause troubles:
>>>> --------------------------------------
>>>> int open(string db_name)
>>>> {
>>>> return sqlite3_open_v2(cast(char*)db_name,
>>>> --------------------------------------
>>>>
>>>> I always thought just casting to the pointer type isn't really safe. I
>>>> guess you should use std.strings toStringz.
>>>>
>>>> (Off topic: std.strings toStringz uses the GC to store the c string.  
>>>> Now
>>>> if I passed the returned pointer to a C function, but didn't store a
>>>> reference in the D program, couldn't that c string get collected while
>>>> the c library would expect it to be still there?)
>>>
>>> Hello there.
>>>
>>> I'm not an expert for anything related to programming, but I'm pretty
>>> sure the string/char[]/char* isn't needed by SQLite after the function
>>> returns, as you will always be using the sqlite4 object pointer.
>>>
>>> As for the issue about null-terminated C strings, I was initially
>>> expecting this to not work, but tried anyway. I guess this has to do
>>> with the fact that SQLite interprets the char* as UTF-8, which is what
>>> D uses. With only a few lines of code, UTF-16 would also work with the
>>> wrapper by the way, but I won't ever use it, so I didn't bother.
>>>
>>> I added quite a few unit tests to the file in order to verify stuff
>>> like this and all of them seem to pass without the slightest issue and
>>> there are no memory leaks either, so I'm assuming that at least the
>>> basic functionality of my connector class is absolutely safe to use.
>>>
>>> The only thing I changed except for the unit tests is the
>>> ptrtostr/ptrtoblob to access the pointer like an array instead of a
>>> while loop and the else -> else static if(T==sqlite3_value*) to ensure
>>> a valid parameter is always passed.
>>>
>>> Greetings, Max.
>>>
>>
>> Did you test with a string that was not in the code itself, e.g. from a
>> config file?
>> String literals are null terminated so you wouldn't have had an issue if
>> all your strings were literals.
>> Utf8 doesn't contain the string length, so you will run in to problems
>> eventually.
>>
>> You have to use toStringz or your own null terminator. Unless of course
>> you know that the function will always be
>> taking string literals. But even then leaving something like that up to
>> the programmer to remember is not exactly
>> fool proof.
>>
>> Enjoy.
>> ~Rory
>
> Hey again and thanks for the hint. I tried finding something on the DM  
> page about string literals being null terminated and while the section  
> about string literals didn't even mention it, it was said some place  
> else.
>
> That explains why using string literals works even though I expected it  
> to fail. It's indeed good to know and adding std.string.toStringz is  
> probably a good idea ;). Thanks.
>
> Greetings, Max.

sure, I must admit it is annoying when the same code can do different  
things just because of where the data came
from. It would be easier to notice the bug if d never added a null on  
literals, but then there would also be a lot more
usages of toStringz.

I think if you want to test it you can do:
auto s = "blah";
open(s[0..$].dup.ptr); // duplicating it should put it somewhere else
			// just slicing will not test


More information about the Digitalmars-d-announce mailing list