📄 resultset.cpp
字号:
case SQL_FETCH_ABSOLUTE: if(rowNum==0) { location_=BEFORE_FIRST; } else { location_=AFTER_LAST; } break; case SQL_FETCH_NEXT: case SQL_FETCH_LAST: location_=AFTER_LAST; break; case SQL_FETCH_FIRST: case SQL_FETCH_PRIOR: location_=BEFORE_FIRST; break; default: //notreached assert(false); } } else { // for forward only cursors, we don't bother fetching the location // we just increment it for each fetch if(isfo) { if(location_<=0) { location_=1; } else { location_+=currentFetchSize_; } } else { SQLUINTEGER l=statement_->_getNumericOption (ODBC3_C(SQL_ATTR_ROW_NUMBER,SQL_ROW_NUMBER)); if(l==0) { location_=UNKNOWN; } else { location_=(int)l; } } }}void ResultSet::_handleStreams(SQLRETURN r){ if(r==SQL_NEED_DATA) { ODBCXX_CHAR_TYPE buf[PUTDATA_CHUNK_SIZE]; while(r==SQL_NEED_DATA) { SQLPOINTER currentCol; r=SQLParamData(hstmt_,¤tCol); this->_checkStmtError(hstmt_,r,ODBCXX_STRING_CONST("SQLParamData failure")); if(r==SQL_NEED_DATA) { DataHandler* dh=rowset_->getColumn((int)currentCol); assert(dh->isStreamed_); int charsPut=0; ODBCXX_STREAM* s=dh->getStream(); int b; while((b=readStream(s,buf,PUTDATA_CHUNK_SIZE))>0) { charsPut+=b; SQLRETURN rPD=SQLPutData(hstmt_,(SQLPOINTER)buf,b*sizeof(ODBCXX_CHAR_TYPE)); this->_checkStmtError(hstmt_,rPD,ODBCXX_STRING_CONST("SQLPutData failure")); } if(charsPut==0) { // SQLPutData has not been called SQLRETURN rPD=SQLPutData(hstmt_,(SQLPOINTER)buf,0); this->_checkStmtError(hstmt_,rPD,ODBCXX_STRING_CONST("SQLPutData(0) failure")); } } } }}int ResultSet::getType(){ return statement_->getResultSetType();}int ResultSet::getConcurrency(){ return statement_->getResultSetConcurrency();}void ResultSet::setFetchSize(int fs){ CHECK_INSERT_ROW; if(fs==0) { fs=SQL_ROWSET_SIZE_DEFAULT; //1 } if(fs>0) { newFetchSize_=fs; if(fs!=currentFetchSize_) { //ok, we'll need to change it //if we are before/after the resultset, it's ok to proceed now if(!LOCATION_IS_VALID) { currentFetchSize_=fs; this->_applyFetchSize(); } } } else { throw SQLException (ODBCXX_STRING_CONST("[libodbc++]: Invalid fetch size ")+intToString(fs)); }}bool ResultSet::next(){ CHECK_INSERT_ROW; if(LOCATION_IS_VALID && rowset_->getCurrentRow()+1 < rowsInRowset_) { //we just move inside the rowset rowset_->setCurrentRow(rowset_->getCurrentRow()+1); this->_applyPosition(); return true; } else if(location_==AFTER_LAST) { //no more to come return false; } //we now know for sure we have to do a fetch this->_prepareForFetch(); this->_doFetch(SQL_FETCH_NEXT,0); if(LOCATION_IS_VALID) { this->_applyPosition(); return true; } return false;}bool ResultSet::previous(){ CHECK_INSERT_ROW; CHECK_SCROLLABLE_CURSOR; if(LOCATION_IS_VALID && rowset_->getCurrentRow()>0) { //alright, just move inside the rowset rowset_->setCurrentRow(rowset_->getCurrentRow()-1); this->_applyPosition(); return true; } else if(location_==BEFORE_FIRST) { //no rows there.. return false; } else { //if, we have, say a rowset that covers rows 10-30, and //we request the previous, we get rows 1-20. Then //we'll have to adjust to position to the //right row int oldloc=location_; this->_prepareForFetch(); this->_doFetch(SQL_FETCH_PRIOR,0); if(LOCATION_IS_VALID) { if(oldloc>0 && oldloc-location_ < currentFetchSize_) { rowset_->setCurrentRow(oldloc-2); //1 for 1-based location, 1 for previous } else { //just the last row in the rowset rowset_->setCurrentRow(rowsInRowset_-1); } this->_applyPosition(); return true; } else { return false; } }}bool ResultSet::first(){ CHECK_INSERT_ROW; CHECK_SCROLLABLE_CURSOR; // don't trust any positions, just fetch the first rowset this->_prepareForFetch(); this->_doFetch(SQL_FETCH_FIRST,0); if(LOCATION_IS_VALID) { this->_applyPosition(); return true; } return false;}bool ResultSet::last(){ CHECK_INSERT_ROW; CHECK_SCROLLABLE_CURSOR; this->_prepareForFetch(); this->_doFetch(SQL_FETCH_LAST,0); if(LOCATION_IS_VALID) { rowset_->setCurrentRow(rowsInRowset_-1); this->_applyPosition(); return true; } else { return false; }}bool ResultSet::relative(int rows){ CHECK_INSERT_ROW; CHECK_SCROLLABLE_CURSOR; if(!LOCATION_IS_VALID) { throw SQLException (ODBCXX_STRING_CONST("[libodbc++]: ResultSet::relative(): no current row")); } if(rows==0) { return true; } if(rows>0 && rowset_->getCurrentRow() < rowsInRowset_-rows) { rowset_->setCurrentRow(rowset_->getCurrentRow()+rows); } else if(rows<0 && rowset_->getCurrentRow() >= -rows) { rowset_->setCurrentRow(rowset_->getCurrentRow()+rows); } else { //since SQL_FETCH_RELATIVE is relative to the start of the rowset //we'll need to adjust rows-=rowset_->getCurrentRow(); this->_prepareForFetch(); this->_doFetch(SQL_FETCH_RELATIVE,rows); } if(LOCATION_IS_VALID) { this->_applyPosition(); return true; } else { return false; }}bool ResultSet::absolute(int row){ CHECK_INSERT_ROW; CHECK_SCROLLABLE_CURSOR; this->_prepareForFetch(); this->_doFetch(SQL_FETCH_ABSOLUTE,row); if(LOCATION_IS_VALID) { this->_applyPosition(); return true; } return false;}void ResultSet::beforeFirst(){ CHECK_INSERT_ROW; CHECK_SCROLLABLE_CURSOR; if(location_!=BEFORE_FIRST) { this->absolute(0); }}void ResultSet::afterLast(){ CHECK_INSERT_ROW; CHECK_SCROLLABLE_CURSOR; if(location_!=AFTER_LAST) { this->_prepareForFetch(); this->_doFetch(SQL_FETCH_LAST,0); //now on last rowset this->_doFetch(SQL_FETCH_NEXT,0); //now after last rowset }}void ResultSet::moveToInsertRow(){ CHECK_SCROLLABLE_CURSOR; if(location_!=INSERT_ROW) { rowBeforeInsert_=rowset_->getCurrentRow(); locBeforeInsert_=location_; rowset_->setCurrentRow(currentFetchSize_); location_=INSERT_ROW; }}void ResultSet::moveToCurrentRow(){ CHECK_SCROLLABLE_CURSOR; if(location_==INSERT_ROW) { if(bindPos_>0) { assert(this->_getDriverInfo()->getMajorVersion()>2); // this occurs after we have inserted rows // with an ODBC3 driver // restore our fetch size and // rebind with the real positions statement_->_setNumericOption (ODBC3_C(SQL_ATTR_ROW_ARRAY_SIZE,SQL_ROWSET_SIZE), currentFetchSize_); rowset_->setCurrentRow(0); this->_bindCols(); // this mirrors rowset_->getCurrentRow() assert(bindPos_==0); if(locBeforeInsert_>0) { // we know our remembered position this->_doFetch(SQL_FETCH_ABSOLUTE, locBeforeInsert_); } else { switch(locBeforeInsert_) { case AFTER_LAST: this->_doFetch(SQL_FETCH_ABSOLUTE,-1); this->_doFetch(SQL_FETCH_NEXT,0); break; case BEFORE_FIRST: case UNKNOWN: // inconsistent default: this->_doFetch(SQL_FETCH_ABSOLUTE,0); } } } else { // we are in the right rowset already location_=locBeforeInsert_; } if(LOCATION_IS_VALID) { rowset_->setCurrentRow(rowBeforeInsert_); this->_applyPosition(); } else { rowset_->setCurrentRow(0); } }}void ResultSet::insertRow(){ CHECK_SCROLLABLE_CURSOR; if(location_==INSERT_ROW) { // first, decide whether we use SQLBulkOperations // or SQLSetPos#if ODBCVER >= 0x0300 if(this->_getDriverInfo()->getMajorVersion()==3) { if(bindPos_==0) { // this is the first time we call insertRow() // while on the insert row statement_->_setNumericOption (ODBC3_C(SQL_ATTR_ROW_ARRAY_SIZE,SQL_ROWSET_SIZE),1); // this would bind only the last row of our rowset this->_bindCols(); assert(bindPos_>0); } this->_bindStreamedCols(); SQLRETURN r=SQLBulkOperations(hstmt_,SQL_ADD); try { this->_checkStmtError(hstmt_,r,ODBCXX_STRING_CONST("SQLBulkOperations failed")); } catch(...) { this->_unbindStreamedCols(); throw; } this->_handleStreams(r); this->_unbindStreamedCols(); rowset_->afterUpdate(); return; }#endif // we are using SQLSetPos(SQL_ADD) to insert a row SQLRETURN r; this->_bindStreamedCols(); try { r=this->_applyPosition(SQL_ADD); } catch(...) { this->_unbindStreamedCols(); throw; } this->_handleStreams(r); this->_unbindStreamedCols(); rowset_->afterUpdate(); } else { throw SQLException (ODBCXX_STRING_CONST("[libodbc++]: Not on insert row")); }}void ResultSet::updateRow(){ CHECK_SCROLLABLE_CURSOR; CHECK_INSERT_ROW; if(!LOCATION_IS_VALID) { throw SQLException (ODBCXX_STRING_CONST("[libodbc++]: No current row")); } this->_bindStreamedCols(); // With ODBC3, the operation below will change our // rowsInRowset_, so we save it SQLRETURN r; {#if ODBCVER >= 0x0300 ValueSaver<SQLUINTEGER> _rows(rowsInRowset_);#endif r=this->_applyPosition(SQL_UPDATE); } this->_handleStreams(r); this->_unbindStreamedCols(); rowset_->afterUpdate();}void ResultSet::refreshRow(){ CHECK_SCROLLABLE_CURSOR;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -