Recently at Sprezz Towers, we had an interesting discussion on resolved selects, latent (or unresolved) selects, sizelocks and manipulating records while in a select list. Surprisingly, there was some confusion, even between ourselves. Once we hashed it all out, we thought it would be a good idea to post on the topic.
Types of SelectsAs most of you know, there are two types of selects in the Revelation environment, latent and resolved. In resolved selects, the results are processed and stored in a temporary
SYSLISTS (or
LISTS) record. In latent selects, the record IDs are not returned until the
READNEXT (or
READNEXT BY) statement is executed. Resolved selects are initiated through the
RLIST function or
PERFORM statement. Latent selects are initiated through the Basic+
reduce subroutine and
select statement.
What many people do not know is that inside each resolved select is a latent select waiting to get out. In order to generate the resolved select, the system must process the select through a latent list.
So, if you were to issue the following as a resolved select:
SELECT SYSPROCS WITH TYPEID = 'STPROC' BY ENTITYID BY APPID
the system will basically execute code similar to this:
0001 * // Parse the sentence
0002 * // Assign some vars
0003 * // Open handles
0004 * // Other initialization based stuff
0005 abort = FALSE$
0006 script = "WITH {TYPEID} EQ 'STPROC'"
0007 sortList = "APPID"
0008 mode = NEW.REDUCE$
0009 tableName = "SYSREPOS"
0010 cursor = 0
0011 flag = ""
0012
0013 call fix_lh( tableName, UPDATE_SIZELOCK$, INCREMENT_SIZELOCK$ )
0014
0015 call reduce( script, sortList, mode, tableName, cursor, successFlag )
0016 if successflag else
0017 * // set error
0018 abort = TRUE$
0019 end
0020
0021 if abort else
0022 select tableName by sortList using cursor else
0023 * // set error
0024 abort = TRUE$
0025 end
0026 end
0027
0028 if abort else
0029 listData = ""
0030 reccount = 0
0031 done = FALSE$
0032 loop
0033 readnext id using cursor by AT else
0034 done = TRUE$
0035 end
0036 until done
0037 listData := id : @FM
0038 reccount += 1
0039 repeat
0040
0041 listData[ -1, 1 ] = ""
0042 call dostime( dateTime )
0043 listKey = "W*" : @STATION : "*" : @APPID : "*" : dateTime
0044 listHeader = @VM : dateTime : @VM : @APPID : @VM : reccount : @VM
0045 listRec = listHeader : @FM : listData
0046 write listRec on hLists, listKey else
0047 * // set error
0048 end
0049 end
0050
0051 if abort else
0052 call make.list( cursor, listData, hDataHandle, hDictHandle )
0053 end
0054
0055 call fix_lh( tableName, UPDATE_SIZELOCK$, DECREMENT_SIZELOCK$ )
More or less...it's not perfect, but it's a pretty rough idea of what happens.
The system parses your sentence, generates a reduce, performs a select/readnext, stores all the returned keys, writes them off to a LISTS record (and updates the save select list queue) and then does a make.list so they are active and available.
In short, resolved selects are a giant shell around reduce/select. When you work with a resolved select, you're processing the list twice; once to resolve it, and once to process it.
It's always quicker to skip the shell and work with reduce/select yourself. However, as with many shelled functions, the system also handles some maintenance work for you.
In the next article, we'll talk about the maintenance work required to handle all this correctly.
Labels: latent, reduce, resolved, select
0 Comments:
Post a Comment
Subscribe to Post Comments [Atom]
<< Home