Boost logo

Boost :

From: Jeff Garland (jeff_at_[hidden])
Date: 2008-03-21 09:20:53


Daniel Pfeifer wrote:
> Database access has been discussed quite often in the Boost mailing
> list. I read through the discussions from Oct 2004 and Jul/Aug 2005 and
> I am well aware of the fact that there is a lot of disagreement
> concerning the interface presented to the programmer.

Yep....

> So I just hope you don't bite my head off if I propose this as
> a GSoC project. ;)

No, but I would expect varied opinions. BTW in case you didn't catch it the
leading candidate for a boost database access library is soci:

http://soci.sourceforge.net/

That said one has to wonder if the authors are ever going to bring it for
review....

> Things I would like to implement:
> * generic binding of parameters and results (using Boost.Fusion)
> * asynchronous access (using Boost.Asio)
> * odbc, postgres, firebird, mysql and sqlite3 backends
> (using their proper C API)
> * DATE, TIME and DATETIME fields (using Boost.Date_Time or struct tm)
>
> Surely other backends can be added, but these are the ones I am (more or
> less) familiar with. BLOBs would be interesting to implement but I am
> afraid time won't permit it.

3 months is a short time. I'd suggest you pick a smaller number of backends
if you're going to propose this. The design should support expansion to the
others, but my sense is that 5 backends in 3 months isn't doable.

> The following code snippet is a quick draft using sqlite3 as a backend.
> This is not the interface I am going to propose, please read on.
>
> boost::asio::io_service io_service;
> boost::database::sqlite3::connection conn(io_service);
>
> conn.open( "testdb" );
>
> std::cout << "client version: " << conn.client_version() << std::endl;
> std::cout << "server version: " << conn.server_version() << std::endl;
>
> boost::database::sqlite3::statement stmt = db.statement();
>
> stmt.prepare( "CREATE TABLE employee"
> "(id INT,name CHAR(20),salary INT,PRIMARY KEY(id))" );
> stmt.execute();
>
> // prepared statement with placeholders
> stmt.prepare( "INSERT INTO employee (id,name,salary) VALUES (?,?,?)" );
> stmt.execute( boost::fusion::make_vector(
> 27, "Horst Zwiebelhacker", 5000) );
>
> stmt.prepare( "SELECT name, salary FROM employee" );
> stmt.execute();
>
> // fetch directly into specified results
> std::string name; int salary;
> while( stmt.fetch( boost::fusion::vector_tie(name,salary) ) )
> {
> std::cout << name << " gets " << salary << " pebbles." << std::endl;
> }
>
> The "open", "prepare" and "execute" functions have "async_"
> counterparts. The sync functions throw exceptions while the async ones
> pass an error to the bound handle as the first parameter.

That's an interesting capability that AFAIK soci doesn't support.

> Both the synchronous and the asynchronous test programs run fine, though
> they are not thread safe (the final library definitely will be).
> I checked if it would be straightforward to implement other backends,
> which turned out to be true for most of them. I struggled with
> PostgreSQL where the type of the parameters has to be known when the
> statement is prepared.
>
> The syntax suggested by Tito Villalobos for declaring a statement seems
> to be a better approach (slightly modified by me):
>
> statement<
> parameters<...>, // query/stored procedure parameter types
> results<...> // recordset column types
> > my_stmt(connection, query_string);
>
> This would make it easier to prepare statements in PostgreSQL and can be
> a benefit for other backends too. Statements could be automatically
> prepared when their execute function is called the first time.
> Finally, variadic templates in C++0x allow to hide the functions
> boost::fusion::make_vector and boost::fusion::vector_tie from the
> programmer, which makes the interface much more intuitive. Imagine
> stmt.execute(27, "Horst Zwiebelhacker", 50000);
> or
> while( stmt.fetch(name,salary) ) ...
> isn't that lovely?

Yeah, that's cool :-)

> Just for clarity: The design I have in mind will provide the programmer
> with an easy way to use SQL. Still the programmer has to write her own
> SQL strings. A library which provides STL functionality by abstracting
> SQL could be built on top of this one. I would like to concentrate on
> making it asynchronous rather than on the STL part.

This is a difficult area as I'd like to suggest you work on extending SOCI to
do this, but given that soci isn't a Boost library I can't really do that. I
think the biggest issue you have is keeping a reasonable scope -- in general a
full database binding library is too large for SoC. That said I see some good
ideas in your proposal so I'm not going to discourage you -- the mentors and
other boosters can help you refine your proposal down to something useful and
doable.

Thanks!

Jeff


Boost list run by bdawes at acm.org, gregod at cs.rpi.edu, cpdaniel at pacbell.net, john at johnmaddock.co.uk