📄 oracle8connection.c
字号:
if (OCILobGetLength(oracle8conn->svc, oracle8conn->err, lob,&loblength)!=OCI_SUCCESS) { conn->sendNullField(); return; } // handle empty lob's if (!loblength) { conn->startSendingLong(0); conn->sendLongSegment("",0); conn->endSendingLong(); return; } // We should be able to call OCILobRead over and over, // as long as it returns OCI_NEED_DATA, but OCILobRead // fails to return OCI_NEED_DATA (at least in version // 8.1.7 for Linux), so we have to do this instead. // OCILobRead appears to return OCI_INVALID_HANDLE when // the LOB is NULL, but this is not documented anywhere. while (retlen) { // initialize retlen to the number of characters we want to read retlen=charstoread; // read a segment from the lob sword retval=OCILobRead(oracle8conn->svc, oracle8conn->err, lob, &retlen, offset, (dvoid *)buf, oracle8conn->maxitembuffersize, (dvoid *)NULL, (sb4(*)(dvoid *,CONST dvoid *,ub4,ub1))NULL, (ub2)0, (ub1)SQLCS_IMPLICIT); // OCILobRead returns OCI_INVALID_HANDLE if // the LOB is NULL. In that case, return a // NULL field. // Otherwise, start sending the field (if we // haven't already), send a segment of the LOB, // move to the next segment and reset the // amount to read. if (retval==OCI_INVALID_HANDLE) { conn->sendNullField(); break; } else { if (start) { conn->startSendingLong(loblength); start=false; } conn->sendLongSegment((char *)buf,(int32_t)retlen); offset=offset+charstoread; } } // if we ever started sending a LOB, // finish sending it now if (!start) { conn->endSendingLong(); }}bool oracle8cursor::executeQuery(const char *query, uint32_t length, bool execute) { // initialize the column count ncols=0; // get the type of the query (select, insert, update, etc...) if (OCIAttrGet(stmt,OCI_HTYPE_STMT, (dvoid *)&stmttype,(ub4 *)NULL, OCI_ATTR_STMT_TYPE,oracle8conn->err)!=OCI_SUCCESS) { return false; }#ifdef HAVE_ORACLE_8i if (stmttype==OCI_STMT_CREATE) { checkForTempTable(query,length); }#endif // set up how many times to iterate; // 0 for selects, 1 for non-selects ub4 iters=1; if (stmttype==OCI_STMT_SELECT) { iters=0; } // initialize row counters row=0; maxrow=0; totalrows=0; // execute the query if (execute) { if (OCIStmtExecute(oracle8conn->svc,stmt, oracle8conn->err,iters, (ub4)0,NULL,NULL, oracle8conn->statementmode)!=OCI_SUCCESS) { return false; } // reset the prepared flag prepared=false; } // if the query is a select, describe/define it if (stmttype==OCI_STMT_SELECT) { // get the column count if (OCIAttrGet((dvoid *)stmt,OCI_HTYPE_STMT, (dvoid *)&ncols,(ub4 *)NULL, OCI_ATTR_PARAM_COUNT, oracle8conn->err)!=OCI_SUCCESS) { return false; } // run through the columns... for (sword i=0; i<ncols; i++) { // get the entire column definition if (OCIParamGet(stmt,OCI_HTYPE_STMT, oracle8conn->err, (dvoid **)&desc[i].paramd, i+1)!=OCI_SUCCESS) { return false; } // get the column name if (OCIAttrGet((dvoid *)desc[i].paramd, OCI_DTYPE_PARAM, (dvoid **)&desc[i].buf, (ub4 *)&desc[i].buflen, (ub4)OCI_ATTR_NAME, oracle8conn->err)!=OCI_SUCCESS) { return false; } // get the column type if (OCIAttrGet((dvoid *)desc[i].paramd, OCI_DTYPE_PARAM, (dvoid *)&desc[i].dbtype,(ub4 *)NULL, (ub4)OCI_ATTR_DATA_TYPE, oracle8conn->err)!=OCI_SUCCESS) { return false; } // get the column precision if (OCIAttrGet((dvoid *)desc[i].paramd, OCI_DTYPE_PARAM, (dvoid *)&desc[i].precision,(ub4 *)NULL, (ub4)OCI_ATTR_PRECISION, oracle8conn->err)!=OCI_SUCCESS) { return false; } // get the column scale if (OCIAttrGet((dvoid *)desc[i].paramd, OCI_DTYPE_PARAM, (dvoid *)&desc[i].scale,(ub4 *)NULL, (ub4)OCI_ATTR_SCALE, oracle8conn->err)!=OCI_SUCCESS) { return false; } // get whether the column is nullable if (OCIAttrGet((dvoid *)desc[i].paramd, OCI_DTYPE_PARAM, (dvoid *)&desc[i].nullok,(ub4 *)NULL, (ub4)OCI_ATTR_IS_NULL, oracle8conn->err)!=OCI_SUCCESS) { return false; } // is the column a LOB? if (desc[i].dbtype==BLOB_TYPE || desc[i].dbtype==CLOB_TYPE || desc[i].dbtype==BFILE_TYPE) { // return 0 for the size of lobs desc[i].dbsize=0; // set the NULL indicators to false rawbuffer::zero(def_indp[i], sizeof(sb2)* oracle8conn->fetchatonce); // allocate a lob descriptor for (uint32_t j=0; j<oracle8conn->fetchatonce; j++) { if (OCIDescriptorAlloc( (void *)oracle8conn->env, (void **)&def_lob[i][j], OCI_DTYPE_LOB,0,0)) { return false; } } // define the column as a lob if (OCIDefineByPos(stmt,&def[i], oracle8conn->err, i+1, (dvoid *)def_lob[i], (sb4)-1, desc[i].dbtype, (dvoid *)0, 0, (ub2 *)0, OCI_DEFAULT)!=OCI_SUCCESS) { return false; } } else { // get the column size if (OCIAttrGet((dvoid *)desc[i].paramd, OCI_DTYPE_PARAM, (dvoid *)&desc[i].dbsize, (ub4 *)NULL, (ub4)OCI_ATTR_DATA_SIZE, oracle8conn->err)!=OCI_SUCCESS) { return false; } // if the column is not a LOB, define it, // translated to a NULL terminated string if (OCIDefineByPos(stmt,&def[i], oracle8conn->err, i+1, (dvoid *)def_buf[i], (sb4)oracle8conn->maxitembuffersize, SQLT_STR, (dvoid *)def_indp[i], (ub2 *)def_col_retlen[i], def_col_retcode[i], OCI_DEFAULT)!=OCI_SUCCESS) { return false; } // set the lob member to NULL for (uint32_t j=0; j<oracle8conn->fetchatonce; j++) { def_lob[i][j]=NULL; } } } } // convert integer output binds for (uint16_t i=0; i<outbindcount; i++) { if (outintbindstring[i]) { *outintbind[i]=charstring:: toInteger(outintbindstring[i]); } } return true;}bool oracle8cursor::queryIsNotSelect() { return (stmttype!=OCI_STMT_SELECT);}bool oracle8cursor::queryIsCommitOrRollback() { // apparantly in OCI8, the cursor type gets // set to 0 for both commits and rollbacks return (!stmttype);}const char *oracle8cursor::errorMessage(bool *liveconnection) { // get the message from oracle text message[1024]; rawbuffer::zero((void *)message,sizeof(message)); sb4 errcode; OCIErrorGet((dvoid *)oracle8conn->err,1, (text *)0,&errcode, message,sizeof(message), OCI_HTYPE_ERROR); message[1023]=(char)NULL; // check for dead connection or shutdown in progress // Might need: 1033 - oracle init/shutdown in progress switch (errcode) { case 22: // invalid session ID; access denied case 28: // your session has been killed case 604: // error occurred at recursive SQL level ... case 1012: // not logged on case 1041: // internal error. hostdef extension doesn't exist case 1089: // immediate shutdown in progress - // no operations are permitted case 3114: // not connected to ORACLE case 3113: // end-of-file on communication channel case 3135: // connection lost contact *liveconnection=false; break; default: *liveconnection=true; } // only return an error message if the error wasn't a dead database delete errormessage; errormessage=new stringbuffer(); if (*liveconnection) { errormessage->append((const char *)message); } return errormessage->getString();}bool oracle8cursor::knowsRowCount() { return false;}uint64_t oracle8cursor::rowCount() { return 0;}bool oracle8cursor::knowsAffectedRows() { return true;}uint64_t oracle8cursor::affectedRows() { // get the affected row count ub4 rows; if (OCIAttrGet(stmt,OCI_HTYPE_STMT, (dvoid *)&rows,(ub4 *)NULL, OCI_ATTR_ROW_COUNT,oracle8conn->err)==OCI_SUCCESS) { return rows; } return 0;}uint32_t oracle8cursor::colCount() { return ncols;}const char * const * oracle8cursor::columnNames() { for (sword i=0; i<ncols; i++) { columnnames[i]=(char *)desc[i].buf; } return columnnames;}uint16_t oracle8cursor::columnTypeFormat() { return (uint16_t)COLUMN_TYPE_IDS;}void oracle8cursor::returnColumnInfo() { // a useful variable uint16_t type; // for each column... for (sword i=0; i<ncols; i++) { // set column type uint16_t binary=0; if (desc[i].dbtype==VARCHAR2_TYPE) { type=VARCHAR2_DATATYPE; } else if (desc[i].dbtype==NUMBER_TYPE) { type=NUMBER_DATATYPE; } else if (desc[i].dbtype==LONG_TYPE) { type=LONG_DATATYPE; } else if (desc[i].dbtype==ROWID_TYPE) { type=ROWID_DATATYPE; } else if (desc[i].dbtype==DATE_TYPE) { type=DATE_DATATYPE; } else if (desc[i].dbtype==RAW_TYPE) { type=RAW_DATATYPE; binary=1; } else if (desc[i].dbtype==LONG_RAW_TYPE) { type=LONG_RAW_DATATYPE; binary=1; } else if (desc[i].dbtype==CHAR_TYPE) { type=CHAR_DATATYPE; } else if (desc[i].dbtype==MLSLABEL_TYPE) { type=MLSLABEL_DATATYPE; } else if (desc[i].dbtype==BLOB_TYPE) { type=BLOB_DATATYPE; binary=1; } else if (desc[i].dbtype==CLOB_TYPE) { type=CLOB_DATATYPE; } else if (desc[i].dbtype==BFILE_TYPE) { type=BFILE_DATATYPE; binary=1; } else { type=UNKNOWN_DATATYPE; } // send the column definition conn->sendColumnDefinition((char *)desc[i].buf, (uint16_t)desc[i].buflen, type, (uint32_t)desc[i].dbsize, (uint32_t)desc[i].precision, (uint32_t)desc[i].scale, (uint16_t)desc[i].nullok,0,0, 0,0,0,binary,0); }}bool oracle8cursor::noRowsToReturn() { return (stmttype!=OCI_STMT_SELECT);}bool oracle8cursor::skipRow() { if (fetchRow()) { row++; return true; } return false;}bool oracle8cursor::fetchRow() { if (row==oracle8conn->fetchatonce) { row=0; } if (row>0 && row==maxrow) { return false; } if (!row) { OCIStmtFetch(stmt,oracle8conn->err,oracle8conn->fetchatonce, OCI_FETCH_NEXT,OCI_DEFAULT); ub4 currentrow; OCIAttrGet(stmt,OCI_HTYPE_STMT, (dvoid *)¤trow,(ub4 *)NULL, OCI_ATTR_ROW_COUNT,oracle8conn->err); if (currentrow==totalrows) { return false; } maxrow=currentrow-totalrows; totalrows=currentrow; } return true;}void oracle8cursor::returnRow() { for (sword col=0; col<ncols; col++) { // handle NULL's if (def_indp[col][row]) { conn->sendNullField(); continue; } // in OCI8, longs are just like other datatypes, but LOBS // are different if (desc[col].dbtype==BLOB_TYPE || desc[col].dbtype==CLOB_TYPE || desc[col].dbtype==BFILE_TYPE) { // send the lob sendLob(def_lob[col][row], &def_buf[col][row*oracle8conn-> maxitembuffersize]);#ifdef HAVE_ORACLE_8i // if the lob is temporary, deallocate it boolean templob; if (OCILobIsTemporary(oracle8conn->env, oracle8conn->err, def_lob[col][row], &templob)!=OCI_SUCCESS) { continue; } if (templob) { OCILobFreeTemporary(oracle8conn->svc, oracle8conn->err, def_lob[col][row]); }#endif continue; } // handle normal datatypes conn->sendField((const char *) &def_buf[col] [row*oracle8conn-> maxitembuffersize], (uint32_t)def_col_retlen[col][row]); } // increment the row counter row++;}void oracle8cursor::cleanUpData(bool freeresult, bool freebinds) { // OCI8 version of ocan(), but since it uses OCIStmtFetch we // only want to run it if the statement was a select if (freeresult && stmttype==OCI_STMT_SELECT) { OCIStmtFetch(stmt,oracle8conn->err,0, OCI_FETCH_NEXT,OCI_DEFAULT); } // free row/column resources if (freeresult) { for (ub4 i=0; i<oracle8conn->maxselectlistsize; i++) { for (uint32_t j=0; j<oracle8conn->fetchatonce; j++) { if (def_lob[i][j]) { OCIDescriptorFree(def_lob[i][j], OCI_DTYPE_LOB); def_lob[i][j]=NULL; } } // should be able to alloc these in openCursor() and // free them in closeCursor() rather than letting // OCIDefineByPos() alloc them and having to clear // them here, but the alloc fails if (def[i]) { OCIHandleFree(def[i],OCI_HTYPE_DEFINE); def[i]=NULL; } } } if (freebinds) { // free lob bind resources#ifdef HAVE_ORACLE_8i for (uint16_t i=0; i<inbindlobcount; i++) { OCILobFreeTemporary(oracle8conn->svc, oracle8conn->err, inbind_lob[i]); OCILobClose(oracle8conn->svc,oracle8conn->err, inbind_lob[i]); OCIDescriptorFree(inbind_lob[i],OCI_DTYPE_LOB); } for (uint16_t i=0; i<outbindlobcount; i++) { if (outbind_lob[i]) { OCILobFreeTemporary(oracle8conn->svc, oracle8conn->err, outbind_lob[i]); OCILobClose(oracle8conn->svc, oracle8conn->err, outbind_lob[i]); OCIDescriptorFree(outbind_lob[i], OCI_DTYPE_LOB); } } inbindlobcount=0; outbindlobcount=0;#endif // free regular bind resources for (uint16_t i=0; i<inbindcount; i++) { delete[] inintbindstring[i]; inintbindstring[i]=NULL; } for (uint16_t i=0; i<outbindcount; i++) { delete[] outintbindstring[i]; outintbindstring[i]=NULL; outintbind[i]=NULL; } inbindcount=0; outbindcount=0; curbindcount=0; }}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -