SOCI 2.2.0 - The C++ Database Access Library

Hi, It's already a matter of "tradition" that all database discussions here have something to do with SOCI. ;-) To confirm this "tradition", I would like to announce that the new version (2.2.0) of the SOCI library is available for download: http://soci.sourceforge.net/ This new version provides: 1. Two new backends: - ODBC (tested with MS SQL Server) - Firebird 2. Complete build system for both Unix/Linux (autotools) and Windows (solution files for MSVC++). 3. STL-compatible iterators: Rowset<string> rs = (sql.prepare << "select name from persons"); copy(rs.begin(), rs.end(), ostream_iterator<string>(cout, "\n")); 4. Stream-like interface for easier dynamic binding and field extraction from rows: Row r; sql << "select name, age, salary from persons where ...", into(r); string name; int age, salary; r >> name >> age >> salary; 5. The comprehensive set of common tests for all supported database servers. 6. Some performance improvements for PostgreSQL. 7. Better docs. 8. Various fixes and tweaks. I would like to stress that the ODBC support was our important milestone that now allows us to claim a quite extensive coverage of existing database technologies. With this in mind, SOCI becomes even more serious and our roadmap for the nearest future is to bring the library to the state that will make it a valid candidate for inclusion into Boost. We will therefore welcome your guidance and suggestions w.r.t. Boost compliance. Note that up to this release, the library was deliberately developed without any external dependencies, so there are obviously wide areas where Boost might be applied within the library itself (example: intrusive pointers to manage some refcounted objects). This is easy. The more difficult part is the library interface and its general philosophy. We welcome your feedback. -- Maciej Sobczak : http://www.msobczak.com/ Programming : http://www.msobczak.com/prog/

Maciej Sobczak wrote:
Hi,
It's already a matter of "tradition" that all database discussions here have something to do with SOCI. ;-)
As is tradition, I'll chime in ;-)
To confirm this "tradition", I would like to announce that the new version (2.2.0) of the SOCI library is available for download:
Hooray (dances around room)!
This new version provides:
...snip good stuff...
I would like to stress that the ODBC support was our important milestone that now allows us to claim a quite extensive coverage of existing database technologies. With this in mind, SOCI becomes even more serious and our roadmap for the nearest future is to bring the library to the state that will make it a valid candidate for inclusion into Boost. We will therefore welcome your guidance and suggestions w.r.t. Boost compliance.
It seems to me that there are a few basic things that need to be done: - have a formal review - convert to boost build - refactor src tree to be boost-like (boost tree, finer grained headers/cpp files) - write some tests (maybe I'm just missing them in the distro)? - full reference docs not necessarily in that order. Personally I tend toward having the review sooner. SOCI's interface as been mostly stable for awhile...although it looks like there's a few twists in this release. The review may uncover other issues that need to be resolved. Or if the library were not accepted it would be quite painful to do a bunch of work to boostify and then decide to just stay independent. Note that I expect the review for SOCI to be tough because it's a fairly large and complex domain/lib. So we ought to ask the review manager for a longer review right up front.
Note that up to this release, the library was deliberately developed without any external dependencies, so there are obviously wide areas where Boost might be applied within the library itself (example: intrusive pointers to manage some refcounted objects). This is easy.
And not critically important for review or acceptance.
The more difficult part is the library interface and its general philosophy.
Not sure I understand the problem here... Jeff

Jeff Garland wrote:
It's already a matter of "tradition" that all database discussions here have something to do with SOCI. ;-)
As is tradition, I'll chime in ;-)
:-)
It seems to me that there are a few basic things that need to be done:
- have a formal review
Of course.
- convert to boost build
This is on the roadmap.
- refactor src tree to be boost-like (boost tree, finer grained headers/cpp files)
Yes, the code might benefit from some work in this area. Still, we would like to limit the number of "entry points" for final users, in the sense that for example it should be enough to do this: #include "soci.h" #include "soci-oracle.h" (names don't matter) to be able to play with Oracle. This way of thinking has led us to single soci.h header, but I agree that it would benefit from some refactoring. The backends have already very fine-grained file structure.
- write some tests (maybe I'm just missing them in the distro)?
Looks like. :-) src/core/test/common-tests.h src/backends/DBNAME/test/test-DBNAME.cpp For each server, the above pair provides a comprehensive set of tests (they are automatically built together with the library; just run them). The common-tests.h file contains common tests cases that are used for all servers.
- full reference docs
doc/reference.html (for client interface) doc/backends.html (for authors of new backends) doc/backends/DBNAME.html (for server-specific issues) Plus subject-by-subject tutorial (start from doc/index.html). Anything missing?
Personally I tend toward having the review sooner. SOCI's interface as been mostly stable for awhile...although it looks like there's a few twists in this release. The review may uncover other issues that need to be resolved. Or if the library were not accepted it would be quite painful to do a bunch of work to boostify and then decide to just stay independent.
Yes, we are aware of this risk.
Note that I expect the review for SOCI to be tough because it's a fairly large and complex domain/lib. So we ought to ask the review manager for a longer review right up front.
That's reasonable.
The more difficult part is the library interface and its general philosophy.
Not sure I understand the problem here...
The SOCI library stands out a bit in the crowd thanks to its basic interfacing assumptions. Some users love it exactly because of its interface and some others hate it exactly for the same reason. This already proved to be a recipe for heat generator. ;-) -- Maciej Sobczak : http://www.msobczak.com/ Programming : http://www.msobczak.com/prog/

Maciej Sobczak wrote:
Jeff Garland wrote:
- refactor src tree to be boost-like (boost tree, finer grained headers/cpp files)
Yes, the code might benefit from some work in this area. Still, we would like to limit the number of "entry points" for final users, in the sense that for example it should be enough to do this:
#include "soci.h" #include "soci-oracle.h"
(names don't matter)
to be able to play with Oracle. This way of thinking has led us to single soci.h header, but I agree that it would benefit from some refactoring. The backends have already very fine-grained file structure.
Ok, well there's no reason you can't have both. The soci.h can just include all the fine-grained headers.
- write some tests (maybe I'm just missing them in the distro)?
Looks like. :-)
src/core/test/common-tests.h src/backends/DBNAME/test/test-DBNAME.cpp
For each server, the above pair provides a comprehensive set of tests (they are automatically built together with the library; just run them). The common-tests.h file contains common tests cases that are used for all servers.
Oh, that's good. The tree refactoring would make the tests more obvious.
- full reference docs
doc/reference.html (for client interface) doc/backends.html (for authors of new backends) doc/backends/DBNAME.html (for server-specific issues)
Plus subject-by-subject tutorial (start from doc/index.html).
Anything missing?
header by header, class by class documentation for all interface classes. I see the reference page, but I suspect that isn't really everything the user might use.
Note that I expect the review for SOCI to be tough because it's a fairly large and complex domain/lib. So we ought to ask the review manager for a longer review right up front.
That's reasonable.
Seems like you might want to get in the queue now...
The more difficult part is the library interface and its general philosophy. Not sure I understand the problem here...
The SOCI library stands out a bit in the crowd thanks to its basic interfacing assumptions. Some users love it exactly because of its interface and some others hate it exactly for the same reason.
This already proved to be a recipe for heat generator. ;-)
Hmm, I guess my memory of this is short. I can't do anything at the moment since I'm already over committed, but I'll try to do an informal review over the holidays to ferret out any issues. BTW, one thing I can imagine being discussed is the library name. SOCI seems a little out of date at this point. As you make the transition to Boost maybe it should be DAL (database access library) or some other more general name. Thx for your efforts! Jeff

Jeff Garland <jeff <at> crystalclearsoftware.com> writes:
Maciej Sobczak wrote:
Jeff Garland wrote: [...]
Note that I expect the review for SOCI to be tough because it's a fairly large and complex domain/lib. So we ought to ask the review manager for a longer review right up front.
That's reasonable.
Seems like you might want to get in the queue now...
[...]
The SOCI library stands out a bit in the crowd thanks to its basic interfacing assumptions. Some users love it exactly because of its interface and some others hate it exactly for the same reason.
This already proved to be a recipe for heat generator.
Hmm, I guess my memory of this is short. I can't do anything at the moment since I'm already over committed, but I'll try to do an informal review over the holidays to ferret out any issues.
Isn't this an instance of a more general problem? Existing libraries that are being considered for submission to Boost should get a sort of pre-review so that their developers may tackle the emerging issues while they proceed with Boostification, rather than after the fact. Should worse come to worse they'd be in a position to decide to pospone or give up their submission before investing too much effort into it. I wonder if such pre-reviews should be given some official status, if just to try and attract a higher number of reviewers. Cheers, Nicola Musatti

Maciej Sobczak wrote:
Jeff Garland wrote:
The more difficult part is the library interface and its general philosophy. Not sure I understand the problem here...
The SOCI library stands out a bit in the crowd thanks to its basic interfacing assumptions. Some users love it exactly because of its interface and some others hate it exactly for the same reason.
This already proved to be a recipe for heat generator. ;-)
In general, providing two different interfaces to do the same thing is considered poor software design. But if divergent use case needs, performance, or other important considerations are present, having two different interfaces may be viewed as a real plus. Witness asio's synchronous and asynchronous interfaces. Viewed from a distance, they seem like duplication. But as you get closer, you see that they offer such a different set of design tradeoffs that both are merited. I don't know if that applies to SOCI. --Beman

Hi, Beman Dawes wrote:
In general, providing two different interfaces to do the same thing is considered poor software design. But if divergent use case needs, performance, or other important considerations are present, having two different interfaces may be viewed as a real plus.
There is a lot of place for debating here. For example, std::copy might be considered to be just duplicating std::transform (with identity), but very few people would agree to drop it. But I get your point. SOCI provides a couple of seemingly unrelated ways of interfacing, but each of them has some rationale, from performance to distinction between static and dynamic bindings. In principle the library would go with just single-row-at-a-time dynamic bindings, but that would not allow us to exploit the ultimate performance that some servers can provide with direct binary data transport. I'm very confident that the interface will be thoroughly scrutinized here. ;-) -- Maciej Sobczak : http://www.msobczak.com/ Programming : http://www.msobczak.com/prog/

Jeff Garland wrote:
Maciej Sobczak wrote:
I would like to stress that the ODBC support was our important milestone that now allows us to claim a quite extensive coverage of existing database technologies. With this in mind, SOCI becomes even more serious and our roadmap for the nearest future is to bring the library to the state that will make it a valid candidate for inclusion into Boost. We will therefore welcome your guidance and suggestions w.r.t. Boost compliance.
It seems to me that there are a few basic things that need to be done:
- have a formal review
Yes, I think so.
- convert to boost build
Moving to/adding support of bjam is on our roadmap already.
- refactor src tree to be boost-like (boost tree, finer grained headers/cpp files)
Yes, we'are aware of this requirement too.
- write some tests (maybe I'm just missing them in the distro)?
When moving to Boost, we think Boost.UTF will be used.
- full reference docs
Currently, we have good docs I believe, but it would need to follow Boost doc format.
not necessarily in that order. Personally I tend toward having the review sooner. SOCI's interface as been mostly stable for awhile...although it looks like there's a few twists in this release. The review may uncover other issues that need to be resolved.
Yes, the outcome would be very interesting. Cheers -- Mateusz Loskot http://mateusz.loskot.net

Mateusz Loskot wrote:
Jeff Garland wrote:
When moving to Boost, we think Boost.UTF will be used.
Hmm, Boost.UTF isn't really an official lib....but ok if there's a similar issue you need to solve it would be good not to replicate.
- full reference docs
Currently, we have good docs I believe, but it would need to follow Boost doc format.
The docs are good although perhaps more tutorial is needed. And there's no official Boost doc format... Jeff

Jeff Garland wrote:
Mateusz Loskot wrote:
Jeff Garland wrote:
When moving to Boost, we think Boost.UTF will be used.
Hmm, Boost.UTF isn't really an official lib....but ok if there's a similar issue you need to solve it would be good not to replicate.
Hmm, honestly I'm confused :-) I thought Boost Unit Test Framework is recommended for use in Boost libraries tests. Cheers -- Mateusz Loskot http://mateusz.loskot.net

Mateusz Loskot wrote:
When moving to Boost, we think Boost.UTF will be used. Hmm, Boost.UTF isn't really an official lib....but ok if there's a similar issue you need to solve it would be good not to replicate.
Hmm, honestly I'm confused :-) I thought Boost Unit Test Framework is recommended for use in Boost libraries tests.
Oh, sorry I thought you were referring to something else that serialization and others use for string handling. Sure using Boost.test would be good... Jeff

Jeff Garland wrote:
Mateusz Loskot wrote:
When moving to Boost, we think Boost.UTF will be used. Hmm, Boost.UTF isn't really an official lib....but ok if there's a similar issue you need to solve it would be good not to replicate. Hmm, honestly I'm confused :-) I thought Boost Unit Test Framework is recommended for use in Boost libraries tests.
Oh, sorry I thought you were referring to something else that serialization and others use for string handling. Sure using Boost.test would be good...
Cool! Thanks! -- Mateusz Loskot http://mateusz.loskot.net

Maciej Sobczak <prog <at> msobczak.com> writes: [...]
I would like to stress that the ODBC support was our important milestone that now allows us to claim a quite extensive coverage of existing database technologies. With this in mind, SOCI becomes even more serious and our roadmap for the nearest future is to bring the library to the state that will make it a valid candidate for inclusion into Boost. We will therefore welcome your guidance and suggestions w.r.t. Boost compliance.
Note that up to this release, the library was deliberately developed without any external dependencies, so there are obviously wide areas where Boost might be applied within the library itself (example: intrusive pointers to manage some refcounted objects). This is easy. The more difficult part is the library interface and its general philosophy.
The last time this topic was discussed, it was hoped that the outcome could be a proposal to be included in the standard committee's TR2. Even though that deadline has passed proposing a library for inclusion in the standard is certainly a worthwhile objective; is that something you want to pursue with SOCI? I'm asking because I think that the answer may influence interface choices, e.g. to simplify support for single backend implementations or to limit use of Boost libraries to those accepted in the TR's. As I already mentioned in a previous discussion I believe that a distinction should be introduced between core DB access functionality and higher abstractions such as the object/relational mapping, especially in view of a possible standard submission. Another issue I consider worth discussing is how dynamic should the choice of backend be. While I think that a plugin oriented architecture would be overkill, the degree of independence from the underlying technology provided by libraries such as Borland's VCL is convenient. This would probably mean adding a registration based mechanism to the way backends are currently selected in SOCI. On the other hand I don't think anybody wants something as complicated as ODBC's driver based approach. Diagnostics is another area that deserves consideration. In a way failures are easy to handle, because you can always, or rather should always, throw exceptions. On the other hand I don't think there's a proven best way for providing non terminating, informative diagnostics. Is it possible to devise a unified approach that combines general backend information to details on data retrieval results (eg. nulls, truncation, etc.)?. This is directly connected to value representation issues, like the use of Boost.Optional to represent nulls, etc. I'll leave more specific API related issues for later. Cheers, Nicola Musatti

Nicola Musatti wrote:
Maciej Sobczak <prog <at> msobczak.com> writes: [...]
I would like to stress that the ODBC support was our important milestone that now allows us to claim a quite extensive coverage of existing database technologies. With this in mind, SOCI becomes even more serious and our roadmap for the nearest future is to bring the library to the state that will make it a valid candidate for inclusion into Boost. We will therefore welcome your guidance and suggestions w.r.t. Boost compliance.
Note that up to this release, the library was deliberately developed without any external dependencies, so there are obviously wide areas where Boost might be applied within the library itself (example: intrusive pointers to manage some refcounted objects). This is easy. The more difficult part is the library interface and its general philosophy.
The last time this topic was discussed, it was hoped that the outcome could be a proposal to be included in the standard committee's TR2. Even though that deadline has passed proposing a library for inclusion in the standard is certainly a worthwhile objective; is that something you want to pursue with SOCI?
As a long-time C++ committee member, I can say with certainty that the committee will be *very* interested in a Boost Database library. Please don't worry about whether it is for TR2, TR3, or something else. Just proceed with getting SOCI ready for a Boost formal review, and work on the assumption that if Boost users find the library useful, it will be proposed for eventual standardization.
I'm asking because I think that the answer may influence interface choices, e.g. to simplify support for single backend implementations or to limit use of Boost libraries to those accepted in the TR's.
For the public interface, I think it is appropriate to depend on any Boost library accepted for TR1,TR2, or C++0x. As far as the internal implementation goes, that is pretty much up to the library's implementors, IMO.
As I already mentioned in a previous discussion I believe that a distinction should be introduced between core DB access functionality and higher abstractions such as the object/relational mapping, especially in view of a possible standard submission.
The C++ committee's LWG tends to prefer that a library expose the lower-level functionality used to build higher-level abstractions, particularly when the library is implemented by calls to third-party API's. Speaking of third-parties, requiring the user to include headers specific to particular back-ends sounds controversial, although I haven't studied SOCO's interface yet so don't know that for sure. --Beman

Hi, Beman Dawes wrote:
I'm asking because I think that the answer may influence interface choices, e.g. to simplify support for single backend implementations or to limit use of Boost libraries to those accepted in the TR's.
For the public interface, I think it is appropriate to depend on any Boost library accepted for TR1,TR2, or C++0x. As far as the internal implementation goes, that is pretty much up to the library's implementors, IMO.
Which raises a series of new questions. Now, the SOCI library provides a common interface that is independent from the particular server technology (well, as far as SQL dialects go...). The user of the library can select any supported platform by naming the factory object at the connection time: Session sql(oracle, "some parameters"); Above, oracle is a name of the factory singleton that is used by Session to create concrete instances for relevant backend objects. For the last three releases we have focused on getting as many working backends (which translate into many factories) as possible, which makes SOCI practically useful. The word "practically" is crucial here, because this is where the possible standardization process can get tricky. The standard was always very careful not to impose any constraints that would unnecessarily limit the implementation possibilities and this will have to be applied here as well. I understand that the committee will be reluctant to put any obligation that the implementation must provide this or that backend factory, which in reality will mean that vendors will be able to provide no factory at all, or just their favourite, so that there will be environments that don't have any single factory in common. Just for the sake of practical example: Microsoft will provide odbc and/or mssql factory, GNU people will provide mysql and postgresql and the portability of final applications is gone. In fact, I see three possibilities: 1. Define backend interface in a way that allows vendors to provide standard-compliant backends. From the interface point of view they will be replaceable, so that two vendors will be able to provide, let's say, the oracle factory, but that still means that the portability of final programs will be severely limited because of the strong dependency on the availability of any given factory in the target environment. 2. Define some "reasonable" set of backends (the current set in SOCI is reasonable) and oblige vendors to implement all of them. This is completely unrealistic for political reasons. 3. Decouple the low-level mechanics even further and state that the way to choose the backend is implementation-defined and external to the C++ itself. This basically brings us to ODBC, which we might therefore standardize right now. My point is that even though I really see SOCI as a very practical tool for people that need practical solutions, I don't see how it might get ever standardized. You just cannot standardize that the library has to support Oracle/MySQL/whatever and if you don't standardize it, there is very little left.
The C++ committee's LWG tends to prefer that a library expose the lower-level functionality used to build higher-level abstractions, particularly when the library is implemented by calls to third-party API's.
This is to a large extent how SOCI works. The backend interface is specified and documented and we were very successful with this - people just jumped in to the project with ready backends that complied with the interface. Most of the time, of course, the authors of new backends have borrowed from existing backends, but it's in principle not necessary.
Speaking of third-parties, requiring the user to include headers specific to particular back-ends sounds controversial, although I haven't studied SOCO's interface yet so don't know that for sure.
You don't include third-party API. You only include the header that gives you visibility of the given factory. In other words, in order to do this: Session sql(oracle, "some params"); you need to #include "soci.h" (for Session and other independent stuff) and "soci-oracle.h" (so that you see oracle as the name of the singleton factory). This is no different than for example: #include "iolibrary.h" #include "sockets.h" where sockets is just one possible factory for use with iolibrary, or this: #include "gui.h" #include "silverbuttons.h" and so on. There should be nothing controversial with this approach. -- Maciej Sobczak : http://www.msobczak.com/ Programming : http://www.msobczak.com/prog/

Maciej Sobczak wrote:
In fact, I see three possibilities:
1. Define backend interface in a way that allows vendors to provide standard-compliant backends. From the interface point of view they will be replaceable, so that two vendors will be able to provide, let's say, the oracle factory, but that still means that the portability of final programs will be severely limited because of the strong dependency on the availability of any given factory in the target environment.
2. Define some "reasonable" set of backends (the current set in SOCI is reasonable) and oblige vendors to implement all of them. This is completely unrealistic for political reasons.
3. Decouple the low-level mechanics even further and state that the way to choose the backend is implementation-defined and external to the C++ itself. This basically brings us to ODBC, which we might therefore standardize right now.
FWIW: POSIX has been standardized without any mentioning, how the backend should be implemented (which file system to use etc.), STL has been standardized without any mentioning, how to implement a std::map etc. I think you should use a similar approach, just standardize the interface and leave the backend implementation to the vendor (what's possible, though, is to specify the interface to the backend as well, just to make these interchangeable). Portability of a application should not be compromized in this scenario, because your application runs without changes on any platform supporting the standarized API not caring about the used backend. In the end you don't care about the used filesystem as well... Regards Hartmut

Hartmut Kaiser wrote:
FWIW: POSIX has been standardized without any mentioning, how the backend should be implemented (which file system to use etc.), STL has been standardized without any mentioning, how to implement a std::map etc.
Yes, but here it's not the question of "how", but "what". In particular: will any given library vendor be obliged to provide backend for Oracle? If yes, why Oracle and how to reference this as a commercial produce from the ISO document? If not, what is the basis for portable applications then?
I think you should use a similar approach, just standardize the interface and leave the backend implementation to the vendor (what's possible, though, is to specify the interface to the backend as well, just to make these interchangeable).
This is already done. It's just that you can only use the backends that are provided with the library. If the library implementation is only one (SOCI), there is no problem, because the set of backends is known.
Portability of a application should not be compromized in this scenario, because your application runs without changes on any platform supporting the standarized API not caring about the used backend.
So how will you connect to Oracle server then?
In the end you don't care about the used filesystem as well...
Yes, but filesystem is abstracted away by the operating system and that's why we don't care. This is not the case with database servers. And you might even want to connect to two different servers from a single program. -- Maciej Sobczak : http://www.msobczak.com/ Programming : http://www.msobczak.com/prog/

Maciej Sobczak wrote:
Beman Dawes wrote:
I'm asking because I think that the answer may influence interface choices, e.g. to simplify support for single backend implementations or to limit use of Boost libraries to those accepted in the TR's.
For the public interface, I think it is appropriate to depend on any Boost library accepted for TR1,TR2, or C++0x. As far as the internal implementation goes, that is pretty much up to the library's implementors, IMO.
Which raises a series of new questions. Now, the SOCI library provides a common interface that is independent from the particular server technology (well, as far as SQL dialects go...). The user of the library can select any supported platform by naming the factory object at the connection time:
Session sql(oracle, "some parameters");
Above, oracle is a name of the factory singleton that is used by Session to create concrete instances for relevant backend objects.
For the last three releases we have focused on getting as many working backends (which translate into many factories) as possible, which makes SOCI practically useful. The word "practically" is crucial here, because this is where the possible standardization process can get tricky. The standard was always very careful not to impose any constraints that would unnecessarily limit the implementation possibilities and this will have to be applied here as well. I understand that the committee will be reluctant to put any obligation that the implementation must provide this or that backend factory, which in reality will mean that vendors will be able to provide no factory at all, or just their favourite, so that there will be environments that don't have any single factory in common. Just for the sake of practical example: Microsoft will provide odbc and/or mssql factory, GNU people will provide mysql and postgresql and the portability of final applications is gone. In fact, I see three possibilities:
1. Define backend interface in a way that allows vendors to provide standard-compliant backends. From the interface point of view they will be replaceable, so that two vendors will be able to provide, let's say, the oracle factory, but that still means that the portability of final programs will be severely limited because of the strong dependency on the availability of any given factory in the target environment.
2. Define some "reasonable" set of backends (the current set in SOCI is reasonable) and oblige vendors to implement all of them. This is completely unrealistic for political reasons.
3. Decouple the low-level mechanics even further and state that the way to choose the backend is implementation-defined and external to the C++ itself. This basically brings us to ODBC, which we might therefore standardize right now.
How about this: 4. Same as (1), but also require one generic backend, say "default_backend", with a portable set of parameters that are really just hints. Vendors could supply additional backends if they desired. The details of default_backend are not otherwise specified. The idea is that those who care more about portability than performance can use default_backend, while those who want the attributes of some specific backend can specify it. They then have to obtain an implementation of that backend if they move to another platform.
My point is that even though I really see SOCI as a very practical tool for people that need practical solutions, I don't see how it might get ever standardized. You just cannot standardize that the library has to support Oracle/MySQL/whatever and if you don't standardize it, there is very little left.
I'll defer commenting on that until I've studied the SOCI docs a bit. Thanks for your interest in Boostifying SOCI! --Beman

Maciej Sobczak wrote:
Beman Dawes wrote: [...]
For the public interface, I think it is appropriate to depend on any Boost library accepted for TR1,TR2, or C++0x. As far as the internal implementation goes, that is pretty much up to the library's implementors, IMO.
Which raises a series of new questions. Now, the SOCI library provides a common interface that is independent from the particular server technology (well, as far as SQL dialects go...). The user of the library can select any supported platform by naming the factory object at the connection time:
Session sql(oracle, "some parameters");
Above, oracle is a name of the factory singleton that is used by Session to create concrete instances for relevant backend objects.
For the last three releases we have focused on getting as many working backends (which translate into many factories) as possible, which makes SOCI practically useful. The word "practically" is crucial here, because this is where the possible standardization process can get tricky. The standard was always very careful not to impose any constraints that would unnecessarily limit the implementation possibilities and this will have to be applied here as well. I understand that the committee will be reluctant to put any obligation that the implementation must provide this or that backend factory, which in reality will mean that vendors will be able to provide no factory at all, or just their favourite, so that there will be environments that don't have any single factory in common. Just for the sake of practical example: Microsoft will provide odbc and/or mssql factory, GNU people will provide mysql and postgresql and the portability of final applications is gone.
Why should that be? Just as you should have gotten (but did not) Oracle SQL CLI, DB2 SQL CLI, etc., all compliant with the ISO - X/Open SQL CLI standard, you should now get Oracle SOCI and DB2 SOCI each with their own backend, and possibly Boost.SOCI providing both and more. The important thing is to get the same C++ API from all of them.
In fact, I see three possibilities:
1. Define backend interface in a way that allows vendors to provide standard-compliant backends. From the interface point of view they will be replaceable, so that two vendors will be able to provide, let's say, the oracle factory, but that still means that the portability of final programs will be severely limited because of the strong dependency on the availability of any given factory in the target environment.
I expect a standard proposal not to impose any kind of constraint on how backends should be provided. The important thing is that the end user API is standardized. [...]
3. Decouple the low-level mechanics even further and state that the way to choose the backend is implementation-defined and external to the C++ itself. This basically brings us to ODBC, which we might therefore standardize right now.
Actually ODBC is about the only database access library that happens to be based on a standard... More seriously, it doesn't have to go that far. You just need to provide access to your backends from textual keywords, possibly making it possible for vendors to default to their preferred one when none is specified.
My point is that even though I really see SOCI as a very practical tool for people that need practical solutions, I don't see how it might get ever standardized. You just cannot standardize that the library has to support Oracle/MySQL/whatever and if you don't standardize it, there is very little left.
SOCI may come to satisfy two very different needs: provide a well tested end user interface for standardization *and* a practical, open source solution for accessing your databases. The standard interface may not mention specific backends, but commercial solutions will have to compete with what SOCI offers free of charge. In a way, even if vendors were to rip SOCI's implementation and call it their product it would be a success.
The C++ committee's LWG tends to prefer that a library expose the lower-level functionality used to build higher-level abstractions, particularly when the library is implemented by calls to third-party API's.
This is to a large extent how SOCI works. The backend interface is specified and documented and we were very successful with this - people just jumped in to the project with ready backends that complied with the interface. Most of the time, of course, the authors of new backends have borrowed from existing backends, but it's in principle not necessary.
I don't think how backends are provided is really a concern from the committee's point of view, even if it is of high practical importance. I understand Beman's comment to mean that the committee prefers libraries that are the thinnest layer above the underlying technology that provides sufficient abstraction. In other words SOCI should not attempt to provide a complete object/relational mapping with all bells and whistles.
Speaking of third-parties, requiring the user to include headers specific to particular back-ends sounds controversial, although I haven't studied SOCO's interface yet so don't know that for sure.
You don't include third-party API. You only include the header that gives you visibility of the given factory. In other words, in order to do this:
Session sql(oracle, "some params");
you need to #include "soci.h" (for Session and other independent stuff) and "soci-oracle.h" (so that you see oracle as the name of the singleton factory).
As I said I think that even this can and should be done away with. Cheers, Nicola Musatti

Nicola Musatti wrote:
... You just need to provide access to your backends from textual keywords, possibly making it possible for vendors to default to their preferred one when none is specified.
Yes, that is what I had in mind. If the textual name isn't supplied by the vendor, it is simply a error. Users can fallback to the vendor default, or obtain the missing backend from a third-party.
SOCI may come to satisfy two very different needs: provide a well tested end user interface for standardization *and* a practical, open source solution for accessing your databases. The standard interface may not mention specific backends, but commercial solutions will have to compete with what SOCI offers free of charge. In a way, even if vendors were to rip SOCI's implementation and call it their product it would be a success.
Yes.
I don't think how backends are provided is really a concern from the committee's point of view, even if it is of high practical importance.
Yes. I'm of the personal opinion that the committee should require that a default backend be provided, but which one isn't likely to specified in the standard.
I understand Beman's comment to mean that the committee prefers libraries that are the thinnest layer above the underlying technology that provides sufficient abstraction.
Yes.
In other words SOCI should not attempt to provide a complete object/relational mapping with all bells and whistles.
The committee might also like higher level functionality, perhaps even "a complete object/relational mapping with all bells and whistles," but that higher level functionality should be built on top of the lower level functionality. How this plays on for SOCI, I don't know yet.
Speaking of third-parties, requiring the user to include headers specific to particular back-ends sounds controversial, although I haven't studied SOCO's interface yet so don't know that for sure. You don't include third-party API. You only include the header that gives you visibility of the given factory. In other words, in order to do this:
Session sql(oracle, "some params");
you need to #include "soci.h" (for Session and other independent stuff) and "soci-oracle.h" (so that you see oracle as the name of the singleton factory).
As I said I think that even this can and should be done away with.
I'm also concerned, although I want to understand more before absolutely saying that the approach should be changed. --Beman

Beman Dawes wrote:
Nicola Musatti wrote:
[...]
In other words, in order to do this:
Session sql(oracle, "some params");
you need to #include "soci.h" (for Session and other independent stuff) and "soci-oracle.h" (so that you see oracle as the name of the singleton factory).
As I said I think that even this can and should be done away with.
I'm also concerned, although I want to understand more before absolutely saying that the approach should be changed.
I haven't followed the thread in detail, so apologies if this was already covered, but FWIW, when I had to design a db layer, I used Connection conn = createConnection( "mysql://user:password@host/database" ); The advantage of this approach is that the URL-like thing can come from a configuration file, so you don't need to recompile to change the backend. In a typical scenario, createConnection would need to look for backend_mysql.dll/.so unless the support for the 'mysql' backend has been statically linked.

Peter Dimov wrote:
Beman Dawes wrote:
Nicola Musatti wrote:
[...]
In other words, in order to do this:
Session sql(oracle, "some params");
you need to #include "soci.h" (for Session and other independent stuff) and "soci-oracle.h" (so that you see oracle as the name of the singleton factory). As I said I think that even this can and should be done away with. I'm also concerned, although I want to understand more before absolutely saying that the approach should be changed.
I haven't followed the thread in detail, so apologies if this was already covered, but FWIW, when I had to design a db layer, I used
Connection conn = createConnection( "mysql://user:password@host/database" );
The advantage of this approach is that the URL-like thing can come from a configuration file, so you don't need to recompile to change the backend. In a typical scenario, createConnection would need to look for backend_mysql.dll/.so unless the support for the 'mysql' backend has been statically linked.
Peter, Personally, I like it pretty much. It would also make a try to unify connection strings for all backends. I will vote on it when we start deeper analysis of all these great ideas of new features. Cheers -- Mateusz Loskot http://mateusz.loskot.net

Nicola Musatti wrote:
As I already mentioned in a previous discussion I believe that a distinction should be introduced between core DB access functionality and higher abstractions such as the object/relational mapping, especially in view of a possible standard submission.
Yes, the SOCI library has this layered structure: http://soci.sourceforge.net/doc/structure.html
Diagnostics is another area that deserves consideration. In a way failures are easy to handle, because you can always, or rather should always, throw exceptions. On the other hand I don't think there's a proven best way for providing non terminating, informative diagnostics.
That's right, this subject is scary. Just consider the fact that some servers do not have numbered error codes (that would be straightforward to map), just strings. Add to this another fact that the server can be "i18ned" and the language of the error message can be chosen by a the admin at the server startup.
Is it possible to devise a unified approach that combines general backend information to details on data retrieval results (eg. nulls, truncation, etc.)?. This is directly connected to value representation issues, like the use of Boost.Optional to represent nulls, etc.
I think that the indicators in SOCI provide this unified approach. -- Maciej Sobczak : http://www.msobczak.com/ Programming : http://www.msobczak.com/prog/

I know the review hasn't even been requested yet but here are some interface suggestions. 1) Session constructor that takes a std::map<basic_string<>, basic_string<>> as the second parameter instead of "service=orcl user=scott password=tiger". 2) With respect to the first request, standard names for username, password and ... that gets mapped automatically into database specific parameter names. You are already doing something similar for parameterized queries. 3) CLOB ie. Ntext that automatically gets extracted as a string field. 4) CLOB class to complement your Blob class 5) A STL compatiple stream interface to your Blob. Boost could help out here. 6) Official support for the wstring type 7) A place to register data providers and to choose one programmatically so that ones code can be configured to use a different database without recompiling. -----Original Message----- From: boost-bounces@lists.boost.org [mailto:boost-bounces@lists.boost.org] On Behalf Of Maciej Sobczak Sent: Tuesday, December 05, 2006 4:24 AM To: boost@lists.boost.org Subject: [boost] SOCI 2.2.0 - The C++ Database Access Library Hi, It's already a matter of "tradition" that all database discussions here have something to do with SOCI. ;-) To confirm this "tradition", I would like to announce that the new version (2.2.0) of the SOCI library is available for download: http://soci.sourceforge.net/ This new version provides: 1. Two new backends: - ODBC (tested with MS SQL Server) - Firebird 2. Complete build system for both Unix/Linux (autotools) and Windows (solution files for MSVC++). 3. STL-compatible iterators: Rowset<string> rs = (sql.prepare << "select name from persons"); copy(rs.begin(), rs.end(), ostream_iterator<string>(cout, "\n")); 4. Stream-like interface for easier dynamic binding and field extraction from rows: Row r; sql << "select name, age, salary from persons where ...", into(r); string name; int age, salary; r >> name >> age >> salary; 5. The comprehensive set of common tests for all supported database servers. 6. Some performance improvements for PostgreSQL. 7. Better docs. 8. Various fixes and tweaks. I would like to stress that the ODBC support was our important milestone that now allows us to claim a quite extensive coverage of existing database technologies. With this in mind, SOCI becomes even more serious and our roadmap for the nearest future is to bring the library to the state that will make it a valid candidate for inclusion into Boost. We will therefore welcome your guidance and suggestions w.r.t. Boost compliance. Note that up to this release, the library was deliberately developed without any external dependencies, so there are obviously wide areas where Boost might be applied within the library itself (example: intrusive pointers to manage some refcounted objects). This is easy. The more difficult part is the library interface and its general philosophy. We welcome your feedback. -- Maciej Sobczak : http://www.msobczak.com/ Programming : http://www.msobczak.com/prog/ _______________________________________________ Unsubscribe & other changes: http://lists.boost.org/mailman/listinfo.cgi/boost

Jarrad Waterloo wrote:
I know the review hasn't even been requested yet but here are some interface suggestions.
1) Session constructor that takes a std::map<basic_string<>, basic_string<>> as the second parameter instead of "service=orcl user=scott password=tiger".
I'm not convinced. First of all, std::map is nothing special. Why not unordered_map? It would be probably better to provide a dedicated helper function that takes the map and build the string from it. Second, some servers don't expect key=value pairs, there might be something entirely different (for example, SQLite3 expects just a filename).
2) With respect to the first request, standard names for username, password and ... that gets mapped automatically into database specific parameter names.
How would you like to use it?
3) CLOB ie. Ntext that automatically gets extracted as a string field. 4) CLOB class to complement your Blob class
Yes, these two are considered.
5) A STL compatiple stream interface to your Blob.
It's not necessarily portable. Various servers differ widely in how they approach BLOB as a concept. The whole idea needs more specs - how should the streaming operation relate to transactions, for example?
6) Official support for the wstring type
Indeed, this seems to be important.
7) A place to register data providers and to choose one programmatically so that ones code can be configured to use a different database without recompiling.
In a sense you can do this with SOCI. Backends are linked-in (so there is no run-time "registration") and the session is started with polymorphic reference to the backend factory. If you expect entirely out-of-program registration/selection support, you have it in the form of ODBC. -- Maciej Sobczak : http://www.msobczak.com/ Programming : http://www.msobczak.com/prog/

I know the review hasn't even been requested yet but here are some interface suggestions.
1) Session constructor that takes a std::map<basic_string<>, basic_string<>> as the second parameter instead of "service=orcl user=scott password=tiger".
I'm not convinced. First of all, std::map is nothing special. Why not unordered_map? It would be probably better to provide a dedicated helper function that takes the map and build the string from it. Second, some servers don't expect key=value pairs, there might be something entirely different (for example, SQLite3 expects just a filename).
2) With respect to the first request, standard names for username,
Std::map was just an example. Whether it is map, unordered_map, vector of name value tuples, it is all the same to me as an object oriented consistent approach to access and build the parameters for a session. This could even be a helper class though I would imagine that the api layer itself might like it in a structured approach so that it wouldn't have to parse it in order to format it correctly. Then again I am a user and not library implementer and just looking for this functionality which is also commonly found in ODBC?,OLEDB,ADO,JDBC and ADO.NET. password
and ... that gets mapped automatically into database specific parameter names.
How would you like to use it?
If a lot of databases has a parameter name that serve the same purpose of a user name it would be nice if each implementation could recognize some standard that you set up that the user can specify 'username' and the implementer will treat it like or translate into their specific terminology 'user name', 'user', 'user id' ...
3) CLOB ie. Ntext that automatically gets extracted as a string field. 4) CLOB class to complement your Blob class
Yes, these two are considered.
5) A STL compatiple stream interface to your Blob.
It's not necessarily portable. Various servers differ widely in how they approach BLOB as a concept. The whole idea needs more specs - how should the streaming operation relate to transactions, for example?
With respect to transactions, however your current Blob implementation works or it can be modeled after how other standard are designed. It may not even matter in many cases since one most common scenario is to write out the whole thing at construction and read out the whole thing multiple times during the lifetime of the record. The most important thing is having a consistent interface that play nicely with STL and other STL compatible streams created with Boost stream libraries.
6) Official support for the wstring type
Indeed, this seems to be important.
7) A place to register data providers and to choose one programmatically so that ones code can be configured to use a different database without recompiling.
In a sense you can do this with SOCI. Backends are linked-in (so there is no run-time "registration") and the session is started with polymorphic reference to the backend factory. If you expect entirely out-of-program registration/selection support, you have it in the form of ODBC.
ODBC is a important and necessary bridge to the past to get new users on board however as you the library move forward users prefer native libraries written within your api as there are fewer layers (performance), potentially more functionality and fewer points of failure. As such SOCI will need to be able to do mostly anything ODBC can do but better. This is just one of them. Business Requirement: User wants to write and compile their program and have it work with any database. Business Requirement: Database provider wants SOCI to do as much work and provide as much requirements as possible so the amount of code they have to write is minimal. Business Requirement: User eventually wants simple easy to create provider api so that they can create a SOCI compliant proxy around their data sources so that that other api's that know SOCI will work with it. -- Maciej Sobczak : http://www.msobczak.com/ Programming : http://www.msobczak.com/prog/ _______________________________________________ Unsubscribe & other changes: http://lists.boost.org/mailman/listinfo.cgi/boost

On 12/6/06, Jarrad Waterloo <jwaterloo@dynamicquest.com> wrote:
I'm not convinced. First of all, std::map is nothing special. Why not unordered_map? It would be probably better to provide a dedicated helper function that takes the map and build the string from it. Second, some servers don't expect key=value pairs, there might be something entirely different (for example, SQLite3 expects just a filename).
Std::map was just an example. Whether it is map, unordered_map, vector of name value tuples, it is all the same to me as an object oriented consistent approach to access and build the parameters for a session. This could even be a helper class though I would imagine that the api layer itself might like it in a structured approach so that it wouldn't have to parse it in order to format it correctly. Then again I am a user and not library implementer and just looking for this functionality which is also commonly found in ODBC?,OLEDB,ADO,JDBC and ADO.NET.
Why not an input iterator range? You could fairly easily check if the value_type was a pair and convert stream into the string as name=value in that case (maybe not including the = if the value's string is empty) or just stream it straight into the string with spaces between if it's not a pair. I suppose an arbitrary container would also work. ~ Scott

Hello, I'm pretty much a lurker on this list that loves to watch what is new coming out and learn from the discussions. A database library interests me a lot though, so for once, I have questions. 1. Transactions begin, commit, and rollback are provided. I did not see any comments in the docs of code to help keep this exception safe. Should the burden of exception safety be passed onto the library? One possibility is Begin returns a "Transaction," a proxy for a "Session," that has a commit function, and will call rollback in the destructor. A transaction proxy would give the impression that several independent proxies may exist, which I am not sure if that could be made accurate, but if not at least it is a thought. 2. Query Construction I read the rationale for not having a query construction syntax. To sum up my understanding of it: when working with DBAs it is good to have queries separate. For some of us hobbyists or for prototyping it might be nice, especially so we do not have to worry about syntax issues that are minor and wouldn't show up till runtime. If the query construction was built on top of taking strings then it would still allow for users to choose whether to use the query construction or to have the expressions stored in a file. This converting it to a string could even be used to easily stream out all of the expressions to a file to ease transition from a compiled version to a runtime file version for the DBAs One possibility is: sql << select("name", "salary").from(persons).where.("id = ",id), into(name), into(salary); Original (From webpage): sql << "select name, salary from persons where id = " << id, into(name), into(salary); The where clause could be templated to allow id to be whatever type (using stringstream or lexical_cast?) to provide simiilar behavior to the "<< id" Some improvements could include: *Setting up column objects: It would take a column name and what table it is from. 1) Could serve as a precondtion: That the column does exist in the table 2) Generate the from clause for you For example: Column personsName ("name", "persons"); Column personsSalary ("salary", "persons"); sql << select(personsName, personsSalary).where.("id = ",id), into(name), into(salary); *lambda like expressions for generating the where clause. It could then be simplified ... Column personsId ("id", "persons"); sql << select(personsName, personsSalary).where.(personsId == id), into(name), into(salary); With this, it could even be improved by tempaltizing the Columns for what type should be contained therein. Then the where clause expression generator could compare the template type of "personId" to "id" A potential complaint is that this makes it too easy to mix tables unintentionally. This is not meant as critisism or something to hold up a review, but suggestions for refining the API according to my limited understanding of code design and SOCI. Reasons for these to not work or improvements on these ideas are definetly welcome. Ed Page

Hi, Edward Page wrote:
I'm pretty much a lurker on this list that loves to watch what is new coming out and learn from the discussions. A database library interests me a lot though, so for once, I have questions.
1. Transactions
begin, commit, and rollback are provided. I did not see any comments in the docs of code to help keep this exception safe.
Yes, we were lazy and the RAII wrapper for transactions somehow was not implemented. :-) This will be certainly provided in the future versions.
2. Query Construction
I read the rationale for not having a query construction syntax. To sum up my understanding of it: when working with DBAs it is good to have queries separate. For some of us hobbyists or for prototyping it might be nice, especially so we do not have to worry about syntax issues that are minor and wouldn't show up till runtime. If the query construction was built on top of taking strings then it would still allow for users to choose whether to use the query construction or to have the expressions stored in a file. This converting it to a string could even be used to easily stream out all of the expressions to a file to ease transition from a compiled version to a runtime file version for the DBAs
One possibility is: sql << select("name", "salary").from(persons).where.("id = ",id), into(name), into(salary);
Original (From webpage): sql << "select name, salary from persons where id = " << id, into(name), into(salary);
The where clause could be templated to allow id to be whatever type (using stringstream or lexical_cast?) to provide simiilar behavior to the "<< id"
Actually, there is nothing that would prevent you from having this. The operator<< in SOCI is just a template forwarder to a regular std::ostringstream object. This means that *whatever* you have that is streamable can go there. If you want to build your own framework of the query builders, go ahead, just make the result of it streamable. We just decided not to do this on our own, for the reasons that you already found in rationale. Still, you can treat SOCI as extensible in this area. If you would like to write your own query builders, there is no obstacle. Just make their result streamable.
Some improvements could include: *Setting up column objects: It would take a column name and what table it is from. 1) Could serve as a precondtion: That the column does exist in the table 2) Generate the from clause for you For example: Column personsName ("name", "persons"); Column personsSalary ("salary", "persons");
sql << select(personsName, personsSalary).where.("id = ",id), into(name), into(salary);
I don't see much benefit in it. Think about multi-table joins or procedure calls. Still, feel free to provide more arguments to support this idea. :-) (And note that this would be more tricky with the current library.)
*lambda like expressions for generating the where clause. It could then be simplified ... Column personsId ("id", "persons"); sql << select(personsName, personsSalary).where.(personsId == id), into(name), into(salary);
With this, it could even be improved by tempaltizing the Columns for what type should be contained therein. Then the where clause expression generator could compare the template type of "personId" to "id"
Similarly, this looks like overengineering to me. Of course, I might just not see the opportunities that are there. Please provide more explanation for this example. Note that the code can be made generic in the obvious way by wrapping the query in the template and having name and salary to be of some template type. Note that the main raison d'etre for SOCI was to make database programming as easy and the code as readable as possible. The above examples are somehow contrary to this motivation. -- Maciej Sobczak : http://www.msobczak.com/ Programming : http://www.msobczak.com/prog/

On 12/5/06, Maciej Sobczak <prog@msobczak.com> wrote:
Hi,
Hello Maciej, [snipped]
We welcome your feedback.
FWIW, it is a very strong naming standard in boost to use uppercase words *only* for macros. I believe that namespace SOCI is a little ugly to look. But of course it is just a matter of taste.
-- Maciej Sobczak : http://www.msobczak.com/ Programming : http://www.msobczak.com/prog/
Best regards, -- Felipe Magno de Almeida

-----Original Message----- From: boost-bounces@lists.boost.org [mailto:boost-bounces@lists.boost.org] On Behalf Of Felipe Magno de Almeida Sent: 05 December 2006 22:28 To: boost@lists.boost.org Subject: Re: [boost] SOCI 2.2.0 - The C++ Database Access Library
On 12/5/06, Maciej Sobczak <prog@msobczak.com> wrote:
[snipped]
We welcome your feedback.
FWIW, it is a very strong naming standard in boost to use uppercase words *only* for macros. I believe that namespace SOCI is a little ugly to look. But of course it is just a matter of taste.
But names are very important and SOCI seems a really bad 'name' to me, even in these acronymic times. I couldn't even quickly find what it was an acronym for! And so the namespace name is also a bad choice. If we can agree that this has a Boost library 'candidate' status (something I think we need a formal procedure to assign), then you could claim Boost.SQL? I suggest that you now ask Boosters for suggestions for names and try to get a consensus before review. The longer you delay a name change, the worse the grepping job ;-) Paul --- Paul A Bristow Prizet Farmhouse, Kendal, Cumbria UK LA8 8AB +44 1539561830 & SMS, Mobile +44 7714 330204 & SMS pbristow@hetp.u-net.com

Paul A Bristow wrote:
If we can agree that this has a Boost library 'candidate' status (something I think we need a formal procedure to assign), then you could claim Boost.SQL?
SOCI isn't an SQL library, really...
I suggest that you now ask Boosters for suggestions for names and try to get a consensus before review. The longer you delay a name change, the worse the grepping job ;-)
I agree, the name should change. I'd look to the title of the email for guidance: The C++ Database Access Library -- I think the last part works pretty well -- says what the library does and can be abbreviated to simply DAL. Jeff

-----Original Message----- From: boost-bounces@lists.boost.org [mailto:boost-bounces@lists.boost.org] On Behalf Of Jeff Garland Sent: 06 December 2006 15:29 To: boost@lists.boost.org Subject: Re: [boost] SOCI 2.2.0 - The C++ Database Access Library
I agree, the name should change. I'd look to the title of the email for guidance: The C++ Database Access Library -- I think the last part works pretty well -- says what the library does and can be abbreviated to simply DAL.
But does it have to be abbreviated? (I'm thinking of founding Acronymics Anonymous...) We know it is a library - otherwise everything in Boost would have to end with an L (and STL and MPL set bad examples that we should not follow). Other library items have a plain name, and matching namespace - like Fusion - and a full name. How about Boost.Access? and namespace boost::access; Surely that name can't be taken ;-) Paul --- Paul A Bristow Prizet Farmhouse, Kendal, Cumbria UK LA8 8AB +44 1539561830 & SMS, Mobile +44 7714 330204 & SMS pbristow@hetp.u-net.com

Other library items have a plain name, and matching namespace - like Fusion - and a full name.
How about Boost.Access? and namespace boost::access;
Surely that name can't be taken ;-)
Or how about Boost.Database, following the lead of Boost.Filesystem? They both do the same kind of thing. Austin Bingham

Austin Bingham wrote:
Other library items have a plain name, and matching namespace - like Fusion - and a full name.
How about Boost.Access? and namespace boost::access;
Surely that name can't be taken ;-)
Or how about Boost.Database, following the lead of Boost.Filesystem? They both do the same kind of thing.
Boost.Database seems exactly right to me. The namespace would presumably be boost::database, and the headers would live in directory boost/database. If there is an "all" header, it would presumably be boost/database.hpp. --Beman

Some comments: 1. Can you please make soci work with something else than the "C" locale. Currently the Session use the global locale for streaming values which will not work since most (all?) locales use a thousand separator which is not allowed in SQL. For me sql << "insert into soci_test (id) values (" << 1234 << ")"; becomes "insert into soci_test (id) values (1 234)" I see two ways of solving it: a. Let the backend assign the locale required for sql-statements. This is the best solution since the backend can query the database to find out decimal separator and date format. b. Add an .imbue member to the session object. ---- 2. I find the "into" handling a bit inconvenient in its current shape: a. I have to create an indicator variable for each parameter. eIndicator inda, indb, indc, ...; sql << "select a,b,c,d... FROM tbl", into(vara, inda), into(varb, indb)... if (inda == eNull) vara = ""; if (indb == eNull) varb = -1; why not have a "intonull" expression that take a second nullValue argument: sql << "select a,b,c,d... from tbl", intonull(vara, ""), intonull(varb, -1)... 2. Don't understand why "NoData" is part of the indicator. Shouldn't it be part of the statement? something like: sql << "select x from tbl", into(a); if (!sql.empty()) // something was fetched or sql << "update tbl set x = 2 where y = 3"; if (sql.rowsaffected() == 0) // not found

Martin Adrian wrote:
1. Can you please make soci work with something else than the "C" locale.
Currently the Session use the global locale for streaming values which will not work since most (all?) locales use a thousand separator which is not allowed in SQL.
For me sql << "insert into soci_test (id) values (" << 1234 << ")";
becomes "insert into soci_test (id) values (1 234)"
I see two ways of solving it: a. Let the backend assign the locale required for sql-statements. This is the best solution since the backend can query the database to find out decimal separator and date format.
b. Add an .imbue member to the session object.
That's a very good point. There is also a third option here, probably most generic - expose the whole stream object, so that users can play with it on their own; this goes far beyond locale control, you can even replace the whole streambuf there. I don't see any immediate use for this, but we didn't foresee the locale issue either.
2. I find the "into" handling a bit inconvenient in its current shape: a. I have to create an indicator variable for each parameter.
eIndicator inda, indb, indc, ...;
sql << "select a,b,c,d... FROM tbl", into(vara, inda), into(varb, indb)...
if (inda == eNull) vara = ""; if (indb == eNull) varb = -1;
why not have a "intonull" expression that take a second nullValue argument: sql << "select a,b,c,d... from tbl", intonull(vara, ""), intonull(varb, -1)...
First note: you don't have to create indicator vars if you don't expect nulls. Second, the above assumes that you have some default value to replace the null. Isn't there a dedicated SQL function for this? What about: sql << "select ...", into(a, default("")), into(b, default(-1)); The point is that there is already a framework for extending into elements this way.
2. Don't understand why "NoData" is part of the indicator. Shouldn't it be part of the statement?
something like:
sql << "select x from tbl", into(a); if (!sql.empty()) // something was fetched
or sql << "update tbl set x = 2 where y = 3"; if (sql.rowsaffected() == 0) // not found
Yes, that's one possible approach. Boost.optional would handle the rest. We have to review this subject. -- Maciej Sobczak : http://www.msobczak.com/ Programming : http://www.msobczak.com/prog/

Maciej Sobczak <prog <at> msobczak.com> writes: Thank you for your quick reply.
There is also a third option here, probably most generic - expose the whole stream object, so that users can play with it on their own; this goes far beyond locale control, you can even replace the whole streambuf there. I don't see any immediate use for this, but we didn't foresee the locale issue either.
Still think it would better if the backend decides how numbers, dates etc should be formatted in the sql string.
why not have a "intonull" expression that take a second nullValue argument: sql << "select a,b,c,d... from tbl", intonull(vara, ""), intonull( varb, -1)...
First note: you don't have to create indicator vars if you don't expect nulls. Second, the above assumes that you have some default value to replace the null. Isn't there a dedicated SQL function for this?
I often run into databases where string fields can both be empty and null with no difference in meaning (just bad design). COALESCE is possible but I think the null handling should be in the code not in the sql statement. What I'm asking for is just some syntactic sugar.
What about:
sql << "select ...", into(a, default("")), into(b, default(-1));
The point is that there is already a framework for extending into elements this way.
Yes that would be ok. (default is a reserved word but I understand what you mean).
sql << "select x from tbl", into(a); if (!sql.empty()) // something was fetched
or sql << "update tbl set x = 2 where y = 3"; if (sql.rowsaffected() == 0) // not found
Yes, that's one possible approach. Boost.optional would handle the rest. We have to review this subject.
Another approach could be to follow the stream syntax with eof() and bad().

Philippe Vaucher wrote:
Rowset<string> rs = (sql.prepare << "select name from persons"); Row r;
This was probably already mentionned, but I think you'd also provide an all lowercase api to fit boost...
This is the least of all issues. Taking into account that people have a hard time choosing the *name* for the library, the lowercase api is a small piece of a small cake. :-) -- Maciej Sobczak : http://www.msobczak.com/ Programming : http://www.msobczak.com/prog/
participants (15)
-
Austin Bingham
-
Beman Dawes
-
Edward Page
-
Felipe Magno de Almeida
-
Hartmut Kaiser
-
Jarrad Waterloo
-
Jeff Garland
-
Maciej Sobczak
-
Martin Adrian
-
Mateusz Loskot
-
me22
-
Nicola Musatti
-
Paul A Bristow
-
Peter Dimov
-
Philippe Vaucher