Output Binding and Fetching Using RWDBTBuffer
Now that you know how to encapsulate buffers with
RWDBTBuffer, let’s see how to associate
RWDBTBuffers with an
RWDBOSql so that the results produced by executing an SQL statement are placed into the buffer. This procedure is also known as
output binding and
fetching. To perform output binding and fetching, we use
operator[] and
operator>>, which allow us to specify a particular result set and result column on which to bind a buffer. Let’s look at an example:
RWDBOSql osql("SELECT NAME, HIRE_YEAR FROM EMPLOYEES", //1
RWDBOSql::Query);
RWDBTBuffer<RWCString> nameBuffer(10); //2
RWDBTBuffer<unsigned> hireBuffer(10); //3
// Bind nameBuffer and hireBuffer to the first two columns
// in the 0th result set.
osql[0] >> nameBuffer >> hireBuffer; //4
On
//1, we create a statement that returns a result set with two columns: one column of the string type of our database, and one column of the unsigned integral type of our database. On
//2 and
//3, we create 10 element
RWDBTBuffers, which we bind to the result set, one
RWDBTBuffer per column. On
//4, we bind
nameBuffer and
hireBuffer to the 0th result set, as the comment indicates.
When the statement has executed, we can fetch the results using the fetch() method. Calling fetch() causes as much data as possible, for the current result set, to be fetched into the output buffers.
If our query produces fewer rows than the number of elements in the
RWDBTBuffers, then the buffers are not entirely filled by the
fetch() call.
If our query produces more rows than the
RWDBTBuffers can contain, however,
fetch() fills the buffers to capacity.
The capacity of the buffers is determined as the smallest number of elements of all the
RWDBTBuffer instances bound to the result set being fetched. In the previous example, the capacity is 10 rows, as both buffers can contain 10 elements. If rows still remain for us to fetch, subsequent calls to
fetch() would result in more rows being fetched into the buffers, and overwriting the data present there.
Now let’s look at an example that fetches data:
RWDBDatabase aDB = RWDBManager::database(...); // 1
RWDBConnection aConn = aDb.database();
…
RWDBOSql anOSql("SELECT ID FROM INVENTORY", RWDBOSql::Query); // 2
anOSql.execute(aConn); // 3
if( anOSql.isValid() && anOSql.hasResult() ) { // 4
unsigned long idArray[100]; // 5
RWDBTBuffer<unsigned long> idBuffer(idArray, 100); // 6
anOSql[0] >> idBuffer; // 7
while(anOSql.fetch(), anOSql.rowsFetched() > 0) { // 8
printInventoryIDs(idArray, anOSql.rowsFetched()); // 9
}
}
On
//1, we create an
RWDBDatabase in order to connect to our database. On
//2, we create an
RWDBOSql that encapsulates a query that should return a single-column result set. For this example, we assume
ID is an unsigned integer column. On
//3, we execute the query using the
execute() method. Note that no output buffers are bound at this time; you can choose to bind your output
RWDBTBuffers either before or after execution. Of course, you must bind the output buffers before calling
fetch(), or there is no place into which to fetch the data!
On //4, we call isValid() to check that no error occurred. We also call RWDBOSql::hasResult() to check that results were actually produced. The method hasResult() returns true if there are available result sets that you haven’t yet processed.
On
//5, we create an array of 100
unsigned longs on the stack. On
//6, we encapsulate the array in an
RWDBTBuffer,
idBuffer, so that the array can be used as an output binding. On
//7, we bind
idBuffer to the first column in the 0th result set, the
ID column specified in our
SELECT.
Line //8 begins the results processing loop. In the while loop, we call fetch() to fetch data, and exit the loop if rowsFetched() returns 0. As long as rowsFetched() remains greater than 0, indicating that there is result data, the function printInventoryIDs() prints the result data that is fetched.
On each call to
fetch(),
RWDBOSql fetches as many rows as possible from the result set. In this case, the output binding holds 100 entries, so at most 100 rows are fetched. If fewer rows are available in the result set, all the rows are fetched. After each call to
fetch(), the function
rowsFetched() returns the number of rows fetched, which indicates what part of the array contains fetched data. When all the result data is exhausted, calling
fetch() returns no rows and
rowsFetched() returns 0, which tells us to exit the loop.