📄 firebirdconnection.c
字号:
// make sure each output bind variable gets null terminated for (short i=0; i<outsqlda->sqld; i++) { if (outbindisstring[i]) { outsqlda->sqlvar[i]. sqldata[outsqlda->sqlvar[i].sqllen-1]=0; } } // set column count to 0 outsqlda->sqld=0; return retval; } // handle non-stored procedures... // describe the cursor outsqlda->sqld=0; if (isc_dsql_describe(firebirdconn->error,&stmt,1,outsqlda)) { return false; } if (outsqlda->sqld>MAX_SELECT_LIST_SIZE) { outsqlda->sqld=MAX_SELECT_LIST_SIZE; } for (short i=0; i<outsqlda->sqld; i++) { // save the actual field type field[i].type=outsqlda->sqlvar[i].sqltype; // handle the null indicator outsqlda->sqlvar[i].sqlind=&field[i].nullindicator; // coerce the datatypes and point where the data should go if (outsqlda->sqlvar[i].sqltype==SQL_TEXT || outsqlda->sqlvar[i].sqltype==SQL_TEXT+1) { outsqlda->sqlvar[i].sqldata=field[i].textbuffer; field[i].sqlrtype=CHAR_DATATYPE; } else if (outsqlda->sqlvar[i].sqltype==SQL_VARYING || outsqlda->sqlvar[i]. sqltype==SQL_VARYING+1) { outsqlda->sqlvar[i].sqldata=field[i].textbuffer; field[i].sqlrtype=VARCHAR_DATATYPE; } else if (outsqlda->sqlvar[i].sqltype==SQL_SHORT || outsqlda->sqlvar[i].sqltype==SQL_SHORT+1) { outsqlda->sqlvar[i].sqldata= (char *)&field[i].shortbuffer; field[i].sqlrtype=SMALLINT_DATATYPE; // Looks like sometimes firebird returns INT64's as // SQL_LONG type. These can be identified because // the sqlscale gets set too. Treat SQL_LONG's with // an sqlscale as INT64's. } else if ((outsqlda->sqlvar[i].sqltype==SQL_LONG || outsqlda->sqlvar[i].sqltype==SQL_LONG+1) && !outsqlda->sqlvar[i].sqlscale) { outsqlda->sqlvar[i].sqldata= (char *)&field[i].longbuffer; field[i].sqlrtype=INTEGER_DATATYPE; } else if ( #ifdef SQL_INT64 (outsqlda->sqlvar[i].sqltype==SQL_INT64 || outsqlda->sqlvar[i].sqltype==SQL_INT64+1) || #endif ((outsqlda->sqlvar[i].sqltype==SQL_LONG || outsqlda->sqlvar[i].sqltype==SQL_LONG+1) && outsqlda->sqlvar[i].sqlscale)) { outsqlda->sqlvar[i].sqldata= (char *)&field[i].int64buffer; if (outsqlda->sqlvar[i].sqlsubtype==1) { field[i].sqlrtype=NUMERIC_DATATYPE; } else { field[i].sqlrtype=DECIMAL_DATATYPE; } } else if (outsqlda->sqlvar[i].sqltype==SQL_FLOAT || outsqlda->sqlvar[i].sqltype==SQL_FLOAT+1) { outsqlda->sqlvar[i].sqldata= (char *)&field[i].floatbuffer; field[i].sqlrtype=FLOAT_DATATYPE; } else if (outsqlda->sqlvar[i].sqltype==SQL_DOUBLE || outsqlda->sqlvar[i].sqltype==SQL_DOUBLE+1) { outsqlda->sqlvar[i].sqldata= (char *)&field[i].doublebuffer; field[i].sqlrtype=DOUBLE_PRECISION_DATATYPE; } else if (outsqlda->sqlvar[i].sqltype==SQL_D_FLOAT || outsqlda->sqlvar[i].sqltype==SQL_D_FLOAT+1) { outsqlda->sqlvar[i].sqldata= (char *)&field[i].doublebuffer; field[i].sqlrtype=D_FLOAT_DATATYPE; } else if (outsqlda->sqlvar[i].sqltype==SQL_ARRAY || outsqlda->sqlvar[i].sqltype==SQL_ARRAY+1) { outsqlda->sqlvar[i].sqldata= (char *)&field[i].quadbuffer; field[i].sqlrtype=ARRAY_DATATYPE; } else if (outsqlda->sqlvar[i].sqltype==SQL_QUAD || outsqlda->sqlvar[i].sqltype==SQL_QUAD+1) { outsqlda->sqlvar[i].sqldata= (char *)&field[i].quadbuffer; field[i].sqlrtype=QUAD_DATATYPE; #ifdef SQL_TIMESTAMP } else if (outsqlda->sqlvar[i].sqltype==SQL_TIMESTAMP || outsqlda->sqlvar[i]. sqltype==SQL_TIMESTAMP+1) { #else } else if (outsqlda->sqlvar[i].sqltype==SQL_DATE || outsqlda->sqlvar[i].sqltype==SQL_DATE+1) { #endif outsqlda->sqlvar[i].sqldata= (char *)&field[i].timestampbuffer; field[i].sqlrtype=TIMESTAMP_DATATYPE; #ifdef SQL_TIMESTAMP } else if (outsqlda->sqlvar[i].sqltype==SQL_TYPE_TIME || outsqlda->sqlvar[i]. sqltype==SQL_TYPE_TIME+1) { outsqlda->sqlvar[i].sqldata= (char *)&field[i].timebuffer; field[i].sqlrtype=TIME_DATATYPE; } else if (outsqlda->sqlvar[i].sqltype==SQL_TYPE_DATE || outsqlda->sqlvar[i]. sqltype==SQL_TYPE_DATE+1) { outsqlda->sqlvar[i].sqldata= (char *)&field[i].datebuffer; field[i].sqlrtype=DATE_DATATYPE; #endif } else if (outsqlda->sqlvar[i].sqltype==SQL_BLOB || outsqlda->sqlvar[i].sqltype==SQL_BLOB+1) { outsqlda->sqlvar[i].sqltype=SQL_BLOB; outsqlda->sqlvar[i].sqldata=(char *)NULL; field[i].sqlrtype=BLOB_DATATYPE; } else { outsqlda->sqlvar[i].sqltype=SQL_VARYING; outsqlda->sqlvar[i].sqldata=field[i].textbuffer; field[i].sqlrtype=UNKNOWN_DATATYPE; } } // Execute the query return !isc_dsql_execute(firebirdconn->error,&firebirdconn->tr, &stmt,1,insqlda);}bool firebirdcursor::queryIsNotSelect() { return (querytype!=isc_info_sql_stmt_select);}bool firebirdcursor::queryIsCommitOrRollback() { return (querytype==isc_info_sql_stmt_commit || querytype==isc_info_sql_stmt_rollback);}const char *firebirdcursor::errorMessage(bool *liveconnection) { char msg[512]; ISC_STATUS *pvector=firebirdconn->error; // declare a buffer for the error if (errormsg) { delete errormsg; } errormsg=new stringbuffer(); // get the status message while (isc_interprete(msg,&pvector)) { errormsg->append(msg)->append(" \n"); } // get the error message // FIXME: vladimir commented this out why? ISC_LONG sqlcode=isc_sqlcode(firebirdconn->error); isc_sql_interprete(sqlcode, msg, 512); errormsg->append(msg); *liveconnection=!(charstring::contains( errormsg->getString(), "Error reading data from the connection") || charstring::contains( errormsg->getString(), "Error writing data to the connection")); return errormsg->getString();}bool firebirdcursor::knowsRowCount() { return false;}uint64_t firebirdcursor::rowCount() { return 0;}bool firebirdcursor::knowsAffectedRows() { return false;}uint64_t firebirdcursor::affectedRows() { return 0;}uint32_t firebirdcursor::colCount() { // for exec procedure queries, outsqlda contains output bind values // rather than column info and there is no result set, thus no column // info return outsqlda->sqld;}const char * const *firebirdcursor::columnNames() { for (short i=0; i<outsqlda->sqld; i++) { columnnames[i]=outsqlda->sqlvar[i].sqlname; } return columnnames;}uint16_t firebirdcursor::columnTypeFormat() { return (uint16_t)COLUMN_TYPE_IDS;}void firebirdcursor::returnColumnInfo() { short precision; // for each column... for (short i=0; i<outsqlda->sqld; i++) { if (field[i].sqlrtype==CHAR_DATATYPE) { precision=outsqlda->sqlvar[i].sqllen; } else if (field[i].sqlrtype==VARCHAR_DATATYPE) { precision=outsqlda->sqlvar[i].sqllen; } else if (field[i].sqlrtype==SMALLINT_DATATYPE) { precision=5; } else if (field[i].sqlrtype==INTEGER_DATATYPE) { precision=11; } else if (field[i].sqlrtype==NUMERIC_DATATYPE) { // FIXME: can be from 1 to 18 // (oddly, scale is given as a negative number) precision=18+outsqlda->sqlvar[i].sqlscale; } else if (field[i].sqlrtype==DECIMAL_DATATYPE) { // FIXME: can be from 1 to 18 // (oddly, scale is given as a negative number) precision=18+outsqlda->sqlvar[i].sqlscale; } else if (field[i].sqlrtype==FLOAT_DATATYPE) { precision=0; } else if (field[i].sqlrtype==DOUBLE_PRECISION_DATATYPE) { precision=0; } else if (field[i].sqlrtype==D_FLOAT_DATATYPE) { precision=0; } else if (field[i].sqlrtype==ARRAY_DATATYPE) { // not sure precision=0; } else if (field[i].sqlrtype==QUAD_DATATYPE) { // not sure precision=0; } else if (field[i].sqlrtype==TIMESTAMP_DATATYPE) { // not sure precision=0; } else if (field[i].sqlrtype==TIME_DATATYPE) { precision=8; } else if (field[i].sqlrtype==DATE_DATATYPE) { precision=10; } else if (field[i].sqlrtype==BLOB_DATATYPE) { precision=outsqlda->sqlvar[i].sqllen; } else if (field[i].sqlrtype==UNKNOWN_DATATYPE) { precision=outsqlda->sqlvar[i].sqllen; } // send column definition // (oddly, scale is given as a negative number) conn->sendColumnDefinition(outsqlda->sqlvar[i].sqlname, charstring::length( outsqlda->sqlvar[i].sqlname), field[i].sqlrtype, outsqlda->sqlvar[i].sqllen, precision, -outsqlda->sqlvar[i].sqlscale,0,0,0, 0,0,0,0,0); }}bool firebirdcursor::noRowsToReturn() { // for exec procedure queries, outsqlda contains output bind values // rather than a result set and there is no result set return (queryIsExecSP)?true:!outsqlda->sqld;}bool firebirdcursor::skipRow() { return fetchRow();}bool firebirdcursor::fetchRow() { ISC_STATUS retcode; if ((retcode=isc_dsql_fetch(firebirdconn->error, &stmt,1,outsqlda))) { // if retcode is 100L, then there are no more rows, // otherwise, there is an error... how do I handle this? return false; } return true;}void firebirdcursor::returnRow() { for (short col=0; col<outsqlda->sqld; col++) { // handle a null field if ((outsqlda->sqlvar[col].sqltype & 1) && field[col].nullindicator==-1) { conn->sendNullField(); continue; } // handle a non-null field if (outsqlda->sqlvar[col].sqltype==SQL_TEXT || outsqlda->sqlvar[col].sqltype==SQL_TEXT+1) { size_t maxlen=outsqlda->sqlvar[col].sqllen; size_t reallen=charstring::length(field[col]. textbuffer); if (reallen>maxlen) { reallen=maxlen; } conn->sendField(field[col].textbuffer,reallen); } else if (outsqlda->sqlvar[col]. sqltype==SQL_SHORT || outsqlda->sqlvar[col]. sqltype==SQL_SHORT+1) { stringbuffer buffer; buffer.append(field[col].shortbuffer); conn->sendField(buffer.getString(), charstring::length(buffer.getString())); } else if (outsqlda->sqlvar[col]. sqltype==SQL_FLOAT || outsqlda->sqlvar[col]. sqltype==SQL_FLOAT+1) { stringbuffer buffer; buffer.append((double)field[col].floatbuffer); conn->sendField(buffer.getString(), charstring::length(buffer.getString())); } else if (outsqlda->sqlvar[col]. sqltype==SQL_DOUBLE || outsqlda->sqlvar[col]. sqltype==SQL_DOUBLE+1 || outsqlda->sqlvar[col]. sqltype==SQL_D_FLOAT || outsqlda->sqlvar[col]. sqltype==SQL_D_FLOAT+1) { stringbuffer buffer; buffer.append((double)field[col].doublebuffer); conn->sendField(buffer.getString(), charstring::length(buffer.getString())); } else if (outsqlda->sqlvar[col]. sqltype==SQL_VARYING || outsqlda->sqlvar[col]. sqltype==SQL_VARYING+1) { // the first 2 bytes are the length in // an SQL_VARYING field int16_t size; rawbuffer::copy((void *)&size, (void *)field[col].textbuffer, sizeof(int16_t)); conn->sendField(field[col].textbuffer+sizeof(int16_t), size); // Looks like sometimes firebird returns INT64's as // SQL_LONG type. These can be identified because // the sqlscale gets set too. Treat SQL_LONG's with // an sqlscale as INT64's. } else if ((outsqlda->sqlvar[col]. sqltype==SQL_LONG || outsqlda->sqlvar[col]. sqltype==SQL_LONG+1) && !outsqlda->sqlvar[col].sqlscale) { stringbuffer buffer; buffer.append((int32_t)field[col].longbuffer); conn->sendField(buffer.getString(), charstring::length(buffer.getString())); } else if ( #ifdef SQL_INT64 (outsqlda->sqlvar[col]. sqltype==SQL_INT64 || outsqlda->sqlvar[col]. sqltype==SQL_INT64+1) || #endif ((outsqlda->sqlvar[col]. sqltype==SQL_LONG || outsqlda->sqlvar[col]. sqltype==SQL_LONG+1) && outsqlda->sqlvar[col].sqlscale)) { // int64's are weird. To the left of the decimal // point is the value/10^scale, to the right is // value%10^scale stringbuffer buffer; if (outsqlda->sqlvar[col].sqlscale) { buffer.append((int64_t)(field[col].int64buffer/(int)pow(10.0,(double)-outsqlda->sqlvar[col].sqlscale)))->append("."); stringbuffer decimal; decimal.append((int64_t)(field[col].int64buffer%(int)pow(10.0,(double)-outsqlda->sqlvar[col].sqlscale))); // gotta get the right number // of decimal places for (int32_t i=charstring::length( decimal.getString()); i<-outsqlda->sqlvar[col].sqlscale; i++) { decimal.append("0"); } buffer.append(decimal.getString()); } else { buffer.append((int64_t)field[col].int64buffer); } conn->sendField(buffer.getString(), charstring::length(buffer.getString())); } else if (outsqlda->sqlvar[col].sqltype==SQL_ARRAY || outsqlda->sqlvar[col].sqltype==SQL_ARRAY+1 || outsqlda->sqlvar[col].sqltype==SQL_QUAD || outsqlda->sqlvar[col].sqltype==SQL_QUAD+1) { // have to handle arrays for real here... conn->sendNullField(); #ifdef SQL_TIMESTAMP } else if (outsqlda->sqlvar[col].sqltype==SQL_TIMESTAMP || outsqlda->sqlvar[col].sqltype==SQL_TIMESTAMP+1) { // decode the timestamp tm entry_timestamp; isc_decode_timestamp(&field[col].timestampbuffer, &entry_timestamp); #else } else if (outsqlda->sqlvar[col].sqltype==SQL_DATE || outsqlda->sqlvar[col].sqltype==SQL_DATE+1) { // decode the timestamp tm entry_timestamp; isc_decode_date(&field[col].timestampbuffer, &entry_timestamp); #endif // build a string of "yyyy-mm-dd hh:mm:ss" format char buffer[20]; snprintf(buffer,20,"%d-%02d-%02d %02d:%02d:%02d", entry_timestamp.tm_year+1900, entry_timestamp.tm_mon+1, entry_timestamp.tm_mday, entry_timestamp.tm_hour, entry_timestamp.tm_min, entry_timestamp.tm_sec); conn->sendField(buffer,19); #ifdef SQL_TIMESTAMP } else if (outsqlda->sqlvar[col].sqltype==SQL_TYPE_TIME || outsqlda->sqlvar[col].sqltype==SQL_TYPE_TIME+1) { // decode the time tm entry_time; isc_decode_sql_time(&field[col].timebuffer, &entry_time); // build a string of "hh:mm:ss" format char buffer[9]; snprintf(buffer,9,"%02d:%02d:%02d", entry_time.tm_hour, entry_time.tm_min, entry_time.tm_sec); conn->sendField(buffer,8); } else if (outsqlda->sqlvar[col].sqltype==SQL_TYPE_DATE || outsqlda->sqlvar[col].sqltype==SQL_TYPE_DATE+1) { // decode the date tm entry_date; isc_decode_sql_date(&field[col].datebuffer, &entry_date); // build a string of "yyyy-mm-dd" format char buffer[11]; snprintf(buffer,11,"%d:%02d:%02d", entry_date.tm_year+1900, entry_date.tm_mon+1, entry_date.tm_mday); conn->sendField(buffer,10); #endif } else if (outsqlda->sqlvar[col].sqltype==SQL_BLOB || outsqlda->sqlvar[col].sqltype==SQL_BLOB+1) { // have to handle blobs for real here... conn->sendNullField(); } }}void firebirdcursor::cleanUpData(bool freeresult, bool freebinds) { if (freebinds) { outbindcount=0; }}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -