// Thorough DBF + SEEK compatibility test — Harbour vs Five PROCEDURE Main() LOCAL i, aStruct, aCities, nIdx, nCount ErrorBlock({|e| Break(e)}) aStruct := { ; {"ID","N",6,0}, {"NAME","C",20,0}, {"CITY","C",15,0}, ; {"CODE","C",5,0}, {"SALARY","N",10,2} ; } BEGIN SEQUENCE dbCreate("seek_test", aStruct) USE "seek_test" NEW aCities := {"Seoul","Tokyo","Beijing","London","NYC"} FOR i := 1 TO 30 APPEND BLANK REPLACE ID WITH i REPLACE NAME WITH PadR("Name_" + PadL(LTrim(Str(i)), 3, "0"), 20) nIdx := ((i-1) % 5) + 1 REPLACE CITY WITH PadR(aCities[nIdx], 15) REPLACE CODE WITH PadR(LTrim(Str(Int((i-1)/10)+1)), 5) REPLACE SALARY WITH 20000 + i * 500.00 NEXT R("SETUP", LTrim(Str(RecCount()))) // S1: Basic field access GO 1 R("S1_REC1_ID", LTrim(Str(FieldGet(1)))) R("S1_REC1_NAME", RTrim(FieldGet(2))) R("S1_REC1_CITY", RTrim(FieldGet(3))) GO 15 R("S1_REC15_ID", LTrim(Str(FieldGet(1)))) R("S1_REC15_NAME", RTrim(FieldGet(2))) GO 30 R("S1_REC30_ID", LTrim(Str(FieldGet(1)))) // S2: NAME index — exact seek INDEX ON FIELD->NAME TO seek_name R("S2_IDX", "OK") GO TOP R("S2_TOP_NAME", RTrim(FieldGet(2))) R("S2_TOP_RECNO", LTrim(Str(RecNo()))) GO BOTTOM R("S2_BOT_NAME", RTrim(FieldGet(2))) R("S2_BOT_RECNO", LTrim(Str(RecNo()))) SEEK PadR("Name_001", 20) R("S2_SEEK_001", B(Found()) + " " + LTrim(Str(RecNo())) + " " + B(EOF())) SEEK PadR("Name_015", 20) R("S2_SEEK_015", B(Found()) + " " + LTrim(Str(RecNo())) + " " + B(EOF())) SEEK PadR("Name_030", 20) R("S2_SEEK_030", B(Found()) + " " + LTrim(Str(RecNo())) + " " + B(EOF())) SEEK PadR("Name_000", 20) R("S2_MISS_000", B(Found()) + " " + LTrim(Str(RecNo())) + " " + B(EOF())) SEEK PadR("Name_031", 20) R("S2_MISS_031", B(Found()) + " " + LTrim(Str(RecNo())) + " " + B(EOF())) SEEK PadR("Name_999", 20) R("S2_MISS_999", B(Found()) + " " + LTrim(Str(RecNo())) + " " + B(EOF())) SEEK PadR("ZZZZZ", 20) R("S2_MISS_ZZZ", B(Found()) + " " + B(EOF())) // S3: Partial key SEEK "Name_0" R("S3_PART_0", B(Found()) + " " + LTrim(Str(RecNo())) + " " + RTrim(FieldGet(2))) SEEK "Name_01" R("S3_PART_01", B(Found()) + " " + LTrim(Str(RecNo()))) SEEK "Name_1" R("S3_PART_1", B(Found()) + " " + LTrim(Str(RecNo()))) SEEK "Name_3" R("S3_PART_3", B(Found()) + " " + LTrim(Str(RecNo()))) SEEK "N" R("S3_PART_N", B(Found()) + " " + LTrim(Str(RecNo()))) SEEK "Z" R("S3_PART_Z", B(Found()) + " " + B(EOF())) // S4: SOFTSEEK SET SOFTSEEK ON SEEK PadR("Name_001", 20) R("S4_SOFT_001", B(Found()) + " " + LTrim(Str(RecNo()))) SEEK PadR("Name_000", 20) R("S4_SOFT_000", B(Found()) + " " + LTrim(Str(RecNo())) + " " + RTrim(FieldGet(2))) SEEK PadR("Name_015X", 20) R("S4_SOFT_15X", B(Found()) + " " + LTrim(Str(RecNo())) + " " + RTrim(FieldGet(2))) SEEK PadR("Name_031", 20) R("S4_SOFT_031", B(Found()) + " " + B(EOF())) SEEK PadR("ZZZZZ", 20) R("S4_SOFT_ZZZ", B(Found()) + " " + B(EOF())) SEEK "A" R("S4_SOFT_A", B(Found()) + " " + LTrim(Str(RecNo())) + " " + RTrim(FieldGet(2))) SET SOFTSEEK OFF // S5: Seek + navigation SEEK PadR("Name_010", 20) R("S5_SEEK_010", B(Found()) + " " + LTrim(Str(RecNo()))) SKIP R("S5_SKIP1", LTrim(Str(RecNo())) + " " + RTrim(FieldGet(2))) SKIP -1 R("S5_SKIPM1", LTrim(Str(RecNo())) + " " + RTrim(FieldGet(2))) SKIP 5 R("S5_SKIP5", LTrim(Str(RecNo())) + " " + RTrim(FieldGet(2))) // S6: Duplicate key (CITY) CLOSE ALL USE "seek_test" NEW INDEX ON FIELD->CITY TO seek_city R("S6_IDX", "OK") GO TOP R("S6_TOP", RTrim(FieldGet(3)) + " " + LTrim(Str(RecNo()))) SEEK PadR("Seoul", 15) R("S6_SEOUL", B(Found()) + " " + LTrim(Str(RecNo()))) nCount := 0 DO WHILE !EOF() .AND. RTrim(FieldGet(3)) == "Seoul" nCount++ SKIP ENDDO R("S6_SEOUL_CNT", LTrim(Str(nCount))) SEEK PadR("Tokyo", 15) R("S6_TOKYO", B(Found()) + " " + LTrim(Str(RecNo()))) SEEK PadR("Beijing", 15) R("S6_BEIJING", B(Found()) + " " + LTrim(Str(RecNo()))) SEEK PadR("London", 15) R("S6_LONDON", B(Found()) + " " + LTrim(Str(RecNo()))) SEEK PadR("NYC", 15) R("S6_NYC", B(Found()) + " " + LTrim(Str(RecNo()))) SEEK PadR("Paris", 15) R("S6_PARIS", B(Found()) + " " + B(EOF())) // S7: SET DELETED + SEEK CLOSE ALL USE "seek_test" NEW INDEX ON FIELD->NAME TO seek_name SET ORDER TO 0 FOR i := 1 TO 30 GO i IF i % 5 == 0 DELETE ENDIF NEXT SET ORDER TO 1 SET DELETED OFF SEEK PadR("Name_005", 20) R("S7_DELOFF_005", B(Found()) + " " + LTrim(Str(RecNo()))) SEEK PadR("Name_010", 20) R("S7_DELOFF_010", B(Found()) + " " + LTrim(Str(RecNo()))) SET DELETED ON GO TOP nCount := 0 DO WHILE !EOF() nCount++ SKIP ENDDO R("S7_DELON_CNT", LTrim(Str(nCount))) SET DELETED OFF SET ORDER TO 0 FOR i := 1 TO 30 GO i IF Deleted() RECALL ENDIF NEXT // S8: Numeric key CLOSE ALL USE "seek_test" NEW INDEX ON Str(FIELD->ID, 6) TO seek_id R("S8_IDX", "OK") SEEK Str(1, 6) R("S8_SEEK_1", B(Found()) + " " + LTrim(Str(RecNo()))) SEEK Str(15, 6) R("S8_SEEK_15", B(Found()) + " " + LTrim(Str(RecNo()))) SEEK Str(30, 6) R("S8_SEEK_30", B(Found()) + " " + LTrim(Str(RecNo()))) SEEK Str(31, 6) R("S8_SEEK_31", B(Found()) + " " + B(EOF())) GO TOP R("S8_TOP_ID", LTrim(Str(FieldGet(1)))) GO BOTTOM R("S8_BOT_ID", LTrim(Str(FieldGet(1)))) // S9: Compound key CLOSE ALL USE "seek_test" NEW INDEX ON FIELD->CITY + FIELD->NAME TO seek_compound R("S9_IDX", "OK") GO TOP R("S9_TOP", RTrim(FieldGet(3)) + " " + RTrim(FieldGet(2)) + " " + LTrim(Str(RecNo()))) GO BOTTOM R("S9_BOT", RTrim(FieldGet(3)) + " " + RTrim(FieldGet(2)) + " " + LTrim(Str(RecNo()))) SEEK PadR("Seoul", 15) + PadR("Name_001", 20) R("S9_SEEK_S001", B(Found()) + " " + LTrim(Str(RecNo()))) SEEK PadR("Seoul", 15) R("S9_PART_SEOUL", B(Found()) + " " + LTrim(Str(RecNo()))) SEEK PadR("Tokyo", 15) R("S9_PART_TOKYO", B(Found()) + " " + LTrim(Str(RecNo()))) // S10: Empty table CLOSE ALL dbCreate("seek_empty", {{"NAME","C",10,0}}) USE "seek_empty" NEW INDEX ON FIELD->NAME TO seek_empty_idx R("S10_RC", LTrim(Str(RecCount()))) SEEK "Test" R("S10_SEEK", B(Found()) + " " + B(EOF()) + " " + LTrim(Str(RecNo()))) GO TOP R("S10_TOP", B(EOF()) + " " + LTrim(Str(RecNo()))) // S11: Single record APPEND BLANK REPLACE NAME WITH "OnlyOne" CLOSE ALL USE "seek_empty" NEW INDEX ON FIELD->NAME TO seek_empty_idx SEEK PadR("OnlyOne", 10) R("S11_FOUND", B(Found()) + " " + LTrim(Str(RecNo()))) SEEK PadR("Other", 10) R("S11_MISS", B(Found()) + " " + B(EOF())) SEEK "Only" R("S11_PARTIAL", B(Found()) + " " + LTrim(Str(RecNo()))) // S12: State after seek CLOSE ALL USE "seek_test" NEW SET INDEX TO seek_name SEEK PadR("Name_020", 20) R("S12_SEEK", B(Found()) + " " + LTrim(Str(RecNo()))) R("S12_BOF", B(BOF())) R("S12_EOF", B(EOF())) SEEK PadR("Name_999", 20) R("S12_MISS_FOUND", B(Found())) R("S12_MISS_EOF", B(EOF())) GO TOP R("S12_GOTOP", LTrim(Str(RecNo())) + " " + B(Found())) // S13: Order switch + seek SET INDEX TO seek_name SEEK PadR("Name_001", 20) R("S13_ORD1", B(Found()) + " " + LTrim(Str(RecNo()))) CLOSE ALL USE "seek_test" NEW SET INDEX TO seek_city SEEK PadR("Tokyo", 15) R("S13_ORD2", B(Found()) + " " + LTrim(Str(RecNo()))) CLOSE ALL USE "seek_test" NEW SET INDEX TO seek_id SEEK Str(25, 6) R("S13_ORD3", B(Found()) + " " + LTrim(Str(RecNo()))) // S14: Full traversal count CLOSE ALL USE "seek_test" NEW SET INDEX TO seek_name GO TOP nCount := 0 DO WHILE !EOF() nCount++ SKIP ENDDO R("S14_NAME_CNT", LTrim(Str(nCount))) CLOSE ALL USE "seek_test" NEW SET INDEX TO seek_city GO TOP nCount := 0 DO WHILE !EOF() nCount++ SKIP ENDDO R("S14_CITY_CNT", LTrim(Str(nCount))) CLOSE ALL RECOVER ? "ERROR" END SEQUENCE RETURN FUNCTION B(lVal) IF lVal RETURN ".T." ENDIF RETURN ".F." PROCEDURE R(cKey, cVal) ? cKey + "=" + cVal RETURN