Interp 函数是使用时间系列 API 的服务器函数的示例。此函数在规则时间系列的值之间插入值以填充空元素。
此函数不处理单个空列。它假设所有列都属于 FLOAT 类型。
select Interp(stock_data) from daily_stocks where stock_name = 'GBase';
此示例和许多其他示例都在 $GBASEDBTDIR/extend/TimeSeries.version 目录中提供。
create function Interp(TimeSeries) returns TimeSeries external name '/tmp/Interpolate.bld(ts_interp)' language c not variant;
select stock_data from daily_stocks where stock_name = 'GBase'; 2011-01-03 00:00:00 1 1 1 1 2011-01-04 00:00:00 2 2 2 2 NULL 2011-01-06 00:00:00 3 3 3 3 select Interp(stock_data) from daily_stocks where stock_name = 'GBase'; 2011-01-03 00:00:00 1 1 1 1 2011-01-04 00:00:00 2 2 2 2 2011-01-05 00:00:00 2.5 2.5 2.5 2.5 2011-01-06 00:00:00 3 3 3 3
/* * SETUP: * create function Interp(TimeSeries) returns TimeSeries * external name 'Interpolate.so(ts_interp)' * language c not variant; * * * USAGE: * select Interp(stock_data) from daily_stocks where stock_id = 901; */ #include <stdio.h> #include <mi.h> #include <tseries.h> # define TS_MAX_COLS 100 # define DATATYPE "smallfloat" /* * This example interpolates between values to fill in null elements. * It assumes that all columns are of type smallfloat and that there are * less than 100 columns in each element. */ ts_timeseries * ts_interp(tsPtr, fParamPtr) ts_timeseries *tsPtr; MI_FPARAM *fParamPtr; { ts_tsdesc *descPtr; ts_tselem tselem; ts_tscan *scan; MI_CONNECTION *conn; ts_typeinfo *typeinfo; int scancode; mi_real *values[TS_MAX_COLS]; mi_real lastValues[TS_MAX_COLS], newValues[TS_MAX_COLS]; mi_boolean nulls[TS_MAX_COLS]; mi_integer minElem, curElem, elem; mi_integer i; mi_boolean noneYet; mi_integer ncols; char strbuf[100]; /* get a connection for libmi */ conn = mi_open(NULL,NULL,NULL); /* open a descriptor for the timeseries */ descPtr = ts_open(conn, tsPtr, mi_fp_rettype(fParamPtr, 0), 0); if ((ncols = (mi_integer) mi_fp_funcstate(fParamPtr)) == 0) { ncols = ts_col_cnt(descPtr); if (ncols > TS_MAX_COLS) { sprintf(strbuf, "Timeseries elements have too many columns, 100 is the max, got %d instead.", ncols); mi_db_error_raise(NULL, MI_FATAL, strbuf, 0); } for (i = 1; i < ncols; i++) { typeinfo = ts_colinfo_number(descPtr, i); if (strlen(typeinfo->ti_typename) != strlen(DATATYPE) && memcmp(typeinfo->ti_typename, DATATYPE, strlen(DATATYPE)) != 0){ sprintf(strbuf, "column was not a %s, got %s instead.", DATATYPE, typeinfo->ti_typename); mi_db_error_raise(NULL, MI_FATAL, strbuf, 0); } } mi_fp_setfuncstate(fParamPtr, (void *) ncols); } noneYet = MI_TRUE; minElem = -1; curElem = 0; /* begin a scan of the whole timeseries */ scan = ts_begin_scan(descPtr, 0, NULL, NULL); while ((scancode = ts_next(scan, &tselem)) != TS_SCAN_EOS) { switch(scancode) { case TS_SCAN_ELEM: /* if this element is not null expand its values */ noneYet = MI_FALSE; ts_get_all_cols(descPtr, tselem, (void **) values, nulls, curElem); if (minElem == -1) { /* save each element */ for (i = 1; i < ncols; i++) lastValues[i] = *values[i]; } else { /* calculate the average */ for (i = 1; i < ncols; i++) { newValues[i] = (*values[i] + lastValues[i])/2.0; lastValues[i] = *values[i]; values[i] = &newValues[i]; } /* update the missing elements */ tselem = ts_make_elem(descPtr, (void **) values, nulls, &elem); for (elem = minElem; elem < curElem; elem++) ts_put_nth_elem(descPtr, tselem, elem); minElem = -1; } break; case TS_SCAN_NULL: if (noneYet) break; /* remember the first null element */ if (minElem == -1) minElem = curElem; break; } curElem++; } ts_end_scan(scan); ts_close(descPtr); return(tsPtr); }