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);
}