Rogue Wave banner
Previous fileTop of DocumentContentsIndexNext file

21.5 The Program

This section examines the t7 program, which writes a number of invoices to a file called t7out.txt. Each invoice represents a customer renting one or more videos from the library.

21.5.1 The Main Routine

The following is the main routine for the tutorial. The line numbers correspond to the comments that follow the code.

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

//1Include the declarations for the standard iostreams.
//2Include the declarations for the DBTools.h++ classes used in this program.
//3Include the declarations for the utility routines commonly used by all the tutorials.
//4Include the declaration of the VVInvoice class used only by this tutorial.
//5-9These lines are for initialization and multiplatform portability. They are common to all the tutorials and are explained in Section 15.5.1.
//10Here an actual connection to a database server is established. The variable aDB serves as a handle to the database defined by arguments to the RWDBManager::database() function.
//11-12These are definitions for the customer ID and video ID. These will contain the actual data read in from the stream. The values will be passed to the VVInvoice constructor and the addRental()member function.
//13This is the start of the main processing loop, which reads the data from the stream and passes the data to the two processing routines. The condition of the stream is tested to determine if all the data was processed.
//14The first value in the stream is read into a customer ID.
//15This line tests the stream for end-of-file, which is only read when a customer ID is read, so the extra statement is needed.
//17This is the start of the video rental processing loop. Each line of the stream contains a customer ID followed by a series of video IDs. The series of videos is ended by a video ID equal to zero. If a valid video ID is read, a rental transaction is added to the invoice.
//18The next value in the stream is read into a video ID.
//19The video ID is checked to determine if the end of the video list was read. If the video ID is valid, a rental transaction is added to the invoice.
//20A rental is added to the invoice using the video ID obtained above via a call to the VVInvoice addRental() function. Further explanation of addRental() is in Section 21.5.2.
//21End of the video rental processing loop, which checks the video ID for a zero value that marks the end of the series.
//22After all the rentals for a customer have been added, the invoice is printed. An invoice retains all knowledge of customer ID, invoice ID, and rentals, so no parameters are needed for the print() member function. Because most of the code in print() deals with output formatting, and the database lookup routines were featured in previous tutorials, there is no line-by-line explanation in this tutorial.
//23Normal program exit.
//24Destructors for all the objects are called here. The database closes automatically along with the output streams.

21.5.2 VVInvoice::addRental

The invocation of the addRental() function inserts new data into the rentals table and updates the videos table. The source code of this member function can be found in the source file invoice.cpp.

//1This line defines the addRental() member function. It accepts one parameter, a video ID. The invoice ID and customer ID were saved as local data members of the VVInvoice when it was constructed. A database was also retained to make access to the database simpler for all member functions.
//2Because two tables are updated by this routine, a single connection is used to control the table manipulations as a single transaction. This is only possible through a common connection.
//3The first step in grouping several data manipulations into a single transaction is to turn off the default behavior of the DBTools.h++ library. By calling beginTransaction(), the connection is reset to not apply data manipulations until commitTransaction() is invoked. See //17.
//4-7The RWDBDateTime instances created on these lines are used to initialize a new VVRentalTransaction instance on line 9.
//8An instance of the class VVRentalTransactionRepository is created on this line to represent the rentals table. The first argument, aDB_, identifies the database where the instance's data resides, which is the same database where invoice's data resides. The second argument identifies the specific table name that holds the rental transaction information.
//9A new VVRentalTransaction instance is created on this line to represent a rental of the video identified by customer ID_, aVideoID and aInvoiceID_. Rental dates and times are also provided.
//10The new rental is inserted into the rental table.
//11Now the video table must be updated to reflect the stock going down by one video. On this line, an instance of the class VVVideoRepository is created to represent the videos table. The first argument, aDB_, identifies the database where the instance's data resides, which is the same database where the invoice's data resides. The second argument identifies the specific table name that holds the video information.
//12An incomplete VVVideo instance is created to pass to the find() member function of VVVideoRepository. Only the video ID is provided.
//13The find() member function of VVVideoRepository takes an instance of VVVideo that has only partial information and finds a matching record in the videos table. It then returns an instance of VVVideo containing the complete record. On this line, a VVVideo instance containing only a videoID is given to the find() function. Once the routine returns, the instance of VVVideo contains complete information about the video with the correct videoID. The find() member function of VVVideoRepository is explained in Section 21.5.3.
//14-15The following section of code updates the quantity on hand for the video being rented. It does this by using the video found in the previous line. It decrements the numOnHand field by one.
//16On this line, an update of the video record takes place. The first parameter is used only for a key to the video that is to be updated. The second parameter is the new value for the video record. Since these are the same, the update is to the same video. This routine is explained in more detail below. The third parameter is the common connection. This groups this update with the previous addition of a video rental.
//17Once both tables have been updated, this line commits all data manipulations as a single transaction. In this case, the addition of a new video rental on //10 and the update of the number of videos on hand on //16 are committed together.

21.5.3 VVVideoRepository::find

The find() member function of the class VVVideoRepository, takes a VVVideo instance as an argument, with only some of its fields filled in. It uses this partial VVVideo as a search criterion. The function returns the first video it finds that matches the field passed in. The source code of this member function, from the file vidrep.cpp, follows.

//1This is the definition of the find() member function for the VVVideoRepository class. It accepts a single parameter, an instance of VVVideo. This VVVideo instance is designed as a criterion for selecting a specific video. The fields within the VVVideo are used to select the first video that matches the fields, returning the completed VVVideo.
//2Throughout the following section of code, a predicate is created based on the fields that have values. Building the predicate dictates surveying the fields of this VVVideo, and for each nonzero or non-null value found, adding an appropriate clause to the predicate. Clauses are added to the predicate using a logical and operation &&. Since it is not known which field will be the first to have a value, the search criterion is first set to a simple expression of TRUE. The && operator can be applied to additional predicates as they are found. This line of code creates a predicate in the form of an RWDBCriterion with TRUE as its value.
//3The RWCString created on this line is a copy of the VVVideo instance's title field.
//4-5If the title field is not null, then a value exists in the field that should be used as a search criterion. The existing search criterion is combined with an expression using the && operator that translates to the equivalent of
... AND video.title LIKE 'sometitle'.
//6-7If the ID field has a nonzero value, it should be added to the search criterion. (Zero is an invalid value for an ID.) The existing search criterion is combined with an expression using the && operator that translates to the equivalent of ... AND video.ID = 69, where 69 is an arbitrarily chosen value that represents the value in aVideo.ID().
//8-18These lines continue in the same vein, adding predicates to the search criterion as the routine finds nonempty fields.
//19Here, a selector is created by the database object. The search criterion is passed to the constructor where it is used in the WHERE clause of the SELECT statement.
//20Shifting a table instance into an RWDBSelector instance selects all columns from that table.
//21Creating a reader here submits the query to the server.
//22Instantiate a VVVideo instance to hold the results of the query.
//23Advance the reader to the first row of the result set.
//24Read the row into the instance of VVVideo.
//25Return the VVVideo. If the query resulted in multiple matches, the additional rows are discarded when the RWDBReader is destroyed.

21.5.4 VVVideoRepository::update

The update() member function of VVVideoRepository accepts two parameters, both of which are instances of VVVideo. The first instance identifies the record to be changed, while the second instance is used as new information.

//1This is the definition of the update() member function for the VVVideoRepository class. It accepts two parameters, which are both instances of VVVideo. The first represents the original video to update, the second represents the new values. Only the ID field of the original record is used to identify the record to be changed.
//2An RWDBUpdater instance associated with the videos table is created here.
//3A predicate is created here that identifies the row in the videos table to be updated. The predicate takes the form of an RWDBCriterion that is created by applying the operator== to the RWDBColumn instance IDColumn_. Assuming that the original ID was 34, this predicate will be the equivalent of videos.ID = 34.
//4Each of the fields in the new VVVideo instance are embedded in RWDBAssignment instances by calling the assign() member function for each of the columns in the table. These assignment expressions are then shifted into the updater.
//5The execute() member function of RWDBUpdater submits the SQL statements to the server.

Previous fileTop of DocumentContentsIndexNext file

©Copyright 2000, Rogue Wave Software, Inc.
Contact Rogue Wave about documentation or support issues.