| 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. |