/* ** Title: Business ** SCCSid: %W% %E% %U% ** CCid: %W% %E% %U% ** Author: Informix Software, Inc. ** Created: 06/11/1998 14:49 ** Description: This is the generated 'C' file for the Business DataBlade. ** Comments: Generated for project Business.3.6 */ /* ** The following is placed here to insure ** that name "mangling" does not occur. */ #ifdef __cplusplus extern "C" { #endif /* Standard library includes. */ #include #include #include #include /* Used by Informix GLS routines. */ #include /* Include when accessing the Informix API. */ #include /* This is the project include file. */ #include "Business.h" #include /* * The AMORT_STATE structure holds the state of a loan's amortization * across iterations. We store this structure in the MI_FP_FUNCSTATE * entry in the MI_FPARAM for the set-valued function LoanAmortization. */ typedef struct { int numyears; int iter; mi_real amount; mi_real balance; mi_real interest_rate; mi_real payment; } AMORT_STATE; /* {{FUNCTION(594117f1-5f4c-11d0-93a5-00a0c9202325) (MergeSection) */ /**************************************************************** ** ** Function name: ** ** PresentValue ** ** Description: ** ** Special Comments: ** ** Entrypoint for the SQL routine ExmPV (real,integer,real) returns real. ** ** Parameters: ** ** Return value: ** ** mi_real ** ** History: ** ** 06/30/1998 - Generated by BladeSmith Version 3.60.630 . ** ** Identification: ** ** NOTE: ** ** BladeSmith will add and remove parameters from the function ** prototype, and will generate tracing calls. ONLY EDIT code ** in blocks marked Your_
. Any other modifications ** will require manual merging. ** ***************************************************************** */ UDREXPORT mi_real *PresentValue ( mi_real * amount, mi_integer numyears, mi_real * interest_rate, MI_FPARAM * Gen_fparam /* Standard info - see DBDK docs.*/ ) { mi_real* Gen_RetVal; /* The return value. */ MI_CONNECTION * Gen_Con; /* The connection handle. */ /* ------ {{Your_Declarations (PreserveSection) BEGIN ------ */ double pv; /* ------ }}Your_Declarations (#0000) END ------ */ /* Use the NULL connection. */ Gen_Con = NULL; /* ------ {{Your_Code (PreserveSection) BEGIN ------ */ /* ** Write to the trace file indicating ** that PresentValue has been called. */ DBDK_TRACE_ENTER( "PresentValue" ); /* simple sanity checks */ if( (*amount < 0.0) || (numyears < 0) || (*interest_rate < 0) ) { mi_db_error_raise( Gen_Con, MI_SQL, "UE001", "FUNCT%s", "PresentValue", (mi_integer)NULL); /* not reached */ } /* compute the present value of the loan */ pv = *amount / pow((double) (1.0f + *interest_rate/100.0f), (double) numyears); /* allocate return value */ Gen_RetVal = (mi_real *) mi_alloc(sizeof(mi_real)); *Gen_RetVal = (mi_real) pv; /* ** Write to the trace file indicating ** that PresentValue has successfully exited. */ DBDK_TRACE_EXIT( "PresentValue" ); /* ------ }}Your_Code (#B4PS) END ------ */ /* Return the function's return value. */ return Gen_RetVal; } /* }}FUNCTION (#6V87I8P7) */ /* {{FUNCTION(edf2f7a0-8384-11d0-93b2-00a0c9202325) (MergeSection) */ /**************************************************************** ** ** Function name: ** ** LoanAmortization ** ** Description: ** ** This function is an iterator function. As such, it must be ** registered using SQL as an iterator function: ** ** create function ExmAmortize( args ) ** returns MI_ROW ** with ** ( ** iterator ** ) ** external name "yourpath/Business.bld(LoanAmortization)" ** language C ** end function; ** ** Iterator functions are called with state information. There are ** three states: SET_INIT, SET_RETONE, and SET_END. This state ** information is passed in via the Gen_fparam argument to the ** function and placed in Gen_IteratorState. During the SET_INIT ** state, the iterator function must perform any required ** initialization. Typically, this means allocating memory to hold ** any information that is needed across calls to the function. ** This allocated memory must be stored back into Gen_fparam by ** calling mi_fp_setfuncstate and can be retrieved by calling ** mi_fp_funcstate. Values passed back from this state are ignored. ** ** Following initialization, the function is repeatedly called in ** the SET_RETONE state. The return value returned from this state ** is passed back to the user. The function is called repeatedly ** until the iterator function signals that no more data is to be ** passed back. The iterator function *MUST* call: ** ** mi_fp_setisdone( Gen_fparam, MI_TRUE ); ** ** to conclude looping. Failing to call this function will result ** in infinite looping! ** ** Finally, the iterator function is called in the SET_END state and ** the function is given a chance to perform any cleanup that is ** required. Values passed back from this state are ignored. ** ** N.B.: If mi_db_error_raise is called during the processing of the ** iterator function, the function is not called in the SET_END ** state. Resources allocated using mi_dalloc on a PER_COMMAND basis ** are freed for you but all other resources should be freed before ** calling mi_db_error_raise. ** ** ** Special Comments: ** ** Entrypoint for the SQL routine ExmAmortize (real,integer,real) returns ExmLoanAmortResult. ** ** Parameters: ** ** Return value: ** ** MI_ROW ** ** History: ** ** 06/30/1998 - Generated by BladeSmith Version 3.60.630 . ** ** Identification: ** ** NOTE: ** ** BladeSmith will add and remove parameters from the function ** prototype, and will generate tracing calls. ONLY EDIT code ** in blocks marked Your_
. Any other modifications ** will require manual merging. ** ***************************************************************** */ UDREXPORT MI_ROW * LoanAmortization ( mi_real * amount, mi_integer num_years, mi_real * interest_rate, MI_FPARAM * Gen_fparam /* Standard info - see DBDK docs.*/ ) { int Gen_IteratorState; /* This is the iteration state. */ MI_CONNECTION * Gen_Con; /* The current connection. */ MI_ROW * Gen_RetVal = 0; /* LoanAmortization's return value. */ /* ------ {{Your_StateInfoDeclaration (PreserveSection) BEGIN ------ */ AMORT_STATE * input; mi_real iter_interest; mi_real iter_principal; mi_real iter_balance; mi_real payment_factor; mi_integer i; void * values[6]; mi_boolean nulls[6]; MI_TYPEID * typid; MI_ROW_DESC * rowdesc; struct _StateInfo { MI_CONNECTION * Conn; /* The current connection. */ void * StateInfo; /* Private state information. */ } * Gen_StateInfo; /* LoanAmortization's state information. */ /* ------ }}Your_StateInfoDeclaration (#0JN8) END ------ */ /* ------ {{Your_AutoVariable_Declarations (PreserveSection) BEGIN ------ */ /* Initialize data members */ Gen_RetVal = 0; input = (AMORT_STATE *) NULL; /* ------ }}Your_AutoVariable_Declarations (#0000) END ------ */ /* Get the iteration state. */ Gen_IteratorState = mi_fp_request( Gen_fparam ); /* ** Based on the iteration state, ** calculate the iterator's return ** value. */ switch( Gen_IteratorState ) { case SET_INIT: /* Initialize */ /* ** Get the current connection handle. ** This connection handle is held in ** the state information for the duration ** of the running of LoanAmortization. */ Gen_Con = mi_open( NULL, NULL, NULL ); /* Verify that the connection has been established. */ if( Gen_Con == 0 ) { /* ** Opening the current connection has failed ** so issue the following message and quit. ** ** "Connection has failed in LoanAmortization." */ DBDK_TRACE_ERROR( "LoanAmortization", ERRORMESG1, 10 ); /* not reached */ } /* ------ {{Your_InitializationCode (PreserveSection) BEGIN ------ */ { /* ** Write to the trace file indicating ** that LoanAmortization has been called. */ DBDK_TRACE_ENTER( "LoanAmortization" ); /* ** Perform any required initializa- ** tion for the iterator function. Any ** state information must be allocated and ** registered here. */ /* ** Allocate the state information. Both ** the private state information and ** connection are stored here. */ Gen_StateInfo = (struct _StateInfo *) mi_dalloc( sizeof( struct _StateInfo ), PER_COMMAND ); if( Gen_StateInfo == NULL ) { DBDK_TRACE_ERROR( "LoanAmortization", ERRORMESG2, 10 ); } /* Save the connection. */ Gen_StateInfo->Conn = Gen_Con; /* ** Allocate any required private ** state information here. */ Gen_StateInfo->StateInfo = mi_dalloc(sizeof(AMORT_STATE), PER_COMMAND); if( Gen_StateInfo->StateInfo == NULL ) { DBDK_TRACE_ERROR( "LoanAmortization", ERRORMESG2, 10 ); } /* Register the private state info in Gen_fParam. */ mi_fp_setfuncstate( Gen_fparam, Gen_StateInfo ); /* ** Save private state information */ input = (AMORT_STATE *)Gen_StateInfo->StateInfo; input->numyears = num_years; input->iter = 1; input->amount = *amount; input->interest_rate = *interest_rate; /* sanity check */ if ((*amount < 0.0) || (num_years < 0) || (*interest_rate < 0)) { mi_db_error_raise(Gen_Con, MI_SQL,"UE001", "FUNCT%s", "LoanAmortization", (char *) NULL); } payment_factor = 0.0f; for (i=1; i<=input->numyears; i++) { payment_factor += 1.0f / (float) pow((double)(1.0+ (input->interest_rate /100.0)), (double) i); } input->payment = input->amount/payment_factor; } /* ------ }}Your_InitializationCode (#VKOT) END ------ */ if( Gen_StateInfo->StateInfo == NULL ) { DBDK_TRACE_ERROR( "LoanAmortization", ERRORMESG2, 10 ); } /* Register the private state info in Gen_fParam. */ mi_fp_setfuncstate( Gen_fparam, Gen_StateInfo ); break; case SET_RETONE: /* Iterate */ /* ** Before using, insure that the state ** information is valid. It might not be ** if the function has not been called as ** an iterator. */ Gen_StateInfo = (struct _StateInfo *)mi_fp_funcstate( Gen_fparam ); if( Gen_StateInfo == NULL ) { DBDK_TRACE_ERROR( "LoanAmortization", ERRORMESG2, 10 ); } /* Retrieve the connection. */ Gen_Con = Gen_StateInfo->Conn; /* ------ {{Your_SetReturnCode (PreserveSection) BEGIN ------ */ { /* ** Write to the trace file indicating ** that LoanAmortization has been called. */ DBDK_TRACE_ENTER( "LoanAmortization" ); /* recover the amortization state from the MI_FPARAM */ input = (AMORT_STATE *)Gen_StateInfo->StateInfo; /* if the loan's paid off, we're done */ if(input->iter > input->numyears) { mi_fp_setisdone( Gen_fparam, MI_TRUE ); mi_fp_setreturnisnull( Gen_fparam, 0, MI_TRUE ); return ((MI_ROW *) NULL); } else { mi_fp_setreturnisnull( Gen_fparam, 0, MI_FALSE ); /* we are not done, so update the private state */ if (input->iter > 1) { input->amount = input->balance; } /* calculate values for the ExmLoanAmortResult */ iter_interest = input->amount * (input->interest_rate / 100.0); iter_principal = input->payment - iter_interest; iter_balance = input->amount - (input->payment - iter_interest); /* bring the balance forward for the next iteration */ input->balance = iter_balance; /* * Now we set up the composite ExmLoanAmortResult value with * the numbers for this iteration. The 'values' array * holds the attribute values for the composite, in row * order, and the 'nulls' array tells MakeCompositeValue * whether any of the values we're supplying are SQL * NULL values. None are, in this case, so we set all the * nulls[] array entries to MI_FALSE. * * The ExmLoanAmortResult row type is defined as * * create type ExmLoanAmortResult ( * Year integer, * BegAmount real, * Payment real, * Interest real, * Principal real, * Balance real * ); * */ /* get typeid. * Here we use a C string containing the type name. * Another way would be to look at the rettype in fparam. */ typid = mi_typestring_to_id(Gen_Con, "ExmLoanAmortResult"); /* create a row desc */ rowdesc = mi_row_desc_create(typid); /* create the return value */ for (i = 0; i < 6; i++) { nulls[i] = MI_FALSE; } values[0] = (void *) input->iter; values[1] = (void *) &input->amount; values[2] = (void *) &input->payment; values[3] = (void *) &iter_interest; values[4] = (void *) &iter_principal; values[5] = (void *) &iter_balance; Gen_RetVal = mi_row_create(Gen_Con, rowdesc, (MI_DATUM *)values, nulls); /* cleanup */ (void) mi_free((char *)typid); /* get set for next iteration */ input->iter++; /* ** Write to the trace file indicating ** that LoanAmortization has successfully exited. */ DBDK_TRACE_EXIT( "LoanAmortization" ); } } /* ------ }}Your_SetReturnCode (#6MM0) END ------ */ /* Check for a NULL return value. */ if( Gen_RetVal == 0 ) { mi_fp_setreturnisnull( Gen_fparam, 0, MI_TRUE ); } else { mi_fp_setreturnisnull( Gen_fparam, 0, MI_FALSE ); } return ( Gen_RetVal ); case SET_END: /* Conclude */ /* Get the state information. */ Gen_StateInfo = (struct _StateInfo *)mi_fp_funcstate( Gen_fparam ); if( Gen_StateInfo != NULL ) { /* Retrieve the connection. */ Gen_Con = Gen_StateInfo->Conn; /* Close the open connection. */ mi_close( Gen_Con ); /* ------ {{Your_SetFinalCode (PreserveSection) BEGIN ------ */ { /* TO DO: free any private resources. */ } /* ------ }}Your_SetFinalCode (#000J) END ------ */ /* Free the private state information. */ if( Gen_StateInfo->StateInfo != NULL ) { mi_free( Gen_StateInfo->StateInfo ); } /* Free the state information. */ mi_free( Gen_StateInfo ); } break; default: /* Get the state information. */ Gen_StateInfo = (struct _StateInfo *)mi_fp_funcstate( Gen_fparam ); if( Gen_StateInfo != NULL ) { /* Retrieve the connection. */ Gen_Con = Gen_StateInfo->Conn; } /* ** This is an invalid state so issue ** the following message and quit. ** ** "Invalid iterator state used in LoanAmortization." */ DBDK_TRACE_ERROR( "LoanAmortization", ERRORMESG17, 10 ); /* not reached */ break; } mi_fp_setreturnisnull( Gen_fparam, 0, MI_TRUE ); return ( 0 ); } /* }}FUNCTION (#3QRA52N8) */ /* {{FUNCTION(594117f0-5f4c-11d0-93a5-00a0c9202325) (MergeSection) */ /**************************************************************** ** ** Function name: ** ** FutureValue ** ** Description: ** ** Special Comments: ** ** Entrypoint for the SQL routine ExmFV (real,integer,real) returns real. ** ** Parameters: ** ** Return value: ** ** mi_real ** ** History: ** ** 06/30/1998 - Generated by BladeSmith Version 3.60.630 . ** ** Identification: ** ** NOTE: ** ** BladeSmith will add and remove parameters from the function ** prototype, and will generate tracing calls. ONLY EDIT code ** in blocks marked Your_
. Any other modifications ** will require manual merging. ** ***************************************************************** */ UDREXPORT mi_real *FutureValue ( mi_real * amount, mi_integer numyears, mi_real * interest_rate, MI_FPARAM * Gen_fparam /* Standard info - see DBDK docs.*/ ) { mi_real* Gen_RetVal; /* The return value. */ MI_CONNECTION * Gen_Con; /* The connection handle. */ /* ------ {{Your_Declarations (PreserveSection) BEGIN ------ */ double fv; /* ------ }}Your_Declarations (#0000) END ------ */ /* Use the NULL connection. */ Gen_Con = NULL; /* ------ {{Your_Code (PreserveSection) BEGIN ------ */ /* ** Write to the trace file indicating ** that FutureValue has been called. */ DBDK_TRACE_ENTER( "FutureValue" ); /* simple sanity checks */ if( (*amount <0.0) || (numyears < 0) || (*interest_rate <0) ) { mi_db_error_raise( Gen_Con, MI_SQL, "UE001", "FUNCT%s", "FutureValue", (mi_integer)NULL); /* not reached */ } /* compute the future value of the loan */ fv = *amount * pow((double) (1.0 + *interest_rate/100.0), (double) numyears); /* allocate return value */ Gen_RetVal = (mi_real *) mi_alloc(sizeof(mi_real)); *Gen_RetVal = (mi_real) fv; /* ** Write to the trace file indicating ** that FutureValue has successfully exited. */ DBDK_TRACE_EXIT( "FutureValue" ); /* ------ }}Your_Code (#A0VP) END ------ */ /* Return the function's return value. */ return Gen_RetVal; } /* }}FUNCTION (#1D1CLFOH) */ #ifdef __cplusplus } #endif