DB Interface Module User’s Guide : PART V The Tutorials : Chapter 19 Inserting Data into a Table : The Program
The Program
This section examines the t3 program you just ran. Its purpose is to write a list of the new customers who were successfully added to the database to a file called t3out.txt.
The Main Routine
The following is the main routine for the tutorial. The line numbers correspond to the comments that follow the code.
 
#include <rw/db/db.h> //1
#include "conrep.h" //2
#include "tututil.h" //3
int main(int argc, char** argv) //4
{
associateStreams("t3in.dat", "t3out.txt",
"t3err.txt"); //5
RWDBManager::setErrorHandler(outputStatus); //6
RWCString serverType, serverName, userName,
password, databaseName, pstring; //7
initializeDatabaseArguments(argc, argv, serverType,
serverName, userName, password,
databaseName, pstring); //8
RWDBDatabase aDB = RWDBManager::database
(serverType, serverName, userName, password,
databaseName, pstring); //9
VVContactRepository customerPool(aDB, customerTable); //10
VVContact aCustomer; //11
while (aCustomer.read(inStream)) { //12
customerPool.insert(aCustomer); //13
outStream << aCustomer.name()
<< " has been added to the customer table."
<< endl; //14
}
closeStreams("t3in.dat", "t3out.txt", "t3err.txt");
return 0;
} //15
 
//1-8 These lines are for initialization. They are common to all the tutorials and are explained in the comments in “The Main Routine.”
//9 Here a connection to a database server is established. The variable aDB will serve as a handle to the database defined by arguments to the RWDBManager::database function.
//10 An instance of the class VVContactRepository is created on this line. The first argument, aDB, identifies the database in which the instance’s data resides. The second argument identifies the specific table that holds the customer information.
//11 An instance of VVContact is created here to hold the information about a new customer.
//12 In this while loop, new customers are read one at a time from the input stream. The input stream is tied to the file t3in.dat. This association is defined on line //5 using the associateStreams() utility method. When no more new customers are available on the input stream, the read routine returns false, and the loop terminates.
//13 This line invokes the insert() member function of the class VVContactRepository. This function takes the customer record as an argument and inserts it into the customer table. The code of the insert() method is described below.
//14 Once a customer record is added to the customer table, the name of the customer, along with a message, is printed to the output stream. Why isn’t there any error checking here? If an insert fails, the error handler in //6 above is called. This routine outputs an error message to the error stream and terminates the program.
//15 Destructors for all the objects are called here. The database closes automatically when its destructor is invoked.
VVContactRepository::insert
The insert member function of VVContactRepository takes an instance of VVContact and inserts it into the table associated with this instance of VVContactRepository.
 
VVContactRepository&
VVContactRepository::insert(const VVContact& aContact) //1
{
RWDBInserter anInserter = table_.inserter(); //2
anInserter << aContact; //3
return *this;
}
//1 This is the definition of the insert() member function of the VVContactRepository class. It accepts one argument, a single instance of VVContact.
//2 Here an inserter object is produced from the table associated with this instance of VVContactRepository. Through this new instance of RWDBInserter, new rows are inserted into the table.
//3 The inserter object behaves somewhat like an input stream. On this line, an instance of VVContact is shifted into the inserter. The effect is to insert the new customer into the table. This line is actually an invocation of an overloaded operator<<(). It takes an RWDBInserter instance as the left argument and a VVContact instance as the right argument. The code of the overloaded operator is described below.
operator<<() for VVContact
The purpose of this overloaded function is to ease the insertion of a VVContact instance into an RWDBInserter instance. The function combines the shifting of the individual components of a VVContact into a single function.
 
RWDBInserter&
operator<< (RWDBInserter& aInserter,
const VVContact& aContact) //1
{
aInserter << aContact.name() << aContact.id()
<< aContact.address() << aContact.city()
<< aContact.state() << aContact.zip()
<< aContact.phone(); //2
aInserter.execute(); //3
 
return aInserter;
}
//1 This line defines the overloaded left shift function for RWDBInserter and VVContact.
//2 This line shifts the individual components of a VVContact instance into an RWDBInserter instance. Each left shift is an invocation of a member function of RWDBInserter. The inserter class overloads the operator<<() for each of the basic C++ types along with several of the Rogue Wave types, such as RWCString.
//3 Shifting values into an inserter does not automatically insert the data into a table. The execute() member function of RWDBInserter actually sends the new data to the database.