diff --git a/lib/modules/Sql.pmod/odbc.pike b/lib/modules/Sql.pmod/odbc.pike index 2fbc1d5ad93f77a13850e9f42e743863efb7ab63..2442fa3cb537d3608c84b2d1a3bccd9bc8e1b810 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 95ee1188f4b6f5c13449911c64876b4bee98219f..8f1fdb18bd886f62e48dcf6cb7cabbee15be2d96 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