From bcbf48259f46a47e7d2b47fab1470a9553c950a5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Henrik=20Grubbstr=C3=B6m=20=28Grubba=29?= <grubba@grubba.org> Date: Wed, 18 Feb 2015 14:17:33 +0100 Subject: [PATCH] Odbc: big_typed_query() now knows about time values. --- lib/modules/Sql.pmod/odbc.pike | 38 ++++++++++++++++++++++++++++++++++ src/modules/Odbc/odbc_result.c | 33 +++++++++++++++++++++++++++++ 2 files changed, 71 insertions(+) diff --git a/lib/modules/Sql.pmod/odbc.pike b/lib/modules/Sql.pmod/odbc.pike index 2fbc1d5ad9..2442fa3cb5 100644 --- a/lib/modules/Sql.pmod/odbc.pike +++ b/lib/modules/Sql.pmod/odbc.pike @@ -51,6 +51,44 @@ class typed_result return Gmp.mpq(mantissa, 10->pow(-scale)); } + //! Time of day. + class TOD(int hour, int minute, int second, + int|void nanos) + { + protected string _sprintf(int c) + { + if (nanos) { + return sprintf("%02d:%02d:%02d.%09d", + hour, minute, second, nanos); + } + return sprintf("%02d:%02d:%02d", hour, minute, second); + } + + protected mixed cast(string t) + { + switch(t) { + case "string": + return _sprintf('s'); + case "int": + // Number of seconds since the start of the day. + return (hour*60 + minute)*60 + second; + case "float": + int seconds = cast("int"); + return seconds + nanos/1000000000.0; + } + return UNDEFINED; + } + } + + //! Function called to create time of day objects. + //! + //! The default implementation just passes along its + //! arguments to @[TOD]. + TOD time_factory(int hour, int minute, int second, int|void nanos) + { + return TOD(hour, minute, second, nanos); + } + //! Function called to create timestamp and date objects. //! //! @note diff --git a/src/modules/Odbc/odbc_result.c b/src/modules/Odbc/odbc_result.c index 95ee1188f4..8f1fdb18bd 100644 --- a/src/modules/Odbc/odbc_result.c +++ b/src/modules/Odbc/odbc_result.c @@ -71,6 +71,7 @@ int odbc_result_fun_num = -1; int odbc_typed_result_fun_num = -1; static int scale_numeric_fun_num = -1; +static int time_factory_fun_num = -1; static int timestamp_factory_fun_num = -1; /* @@ -211,6 +212,25 @@ static void push_numeric(int i) free_string(data); } +static void push_time(int i) +{ + struct pike_string *data = Pike_sp[-1].u.string; + struct tagTIME_STRUCT *time = (struct tagTIME_STRUCT *)(data->str); + if (data->len < sizeof(struct tagTIME_STRUCT)) { + return; + } + Pike_sp--; + push_int(time->hour); + push_int(time->minute); + push_int(time->second); +#if 0 + /* New in struct tagSS_TIME2_STRUCT. */ + push_int(time->fraction); /* ns */ +#endif + free_string(data); + apply_current(time_factory_fun_num, 3); +} + static void push_date(int i) { struct pike_string *data = Pike_sp[-1].u.string; @@ -427,6 +447,12 @@ static void odbc_fix_fields(void) field_info[i].factory = push_date; break; case SQL_SS_TIME2: + /* This corresponds to MSSQL time, and is time of day + * with nanosecond precision. + * + * FIXME: We just convert it to SQL_C_TYPE_TIME for now. + */ + /* FALL_THROUGH */ case SQL_TIME: push_text("time"); field_info[i].type = SQL_C_WCHAR; @@ -434,6 +460,9 @@ static void odbc_fix_fields(void) * wants bytes. */ field_info[i].size = 32 * (ptrdiff_t)sizeof(SQLWCHAR); + field_info[i].bin_type = SQL_C_TYPE_TIME; + field_info[i].bin_size = sizeof(struct tagTIME_STRUCT); + field_info[i].factory = push_time; break; case SQL_SS_TIMESTAMPOFFSET: /* This corresponds to MSSQL datetimeoffset, and is @@ -1336,6 +1365,10 @@ void init_odbc_res_programs(void) ADD_FUNCTION("scale_numeric", NULL, tFunc(tInt tInt, tOr(tInt, tObj)), ID_PUBLIC); + time_factory_fun_num = + ADD_FUNCTION("time_factory", NULL, + tFunc(tInt tInt tInt tOr(tInt, tVoid), tMix), + ID_PUBLIC); timestamp_factory_fun_num = ADD_FUNCTION("timestamp_factory", NULL, tFunc(tInt tInt tInt -- GitLab