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

7.4 The Value Layer

The value layer consists of the data and variables you pass by value when writing to the value-based classes of the DB Interface Module. Performance features such as inserter and reader caching make these classes both efficient and easy to use. (See Chapter 9, "Caching.") Applications using these classes can move data back and forth safely and efficiently between the value layer and the variables in the application. Typically, this is done with the insertion << and extraction >> operators of the various classes. For example, if you want to insert some integers into a table by value, you would place them into an RWDBInserter:

To read a string and a float from a table, you would extract them from an RWDBReader:

Code in the value layer of the DB Interface Module data model is responsible for converting the literal 1234 and the int i into RWDBTBuffer<T> instances for internal storage, and for converting other RWDBTBuffer<T> instances into application variables. Although this example is simple, it illustrates several features provided by the value layer:

Use of general purpose data types. The example code above uses general purpose data types, ints, floats, and RWCStrings. The database classes RWDBInserter and RWDBReader are used exclusively for data transport; no special types or structures are needed to store the data itself.

Type safety. Database programming is notorious for its lack of type safety. This is mainly because it is impossible to know at compile time which data types belong in which database objects at runtime. By using the DB Interface Module, you can attain runtime type safety; the data model ensures that only type-safe conversions are attempted.

Memory management. Notice that there is no explicit binding of program variables in the example above. In fact, there are no pointers at all. This eliminates a very common cause of error. Explicit variable binding is available when extra control over memory management is desired; however, it should only be used when necessary.

Robustness. There isn't any error checking in the example above. For now, simply note that an application can freely continue in the face of errors, without worrying about crashing because of a lack of error checking. (See Chapter 6, "The Error Model.")

The structured data types used in the value layer include:

Classes RWBasicUString, RWWString, and RWDBMBString are briefly described in Chapter 13, "Internationalization." The other classes are briefly described in the following sections.

7.4.1 RWCString

Class RWCString can be found in the Essential Tools Module. It is an industry standard for string manipulation, providing string processing features that are just as efficient as those in C, but far less prone to errors. Its features include memory management, collation, substrings, pattern matching, regular expressions, I/O, tokenizing, and support for multibyte strings.

Class RWCString has member functions to read, compare, store, restore, concatenate, prefix, and append RWCStrings and char*'s. Operators allow access to individual characters, with or without bounds checking.

For a full discussion of the features of this class, please see the Essential Tools Module User's Guide and the SourcePro C++ API Reference Guide.

7.4.2 RWDateTime

Class RWDateTime, also contained in the Essential Tools Module, is the primary class used for dates and time in the DB Interface Module. This class serves as a compact representation for calendar calculations. It shields you from many of the details of programming with time elements, like leap years, and performs conversions to and from conventional calendar formats.

SourcePro DB compatibility is provided to RWDateTime instances that are initialized to either RWDateTime::null or a valid date. For a full discussion of the many features of this class, please see the Essential Tools Module User's Guide and the SourcePro C++ API Reference Guide.


Class RWDateTime should be used for dates and time in SourcePro DB. Class RWDBDateTime is deprecated.

7.4.2.1 Example

The following example shows how RWDateTime performs date calculations. This code prints out the date January 6, 1990, then calculates and prints the date of the previous Sunday, using the global locale:

Program output:


In this example, RWDBDateTime (deprecated), can be substituted for RWDateTime. See Section 7.4.3.

7.4.2.2 Constructors

An RWDateTime may be constructed in many ways. For example, you can:

In the first example, we use the enumerated constructor to construct RWDateTime with current value. If you are constructing an array and must fill in today's date, you must assign the dates explicitly (see the Essential Tools documentation for more details).

There are many other constructors, including those that use RWDate or RWTime in various ways. There are accessors for each component of an RWDateTime (years, months, days, hours, and so on), as well as for its RWDate component and RWTime component. Both RWDate and RWTime provide powerful localization features which may be accessed and changed via the RWDateTime interface. Member operators and functions allow a complete range of arithmetic manipulations on date and time values.

Complete information on the capabilities of RWDate, RWTime, and RWDateTime can be found in the Essential Tools Module User's Guide and the SourcePro C++ API Reference Guide.

7.4.3 RWDBDateTime

Class RWDBDateTime used to be the primary class for representing and manipulating dates and time in the DB Interface Module. It is now deprecated and reimplemented on class RWDateTime of the Essential Tools Module of SourcePro Core.

RWDateTime has the following advantages over RWDBDateTime:

RWDBDateTime is still included in the SourcePro DB API, and can be used interchangeably with RWDateTime. Code written with RWDBDateTime need not be rewritten. However, Rogue Wave recommends developing new applications with class RWDateTime. For information on using RWDateTime in SourcePro DB, please see Section 7.4.2 in this manual, and the entry for RWDateTime in the SourcePro C++ API Reference Guide.

To continue using RWDBDateTime, see the entry on RWDBDateTime in the SourcePro C++ API Reference Guide. If you are a previous user of RWDBDateTime, also see the following sections on changes to the RWDBDateTime API beginning with SourcePro DB 5.2.

7.4.3.1 Conversions between RWDBDateTime and RWDateTime

RWDBDateTime is now completely compatible with RWDateTime. Conversions are provided between the two classes, as in the following example:

It is also possible to convert any RWDateTime instance to an RWDBDateTime instance:

The way that RWDBDateTime stores dates was changed in SourcePro DB 5.2. It now carries the same limits and restrictions as RWDateTime. Please see the entry for class RWDateTime in the Essential Tools Module User's Guide.

7.4.3.2 Persistence

The RWDBDateTime methods saveOn() and restoreFrom() now save and restore the date in a different format than before SourcePro DB 5.2. The new format is more efficient in both time and space. To provide a migration path, the static method persistence() was provided to allow a change in the runtime behavior of the methods saveOn() and restoreFrom().

To read dates saved in the previous format, make the following call:

This sets the persistence model of the class to the legacy format. By default, dates are stored in a new format that is compatible with RWDateTime. To change the persistence model back to the default format, make the following call:

To determine the current persistence model, make the following call:

After this call, the variable persistence can be compared to RWDBDateTime::Default and RWDBDateTime::Legacy.

As mentioned previously, the new persistence model is completely compatible with RWDateTime. For this reason, an instance of RWDBDateTime saved to a file can be read back as RWDateTime and vice versa.

7.4.3.3 64-bit Variables

RWDBDateTime is valid for thousands of years into the future. This means that several methods take 64-bit values as parameters in order to cover the full range of valid values. The methods that now take 64-bit values are: addMilliseconds(), addSeconds(), addMinutes(), and addHours(). Additionally, the method seconds() returns a 64-bit value. For example:

For detailed information on functions that take 64-bit parameters, please see the entry for RWDBDateTime (deprecated) in the SourcePro C++ API Reference Guide.

7.4.3.4 Optional RWZone Parameter

Beginning with SourcePro DB 5.2, several RWDBDateTime (deprecated) methods now have a new optional parameter of type RWZone that allows a zone to be specified. For more information on these methods, please see the entries for RWDBDateTime and RWZone in the SourcePro C++ API Reference Guide.

7.4.3.5 Current Time

Beginning with SourcePro DB 5.2, when an instance of RWDBDateTime is set to the current time using the method now() or through the use of the default constructor, the milliseconds portion is no longer set to zero. The milliseconds portion now reflects the actual time.

7.4.4 RWDBDuration

Class RWDBDuration represents a time span, stored in a double as a number of seconds. All reasonable arithmetic operations involving time spans are supported, including addition and subtraction, multiplication by a constant, incrementation by seconds, minutes, hours, and so forth.

RWDBDuration also supports arithmetic operations involving the imprecise quantities months and years, whose exact number of days vary. The DB Interface Module supports these operations using the following conversions:

Table 11: Time conversions in RWDBDuration

Time Span
const double RWDBDuration::DUR_MILLISECONDS_PER_SEC = ((double)1000.0);
const double RWDBDuration::DUR_SECONDS_PER_MIN = ((double)60.0);
const double RWDBDuration::DUR_SECONDS_PER_HR = ((double)3600.0);
const double RWDBDuration::DUR_SECONDS_PER_DAY = ((double)86400.0);
const double RWDBDuration::DUR_SECONDS_PER_WEEK = ((double)604800.0);
const double RWDBDuration::DUR_SECONDS_PER_RWMTH = ((double)2419200.0);
const double RWDBDuration::DUR_SECONDS_PER_RWYR = ((double)29030400.0);

From the table, we see that adding one month to an RWDBDuration adds four weeks' worth of seconds to the duration, regardless of the number of weeks in any particular month.

As a reminder of this interpretation, the methods for accessing years and months are named asRWMonths() and asRWYears(). Applications can apply specialized arithmetic for durations that span more than one month or year by using the arithmetic operators for doubles.

7.4.5 RWDBBlob

Class RWDBBlob provides memory management services and access to a binary large object (blob) with arbitrary data and length. Class RWDBBlob is derived from RWCollectable, so all features of a collectable are supported, including persistance. Class RWDBBlob does not provide any semantic interpretation of its data; it is designed as a base class that applications can specialize to provide application-specific semantics.

In the following example, we illustrate how a hypothetical structure, struct SOUND, might be transferred between a database and program variables.

The example transfers data back and forth between SOUND, sound, and the RWDBBlobs, aBlob and newBlob.

The loop at //1 uses a reader to iterate through a table holding SOUNDs. The data is transferred to aBlob from the reader on //2. The RWDBBlob member functions length() and data() are used on //3 and //4 to set the related components of sound.

The loop at //5 reads from the input file stream and on //6, we ensure that we read data successfully and break out of the loop if we don't. On //7, we create an RWDBBlob instance newBlob using the data and length in the sound instance. The newBlob does not copy the data from sound, but simply holds a pointer to the data, saving memory. On //8 an RWDBInserter is produced from the soundTable. On //9 the newBlob is shifted into the inserter. On //10 the execute() method is invoked and the new sound is added to the database table.

Class RWDBBlob can be used effectively with the bulk interface. Please see Section 8.2.2, "Bulk Classes and RWDBBlob," for an example.

7.4.6 RWDecimalPortable

Class RWDecimalPortable from the Essential Tools Module represents an arbitrary precision decimal fraction as a character string. This class exists mainly to provide a technique for retrieving exact precision numeric data types, such as monetary values. Some databases have methods for representing numeric values exactly. If the DB Interface Module fetched these values into float or double precision variables, there would be a risk of inaccuracy. Native C++ floating data types represent numbers using base 2; however, many noninteger decimal numbers, such as 0.1 and 19.7, cannot be exactly represented in base 2. For accounting or financial computations, the round-off error inherent in floating point arithmetic is unacceptable.

There are good reasons for using RWDecimalPortable:

The following example demonstrates the difference in accuracy between RWDecimalPortable and the built-in type double. In each case below, we add one cent to a zero-initialized variable one hundred times. We then remove one dollar, which should return the variable to zero. Using RWDecimalPortable, the test succeeds; the account balances. Using double, the value does not return to zero.

7.4.7 RWDBValue

In the DB Interface Module, class RWDBValue is the means of integrating data in the value layer with the pointer layer. RWDBValue automatically converts between compatible C++ and structured types, allowing the value layer to be type safe. An RWDBValue-based accessor and mutator are provided on RWDBTBuffer<T>, giving the Open SQL interface the flexibility needed to support the value layer. RWDBValue also adds null/not null semantics to the primitive types.

In application programs, RWDBValue is especially useful when working with results where the type of data is not known. Programs can read data directly into RWDBValue instances, and then interrogate the instance to find out what kind of data was placed in it. RWDBValue instances can be held in collections and passed without knowing what type of data they are holding. Conversion methods on RWDBValue allow applications to handle unknown data in a robust, predictable manner.

You will find a complete entry for RWDBValue in the SourcePro C++ API Reference Guide, but its main components are listed here:

As mentioned earlier, RWDBValue is used internally to integrate the value and pointer layers of the DB Interface Module. Whenever data arrives from a database, routines in the database layer interrogate the database API for its type, and store the data into RWDBTBuffer<T>, where T is the primitive or structured type of the DB Interface Module best able to hold the data. RWDBTBuffer<T> provides an accessor that automatically converts data elements into RWDBValue instances for the value layer. Whenever the value layer requests data from the pointer layer, RWDBValue's canConvert() routine is consulted to determine whether or not the conversion can be made. If not, an error condition arises. Otherwise, the appropriate as<Type>()routine is invoked to convert to the requested type.

7.4.8 Internationalization Data Types

Data types RWDBMBString, RWWString, and RWBasicUString are used for supporting internationalization in SourcePro DB. They are explained in detail in Chapter 13, "Internationalization."



Previous fileTop of DocumentContentsIndex pageNext 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.
Contact Rogue Wave about documentation or support issues.