📄 freetdsconnection.c
字号:
if (cursorquery.match(query)) { // initiate a cursor command cmd=cursorcmd;#ifdef FREETDS_SUPPORTS_CURSORS if (ct_cursor(cursorcmd,CS_CURSOR_DECLARE, (CS_CHAR *)cursorname,CS_NULLTERM, (CS_CHAR *)query,length, //CS_READ_ONLY)!=CS_SUCCEED) { CS_UNUSED)!=CS_SUCCEED) { return false; }#endif } else if (rpcquery.match(query)) { // initiate an rpc command isrpcquery=true; cmd=languagecmd;#ifdef FREETDS_SUPPORTS_CURSORS if (ct_command(languagecmd,CS_RPC_CMD, (CS_CHAR *)rpcquery.getSubstringEnd(0), length-rpcquery.getSubstringEndOffset(0), CS_UNUSED)!=CS_SUCCEED) { return false; }#endif } else { // initiate a language command cmd=languagecmd;#ifdef FREETDS_SUPPORTS_CURSORS if (ct_command(languagecmd,CS_LANG_CMD, (CS_CHAR *)query,length, CS_UNUSED)!=CS_SUCCEED) { return false; }#endif } clean=false; prepared=true; return true;}bool freetdscursor::supportsNativeBinds() {#ifdef FREETDS_SUPPORTS_CURSORS return true;#else return false;#endif}void freetdscursor::checkRePrepare() { // Sybase doesn't allow you to rebind and re-execute when using // ct_command. You have to re-prepare too. I'll make this transparent // to the user. if (!prepared) { prepareQuery(query,length); }}#ifdef FREETDS_SUPPORTS_CURSORSbool freetdscursor::inputBindString(const char *variable, uint16_t variablesize, const char *value, uint16_t valuesize, int16_t *isnull) { checkRePrepare(); (CS_VOID)rawbuffer::zero(¶meter[paramindex], sizeof(parameter[paramindex])); if (charstring::isInteger(variable+1,variablesize-1)) { parameter[paramindex].name[0]=(char)NULL; parameter[paramindex].namelen=0; } else { charstring::copy(parameter[paramindex].name,variable); parameter[paramindex].namelen=variablesize; } parameter[paramindex].datatype=CS_CHAR_TYPE; parameter[paramindex].maxlength=CS_UNUSED; parameter[paramindex].status=CS_INPUTVALUE; parameter[paramindex].locale=NULL; if (ct_param(cmd,¶meter[paramindex], (CS_VOID *)value,valuesize,0)!=CS_SUCCEED) { return false; } paramindex++; return true;}bool freetdscursor::inputBindInteger(const char *variable, uint16_t variablesize, int64_t *value) { checkRePrepare(); (CS_VOID)rawbuffer::zero(¶meter[paramindex], sizeof(parameter[paramindex])); if (charstring::isInteger(variable+1,variablesize-1)) { parameter[paramindex].name[0]=(char)NULL; parameter[paramindex].namelen=0; } else { charstring::copy(parameter[paramindex].name,variable); parameter[paramindex].namelen=variablesize; } parameter[paramindex].datatype=CS_INT_TYPE; parameter[paramindex].maxlength=CS_UNUSED; parameter[paramindex].status=CS_INPUTVALUE; parameter[paramindex].locale=NULL; if (ct_param(cmd,¶meter[paramindex], (CS_VOID *)value,sizeof(int64_t),0)!=CS_SUCCEED) { return false; } paramindex++; return true;}bool freetdscursor::inputBindDouble(const char *variable, uint16_t variablesize, double *value, uint32_t precision, uint32_t scale) { checkRePrepare(); (CS_VOID)rawbuffer::zero(¶meter[paramindex], sizeof(parameter[paramindex])); if (charstring::isInteger(variable+1,variablesize-1)) { parameter[paramindex].name[0]=(char)NULL; parameter[paramindex].namelen=0; } else { charstring::copy(parameter[paramindex].name,variable); parameter[paramindex].namelen=variablesize; } parameter[paramindex].datatype=CS_FLOAT_TYPE; parameter[paramindex].maxlength=CS_UNUSED; parameter[paramindex].status=CS_INPUTVALUE; parameter[paramindex].precision=precision; parameter[paramindex].scale=scale; parameter[paramindex].locale=NULL; if (ct_param(cmd,¶meter[paramindex], (CS_VOID *)value,sizeof(double),0)!=CS_SUCCEED) { return false; } paramindex++; return true;}bool freetdscursor::outputBindString(const char *variable, uint16_t variablesize, char *value, uint16_t valuesize, int16_t *isnull) { checkRePrepare(); outbindtype[outbindindex]=CS_CHAR_TYPE; outbindstrings[outbindindex]=value; outbindstringlengths[outbindindex]=valuesize; outbindindex++; (CS_VOID)rawbuffer::zero(¶meter[paramindex], sizeof(parameter[paramindex])); if (charstring::isInteger(variable+1,variablesize-1)) { parameter[paramindex].name[0]=(char)NULL; parameter[paramindex].namelen=0; } else { charstring::copy(parameter[paramindex].name,variable); parameter[paramindex].namelen=variablesize; } parameter[paramindex].datatype=CS_CHAR_TYPE; parameter[paramindex].maxlength=valuesize; parameter[paramindex].status=CS_RETURN; parameter[paramindex].locale=NULL; if (ct_param(cmd,¶meter[paramindex], (CS_VOID *)NULL,0, (CS_SMALLINT)*isnull)!=CS_SUCCEED) { return false; } paramindex++; return true;}bool freetdscursor::outputBindInteger(const char *variable, uint16_t variablesize, int64_t *value, int16_t *isnull) { checkRePrepare(); outbindtype[outbindindex]=CS_INT_TYPE; outbindints[outbindindex]=value; outbindindex++; (CS_VOID)rawbuffer::zero(¶meter[paramindex], sizeof(parameter[paramindex])); if (charstring::isInteger(variable+1,variablesize-1)) { parameter[paramindex].name[0]=(char)NULL; parameter[paramindex].namelen=0; } else { charstring::copy(parameter[paramindex].name,variable); parameter[paramindex].namelen=variablesize; } parameter[paramindex].datatype=CS_INT_TYPE; parameter[paramindex].maxlength=CS_UNUSED; parameter[paramindex].status=CS_RETURN; parameter[paramindex].locale=NULL; if (ct_param(cmd,¶meter[paramindex], (CS_VOID *)NULL,0, (CS_SMALLINT)*isnull)!=CS_SUCCEED) { return false; } paramindex++; return true;}bool freetdscursor::outputBindDouble(const char *variable, uint16_t variablesize, double *value, uint32_t *precision, uint32_t *scale, int16_t *isnull) { checkRePrepare(); outbindtype[outbindindex]=CS_FLOAT_TYPE; outbinddoubles[outbindindex]=value; outbindindex++; (CS_VOID)rawbuffer::zero(¶meter[paramindex], sizeof(parameter[paramindex])); if (charstring::isInteger(variable+1,variablesize-1)) { parameter[paramindex].name[0]=(char)NULL; parameter[paramindex].namelen=0; } else { charstring::copy(parameter[paramindex].name,variable); parameter[paramindex].namelen=variablesize; } parameter[paramindex].datatype=CS_FLOAT_TYPE; parameter[paramindex].maxlength=CS_UNUSED; parameter[paramindex].status=CS_RETURN; parameter[paramindex].locale=NULL; if (ct_param(cmd,¶meter[paramindex], (CS_VOID *)NULL,0, (CS_SMALLINT)*isnull)!=CS_SUCCEED) { return false; } paramindex++; return true;}#endifbool freetdscursor::executeQuery(const char *query, uint32_t length, bool execute) { // clear out any errors if (freetdsconn->errorstring) { freetdsconn->deadconnection=false; delete freetdsconn->errorstring; freetdsconn->errorstring=NULL; } if (ct_command(cmd,CS_LANG_CMD, (CS_CHAR *)query,length, CS_UNUSED)!=CS_SUCCEED) { return false; } clean=false; // initialize return values ncols=0; knowsaffectedrows=false; affectedrows=0; row=0; maxrow=0; totalrows=0;#ifdef FREETDS_SUPPORTS_CURSORS if (cmd==cursorcmd) { if (ct_cursor(cursorcmd,CS_CURSOR_ROWS, NULL,CS_UNUSED, NULL,CS_UNUSED, (CS_INT)FETCH_AT_ONCE)!=CS_SUCCEED) { return false; } if (ct_cursor(cursorcmd,CS_CURSOR_OPEN, NULL,CS_UNUSED, NULL,CS_UNUSED, CS_UNUSED)!=CS_SUCCEED) { return false; } }#endif if (ct_send(cmd)!=CS_SUCCEED) { cleanUpData(true,true); return false; } for (;;) { results=ct_results(cmd,&resultstype); if (results==CS_FAIL || resultstype==CS_CMD_FAIL || resultstype==CS_CMD_DONE) { cleanUpData(true,true); return false; } if (cmd==languagecmd) { if (isrpcquery) { // For rpc commands, there could be several // result sets - CS_STATUS_RESULT, // maybe a CS_PARAM_RESULT and maybe a // CS_ROW_RESULT, we're not guaranteed // what order they'll come in though, what // a pickle... // For now, we care about the CS_PARAM_RESULT, // or the CS_ROW_RESULT, whichever we get first, // presumably there will only be 1 row in the // CS_PARAM_RESULT... if (resultstype==CS_PARAM_RESULT || resultstype==CS_ROW_RESULT) { break; } } else { // For non-rpc language commands (non-selects), // there should be only one result set. break; } } else if (resultstype==CS_ROW_RESULT ||#ifdef FREETDS_SUPPORTS_CURSORS resultstype==CS_CURSOR_RESULT ||#endif resultstype==CS_COMPUTE_RESULT) { // For cursor commands (selects), each call to // ct_cursor will have generated a result set. There // will be result sets for the CS_CURSOR_DECLARE, // CS_CURSOR_ROWS and CS_CURSOR_OPEN calls. We need to // skip past the first 2, unless they failed. If they // failed, it will be caught above. break; } // if we got here, then we don't want to process this result // set, cancel it and move on to the next one... if (ct_cancel(NULL,cmd,CS_CANCEL_CURRENT)==CS_FAIL) { freetdsconn->deadconnection=true; // FIXME: call ct_close(CS_FORCE_CLOSE) return false; } } checkForTempTable(query,length); // reset the prepared flag prepared=false; // For queries which return rows or parameters (output bind variables), // get the column count and bind columns. For DML queries, get the // affected row count. // Affected row count is only supported in versio>=0.53 but appears // to be broken in 0.61 as well if (majorversion==0 && (minorversion<53 || minorversion==61)) { knowsaffectedrows=false; } else { knowsaffectedrows=true; } // For queries which return rows or parameters (output bind variables), // get the column count and bind columns. For DML queries, get the // affected row count. bool moneycolumn=false; affectedrows=0; if (resultstype==CS_ROW_RESULT ||#ifdef FREETDS_SUPPORTS_CURSORS resultstype==CS_CURSOR_RESULT ||#endif resultstype==CS_COMPUTE_RESULT || resultstype==CS_PARAM_RESULT) { if (ct_res_info(cmd,CS_NUMDATA,(CS_VOID *)&ncols, CS_UNUSED,(CS_INT *)NULL)!=CS_SUCCEED) { return false; } if (ncols>MAX_SELECT_LIST_SIZE) { ncols=MAX_SELECT_LIST_SIZE; } // bind columns for (CS_INT i=0; i<ncols; i++) { // dealing with money columns cause freetds < 0.53 to // crash, take care of that here... if (majorversion==0 && minorversion<53 && !moneycolumn) { CS_DATAFMT moneytest; ct_describe(cmd,i+1,&moneytest); if (moneytest.datatype==CS_MONEY_TYPE || moneytest.datatype==CS_MONEY4_TYPE) { moneycolumn=true; if (freetdsconn->errorstring) { delete freetdsconn->errorstring; } freetdsconn->errorstring= new stringbuffer(); freetdsconn->errorstring->append( "FreeTDS versions prior to "); freetdsconn->errorstring->append( "0.53 do not support MONEY "); freetdsconn->errorstring->append( "or SMALLMONEY datatypes. "); freetdsconn->errorstring->append( "Please upgrade SQL Relay to "); freetdsconn->errorstring->append( "a version compiled against "); freetdsconn->errorstring->append( "FreeTDS >= 0.53 "); } } // get the field as a null terminated character string // no longer than MAX_ITEM_BUFFER_SIZE, override some // other values that might have been set also column[i].datatype=CS_CHAR_TYPE; column[i].format=CS_FMT_NULLTERM; column[i].maxlength=MAX_ITEM_BUFFER_SIZE; column[i].scale=CS_UNUSED; column[i].precision=CS_UNUSED; column[i].status=CS_UNUSED; column[i].count=FETCH_AT_ONCE; column[i].usertype=CS_UNUSED; column[i].locale=NULL; // bind the columns for the fetches if (ct_bind(cmd,i+1,&column[i],(CS_VOID *)data[i], datalength[i],nullindicator[i])!=CS_SUCCEED) { break; } } } else if (resultstype==CS_CMD_SUCCEED && knowsaffectedrows) { if (ct_res_info(cmd,CS_ROW_COUNT,(CS_VOID *)&affectedrows, CS_UNUSED,(CS_INT *)NULL)!=CS_SUCCEED) { return false; } } // If we got a moneycolumn (and version<0.53) then cancel the // result set. Otherwise FreeTDS will spew "unknown marker" // errors to the screen when cleanUpData() is called. if (moneycolumn) { if (ct_cancel(NULL,cmd,CS_CANCEL_CURRENT)==CS_FAIL) { freetdsconn->deadconnection=true; // FIXME: call ct_close(CS_FORCE_CLOSE) return false; } return false; }
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -