@@ -256,7 +256,7 @@ SQLRETURN set_param_decdigits(esodbc_rec_st *irec,
256256 * SQL_INTERVAL_DAY_TO_SECOND, SQL_INTERVAL_HOUR_TO_SECOND, or
257257 * SQL_INTERVAL_MINUTE_TO_SECOND, the SQL_DESC_PRECISION field of the
258258 * IPD is set to DecimalDigits." */
259- case METATYPE_DATETIME :
259+ case METATYPE_DATE_TIME :
260260 if (irec -> concise_type == SQL_TYPE_DATE ) {
261261 break ;
262262 }
@@ -293,7 +293,7 @@ SQLSMALLINT get_param_decdigits(esodbc_rec_st *irec)
293293 assert (irec -> desc -> type == DESC_TYPE_IPD );
294294
295295 switch (irec -> meta_type ) {
296- case METATYPE_DATETIME :
296+ case METATYPE_DATE_TIME :
297297 if (irec -> concise_type == SQL_TYPE_DATE ) {
298298 break ;
299299 }
@@ -327,7 +327,7 @@ SQLRETURN set_param_size(esodbc_rec_st *irec,
327327 * IPD is set to the value of [s]ize." */
328328 case METATYPE_STRING :
329329 case METATYPE_BIN :
330- case METATYPE_DATETIME :
330+ case METATYPE_DATE_TIME :
331331 case METATYPE_INTERVAL_WSEC :
332332 case METATYPE_INTERVAL_WOSEC :
333333 return EsSQLSetDescFieldW (irec -> desc , param_no , SQL_DESC_LENGTH ,
@@ -363,7 +363,7 @@ SQLULEN get_param_size(esodbc_rec_st *irec)
363363 switch (irec -> meta_type ) {
364364 case METATYPE_STRING :
365365 case METATYPE_BIN :
366- case METATYPE_DATETIME :
366+ case METATYPE_DATE_TIME :
367367 case METATYPE_INTERVAL_WSEC :
368368 case METATYPE_INTERVAL_WOSEC :
369369 return irec -> length ;
@@ -1466,7 +1466,7 @@ static SQLRETURN wstr_to_wstr(esodbc_rec_st *arec, esodbc_rec_st *irec,
14661466 return transfer_xstr0 (arec , irec , & xsrc , data_ptr , octet_len_ptr );
14671467}
14681468
1469- /* Converts an xstr to a TS.
1469+ /* Converts an ISO 8601-formated xstr to a TS.
14701470 * xstr needs to be trimmed to exact data (no padding, no 0-term counted).
14711471 * If ts_buff is non-NULL, the xstr will be copied (possibly W-to-C converted)
14721472 * into it. */
@@ -1532,8 +1532,9 @@ static BOOL xstr_to_timestamp_struct(esodbc_stmt_st *stmt, xstr_st *xstr,
15321532 return TRUE;
15331533}
15341534
1535-
1536- static BOOL parse_timedate (esodbc_stmt_st * stmt , xstr_st * xstr ,
1535+ /* Analyzes the received string as time/date/timedate(timestamp) and parses it
1536+ * into received 'tss' struct, indicating detected format in 'format'. */
1537+ static BOOL parse_date_time_ts (esodbc_stmt_st * stmt , xstr_st * xstr ,
15371538 TIMESTAMP_STRUCT * tss , SQLSMALLINT * format , cstr_st * ts_buff )
15381539{
15391540 /* template buffer: date or time values will be copied in place and
@@ -1641,15 +1642,16 @@ static SQLRETURN wstr_to_timestamp(esodbc_rec_st *arec, esodbc_rec_st *irec,
16411642
16421643 switch (irec -> concise_type ) {
16431644 case SQL_TYPE_TIMESTAMP :
1645+ case SQL_TYPE_DATE : /* ES/SQL passes date as DATETIME */
16441646 if (! xstr_to_timestamp_struct (stmt , & xstr , tss , NULL )) {
16451647 RET_HDIAGS (stmt , SQL_STATE_22018 );
16461648 }
16471649 if (format ) {
1648- * format = SQL_TYPE_TIMESTAMP ;
1650+ * format = irec -> concise_type ;
16491651 }
16501652 break ;
16511653 case SQL_VARCHAR :
1652- if (! parse_timedate (stmt , & xstr , tss , format , NULL )) {
1654+ if (! parse_date_time_ts (stmt , & xstr , tss , format , NULL )) {
16531655 RET_HDIAGS (stmt , SQL_STATE_22018 );
16541656 }
16551657 break ;
@@ -1658,7 +1660,6 @@ static SQLRETURN wstr_to_timestamp(esodbc_rec_st *arec, esodbc_rec_st *irec,
16581660 case SQL_LONGVARCHAR :
16591661 case SQL_WCHAR :
16601662 case SQL_WLONGVARCHAR :
1661- case SQL_TYPE_DATE :
16621663 case SQL_TYPE_TIME :
16631664 BUGH (stmt , "unexpected (but permitted) SQL type." );
16641665 RET_HDIAGS (stmt , SQL_STATE_HY004 );
@@ -1685,6 +1686,7 @@ static SQLRETURN wstr_to_date(esodbc_rec_st *arec, esodbc_rec_st *irec,
16851686 TIMESTAMP_STRUCT tss ;
16861687 SQLRETURN ret ;
16871688 SQLSMALLINT fmt ;
1689+ esodbc_state_et state ;
16881690
16891691 if (octet_len_ptr ) {
16901692 * octet_len_ptr = sizeof (* ds );
@@ -1703,8 +1705,15 @@ static SQLRETURN wstr_to_date(esodbc_rec_st *arec, esodbc_rec_st *irec,
17031705 ds -> month = tss .month ;
17041706 ds -> day = tss .day ;
17051707 if (tss .hour || tss .minute || tss .second || tss .fraction ) {
1706- /* value's truncated */
1707- RET_HDIAGS (stmt , SQL_STATE_01S07 );
1708+ if (fmt == SQL_TYPE_TIMESTAMP ) {
1709+ /* value's truncated */
1710+ state = SQL_STATE_01S07 ;
1711+ } else {
1712+ ERRH (stmt , "DATE type value contains non-zero time "
1713+ "components: `" LWPDL "`." , chars_0 - 1 , wstr );
1714+ state = SQL_STATE_22018 ;
1715+ }
1716+ RET_HDIAGS (stmt , state );
17081717 }
17091718 } else {
17101719 DBGH (stmt , "REC@0x%p, NULL data_ptr" , arec );
@@ -2796,8 +2805,7 @@ SQLRETURN sql2c_string(esodbc_rec_st *arec, esodbc_rec_st *irec,
27962805 if (irec->type != SQL_INTERVAL) { \
27972806 break; \
27982807 } \
2799- ret = interval_iso8601_to_sql(arec, irec, wstr, &chars_0, \
2800- buff); \
2808+ ret = interval_iso8601_to_sql(arec, irec, wstr, &chars_0, buff); \
28012809 if (! SQL_SUCCEEDED(ret)) { \
28022810 return ret; \
28032811 } \
@@ -3636,7 +3644,7 @@ static SQLRETURN convert_str_to_timestamp(esodbc_stmt_st *stmt,
36363644 assert (dest );
36373645 ts_buff .str = dest ;
36383646 ts_buff .cnt = sizeof (ESODBC_ISO8601_TEMPLATE ) - 1 ;
3639- if (! parse_timedate (stmt , & xstr , & tss , & format , & ts_buff )) {
3647+ if (! parse_date_time_ts (stmt , & xstr , & tss , & format , & ts_buff )) {
36403648 ERRH (stmt , "failed to parse input as Time/Date/Timestamp" );
36413649 RET_HDIAGS (stmt , SQL_STATE_22008 );
36423650 } else if (format == SQL_TYPE_TIME ) {
0 commit comments