Skip to content

Commit

Permalink
Enable DATE conversions (#115)
Browse files Browse the repository at this point in the history
* 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.

(cherry picked from commit 029d794)
  • Loading branch information
bpintea committed Feb 20, 2019
1 parent 7f948b4 commit ffc2338
Show file tree
Hide file tree
Showing 6 changed files with 46 additions and 33 deletions.
38 changes: 23 additions & 15 deletions driver/convert.c
Original file line number Diff line number Diff line change
Expand Up @@ -256,7 +256,7 @@ SQLRETURN set_param_decdigits(esodbc_rec_st *irec,
* SQL_INTERVAL_DAY_TO_SECOND, SQL_INTERVAL_HOUR_TO_SECOND, or
* SQL_INTERVAL_MINUTE_TO_SECOND, the SQL_DESC_PRECISION field of the
* IPD is set to DecimalDigits." */
case METATYPE_DATETIME:
case METATYPE_DATE_TIME:
if (irec->concise_type == SQL_TYPE_DATE) {
break;
}
Expand Down Expand Up @@ -293,7 +293,7 @@ SQLSMALLINT get_param_decdigits(esodbc_rec_st *irec)
assert(irec->desc->type == DESC_TYPE_IPD);

switch(irec->meta_type) {
case METATYPE_DATETIME:
case METATYPE_DATE_TIME:
if (irec->concise_type == SQL_TYPE_DATE) {
break;
}
Expand Down Expand Up @@ -327,7 +327,7 @@ SQLRETURN set_param_size(esodbc_rec_st *irec,
* IPD is set to the value of [s]ize." */
case METATYPE_STRING:
case METATYPE_BIN:
case METATYPE_DATETIME:
case METATYPE_DATE_TIME:
case METATYPE_INTERVAL_WSEC:
case METATYPE_INTERVAL_WOSEC:
return EsSQLSetDescFieldW(irec->desc, param_no, SQL_DESC_LENGTH,
Expand Down Expand Up @@ -363,7 +363,7 @@ SQLULEN get_param_size(esodbc_rec_st *irec)
switch (irec->meta_type) {
case METATYPE_STRING:
case METATYPE_BIN:
case METATYPE_DATETIME:
case METATYPE_DATE_TIME:
case METATYPE_INTERVAL_WSEC:
case METATYPE_INTERVAL_WOSEC:
return irec->length;
Expand Down Expand Up @@ -1466,7 +1466,7 @@ static SQLRETURN wstr_to_wstr(esodbc_rec_st *arec, esodbc_rec_st *irec,
return transfer_xstr0(arec, irec, &xsrc, data_ptr, octet_len_ptr);
}

/* Converts an xstr to a TS.
/* Converts an ISO 8601-formated xstr to a TS.
* xstr needs to be trimmed to exact data (no padding, no 0-term counted).
* If ts_buff is non-NULL, the xstr will be copied (possibly W-to-C converted)
* into it. */
Expand Down Expand Up @@ -1532,8 +1532,9 @@ static BOOL xstr_to_timestamp_struct(esodbc_stmt_st *stmt, xstr_st *xstr,
return TRUE;
}


static BOOL parse_timedate(esodbc_stmt_st *stmt, xstr_st *xstr,
/* Analyzes the received string as time/date/timedate(timestamp) and parses it
* into received 'tss' struct, indicating detected format in 'format'. */
static BOOL parse_date_time_ts(esodbc_stmt_st *stmt, xstr_st *xstr,
TIMESTAMP_STRUCT *tss, SQLSMALLINT *format, cstr_st *ts_buff)
{
/* template buffer: date or time values will be copied in place and
Expand Down Expand Up @@ -1641,15 +1642,16 @@ static SQLRETURN wstr_to_timestamp(esodbc_rec_st *arec, esodbc_rec_st *irec,

switch (irec->concise_type) {
case SQL_TYPE_TIMESTAMP:
case SQL_TYPE_DATE: /* ES/SQL passes date as DATETIME */
if (! xstr_to_timestamp_struct(stmt, &xstr, tss, NULL)) {
RET_HDIAGS(stmt, SQL_STATE_22018);
}
if (format) {
*format = SQL_TYPE_TIMESTAMP;
*format = irec->concise_type;
}
break;
case SQL_VARCHAR:
if (! parse_timedate(stmt, &xstr, tss, format, NULL)) {
if (! parse_date_time_ts(stmt, &xstr, tss, format, NULL)) {
RET_HDIAGS(stmt, SQL_STATE_22018);
}
break;
Expand All @@ -1658,7 +1660,6 @@ static SQLRETURN wstr_to_timestamp(esodbc_rec_st *arec, esodbc_rec_st *irec,
case SQL_LONGVARCHAR:
case SQL_WCHAR:
case SQL_WLONGVARCHAR:
case SQL_TYPE_DATE:
case SQL_TYPE_TIME:
BUGH(stmt, "unexpected (but permitted) SQL type.");
RET_HDIAGS(stmt, SQL_STATE_HY004);
Expand All @@ -1685,6 +1686,7 @@ static SQLRETURN wstr_to_date(esodbc_rec_st *arec, esodbc_rec_st *irec,
TIMESTAMP_STRUCT tss;
SQLRETURN ret;
SQLSMALLINT fmt;
esodbc_state_et state;

if (octet_len_ptr) {
*octet_len_ptr = sizeof(*ds);
Expand All @@ -1703,8 +1705,15 @@ static SQLRETURN wstr_to_date(esodbc_rec_st *arec, esodbc_rec_st *irec,
ds->month = tss.month;
ds->day = tss.day;
if (tss.hour || tss.minute || tss.second || tss.fraction) {
/* value's truncated */
RET_HDIAGS(stmt, SQL_STATE_01S07);
if (fmt == SQL_TYPE_TIMESTAMP) {
/* value's truncated */
state = SQL_STATE_01S07;
} else {
ERRH(stmt, "DATE type value contains non-zero time "
"components: `" LWPDL "`.", chars_0 - 1, wstr);
state = SQL_STATE_22018;
}
RET_HDIAGS(stmt, state);
}
} else {
DBGH(stmt, "REC@0x%p, NULL data_ptr", arec);
Expand Down Expand Up @@ -2796,8 +2805,7 @@ SQLRETURN sql2c_string(esodbc_rec_st *arec, esodbc_rec_st *irec,
if (irec->type != SQL_INTERVAL) { \
break; \
} \
ret = interval_iso8601_to_sql(arec, irec, wstr, &chars_0, \
buff); \
ret = interval_iso8601_to_sql(arec, irec, wstr, &chars_0, buff); \
if (! SQL_SUCCEEDED(ret)) { \
return ret; \
} \
Expand Down Expand Up @@ -3636,7 +3644,7 @@ static SQLRETURN convert_str_to_timestamp(esodbc_stmt_st *stmt,
assert(dest);
ts_buff.str = dest;
ts_buff.cnt = sizeof(ESODBC_ISO8601_TEMPLATE) - 1;
if (! parse_timedate(stmt, &xstr, &tss, &format, &ts_buff)) {
if (! parse_date_time_ts(stmt, &xstr, &tss, &format, &ts_buff)) {
ERRH(stmt, "failed to parse input as Time/Date/Timestamp");
RET_HDIAGS(stmt, SQL_STATE_22008);
} else if (format == SQL_TYPE_TIME) {
Expand Down
5 changes: 2 additions & 3 deletions driver/defs.h
Original file line number Diff line number Diff line change
Expand Up @@ -273,9 +273,8 @@
* Timedate functions support:
* - supported: DAYNAME, DAYOFMONTH, DAYOFWEEK, DAYOFYEAR, EXTRACT, HOUR,
* MINUTE, MONTH, MONTHNAME, QUARTER, SECOND, WEEK, YEAR, NOW,
* CURRENT_TIMESTAMP;
* - not supported: CURRENT_DATE, CURRENT_TIME, CURDATE,
* CURTIME, TIMESTAMPADD, TIMESTAMPDIFF.
* CURRENT_TIMESTAMP, CURRENT_DATE, CURDATE;
* - not supported: CURRENT_TIME, CURTIME, TIMESTAMPADD, TIMESTAMPDIFF.
*/
#define ESODBC_TIMEDATE_FUNCTIONS (0LU | \
SQL_FN_TD_DAYNAME | SQL_FN_TD_DAYOFMONTH | SQL_FN_TD_DAYOFWEEK | \
Expand Down
10 changes: 5 additions & 5 deletions driver/handles.c
Original file line number Diff line number Diff line change
Expand Up @@ -1963,7 +1963,7 @@ static void set_defaults_from_meta_type(esodbc_rec_st *rec)
rec->length = ESODBC_DEF_STRING_LENGTH;
rec->precision = ESODBC_DEF_STRING_PRECISION;
break;
case METATYPE_DATETIME:
case METATYPE_DATE_TIME:
if (rec->datetime_interval_code == SQL_CODE_DATE ||
rec->datetime_interval_code == SQL_CODE_TIME) {
rec->precision = ESODBC_DEF_DATETIME_PRECISION;
Expand Down Expand Up @@ -2048,7 +2048,7 @@ static esodbc_metatype_et sqltype_to_meta(SQLSMALLINT concise)
case SQL_TYPE_TIMESTAMP:
// case SQL_TYPE_UTCDATETIME:
// case SQL_TYPE_UTCTIME:
return METATYPE_DATETIME;
return METATYPE_DATE_TIME;

/* interval (note: SQL_INTERVAL is verbose, not concise) */
case SQL_INTERVAL_MONTH:
Expand Down Expand Up @@ -2134,7 +2134,7 @@ static esodbc_metatype_et sqlctype_to_meta(SQLSMALLINT concise)
case SQL_C_TYPE_TIMESTAMP:
// case SQL_C_TYPE_TIME_WITH_TIMEZONE:
// case SQL_C_TYPE_TIMESTAMP_WITH_TIMEZONE:
return METATYPE_DATETIME;
return METATYPE_DATE_TIME;

/* interval */
case SQL_C_INTERVAL_DAY:
Expand Down Expand Up @@ -2216,7 +2216,7 @@ static BOOL consistency_check(esodbc_rec_st *rec)

/* check SQL_DESC_PRECISION field */
/* "a time or timestamp data type" */
case METATYPE_DATETIME:
case METATYPE_DATE_TIME:
if (rec->concise_type == SQL_TYPE_DATE) {
break;
}
Expand All @@ -2233,7 +2233,7 @@ static BOOL consistency_check(esodbc_rec_st *rec)
return FALSE;
}
}
if (rec->meta_type == METATYPE_DATETIME) {
if (rec->meta_type == METATYPE_DATE_TIME) {
break;
}
/* check SQL_DESC_DATETIME_INTERVAL_PRECISION */
Expand Down
6 changes: 4 additions & 2 deletions driver/handles.h
Original file line number Diff line number Diff line change
Expand Up @@ -64,7 +64,7 @@ typedef enum {
METATYPE_FLOAT_NUMERIC,
METATYPE_STRING,
METATYPE_BIN,
METATYPE_DATETIME,
METATYPE_DATE_TIME,
METATYPE_INTERVAL_WSEC,
METATYPE_INTERVAL_WOSEC,
METATYPE_BIT,
Expand Down Expand Up @@ -335,8 +335,10 @@ typedef struct struct_stmt {
* returning to the application." */
SQLULEN query_timeout;

/* [current] result set (= one answer from ES/SQL; can contain a cursor) */
/* [current] result set (= one page from ES/SQL; can contain a cursor) */
resultset_st rset;
/* count of result sets fetched */
size_t nset;
/* total count of fetched rows for one statement (sum(resultset.nrows)) */
size_t tf_rows;
/* SQL data types conversion to SQL C compatibility (IRD.SQL -> ARD.C) */
Expand Down
2 changes: 1 addition & 1 deletion driver/log.h
Original file line number Diff line number Diff line change
Expand Up @@ -44,7 +44,7 @@

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

#ifdef UNICODE
# define LTSTR LWSTR
Expand Down
18 changes: 11 additions & 7 deletions driver/queries.c
Original file line number Diff line number Diff line change
Expand Up @@ -79,7 +79,7 @@ static void set_col_size(esodbc_rec_st *rec)
case METATYPE_BIN:
/* "The defined or maximum length in bytes of the column " */
/* no break */
case METATYPE_DATETIME:
case METATYPE_DATE_TIME:
/* "number of characters in the character representation" */
rec->length = rec->es_type->column_size;
break;
Expand Down Expand Up @@ -281,6 +281,7 @@ SQLRETURN TEST_API attach_answer(esodbc_stmt_st *stmt, char *buff, size_t blen)
stmt->rset.nrows = 0;
#endif /*0*/
} else {
stmt->nset ++;
/* the cast is made safe by the decoding format indicator for array */
stmt->rset.nrows = (size_t)UJLengthArray(rows);
stmt->tf_rows += stmt->rset.nrows;
Expand Down Expand Up @@ -934,8 +935,8 @@ SQLRETURN EsSQLFetch(SQLHSTMT StatementHandle)
DBGH(stmt, "ES/app data/buffer types found compatible.");
}

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

/* reset SQLGetData state, to reset fetch position */
STMT_GD_RESET(stmt);
Expand Down Expand Up @@ -1513,7 +1514,7 @@ static esodbc_estype_st *match_es_type(esodbc_rec_st *arec,
case METATYPE_BIN:
/* SQL_VARBINARY == -3 == ES/SQL BINARY */
return lookup_es_type(dbc, SQL_VARBINARY, /*no prec*/0);
case METATYPE_DATETIME:
case METATYPE_DATE_TIME:
assert(irec->concise_type == SQL_TYPE_DATE ||
irec->concise_type == SQL_TYPE_TIME);
return lookup_es_type(dbc, SQL_TYPE_TIMESTAMP, /*no prec*/0);
Expand Down Expand Up @@ -2059,6 +2060,9 @@ SQLRETURN TEST_API serialize_statement(esodbc_stmt_st *stmt, cstr_st *buff)
memcpy(body + pos, dbc->fetch.str, dbc->fetch.slen);
pos += dbc->fetch.slen;
}

/* reset the page counter when the params change */
stmt->nset = 0;
}
/* "mode": */
memcpy(body + pos, JSON_KEY_VAL_MODE, sizeof(JSON_KEY_VAL_MODE) - 1);
Expand Down Expand Up @@ -2176,7 +2180,7 @@ SQLRETURN EsSQLExecDirectW
if (SQL_SUCCEEDED(ret)) {
ret = EsSQLExecute(stmt);
}
#ifndef NDEBUG
#ifdef NDEBUG
/* no reason to keep it (it can't be re-executed), except for debugging */
detach_sql(stmt);
#endif /* NDEBUG */
Expand Down Expand Up @@ -2235,7 +2239,7 @@ static inline SQLULEN get_col_size(esodbc_rec_st *rec)

case METATYPE_STRING:
case METATYPE_BIN:
case METATYPE_DATETIME:
case METATYPE_DATE_TIME:
case METATYPE_INTERVAL_WSEC:
case METATYPE_INTERVAL_WOSEC:
case METATYPE_BIT:
Expand All @@ -2255,7 +2259,7 @@ static inline SQLSMALLINT get_col_decdigits(esodbc_rec_st *rec)
assert(DESC_TYPE_IS_IMPLEMENTATION(rec->desc->type));

switch (rec->meta_type) {
case METATYPE_DATETIME:
case METATYPE_DATE_TIME:
case METATYPE_INTERVAL_WSEC:
return ESODBC_MAX_SEC_PRECISION;

Expand Down

0 comments on commit ffc2338

Please sign in to comment.