home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
PC Press 1997 July
/
Sezamfile97_1.iso
/
msdos
/
database
/
pdx_ti2.arj
/
TI1113.ASC
< prev
next >
Wrap
Text File
|
1992-09-04
|
12KB
|
463 lines
PRODUCT : Paradox NUMBER : 1113
VERSION : 4.0
OS : DOS
DATE : September 4, 1992 PAGE : 1/7
TITLE : LOCATE INDEXORDER
Intended Audience:
PAL programmers
Prerequisites:
Thorough understanding of indexes, including key fields, compound
secondary indexes, maintained indexes, and Image | OrderTable.
Understand Chapters 3 and 4 of the PAL Programmer's Guide.
Should have a basic understanding of the LOCATE command.
Purpose:
This Technical Information sheet expands on and clarifies the
documentation for LOCATE INDEXORDER. It provides information on
the differences between LOCATE and LOCATE INDEXORDER.
Disclaimer:
The PAL code in this document is skeletal, and should only be
used as examples. In particular, an actual application would
need to do a lot more error checking.
A brief review of LOCATE:
LOCATE sets Retval to false if it does not find a record. You
can use LOCATE on multiple fields, but they must be the first
fields in the table structure. When using LOCATE on multiple
fields, you do not have to place the cursor in the field you are
doing the LOCATE on.
LOCATE NEXT does not require a previous LOCATE, unlike ZOOMNEXT,
so it is ideal for searching from the middle of the table. It
always starts searching from the current position. However, if
the record you are on contains the value used in LOCATE NEXT, you
will get a Retval of True without moving anywhere; it is
necessary to move to the next record for each subsequent LOCATE
NEXT.
LOCATE searches the table sequentially, so it will only use the
current field's index if the view is ordered by the current field
or the key fields(s). For example, look at the following table:
PRODUCT : Paradox NUMBER : 1113
VERSION : 4.0
OS : DOS
DATE : September 4, 1992 PAGE : 2/7
TITLE : LOCATE INDEXORDER
XYZZY ══╦═════ A ══════╦═════ B ══════╦═════ C ══════╗
1 ║ 6 ║ 1 ║ 7 ║
2 ║ 4 ║ 3 ║ 12 ║
3 ║ 9 ║ 3 ║ 1 ║
4 ║ 2 ║ 6 ║ 5 ║
5 ║ 1 ║ 7 ║ 9 ║
6 ║ 8 ║ 7 ║ 1 ║
7 ║ 10 ║ 7 ║ 7 ║
8 ║ 7 ║ 10 ║ 8 ║
9 ║ 3 ║ 12 ║ 4 ║
10 ║ 5 ║ 12 ║ 5 ║
All fields are type S. [A] is keyed, and [B] and [C] have
maintained secondary indexes. Xyzzy is currently ordered on [B].
If your cursor is on [B], then LOCATE would use [B]'s index, but
if the cursor is on [A] or [C] LOCATE would not use [A]'s or
[C]'s index. If the table were ordered on [A] (key order), then
LOCATE would use the current field's index no matter which field
you were on.
LOCATE INDEXORDER
LOCATE INDEXORDER always searches directly through the index,
regardless of the current OrderTable. For example, let's use
Xyzzy again:
VIEW "Xyzzy"
MOVETO [B]
ORDERTABLE SELECT "B"
MOVETO [C]
LOCATE 1 ; You are on record 3
LOCATE INDEXORDER 1 ; You are now on record 6 because 8 is
; less than 9 in [A]
It's easier to understand what happened with the LOCATE
INDEXORDER if you move to field A and do an OrderTable.
Although LOCATE INDEXORDER has many different forms, some of them
must be used in a specific order within a script: you cannot do a
LOCATE INDEXORDER NEXT/PREV until you have used one of the forms
without a NEXT/PREV in it.
PRODUCT : Paradox NUMBER : 1113
VERSION : 4.0
OS : DOS
DATE : September 4, 1992 PAGE : 3/7
TITLE : LOCATE INDEXORDER
Basically, LOCATE INDEXORDER NEXT/PREV move the current index
pointer up and down one position at a time, just the way that UP
and DOWN move the record pointer one position at a time. Because
LOCATE INDEXORDER is based on the index (independent of the
record pointer), you can change the current record position
without changing the current index location. See the example on
page 4.
LOCATE INDEXORDER has the same restrictions as LOCATE: the cursor
must either be in the field you want to search on, or use the
multi-field key search. The BY keyword allows you to specify a
compound (multi-field) index, but the cursor must be in the first
field of the index.
For example, if your cursor is on [B] of Xyzzy, then LOCATE
INDEXORDER 7 would bring you to record 5. Now suppose that you
have a compound index Bc on [B] and [C]. LOCATE INDEXORDER BY
"Bc" 7 would then take you to record 6 because 1 is less than 7
or 9 in [C].
Notice that the previous example used only one value even though
the index Bc is based on two fields. LOCATE INDEXORDER BY does
not require that you have the same number of values as there are
fields in the index, but all of the values that are present must
match the data types in the indexed fields.
LOCATE INDEXORDER BESTMATCH is somewhat similar to LOCATE PATTERN
or LOCATE INDEXORDER PATTERN, but it is guaranteed to match a
record. LOCATE INDEXORDER BESTMATCH searches for records in the
following sequence:
-- If there is an exact match it will move to the first record
(in the index) containing that value.
-- If the value is larger than the maximum value in the field, it
will move to the record containing the last occurrence
of the maximum value in the field.
-- Otherwise, it will move to the first record containing a
higher value than the one searched for.
PRODUCT : Paradox NUMBER : 1113
VERSION : 4.0
OS : DOS
DATE : September 4, 1992 PAGE : 4/7
TITLE : LOCATE INDEXORDER
LOCATE INDEXORDER FIRST/LAST should be considered equivalent to
LOCATE INDEXORDER MIN/MAX. It moves the index pointer to the
first or last entry in the index, then moves the record pointer
to the appropriate record. For example (using Xyzzy again), if
you move to [C] and do a LOCATE INDEXORDER FIRST, you will go to
record 6; LOCATE INDEXORDER LAST will place the cursor on
record 2.
EXAMPLES
The following table represents travel expenses for salesmen.
When they come back to the office, they turn in their records;
each transaction receives a unique Id number. Because the
salesmen return their receipts in a jumbled pile, the dates end
up a bit scrambled, so most people view it with an OrderTable on
[Date].
Transact:
Id N*
Date D
Account A5
Amount $
[Date] and [Account] both have maintained secondary indexes.
TRANSACT ═╦═══ Id ═══╦═══ Date ═══╦═ Account ═╦═══ Amount ═══╗
1 ║ 25126 ║ 5/29/92 ║ TRAV ║ 579.00 ║
2 ║ 25125 ║ 6/01/92 ║ FOOD ║ 35.00 ║
3 ║ 25129 ║ 6/03/92 ║ TRAV ║ 88.00 ║
4 ║ 25127 ║ 6/04/92 ║ CAR ║ 125.00 ║
5 ║ 25128 ║ 6/06/92 ║ FOOD ║ 53.75 ║
6 ║ 25130 ║ 6/08/92 ║ TRAV ║ 1,024.00 ║
7 ║ 25131 ║ 6/15/92 ║ FOOD ║ 12.00 ║
8 ║ 25132 ║ 6/15/92 ║ FOOD ║ 18.30 ║
9 ║ 25134 ║ 6/17/92 ║ ENT ║ 75.00 ║
10 ║ 25133 ║ 6/18/92 ║ CAR ║ 38.00 ║
The VP of Sales likes to keep a close eye on travel expenses, so
here's a simple script to help:
PRODUCT : Paradox NUMBER : 1113
VERSION : 4.0
OS : DOS
DATE : September 4, 1992 PAGE : 5/7
TITLE : LOCATE INDEXORDER
VIEW "Transact"
MOVETO FIELD "Date"
ORDERTABLE SELECT "Date"
MOVETO [Account]
LOCATE INDEXORDER "TRAV" ; This sets up the index
WHILE TRUE
WAIT TABLE ; Allow user to cursor freely
; within the table
PROMPT "Press ESC to quit, Ctrl-PgUp/PgDn to jump" +
" between TRAV expenses"
UNTIL "Esc", "CtrlPgUp", "CtrlPgDn"
SWITCH
CASE RETVAL = "Esc" :
QUITLOOP
CASE RETVAL = "CtrlPgDn" :
Fld = FIELD() ; Save the current field
MOVETO [Account]
LOCATE INDEXORDER NEXT "TRAV"
IF NOT RETVAL THEN BEEP ENDIF
MOVETO FIELD Fld
CASE RETVAL = "CtrlPgUp" :
Fld = FIELD()
MOVETO [Account]
LOCATE INDEXORDER PREV "TRAV"
IF NOT RETVAL THEN BEEP ENDIF
MOVETO FIELD Fld
ENDSWITCH
ENDWHILE
CLEARIMAGE
PRODUCT : Paradox NUMBER : 1113
VERSION : 4.0
OS : DOS
DATE : September 4, 1992 PAGE : 6/7
TITLE : LOCATE INDEXORDER
Another commonly-requested feature is the ability to jump to the
last record or the second-to-last record. Suppose that you want
to see the next-to-last FOOD entry:
VIEW "Transact"
MOVETO [Account]
LOCATE INDEXORDER "FOOD"
WHILE RETVAL ; Keep looping through until you
; get to the last FOOD item.
LOCATE INDEXORDER NEXT "FOOD"
ENDWHILE
LOCATE INDEXORDER PREV "FOOD"
A trick for jumping to the last record containing a specific
value that works well with S or D type fields is the following:
ACCEPT "D" TO Date
VIEW "Transact"
MOVETO [Date]
LOCATE INDEXORDER Date ; Make sure that Date exists
IF RETVAL THEN
; The next line finds the closest match after the Date
; you are looking for. Note the assumption that Date is
; not the maximum date in this field.
LOCATE INDEXORDER BESTMATCH Date+1
; Now move back one record. You could use UP, but that
; wouldn't maintain the index pointer.
LOCATE INDEXORDER PREV Date
ELSE
BEEP
CLEARIMAGE
QUIT "Sorry, no match was found"
ENDIF
PRODUCT : Paradox NUMBER : 1113
VERSION : 4.0
OS : DOS
DATE : September 4, 1992 PAGE : 7/7
TITLE : LOCATE INDEXORDER
A similar technique works for A fields where the value searched
for is less than the length of the field:
ACCEPT "A4" TO Account
VIEW "Transact"
MOVETO [Account] ; This is an A5
LOCATE INDEXORDER Account
IF RETVAL THEN
; Use the next higher alpha string
LOCATE INDEXORDER BESTMATCH Account + CHR(1)
LOCATE INDEXORDER PREV Account
ELSE
BEEP
CLEARIMAGE
QUIT "Sorry, no match was found"
ENDIF
If the search string were the same length as the field, you would
need to use (with the ASCII sort order):
LOCATE INDEXORDER BESTMATCH SUBSTR(Account, 1,
LEN(Account) - 1 ) +
CHR ( ASC ( SUBSTR(Account, LEN(Account), 1) ) + 1 )
DISCLAIMER: You have the right to use this technical information
subject to the terms of the No-Nonsense License Statement that
you received with the Borland product to which this information
pertains.