From 2f6fe337f74a77e7c044580f129048725a5463f2 Mon Sep 17 00:00:00 2001 From: David Declerck Date: Fri, 20 Dec 2024 18:01:48 +0100 Subject: [PATCH] Improve handling of partial keys --- libcob/ChangeLog | 5 +++ libcob/fileio.c | 12 ++++--- tests/testsuite.src/run_file.at | 60 +++++++++++++++++++++++++++++++++ 3 files changed, 72 insertions(+), 5 deletions(-) diff --git a/libcob/ChangeLog b/libcob/ChangeLog index 3f523717..e6f111a6 100644 --- a/libcob/ChangeLog +++ b/libcob/ChangeLog @@ -1,4 +1,9 @@ +2024-12-20 David Declerck + + * fileio.c (indexed_start_internal): improve handling of partial + keys, to ensure BDB always compares keys of identical length + 2024-12-18 David Declerck * string.c: fix a bug where the source of STRING/UNSTRING/INSPECT diff --git a/libcob/fileio.c b/libcob/fileio.c index df7cc89c..5e5aa223 100644 --- a/libcob/fileio.c +++ b/libcob/fileio.c @@ -793,7 +793,6 @@ bdb_setkey (cob_file *f, int idx) struct indexed_file *p = f->file; int len; - memset (p->savekey, 0, p->maxkeylen); len = bdb_savekey (f, p->savekey, f->record->data, idx); p->key.data = p->savekey; p->key.size = (cob_dbtsize_t) len; @@ -923,6 +922,9 @@ bdb_bt_compare (DB *db, const DBT *k1, const DBT *k2 { const unsigned char *col = (unsigned char *)DBT_GET_APP_DATA (k1); COB_UNUSED (db); +#if DB_VERSION_MAJOR >= 6 + locp = NULL; /* docs: must be set to NULL or corruption can occur ... */ +#endif #ifdef USE_BDB_KEYDIFF /* flag passed with CPPFLAGS */ return cob_cmp_strings (k1->data, k2->data, (size_t)k1->size, (size_t)k2->size, col); #else @@ -936,9 +938,6 @@ bdb_bt_compare (DB *db, const DBT *k1, const DBT *k2 cob_hard_failure (); } /* LCOV_EXCL_STOP */ -#if DB_VERSION_MAJOR >= 6 - locp = NULL; /* docs: must be set to NULL or corruption can occur ... */ -#endif return indexed_key_compare (k1->data, k2->data, k2->size, col); #endif /* USE_BDB_KEYDIFF */ } @@ -3909,7 +3908,10 @@ indexed_start_internal (cob_file *f, const int cond, cob_field *key, /* Search */ bdb_setkey (f, p->key_index); - p->key.size = (cob_dbtsize_t)partlen; /* may be partial key */ + if (partlen < fullkeylen) { + memset((char *)p->key.data + partlen, 0, fullkeylen - partlen); + } + /* The open cursor makes this function atomic */ if (p->key_index != 0) { p->db[0]->cursor (p->db[0], NULL, &p->cursor[0], 0); diff --git a/tests/testsuite.src/run_file.at b/tests/testsuite.src/run_file.at index 9dca167e..57c4eee8 100644 --- a/tests/testsuite.src/run_file.at +++ b/tests/testsuite.src/run_file.at @@ -3098,6 +3098,66 @@ rewriting key: 98651234 AT_CLEANUP +AT_SETUP([INDEXED START with partial key and collating sequence]) +AT_KEYWORDS([runfile READ WRITE START]) + +AT_SKIP_IF([test "$COB_HAS_ISAM" = "no"]) + +AT_DATA([prog.cob], [ + IDENTIFICATION DIVISION. + PROGRAM-ID. prog. + ENVIRONMENT DIVISION. + INPUT-OUTPUT SECTION. + FILE-CONTROL. + SELECT F-DATA ASSIGN TO EXTERNAL fdata + ORGANIZATION INDEXED + ACCESS MODE DYNAMIC + RECORD KEY R-KEY + FILE STATUS F-STATUS. + DATA DIVISION. + FILE SECTION. + FD F-DATA. + 01 R-DATA. + 05 R-KEY. + 10 R-SUBKEY-1 PIC X(3). + 10 R-SUBKEY-2 PIC X(2). + 05 R-NUM PIC 99. + WORKING-STORAGE SECTION. + 01 F-STATUS PIC X(2) VALUE SPACE. + PROCEDURE DIVISION. + OPEN OUTPUT F-DATA. + MOVE "ABC12" TO R-KEY. + MOVE 1 TO R-NUM. + WRITE R-DATA. + MOVE "DEF34" TO R-KEY. + MOVE 2 TO R-NUM. + WRITE R-DATA. + MOVE "GHI56" TO R-KEY. + MOVE 3 TO R-NUM. + WRITE R-DATA. + CLOSE F-DATA. + OPEN INPUT F-DATA. + MOVE SPACES TO R-KEY. + MOVE "DEF" TO R-SUBKEY-1. + START F-DATA KEY >= R-SUBKEY-1. + DISPLAY "START STATUS: " F-STATUS. + READ F-DATA NEXT. + DISPLAY "READ STATUS: " F-STATUS. + DISPLAY "READ " R-KEY ", " R-NUM. + CLOSE F-DATA. + STOP RUN. +]) + +AT_CHECK([$COMPILE -fdefault-file-colseq=EBCDIC prog.cob], [0], [], []) +AT_CHECK([$COBCRUN_DIRECT ./prog], [0], +[START STATUS: 00 +READ STATUS: 00 +READ DEF34, 02 +], []) + +AT_CLEANUP + + AT_SETUP([WRITE + REWRITE FILE name]) AT_KEYWORDS([runfile RELATIVE COB_SYNC])