WDataValue::SetCHAR()
TIMESTAMP Parsing Bug
If the datavalue is set to SQL_C_TIMESTAMP, SetCHAR fails and returns false, if the fraction has more than 4 digits.
The code further down fixes the bug.
The bug exists in Power 2.5 beta, 2.1 and probably in all previous versions.
BOOL DVFromString( const char * str, DATE_STRUCT * d, TIME_STRUCT * t, TIMESTAMP_STRUCT *ts )
{
#undef MAX_VALUES
#define MAX_VALUES 7
BOOL ok = TRUE;
const char * s;
const char * e;
WULong val;
WULong values[MAX_VALUES];
int i;
int leading = 0, numchars = 0;
memset( values, 0, sizeof( values ) );
s = str;
i = 0;
val = strtoul( s, (char**)&e, 10 );
if( s != e )
{
while( i < MAX_VALUES && *s != '\0' )
{
values[i++] = val;
while( isspace( *e ) )
++e;
if( *e == '\0' )
break;
if( !isdigit( *e ) )
++e;
while( isspace( *e ) )
++e;
if( *e == '\0' )
break;
s = e;
// Special case: for timestamps the last bit is a
// fractional number so we need to count # of leading
// zeros...
if( i == ( MAX_VALUES - 1 ) )
{
while( *s == '0' )
{
++s;
++leading;
}
val = 0;
numchars = 0;
if( leading < 9 )
{
e = s;
while( ( numchars + leading ) < 9 && isdigit( *e ) )
{
val *= 10;
val += ( *e - '0' );
++e;
++numchars;
}
while( isdigit( *e ) )
++e;
}
}
else
{
val = strtoul( s, (char**)&e, 10 );
}
}
}
// Copy values...
if( d )
{
d->year = (SWORD) values[0];
d->month = (UWORD) values[1];
d->day = (UWORD) values[2];
if( i != 3 ) ok = FALSE;
if( d->year < 0 || d->year > 9999 ) ok = FALSE;
if( d->month < 1 || d->month > 12 ) ok = FALSE;
if( d->day < 1 || d->day > 31 ) ok = FALSE;
}
else if( t )
{
t->hour = (UWORD) values[0];
t->minute = (UWORD) values[1];
t->second = (UWORD) values[2];
if( i != 2 && i != 3 ) ok = FALSE;
if( t->hour > 23 ) ok = FALSE;
if( t->minute > 59 ) ok = FALSE;
if( t->second > 59 ) ok = FALSE;
}
else if( ts )
{
ts->year = (SWORD) values[0];
ts->month = (UWORD) values[1];
ts->day = (UWORD) values[2];
ts->hour = (UWORD) values[3];
ts->minute = (UWORD) values[4];
ts->second = (UWORD) values[5];
if( i > 6 && leading < 9 )
{
while( isspace( *e ) )
++e;
if( *e != '\0' )
ok = FALSE; // extra stuff at end...
else
{
for( int i = 0; i < ( 9 - leading - numchars ); ++i ){
values[6] *= 10;
}
}
}
else
values[6] = 0;
ts->fraction = (UDWORD) values[6];
if( i < 5 ) ok = FALSE;
if( ts->year < 0 || ts->year > 9999 ) ok = FALSE;
if( ts->month < 1 || ts->month > 12 ) ok = FALSE;
if( ts->day < 1 || ts->day > 31 ) ok = FALSE;
if( ts->hour > 23 ) ok = FALSE;
if( ts->minute > 59 ) ok = FALSE;
if( ts->second > 59 ) ok = FALSE;
if( ts->fraction > 999999999 ) ok = FALSE;
}
else
ok = FALSE;
return ok;
}