123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328 |
- /*
- * Licensed Materials - Property of HCL
- *
- * IBM Informix DataBlade Module
- * (C) Copyright International Business Machines Corporation 2002.
- * (c) Copyright HCL Technologies Ltd. 2017. All Rights Reserved.
- *
- * COPYRIGHT LICENSE:
- * This information contains sample application programs in source language,
- * which illustrate programming techniques on various operating platforms.
- * You may copy, modify, and distribute these sample programs in any form
- * without payment to IBM, for the purposes of developing, using, marketing
- * or distributing application programs conforming to the application
- * programming interface for the operating platform for which the sample
- * programs are written. These examples have not been thoroughly tested under
- * all conditions. IBM, therefore, cannot guarantee or imply reliability,
- * serviceability, or function of these programs. You may copy, modify, and
- * distribute these sample programs in any form without payment to IBM for
- * the purposes of developing, using, marketing, or distributing application
- * programs conforming to IBM's application programming interfaces.
- * Each copy or any portion of these sample programs or any derivative work,
- * must include a copyright notice as follows:
- * © (your company name) (year). Portions of this code are derived from
- * IBM Corp. Sample Programs. © Copyright IBM Corp. (enter the year or
- * years). All rights reserved.
- *
- */
- # include "tseries.h"
- /*
- * ApplyFunc:
- * create function ApplyFunc(lvarchar,
- * row,
- * TimeSeries,
- * TimeSeries default NULL,
- * datetime year to fraction(5) default NULL,
- * datetime year to fraction(5) default NULL,
- * integer default NULL)
- * returns TimeSeries with (handlesnulls)
- * external name '$INFORMIXDIR/funcs/applyfunc.bld(apply_func)'
- * language c;
- */
- /* struct to keep track of state */
- typedef struct _apply_state {
- MI_CONNECTION *apply_conn;
- MI_FUNC_DESC *apply_func;
- mi_string *apply_sig;
- mi_string *apply_funcname;
- mi_string *apply_tssubtypename;
- mi_string *apply_rowtypename;
- MI_FPARAM *apply_fparam;
- } apply_state;
- /*
- * APPLY_FUNC:
- * This function applied a function to a range of the elements within
- * the src timeseries. The results are placed in the dst timeseries.
- *
- * This function is passed:
- * funcname: name of SPL or C or JAVA function to call,
- * this function must have a signature of
- * funcname(rowtype1, rowtype2)
- * where rowtype1 is the name of the timeseries
- * subtype, and rowtype2 is the name of the
- * row type that contains extra params
- * data_row: contains the non-timeseries arguments that
- * will be passed to function "funcname".
- * src_ts: the source timeseries which "funcname" will
- * be applied to.
- * dst_ts: optional. if supplied results of funcname are
- * inserted here. if not supplied the dst_ts is
- * created in this function.
- * start: where to start the scan.
- * end: where to end the scan.
- * flags: flags passed to ts_open.
- */
- #ifdef NT
- __declspec(dllexport)
- #endif
- ts_timeseries *
- apply_func(mi_lvarchar *funcname,
- MI_ROW *data_row,
- ts_timeseries *src_ts,
- ts_timeseries *dst_ts,
- mi_datetime *start,
- mi_datetime *end,
- mi_integer flags,
- MI_FPARAM *fParam)
- {
- ts_tselem elem;
- MI_ROW *row, *val;
- apply_state *state;
- MI_MEMORY_DURATION md;
- MI_TYPE_DESC *td, *subtype_td;
- mi_string *ts_rowtype, *rowtype;
- mi_string *sig;
- ts_tsdesc *tsdesc, *newdesc;
- ts_tscan *tsscan;
- mi_integer err, len, nelems, off, ret;
- mi_boolean is_irreg;
- /* look for NULL values */
- if (mi_fp_argisnull(fParam, 0))
- mi_db_error_raise(NULL, MI_SQL, "UTSFF", 0);
- if (mi_fp_argisnull(fParam, 1))
- mi_db_error_raise(NULL, MI_SQL, "UTSFL", 0);
- if (mi_fp_argisnull(fParam, 2))
- mi_db_error_raise(NULL, MI_SQL, "UTSFN", 0);
- if (mi_fp_argisnull(fParam, 3))
- dst_ts = NULL;
- if (mi_fp_argisnull(fParam, 4))
- start = NULL;
- if (mi_fp_argisnull(fParam, 5))
- end = NULL;
- if (mi_fp_argisnull(fParam, 6))
- flags = 0;
- /*
- * check and see if we have already gotten a state from
- * a previous row.
- */
- if (!(state = (apply_state *) mi_fp_funcstate(fParam)) ||
- strlen(state->apply_funcname) != mi_get_varlen(funcname) ||
- memcmp(state->apply_funcname, mi_get_vardata(funcname), mi_get_varlen(funcname))) {
- /*
- * we either don't have any state yet, or
- * we the parameters to this function have changed.
- */
- md = mi_switch_mem_duration (PER_COMMAND);
- if (state != NULL) {
- /* remove previous state info */
- mi_free(state->apply_funcname);
- mi_routine_end(state->apply_conn, state->apply_func);
- } else {
- /* allocate space for our state info */
- state = mi_alloc(sizeof(apply_state));
- state->apply_conn = mi_open(NULL, NULL, NULL);
- /* get the timeseries subtype name */
- td = mi_type_typedesc(state->apply_conn, mi_fp_argtype(fParam, 2));
- subtype_td = mi_type_element_typedesc(td);
- ts_rowtype = mi_type_typename(subtype_td);
- len = strlen(ts_rowtype) + 1;
- state->apply_tssubtypename = (mi_string *) mi_alloc(len);
- strcpy(state->apply_tssubtypename, ts_rowtype);
- state->apply_tssubtypename[len] = 0;
- /* get the argument row name */
- td = mi_type_typedesc(state->apply_conn, mi_fp_argtype(fParam, 1));
- rowtype = mi_type_typename(td);
- len = strlen(rowtype) + 1;
- state->apply_rowtypename = (mi_string *) mi_alloc(len);
- strcpy(state->apply_rowtypename, rowtype);
- state->apply_rowtypename[len] = 0;
- }
- /* construct the function signature */
- state->apply_funcname = mi_lvarchar_to_string(funcname);
- len = strlen(state->apply_funcname) +
- 1 + /* '(' */
- strlen(state->apply_tssubtypename) +
- 1 + /* ',' */
- strlen(state->apply_rowtypename) +
- 1 + /* ')' */
- 1; /* '\0' */
- state->apply_sig = sig = (mi_string *) mi_alloc(len);
- sprintf(sig, "%s(%s,%s)", state->apply_funcname,
- state->apply_tssubtypename,
- state->apply_rowtypename);
- /* get the function */
- state->apply_func = mi_routine_get(state->apply_conn, MI_FUNC, sig);
- /* get the fparam for the function */
- state->apply_fparam = mi_fparam_get(state->apply_conn, state->apply_func);
- (void) mi_switch_mem_duration (md);
- }
- /* open the source timeseries */
- tsdesc = ts_open(state->apply_conn, src_ts, mi_fp_argtype(fParam, 2),flags);
- /* calculate (guess) the number of elements between start and end */
- if (!end)
- if (!start)
- nelems = ts_nelems(tsdesc);
- else
- nelems = 100; /* just guess */
- else
- nelems = ts_cal_index(state->apply_conn,
- ts_get_calname(src_ts),
- start ? start : ts_get_origin(src_ts),
- end);
- is_irreg = TS_IS_IRREGULAR(src_ts);
- if (dst_ts == NULL) {
- /* a destination ts was not passed in, so create one */
- dst_ts = ts_create(state->apply_conn,
- ts_get_calname(src_ts),
- start ? start : ts_get_origin(src_ts),
- ts_get_threshold(src_ts),
- TS_IS_IRREGULAR(src_ts) ? TS_CREATE_IRR : 0,
- mi_fp_argtype(fParam, 2),
- nelems,
- ts_get_containername(src_ts));
- off = 0;
- } else if (!is_irreg) {
- /*
- * we have a destination timeseries, get
- * the offset of the starting point
- */
- off = ts_cal_index(state->apply_conn,
- ts_get_calname(dst_ts),
- ts_get_origin(dst_ts),
- start);
- } else
- off = 0;
- /* open the destination timeseries */
- newdesc = ts_open(state->apply_conn, dst_ts, mi_fp_argtype(fParam, 2), 0);
- /* start a scan of the source timeseries */
- tsscan = ts_begin_scan(tsdesc, 0, start, end);
- /* loop through the values in the source timeseries */
- while ((ret = ts_next(tsscan, &elem)) != TS_SCAN_EOS) {
- if (ret == TS_SCAN_NULL) {
- /* this element is missing */
- off++;
- continue;
- }
- /* convert this element into a row */
- row = ts_elem_to_row(tsdesc, elem, ts_current_offset(tsscan));
- /*
- * call the function with the element data and
- * the argument row data
- */
- val = (MI_ROW *) mi_routine_exec(state->apply_conn, state->apply_func, &err, row, data_row);
- /* if the return was NULL ignore it */
- if (mi_fp_returnisnull(state->apply_fparam, 0)) {
- off++;
- continue;
- }
- /* turn the returned row into an element */
- elem = ts_row_to_elem(newdesc, val, NULL);
- /* put the element into the destination timeseries */
- if (is_irreg)
- (void) ts_put_elem(newdesc, elem, ts_current_timestamp(tsscan));
- else
- (void) ts_put_nth_elem(newdesc, elem, off++);
- }
- /* cleanup */
- ts_end_scan(tsscan);
- ts_close(tsdesc);
- ts_close(newdesc);
- return(dst_ts);
- }
- /*
- * We don't have a good place to put this currently, so put it here for now.
- *
- * begin hilow.c
- */
- #ifdef NT
- __declspec(dllexport)
- #endif
- MI_ROW *
- high_low_diff(MI_ROW * row, MI_FPARAM * fp)
- {
- MI_ROW_DESC *rowdesc;
- MI_ROW *result;
- void *values[2];
- mi_boolean nulls[2];
- mi_real *high, *low;
- mi_real r;
- mi_integer len;
- MI_CONNECTION *conn;
- mi_integer rc;
- nulls[0] = MI_TRUE;
- nulls[1] = MI_FALSE;
- conn = mi_open(NULL, NULL, NULL);
- if ((rc = mi_value(row, 1, (MI_DATUM *) & high, &len)) == MI_ERROR)
- mi_db_error_raise(conn, MI_EXCEPTION,
- "ts_test_float_sql: corrupted argument row");
- if (rc == MI_NULL_VALUE)
- goto retisnull;
- if ((rc = mi_value(row, 2, (MI_DATUM *) & low, &len)) == MI_ERROR)
- mi_db_error_raise(conn, MI_EXCEPTION,
- "ts_test_float_sql: corrupted argument row");
- if (rc == MI_NULL_VALUE)
- goto retisnull;
- r = *high - *low;
- values[1] = (void *) &r;
- rowdesc = mi_row_desc_create(mi_typestring_to_id(conn, "one_real"));
- result = mi_row_create(conn, rowdesc, (MI_DATUM *) values, nulls);
- mi_close(conn);
- return (result);
- retisnull:
- mi_fp_setreturnisnull(fp, 0, MI_TRUE);
- return (MI_ROW *) NULL;
- } /* end of applyfunc.c */
|