Pro*C generated code truncating TO_DATE results incorrectly

From: Cary Gerber <carygerber_at_yahoo.com>
Date: 15 Aug 2001 12:05:00 -0700
Message-ID: <5dac3ab3.0108151105.eddb658_at_posting.google.com>



We are moving from Informix to Oracle, and one of the many things I liked about Informix was the ease of manipulating date/time values in C. I looked around and found the trick of subtracting a date from 1-1-1970 to get number of minutes or seconds as a base reference value. However, I am getting very strange results when SQL statements involving TO_DATE (xxx) * 1440 into long host variables. We opened a case (#1757282.999) and was told that this was a C-issue and not an oracle issue. Please review the following data that was sent to Oracle and show me where this is a C issue versus a Pro*C or server issue.

It is not a problem with C-conversion to integer (long). It is a problem with
whatever PRO*C is generating. I have changed the query to return the same
value 3 times, once into different data types of C. I further do a C- conversion of a float to integer and do not get the same integer value that
the query returns into my int host variable. The float values have no residual fractional parts, however selecting into a long returns one less than the integer equivalents of the doubles. If you change this to seconds, you still get an error of 1.

Seconds without Round -> 16612342.000000, 16612342.000000, 16612341 ( returned from query into long host variable) C conversion to int -> 16612342 (same variable, just assigned the int. truncated value from the double float above) Seconds with Round -> 16612342.000000, 16612342.000000, 16612342 C conversion to int -> 16612342

/***** INCLUDES HERE ******/
int main(int argc, char *argv[])
{

    int      count = 0;
    int      ret = 0;
         
    EXEC SQL begin declare section;
        char        connect[16];
        EVENT_DS    one_evt;

        /**** TEST ****/
        double dsecs_since_70;
        float  fsecs_since_70;
        long   isecs_since_70;

    EXEC SQL end declare section;

        /****** CONNECT HERE *****/     EXEC SQL set transaction isolation level read committed;     if(!SQLOK()) exit(1);

    /***** TEST *****/
    exec sql select

        (TO_DATE('02-08-2001 08:22:00','DD-MM-YYYY hh24:mi:ss') - TO_DATE('01-
01-1970 00:00:00','DD-MM-YYYY hh24:mi:ss')) * 1440,

        (TO_DATE('02-08-2001 08:22:00','DD-MM-YYYY hh24:mi:ss') - TO_DATE('01-
01-1970 00:00:00','DD-MM-YYYY hh24:mi:ss')) * 1440,

        (TO_DATE('02-08-2001 08:22:00','DD-MM-YYYY hh24:mi:ss') - TO_DATE('01-
01-1970 00:00:00','DD-MM-YYYY hh24:mi:ss')) * 1440

        into :dsecs_since_70, :fsecs_since_70, :isecs_since_70
        from DUAL;

    if (!SQLOK()) exit(1);

    printf("Seconds without Round -> %lf, %f, %ld\n", dsecs_since_70, fsecs_since_70, isecs_since_70);

    isecs_since_70 = (long)dsecs_since_70;     printf("C conversion to int -> %ld\n", isecs_since_70);

    exec sql select

        ROUND((TO_DATE('02-08-2001 08:22:00','DD-MM-YYYY hh24:mi:ss')
-

TO_DATE('01-01-1970 00:00:00','DD-MM-YYYY hh24:mi:ss')) * 1440),

        ROUND((TO_DATE('02-08-2001 08:22:00','DD-MM-YYYY hh24:mi:ss')
-

TO_DATE('01-01-1970 00:00:00','DD-MM-YYYY hh24:mi:ss')) * 1440),

        ROUND((TO_DATE('02-08-2001 08:22:00','DD-MM-YYYY hh24:mi:ss')
-

TO_DATE('01-01-1970 00:00:00','DD-MM-YYYY hh24:mi:ss')) * 1440)

        into :dsecs_since_70, :fsecs_since_70, :isecs_since_70
        from DUAL;

    if (!SQLOK()) exit(1);

    printf("Seconds with Round -> %lf, %f, %ld\n", dsecs_since_70, fsecs_since_70, isecs_since_70);

    isecs_since_70 = (long)dsecs_since_70;     printf("C conversion to int -> %ld\n", isecs_since_70); } Received on Wed Aug 15 2001 - 21:05:00 CEST

Original text of this message