On Mon, 2006-06-12 at 17:51 -0400, Chris Darroch wrote: > Personally, I think I prefer either (2) or (3). It seems more > intuitive to me that if I prepare a SQL statement with sprintf()-style > argument specifiers, then I don't also need to supply a trailing > NULL in the style of apr_pstrcat().
It is easy to make that change in PostgreSQL and SQLite drivers (i.e. to remember the number of args parsed in _prepare). People can keep passing NULL as the last argument in pvquery/pvselect - they shouldn't get hurt. If nobody objects, I can take it upon myself to do this. As for strings v. natives v. structures (i.e. your point 6), I think we should handle this by having a whole set of new functions for this purpose. I would personally keep the existing functions the way they are, because: - passing strings in/out for everything is handy - it ensures backward compatibility I would enhance this behaviour for existing functions to understand a few more things, like floats, doubles, longs, shorts, timestamps (all passed in as strings) and BLOBs (ASCII encoded, as I originally suggested). This would give us a whole lot of "strings only" stuff to work with. Not sure if formatting strings in apr_vformatter should really be related to SQL data type info we are passing in/out here, but if the list thinks this is the right way to go, I have no problem with it. So, now that we have the "strings" API out of the way, I think we should also introduce a new "binary" API for native data types. First, I would keep the _prepare identical for both "strings" and "binary" interface. The formats used should be able to cater for both. In this phase, we just "hint" what is to be expected, but not "hardcode" anything. Then, we can have "binary" equivalents of p[v]query/select and get_entry. Here is how I see them working: All "simple" types like int, long, float, double etc. are passed in by pointer only. No need to employ any kind of wrapper structure - lengths and types are known by the compiler and we can map those directly to SQL types too. Some other types, like timestamps, dates and times are probably best passed as their string representations, as this is what SQL backends can work with, as well as C native APIs, through conversion functions. BLOBs and such could be passed in through a structure defining all required elements (length and binary data), including the infamous column/table info for Oracle. The binary equivalent of get_entry would then return relevant pointers. The caller already knows what that is - he/she is the one doing this in the first place, no need to wrap all this with unneeded info. Basically, I'm trying to take the shortest path from A to B. If we can pass native as is, we do. If we can "cheat" by using strings, we do. For everything else, we do "proper". In other words, if it needs wrapping, we wrap. So, the caller can follow one of two paths: apr_dbd_prepare() apr_dbd_p[v]query/select() --> takes all args as strings apr_dbd_get_row() apr_dbd_get_entry() --> returns all strings or apr_dbd_prepare() apr_dbd_bp[v]query/select() --> takes various pointer args apr_dbd_get_row() apr_dbd_get_bentry() --> returns void * Obviously, we'd have some meaningful function names for all this. -- Bojan
