Retrieving Data
The first step in data retrieval is expressing the desired query. To process the rows, a rowset structure client-side needs to be instantiated. The most common class client-side for handling the rowset has a confusing name: RDbView. It's confusing because:
- This is a rowset, not the view common in some SQL implementations--those views are stored with the database. This is a rowset--RDbView's (abstract) ancestor in the class hierarchy is the RDbRowset.
- Unlike some rowset implementations, there is actually only one row at a time stored in this client-side structure.
After the query is sent to the DBMS server, the next step is to call RDbRowset::Prepare(). Prepare() basically allocates structures server-side for the evaluated rows. The TDbWindow argument to Prepare() lets you make suggestions as to the size of the server-size structure. Finally, the RDbRowset::Evaluate() method is called. This is an incremental evaluation, which causes the server-side structures prepared previously to be filled. The EvaluateAll() method should be used with caution--SQL rows retrieved can be quite large--unless you know you're only going to get a small rowset as a result (say one row, since you have a unique index), it's more prudent to use Evaluate(), and evaluate server-side in incremental steps.
SymbianOS avoids a lot of the problems caused by methods that block through ubiquitous asynchronous non-blocking methods, and the API into the Symbian DBMS is no exception. Most calls have asynchronous versions, and are designed to allow processing to occur in incremental steps. Open select statements in any SQL environment are notorious for causing problems due to the potential for large rowsets--this can cause incorrectly--designed database clients to hang or cause the unnecessary allocation of large amounts of memory, something that is anathema in memory-constrained environments. The SymbianOS developer has the option for specifying the server-side buffer space usage. In the following example, the developer is requesting the server allocate memory for three rows before, and three rows after, the current row. Listing Three is code that performs retrieval.
... //here is my select statement _LIT(KRetrieveData,"select * from authors"); //Prepare server-side buffer of 3 rows before and after User::LeaveIfError(myRowset.Prepare(myDatabase,TDbQuery(KRetrieveData),TDbWi ndow(3,3))); // I need to cleanup any RClass -- this includes myRowset // so I'll put myRowset on the cleanup stack CleanupClosePushL(myRowset); // My simple program only needs to evaluate once User::LeaveIfError(myRowset.EvaluateAll()); //subsequent retrieval while ( myRowset.NextL() ) { // get the current row myRowset.GetL(); author_id = myRowset.ColUint(1); last_name = myRowset.ColDes(2); first_name = myRowset.ColDes(3); // do something with the results. // in my simple program, I just print each row to the console console->Printf(_L("%d "), author_id); console->Printf(last_name); console->Printf(_L(" ")); console->Printf(first_name); console->Printf(_L("\n")); }
Note that this buffer is server-side. Remember that the client only retrieves one row at a time.