/* ** Title: Parts ** SCCSid: %W% %E% %U% ** CCid: %W% %E% %U% ** Author: Informix Software, Inc. ** Created: 06/11/1998 14:50 ** Description: This is the generated 'C' file for the Parts DataBlade. ** Comments: Generated for project Parts.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 #include /* Used by Informix GLS routines. */ #include /* Include when accessing the Informix API. */ #include /* This is the project include file. */ #include "Parts.h" #define ERR_CONN_FAILED "08006" #define ERR_ALLOC_FAILED "VM001" #define ERR_TOOMANY_COLS "UVE01" #define ERR_EXEC_FAILED "UVE02" /* ** Structure for the linked list of parts a linked ** list is used due to the dynamic nature of the ** explosion of parts. There could be no children ** or there could be thousands of children */ typedef struct PART { mi_integer parent; mi_integer part; struct PART *nxt; } PARTS; /* ** Local function declarations. These functions are ** called by Explode, but not accessible from the ** outside. */ static PARTS * get_parts(MI_CONNECTION *conn, PARTS *parts, char *sqlbuf); /* {{FUNCTION(abad8e08-5f52-11d0-93a5-00a0c9202325) (MergeSection) */ /**************************************************************** ** ** Function name: ** ** Explode ** ** Description: ** ** Special Comments: ** ** Entrypoint for the SQL routine Explode (integer,lvarchar,lvarchar,lvarchar) returns set (integer not null). ** ** Parameters: ** ** Return value: ** ** set (integer not null) ** ** History: ** ** 06/11/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. ** ***************************************************************** */ MI_COLLECTION * Explode ( mi_integer Nval, mi_lvarchar * Table, mi_lvarchar * Key, mi_lvarchar * Ptr, MI_FPARAM * Gen_fparam /* Standard info - see DBDK docs.*/ ) { MI_CONNECTION * Gen_Con; /* The connection handle. */ MI_COLLECTION * Gen_RetVal; /* The return value wrapper. */ MI_COLL_DESC * Gen_OutCollDesc; /* The collection descriptor. */ MI_TYPEID * Gen_TypeId; /* The collection's type ID. */ MI_DATUM * Gen_Value; /* Insert this collection value. */ mi_integer Gen_Result; /* The return value. */ mi_lvarchar * Gen_InData; /* The data value. */ /* ------ {{Your_Declarations (PreserveSection) BEGIN ------ */ char SelectBuf[1024]; char sqlbuf[1024]; PARTS * rp; PARTS * fp; PARTS * start_parts; PARTS * parts; PARTS * last_part; MI_DATUM value; mi_integer result; mi_integer position; /* ------ }}Your_Declarations (#0000) END ------ */ /* Get the current connection handle. */ 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 Explode." */ DBDK_TRACE_ERROR( "Explode", ERRORMESG1, 10 ); /* not reached */ } /* Get the type ID for the given collection type. */ Gen_TypeId = mi_typestring_to_id( Gen_Con, "set (integer not null)" ); /* Validate the type ID. */ if( Gen_TypeId == NULL ) { /* ** Insertion into the collection has failed ** so issue the following message and quit. ** ** "Insertion into the collection ** has failed in Explode." */ DBDK_TRACE_ERROR( "Explode", ERRORMESG16, 10 ); /* not reached */ } /* Create the collection. */ Gen_RetVal = mi_collection_create( Gen_Con, Gen_TypeId ); /* Check for a successful creation. */ if ( Gen_RetVal == NULL ) { /* ** Collection creation has failed so ** issue the following message and quit. ** ** "Collection creation has failed in Explode." */ DBDK_TRACE_ERROR( "Explode", ERRORMESG15, 10 ); /* not reached */ } /* Open the collection for use and get a handle to it. */ Gen_OutCollDesc = mi_collection_open( Gen_Con, Gen_RetVal ); /* Insure that the open operation was successful. */ if ( Gen_OutCollDesc == NULL ) { /* ** Collection creation has failed so ** issue the following message and quit. ** ** "Collection creation has failed in Explode." */ DBDK_TRACE_ERROR( "Explode", ERRORMESG15, 10 ); /* not reached */ } /* ------ {{Your_Code (PreserveSection) BEGIN ------ */ /* ** Write to the trace file indicating ** that Explode has been called. */ DBDK_TRACE_ENTER( "Explode" ); /* ** The function Explode() will be called once ** from the DataBlade framework. ** It is building a collection of values. */ sprintf(SelectBuf, "select %s from %s where %s = %%d order by 1;", mi_text_to_string(Key), mi_text_to_string(Table), mi_text_to_string(Ptr)); /* ** Allocate the first entry in the linked ** list. Since the value of the first item in ** the list is known, it is assigned and the ** second items memory is allocated */ if ((start_parts = (PARTS *)mi_dalloc(sizeof(PARTS), PER_COMMAND)) == NULL) { mi_db_error_raise(Gen_Con, MI_SQL, ERR_ALLOC_FAILED, NULL); /* not reached */ } parts = start_parts; parts->nxt = NULL; parts->part = Nval; parts->parent = 0; /* ** Set the duration of the memory this will ** keep the memory active for as long as the ** current command is functioning. As ** opposed to releasing memory when the ** C function is completed */ if ((parts->nxt = (PARTS *)mi_dalloc(sizeof(PARTS), PER_COMMAND)) == NULL) { mi_db_error_raise(Gen_Con, MI_SQL, ERR_ALLOC_FAILED, NULL); /* not reached */ } last_part = parts->nxt; last_part->nxt = NULL; /* ** While there are still entrys that possibly ** have children, try to append the children ** on to the end of the list */ parts = start_parts; while(parts->nxt != NULL) { sprintf(sqlbuf, SelectBuf, parts->part); last_part = get_parts(Gen_Con, parts, sqlbuf); parts = parts->nxt; } /* ** loop through the parts list here and ** add each result to the collection */ rp = start_parts; position = 1; while (rp) { /* The last one in the list is bogus */ if (rp->nxt != NULL) { value = (MI_DATUM)rp->part; result = mi_collection_insert(Gen_Con, Gen_OutCollDesc, value, MI_CURSOR_NEXT, 0); if (result != MI_OK) { if (result == MI_ERROR) mi_db_error_raise(NULL, MI_MESSAGE, "mi_collection_insert returned MI_ERROR", NULL); if (result == MI_NULL_VALUE) mi_db_error_raise(NULL, MI_MESSAGE, "mi_collection_insert returned MI_NULL_VALUE", NULL); } position++; } fp = rp; rp = rp->nxt; mi_free( (char *)fp ); } /* ** Write to the trace file indicating ** that Explode has successfully exited. */ DBDK_TRACE_EXIT( "Explode" ); /* ------ }}Your_Code (#K4EF) END ------ */ /* Close the open collection. */ mi_collection_close( Gen_Con, Gen_OutCollDesc ); /* Close the connection. */ mi_close( Gen_Con ); /* Return the function's return value. */ return Gen_RetVal; } /* }}FUNCTION (#F4JG) */ /**************************************************************** ** Function name: ** ** get_parts ** ** Description: ** get_parts is doing the 'real work' against the ** database: the generated SQL statement (see ** get_parts_list) is being executed and the results ** are added to the linked list. ** ** Special Comments: ** ** Local function ** ** Parameters: ** ** Return value: ** ** PARTS * ** ***************************************************************** */ static PARTS *get_parts(MI_CONNECTION *conn, PARTS *parts, char *sqlbuf) { PARTS *last_part; MI_ROW *row; MI_ROW_DESC *rowdesc; mi_integer collen, error, numcols, icolval; char *colval; int state = 0; if ((last_part = (PARTS *)mi_dalloc(sizeof(PARTS), PER_COMMAND)) == NULL) { mi_db_error_raise(conn, MI_SQL, ERR_ALLOC_FAILED, NULL); /* not reached */ } /* ** Execute the SQL statement in sqlbuf */ state = mi_exec(conn, sqlbuf, MI_QUERY_NORMAL); if (state == MI_ERROR) { mi_db_error_raise(conn, MI_SQL, ERR_EXEC_FAILED, "STMT%s", sqlbuf, NULL); /* not reached */ } /* ** We're only interested in the data rows */ while ((state = mi_get_result(conn)) == MI_ROWS) { /* ** 1. For the row get the row description ** 2. Get the number of columns in the row */ rowdesc = mi_get_row_desc_without_row(conn); numcols = mi_column_count(rowdesc); if (numcols > 1) { mi_db_error_raise(conn, MI_SQL, ERR_TOOMANY_COLS, NULL); /* not reached */ } /* ** Get all the rows from the result set */ while ((row = mi_next_row(conn, &error)) != NULL) { /* ** Get the value of the 1st column from the ** retrieved row. We're selecting only one ** column from the parts table. */ switch (mi_value(row, 0, (MI_DATUM*)&colval, &collen)) { case MI_ERROR: case MI_NULL_VALUE: colval = 0; break; case MI_NORMAL_VALUE: break; } /* ** Add the value to the linked list */ icolval = atoi(colval); last_part->part = icolval; last_part->nxt = parts->nxt; last_part->parent = parts->part; parts->nxt = last_part; if ((last_part = (PARTS *)mi_dalloc(sizeof(PARTS), PER_COMMAND)) == NULL) { mi_db_error_raise(conn, MI_SQL, ERR_ALLOC_FAILED, NULL); /* not reached */ } } } /* ** Completes the query execution for ** connection conn. */ mi_query_finish(conn); return(last_part); } #ifdef __cplusplus } #endif