Structure of a C Stored Function

Each new set of code should be implemented as a C file, which we refer to as a C stored function. Since each stored function will eventually become a library in which the MIM server will load upon startup, the C implementation was chosen so as to avoid problems with loading C++ libraries.

It is essential for a stored function to be able to maintain a state, which would persist between invocations of different stored function functions. The stored function state is represented by the following structure (which we call stored function arguments, thus the name):

  typedef struct {
    //error string
    char                    *error; 
    //pointer to a SchSchema object
    void                    *schema;
    //pointer to an ExXmimOptions object, containing user defaults
    const void              *user_defaults;
    //pointer to an ExCompiledQuery object corresponding to the current query
    void                    *compiled_query;
    //MimUnits (ExRelcol units)
    int                     units;
    //ExRelcol modulus
    int                     modulus;

    //pointer to the cfunc's characteristic time series,
    //a time series which has non-NaN values for times
    //when this c stored function is defined and NaN 
    //values when it is not
    void                    *characteristic_time_series;
    //pointer to the cfunc's ExTradingPattern object
    void                    *trading_pattern;
    //pointer to the cfunc's ExDateRange object
    void                    *trading_date_range;
    //cfunc specific state 
    xmim_cfunc_state            *state;
    //constant int args 
    xmim_cfunc_int_args         *int_args;
    //constant double args 
    xmim_cfunc_double_args      *double_args;
    //category args 
    xmim_cfunc_                 *category_args;
    //string args 
    xmim_cfunc_string_args      *string_args;
    //ATTR args
    xmim_cfunc_attr_args        *attr_args;
    //time offset args
    xmim_cfunc_time_offset_args *offset_args;
    //period args
    xmim_cfunc_time_period_args *period_args;
    //security args
    xmim_cfunc_security_args    *security_args;
    //default return value
    double                  default_val;
    //return value of the get_value method
    double                  result;
  } xmim_cfunc_args;

This structure has a member called state, which is an array of void*, specific to a particular stored function. A stored function may store any information it needs to persist between the function calls in this array.

Each stored function has the following structure. All functions are mandatory, unless specified otherwise. The function cfunc_instance_init_defaults initializes the default values of the stored function. Each stored function should "know" about the arguments it expects. The stored function will initialize the appropriate arguments in this function, i.e., assign the values to the names and size members of the appropriate structs.

extern "C" int cfunc_instance_init_defaults (xmim_cfunc_args *args) {
...
}

For example, if a stored function expects to get three constants as arguments, it should do something analogous to the following in the cfunc_instance_init_defaults function:

Also, we suggest that a stored function initialize args->state in this function.

This can be performed in the cfunc_instance_init function as well.

  int num = 3;  
  args->int_args->size = num;
  args->int_args->ptr = new int[num];
  for (int i = 0; i < num; i++)
    args->int_args->ptr[i] = 0;

  args->int_args->names = new char*[num];
  args->int_args->names[0] = "day";
  args->int_args->names[1] = "month";
  args->int_args->names[2] = "year";

The function cfunc_instance_init initializes the state ( argsstate ) of a stored function. Everything that needs to be initialized before the cfunc_instance_get_value function will be called should be initialized here.

The stored function's input parameters are set at this point and can be used by the stored function to initialize its state if necessary.

extern "C" int cfunc_instance_init (xmim_cfunc_args *args) {  
...
}

The optional function cfunc_instance_compute_trading_pattern computes the trading pattern for a cfunc.

extern "C" int cfunc_instance_compute_trading_pattern (xmim_cfunc_args *args) {
...
}

The optional function cfunc_instance_compute_trading_date_range computes the trading date range for a stored function.

extern "C" int cfunc_instance_compute_trading_date_range (xmim_cfunc_args *args) {
...
}

The optional function cfunc_instance_get_characteristic_time_series computes the characteristic time series for a stored function. A characteristic time series is a time series which has non-NaN values for times when the date exists and NaN values for times when the date does not exist.

extern "C" int cfunc_instance_get_characteristic_time_series (xmim_cfunc_args *args) {
...
}

The function cfunc_instance_get_value sets args->result to the value this stored function needs to return for the date and time dt.

extern "C" int cfunc_instance_get_value (xmim_cfunc_args *args, xmim_cfunc_date_time *dt) {
...
}

The function cfunc_instance_destroy is a destructor for a stored function. A stored function should destroy all the instances it creates.

extern "C" int cfunc_instance_destroy (xmim_cfunc_args *args) {
...
}

C Stored Functions can have constant (integer, double), attribute, time offset, time period, security, category, and string input arguments. The first five argument types are the same as arguments accepted by macros. The category argument is stored as a string and can be used to retrieve and process all relations under that category in the MIM schema hierarchy. The string argument appears as a sequence of characters in double quotes in the C stored function call. For example, the following is a call to a C stored function named builtin_string_example which takes two string arguments ("ALEX" and "Close"):

builtin_string_example(“ALEX”, “Close”)

A C stored function "registers" a string input argument in the same way as any other argument. Namely, builtin_string_example may "register" to receive two string arguments (relation name and column name) with the following code in its cfunc_instance_init_defaults functions as follows:

  int num = 2;
  //string args
  xmim_cfunc_string_args *str = new xmim_cfunc_string_args;
  str->size = num;
  str->names = new char*[num]
  str->names[0] = "relation";
  str->names[1] = "column";
  str->ptr = new char*[num];
  for (int i = 0; i < num; i++)
    str->ptr[i] = NULL;

  args->string_args = str;

String input arguments are handled in the same way as the rest of the arguments.

The cfunc_instance_get_characteristic_time_series function is optional, but when defined, is expected to set the args->characteristic_time_series member to the appropriate characteristic time series, such that the time series has a non-NaN value when the date exists and a NaN value for the times when the date does not exist. For example, if a stored function is defined at exactly the times when the Close of IBM is defined, then args->characteristic_time_series should be set to the time series retrieved via the xmim_cfunc_get_time_series function for the Close of IBM.