Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Enable DATE conversions #115

Merged
merged 5 commits into from
Feb 20, 2019
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
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