LOCATE

LOCATE, LOCATE()

Top  Previous  Next

 

The LOCATE statement searches a dynamic array for a given field, value or subvalue. The LOCATE() function provides similar capabilities and is particularly suited to use in dictionary I-type items.

 

 

Format

 

This statement has three different syntaxes / semantics for compatibility with other systems.

 

Default style

LOCATE string IN dyn.array<field {,value {, subvalue}}> {BY order} {SETTING var}

{THEN statement(s)}

{ELSE statement(s)}

 

UniVerse style (enabled by use of $MODE UV.LOCATE)

LOCATE string IN dyn.array{<field {,value }>} {, start}  {BY order} SETTING var

{THEN statement(s)}

{ELSE statement(s)}

 

Pick style

LOCATE(string, dyn.array{, field {, value {, start }}}; var {; order})

{THEN statement(s)}

{ELSE statement(s)}

 

Function style (returns position as function value)

LOCATE(string, dyn.array, field {,value {, subvalue }} {; order})

 

where

 

stringevaluates to the item to be located.

 

dyn.arrayis the dynamic array in which searching is to occur.

 

fieldis the field at which searching is to commence.

 

valueis the value at which searching is to commence. If omitted or zero, searching occurs at the field level.

 

subvalueis the subvalue at which searching is to commence. If omitted or zero, searching occurs at the value level.

 

orderevaluates to the ordering string as described below. If omitted, no ordering is assumed.

 

varis the variable to receive the position value.

 

statement(s)are statements to be executed depending on the outcome of the LOCATE action.

 

At least one of the THEN and ELSE clauses must be present.

 

 

The LOCATE statement searches for fields, values or subvalues within a dynamic array. The semantics of this operation depend on the style selected as described below.

 

 

Default Style

 

The default style  of LOCATE is as found in products such as Prime Information, PI/open and with certain mode settings in UniVerse and Unidata.

 

If only field is specified, LOCATE searches for a field that matches string. If field and value are specified but subvalue is omitted, LOCATE searches for a value within the specified field that matches string. If field, value and subvalue are specified, LOCATE searches for a subvalue within the specified field and value that matches string.

 

Searching commences at the starting position defined in the IN clause. If a match is found, var is set to its field, value or subvalue position as appropriate to the level of the search. If no match is found, var is set to the position at which a new item should be inserted. For an unordered LOCATE this will be such that it would be appended.

 

Note that the syntax actually reads incorrectly. A LOCATE statement such as

LOCATE DT IN DATES<1> SETTING POS THEN ...

is not searching in DATES<1> at all. It is searching starting at DATES<1>.

 

 

UniVerse Style

 

Pick and Reality systems and the UniVerse database running in Ideal, Pick, Reality or IN2 flavour uses the IN clause to identify the item to be searched, not the starting position. The starting position is assumed to be the first item in the data but may specified explicitly in the command by including the start item.

 

This format of LOCATE can be selected by including a line

$MODE UV.LOCATE

in the program on a line preceding the LOCATE statement.

 

 

Pick Style

 

The original Pick database used a very different syntax which can be used in QM without any special mode settings. Note that despite the presence of brackets, this is a statement and should not be confused with the LOCATE() function described below.

 

 

In all three styles, the THEN clause is executed if the string is found in dyn.array. The ELSE clause is found if the string is not found.

 

In QMBasic, unlike other multivalue environments, the SETTING clause is optional. If omitted, the THEN or ELSE clause is executed as described above but no positional information is returned.

 

Note that this syntax, as found in Information style multivalue products, is actually illogical. The IN clause does not specify the data within which to search. Instead it specifies the start position for the search. The alternative syntax enabled by the UV.LOCATE compiler mode and described below is more logical. This syntax is found in Pick, Reality and some flavours of UniVerse.

 

 

The optional BY clause allows selection of an ordering rule specified as a series of case insensitive letters. These are:

 

A or DAscending or descending sort order. On non-ECS mode systems, the sort weight of each character is determined by its ASCII character value. On ECS mode systems, the sort weights are taken from the currently active character map. If neither code is present, no sorting is used.

 

L or RLeft or right aligned sort. These codes are ignored if no sort mode is specified. A left aligned sort compares characters from left to right and determines the sort order when the first difference is encountered. In a right aligned sort, if the item being examined is not of the same length as the string being located, leading spaces are added to the shorter item prior to a left to right comparison. Integer numeric data that can be represented as a 64 bit value, including a negative value, is treated as a special case in a right aligned sort and is sorted into correct numeric sequence. In the Pick style syntax, fractional values are also allowed in numeric sorting.

 

C or NOverrides default case sensitivity of the program. C forces case sensitivity and N forces non-case sensitivity. If neither code is present, case sensitivity is applied unless the $NOCASE.STRINGS compiler directive has been used to make string comparisons case insensitive.

 

 

Left aligned ordering is faster than right aligned and should be used for textual data. Right aligned ordering is useful for numeric data such as internal format dates where the left aligned ordering would lead to sequencing problems (for example, 17 May 1995 is day 9999, 18 May 1995 is day 10000. Use of a left aligned ordering would place these dates out of calendar order).

 

 

The LOCATE() function works like the Information style described above but returns the position at which the item was found as its result value, zero if it was not found. Although the order argument can be used to specify the expected ordering and has the impact described above for numeric data, this function does not provide a way to identify where an item should be inserted if it is not found. The LOCATE() function is particularly suited to use in dictionary I-type items.

 

 

The result of a LOCATE statement or LOCATE() function with a specific ordering when applied to a dynamic array which does not conform to that ordering is undefined and likely to lead to misbehaviour of the program at run time.

 

 

 

Examples

 

Default style:

LOCATE PART.NO IN PARTS<1> BY "AL" SETTING I ELSE

  INS PART.NO BEFORE PARTS<I>

END

 

This program fragment locates PART.NO in a sorted list PARTS and, if it is not already present, inserts it.

 

UniVerse style:

LOCATE PART.NO IN PARTS BY "AL" SETTING I ELSE

  INS PART.NO BEFORE PARTS<I>

END

 

This is the same as the first example but reworked to use UniVerse style.

 

Function style:

I = LOCATE(PART.NO, PARTS, 1; "AL")

 

This statement performs the same search as the previous example but can only be used to find the position of an existing item, not to determine where a new item should be inserted to maintain the correct sort order.

 

 

See also:

DEL, DELETE(), EXTRACT(), FIND, FINDSTR, INS, INSERT(), LISTINDEX(), REPLACE()