home *** CD-ROM | disk | FTP | other *** search
- {$N+,E+}
- (* Copyright (c) 1989 by Borland International, Inc. *)
- program Sort;
-
- uses
- PXEngine;
- (*
- * SORT.PAS
- *
- * This example program sorts a file on any combination of fields
- * in either ascending or descending order.
- *
- * The algorithm supplied is a Shell sort. However, since the
- * comparison and switch routines are generic, any sort algorithm
- * could be applied. In addition, this file sort could be made
- * more efficient by employing an intelligent buffering
- * algorithm to help reducing disk accesses.
- *
- * The program body is an example of how a command line file sort
- * program can be written. The sort function could just as easily
- * be called from within an application.
- *
- * Remark : Sorting only makes sense if the table is NOT indexed
- *)
-
- const
- MAXFIELDNUMBER = 255;
-
- type
- SortOrderT = (ASCENDING, DESCENDING);
-
- var (* Globals *)
- PXErr: Integer; (* last PX error *)
- RecHandle1, (* handle to first comparison rec *)
- RecHandle2: RecordHandle; (* handle to second comparison rec *)
- TblHandle: TableHandle; (* global table handle *)
- Fields: WordArray; (* fields which are relevant to
- sortorder *)
- I, H1, H2: Word;
-
-
- (*
- * Procedure:
- * Error
- *
- * Arguments:
- * PXErr Paradox Engine error code
- *
- * Description:
- * Prints the message of the error code stored in pxErr,
- * exits the engine, and terminates the program, if an error
- * occures.
- *
- * Returns:
- * None
- *)
- procedure Error(PXErr: Integer);
-
- begin
- if PXErr <> 0 then
- begin
- WriteLn('Paradox Engine Error: ', PXErrMsg(PXErr));
- if PXExit = 0 then; (* ignore return code *)
- Halt(PXErr);
- end;
- end; (* Error *)
-
-
- (*
- * Function:
- * Compare
- *
- * Arguments:
- * Field Field handle of field to compare
- * SortOrder ASCENDING or DESCENDING
- *
- * Description:
- * Compares a given field of two records
- *
- * Returns:
- * 0 Records are equal
- * < 0 Records need switching
- * > 0 Records are in sorted order
- *)
- function Compare(Field: FieldHandle;
- SortOrder: SortOrderT): Integer;
-
- var
- RH1, RH2: Word;
- Long1, Long2: LongInt;
- Short1, Short2: Integer;
- Doub1, Doub2: Double;
- Alpha1, Alpha2: String ;
- FldType: NameString;
-
- begin
- (* Setup records according to sortorder *)
- if SortOrder = ASCENDING then
- begin
- RH1 := RecHandle1;
- RH2 := RecHandle2;
- end
- else
- begin
- RH1 := RecHandle2;
- RH2 := RecHandle1;
- end;
- (* Get field type *)
- Error(PXFldType(TblHandle, Field, FldType));
- (* Compare fields *)
- case FldType[1] of
- 'D':
- begin
- Error(PXGetDate(RH1, Field, Long1));
- Error(PXGetDate(RH2, Field, Long2));
- Compare := Long2 - Long1;
- end;
- 'S':
- begin
- Error(PXGetShort(RH1, Field, Short1));
- Error(PXGetShort(RH2, Field, Short2));
- Compare := Short2 - Short1;
- end;
- 'A':
- begin
- Error(PXGetAlpha(RH1, Field, Alpha1));
- Error(PXGetAlpha(RH2, Field, Alpha2));
- if Alpha2 < Alpha1 then
- Compare := - 1
- else if Alpha2 > Alpha1 then
- Compare := 1
- else
- Compare := 0;
- end;
- 'N', '$':
- begin
- Error(PXGetDoub(RH1, Field, Doub1));
- Error(PXGetDoub(RH2, Field, Doub2));
- if Doub2 < Doub1 then
- Compare := - 1
- else if Doub2 > Doub1 then
- Compare := 1
- else
- Compare := 0;
- end
- else Compare := 0;
- end; (* CASE *)
- end; (* Compare *)
-
-
- (*
- * Procedure:
- * ProcessElement
- *
- * Arguments:
- * Rec1 Record number of first comparison record
- * Rec2 Record number of second comparison record
- * NFields Number of fields to use in sort comparison
- * Fields Array of fieldhandles
- * SortOrder ASCENDING or DESCENDING
- *
- * Description:
- * Compares two record numbers and exchanges them if needed
- *
- * Returns:
- * None
- *)
- procedure ProcessElement(Rec1, Rec2: RecordNumber;
- NFields: Integer;
- Fields: WordArray;
- SortOrder: SortOrderT);
-
- var
- NeedSwitch: Boolean;
- I, Ret: Integer;
-
- begin
- (* Get the records *)
- Error(PXRecGoto(TblHandle, Rec1));
- Error(PXRecGet(TblHandle, RecHandle1));
- Error(PXRecGoto(TblHandle, Rec2));
- Error(PXRecGet(TblHandle, RecHandle2));
- (* Compare each field *)
- I := 1;
- Ret := 0;
- while (I <= NFields) and (Ret = 0) do
- begin
- Ret := Compare(Fields[I], SortOrder);
- NeedSwitch := Ret < 0;
- Inc(I);
- end;
- (* Switch and update if needed *)
- if NeedSwitch then
- begin
- Error(PXRecGoto(TblHandle, Rec1));
- Error(PXRecUpdate(TblHandle, RecHandle2));
- Error(PXRecGoto(TblHandle, Rec2));
- Error(PXRecUpdate(TblHandle, RecHandle1));
- end;
- end; (* ProcessElement *)
-
-
- (*
- * Procedure:
- * TableSort
- *
- * Arguments:
- * TblName Name of table to sort
- * NFields Number of fields to use in sort
- * Fields Array of field handles
- * SortOrder ASCENDING or DESCENDING
- *
- * Description:
- * Sorts a table using a standard Shell sort on a given
- * table
- *
- * Returns:
- * None
- *)
- procedure TableSort(TblName: String ;
- NFields: Integer;
- Fields: WordArray;
- SortOrder: SortOrderT);
-
- var
- Span, (* span of current sort *)
- NRecs: LongInt;
- I: Integer; (* Shell sort counter *)
-
- begin
- (* Open table with buffering *)
- Error(PXTblOpen(TblName, TblHandle, 0, True));
- (* Get number of recs *)
- Error(PXTblNRecs(TblHandle, NRecs));
- (* Allocate 2 record handles *)
- Error(PXRecBufOpen(TblHandle, RecHandle1));
- Error(PXRecBufOpen(TblHandle, RecHandle2));
- (* Perform Shell sort on records *)
- for Span := NRecs div 2 downto 1 do
- for I := 1 to NRecs - Span do
- ProcessElement(I, I + Span, NFields, Fields, SortOrder);
- (* Deallocate everything *)
- Error(PXRecBufClose(RecHandle1));
- Error(PXRecBufClose(RecHandle2));
- Error(PXTblClose(TblHandle));
- end; (* TableSort *)
-
-
- (* Main program
- *
- *
- * Description:
- * This is an example of how a table sort can
- * be implemented
- *
- * Command line arguments are as follows:
- * sort <tablename> <sortorder> <field1>...<fieldN>
- * tablename Name of table to sort
- * sortorder 0=ascending, 1=descending
- * field1..N field handles to sort on
- *
- * Returns:
- * Exit Code
- *)
- begin
- (* Initialize Engine *)
- Error(PXInit);
- (* Store field handles in an array *)
- for I := 3 to ParamCount do
- begin
- Val(ParamStr(I), H1, H2);
- Fields[I - 2] := H1;
- end;
- (* Call the sort *)
- Val(ParamStr(2), H1, H2);
- TableSort(ParamStr(1), ParamCount - 2, Fields, SortOrderT(H1));
- (* End Engine *)
- PX(PXExit);
- end.
-