FNC_TblOpGetBaseInfo()を使用して、UDTメタデータを取得するCテーブル演算子の例です。
/* CREATE FUNCTION mift1() RETURNS TABLE VARYING USING FUNCTION mift1_contract SPECIFIC mift1 LANGUAGE C NO SQL NO EXTERNAL DATA PARAMETER STYLE SQLTable NOT DETERMINISTIC CALLED ON NULL INPUT EXTERNAL NAME 'CS!mift1!mift1.c!F!mift1'; */
#define SQL_TEXT Latin_Text #include <stdio.h> #include <sqltypes_td.h> #define BufferSize (32*1024) #define SetError(e, m) strcpy((char *)sqlstate, ( e) ); strcpy((char *)error_message, ( m ))
typedef struct { int colcount; FNC_TblOpColumnDef_t *iCols; FNC_TblOpHandle_t *Handle; int is_eof; int dimension; }InputInfo_t;
int mift1_contract( INTEGER *Result, int *indicator_Result, char sqlstate[6], SQL_TEXT extname[129], SQL_TEXT specific_name[129], SQL_TEXT error_message[257]) { FNC_TblOpColumnDef_t *oCols; FNC_TblOpColumnDef_t *iCols; Stream_Fmt_en format; InputInfo_t *icolinfo; int incount, outcount, ocolcount; int i,j, totalcols; UDT_BaseInfo_t *baseInfos; char mycontract[] = "this is my contract... this is my contract... this is my contract..."; FNC_TblOpGetStreamCount(&incount, &outcount); if(incount == 0) { SetError("U0003", "mift1 requires number of input streams to be > 0."); return -1; } icolinfo = FNC_malloc (incount * sizeof(InputInfo_t)); totalcols = 0; for(i=0; i < incount; i++) { icolinfo[i].colcount = FNC_TblOpGetColCount(i, ISINPUT); totalcols += icolinfo[i].colcount; icolinfo[i].iCols = FNC_malloc(TblOpSIZECOLDEF(icolinfo[i].colcount)); TblOpINITCOLDEF(icolinfo[i].iCols, icolinfo[i].colcount); FNC_TblOpGetColDef(i, ISINPUT, icolinfo[i].iCols); } /* Allocate space for columns. */ oCols = (FNC_TblOpColumnDef_t *)FNC_malloc( TblOpSIZECOLDEF(totalcols) ); memset(oCols, 0 , TblOpSIZECOLDEF(totalcols) ); oCols->num_columns = totalcols; oCols->length = TblOpSIZECOLDEF(totalcols) - (2 * sizeof(int)) ; TblOpINITCOLDEF(oCols, totalcols); ocolcount = 0; /* Copy input columns to output columns. */ for(j=0; j < incount; j++) { iCols = icolinfo[j].iCols; baseInfos = (UDT_BaseInfo_t *)FNC_malloc(iCols->num_columns * sizeof(UDT_BaseInfo_t)); /* Get base info */ FNC_TblOpGetBaseInfo(iCols, baseInfos); for(i=0;i < iCols->num_columns;i++) { switch (iCols->column_types[i].datatype) { case DECIMAL1_DT: case DECIMAL4_DT: case DECIMAL8_DT: oCols->column_types[ocolcount].size.range.totaldigit = iCols->column_types[i].size.range.totaldigit; oCols->column_types[ocolcount].size.range.fracdigit = iCols->column_types[i].size.range.fracdigit; break; case DECIMAL2_DT: oCols->column_types[ocolcount].size.range.totaldigit= 5; oCols->column_types[ocolcount].size.range.fracdigit= iCols->column_types[i].size.range.fracdigit; break; case TIME_DT: case TIMESTAMP_DT: case PERIOD_DT: oCols->column_types[ocolcount].size.precision = iCols->column_types[i].size.precision; break; case INTERVAL_YEAR_DT: case INTERVAL_YTM_DT: case INTERVAL_MONTH_DT: case INTERVAL_DAY_DT: case INTERVAL_DTH_DT: case INTERVAL_DTM_DT: case INTERVAL_DTS_DT: case INTERVAL_HOUR_DT: case INTERVAL_HTM_DT: case INTERVAL_HTS_DT: case INTERVAL_MINUTE_DT: case INTERVAL_MTS_DT: case INTERVAL_SECOND_DT: oCols->column_types[ocolcount].size.intervalrange = iCols->column_types[i].size.intervalrange; break; case JSON_DT: oCols->column_types[ocolcount].JSONStorageFormat = JSON_TEXT_EN; oCols->column_types[ocolcount].charset = iCols->column_types[i].charset; oCols->column_types[ocolcount].size.length = iCols->column_types[i].size.length; oCols->column_types[ocolcount].udt_indicator = 5; memcpy(oCols->column_types[ocolcount].udt_type, icols->column_types[i].udt_type, FNC_MAXNAMELEN_EON); break; case ARRAY_DT: oCols->column_types[ocolcount].charset = iCols->column_types[i].charset; oCols->column_types[ocolcount].size.length = iCols->column_types[i].size.length; oCols->column_types[ocolcount].udt_indicator = 4; memcpy(oCols->column_types[ocolcount].udt_type, icols->column_types[i].udt_type, FNC_MAXNAMELEN_EON); oCols->column_types[ocolcount].struct_num_attributes= iCols->column_types[i].struct_num_attributes; break; default: oCols->column_types[ocolcount].size.length = iCols->column_types[i].size.length; oCols->column_types[ocolcount].charset = LATIN_CT; break; } oCols->column_types[ocolcount].datatype = iCols->column_types[i].datatype; oCols->column_types[ocolcount].period_et = iCols->column_types[i].period_et; oCols->column_types[ocolcount].bytesize = iCols->column_types[i].bytesize; ocolcount++; } FNC_free(baseInfos); } FNC_TblOpSetContractDef(mycontract, strlen(mycontract)+1); /* Define output columns. */ FNC_TblOpSetOutputColDef(0, oCols); format = INDICFMT1; FNC_TblOpSetFormat("RECFMT", 0, ISINPUT, &format, sizeof(format)); FNC_TblOpSetFormat("RECFMT", 0, ISOUTPUT, &format, sizeof(format)); FNC_free(oCols); for(i=0; i < incount; i++) FNC_free(icolinfo[i].iCols); FNC_free(icolinfo); *Result = 1; }
void mift1() { int i; FNC_TblOpColumnDef_t *iCols, *oCols; FNC_TblOpHandle_t *Handle,*OutHandle; Stream_Fmt_en format; int incount, outcount,j; InputInfo_t *icolinfo; int *Result; int allStreamsEOF = 0; LOB_CONTEXT_ID lobid; FNC_LobLength_t actlen; LOB_RESULT_LOCATOR lrl_a[32]; int truncerr; BYTE Buffer[BufferSize]; int foundrow = 0; int isfirsttime = 1; FNC_TblOpGetStreamCount(&incount, &outcount); icolinfo = FNC_malloc (incount * sizeof(InputInfo_t)); for(i=0; i < incount; i++) { /* Get Column Count */ icolinfo[i].colcount = FNC_TblOpGetColCount(i, ISINPUT); /* Get Column Definitions */ icolinfo[i].iCols = FNC_malloc(TblOpSIZECOLDEF(icolinfo[i].colcount)); TblOpINITCOLDEF(icolinfo[i].iCols, icolinfo[i].colcount); FNC_TblOpGetColDef(i, ISINPUT, icolinfo[i].iCols); /* Get Handles */ icolinfo[i].Handle = (FNC_TblOpHandle_t *)FNC_TblOpOpen(i,'r',0); icolinfo[i].dimension = FNC_TblOpIsDimension(i,ISINPUT); icolinfo[i].is_eof = 0; } Result = FNC_malloc(incount * SIZEOF_INTEGER); OutHandle = (FNC_TblOpHandle_t*)FNC_TblOpOpen(0,'w',0); isfirsttime = 1; while(1) { allStreamsEOF = 1; int ocount; for(j=0; j < incount; j++) { if ( icolinfo[j].is_eof == 0) Result[j] = FNC_TblOpRead(icolinfo[j].Handle); if( Result[j] == TBLOP_EOF) icolinfo[j].is_eof = 1; else if( Result[j] == TBLOP_SUCCESS) icolinfo[j].is_eof = 0; allStreamsEOF = allStreamsEOF & icolinfo[j].is_eof; } if(allStreamsEOF) break; /* We will write the o/p if atleast one non-dimesion o/p found a row */ foundrow = 0 ; if( isfirsttime == 1 ) { for( j=0; j < incount; j++) { if (icolinfo[j].dimension == 0 && icolinfo[j].is_eof == 0) { foundrow = 1; } } } if ( isfirsttime == 1 && foundrow == 0) break; isfirsttime = 0; ocount = 0; for(j=0; j < incount; j++) { Handle = icolinfo[j].Handle; iCols = icolinfo[j].iCols; for (i=0; i < iCols->num_columns; i++) { switch (iCols->column_types[i].datatype) { case CLOB_REFERENCE_DT: case BLOB_REFERENCE_DT: case JSON_DT: case XML_DT: case ST_GEOMETRY_DT: /* This is output code, as we only have 1 outputstream should be 0 */ lrl_a[ocount] = FNC_LobCol2Loc(0, ocount); if(icolinfo[j].is_eof == 0) { if (!(TBLOPISNULL(Handle->row->indicators,i))) { FNC_LobOpen_CL(Handle->row->columnptr[i], &lobid, 0, 0); truncerr = 0; while( FNC_LobRead(lobid, Buffer, BufferSize, &actlen) == 0 && !truncerr) truncerr=FNC_LobAppend (lrl_a[ocount], Buffer, actlen, &actlen); FNC_LobClose(lobid); } } break; default: if(icolinfo[j].is_eof == 0) { OutHandle->row->columnptr[ocount] = Handle->row->columnptr[i]; OutHandle->row->lengths[ocount] = Handle->row->lengths[i]; } break; } if (icolinfo[j].is_eof == 1 || TBLOPISNULL(Handle->row->indicators,i)) { TBLOPSETNULL(OutHandle->row->indicators,ocount); } ocount++; } } FNC_TblOpWrite(OutHandle); // Writes current output row } for(i=0; i < incount; i++) { FNC_free(icolinfo[i].iCols); FNC_TblOpClose(icolinfo[i].Handle); // close all contexts } FNC_free(icolinfo); FNC_free(Result); FNC_TblOpClose(OutHandle); // close all contexts }