`
Par2: Pointer() and Position 1998-05-18 -- Sean Wilson The POINTER() function is probably one of the least well understood file commands in the Clarion language, the presence of the POSITION() command with it's apparently identical functionality does little to clear the confusion. The problems that arise with the use of the POINTER() function, tend to arise from differences in the implementation of this function between one file driver and another, and the assumptions that developers make based on past experience with other file drivers. There are many implementation specific differences between file drivers. Whilst the drivers are designed to behave identically (where possible) for the documented use of a command, it is possible to write code that will work correctly with one driver but not with another. The POINTER() command is often misused, because the values that it returns exhibit highly implementation dependent characteristics. I will examine the characteristics of some of the drivers before drawing a conclusion. The Clarion File Driver ----------------------------------- Most Clarion developers are familiar with the Clarion File Driver which formed the basis for the specification of most of the file commands. The value returned by the Clarion File Driver for POINTER() is the number of the record in the sequence. This means that if POINTER(file) returns n, the next record in the file can be obtained by calling GET(file,n+1). Similarly, if POINTER(key) returns n, the next record in the sequence can be obtained by calling GET(key,n+1). This behaviour is peculiar to the Clarion driver, however many developers believe that GET(f, POINTER(f)+1) will obtain the next record, and more particularly that GET(f, 1) will obtain the first record in the sequence. The TopSpeed File Driver ---------------------------------------- The TopSpeed Driver returns pointers that reflect the temporal order in which records were added to a file. The first record added to a TopSpeed file contains control information so GET(f,1) does not return a valid record for an applications file. The pointer values are added in a contiguous sequence from 1..2^32, once a value has been allocated it will never be reallocated. One consequence of this is that pointers are completely stable, a given pointer value will refer to the same record for the lifetime of the table, if the record is removed the pointer will always be invalid. Another consequence of this allocation mechanism affects superfiles where records added to different tables within a superfile take distinct values from the same sequence. So, for example, if you add records alternately to tables A and B in the same superfile, table A may have pointer values 3,5,7,9,... and table B may have pointer values 4,6,8,10. That is to say, POINTER() will return a given value for at most one table in a superfile. It is not safe to assume that with the TopSpeed File Driver, GET(f,POINTER(f)+1) obtains the next record in a table. The xBase File Drivers ----------------------------------- The xBase File Drivers return pointer values that reflect the position of the record in the tables sequence. POINTER(file) and POINTER(key) return the same value for a given record. Because new records are appended to the end of the file, and deletions do not reorganise the data table, pointer values are stable until the table is compressed using PACK(). What's more, GET(f,POINTER(f)+1) will return the next record in the file (if it exists), but may not return the subsequent record in a key sequence. The Paradox File Driver ------------------------------------- The Paradox File Driver returns pointer values that reflect the position of the record within the sequence. If the table has a primary key then the records within the table are maintained in primary key order. This means that the pointer values can be highly unstable. The first record in the sequence has pointer value 1, if a record with a lower primary key value is inserted that record will return a pointer value of 1. Calling GET(f,POINTER(f)+1) will obtain the next record in the table, and may be used to get the next record in the primary key sequence if a primary key exists. The DOS File Driver ------------------------------- The DOS File Driver returns pointer values that reflect the byte postion of the record within the file. For practical reasons, it is important to be able to arithmetically change pointer values to access records in DOS files, so GET(f,n) will return the record starting at the nth byte. POSITION() to the Rescue ------------------------------------------ With such a variety of implementation specific semantics for one particular function, it is clear to see why there can be a great deal of confusion about the POINTER() function. The POINTER() function, clearly has it's uses, however for the purists a better alternative is the POSITION() function. The POSITION() function offers much the same functionality as the POINTER() function but because of it's implementation offers less scope for misuse than the POINTER() function and is more portable between file drivers (all drivers support POSITION()/RESET() some drivers do not support POINTER()). One important difference, is that the POSITION() function returns a STRING, the driver can therefore return a great deal more information which means that there is usually much more stability associated with POSITION() values. It is not possible to use SET() or GET() with the values returned by the POSTION() function, but identical results can be obtained using variations with REGET(), SET(), NEXT() and PREVIOUS(). One disadvantage, is that the size of the string returned by POSITION() is implementation dependent, and is often dependent on the sequence. However, the size of the string is usually documented and the Paradox File Driver even provides a property to determine at run-time the size of the string that needs to be allocated. Conclusions ------------------- The POINTER() function tends to cause problems as a result of confusion to do with the wide variety of implementation specific characteristics of the return value. The POSITION() function returns a much more opaque value that is less prone to misuse, is intended to be portable and is supported by all drivers. If you choose to use POINTER() in an application remember the following: The return value may be the position in the sequence, the byte position in the file, the temporal position in the sequence or some other representation of the record location. The command GET(f,1) may not obtain the first record in the sequence (use SET(f); NEXT(f) instead). The pointer may not have arithmetic properties, i.e. GET(f,POINTER(f)+1) may not obtain the next record (use SET(...);NEXT(f) insead). POSITON() is more portable. Printed November 23, 2024, 3:39 am This article has been viewed/printed 35201 times. |