dbstreams User Guide: How to use the dbstreams database access class libarary | ||
---|---|---|
Prev | Chapter 2. Jumping In | Next |
More likely than not, the application keeps its data in some kind of container, perhaps a std::vector or std::list. Populating and saving them with an ordinary C library can be a royal pain in the tucus.
The simplest way to fill and save a container uses dbstream::read and dbstream::write. [1] The technique relies on read & write methods in the container's value_type class to implement the logic to write/read one row to/from the database. In this example, the object's write method is general enough that it can also be used to write to a std::iostream.
Example 2-2. Container Example
class example_row { int i; double d; std::string s; public: template <typename OS> OS& read( OS& os ) { os >> c("t") >> i >> c("r") >> d >> c("s") >> s; return os; } template <typename OS> OS& write( OS& os ) const { os << i << d << s << endl; return os; } }; std::deque<example_row> rowset; dbstream<dbstatus> db(provider, username, password); db.open( servername, catalog ); if( !db ) throw db.status(); /* (Table T was created and populated in the first example.) */ q = "select * from T "; db << q; if( !db ) { throw db.status(); } db.read( rowset ); db.table("T"); db.write( rowset ); if( !db ) { throw db.status(); } db.close();
Elements of Filling and Saving a Container
class example_row { int i; double d; std::string s; public: template <typename OS> OS& read( OS& os ) { os >> c("t") >> i >> c("r") >> d >> c("s") >> s; return os; } template <typename OS> OS& write( OS& os ) const { os << i << d << s << endl; return os; } }; std::deque<example_row> rowset;
Something, somewhere, somehow has to define how the container's data map onto a row in the database. In this paradigm, that's done by the container element class.
The mapping function must be called read and write, and they must take a dbstream
as their only argument.
db.read( rowset );
The dbstream::read function accepts any kind of container for which iterators and push_back are defined. Perhaps the code is easier to understand than the description, so here is the definition of dbstream::read:
template <typename CONTAINER> dbstream<STATUS> read( CONTAINER& container ) { while( status() && !status().eof() ) { CHECK_PROVIDER(); typename CONTAINER::value_type element; element.read( *this ); container.push_back( element ); pprovider->next_row(); } return *this; }
Although there's some implementation detail here, it's not important to understanding how the function works. For every row in the stream, the container's value_type::read function is called, and the (now populated) object is appended to the container.
db.table("T"); db.write( rowset );
Open the table and write the container. The logic is the mirror of reading.
[1] | A more general method, using iterators, is planned but not yet implemented. |