Skip to content

Commit 029d794

Browse files
authored
Enable DATE conversions (#115)
* rename meta type for date/time/timestamp - change to METATYPE_DATE_TIME after ES/SQL's timestamp data type renaming to DATETIME * s/parse_datetime/parse_date_time_ts/ - rename function that parses date/time/timestamp * add a resultset / page counter - add a page counter to track how many pages have been fetched from ES * update advertized supported scalars - current day has been added * enable DATE conversion - allow the new DATE type be converted to timestamp and date structs.
1 parent 9447c43 commit 029d794

File tree

6 files changed

+46
-33
lines changed

6 files changed

+46
-33
lines changed

driver/convert.c

Lines changed: 23 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -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) {

driver/defs.h

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -273,9 +273,8 @@
273273
* Timedate functions support:
274274
* - supported: DAYNAME, DAYOFMONTH, DAYOFWEEK, DAYOFYEAR, EXTRACT, HOUR,
275275
* MINUTE, MONTH, MONTHNAME, QUARTER, SECOND, WEEK, YEAR, NOW,
276-
* CURRENT_TIMESTAMP;
277-
* - not supported: CURRENT_DATE, CURRENT_TIME, CURDATE,
278-
* CURTIME, TIMESTAMPADD, TIMESTAMPDIFF.
276+
* CURRENT_TIMESTAMP, CURRENT_DATE, CURDATE;
277+
* - not supported: CURRENT_TIME, CURTIME, TIMESTAMPADD, TIMESTAMPDIFF.
279278
*/
280279
#define ESODBC_TIMEDATE_FUNCTIONS (0LU | \
281280
SQL_FN_TD_DAYNAME | SQL_FN_TD_DAYOFMONTH | SQL_FN_TD_DAYOFWEEK | \

driver/handles.c

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1963,7 +1963,7 @@ static void set_defaults_from_meta_type(esodbc_rec_st *rec)
19631963
rec->length = ESODBC_DEF_STRING_LENGTH;
19641964
rec->precision = ESODBC_DEF_STRING_PRECISION;
19651965
break;
1966-
case METATYPE_DATETIME:
1966+
case METATYPE_DATE_TIME:
19671967
if (rec->datetime_interval_code == SQL_CODE_DATE ||
19681968
rec->datetime_interval_code == SQL_CODE_TIME) {
19691969
rec->precision = ESODBC_DEF_DATETIME_PRECISION;
@@ -2048,7 +2048,7 @@ static esodbc_metatype_et sqltype_to_meta(SQLSMALLINT concise)
20482048
case SQL_TYPE_TIMESTAMP:
20492049
// case SQL_TYPE_UTCDATETIME:
20502050
// case SQL_TYPE_UTCTIME:
2051-
return METATYPE_DATETIME;
2051+
return METATYPE_DATE_TIME;
20522052

20532053
/* interval (note: SQL_INTERVAL is verbose, not concise) */
20542054
case SQL_INTERVAL_MONTH:
@@ -2134,7 +2134,7 @@ static esodbc_metatype_et sqlctype_to_meta(SQLSMALLINT concise)
21342134
case SQL_C_TYPE_TIMESTAMP:
21352135
// case SQL_C_TYPE_TIME_WITH_TIMEZONE:
21362136
// case SQL_C_TYPE_TIMESTAMP_WITH_TIMEZONE:
2137-
return METATYPE_DATETIME;
2137+
return METATYPE_DATE_TIME;
21382138

21392139
/* interval */
21402140
case SQL_C_INTERVAL_DAY:
@@ -2216,7 +2216,7 @@ static BOOL consistency_check(esodbc_rec_st *rec)
22162216

22172217
/* check SQL_DESC_PRECISION field */
22182218
/* "a time or timestamp data type" */
2219-
case METATYPE_DATETIME:
2219+
case METATYPE_DATE_TIME:
22202220
if (rec->concise_type == SQL_TYPE_DATE) {
22212221
break;
22222222
}
@@ -2233,7 +2233,7 @@ static BOOL consistency_check(esodbc_rec_st *rec)
22332233
return FALSE;
22342234
}
22352235
}
2236-
if (rec->meta_type == METATYPE_DATETIME) {
2236+
if (rec->meta_type == METATYPE_DATE_TIME) {
22372237
break;
22382238
}
22392239
/* check SQL_DESC_DATETIME_INTERVAL_PRECISION */

driver/handles.h

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -64,7 +64,7 @@ typedef enum {
6464
METATYPE_FLOAT_NUMERIC,
6565
METATYPE_STRING,
6666
METATYPE_BIN,
67-
METATYPE_DATETIME,
67+
METATYPE_DATE_TIME,
6868
METATYPE_INTERVAL_WSEC,
6969
METATYPE_INTERVAL_WOSEC,
7070
METATYPE_BIT,
@@ -335,8 +335,10 @@ typedef struct struct_stmt {
335335
* returning to the application." */
336336
SQLULEN query_timeout;
337337

338-
/* [current] result set (= one answer from ES/SQL; can contain a cursor) */
338+
/* [current] result set (= one page from ES/SQL; can contain a cursor) */
339339
resultset_st rset;
340+
/* count of result sets fetched */
341+
size_t nset;
340342
/* total count of fetched rows for one statement (sum(resultset.nrows)) */
341343
size_t tf_rows;
342344
/* SQL data types conversion to SQL C compatibility (IRD.SQL -> ARD.C) */

driver/log.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -44,7 +44,7 @@
4444

4545
/* macro for logging of Xstr_st objects */
4646
#define LWSTR(_wptr) (int)(_wptr)->cnt, (_wptr)->str
47-
#define LCSTR(_wptr) (int)(_wptr)->cnt, (_wptr)->str
47+
#define LCSTR(_cptr) (int)(_cptr)->cnt, (_cptr)->str
4848

4949
#ifdef UNICODE
5050
# define LTSTR LWSTR

driver/queries.c

Lines changed: 11 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -79,7 +79,7 @@ static void set_col_size(esodbc_rec_st *rec)
7979
case METATYPE_BIN:
8080
/* "The defined or maximum length in bytes of the column " */
8181
/* no break */
82-
case METATYPE_DATETIME:
82+
case METATYPE_DATE_TIME:
8383
/* "number of characters in the character representation" */
8484
rec->length = rec->es_type->column_size;
8585
break;
@@ -281,6 +281,7 @@ SQLRETURN TEST_API attach_answer(esodbc_stmt_st *stmt, char *buff, size_t blen)
281281
stmt->rset.nrows = 0;
282282
#endif /*0*/
283283
} else {
284+
stmt->nset ++;
284285
/* the cast is made safe by the decoding format indicator for array */
285286
stmt->rset.nrows = (size_t)UJLengthArray(rows);
286287
stmt->tf_rows += stmt->rset.nrows;
@@ -934,8 +935,8 @@ SQLRETURN EsSQLFetch(SQLHSTMT StatementHandle)
934935
DBGH(stmt, "ES/app data/buffer types found compatible.");
935936
}
936937

937-
DBGH(stmt, "(`" LCPDL "`); cursor @ %zd / %zd.", LCSTR(&stmt->u8sql),
938-
stmt->rset.vrows, stmt->rset.nrows);
938+
DBGH(stmt, "cursor @ row %zu / %zu in page #%zu. (SQL: `" LCPDL "`).",
939+
stmt->rset.vrows, stmt->rset.nrows, stmt->nset, LCSTR(&stmt->u8sql));
939940

940941
/* reset SQLGetData state, to reset fetch position */
941942
STMT_GD_RESET(stmt);
@@ -1513,7 +1514,7 @@ static esodbc_estype_st *match_es_type(esodbc_rec_st *arec,
15131514
case METATYPE_BIN:
15141515
/* SQL_VARBINARY == -3 == ES/SQL BINARY */
15151516
return lookup_es_type(dbc, SQL_VARBINARY, /*no prec*/0);
1516-
case METATYPE_DATETIME:
1517+
case METATYPE_DATE_TIME:
15171518
assert(irec->concise_type == SQL_TYPE_DATE ||
15181519
irec->concise_type == SQL_TYPE_TIME);
15191520
return lookup_es_type(dbc, SQL_TYPE_TIMESTAMP, /*no prec*/0);
@@ -2059,6 +2060,9 @@ SQLRETURN TEST_API serialize_statement(esodbc_stmt_st *stmt, cstr_st *buff)
20592060
memcpy(body + pos, dbc->fetch.str, dbc->fetch.slen);
20602061
pos += dbc->fetch.slen;
20612062
}
2063+
2064+
/* reset the page counter when the params change */
2065+
stmt->nset = 0;
20622066
}
20632067
/* "mode": */
20642068
memcpy(body + pos, JSON_KEY_VAL_MODE, sizeof(JSON_KEY_VAL_MODE) - 1);
@@ -2176,7 +2180,7 @@ SQLRETURN EsSQLExecDirectW
21762180
if (SQL_SUCCEEDED(ret)) {
21772181
ret = EsSQLExecute(stmt);
21782182
}
2179-
#ifndef NDEBUG
2183+
#ifdef NDEBUG
21802184
/* no reason to keep it (it can't be re-executed), except for debugging */
21812185
detach_sql(stmt);
21822186
#endif /* NDEBUG */
@@ -2235,7 +2239,7 @@ static inline SQLULEN get_col_size(esodbc_rec_st *rec)
22352239

22362240
case METATYPE_STRING:
22372241
case METATYPE_BIN:
2238-
case METATYPE_DATETIME:
2242+
case METATYPE_DATE_TIME:
22392243
case METATYPE_INTERVAL_WSEC:
22402244
case METATYPE_INTERVAL_WOSEC:
22412245
case METATYPE_BIT:
@@ -2255,7 +2259,7 @@ static inline SQLSMALLINT get_col_decdigits(esodbc_rec_st *rec)
22552259
assert(DESC_TYPE_IS_IMPLEMENTATION(rec->desc->type));
22562260

22572261
switch (rec->meta_type) {
2258-
case METATYPE_DATETIME:
2262+
case METATYPE_DATE_TIME:
22592263
case METATYPE_INTERVAL_WSEC:
22602264
return ESODBC_MAX_SEC_PRECISION;
22612265

0 commit comments

Comments
 (0)