Rogue Wave banner
Previous fileTop of DocumentContentsIndex pageNext file
DB Interface Module User's Guide
Rogue Wave web site:  Home Page  |  Main Documentation Page

17.5 The Program

This section examines the t1 program you just ran. Its purpose is to output the mailing labels for all the customers to a file called t1out.txt.

17.5.1 The Main Routine

This code sample shows how to use the classes VVContact and VVContactRepository. The line numbers correspond to the comments that follow the code.

Here is a line-by-line description of the program:

//1

Include the declarations for the DB Interface Module classes used in this program.

//2

Include the declaration for the class VVContactRepository.

//3

Include the declarations for the utility routines commonly used by all the tutorials.

//4

Start of the main routine of the tutorial. It accepts database connection arguments which can be used to override the defaults.

//5

Again, because of cross-platform development issues, we decided that all input and output for these tutorials should take place to and from files. This is because Windows applications do not necessarily have access to the standard cin, cout, and cerr streams. This function allows file names to be associated with the three streams. The first argument represents input to the program. Since no input from a theoretical user is necessary in this program, an empty string is offered. The second argument is the stream for standard output. The mailing labels go out to this file. The third argument is for error messages. Although associateStreams() is not part of the DB Interface Module, it is provided for cross-platform portability of these tutorials.

//6

This line sets up an error handler. If this program is running, the database reports an error while this program is running the function pointed to by outputStatus() is invoked. The function outputStatus() is in tutdefs.h. It checks the severity of the error and decides if the program should be aborted after it sends the error details to a file specified on the previous line.

//7

Here, six RWCString instances are declared. They will hold information used in logging into the database server.

//8

The routine called here places values into the RWCString instances declared on the preceding line. The user of this program can override the default values on the command line. This routine hides the complexity of the parsing. The function initializeDatabaseArguments() is not part of the DB Interface Module and exists only for the convenience of these tutorials. You can find the definitions in the tututil.h include file..

//9

Here an actual connection to a database server is established. The variable aDB will contain the means to access 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

The class VVContactRepository contains several useful member functions. The one invoked on this line spools mailing labels out for all customers to the stream specified as the argument.

//12

Destructors of all the objects are called here. The database closes automatically as its destructor is called.

This program is really quite short, considering all that it accomplishes. Lines //10 and //11 do most of the work. A detailed examination of the code behind these lines is important for understanding how the DB Interface Module is best used.

17.5.2 VVContactRepository Constructor

Let's look closely at the constructor for VVContactRepository found in the file conrep.cpp. This constructor sets the stage for manipulating the pool of customers.

//1

The first line simply declares the input parameters: a reference to the database and the name of the table holding the customer data.

//2

An instance of VVContactRepository maintains a copy of the database that it is associated with. This initialization makes the association.

//3

An instance of VVContactRepository also maintains a table that represents the customer table in the database. It does this by calling the table() member function of its database object. This function returns an instance of RWDBTable. It is important to note that creating an instance of RWDBTable does not force the RWDBDatabase instance to check the server for the existence of the table. The DB Interface Module accesses the database server only when data is actually manipulated or read. When the table() member function of the class RWDBDatabase instance returns an RWDBTable instance, it is saved by this constructor for future use.

//4

In these seven lines, the columns of the table in the database are identified and saved as instances of RWDBColumn. Most of these columns are not used in this tutorial, but they are important in future exercises.

//5

The actual body of the constructor has nothing to do. All the work was done by the initializations.

17.5.3 VVContactRepository::mailingLabels

Now that the construction of the VVContactRepository instance is complete, the next step in the main routine program was to call the mailingLabels() member function. Here is the source code for VVContactRepository::mailingLabels() from the file conrep.cpp and the description of the code:

//1

This line defines the mailingLabels() member function for the class VVContactRepository, which receives an output stream as its argument.

//2

The class VVContactRepository kept an associated database named aDB_ in the VVContactRepository constructor. On this line, it uses the database to create an instance of RWDBSelector, which is an object used to select data from a database.

//3

An associated RWDBTable, called table_, was also kept by the constructor. Here the selector is asked to select all the data from table_. In SQL terms, this is like SELECT * from the table.

//4

We would like our mailing labels sorted into alphabetical order, so the selector is instructed to orderBy the column in which the customer's name is stored. This column was stored by the constructor in the nameColumn_ variable. This is analogous to the SQL ORDER BY NAME.

//5

Here the table is used to create an instance of RWDBReader. A reader can be thought of as both an iterator and a stream. It iterates through the rows of the table that created it, and can stream out the values of the columns in each row. If we had not been concerned with ordering the results, //2-//5 could have been replaced with the single statement RWDBReader aReader = table_.reader();.

//6

The table in the database in this tutorial has fields that match the instance variables in the class VVContact. This routine is about to start reading data from the table, and an instance of VVContact is a made-to-order place to store information from that table. This line creates an instance of VVContact to serve as a temporary variable for a single row from the table.

//7

A reader is like an iterator. It must be advanced to the next row. Invoking the reader with the operator() member function advances the reader to the next row. If there are no more rows, then operator() returns a zero value and the loop terminates.

//8

A reader is also like a stream. Here an entire row of data flows from the reader into the instance of VVContact. An explanation of this can be found in Section 17.5.4.

//9

Since the instance of VVContact is now complete, its own member functions can be called. The mailingLabel() member function simply outputs the instance variables for this customer in a form acceptable to the U.S. Postal Service.

//10

The mailing labels need to be delimited in some manner, so we add two blank lines.

//11

This routine needs to return an instance of VVContactRepository, so it returns itself. At this point, destructors for the VVContact instance, RWDBSelector instance, and the RWDBReader instance are called. There are no pending rows from the RWDBReader. If there were, they would have been quietly and automatically discarded here.

17.5.4 operator>>() for VVContact

In //8 of the previous code section, a VVContact instance was initialized by shifting out from an RWDBReader instance. This is an important technique and warrants closer examination. Line //8 above actually invokes a global overloading of the operator>>() function involving an RWDBReader on the left and a VVCustomer on the right. The code for this function, found in conrep.cpp, follows:



Previous fileTop of DocumentContentsNo linkNext file

Copyright © Rogue Wave Software, Inc. All Rights Reserved.

The Rogue Wave name and logo, and SourcePro, are registered trademarks of Rogue Wave Software. All other trademarks are the property of their respective owners.
Provide feedback to Rogue Wave about its documentation.