Appserver

emnu

Member
Hi,

I was wondering how to get a batch of records from a stateless appserver session to a client session. Theoretically it's quit simple. On the client side you connect to the appserver, you set your batch size, ex. 50 recs in one batch, on the serverside you create a query, put the 50 first recs in a temp table, and send them to the client side and copy them to the client side temp-table. So far so good, this works. But now, how can i efficiently get the next batch of records on the server side to the client and add them to the client temp-table. When requesting the next batch on a stateless appserver, we have to reopen the query, skipping the 50 first recs with qh:get-next(), when reaching rec. 51, put this one and 49 next into the temp-table and send them to the client side, ... This works, but i want to avoid the 50 skips (get-next), so if i have a unique key, i can shrink the result list with a where clause. ex. customer number is unique, so the first time the dynamic query will be like ...
qh:query-prepare("for each " + cTable + " where " + cTable + "." + cField +
" > " + CurrentCustNum + " no-lock"), where in out example cTable = customer, cField = custnum and the first time a batch is requested CurrentCustNum is 0, the second time CurrentCustNum is 50. This is OK for unique values and in this way you can avoid the "get-next" skip. But this doesn't if you want to get the batches ordered by a none unique value, like name (ex. there can be 100 SMITHS in the customer table). If you take the example above then you get ... customer.name > "SMITH". So if in our example. customer SMITH was the 50th record, the next 99 SMITH'S won't come in the result list.
I thought i found the solution by sending the rowid of the last record in the client-side temp-table to the server, and executing next statement;
bhTable:FIND-BY-ROWID(rLastRowid). /* find next record in database */
But this doesn't set the cursor of the linked query to this record, so a find next of query gives just the first record (i opened the query, exec. the find by rowid, then the get-next on the query). And there is no FIND-NEXT OR FIND-PREV for Dynamic buffers.
Any one any clue ?

Thanx for any Response
Emnu.
 
Hi,

You can have a calculated field function in your query. and that can act like a rowcount. I am not sure how much it would hit performance. But could be a soln.

HTH
V

emnu said:
Hi,

I was wondering how to get a batch of records from a stateless appserver session to a client session. Theoretically it's quit simple. On the client side you connect to the appserver, you set your batch size, ex. 50 recs in one batch, on the serverside you create a query, put the 50 first recs in a temp table, and send them to the client side and copy them to the client side temp-table. So far so good, this works. But now, how can i efficiently get the next batch of records on the server side to the client and add them to the client temp-table. When requesting the next batch on a stateless appserver, we have to reopen the query, skipping the 50 first recs with qh:get-next(), when reaching rec. 51, put this one and 49 next into the temp-table and send them to the client side, ... This works, but i want to avoid the 50 skips (get-next), so if i have a unique key, i can shrink the result list with a where clause. ex. customer number is unique, so the first time the dynamic query will be like ...
qh:query-prepare("for each " + cTable + " where " + cTable + "." + cField +
" > " + CurrentCustNum + " no-lock"), where in out example cTable = customer, cField = custnum and the first time a batch is requested CurrentCustNum is 0, the second time CurrentCustNum is 50. This is OK for unique values and in this way you can avoid the "get-next" skip. But this doesn't if you want to get the batches ordered by a none unique value, like name (ex. there can be 100 SMITHS in the customer table). If you take the example above then you get ... customer.name > "SMITH". So if in our example. customer SMITH was the 50th record, the next 99 SMITH'S won't come in the result list.
I thought i found the solution by sending the rowid of the last record in the client-side temp-table to the server, and executing next statement;
bhTable:FIND-BY-ROWID(rLastRowid). /* find next record in database */
But this doesn't set the cursor of the linked query to this record, so a find next of query gives just the first record (i opened the query, exec. the find by rowid, then the get-next on the query). And there is no FIND-NEXT OR FIND-PREV for Dynamic buffers.
Any one any clue ?

Thanx for any Response
Emnu.
 
Hi,

You can use the rowid (passing the last rowid found back to the AppServer) and then use the REPOSITION-TO-ROWID method on the query and get the next 50 records. This should work.

However... there is (of course) a pittfall. If the 50th record (so the last one you have retrieved) is deleted between the two "get" operations, your AppServer process will not be able to find the record and thus not be able to get the next 50 records (because it has no idea where to go).

Another solution is to "remember" how many records you have retrieved on your client and to send this number to the AppServer process. Instead of doing a GET-NEXT(NO-LOCK) 50 times you can then do a the REPOSITION-FORWARD(<number of records>) method and pick up the query from there.

Of course the last method also has a pittfall. Say the user has sofar retrieved 150 records from the server and the next batch of 50 has to be retrieved, but in the mean time someone has deleted say three records from the first 150. Your program will do a REPOSITION-FORWARD of 150. This means that the next batch will not be correct because you will not get the records you are supposed to (you will miss the first 3 that you should get). It will be hard to figure out that this has occurred and the user will see incorrect (incomplete) data.

The first solution has (my personal opinion) preference, since you can - because the record you need to get does not exist anymore - catch this situation in the AppServer program and, for instance, alert the user and/or reopen the whole query etc.

Note that a similar situations (both problems) also occur in reverse, when someone adds or modifies records somewhere in the records that are already on the client. These will not be present (or correct) on your client until the user reopens the whole query (from the beginning).

HTH
 
Back
Top