Subject: Bug: PGTYPEStimestamp_from_asc() in ECPG pgtypelib

From: "Ryo Matsumura (Fujitsu)" <[email-masked]>
Date: Thu, 9 May 2024 10:54:31 +0000

Hi hackers,

I detected two problems about ECPG.
I show my opinion. Please comment.
If it's correct, I will prepare a patch.
Thank you.

1.
It is indefinite what PGTYPEStimestamp_from_asc() returns in error.
The following is written in document(36.6.8. Special Constants of pgtypeslib):
  A value of type timestamp representing an invalid time stamp.
  This is returned by the function PGTYPEStimestamp_from_asc on parse error.
  Note that due to the internal representation of the timestamp data type,
  PGTYPESInvalidTimestamp is also a valid timestamp at the same time.
  It is set to 1899-12-31 23:59:59. In order to detect errors,
  make sure that your application does not only test for PGTYPESInvalidTimestamp
  but also for errno != 0 after each call to PGTYPEStimestamp_from_asc.

However, PGTYPESInvalidTimestamp is not defined anywhere.
It no loger exists at REL6_2 that is the oldest branch.
At current implementation, PGTYPEStimestamp_from_asc returns -1.

So we must fix the document so that users write as follows:

  r = PGTYPEStimestamp_from_asc(.....);
  if (r < 0 || errno != 0)
    goto error;

2.
Regression test of pgtypelib is not robust (maybe incorrect).
Our test failed although there is no bug actually.

I think block2 and block3 should be swapped.

---[src/interfaces/ecpg/test/pgtypeslib/dt_test.pgc]---

  // block1 (my comment)
      ts1 = PGTYPEStimestamp_from_asc("96-02-29", NULL);
      text = PGTYPEStimestamp_to_asc(ts1);
      printf("timestamp_to_asc1: %s\n", text);
      PGTYPESchar_free(text);

  // block2
      ts1 = PGTYPEStimestamp_from_asc("1994-02-11 26:10:35", NULL);
      text = PGTYPEStimestamp_to_asc(ts1);
      printf("timestamp_to_asc3: %s\n", text);
      PGTYPESchar_free(text);

  // The following comment is for block1 clearly.
/*     abc-03:10:35-def-02/11/94-gh  */
/*      12345678901234567890123456789 */

  // block3
  // Maybe the following is for 'ts1' returned in block1.
  // In our environment, 'out' is indefinite because PGTYPEStimestamp_fmt_asc()
  // didn't complete and the area is not initialized.
      out = (char*) malloc(32);
      i = PGTYPEStimestamp_fmt_asc(&ts1, out, 31, "abc-%X-def-%x-ghi%%");
      printf("timestamp_fmt_asc: %d: %s\n", i, out);
      free(out);

------------------------------------

Best Regards
Ryo Matsumura

Best Regards
Ryo Matsumura