0

I am working with C programming language and using Postgres database to insert records. One of the columns of the table in the database is of type timestamp. The data I am getting in the C program is of type int64_t and I need to pass this value as a parameter in the INSERT statement like shown below. In order to do that, I tried to convert the int64_t value to a string using sprintf().

 char str[21];
 sprintf(str, "%" PRId64 "\n", someTimeReceived inTheProgram);  
 const char * const paramValues[1] = { str };

 PGresult *res =     res = PQexecParams(
            conn,
            "INSERT INTO dummy VALUES(1,to_timestamp($1)::timestamp)",

            1,            /* one parameter */
            NULL,
            paramValues,
            NULL,        /* parameter lengths are not required for strings */
            NULL,        /* all parameters are in text format */
            0            /* result shall be in text format */
        );

But on using sprintf(), some garbage value are being inserted at the end of string. For example if the received int64_t value is 132408394771256230 then sprintf() is converting it to 132408394771256230\n\0\003. Because of the extra garbage values appended at the end of string, the program fails to insert the given value and then terminates.

halfer
  • 19,824
  • 17
  • 99
  • 186
A Beginner
  • 393
  • 2
  • 12

1 Answers1

2

if the received int64_t value is 132408394771256230 then sprintf() is converting it to 132408394771256230\n\0\003

no, sprintf only writes 132408394771256230\n\0 into str and let the rest of the array unchanged, the character of code 3 was present before the call of sprintf (the array is not initialized) but of course it can be anything else.

Because of the extra garbage values appended at the end of string, the program fails to insert the given value and then terminates.

no again, PQexecParams manages params as an array of strings (one string in your case) following the convention a string is ended by a null character, PQexecParams does not read/care about what there is after the null character, and does know even about the 'envelop' of your string (an array of 21 characters in your case).

Your problem probably comes because of the undesirable newline in your string, producing the command to be the string

INSERT INTO dummy VALUES(1,to_timestamp(132408394771256230\n)::timestamp)

just remove \n in the format of your sprintf.


Supposing it is needed to have the newline your array must be sized 22 rather than 21 to manage negative value without an undefined behavior writing out of the array.


...some garbage value

you certainly see the null character and the byte after because you use a debugger and that debugger knows str is sized 21 and when you ask to see the value of str the debugger consider str as an array of characters rather than a string. If you ask your debugger to show (char*) str it will consider str as a string and will not show the null character nor the character after.


[edit]

The function request the date-time as a string yyyy-mm-dd hh:mm:ss rather than your big number being an ua_datetime

To convert an ua_datetime to a the expected string use (see documentation) :

nt ua_datetime_snprintf (char * dst, size_t size, const ua_datetime * dt)   

the result is a string YYYY-MM-DDThh:mm:ss.nnnZ so after just replace the last dot by a null character and 'T' by a space (supposing a 'T' is really produced, try and adapt)

An other way is to use :

time_t ua_datetime_to_time_t(const ua_datetime * dt)    

then to make your string with standard function from the time_t

Anyway you have to understand you loose a lot of precision, ua_datetime are in 100 nanosecond while *postgress timestamp are in second only

bruno
  • 32,421
  • 7
  • 25
  • 37
  • I removed `\n` but still no luck in inserting the record in the database and the program is getting terminated. – A Beginner Aug 02 '20 at 14:55
  • @ABeginner do you come back from *PQexecParams* ? if yes what it returns ? Can you run your program using *valgrind* (compile with debug first) ? are you sure about *timestamp* representation as a big number rather than *yyyy-mm-dd hh:mm:ss* for instance ? – bruno Aug 02 '20 at 15:11
  • Do you mean what status code it returns? If so, then it returns 7. – A Beginner Aug 02 '20 at 15:17
  • @ABeginner and what 7 means ? If *PQexecParams* returns where do you have your crash ? Again can you use *valgrind* ? – bruno Aug 02 '20 at 15:18
  • It stands for `PGRES_FATAL_ERROR` which implies that the query execution has failed. – A Beginner Aug 02 '20 at 15:19
  • ok, so can you try with a typestamp having the form *yyyy-mm-dd hh:mm:ss* in the string whatever the values just to try ? – bruno Aug 02 '20 at 15:20
  • Let us [continue this discussion in chat](https://chat.stackoverflow.com/rooms/219094/discussion-between-a-beginner-and-bruno). – A Beginner Aug 02 '20 at 15:43