/* ** Title: TopK ** SCCSid: %W% %E% %U% ** CCid: %W% %E% %U% ** Author: Informix Software, Inc. ** Created: 06/22/1998 15:59 ** Description: This is the generated 'C' file for the TopK DataBlade. ** Comments: Generated for project TopK.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 "TopK.h" /* Private forward declaration */ static void topk_error(char* msg); static mi_integer topk_setinit(MI_COLLECTION *intset, mi_integer k, MI_FPARAM *fParam); static mi_integer topk_setretone(MI_FPARAM *fParam); static mi_integer topk_setend(MI_FPARAM *fParam); /* Private data structure */ /* we keep the top K integers in this structure */ typedef struct _topk_terms { int tk_k; int tk_nterms; int tk_curterm; mi_integer *tk_terms; } topk_terms; struct _StateInfo { MI_CONNECTION * Conn; /* The current connection. */ topk_terms * StateInfo; /* Private state information. */ }; /* {{FUNCTION(9f039a80-836c-11d0-93b2-00a0c9202325) (MergeSection) */ /**************************************************************** ** ** Function name: ** ** TopK ** ** Description: ** ** This function is an iterator function. As such, it must be ** registered using SQL as an iterator function: ** ** create function TopK( args ) ** returns mi_integer ** with ** ( ** iterator ** ) ** external name "yourpath/TopK.bld(TopK)" ** 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 TopK (set (integer not null),integer) returns integer. ** ** Parameters: ** ** Return value: ** ** mi_integer ** ** History: ** ** 06/22/1998 - Generated by BladeSmith Version 3.60.TC1B1. ** ** 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_integer TopK ( MI_COLLECTION * intset, mi_integer k, 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_integer Gen_RetVal = 0; /* TopK's return value. */ /* ------ {{Your_StateInfoDeclaration (PreserveSection) BEGIN ------ */ struct _StateInfo { MI_CONNECTION * Conn; /* The current connection. */ topk_terms * StateInfo; /* Private state information. */ }* Gen_StateInfo; /* TopK's state information. */ /* ------ }}Your_StateInfoDeclaration (#0JN8) END ------ */ /* ------ {{Your_AutoVariable_Declarations (PreserveSection) BEGIN ------ */ MI_COLL_DESC * colldesc; /* The collection handle */ mi_integer result; mi_integer curVal; mi_integer curValLength; mi_integer * term; int i, j; topk_terms * tk; /* ------ }}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 TopK. */ 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 TopK." */ DBDK_TRACE_ERROR( "TopK", ERRORMESG1, 10 ); /* not reached */ } /* ------ {{Your_InitializationCode (PreserveSection) BEGIN ------ */ { /* ** Write to the trace file indicating ** that TopK has been called. */ DBDK_TRACE_ENTER( "TopK_setinit" ); /* Test k */ if (k <= 0) { DBDK_TRACE_EXIT( "TopK_setinit" ); mi_db_error_raise(Gen_Con, MI_MESSAGE, "K must be > 0 in TopKIntegers", NULL); } /* ** 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( "TopK", ERRORMESG2, 10 ); } /* Save the connection. */ Gen_StateInfo->Conn = Gen_Con; /* ** allocate and protect memory for sorted set */ tk = (topk_terms *) mi_dalloc(sizeof(topk_terms),PER_COMMAND); if( tk == NULL ) { DBDK_TRACE_ERROR( "TopK", ERRORMESG2, 10 ); } term = (mi_integer *) mi_dalloc((k+1) * sizeof(mi_integer), PER_COMMAND); if( term == NULL ) { DBDK_TRACE_ERROR( "TopK", ERRORMESG2, 10 ); } /* save set in state information */ Gen_StateInfo->StateInfo = tk; /* Register the private state info in Gen_fParam. */ mi_fp_setfuncstate( Gen_fparam, Gen_StateInfo ); /* initialize tk */ tk->tk_k = k; tk->tk_nterms = 0; tk->tk_curterm = 0; tk->tk_terms = term; /* open the collection */ if ((colldesc = mi_collection_open(Gen_Con, intset)) == NULL) { mi_db_error_raise(Gen_Con, MI_MESSAGE, "mi_collection_open failed", NULL); /* not reached */ } /* * Now iterate over the set, and find the top K values. * We do an expensive insertion sort here; this could * be recoded to be more efficient. */ result = mi_collection_fetch(Gen_Con, colldesc, MI_CURSOR_FIRST, 0, (MI_DATUM*)&curVal, &curValLength); while (result != MI_END_OF_DATA) { if (result == MI_NORMAL_VALUE) { /* * Find the insertion point for this entry in the top * k terms. */ for (i = 0; i < tk->tk_nterms && curVal < term[i]; i++) { continue; } /* insert this entry if it qualifies */ if (i < tk->tk_k) { for (j = tk->tk_nterms; j > i; j--) term[j] = term[j - 1]; term[i] = curVal; if (tk->tk_nterms < tk->tk_k) tk->tk_nterms++; } } /* get next item in the set */ result = mi_collection_fetch(Gen_Con, colldesc, MI_CURSOR_NEXT, 0, (MI_DATUM*)&curVal, &curValLength); } /* close the collection */ mi_collection_close(Gen_Con,colldesc); /* * By here, return set is initialized and stored in the fParam. */ mi_fp_setisdone( Gen_fparam, MI_FALSE ); mi_fp_setreturnisnull( Gen_fparam, 0, MI_TRUE ); /* ** Write to the trace file indicating ** that TopK has successfully exited. */ DBDK_TRACE_EXIT( "TopK_setinit" ); Gen_RetVal = 0; } /* ------ }}Your_InitializationCode (#Q0EM) END ------ */ if( Gen_StateInfo->StateInfo == NULL ) { DBDK_TRACE_ERROR( "TopK", 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( "TopK", ERRORMESG2, 10 ); } /* Retrieve the connection. */ Gen_Con = Gen_StateInfo->Conn; /* ------ {{Your_SetReturnCode (PreserveSection) BEGIN ------ */ { /* ** Write to the trace file indicating ** that TopK has been called. */ DBDK_TRACE_ENTER( "TopK_setretone" ); tk = Gen_StateInfo->StateInfo; /* notify the caller if we're done */ if (tk->tk_curterm == tk->tk_nterms) { mi_fp_setisdone( Gen_fparam, MI_TRUE ); mi_fp_setreturnisnull( Gen_fparam, 0, MI_TRUE ); Gen_RetVal = 0; } else { mi_fp_setreturnisnull( Gen_fparam, 0, MI_FALSE ); /* otherwise, return the next value */ Gen_RetVal = tk->tk_terms[tk->tk_curterm++]; } /* ** Write to the trace file indicating ** that TopK has successfully exited. */ DBDK_TRACE_EXIT( "TopK_setretone" ); } /* ------ }}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 ------ */ /* ** Write to the trace file indicating ** that TopK has been called. */ DBDK_TRACE_ENTER( "TopK_setretone" ); /* Free the private state information. */ tk = Gen_StateInfo->StateInfo; mi_free((char *) tk->tk_terms); mi_free((char *) tk); /* ** Write to the trace file indicating ** that TopK has successfully exited. */ DBDK_TRACE_EXIT( "TopK_setretone" ); /* ------ }}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 TopK." */ DBDK_TRACE_ERROR( "TopK", ERRORMESG17, 10 ); /* not reached */ break; } mi_fp_setreturnisnull( Gen_fparam, 0, MI_TRUE ); return ( 0 ); } /* }}FUNCTION (#OHP8G1K6) */ #ifdef __cplusplus } #endif