IDE_RC cmpCallbackBASEHandshake(cmiProtocolContext *aProtocolContext, cmiProtocol *aProtocol, void * /*aSessionOwner*/, void * /*aUserContext*/) { cmpArgBASEHandshake *sArg = CMI_PROTOCOL_GET_ARG(*aProtocol, BASE, Handshake); cmmSession *sSession = aProtocolContext->mSession; UChar sBaseVersion; UChar sModuleVersion; /* * Module ID 검사 */ if (sSession != NULL) { IDE_TEST_RAISE(sSession->mModuleID != sArg->mModuleID, InvalidModule); } else { IDE_TEST_RAISE((sArg->mModuleID == CMP_MODULE_BASE) || (sArg->mModuleID >= CMP_MODULE_MAX), InvalidModule); } /* * 사용할 Version 세팅 */ sBaseVersion = IDL_MIN(sArg->mBaseVersion, gCmpModule[CMP_MODULE_BASE]->mVersionMax - 1); sModuleVersion = IDL_MIN(sArg->mModuleVersion, gCmpModule[sArg->mModuleID]->mVersionMax - 1); /* * Session에 Version 세팅 */ if (sSession != NULL) { sSession->mBaseVersion = sBaseVersion; sSession->mModuleVersion = sModuleVersion; } return answerHandshake(aProtocolContext, sBaseVersion, sArg->mModuleID, sModuleVersion); IDE_EXCEPTION(InvalidModule); { IDE_SET(ideSetErrorCode(cmERR_ABORT_INVALID_MODULE)); } IDE_EXCEPTION_END; return answerError(aProtocolContext); }
/* Append sorted list b to sorted list a. The result is unsorted but * a[1] is the min of the result and a[a[0]] is the max. */ int bdb_idl_append( ID *a, ID *b ) { ID ida, idb, tmp, swap = 0; if ( BDB_IDL_IS_ZERO( b ) ) { return 0; } if ( BDB_IDL_IS_ZERO( a ) ) { BDB_IDL_CPY( a, b ); return 0; } if ( b[0] == 1 ) { return bdb_idl_append_one( a, BDB_IDL_FIRST( b )); } ida = BDB_IDL_LAST( a ); idb = BDB_IDL_LAST( b ); if ( BDB_IDL_IS_RANGE( a ) || BDB_IDL_IS_RANGE(b) || a[0] + b[0] >= BDB_IDL_UM_MAX ) { a[2] = IDL_MAX( ida, idb ); a[1] = IDL_MIN( a[1], b[1] ); a[0] = NOID; return 0; } if ( ida > idb ) { swap = idb; a[a[0]] = idb; b[b[0]] = ida; } if ( b[1] < a[1] ) { tmp = a[1]; a[1] = b[1]; } else { tmp = b[1]; } a[0]++; a[a[0]] = tmp; { int i = b[0] - 1; AC_MEMCPY(a+a[0]+1, b+2, i * sizeof(ID)); a[0] += i; } if ( swap ) { b[b[0]] = swap; } return 0; }
static IDE_RC mtvEstimate( mtcNode* aNode, mtcTemplate* aTemplate, mtcStack* aStack, SInt, mtcCallBack* ) { SInt sPrecision; aStack[0].column = aTemplate->rows[aNode->table].columns+aNode->column; aTemplate->rows[aNode->table].execute[aNode->column] = mtvExecute; if( mtl::mNationalCharSet->id == MTL_UTF8_ID ) { sPrecision = IDL_MIN( aStack[1].column->precision, (SInt)MTD_UTF8_NCHAR_PRECISION_MAXIMUM); } else { sPrecision = IDL_MIN( aStack[1].column->precision, (SInt)MTD_UTF16_NCHAR_PRECISION_MAXIMUM); } IDE_TEST( mtc::initializeColumn( aStack[0].column, & mtdNvarchar, 1, sPrecision, 0 ) != IDE_SUCCESS ); return IDE_SUCCESS; IDE_EXCEPTION_END; return IDE_FAILURE; }
/* nbytes = MG_NET_RECV(socket, variable [, MAXIMUM_BYTES=b]) Reads the raw data available on the socket and returns a BYTE array in variable. The maximum number of bytes to read can be specified by the MAXIMUM_BYTES keyword. The default is to read all the data available on the socket. Note: no byteswapping is performed. */ static IDL_VPTR IDL_CDECL mg_net_recv(int argc, IDL_VPTR argv[], char *argk) { IDL_LONG i, iRet, err; int len; IDL_VPTR vpPlainArgs[2], vpTmp; char *pbuffer; static IDL_LONG iMax; static IDL_KW_PAR kw_pars[] = { IDL_KW_FAST_SCAN, { "MAXIMUM_BYTES", IDL_TYP_LONG, 1, IDL_KW_ZERO, 0, IDL_CHARA(iMax) }, { NULL } }; IDL_KWCleanup(IDL_KW_MARK); IDL_KWGetParams(argc, argv, argk, kw_pars, vpPlainArgs, 1); i = IDL_LongScalar(vpPlainArgs[0]); if ((i < 0) || (i >= MAX_SOCKETS)) return (IDL_GettmpLong(-1)); if (net_list[i].iState != NET_IO) return (IDL_GettmpLong(-1)); IDL_EXCLUDE_EXPR(vpPlainArgs[1]); err = IOCTL(net_list[i].socket, FIONREAD, &len); if (err != 0) { iRet = -1; goto err; } if (iMax) len = IDL_MIN(iMax, len); pbuffer = (char *) IDL_MakeTempVector(IDL_TYP_BYTE, len, IDL_ARR_INI_NOP, &vpTmp); IDL_VarCopy(vpTmp, vpPlainArgs[1]); iRet = recv(net_list[i].socket, pbuffer, len, 0); err: IDL_KWCleanup(IDL_KW_CLEAN); return(IDL_GettmpLong(iRet)); }
/* * idl_union - return a = a union b */ int bdb_idl_union( ID *a, ID *b ) { ID ida, idb; ID cursora = 0, cursorb = 0, cursorc; if ( BDB_IDL_IS_ZERO( b ) ) { return 0; } if ( BDB_IDL_IS_ZERO( a ) ) { BDB_IDL_CPY( a, b ); return 0; } if ( BDB_IDL_IS_RANGE( a ) || BDB_IDL_IS_RANGE(b) ) { over: ida = IDL_MIN( BDB_IDL_FIRST(a), BDB_IDL_FIRST(b) ); idb = IDL_MAX( BDB_IDL_LAST(a), BDB_IDL_LAST(b) ); a[0] = NOID; a[1] = ida; a[2] = idb; return 0; } ida = bdb_idl_first( a, &cursora ); idb = bdb_idl_first( b, &cursorb ); cursorc = b[0]; /* The distinct elements of a are cat'd to b */ while( ida != NOID || idb != NOID ) { if ( ida < idb ) { if( ++cursorc > BDB_IDL_UM_MAX ) { goto over; } b[cursorc] = ida; ida = bdb_idl_next( a, &cursora ); } else { if ( ida == idb ) ida = bdb_idl_next( a, &cursora ); idb = bdb_idl_next( b, &cursorb ); } } /* b is copied back to a in sorted order */ a[0] = cursorc; cursora = 1; cursorb = 1; cursorc = b[0]+1; while (cursorb <= b[0] || cursorc <= a[0]) { if (cursorc > a[0]) idb = NOID; else idb = b[cursorc]; if (cursorb <= b[0] && b[cursorb] < idb) a[cursora++] = b[cursorb++]; else { a[cursora++] = idb; cursorc++; } } return 0; }
/* * idl_intersection - return a = a intersection b */ int bdb_idl_intersection( ID *a, ID *b ) { ID ida, idb; ID idmax, idmin; ID cursora = 0, cursorb = 0, cursorc; int swap = 0; if ( BDB_IDL_IS_ZERO( a ) || BDB_IDL_IS_ZERO( b ) ) { a[0] = 0; return 0; } idmin = IDL_MAX( BDB_IDL_FIRST(a), BDB_IDL_FIRST(b) ); idmax = IDL_MIN( BDB_IDL_LAST(a), BDB_IDL_LAST(b) ); if ( idmin > idmax ) { a[0] = 0; return 0; } else if ( idmin == idmax ) { a[0] = 1; a[1] = idmin; return 0; } if ( BDB_IDL_IS_RANGE( a ) ) { if ( BDB_IDL_IS_RANGE(b) ) { /* If both are ranges, just shrink the boundaries */ a[1] = idmin; a[2] = idmax; return 0; } else { /* Else swap so that b is the range, a is a list */ ID *tmp = a; a = b; b = tmp; swap = 1; } } /* If a range completely covers the list, the result is * just the list. If idmin to idmax is contiguous, just * turn it into a range. */ if ( BDB_IDL_IS_RANGE( b ) && BDB_IDL_FIRST( b ) <= BDB_IDL_FIRST( a ) && BDB_IDL_LAST( b ) >= BDB_IDL_LAST( a ) ) { if (idmax - idmin + 1 == a[0]) { a[0] = NOID; a[1] = idmin; a[2] = idmax; } goto done; } /* Fine, do the intersection one element at a time. * First advance to idmin in both IDLs. */ cursora = cursorb = idmin; ida = bdb_idl_first( a, &cursora ); idb = bdb_idl_first( b, &cursorb ); cursorc = 0; while( ida <= idmax || idb <= idmax ) { if( ida == idb ) { a[++cursorc] = ida; ida = bdb_idl_next( a, &cursora ); idb = bdb_idl_next( b, &cursorb ); } else if ( ida < idb ) { ida = bdb_idl_next( a, &cursora ); } else { idb = bdb_idl_next( b, &cursorb ); } } a[0] = cursorc; done: if (swap) BDB_IDL_CPY( b, a ); return 0; }
IDE_RC mtfConvertEstimate( mtcNode* aNode, mtcTemplate* aTemplate, mtcStack* aStack, SInt /* aRemain */, mtcCallBack* aCallBack ) { const mtdModule* sModules[3]; SInt sPrecision; IDE_TEST_RAISE( ( aNode->lflag & MTC_NODE_QUANTIFIER_MASK ) == MTC_NODE_QUANTIFIER_TRUE, ERR_NOT_AGGREGATION ); IDE_TEST_RAISE( ( aNode->lflag & MTC_NODE_ARGUMENT_COUNT_MASK ) < 2 || ( aNode->lflag & MTC_NODE_ARGUMENT_COUNT_MASK ) > 3, ERR_INVALID_FUNCTION_ARGUMENT ); aStack[0].column = aTemplate->rows[aNode->table].columns + aNode->column; IDE_TEST( mtf::getCharFuncResultModule( &sModules[0], aStack[1].column->module ) != IDE_SUCCESS ); sModules[1] = &mtdVarchar; sModules[2] = &mtdVarchar; IDE_TEST( mtf::makeConversionNodes( aNode, aNode->arguments->next, aTemplate, aStack + 2, aCallBack, sModules + 1 ) != IDE_SUCCESS ); if( (aStack[1].column->module->id == MTD_NCHAR_ID) || (aStack[1].column->module->id == MTD_NVARCHAR_ID) ) { if( ( aNode->lflag & MTC_NODE_ARGUMENT_COUNT_MASK ) == 2 ) { aTemplate->rows[aNode->table].execute[aNode->column] = mtfExecuteNcharFor2Args; } else { aTemplate->rows[aNode->table].execute[aNode->column] = mtfExecuteNcharFor3Args; } // NCHAR의 precision은 문자의 개수이므로 // 결과 타입인 char의 precision은 max precision만큼 늘어날 수 있다. sPrecision = aStack[1].column->precision * MTL_MAX_PRECISION; sPrecision = IDL_MIN( aStack[1].column->precision * MTL_MAX_PRECISION, (SInt)MTD_UTF8_NCHAR_PRECISION_MAXIMUM ); } else { if( ( aNode->lflag & MTC_NODE_ARGUMENT_COUNT_MASK ) == 2 ) { aTemplate->rows[aNode->table].execute[aNode->column] = mtfExecuteFor2Args; } else { aTemplate->rows[aNode->table].execute[aNode->column] = mtfExecuteFor3Args; } // 캐릭터 셋 변환 후, 최대 2배까지 늘어날 수 있다. // ex) ASCII => UTF16 sPrecision = aStack[1].column->precision * 2; } IDE_TEST( mtc::initializeColumn( aStack[0].column, &mtdVarchar, 1, sPrecision, 0 ) != IDE_SUCCESS ); return IDE_SUCCESS; IDE_EXCEPTION( ERR_NOT_AGGREGATION ); IDE_SET(ideSetErrorCode(mtERR_ABORT_NOT_AGGREGATION)); IDE_EXCEPTION( ERR_INVALID_FUNCTION_ARGUMENT ); IDE_SET(ideSetErrorCode(mtERR_ABORT_INVALID_FUNCTION_ARGUMENT)); IDE_EXCEPTION_END; return IDE_FAILURE; }
IDE_RC mtfStuffCalculate( mtcNode* aNode, mtcStack* aStack, SInt aRemain, void* aInfo, mtcTemplate* aTemplate ) { /*********************************************************************** * * Description : Stuff Calculate * * Implementation : * STUFF ( char1, start, length, char2 ) * * aStack[0] : char1을 start부터 length만큼 지우고 그 사이에 char2를 삽입한 문자열 * aStack[1] : char1 ( 문자값 ) * aStack[2] : start ( 숫자값 ) * aStack[3] : length ( 숫자값 ) * aStack[4] : char2 ( 문자값 ) * * Ex) STUFF ('ABCDE', 3, 2, 'FGHK') ==> ABFGHKE * ***********************************************************************/ const mtlModule * sLanguage; mtdCharType * sResult; mtdCharType * sString1; mtdCharType * sString2; SInt sLength = 0; SInt sStart = 0; UChar * sIndex; UChar * sFence; UChar * sStartIndex; UChar * sEndIndex; UShort sResultIndex = 0; UShort sString1CharCount = 0; UShort sString2CharCount = 0; UShort i = 0; idBool sIsAllRemove = ID_FALSE; IDE_TEST( mtf::postfixCalculate( aNode, aStack, aRemain, aInfo, aTemplate ) != IDE_SUCCESS ); if( (aStack[1].column->module->isNull( aStack[1].column, aStack[1].value ) == ID_TRUE) || (aStack[2].column->module->isNull( aStack[2].column, aStack[2].value ) == ID_TRUE) || (aStack[3].column->module->isNull( aStack[3].column, aStack[3].value ) == ID_TRUE) ) { aStack[0].column->module->null( aStack[0].column, aStack[0].value ); } else { sLanguage = aStack[1].column->language; sResult = (mtdCharType*)aStack[0].value; sString1 = (mtdCharType*)aStack[1].value; sStart = *(mtdIntegerType*)aStack[2].value; sLength = *(mtdIntegerType*)aStack[3].value; sString2 = (mtdCharType*)aStack[4].value; sResultIndex = 0; IDE_TEST_RAISE( sLength < 0, ERR_ARGUMENT3_VALUE_OUT_OF_RANGE ); sString1CharCount = 0; sIndex = sString1->value; sFence = sIndex + sString1->length; // string1의 문자열의 길이( = 문자개수 )를 구함 while ( sIndex < sFence ) { (void)sLanguage->nextCharPtr( & sIndex, sFence ); sString1CharCount++; } //fix BUG-18161 IDE_TEST_RAISE( ( sStart > sString1CharCount + 1 ) || ( sStart < 1 ), ERR_ARGUMENT2_VALUE_OUT_OF_RANGE ); // BUG-25914 // stuff 수행 결과가 결과노드의 precision을 넘을 수 없다. if( (aStack[1].column->module->id == MTD_NCHAR_ID) || (aStack[1].column->module->id == MTD_NVARCHAR_ID) ) { //--------------------------------------------------------------------- // case 1. nchar / nvarchar // // start/length와 nchar/nvarchar의 precision과 의미가 같기 때문에 // stuff결과의 글자수로 최대 precision을 평가한다. // // 예제) 결과 / precision // stuff('abcde', 1, 3, 'xx') => xxde | 4 // stuff('abcde', 1, 5, 'xx') => xx | 2 // stuff('abcde', 3, 5, 'xx') => abcxx | 5 // stuff('abcde', 6, 3, 'xx') => abcdexx | 7 // stuff('abcde', 1, 5, '') => abcdexx | 7 // stuff('가ab나', 1, 2, '다라') => b다라나 | 4 // stuff('가ab나', 2, 3, '다라') => 가다라 | 3 // stuff('가ab나', 2, 8, '다라') => 가다라 | 3 //--------------------------------------------------------------------- sString2CharCount = 0; sIndex = sString2->value; sFence = sIndex + sString2->length; // string2의 문자열의 길이( = 문자개수 )를 구함. while ( sIndex < sFence ) { (void)sLanguage->nextCharPtr( & sIndex, sFence ); sString2CharCount++; } IDE_TEST_RAISE( ( sString1CharCount - IDL_MIN( sString1CharCount - sStart + 1, sLength) + sString2CharCount ) > aStack[0].column->precision, ERR_INVALID_LENGTH ); } else { //--------------------------------------------------------------------- // case 2. char / varchar // // char/varchar의 precision은 byte를 의미하기 때문에 // stuff결과의 byte수로 최대 precision을 평가한다. // // 예제) 결과 / precision // stuff('abcde', 1, 3, 'xx') => xxde | 4 // stuff('abcde', 1, 5, 'xx') => xx | 2 // stuff('abcde', 3, 5, 'xx') => abcxx | 5 // stuff('abcde', 6, 3, 'xx') => abcdexx | 7 // stuff('abcde', 1, 5, '') => abcdexx | 7 // stuff('가ab나', 1, 2, '다라') => b다라나 | 7 // stuff('가ab나', 2, 3, '다라') => 가다라 | 6 // stuff('가ab나', 2, 8, '다라') => 가다라 | 6 //--------------------------------------------------------------------- sIndex = sString1->value; sFence = sIndex + sString1->length; sResultIndex = 0; sStartIndex = sString1->value; sEndIndex = sString1->value; // char1에서 지울 문자의 byte길이를 구함. for( i = 1; sIndex < sFence ; i++ ) { (void)sLanguage->nextCharPtr( & sIndex, sFence ); if( i == sStart ) { sStartIndex = sIndex; } else { // Nothing to do. } if( (i == sStart + sLength) || (sIndex == sFence) ) { sEndIndex = sIndex; break; } else { // Nothing to do. } } IDE_TEST_RAISE( ( sString1->length - (sEndIndex - sStartIndex) + sString2->length ) > aStack[0].column->precision, ERR_INVALID_LENGTH ); } // 1. char1의 뒤에 char2를 삽일할 경우 // (sStart == sString1->length + 1, sLength는 상관없음) if ( sStart == sString1CharCount + 1 ) { sIndex = 0; sResultIndex = 0; idlOS::memcpy ( sResult->value, sString1->value, sString1->length ); sResultIndex = sResultIndex + sString1->length; idlOS::memcpy ( sResult->value + sResultIndex, sString2->value, sString2->length ); sResult->length = sString1->length + sString2->length; } // 2. char1에서 start 왼쪽에 char2를 삽입할 경우 (sStart > 0) else if ( sStart > 0 ) { sIndex = sString1->value; sFence = sIndex + sString1->length; sResultIndex = 0; // char1에서 start-1만큼 포인터 전진 후, start-1까지의 문자를 memcpy한다. for ( i = 0; i < sStart - 1; i++ ) { (void)sLanguage->nextCharPtr( & sIndex, sFence ); } // char1에서 1 ~ start-1까지 복사 idlOS::memcpy ( sResult->value + sResultIndex, sString1->value, sIndex - sString1->value ); sResultIndex += sIndex - sString1->value; // 삭제할 length가 char1을 초과하면 // start부터 char1의 마지막 문자까지의 문자 개수로 재설정 if ( sLength > sString1CharCount - sStart + 1) { sLength = sString1CharCount - sStart + 1; } // length 만큼 건너뛴다. for ( i = 0; i < sLength; i++ ) { (void)sLanguage->nextCharPtr( & sIndex, sFence ); // char1을 끝까지 삭제하면 sIsAllRemove flag 설정 if ( sIndex >= sFence ) { sIsAllRemove = ID_TRUE; } } // char2 문자 삽입 idlOS::memcpy (sResult->value + sResultIndex, sString2->value, sString2->length); sResultIndex = sResultIndex + sString2->length; // char1 남아있는 문자가 있는 경우 if ( sIsAllRemove == ID_FALSE ) { idlOS::memcpy (sResult->value + sResultIndex, sIndex, sString1->length - (sIndex - sString1->value) ); } sResult->length = sResultIndex + sString1->length - (sIndex - sString1->value); } else { //nothing to do } } return IDE_SUCCESS; IDE_EXCEPTION( ERR_INVALID_LENGTH ); { IDE_SET(ideSetErrorCode(mtERR_ABORT_INVALID_LENGTH)); } IDE_EXCEPTION( ERR_ARGUMENT2_VALUE_OUT_OF_RANGE ); { IDE_SET( ideSetErrorCode(mtERR_ABORT_ARGUMENT_VALUE_OUT_OF_RANGE, sStart ) ); } IDE_EXCEPTION( ERR_ARGUMENT3_VALUE_OUT_OF_RANGE ); { IDE_SET( ideSetErrorCode(mtERR_ABORT_ARGUMENT_VALUE_OUT_OF_RANGE, sLength ) ); } IDE_EXCEPTION_END; return IDE_FAILURE; }