oraub8 SqlLob::length() { if(!is_not_null()) return 0; bool done = false; oraub8 len; while(!done) { sword res = OCICALL(OCILobGetLength2(_conn._svc_ctx, _conn._env._errh, _loc, &len)); if( res != OCI_SUCCESS ) { sb4 errorcode; sword res2 = OCICALL(OCIErrorGet(_conn._env._errh, 1, NULL, &errorcode, NULL, 0, OCI_HTYPE_ERROR)); assert(res2 == OCI_SUCCESS); if(errorcode == 3127) // ORA-03127: no new operations allowed until the active operation ends { std::cerr << "ORA-03127: no new operations allowed until the active operation ends" << std::endl; MSLEEP(100); } else { oci_check_error(__TROTL_HERE__, _conn._env._errh, res); } } else { done = true; } } return len; };
/*--------------------------------------------------------------------- * query_withROWID - query the source db with rowid *---------------------------------------------------------------------*/ static void query_withROWID(oci_t *ocip, myctx_t *myctx, char* rowid, ub2 rowidl, boolean idkey) { oratext tmp [2048]; oratext *sqlstmt = (oratext *) "select count(*) from %.*s where ROWID = '%.*s'"; OCIDefine *defnp1 = (OCIDefine *) NULL; OCIBind *bindp1 = (OCIBind *)NULL; ub4 count = 0; sprintf((char *)tmp, (char *)sqlstmt, myctx->onamelen, myctx->oname, rowidl, rowid); printf(">>> query statement = %s\n", tmp); OCICALL(ocip, OCIStmtPrepare(ocip->stmtp, ocip->errp, (CONST text *)tmp, (ub4)strlen((char *)tmp), (ub4)OCI_NTV_SYNTAX, (ub4)OCI_DEFAULT)); OCICALL(ocip,OCIDefineByPos(ocip->stmtp, &defnp1, ocip->errp, (ub4) 1, (dvoid*) &count, (sb4) sizeof(count), (ub2)SQLT_INT, (dvoid*) 0, (ub2 *) 0, (ub2 *) 0, OCI_DEFAULT)); OCICALL(ocip, OCIStmtExecute(ocip->svcp, ocip->stmtp, ocip->errp, (ub4)1, (ub4)0, (const OCISnapshot *)0, (OCISnapshot *)0, (ub4)OCI_DEFAULT)); printf ("\n>>> query result: count = %d\n", count); }
/* * I am not sure here, OCILobAssign or just simple pointer assign? */ void ConvertorForRead::Fire(const BindParClob &BP, SqlClob &CL) { CL._ind = BP.indp[_row]; if(CL.is_not_null()) { if(BP.isTemporary(_row)) { sword res = OCICALL(OCILobLocatorAssign(BP._stmt._conn._svc_ctx, BP._env._errh, ((OCILobLocator**)BP.valuep)[_row], &CL._loc)); oci_check_error(__TROTL_HERE__, BP._env._errh, res); } else { sword res = OCICALL(OCILobAssign(BP._env, BP._env._errh, ((OCILobLocator**)BP.valuep)[_row], &CL._loc)); oci_check_error(__TROTL_HERE__, BP._env._errh, res); } //CL._loc = ((OCILobLocator**)BP.valuep)[_row]; //((OCILobLocator**)BP.valuep)[_row] = NULL; //CL._ind = BP.indp[_row]; //#if ORACLE_MAJOR_VERSION>=8 && ORACLE_MINOR_VERSION>=1 // res = OCICALL(OCILobLocatorAssign(_conn._svc_ctx, _conn._env._errh, other._loc, &_loc)); //#else // res = OCICALL(OCILobAssign(_conn._env, _conn._env._errh, other._loc, &_loc)); // no support for temporary LOBs //#endif } };
SqlOpenLob::~SqlOpenLob() { bool done = false; while(!done) { sword res = OCICALL(OCILobClose( _lob._conn._svc_ctx, _lob._conn._env._errh, _lob._loc )); if( res != OCI_SUCCESS ) { sb4 errorcode; sword res2 = OCICALL(OCIErrorGet(_lob._conn._env._errh, 1, NULL, &errorcode, NULL, 0, OCI_HTYPE_ERROR)); assert(res2 == OCI_SUCCESS); if(errorcode == 3127) // ORA-03127: no new operations allowed until the active operation ends { std::cerr << "ORA-03127: no new operations allowed until the active operation ends" << std::endl; MSLEEP(100); } else { oci_check_error(__TROTL_HERE__, _lob._conn._env._errh, res); } } else { done = true; } } };
SqlLob::~SqlLob() { // According to the Oracle 10g documentation we should try to free // implicit created temporary LOBs as soon as possible. if (isTemporary()) { sword res = OCICALL(OCILobFreeTemporary(_conn._svc_ctx, _conn._env._errh, _loc)); oci_check_error(__TROTL_HERE__, _conn._env._errh, res); } sword res = OCICALL(OCIDescriptorFree(_loc, OCI_DTYPE_LOB)); oci_check_error(__TROTL_HERE__, _conn._env, res); };
bool SqlLob::isOpen() const { bOOlean flag; sword res = OCICALL(OCILobIsOpen(_conn._svc_ctx, _conn._env._errh, _loc, &flag)); oci_check_error(__TROTL_HERE__, _conn._env._errh, res); return !!flag; };
bool SqlLob::operator==(const SqlLob& other) const { bOOlean is_equal; sword res = OCICALL(OCILobIsEqual(_conn._env, _loc, other._loc, &is_equal)); oci_check_error(__TROTL_HERE__, _conn._env, res); return !!is_equal; };
bool BindParLob::isTemporary(unsigned _row) const { bOOlean flag; sword res = OCICALL(OCILobIsTemporary(_env, _env._errh, ((OCILobLocator**)valuep)[_row], &flag)); oci_check_error(__TROTL_HERE__, _env._errh, res); return !!flag; }
/*--------------------------------------------------------------------- * get_chunks - Get all the chunks belonging to the current LCR. *---------------------------------------------------------------------*/ static void get_chunks(myctx_t *ctx) { oratext *colname; ub2 colname_len; ub2 coldty; oraub8 col_flags; ub2 col_csid; ub4 bytes_rd; ub1 *buffer; oraub8 row_flag; sword err; sb4 rtncode; oci_t *ocip = ctx->outbound_ocip; /* Loop to receive each chunk until there is no more data for the current * row change. */ do { OCICALL(ocip, OCIXStreamOutChunkReceive(ocip->svcp, ocip->errp, &colname, &colname_len, &coldty, &col_flags, &col_csid, &bytes_rd, &buffer, &row_flag, OCI_DEFAULT)); print_chunk_cb(ctx, colname, colname_len, coldty, col_flags, col_csid, bytes_rd, buffer, row_flag); } while (row_flag & OCI_XSTREAM_MORE_ROW_DATA); }
bool SqlLob::isTemporary() const { bOOlean flag; sword res = OCICALL(OCILobIsTemporary(_conn._env, _conn._env._errh, _loc, &flag)); oci_check_error(__TROTL_HERE__, _conn._env._errh, res); return !!flag; };
/* * NOTE: !! offset has to be >= 1. Oracle's LOBs start at 1st byte. */ oraub8 SqlClob::read(dvoid* bufp, oraub8 buflen, oraub8 offset, oraub8 amount, oraub8 *chars, ub2 csid, ub1 csfrm) { oraub8 char_amt = 0; bool done = false; while(!done) { sword res = OCICALL(OCILobRead2( _conn._svc_ctx, _conn._env._errh, _loc, &amount, &char_amt, offset, bufp, buflen, OCI_ONE_PIECE, /* ub1 piece */ NULL, /* dvoid* ctxp */ NULL, /* sb4 (*cbfp)(dvoid*ctxp,CONST dvoid*bufp,oraub8*len,ub1*piece) */ 0 /* csid */, 0 /* csfrm */ )); if( res != OCI_SUCCESS ) { sb4 errorcode; sword res2 = OCICALL(OCIErrorGet(_conn._env._errh, 1, NULL, &errorcode, NULL, 0, OCI_HTYPE_ERROR)); assert(res2 == OCI_SUCCESS); if(errorcode == 24804) // ORA-24804: Lob read/write functions called while another OCI LOB read/write streaming is in progress { std::cerr << "ORA-24804: Lob read/write functions called while another OCI LOB read/write streaming is in progress" << std::endl; MSLEEP(100); } else { oci_check_error(__TROTL_HERE__, _conn._env._errh, res); } } else { done = true; } } if(chars) *chars = char_amt; return amount; };
ub4 BindParLob::getChunkSize(unsigned _row) const { ub4 retval; sword res = OCICALL(OCILobGetChunkSize(_stmt._conn._svc_ctx, _env._errh, ((OCILobLocator**)valuep)[_row], &retval)); oci_check_error(__TROTL_HERE__, _env._errh, res); return retval; }
void BindParLob::descAlloc(void) //TODO OCI_DTYPE_FILE for BFILE, CFILE { for(unsigned i=0; i<_cnt; ++i) { sword res = OCICALL(OCIDescriptorAlloc(_env, &((void**)valuep)[i], OCI_DTYPE_LOB, 0, NULL)); oci_check_error(__TROTL_HERE__, _env, res); } }
/*--------------------------------------------------------------------- * getRowID - Get RowID of this ID Key LCR *---------------------------------------------------------------------*/ static sword getRowID (myctx_t* ctxp, void* lcrp, oratext* rowid, ub2* len) { oci_t *ocip = ctxp->outbound_ocip; ub2 i = 0; ub2 num_attrs = 0; void *attr_value[OCI_LCR_MAX_ATTRIBUTES]; oratext *attr_name [OCI_LCR_MAX_ATTRIBUTES]; ub2 attr_namel[OCI_LCR_MAX_ATTRIBUTES]; ub2 attr_dty[OCI_LCR_MAX_ATTRIBUTES]; OCIInd attr_ind[OCI_LCR_MAX_ATTRIBUTES]; ub2 attr_len[OCI_LCR_MAX_ATTRIBUTES]; if (rowid == NULL) return OCI_ERROR; /* get the attributes for this lcr */ OCICALL(ocip, OCILCRAttributesGet(ocip->svcp, ocip->errp, &num_attrs, attr_name, attr_namel, attr_dty, attr_value, attr_ind, attr_len, lcrp, OCI_LCR_MAX_ATTRIBUTES, OCI_DEFAULT)); if (num_attrs == 0) return OCI_ERROR; for (i = 0; i < num_attrs; i++) { /* filter out Row_ID for this LCR */ if ((attr_ind[i] != OCI_IND_NULL) && !strncmp ((const char*)attr_name[i], OCI_LCR_ATTR_ROW_ID, attr_namel[i]) && (attr_dty[i] == SQLT_RDD)) { OCIRowid *rid = attr_value[i]; oratext rid_buf[80]; ub2 reslen = (ub2)sizeof(rid_buf); OCICALL(ocip, OCIRowidToChar(rid, rid_buf, &reslen, ocip->errp)); memcpy (rowid, rid_buf, reslen); *len = reslen; return OCI_SUCCESS; } } return OCI_ERROR; }
oraub8 SqlBlob::write(const dvoid* bufp, oraub8 buflen, oraub8 offset/*=1*/, oraub8 amount) { sword res = OCICALL(OCILobWrite2(_conn._svc_ctx, _conn._env._errh, _loc, &amount, NULL, offset, (dvoid*)bufp, buflen, OCI_ONE_PIECE/*ub1 piece*/, NULL/*dvoid* ctxp*/, NULL/*sb4 (*cbfp)(dvoid*ctxp,dvoid*bufp,ub4*len,ub1*piece)*/, 0, 0)); oci_check_error(__TROTL_HERE__, _conn._env._errh, res); return amount; };
tstring BindParRid::get_string(unsigned int i) const { if(indp[i] == OCI_IND_NULL) return ""; OraText buffer[4001]; ub2 outbfl = sizeof(buffer); sword res = OCICALL(OCIRowidToChar(((OCIRowid**)valuep)[i], buffer, &outbfl, _stmt._errh)); oci_check_error(__TROTL_HERE__, _stmt._errh, res); return tstring((char*)buffer, outbfl); }
void ConvertorForRead::Fire(const BindParCFile &BP, SqlClob &CL) { CL._ind = BP.indp[_row]; if(CL.is_not_null()) { sword res = OCICALL(OCILobAssign(BP._env, BP._env._errh, ((OCILobLocator**)BP.valuep)[_row], &CL._loc)); oci_check_error(__TROTL_HERE__, BP._env._errh, res); char dirname[33], filename[256]; ub2 dirnamelen = sizeof(dirname); ub2 filenamelen = sizeof(filename); res = OCICALL(OCILobFileGetName(BP._env, BP._env._errh, ((OCILobLocator**)BP.valuep)[_row], (OraText*)dirname, &dirnamelen, (OraText*)filename, &filenamelen )); oci_check_error(__TROTL_HERE__, BP._env._errh, res); CL._dirname = tstring(dirname, dirnamelen); CL._filename = tstring(filename, filenamelen); } };
ub4 SqlLob::getChunkSize() { ub4 size = 8132; // 8132 value usually returned for blobs if (_dirname.empty()) { // OCILobGetChunkSize works only for real BLOBs not for BFILEs sword res = OCICALL( OCILobGetChunkSize(_conn._svc_ctx, _conn._env._errh, _loc, &size)); oci_check_error(__TROTL_HERE__, _conn._env._errh, res); } return size; };
void ConvertorForRead::Fire(const BindParCollectionTabVarchar &BP, SqlCollection &SV) { sword res; SV._collection_tdo = BP._collection_tdo; SV._collection_typecode = BP._collection_typecode; SV._collection_data_type = BP._collection_data_type; SV._ind = *(sb2*)(BP._collection_indp[_row]); SV._data_type_name = BP._type_name; res = OCICALL(OCIObjectNew(BP._stmt._env, BP._stmt._errh, BP._stmt._conn._svc_ctx, OCI_TYPECODE_TABLE, // TabNum => Table BP._collection_tdo, NULL, // dvoid *table OCI_DURATION_SESSION, TRUE, // boolean value (dvoid**) &SV._valuep)); oci_check_error(__TROTL_HERE__, BP._stmt._errh, res); res = OCICALL(OCICollAssign(BP._stmt._env, BP._stmt._errh, (OCIColl*)BP.valuep[_row], SV._valuep)); oci_check_error(__TROTL_HERE__, BP._stmt._errh, res); }
// todo - this relies on the fact that BindParNumber is BindParNumber now void ConvertorForRead::Fire(const BindParNumber &BP, SqlNumber &SN) { SN._ind = BP.indp[_row]; if(SN.is_not_null()) { sword res = OCICALL(OCINumberAssign(SN._env._errh, BP.get_ref(_row), &SN._val)); oci_check_error(__TROTL_HERE__, SN._env._errh, res); } // TODO raise exception here, if STMT.type==PL/SQL and BP._cnt > 1 //if(BP._cnt != 1) //std::cerr << "Warning assigning vector into scalar(" << BP._cnt << ")" << std::endl; };
oraub8 SqlBlob::read(dvoid* bufp, oraub8 buflen, oraub8 offset, oraub8 amount) { sword res = OCICALL(OCILobRead2(_conn._svc_ctx, _conn._env._errh, _loc, &amount, NULL, offset, bufp, buflen, OCI_ONE_PIECE, /* ub1 piece */ NULL, /* dvoid* ctxp */ NULL, /* sb4 (*cbfp)(dvoid*ctxp,CONST dvoid*bufp,ub4*len,ub1*piece) */ 0, 0 /* ub2 csid, ub1 csfrm */ )); oci_check_error(__TROTL_HERE__, _conn._env._errh, res); return amount; };
oraub8 SqlBlob::write_append(const dvoid* bufp, oraub8 buflen, oraub8 amount) { sword res = OCICALL(OCILobWriteAppend2(_conn._svc_ctx, _conn._env._errh, _loc, &amount, NULL, (dvoid*)bufp, buflen, OCI_ONE_PIECE, /* ub1 piece */ NULL, /* dvoid* ctxp */ NULL, /* sb4 (*cbfp)(dvoid*ctxp,dvoid*bufp,ub4*len,ub1*piece)*/ 0, 0 /* ub2 csid, ub1 csfrm */ )); oci_check_error(__TROTL_HERE__, _conn._env._errh, res); return amount; };
void BindParLob::descFree(void) { for(unsigned i=0; i<_cnt; ++i) { if(((OCILobLocator**)valuep)[i]) { //std::cerr << "void descFree(void): " << i << std::endl; sword res = OCICALL(OCIDescriptorFree( ((void**)valuep)[i], OCI_DTYPE_LOB)); oci_check_error(__TROTL_HERE__, _env, res); } } //std::cerr << "void descFree(void) done" << std::endl; }
oraub8 SqlClob::write_append(const dvoid* bufp, oraub8 buflen, oraub8 amount, ub2 csid, ub1 csfrm) { sword res = OCICALL(OCILobWriteAppend2(_conn._svc_ctx, _conn._env._errh, _loc, &amount, /* *byte_amtp - The number of bytes to write to the database. For CLOB and NCLOB it is used only when char_amtp is zero. */ NULL, /* *char_amtp - The maximum number of characters to write to the database. */ (dvoid*)bufp, buflen, OCI_ONE_PIECE, /* ub1 piece*/ NULL, /* dvoid* ctxp */ NULL, /* sb4 (*cbfp)(dvoid*ctxp,dvoid*bufp,oraub8*len,ub1*piece) */ csid, csfrm)); oci_check_error(__TROTL_HERE__, _conn._env._errh, res); return amount; };
/*--------------------------------------------------------------------- * attach - Attach to XStream server specified in connection info *---------------------------------------------------------------------*/ static void attach_session(oci_t * ocip, conn_info_t *conn, boolean outbound) { sword err; ub4 mode = OCI_DEFAULT; ub4 ack_interval = 30; ub4 idle_tmout = 5; printf (">>> attach_session server=%.*s \n", conn->svrnmlen, conn->svrnm); OCICALL(ocip, OCIAttrSet((dvoid *) ocip->srvp, (ub4) OCI_HTYPE_SERVER, (dvoid *) &ack_interval, (ub4) 0, (ub4) OCI_ATTR_XSTREAM_ACK_INTERVAL, ocip->errp)); if (outbound) { OCICALL(ocip, OCIAttrSet((dvoid *) ocip->srvp, (ub4) OCI_HTYPE_SERVER, (dvoid *) &idle_tmout, (ub4) 0, (ub4) OCI_ATTR_XSTREAM_IDLE_TIMEOUT, ocip->errp)); OCICALL(ocip, OCIXStreamOutAttach(ocip->svcp, ocip->errp, conn->svrnm, (ub2)conn->svrnmlen, (ub1 *)0, 0, OCI_DEFAULT)); } else { OCICALL(ocip, OCIXStreamInAttach(ocip->svcp, ocip->errp, conn->svrnm, (ub2)conn->svrnmlen, (oratext *)"From_XOUT", 9, (ub1 *)0, 0, OCI_DEFAULT)); } ocip->attached = TRUE; ocip->outbound = outbound; printf (">>> attach_session -- Done. \n"); }
void BindParRid::descAlloc(void) { for(unsigned i=0; i<_cnt; ++i) { //sword res = OCICALL(OCIDescriptorAlloc(_env, &((void**)valuep)[i], OCI_DTYPE_ROWID, 0, NULL)); sword res = OCICALL(OCIDescriptorAlloc(_env, &valuep[i], OCI_DTYPE_ROWID, 0, NULL)); oci_check_error(__TROTL_HERE__, _env, res); } // sword res = OCICALL(OCIArrayDescriptorAlloc( // (void *)_env, // (void **)&valuep, // OCI_DTYPE_ROWID, // _cnt, // 0, // (void **)0)); // oci_check_error(__TROTL_HERE__, _env, res); }
OciException::OciException(tstring where, OCIError* errh) : _where(where), _mess(where), _line(0), _column(0) { char buffer[1024]; sb4 errorcode; ub4 recordno = 1; // Indicates the status record from which the application seeks info. Starts from 1. sword res = OCICALL(OCIErrorGet(errh, recordno, NULL, &errorcode, (OraText*)buffer, sizeof(buffer), OCI_HTYPE_ERROR)); switch(res) { case OCI_SUCCESS: { _sql_error_code.push_back(errorcode); _mess.push_back('\n'); _mess.append(buffer); break; } case OCI_NO_DATA: { _sql_error_code.push_back(21002); _mess.push_back('\n'); _mess.append("OCIErrorGet: OCI_NO_DATA\n"); break; } default: { tostream s; _sql_error_code.push_back(0); _mess.push_back('\n'); _mess.append("OCIErrorGet: unknown error: \n"); s << res; _mess.append(s.str()); } // no break here } #ifdef DEBUG dbg::stack s; std::copy(s.begin(), s.end(), std::ostream_iterator<dbg::stack_frame>(_stack, "\n")); _mess.push_back('\n'); _mess.append(_stack.str()); #endif _parse_offset = 0; }
void BindParXML::init(SqlStatement &stmt) { sword res; xmltdo = 0; _xmlvaluep = (OCIXMLType**) calloc(_cnt, sizeof(OCIXMLType*)); _xmlindp = (OCIInd*) calloc(_cnt, sizeof(OCIInd)); // xmlsize = new ub4 [_cnt]; // std::cout << "BindParXML::init\n"; res = OCICALL(OCITypeByName(_stmt._env, _stmt._errh, _stmt._conn._svc_ctx, (const oratext*)"SYS", strlen("SYS"), (const oratext*)"XMLTYPE", strlen("XMLTYPE"), 0, 0, OCI_DURATION_SESSION, OCI_TYPEGET_HEADER, (OCIType**) &xmltdo )); oci_check_error(__TROTL_HERE__, _stmt._errh, res); if(xmltdo == NULL) throw OciException(__TROTL_HERE__, "Unknown datatype in the database: SYS.XMLTYPE"); for(int i=0; i<g_OCIPL_BULK_ROWS; i++) { _xmlvaluep[i] = NULL; _xmlindp[i] = OCI_IND_NULL; } // for(int i=0; i<_cnt; i++) // { //// xmlsize[i] = 0; // res = OCICALL(OCIObjectNew(conn._env, // conn._env._errh, // conn._svc_ctx, // OCI_TYPECODE_OPAQUE, // xmltdo, // 0, // OCI_DURATION_SESSION, // FALSE, // (dvoid **) &xml[i] // )); // oci_check_error(__TROTL_HERE__, conn._env._errh, res); // } }
void BindParXML::define_hook() { // xmlsize = 0; // std::cout << "OCIDefineObject" << std::endl; sword res = OCICALL(OCIDefineObject(defnpp, _stmt._errh, xmltdo, // TODO If the application wants the buffer to be implicitly allocated in the cache, // *pgvpp should be passed in as null. (dvoid **) &(_xmlvaluep[0]), 0, 0, //(dvoid **) &xml_ind, 0)); oci_check_error(__TROTL_HERE__, _stmt._errh, res); // res = OCICALL(OCIDefineArrayOfStruct(defnpp, stmt._errh, sizeof(OCIXMLType*), 0, 0, 0)); // oci_check_error(__TROTL_HERE__, stmt._errh, res); }
DescribeColumn::DescribeColumn(OciConnection &con, OciHandle<OCIStmt> &stmt, unsigned columnPosition, const tstring &sql) : Describe(con, "") , _tableName("") , _name("") , _schema_name("") , _type_name("") , _data_type(0) , _typecode(0) , _collection_typecode(0) , _collection_data_type(0) , _precision(0) , _scale(0) , _charset_id(0) , _charset_form(0) , _char_used(0) , _char_size(0) , _data_size(0) , _fprecision(0) , _lfprecision(0) , _is_null(0) , _ref_tdo(NULL) , _type(NULL) , _utf16(false) , _reg_name("") { OciParam param(con._env, NULL); sword res = OCICALL(OCIParamGet((OCIStmt*)stmt, OciHandleID<OCIStmt>::get_type_id(), con._env._errh, (dvoid**)(OCIParam**)param, columnPosition)); oci_check_error(__TROTL_HERE__, con._env._errh, res); describe(con, param); // OCI_ATTR_PRECISION The precision of numeric columns. If the precision is nonzero and scale is -127, // then it is a FLOAT, else it is a NUMBER(precision, scale). // For the case when precision is 0, NUMBER(precision, scale) can be represented simply as NUMBER. // ub1 for explicit describe // sb2 for implicit describe sb2 precision; precision = param.get_attribute<sb2>(OCI_ATTR_PRECISION); _precision = precision; };