project BLF > class BQueryCache > method RunQuery
Description
This method implements the standard interface of API queries for API query procedures.
This method will be called from the generated code for query procedures and not directly from the client.
Parameters
icClassName | input | character | |
icMethodName | input | character | |
icRange | input | character | |
icRowid | input | character | |
iiRowNum | input | integer | |
iiNumber | input | integer | |
icSortColumns | input | character | |
ilCountOnly | input | logical | |
ilForwardRead | input | logical | |
iiMaximumBrowseRecordsToCount | input | integer | |
tFilter | input | temp-table | |
oiCount | output | integer | |
olEndOfQuery | output | logical | |
ihResultSetBuffer | input | handle | |
oiReturnStatus | output | integer | Return status of the method. |
Internal usage
unused
program code (program1/bquerycache.p)
olEndOfQuery = yes.
if icRowid = ? then icRowid = "".
if iiRowNum = ? then iiRowNum = 0.
if iiNumber = ? then iiNumber = 0.
if icRowid = ""
and iiNumber = 0
then do:
/* ================================================================= */
/* when requested to return a full dataset, do not create a cache. */
/* Also do not look if any cache exists. */
/* ================================================================= */
<M-65 run BusinessClassActions
(input icClassName (icClassShortname),
input 'START+OPEN' (icAction),
input no (ilSubtransaction),
input-output viQueryClassOC (biClassOpenCount),
input-output vhQueryClass (bhClassInstanceHandle),
input-output viQueryClassID (biClassInstanceId),
input '' (icDraftReference),
input '' (icUserDefinedContext),
output viFcReturnSuper (oiReturnStatus)) in BQueryCache>
if viFcReturnSuper <> 0
then oiReturnStatus = viFcReturnSuper.
if viFcReturnSuper < 0
then return.
run value(icMethodName) in vhQueryClass
(input dataset tFilter,
output dataset-handle vhQueryDataset by-reference,
output viFcReturnSuper).
if viFcReturnSuper <> 0
then oiReturnStatus = viFcReturnSuper.
if viFcReturnSuper < 0
then do:
<M-35 run BusinessClassActions
(input icClassName (icClassShortname),
input 'CLOSE+STOP' (icAction),
input no (ilSubtransaction),
input-output viQueryClassOC (biClassOpenCount),
input-output vhQueryClass (bhClassInstanceHandle),
input-output viQueryClassID (biClassInstanceId),
input '' (icDraftReference),
input '' (icUserDefinedContext),
output viFcReturnSuper (oiReturnStatus)) in BQueryCache>
return.
end.
/* ================================================================= */
/* Count records in the resultset, or copy requested data */
/* into the output resultset (ihResultSetBuffer). */
/* ================================================================= */
vhQueryTableBuffer = vhQueryDataset:get-top-buffer(1).
create query vhQuery in widget-pool "non-persistent".
vhQuery:forward-only = yes.
vhQuery:set-buffers(vhQueryTableBuffer).
/* ================================================================= */
/* Apply sorting. */
/* ================================================================= */
if ilCountOnly = no
and num-entries (icSortColumns,"|") = 2
then do viSortNum = 1 to vhQueryTableBuffer:num-fields:
vhSortField = vhQueryTableBuffer:buffer-field(viSortNum).
if substring(vhSortField:name,3,-1,"CHARACTER") = entry(1,icSortColumns,"|")
then do:
vhQuery:query-prepare ("for each " + vhQueryTableBuffer:name +
" by " + vhSortField:name +
(if entry(2,icSortColumns,"|") = "D" then " descending by ti_Sequence descending" else " by ti_Sequence")).
vhQuery:query-open().
vhQuery:get-first().
do while not vhQuery:query-off-end:
viSortCount = viSortCount + 1.
vhQueryTableBuffer::ti_Sequence = viSortCount.
vhQuery:get-next().
end.
vhQuery:query-close().
leave.
end.
end.
vhQuery:query-prepare ("for each " + vhQueryTableBuffer:name + " by " + vhQueryTableBuffer:name + ".ti_Sequence").
vhQuery:query-open().
do while true:
vhQuery:get-next().
if vhQuery:query-off-end then leave.
if ilCountOnly
then oiCount = oiCount + 1.
else do:
ihResultSetBuffer:buffer-create().
ihResultSetBuffer:raw-transfer(false,vhQueryTableBuffer).
ihResultSetBuffer:buffer-release().
end.
end.
vhQuery:query-close().
delete object vhQuery.
<M-73 run BusinessClassActions
(input icClassName (icClassShortname),
input 'CLOSE+STOP' (icAction),
input no (ilSubtransaction),
input-output viQueryClassOC (biClassOpenCount),
input-output vhQueryClass (bhClassInstanceHandle),
input-output viQueryClassID (biClassInstanceId),
input '' (icDraftReference),
input '' (icUserDefinedContext),
output viFcReturnSuper (oiReturnStatus)) in BQueryCache>
end.
else do:
<M-79 run StartPersistence
(output vhPL (ohPersistence),
output viFcReturnSuper (oiReturnStatus)) in BQueryCache>
if viFcReturnSuper <> 0
then oiReturnStatus = viFcReturnSuper.
if viFcReturnSuper < 0
then return.
/* ================================================================= */
/* Calculate a unique key to identify the current search. */
/* ================================================================= */
vpSearchKeyData = icClassName + "." + icMethodName + "." + string(viSessionID).
vaSearchKey = md5-digest(vpSearchKeyData).
vcSearchKey = base64-encode(vaSearchKey).
vcSearchQuery = "for each QueryCache where QueryCache.SearchKey = '" + vcSearchKey + "'".
if ilCountOnly
then LoopForCount: do while true:
pause 3 no-message.
vhFcComponent = vhPL.
<M-97 run ReadDirect
(input 'QueryCache' (icTableName),
input vcSearchQuery (icPrepare),
input 'RecordCount' (icFieldList),
output vcrc (ocValueList),
input {&TARGETPROCEDURE} (ihClass),
output viFcReturnSuper (oiReturnStatus)) in persistence>
viTo = integer(vcrc) no-error.
if viFcReturnSuper >= 0
and viTo >= 0
then do:
oiCount = viTo.
leave LoopForCount.
end.
else do:
/* ================================================================= */
/* When no resultset found, another process is still creating it. */
/* ================================================================= */
if viCountLoop > 20
then leave LoopForCount. /* waited more than enough, just return a zero count */
/* try again */
viCountLoop = viCountLoop + 1.
next LoopForCount.
end.
end.
else do:
if icRowid = ""
and ilForwardRead = yes
then do:
/* any existing cache will be overridden */
vlGetData = yes.
vhFcComponent = vhPL.
<M-64 run WriteDirect
(input 'QueryCache' (icTableName),
input vcSearchQuery (icPrepare),
input 'RecordCount' (icFieldList),
input 'i' (icFieldListDataTypes),
input '-1' (icAbsolute),
input '' (icIncremental),
input {&TARGETPROCEDURE} (ihClass),
input vcUserLogin (icUserLogin),
output viFcReturnSuper (oiReturnStatus)) in persistence>
/* ignore errors */
end.
/* ================================================================= */
/* Load the description of the query resultset into memory. */
/* Not the resultset data ! */
/* ================================================================= */
vcSearchQuery = "for each QueryCache where QueryCache.SearchKey = '" + vcSearchKey + "'".
<M-22 run DataLoad
(input '' (icRowids),
input '' (icPkeys),
input '' (icObjectIds),
input vcSearchQuery (icFreeform),
input no (ilKeepPrevious),
output viFcReturnSuper (oiReturnStatus)) in BQueryCache>
if viFcReturnSuper = -4
then do:
/* ================================================================= */
/* When no resultset found, create it. */
/* ================================================================= */
<M-23 run DataNew (output viFcReturnSuper (oiReturnStatus)) in BQueryCache>
if viFcReturnSuper <> 0
then oiReturnStatus = viFcReturnSuper.
if viFcReturnSuper < 0
then return.
vlGetData = yes.
vhFcComponent = vhPL.
assign tQueryCache.SearchKey = vcSearchKey
tQueryCache.Instance_ID = <M-45 GetNextValue (input 'InstanceNumber' (icSequence)) in persistence>.
end.
else do:
if viFcReturnSuper <> 0
then oiReturnStatus = viFcReturnSuper.
if viFcReturnSuper < 0
then return.
find first tQueryCache.
if vlGetData
then do:
assign tQueryCache.RecordCount = 0
tQueryCache.tc_Status = "C".
vhFcComponent = vhPL.
<M-75 run DeleteInstance
(input tQueryCache.Instance_ID (iiInstanceID),
input {&TARGETPROCEDURE} (ihClass),
input 'BQueryCache' (icClassName),
output viFcReturnSuper (oiReturnStatus)) in persistence>
if viFcReturnSuper <> 0
then oiReturnStatus = viFcReturnSuper.
if viFcReturnSuper < 0
then return.
end.
end.
if vlGetData
then do:
<M-82 run BusinessClassActions
(input icClassName (icClassShortname),
input 'START+OPEN' (icAction),
input no (ilSubtransaction),
input-output viQueryClassOC (biClassOpenCount),
input-output vhQueryClass (bhClassInstanceHandle),
input-output viQueryClassID (biClassInstanceId),
input '' (icDraftReference),
input '' (icUserDefinedContext),
output viFcReturnSuper (oiReturnStatus)) in BQueryCache>
if viFcReturnSuper <> 0
then oiReturnStatus = viFcReturnSuper.
if viFcReturnSuper < 0
then return.
run value(icMethodName) in vhQueryClass
(input dataset tFilter,
output dataset-handle vhQueryDataset by-reference,
output viFcReturnSuper).
if viFcReturnSuper <> 0
then oiReturnStatus = viFcReturnSuper.
if viFcReturnSuper < 0
then do:
<M-53 run BusinessClassActions
(input icClassName (icClassShortname),
input 'CLOSE+STOP' (icAction),
input no (ilSubtransaction),
input-output viQueryClassOC (biClassOpenCount),
input-output vhQueryClass (bhClassInstanceHandle),
input-output viQueryClassID (biClassInstanceId),
input '' (icDraftReference),
input '' (icUserDefinedContext),
output viCountLoop (oiReturnStatus)) in BQueryCache>
return.
end.
/* ================================================================= */
/* Count records in the resultset, and copy requested data */
/* into the output resultset (ihResultSetBuffer). */
/* ================================================================= */
vhQueryTableBuffer = vhQueryDataset:get-top-buffer(1).
create query vhQuery in widget-pool "non-persistent".
vhQuery:set-buffers(vhQueryTableBuffer).
/* ================================================================= */
/* Apply sorting. */
/* ================================================================= */
if num-entries (icSortColumns,"|") = 2
then do viSortNum = 1 to vhQueryTableBuffer:num-fields:
vhSortField = vhQueryTableBuffer:buffer-field(viSortNum).
if substring(vhSortField:name,3,-1,"CHARACTER") = entry(1,icSortColumns,"|")
then do:
vhQuery:query-prepare ("for each " + vhQueryTableBuffer:name +
" by " + vhSortField:name +
(if entry(2,icSortColumns,"|") = "D" then " descending by ti_Sequence descending" else " by ti_Sequence")).
vhQuery:query-open().
vhQuery:get-first().
do while not vhQuery:query-off-end:
viSortCount = viSortCount + 1.
vhQueryTableBuffer::ti_Sequence = viSortCount.
vhQuery:get-next().
end.
vhQuery:query-close().
leave.
end.
end.
if iiRowNum = 0
and icRowid <> ""
then do:
vhQuery:query-prepare ("for each " + vhQueryTableBuffer:name
+ " where " + vhQueryTableBuffer:name + ".tc_Rowid = '" + icRowid + "'").
vhQuery:query-open().
vhQuery:get-first().
if not vhQuery:query-off-end
then iiRowNum = vhQueryTableBuffer::ti_Sequence.
vhQuery:query-close().
end.
if iiRowNum = 0
and icRowid = ""
and ilForwardRead = no
then do:
vhQuery:query-prepare ("for each " + vhQueryTableBuffer:name
+ " by " + vhQueryTableBuffer:name + ".ti_Sequence descending").
vhQuery:query-open().
vhQuery:get-first().
if not vhQuery:query-off-end
then iiRowNum = vhQueryTableBuffer::ti_Sequence + 1.
vhQuery:query-close().
end.
if ilForwardRead
then assign viFrom = iiRowNum
vito = (if iiNumber = 0 then 999999 else iiRowNum + iiNumber + 1).
else assign viFrom = (if iiNumber = 0 then 0 else iiRowNum - iiNumber - 1)
vito = iiRowNum.
vhQuery:query-prepare ("for each " + vhQueryTableBuffer:name + " by " + vhQueryTableBuffer:name + ".ti_Sequence").
vhQuery:query-open().
do while true:
vhQuery:get-next().
if vhQuery:query-off-end then leave.
tQueryCache.RecordCount = tQueryCache.RecordCount + 1.
if vhQueryTableBuffer::ti_Sequence > viFrom
and vhQueryTableBuffer::ti_Sequence < viTo
then do:
ihResultSetBuffer:buffer-create().
ihResultSetBuffer:raw-transfer(false,vhQueryTableBuffer).
ihResultSetBuffer:buffer-release().
end.
end.
vhQuery:query-close().
delete object vhQuery.
if (ilForwardRead = yes and viTo <= tQueryCache.RecordCount)
or (ilForwardRead = no and viFrom > 0)
then olEndOfQuery = no.
/* ================================================================= */
/* Save the resultset. */
/* ================================================================= */
vhFcComponent = vhPL.
<M-48 run SaveInstance
(input {&TARGETPROCEDURE} (ihClass),
input tQueryCache.Instance_ID (iiInstanceID),
input vhQueryDataset (ihInstanceData),
input 'BQueryCache' (icClassName),
output viFcReturnSuper (oiReturnStatus)) in persistence>
/* data does not need validation or additional updates */
vlFcDataValidated = true.
<M-55 run DataSave (output viFcReturnSuper (oiReturnStatus)) in BQueryCache>
<M-6 run BusinessClassActions
(input icClassName (icClassShortname),
input 'CLOSE+STOP' (icAction),
input no (ilSubtransaction),
input-output viQueryClassOC (biClassOpenCount),
input-output vhQueryClass (bhClassInstanceHandle),
input-output viQueryClassID (biClassInstanceId),
input '' (icDraftReference),
input '' (icUserDefinedContext),
output viCountLoop (oiReturnStatus)) in BQueryCache>
if viFcReturnSuper <> 0
then oiReturnStatus = viFcReturnSuper.
if viFcReturnSuper < 0
then return.
end. /* vlgetdata = yes */
else do:
/* ================================================================= */
/* Load the resultset data. */
/* ================================================================= */
create temp-table vhCacheDataTable in widget-pool "non-persistent".
vhCacheDataTable:create-like(ihResultSetBuffer).
vhCacheDataTable:temp-table-prepare(ihResultSetBuffer:table).
vhCacheDataTableBuffer = vhCacheDataTable:default-buffer-handle.
create dataset vhCacheDataDataset in widget-pool "non-persistent".
vhCacheDataDataset:name = ihResultSetBuffer:table.
vhCacheDataDataset:set-buffers(vhCacheDataTableBuffer).
vhFcComponent = vhPL.
<M-32 run LoadInstance
(input {&TARGETPROCEDURE} (ihClass),
input tQueryCache.Instance_ID (iiInstanceID),
input vhCacheDataDataset (ihInstanceData),
input 'BQueryCache' (icClassName),
output viCountLoop (oiDraftInstanceId),
output viFcReturnSuper (oiReturnStatus)) in persistence>
if viFcReturnSuper <> 0
then oiReturnStatus = viFcReturnSuper.
if viFcReturnSuper < 0
then do:
delete object vhCacheDataDataset.
return.
end.
create query vhQuery in widget-pool "non-persistent".
vhQuery:forward-only = yes.
vhQuery:set-buffers(vhCacheDataTableBuffer).
if iiRowNum = 0
and icRowid <> ""
then do:
vhQuery:query-prepare ("for each " + vhCacheDataTableBuffer:name
+ " where " + vhCacheDataTableBuffer:name + ".tc_Rowid = '" + icRowid + "'").
vhQuery:query-open().
vhQuery:get-first().
if not vhQuery:query-off-end
then iiRowNum = vhCacheDataTableBuffer::ti_Sequence.
vhQuery:query-close().
end.
if ilForwardRead
then assign viFrom = iiRowNum
vito = (if iiNumber = 0 then 999999 else iiRowNum + iiNumber + 1).
else do:
if iiRowNum = 0 then iiRowNum = tQueryCache.RecordCount + 1.
assign viFrom = (if iiNumber = 0 then 0 else iiRowNum - iiNumber - 1)
vito = iiRowNum.
end.
vhQuery:query-prepare ("for each " + vhCacheDataTableBuffer:name
+ " where " + vhCacheDataTableBuffer:name + ".ti_Sequence > " + string(viFrom)
+ " and " + vhCacheDataTableBuffer:name + ".ti_Sequence < " + string(viTo)
+ " by " + vhCacheDataTableBuffer:name + ".ti_Sequence").
vhQuery:query-open().
do while true:
vhQuery:get-next().
if vhQuery:query-off-end then leave.
ihResultSetBuffer:buffer-create().
ihResultSetBuffer:raw-transfer(false,vhCacheDataTableBuffer).
ihResultSetBuffer:buffer-release().
end.
vhQuery:query-close().
delete object vhQuery.
delete object vhCacheDataDataset.
if (ilForwardRead = yes and viTo <= tQueryCache.RecordCount)
or (ilForwardRead = no and viFrom > 0)
then olEndOfQuery = no.
end. /* vlgetdata = no */
end. /* ilCountOnly = no */
/* Return this unique key back to the client in tFcMessages
(because it cannot be added as a parameter to the generic API query interface)
*/
<M-91 run SetMessage
(input 'QueryCacheKey' (icMessage),
input '' (icArguments),
input 'QueryCacheKey' (icFieldName),
input vcSearchKey (icFieldValue),
input 'I' (icType),
input 0 (iiSeverity),
input '' (icRowid),
input 'blf-251439':U (icFcMsgNumber),
input '' (icFcExplanation),
input '' (icFcIdentification),
input '' (icFcContext),
output viFcReturnSuper (oiReturnStatus)) in BQueryCache>
end.
finally:
delete object vhQueryDataset no-error.
end finally.