Home page Home page Home page Home page
Pixel
Pixel Header R1 C1 Pixel
Pixel Header R2 C1 Pixel
Pixel Header R3 C1 Pixel
Pixel
By APK | Monday 23 May 2011 13:16 | 0 Comments
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 Selects

As 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: , , ,

0 Comments:

Post a Comment

Subscribe to Post Comments [Atom]



<< Home

Pixel
Pixel Footer R1 C1 Pixel
Pixel
Pixel
Pixel