DB Interface Module User’s Guide : PART II Using the Basic Features : Chapter 4 The Database Classes : Tables : Reading Tables: Class RWDBReader
Reading Tables: Class RWDBReader
Before we look at the other types of tables available in the DB Interface Module, let’s look at how the data in a table is read. The next example program shows how to read information from a table using the class RWDBReader. The database table it references is the purchase table, which is part of the tutorials for SourcePro DB.
NOTE >> You must install and compile the tutorials when you install the SourcePro DB in order to run this example. See Installing and Building Your SourcePro C++ Products and Building Your Applications for more information.
To run this example, change the parameters for the RWDBManager::database() call to fit your system. To use this code, the <ver> placeholder in any library names would need to be replaced with the actual digits representing the library version number.
Example 2 – Reading a database table
// Example Program 2 - Reading a database table
#include <rw/rstream.h>
#include <rw/db/db.h>
 
int
main()
RWDBDatabase myDbase = RWDBManager::database(
"libctl<ver>12d.so", // DB Access Module name
"SYBASE100", // server name
"user", // user name
"pwd", // password
"DEMO_DB" // database name
);
RWDBConnection myConnection = myDbase.connection();
RWDBTable purchases = myDbase.table("purchase");
RWDBReader rdr = purchases.reader(myConnection);
 
int videoID;
int supplierID;
int purchaseOrderNumber;
RWDecimalPortable pricePerUnit;
int quantity;
 
while (rdr()) {
RWDateTime date;
rdr >> videoID >> supplierID >> purchaseOrderNumber //1
>> pricePerUnit >> quantity >> date;
std::cout << videoID << "\t" << supplierID << "\t"
<< purchaseOrderNumber << "\t" << pricePerUnit << "\t"
<< quantity << "\t" << date.asString() << std::endl;
}
return 0;
}
RWDBReader reads tabular data, providing sequential access to a table's rows, and random access to fields within a row.
While traversing a table's rows, a reader acts much like an iterator. When a reader is first obtained from a table, it is positioned before the first row of the table. The C++ function call operator() is used to advance the reader to the next row. When there are no more rows, it returns 0.
Within a row, the reader is used with the extraction operator >>, which extracts values from the reader into program variables. Because indexing by column name and column number is also supported, we could have written //1 of our example like this:
 
rdr["videoID"] >> videoID;
rdr["supplierID"] >> supplierID;
// etc.
If we were concerned about NULL values in certain columns, we could have used indicator variables with our reader as a way to detect them:
 
RWDBNullIndicator nullVideo, nullSupplier;
int videoID;
int supplierID;
int purchaseOrderNumber;
RWDecimalPortable pricePerUnit;
int quantity;
RWDateTime date;
 
while (rdr()) {
rdr >> nullVideo >> videoID >> nullSupplier >> supplierID
>> purchaseOrderNumber >> pricePerUnit >> quantity >> date;
if (nullVideo || nullSupplier) {
std::cout << "Missing Information!" << std::endl;
}
else {
std::cout << videoID << "\t" << supplierID << "\t"
<< purchaseOrderNumber << "\t" << pricePerUnit << "\t"
<< quantity << "\t" << date.asString() << std::endl;
}
}
Overloading the Extraction Operator
The extraction operator is defined for all the C++ and DB Interface Module data types. Naturally, it is easy to define it for your own classes. For example:
 
struct Purchase {
int videoID;
int supplierID;
int purchaseOrderNumber;
RWDecimalPortable pricePerUnit;
int quantity;
RWDateTime date;
};
RWDBReader&
operator>>(RWDBReader& rdr, Purchase& p) {
rdr >> p.videoID >> p.supplierID
>> p.purchaseOrderNumber
>> p.pricePerUnit >> p.quantity >> p.date;
return rdr;
}
Now we can read from the purchase table directly into Purchase instances:
 
Purchase p;
 
while (rdr()) {
rdr >> p;
// process p;
}
This is an important technique, and it is explained more thoroughly in Chapter 17, “Retrieving Data from a Table,” the first advanced tutorial.