Using RWDBMultiRow for Ad Hoc Queries
In
Output Binding and Fetching Using RWDBTBuffer, we created our own
RWDBTBuffers when buffers were needed to hold query results. We could do this since we knew the format of our results in advance. If the format of results is not known, however,
RWDBMultiRow can help create
RWDBTBuffers for results. Let’s see how this is done.
In the example in
Output Binding and Fetching Using RWDBTBuffer, we used
RWDBMultiRow when we made output bindings for our results:
...
anOSql[0] >> idBuffer; // 7
...
The expression
anOSql[0] returns an
RWDBMultiRow reference, and the
RWDBMultiRow operator>> appends an
RWDBTBuffer to itself.
RWDBOSql internally stores an
RWDBMultiRow for each result set, and
operator[] returns a reference to the
RWDBMultiRow for the specified result set. In some cases, the number or type of columns in the result set is unknown until runtime. As we will see below, we can use
RWDBMultiRow to automatically create
RWDBTBuffers for us in these cases.
Class
RWDBOSql provides a method,
schema(), which returns an
RWDBSchema representing the schema of the current result set. Each column in the returned
RWDBSchema details information about the corresponding results column, including its name, datatype, and other information.
RWDBMultiRow provides a constructor that takes an
RWDBSchema, and creates appropriate
RWDBTBuffers. Here’s an example of how we could use
RWDBMultiRow to automatically create output bindings:
RWCString aQuery = getUserSpecifiedQuery(); //1
RWDBOSql anOSql(aQuery, RWDBOSql::Query); //2
anOSql.execute(aConn); //3
RWDBMultiRow outputBindings(anOSql.schema(), 1); //4
anOSql[0] = outputBindings; //5
while(anOSql.fetch(), anOSql.rowsFetched() > 0) { //6
processResults(outputBindings); //7
}
On
//1 and
//2, an
RWDBOSql is created from a user-specified query, and on
//3, the query is executed. Note that the output bindings are not yet specified at this time. As we explained in the example in
Output Binding and Fetching Using RWDBTBuffer, output bindings may be specified before or after
execute() is invoked, as long as they are specified before
fetch() is invoked.
On
//4, we call
anOSql.schema(), which returns an
RWDBSchema representing the schema of the result set. We use this
RWDBSchema to construct a new
RWDBMultiRow, which immediately uses this
RWDBSchema to construct an
RWDBTBuffer for each column. The
RWDBMultiRow instantiates the
RWDBTBuffer templates on the types corresponding to each column’s type, and appends the new
RWDBTBuffers to itself. The
1 corresponds to the number of entries each
RWDBTBuffer will have; each
RWDBTBuffer will have
1 entry.
On
//5, we use the new
RWDBMultiRow as the output bindings for the 0th result set of our
RWDBOSql. Like many classes of the standard interface of the DB Interface Module,
RWDBMultiRow is designed around the Interface/Implementation paradigm, and the state of each
RWDBMultiRow is held in a hidden, reference-counted implementation class. Using the assignment operator causes the
RWDBOSql’s internal
RWDBMultiRow for the 0th result set to refer to the implementation of the
RWDBMultiRow we just constructed. The
RWDBOSql now uses our newly created
RWDBTBuffers, but no performance is lost by creating a copy.
Although creating this
RWDBMultiRow from an
RWDBSchema is a useful technique, please note that it requires extra steps while trying to access the data fetched. These extra steps are described in the next section
Obtaining Data from RWDBMultiRow. All these can impose quite a performance penalty, depending on how frequently they are used.
NOTE: This technique may impede performance.
For this reason, we recommend that you use these features only when it is impossible to know the results of a query and
RWDBTBuffers cannot be created based on the
RWDBSchema returned by the
RWDBOSql::schema()_ call. In other cases, it is preferable to directly instantiate
RWDBTBuffers of the appropriate type and directly bind them to your
RWDBOSql.
Lines
//6 and
//7 perform the standard results-processing loop that we use in
Output Binding and Fetching Using RWDBTBuffer. The
processResults() function processes the results fetched into the given
RWDBMultiRow and its
RWDBTBuffers.