/*{ ** Name: ops_gqtree - get query tree from QSF ** ** Description: ** This procedure will get a query tree from QSF ** and initialize the global QSF control block ** ** Inputs: ** global ptr to global state variable ** ** Outputs: ** global->ops_qsfcb initialized ** Returns: ** QSF status ** Exceptions: ** none ** ** Side Effects: ** none ** ** History: ** 26-jan-88 (seputis) ** initial creation ** 7-jan-94 (swm) ** Bug #58635 ** Added PTR cast for qsf_owner which has changed type to PTR. ** 10-Jan-2001 (jenjo02) ** Initialize qsf_sid with session's SID. [@history_template@]... */ DB_STATUS ops_gqtree( OPS_STATE *global) { /* get the query tree from QSF */ DB_STATUS qsfstatus; /* QSF return status */ global->ops_qsfcb.qsf_length = sizeof(QSF_RCB); /* initialize header ** for control block */ global->ops_qsfcb.qsf_type = QSFRB_CB; global->ops_qsfcb.qsf_owner = (PTR)DB_OPF_ID; global->ops_qsfcb.qsf_ascii_id = QSFRB_ASCII_ID; global->ops_qsfcb.qsf_sid = global->ops_cb->ops_sid; STRUCT_ASSIGN_MACRO(global->ops_caller_cb->opf_query_tree, global->ops_qsfcb.qsf_obj_id); /* move the name to the QSF control ** block */ global->ops_qsfcb.qsf_lk_state = QSO_EXLOCK; /* lock exclusively so ** that this object can be destroyed ** later */ qsfstatus = qsf_call( QSO_LOCK, &global->ops_qsfcb); /* get exclusive ** access to object */ if (DB_SUCCESS_MACRO(qsfstatus)) { global->ops_lk_id = global->ops_qsfcb.qsf_lk_id; /* save the lock id ** so that the object can be destroyed ** later */ global->ops_procedure = (PST_PROCEDURE *)global->ops_qsfcb.qsf_root; /* save ** the ptr to procedure header which ** should be the root */ } return(qsfstatus); }
/*{ ** Name: opx_sccerror - report error to user ** ** Description: ** Report a message to the user ** ** Inputs: ** status status of error ** msg_buffer ptr to message ** error ingres error number ** ** Outputs: ** Returns: ** VOID ** Exceptions: ** none ** ** Side Effects: ** fatal status will cause query to be aborted, and previous text sent ** to user to be flushed ** ** History: ** 15-apr-87 (seputis) ** initial creation ** 21-may-89 (jrb) ** changed interface to this routine to accept generic error ** 28-may-92 (seputis) ** - dump query for any error which is logged ** 24-oct-92 (andre) ** replaced generic error (i4) with sqlstate (DB_SQLSTATE *) in ** the interface of opx_sccerror() ** 13-nov-92 (andre) ** If sqlstate is not passed into opx_sccerror(), set scf_sqlstate ** to MISC_ING_ERRORS" [@history_line@]... [@history_template@]... */ static DB_STATUS opx_sccerror( DB_STATUS status, DB_SQLSTATE *sqlstate, OPX_ERROR error, char *msg_buffer, i4 msg_length) { SCF_CB scf_cb; DB_STATUS scf_status; scf_cb.scf_length = sizeof(scf_cb); scf_cb.scf_type = SCF_CB_TYPE; scf_cb.scf_facility = DB_OPF_ID; scf_cb.scf_nbr_union.scf_local_error = error; if (sqlstate) STRUCT_ASSIGN_MACRO((*sqlstate), scf_cb.scf_aux_union.scf_sqlstate); else MEcopy((PTR) SS50000_MISC_ERRORS, DB_SQLSTATE_STRING_LEN, (PTR) scf_cb.scf_aux_union.scf_sqlstate.db_sqlstate); scf_cb.scf_len_union.scf_blength = msg_length; scf_cb.scf_ptr_union.scf_buffer = msg_buffer; scf_cb.scf_session = DB_NOSESSION; if (DB_SUCCESS_MACRO(status)) scf_status = scf_call(SCC_TRACE, &scf_cb); else { /* Dump the session that caused this error */ if ((error % 256) >= 128) scs_avformat(); /* dump info on internal ** consistency checks only, ** i.e. do not dump for errors like ** OP0008 */ scf_status = scf_call(SCC_ERROR, &scf_cb); } if (scf_status != E_DB_OK) { TRdisplay("SCF error displaying OPF message to user\n"); TRdisplay("OPF message is :%s",msg_buffer); } return (scf_status); }
/*{ ** Name: opx_vrecover - this routine return an error code without reporting ** ** Description: ** This routine will not log or report to the user this recoverable error ** to but instead exit to the caller who is expected to take corrective ** action. ** ** Inputs: ** error optimizer error code to report ** facility facility's error code ** status facility's return status ** ** Outputs: ** Returns: ** VOID ** Exceptions: ** - internal exception generated ** ** Side Effects: ** the exception handling routines are responsible for ** deallocating OPF resources bound to this session. ** ** History: ** 3-jul-86 (seputis) ** initial creation [@history_line@]... */ VOID opx_vrecover( DB_STATUS status, OPX_ERROR error, OPX_FACILITY facility) { OPS_CB *opscb; /* ptr to session control block ** for this optimization */ opscb = ops_getcb(); opscb->ops_retstatus = status; /* save status code */ opscb->ops_callercb->opf_errorblock.err_code = error; /* save error code */ opscb->ops_callercb->opf_errorblock.err_data = facility; /* save code ** from facility */ if (DB_SUCCESS_MACRO(status)) { return; /* return if error is not ** serious */ } EXsignal( (EX)EX_JNP_LJMP, (i4)1, (long)error); /* signal an optimizer long ** jump with error code */ }
/*{ ** Name: ops_alter - alter session or server state for OPF ** ** Description: ** This routine contains all processing of the SET commands for the ** optimizer. These commands can be at the server or session level. ** There is currently no protection mechanism available for which ** users are able to access these SET commands. There probably should ** be a system catalog created to decide privileges and min and max ** values allowable for a session. Currently, all users can do anything ** at all. This routine will not do anything in terms of checking ** privileges. ** ** SET [[SESSION] | SERVER] CPUFACTOR <value> ** SET [[SESSION] | SERVER] TIMEOUT <value> ** SET [[SESSION] | SERVER] QEP ** SET [[SESSION] | SERVER] NOQEP ** SET [[SESSION] | SERVER] RET_INTO <storage_structure> ** ** FIXME need to use semaphores to access global structures. ** ** Inputs: ** opf_cb ptr to caller's control block ** ** Outputs: ** Returns: ** E_DB_OK ** Exceptions: ** none ** ** Side Effects: ** none ** ** History: ** 30-jun-86 (seputis) ** initial creation [@history_line@]... */ DB_STATUS ops_alter( OPF_CB *opf_cb) { DB_STATUS status; /* user return status */ switch (opf_cb->opf_level) { case OPF_SERVER: { /* change operating characteristics of the server */ DB_STATUS temp_status; /* get exclusive access before updating */ status = ops_exlock(opf_cb, &((OPS_CB *)(opf_cb->opf_scb))->ops_server->opg_semaphore); if (DB_FAILURE_MACRO(status)) break; temp_status = ops_change( opf_cb, &((OPG_CB*)opf_cb->opf_server)->opg_alter); /* release exclusive access */ status = ops_unlock(opf_cb, &((OPS_CB *)(opf_cb->opf_scb))->ops_server->opg_semaphore); if (DB_SUCCESS_MACRO(status)) status = temp_status; break; } case OPF_SESSION: { /* change operating characteristics of this session */ status = ops_change( opf_cb, &((OPS_CB *)(opf_cb->opf_scb))->ops_alter); break; } default: # ifdef E_OP0089_ALTER { opx_rerror( opf_cb, E_OP0089_ALTER); return( E_DB_ERROR ); } #endif } return (status); }
/*{ ** Name: opx_float - handle floating point exception in OPF ** ** Description: ** This routine will process a floating point exception error ** within the optimizer. This will normally be done by skipping ** the part of the search space which causes the floating point ** exception. ** ** Inputs: ** error floating point error code ** hard TRUE - if HARD error occurs ** which cannot be continued from ** ** Outputs: ** ** Returns: ** VOID ** Exceptions: ** none ** ** Side Effects: ** none ** ** History: ** 28-nov-90 (seputis) ** initial creation ** 21-jan-91 (jkb) submitted for seputis ** correct potential UNIX floating point problem ** 18-apr-91 (seputis) ** - fix bug 36920 ** 31-mar-92 (rog) ** Remove underscores from EX return statuses. [@history_template@]... */ STATUS opx_float( OPX_ERROR error, bool hard) { OPS_CB *opscb; /* session control block */ OPF_CB *opfcb; /* caller's control block */ opscb = ops_getcb(); /* get optimizer session control block */ opfcb = opscb->ops_state->ops_caller_cb; /* report unexpected exception ** otherwise */ if (opscb->ops_check && opt_strace( opscb, OPT_F048_FLOAT) && !hard && (opscb->ops_state->ops_gmask & OPS_BFPEXCEPTION) ) { opscb->ops_state->ops_gmask |= OPS_FPEXCEPTION; /* mark ** plan as having a floating point ** exception */ return(EXCONTINUES); /* try to recover from floating point ** exception unless a hard error occurs ** or a plan has been found which did ** not have a floating point exception */ } if (DB_SUCCESS_MACRO(opscb->ops_retstatus)) { opfcb->opf_errorblock.err_code = error; /* save error code */ opscb->ops_retstatus = E_DB_WARN; /* change status only if more ** severe */ } opscb->ops_state->ops_gmask |= (OPS_FLSPACE | OPS_FLINT); /* indicate that ** search space has been reduced */ return(EXDECLARE); }
/*{ ** Name: opx_verror - this routine will report another facility's error ** ** Description: ** This routine will report an error from another facility ** optimizer error. It will check the status and see the error ** is recoverable. The routine will not return if the status is fatal ** but instead generate an internal exception and ** exit via the exception handling mechanism. The error code will be ** placed directly in the user's calling control block. A ptr to this ** block was placed in the session control block (which can be requested ** from SCF) ** ** Inputs: ** error optimizer error code to report ** facility facility's error code ** status facility's return status ** ** Outputs: ** Returns: ** VOID ** Exceptions: ** - internal exception generated ** ** Side Effects: ** the exception handling routines are responsible for ** deallocating OPF resources bound to this session. ** ** History: ** 3-jul-86 (seputis) ** initial creation ** 28-jan-91 (seputis) ** added support for OPF ACTIVE flag ** 30-apr-92 (bryanp) ** Translate E_RD002A_DEADLOCK to E_OP0010_RDF_DEADLOCK. [@history_line@]... */ VOID opx_verror( DB_STATUS status, OPX_ERROR error, OPX_FACILITY facility) { OPS_CB *opscb; /* ptr to session control block ** for this optimization */ opscb = ops_getcb(); opscb->ops_retstatus = status; /* save status code */ if (facility == E_RD002A_DEADLOCK) error = E_OP0010_RDF_DEADLOCK; if ((facility == E_RD002B_LOCK_TIMER_EXPIRED) && (opscb->ops_smask & OPS_MCONDITION)) { error = E_OP000D_RETRY; /* when an attempt is made to ** report the RDF timeout error ** then it should be translated ** into a retry error, since an ** undetected deadlock may have ** occurred due to the ACTIVE flag */ opscb->ops_server->opg_sretry++; /* track number of retrys */ opx_vrecover(status, E_OP000D_RETRY, facility); /* this routine will not ** return */ } else opx_rverror(opscb->ops_callercb, status, error, facility); if (DB_SUCCESS_MACRO(status)) { return; /* return if error is not ** serious */ } EXsignal( (EX)EX_JNP_LJMP, (i4)1, (long)error); /* signal an optimizer long ** jump with error code */ }
/*{ ** Name: psy_kinteg - Destroy one or more integrities for a table. ** ** INTERNAL PSF call format: status = psy_kinteg(&psy_cb, sess_cb); ** ** EXTERNAL call format: status = psy_call(PSY_KINTEG, &psy_cb, sess_cb); ** ** Description: ** The psy_kinteg function removes the definitions of one or more ** integrities on a table from the system relations (integrities, ** tree, and iiqrytext). ** Optionally, one can tell this function to destroy all of the ** integrities on the given table. ** ** Inputs: ** psy_cb ** .psy_tables[0] Id of table from which to remove ** integrities ** .psy_numbs[] Array of integrity id numbers telling ** which integrities to destroy (at most ** 20) ** .psy_numnms Number telling how many integrity ** numbers there are. Zero means to ** destroy all of the integrities ** on the given table. ** .psy_tabname[0] Name of table from which to remove ** integrities ** sess_cb Pointer to session control block ** (Can be NULL) ** ** Outputs: ** psy_cb ** .psy_error Filled in if an error happens ** .err_code What the error was ** E_PS0000_OK Success ** E_PS0001_USER_ERROR User made a mistake ** E_PS0002_INTERNAL_ERROR Internal inconsistency in PSF ** Returns: ** E_DB_OK Function completed normally. ** E_DB_WARN Function completed with warning(s) ** E_DB_ERROR Function failed; non-catastrophic error ** E_DB_FATAL Function failed; catastrophic error ** Exceptions: ** none ** ** Side Effects: ** Removes query tree(s) representing predicates of integrities from ** tree relation, text of defining query (or queries) from iiqrytext ** relation, rows defining integrity (or integrities) from integrities ** relation. If there are no more integrities on this table, will ** use DMF alter table function to indicate this. ** ** History: ** 02-oct-85 (jeff) ** written ** 30-aug-88 (andre) ** check if the user specified integrity 0 to be deleted, ** and if so, warn that it doesn't exist (this will prevent someone ** from inadvertently deleting all integrities by specifying that ** integrity 0 be deleted.) ** 30-aug-88 (andre) ** When looking at individual integrities, return E_DB_ERROR if any ** errors were found when processing individual integrities. ** 12-mar-90 (andre) ** set rdr_2types_mask to 0. ** 22-may-90 (teg) ** init rdr_instr to RDF_NO_INSTR ** 03-aug-1992 (barbara) ** Call pst_rdfcb_init to initialize RDF_CB before calling RDF. ** Invalidate infoblk from RDF cache after dropping integrity. ** 07-aug-92 (teresa) ** RDF_INVALID must be called for the base object that the ** integrity was defined on as well as for the integrity trees. ** 14-sep-92 (barbara) ** Set type field and tableid in the RDF cb used to invalidate ** the cached entries. ** 14-jul-93 (ed) ** replacing <dbms.h> by <gl.h> <sl.h> <iicommon.h> <dbdbms.h> ** 10-aug-93 (andre) ** removed declaration of rdf_call() ** 30-sep-93 (stephenb) ** Pass tablename from psy_cb to rdf_rb, so that we can use the ** information to audit in QEF. */ DB_STATUS psy_kinteg( PSY_CB *psy_cb, PSS_SESBLK *sess_cb) { RDF_CB rdf_cb; RDF_CB rdf_inv_cb; /* For invalidation */ register RDR_RB *rdf_rb = &rdf_cb.rdf_rb; DB_STATUS status = E_DB_OK; i4 err_code; register i4 i; /* Fill in RDF control block */ pst_rdfcb_init(&rdf_cb, sess_cb); pst_rdfcb_init(&rdf_inv_cb, sess_cb); STRUCT_ASSIGN_MACRO(psy_cb->psy_tables[0], rdf_rb->rdr_tabid); STRUCT_ASSIGN_MACRO(psy_cb->psy_tables[0], rdf_inv_cb.rdf_rb.rdr_tabid); rdf_rb->rdr_types_mask = RDR_INTEGRITIES; rdf_inv_cb.rdf_rb.rdr_types_mask = RDR_INTEGRITIES; rdf_rb->rdr_update_op = RDR_DELETE; rdf_rb->rdr_name.rdr_tabname = psy_cb->psy_tabname[0]; /* No integrity numbers means destroy all integrities. */ if (psy_cb->psy_numnms == 0) { /* Zero integrity number means destroy all integs. */ rdf_rb->rdr_qrymod_id = 0; status = rdf_call(RDF_UPDATE, (PTR) &rdf_cb); if (DB_FAILURE_MACRO(status)) { if (rdf_cb.rdf_error.err_code == E_RD0002_UNKNOWN_TBL) { (VOID) psf_error(E_PS0903_TAB_NOTFOUND, 0L, PSF_USERERR, &err_code, &psy_cb->psy_error, 1, psf_trmwhite(sizeof(psy_cb->psy_tabname[0]), (char *) &psy_cb->psy_tabname[0]), &psy_cb->psy_tabname[0]); } else { (VOID) psf_rdf_error(RDF_UPDATE, &rdf_cb.rdf_error, &psy_cb->psy_error); } return (status); } /* Invalidate table info from RDF cache */ /* first invalidate the object from the relation cache */ status = rdf_call(RDF_INVALIDATE, (PTR) &rdf_inv_cb); if (DB_FAILURE_MACRO(status)) (VOID) psf_rdf_error(RDF_INVALIDATE, &rdf_inv_cb.rdf_error, &psy_cb->psy_error); /* now invalidate any integrity trees from the cache */ rdf_inv_cb.rdf_rb.rdr_2types_mask |= RDR2_CLASS; status = rdf_call(RDF_INVALIDATE, (PTR) &rdf_inv_cb); if (DB_FAILURE_MACRO(status)) (VOID) psf_rdf_error(RDF_INVALIDATE, &rdf_inv_cb.rdf_error, &psy_cb->psy_error); } else { DB_STATUS stat; /* Run through the integrity numbers, destroying each one */ for (i = 0; i < psy_cb->psy_numnms; i++) { /* if user specified 0, complain and proceed with next integrity # */ if ((rdf_rb->rdr_qrymod_id = psy_cb->psy_numbs[i]) == 0) { /* remember error to report later */ status = (status > E_DB_ERROR) ? status : E_DB_ERROR; (VOID) psf_error(5203, 0L, PSF_USERERR, &err_code, &psy_cb->psy_error, 1, sizeof (rdf_rb->rdr_qrymod_id), &rdf_rb->rdr_qrymod_id); continue; } stat = rdf_call(RDF_UPDATE, (PTR) &rdf_cb); /* remember the highest status seen so far */ status = (status > stat) ? status : stat; if (DB_FAILURE_MACRO(stat)) { switch (rdf_cb.rdf_error.err_code) { case E_RD0002_UNKNOWN_TBL: (VOID) psf_error(E_PS0903_TAB_NOTFOUND, 0L, PSF_USERERR, &err_code, &psy_cb->psy_error, 1, psf_trmwhite(sizeof(psy_cb->psy_tabname[0]), (char *) &psy_cb->psy_tabname[0]), &psy_cb->psy_tabname[0]); break; case E_RD0013_NO_TUPLE_FOUND: (VOID) psf_error(5203, 0L, PSF_USERERR, &err_code, &psy_cb->psy_error, 1, sizeof (rdf_rb->rdr_qrymod_id), &rdf_rb->rdr_qrymod_id); continue; default: (VOID) psf_rdf_error(RDF_UPDATE, &rdf_cb.rdf_error, &psy_cb->psy_error); } return (status); } /* invalidate the integrity tree from the cache. */ rdf_inv_cb.rdf_rb.rdr_sequence = psy_cb->psy_numbs[i]; rdf_inv_cb.rdf_rb.rdr_2types_mask |= RDR2_ALIAS; status = rdf_call(RDF_INVALIDATE, (PTR) &rdf_inv_cb); if (DB_FAILURE_MACRO(status)) { (VOID) psf_rdf_error(RDF_INVALIDATE, &rdf_inv_cb.rdf_error, &psy_cb->psy_error); break; } } /* now invalidate the integrity base object from the relation cache */ if (DB_SUCCESS_MACRO(status)) { rdf_inv_cb.rdf_rb.rdr_sequence = 0; rdf_inv_cb.rdf_rb.rdr_2types_mask &= ~RDR2_ALIAS; status = rdf_call(RDF_INVALIDATE, (PTR) &rdf_inv_cb); if (DB_FAILURE_MACRO(status)) { (VOID) psf_rdf_error(RDF_INVALIDATE, &rdf_inv_cb.rdf_error, &psy_cb->psy_error); } } } return (status); }
VOID opc_querycomp( OPS_STATE *global) { DB_STATUS ret; global->ops_gmask |= OPS_OPCEXCEPTION; /* mark facility as being in OPC */ #ifdef OPT_F033_OPF_TO_OPC if (opt_strace(global->ops_cb, OPT_F033_OPF_TO_OPC) == TRUE) { char temp[OPT_PBLEN + 1]; bool init = 0; if (global->ops_cstate.opc_prbuf == NULL) { global->ops_cstate.opc_prbuf = temp; init++; } /* Trace all of 'global' */ if (global->ops_statement != NULL) { opt_state(global); } if (init) { global->ops_cstate.opc_prbuf = NULL; } } #endif if ( opt_strace(global->ops_cb, OPT_F071_QEP_WITHOUT_COST ) == TRUE && global->ops_subquery) { opt_cotree_without_stats( global ); } /* If this is CREATE TABLE, check for primary, unique, foreign key ** constraints to use for default base table structure. */ if (global->ops_statement && global->ops_statement->pst_type == PST_CREATE_TABLE_TYPE && global->ops_statement->pst_specific.pst_createTable. pst_createTableFlags == PST_CRT_TABLE) { QEU_CB *qeucb = global->ops_statement->pst_specific.pst_createTable.pst_createTableQEUCB; DMU_CB *dmucb = (DMU_CB *) qeucb->qeu_d_cb; bool checkit = FALSE; if (BTtest(DMU_AUTOSTRUCT, dmucb->dmu_chars.dmu_indicators)) checkit = (dmucb->dmu_chars.dmu_flags & DMU_FLAG_AUTOSTRUCT) != 0; else checkit = opt_strace(global->ops_cb, OPT_F084_TBLAUTOSTRUCT ) || global->ops_cb->ops_alter.ops_autostruct != 0; if (checkit) opc_checkcons(global->ops_statement, dmucb); } /* On entry for rule processing, assume ops_qpinit == TRUE. There */ /* is no need to allocate a memory stream since we are contuing */ /* processing on the QP that was started by the triggering statement. */ if (global->ops_qpinit == FALSE) { /* First, lets open the stack ULM memory stream that OPC uses */ opu_Osmemory_open(global); /* Tell QSF that we want to store an object; */ global->ops_qsfcb.qsf_obj_id.qso_type = QSO_QP_OBJ; if (global->ops_procedure->pst_flags & PST_REPEAT_DYNAMIC) { char *p; global->ops_qsfcb.qsf_obj_id.qso_lname = sizeof(DB_CURSOR_ID) + sizeof(i4); MEfill(sizeof(global->ops_qsfcb.qsf_obj_id.qso_name), 0, global->ops_qsfcb.qsf_obj_id.qso_name); MEcopy((PTR)&global->ops_procedure->pst_dbpid.db_cursor_id[0], sizeof (global->ops_procedure->pst_dbpid.db_cursor_id[0]), (PTR)global->ops_qsfcb.qsf_obj_id.qso_name); p = (char *) global->ops_qsfcb.qsf_obj_id.qso_name + 2*sizeof(i4); if (global->ops_caller_cb->opf_locator) MEcopy((PTR)"ql", sizeof("ql"), p); else MEcopy((PTR)"qp", sizeof("qp"), p); p = (char *) global->ops_qsfcb.qsf_obj_id.qso_name + sizeof(DB_CURSOR_ID); I4ASSIGN_MACRO(global->ops_caller_cb->opf_udbid, *(i4 *) p); } else if ( global->ops_procedure->pst_isdbp == TRUE || ( global->ops_qheader != NULL && (global->ops_qheader->pst_mask1 & PST_RPTQRY) ) ) { global->ops_qsfcb.qsf_obj_id.qso_lname = sizeof (global->ops_procedure->pst_dbpid); MEcopy((PTR)&global->ops_procedure->pst_dbpid, sizeof (global->ops_procedure->pst_dbpid), (PTR)global->ops_qsfcb.qsf_obj_id.qso_name); } else { global->ops_qsfcb.qsf_obj_id.qso_lname = 0; } /* Also allow for the case where a concurrent clash causes a new ** object at an awkward point */ if ((ret = qsf_call(QSO_CREATE, &global->ops_qsfcb)) != E_DB_OK && !(ret == E_DB_ERROR && global->ops_qsfcb.qsf_error.err_code == E_QS001C_EXTRA_OBJECT) && !((global->ops_procedure->pst_flags & PST_SET_INPUT_PARAM) && global->ops_qsfcb.qsf_error.err_code == E_QS001C_EXTRA_OBJECT)) { /* if object exists and we have a named query plan. */ if (global->ops_qsfcb.qsf_error.err_code == E_QS000A_OBJ_ALREADY_EXISTS ) { /* Log query info */ QSO_OBID *obj = &global->ops_qsfcb.qsf_obj_id; char *qrytype; char *objtype; char *objname; char *qrytext; char tmp[(DB_OWN_MAXNAME + DB_CURSOR_MAXNAME) + 3 + 1]; DB_STATUS status; QSF_RCB qsf_rb; PSQ_QDESC *qdesc; if (global->ops_procedure->pst_isdbp == TRUE) qrytype = "database procedure"; else if (global->ops_qheader != NULL && (global->ops_qheader->pst_mask1 & PST_RPTQRY) ) qrytype = "repeat query"; else qrytype = "non-repeat query"; objtype = "QSO_QP_OBJ"; if (obj->qso_lname == 0) { objname = "QSF object has no name"; } else { char fmt[30]; DB_CURSOR_ID *curid; char *user; i4 *dbid; curid = (DB_CURSOR_ID *)obj->qso_name; user = curid->db_cur_name + DB_CURSOR_MAXNAME; dbid = (i4 *)(user + DB_OWN_MAXNAME); STprintf(fmt, ":%%lx:%%lx:%%.%ds:%%.%ds:%%lx:", DB_CURSOR_MAXNAME, DB_OWN_MAXNAME); STprintf(tmp, fmt, (i4)curid->db_cursor_id[0], (i4)curid->db_cursor_id[1], curid->db_cur_name, user, (i4)(*dbid)); objname = tmp; } qsf_rb.qsf_type = QSFRB_CB; qsf_rb.qsf_ascii_id = QSFRB_ASCII_ID; qsf_rb.qsf_length = sizeof(qsf_rb); qsf_rb.qsf_owner = (PTR)DB_OPF_ID; qsf_rb.qsf_obj_id.qso_handle = global->ops_caller_cb->opf_thandle; qrytext = "Query text was not available."; if (qsf_rb.qsf_obj_id.qso_handle != NULL) { status = qsf_call(QSO_INFO, &qsf_rb); if (DB_SUCCESS_MACRO(status)) { qdesc = (PSQ_QDESC*) qsf_rb.qsf_root; qrytext = qdesc->psq_qrytext; } } /* log an error */ opx_lerror((OPX_ERROR)E_OP089F_QSF_FAILCREATE, (i4)4, (PTR)qrytype, (PTR)objtype, (PTR)objname, (PTR)qrytext); } opx_verror(ret, E_OP0882_QSF_CREATE, global->ops_qsfcb.qsf_error.err_code); } /* Put the handle for the QEP into the callers CB; ** - will be used for deallocation in case of an error ** - both the object id and the lock id are needed in order to destroy ** the object */ STRUCT_ASSIGN_MACRO(global->ops_qsfcb.qsf_obj_id, global->ops_caller_cb->opf_qep); global->ops_qplk_id = global->ops_qsfcb.qsf_lk_id; global->ops_qpinit = TRUE; /* Allocate and initialize the QP. */ opc_iqp_init(global); } /* Continue the QP compilation by adding the current statement */ if (global->ops_statement != NULL) { opc_cqp_continue(global); } /* if it's time to stop compiling the query, then lets close stuff. */ /* The caller is responsible for making one additional call to OPC */ /* with ops_statement == NULL after all statements in the QP we are */ /* currently building have been compiled. Note that this is a change */ /* from the previous version of this routine which required the extra */ /* call only if a db procedure was being compiled. Such a call must */ /* also be made after the last statement in each rule list. This allows */ /* OPC to link all conditionals statements in the rule list together */ /* before continuing with the next user statement to be compiled. */ if (global->ops_statement == NULL) { /* We're finished compiling all of the statements, so lets finish ** the QP */ opc_fqp_finish(global); /* The QP is only associated with the outer query, not a rule list */ if (!global->ops_inAfterRules && !global->ops_inBeforeRules) { /* Tell QSF what the root of the QEP is; */ global->ops_qsfcb.qsf_root = (PTR) global->ops_cstate.opc_qp; if ((ret = qsf_call(QSO_SETROOT, &global->ops_qsfcb)) != E_DB_OK) { opx_verror(ret, E_OP0883_QSF_SETROOT, global->ops_qsfcb.qsf_error.err_code); } if ((ret = qsf_call(QSO_UNLOCK, &global->ops_qsfcb)) != E_DB_OK) { opx_verror(ret, E_OP089E_QSF_UNLOCK, global->ops_qsfcb.qsf_error.err_code); } /* Now lets close the stack ULM memory stream that OPC used */ opu_Csmemory_close(global); } } global->ops_gmask &= (~OPS_OPCEXCEPTION); /* mark facility as leaving OPC */ }
/*{ ** Name: psy_gproc - Get a database procedure definition from ** the system catalogs. ** ** Description: ** ** Inputs: ** psq_cb ** psq_cursid ** db_cur_name dbproc name ** sess_cb ** pss_user current user name ** pss_dba dba name ** qsf_rb ** rdf_cb ** dbp_owner name of the owner whose dbproc will be ** looked up iff gproc_mask & PSS_DBP_BY_OWNER. ** gproc_mask mask used to specify the possible owners of ** the dbproc to look for ** PSS_USRDBP look for dbproc owned by the current user ** PSS_DBADBP look for dbproc owned by the DBA ** PSS_INGDBP look for dbproc owned by $INGRES ** PSS_DBP_BY_OWNER look for dbproc owned by the specific user ** ** NOTE: if PSS_DBP_BY_OWNER is set, ** PSS_USRDBP, PSS_DBADBP, and PSS_INGDBP ** will be disregarded ** otherwise, we expect that PSS_USRDBP ** will be always set, while PSS_DBADBP ** and PSS_INGDBP may or may not be set ** ** Outputs: ** alt_user set to point the name of dbproc owner if ** different from cb->pss_user ** psq_cb ** psq_error filled in if an error occurred ** ** ret_flags bits may be set to pass info to the caller ** PSS_MISSING_DBPROC dbproc not found ** ** Exceptions: ** none ** ** Returns ** E_DB_OK, E_DB_ERROR ** ** Side Effects: ** Allocates memory. ** ** History: ** 27-apr-88 (stec) ** Created. ** 04-aug-88 (stec) ** Improve recovery of resources. ** 17-aug-88 (stec) ** Change bad STRUCT_ASSIGN statements. ** 28-sep-88 (stec) ** Do not lock object on cleanup. ** 28-sep-88 (stec) ** Must not unfix RDF entry. ** 16-mar-89 (andre) ** Added a new parameter - alt_user. ** psy_gproc will no longer reset pss_user or set pss_ruset. Instead ** it may set the ptr passed to it to the name of the dbproc owner. ** 16-mar-89 (neil) ** Modified psy_gproc to access the procedure through the specified ** owner (psq_als_owner) if psq_alias_set is on. ** 27-apr-89 (andre) ** Further modify to search for dbprocs owned by $ingres if the search ** by user and DBA failed. The search part of the function has been, ** essentially, rewritten. ** 12-mar-90 (andre) ** set rdr_2types_mask to 0. ** 22-may-90 (teg) ** init rdr_instr to RDF_NO_INSTR ** 01-jun-90 (andre) ** Changed interface to allow caller to explicitly specify the possible ** owners of the dbproc to look for. ** 01-oct-91 (andre) ** Added ret_flags to the interface - this field will be used to pass ** additional info to the caller. in particular, it will allow us to ** signal certain classes of errors (e.g. dbproc not found) without ** setting return status to E_DB_ERROR, thus enabling the caller to ** distinguish such errors from unexpected errors ** 15-oct-1993 (rog) ** We need to use ulm_copy() instead of MEcopy() when copying query ** text that might be more than 64k. ** 12-jan-94 (andre) ** As a part of fix for bug 58048, we must remove the assumption that ** either PSS_USRDBP or PSS_DBP_BY_OWNER bit will always be set in ** gproc_mask. Now we will be prepared to handle PSS_DBP_BY_OWNER or ** one or more of PSS_USRDBP, PSS_DBADBP, and PSS_INGDBP. ** 13-jan-94 (andre) ** if we fail to find a dbproc, we will set PSS_MISSING_DBPROC in ** *ret_flags, but leave it up to the caller to issue an error ** message - this way the caller can decide whether this warrants an ** error message and if so can choose his favourite error message */ DB_STATUS psy_gproc( PSQ_CB *psq_cb, PSS_SESBLK *sess_cb, QSF_RCB *qsf_rb, RDF_CB *rdf_cb, DB_OWN_NAME **alt_user, DB_OWN_NAME *dbp_owner, i4 gproc_mask, i4 *ret_flags) { DB_STATUS status, stat; i4 err_code; RDD_QRYMOD *pinfo; PSQ_QDESC *qdesc; bool leave_loop = TRUE; DB_PROCEDURE *dbp; SXF_ACCESS access; i4 msgid; i4 local_status; *ret_flags = 0; /* First call RDF to retrieve the definition ** of the procedure. */ /* Initialize the RDF control block */ pst_rdfcb_init(rdf_cb, sess_cb); (VOID) MEcopy((PTR) psq_cb->psq_cursid.db_cur_name, sizeof (DB_DBP_NAME), (PTR) &rdf_cb->rdf_rb.rdr_name.rdr_prcname); rdf_cb->rdf_rb.rdr_types_mask = RDR_PROCEDURE | RDR_BY_NAME; /* assume that the dbproc is owned by the current user */ *alt_user = (DB_OWN_NAME *) NULL; do { if (gproc_mask & (PSS_USRDBP | PSS_DBP_BY_OWNER)) { if (gproc_mask & PSS_USRDBP) { STRUCT_ASSIGN_MACRO(sess_cb->pss_user, rdf_cb->rdf_rb.rdr_owner); } else { STRUCT_ASSIGN_MACRO((*dbp_owner), rdf_cb->rdf_rb.rdr_owner); if (MEcmp((PTR)&sess_cb->pss_user, (PTR) dbp_owner, sizeof(DB_OWN_NAME))) { *alt_user = dbp_owner; /* Try someone else */ } } /* Get the text */ status = rdf_call(RDF_GETINFO, (PTR) rdf_cb); /* ** We do not want to continue search if: ** 1) dbproc was found OR ** 2) we got an error other that PROC_NOT_FOUND OR ** 3) caller requested a dbproc owned by a specific user ** (gproc_mask & PSS_DBP_BY_OWNER) OR */ if ( DB_SUCCESS_MACRO(status) || rdf_cb->rdf_error.err_code != E_RD0201_PROC_NOT_FOUND || gproc_mask & PSS_DBP_BY_OWNER) { break; } } /* ** if we were told to check whether a dbproc is owned by the DBA, do so ** unless the DBA is the current user and we have already established ** that the current user does not own a dbproc with this name */ if ( gproc_mask & PSS_DBADBP && ( ~gproc_mask & PSS_USRDBP || MEcmp((PTR) &sess_cb->pss_user, (PTR) &sess_cb->pss_dba.db_tab_own, sizeof(DB_OWN_NAME)) ) ) { STRUCT_ASSIGN_MACRO(sess_cb->pss_dba.db_tab_own, rdf_cb->rdf_rb.rdr_owner); /* ** If we succeed and the DBA is different from the current user, ** the procedure text will have to be parsed in the context of ** dbproc's owner, i.e. DBA. Note that if we were also asked to ** check whether the dbproc is owned by the current user and still ** found ourselves here, DBA must be different from the current user */ if ( gproc_mask & PSS_USRDBP || MEcmp((PTR) &sess_cb->pss_user, (PTR) &sess_cb->pss_dba.db_tab_own, sizeof(DB_OWN_NAME))) { *alt_user = &sess_cb->pss_dba.db_tab_own; } /* Get the text */ status = rdf_call(RDF_GETINFO, (PTR) rdf_cb); /* ** We do not want to continue search if: ** 1) dbproc was found OR ** 2) we got an error other that PROC_NOT_FOUND */ if (DB_SUCCESS_MACRO(status) || rdf_cb->rdf_error.err_code != E_RD0201_PROC_NOT_FOUND) { break; } } if (gproc_mask & PSS_INGDBP) { MEmove(sizeof(*sess_cb->pss_cat_owner), (PTR)sess_cb->pss_cat_owner, ' ', DB_OWN_MAXNAME, (PTR) &rdf_cb->rdf_rb.rdr_owner); } else { /* ** if user has not requested that a dbproc owned by $INGRES be ** looked up, might as well get out of the loop */ break; } /* ** if we were told to check whether a dbproc is owned by $ingres, do so ** unless the $ingres is the current user and we have already ** established that the current user does not own a dbproc with this ** name or $ingres is the DBA and we have already established that the ** DBA does not own a dbproc with this name */ if ( ( ~gproc_mask & PSS_USRDBP || MEcmp((PTR)&sess_cb->pss_user, (PTR) &rdf_cb->rdf_rb.rdr_owner, sizeof(DB_OWN_NAME)) ) && ( ~gproc_mask & PSS_DBADBP || MEcmp((PTR) &sess_cb->pss_dba.db_tab_own, (PTR) &rdf_cb->rdf_rb.rdr_owner, sizeof(DB_OWN_NAME)) ) ) { /* ** If we succeed, the procedure text will have to be parsed in ** the context of the original owner, i.e. $ingres. */ *alt_user = &rdf_cb->rdf_rb.rdr_owner; /* ** If we succeed and $ingres is not the current user, the procedure ** text will have to be parsed in the context of dbproc's owner, ** i.e. $ingres. Note that if we were also asked to check whether ** the dbproc is owned by the current user and still found ourselves ** here, the current user must NOT be $ingres */ if ( gproc_mask & PSS_USRDBP || MEcmp((PTR) &sess_cb->pss_user, (PTR) &rdf_cb->rdf_rb.rdr_owner, sizeof(DB_OWN_NAME))) { *alt_user = &sess_cb->pss_dba.db_tab_own; } /* Get the text */ status = rdf_call(RDF_GETINFO, (PTR) rdf_cb); } /* leave_loop has already been set to TRUE */ } while (!leave_loop); if (DB_FAILURE_MACRO(status)) { if (rdf_cb->rdf_error.err_code == E_RD0201_PROC_NOT_FOUND) { /* ** dbproc was not found - set a bit in ret_flags and reset status to ** E_DB_OK to enable callers to distinguish between this and other ** errors */ status = E_DB_OK; *ret_flags |= PSS_MISSING_DBPROC; } else { (VOID) psf_rdf_error(RDF_GETINFO, &rdf_cb->rdf_error, &psq_cb->psq_error); } return(status); } /* we get here only if the dbproc was found */ /* ** If the procedure has a security label, validate it */ dbp=rdf_cb->rdf_info_blk->rdr_dbp; /* Initialize the QSF control block */ qsf_rb->qsf_type = QSFRB_CB; qsf_rb->qsf_ascii_id = QSFRB_ASCII_ID; qsf_rb->qsf_length = sizeof(QSF_RCB); qsf_rb->qsf_owner = (PTR)DB_PSF_ID; qsf_rb->qsf_sid = sess_cb->pss_sessid; qsf_rb->qsf_obj_id.qso_type = QSO_QTEXT_OBJ; qsf_rb->qsf_obj_id.qso_lname = 0; /* Having retrieved the text place it in QSF ** because the parser expects it to be there. */ status = qsf_call(QSO_CREATE, qsf_rb); if (DB_FAILURE_MACRO(status)) { i4 qerr = qsf_rb->qsf_error.err_code; if (qerr == E_QS0001_NOMEM) { (VOID) psf_error(qerr, qerr, PSF_CALLERR, &err_code, &psq_cb->psq_error, 0); } else { (VOID) psf_error(E_PS0A05_BADMEMREQ, qerr, PSF_INTERR, &err_code, &psq_cb->psq_error, 0); } goto cleanup2; } /* Object is locked exclusively now. */ pinfo = rdf_cb->rdf_rb.rdr_procedure; /* Allocate enough memory for the query descriptor ** plus the length of text. */ qsf_rb->qsf_sz_piece = sizeof(PSQ_QDESC) + pinfo->rdf_l_querytext + 3; /* one space, one null, ** one for safety. */ status = qsf_call(QSO_PALLOC, qsf_rb); if (DB_FAILURE_MACRO(status)) { i4 qerr = qsf_rb->qsf_error.err_code; if (qerr == E_QS0001_NOMEM) { (VOID) psf_error(qerr, qerr, PSF_CALLERR, &err_code, &psq_cb->psq_error, 0); } else { (VOID) psf_error(E_PS0A05_BADMEMREQ, qerr, PSF_INTERR, &err_code, &psq_cb->psq_error, 0); } goto cleanup1; } qdesc = (PSQ_QDESC *) qsf_rb->qsf_piece; /* Initialize query descriptor. */ qdesc->psq_qrysize = pinfo->rdf_l_querytext + 1; /* 1 trailing space */ qdesc->psq_datasize = 0; qdesc->psq_dnum = 0; qdesc->psq_qrytext = (char *)(qdesc + 1); /* Ptr arithmetic, should point ** right after the PSQ_QDESC. */ qdesc->psq_qrydata = (DB_DATA_VALUE **) NULL; /* QSF memory has been allocated now, copy ** the text from RDF. */ ulm_copy((PTR) pinfo->rdf_querytext, (i4) pinfo->rdf_l_querytext, (PTR) qdesc->psq_qrytext); /* Add a space after the text and null terminate. */ { char *p; p = qdesc->psq_qrytext; /* beginning of text */ p += pinfo->rdf_l_querytext; /* 1st char past end */ *p++ = ' '; *p = '\0'; /* 2nd char past end */ } /* Set root for the QSF object */ qsf_rb->qsf_root = qsf_rb->qsf_piece; status = qsf_call(QSO_SETROOT, qsf_rb); if (DB_FAILURE_MACRO(status)) { (VOID) psf_error(E_PS0A05_BADMEMREQ, qsf_rb->qsf_error.err_code, PSF_INTERR, &err_code, &psq_cb->psq_error, 0); goto cleanup1; } status = qsf_call(QSO_UNLOCK, qsf_rb); if (DB_FAILURE_MACRO(status)) { (VOID) psf_error(E_PS0B05_CANT_UNLOCK, qsf_rb->qsf_error.err_code, PSF_INTERR, &err_code, &psq_cb->psq_error, 0); goto cleanup1; } psq_cb->psq_qid = qsf_rb->qsf_obj_id.qso_handle; return (status); cleanup1: /* Destroy the object, it's already locked. */ stat = qsf_call(QSO_DESTROY, qsf_rb); if (DB_FAILURE_MACRO(stat)) { (VOID) psf_error(E_PS0A09_CANTDESTROY, qsf_rb->qsf_error.err_code, PSF_INTERR, &err_code, &psq_cb->psq_error, 0); if (stat > status) status = stat; } cleanup2: /* RDF object can be released now. */ stat = rdf_call(RDF_UNFIX, (PTR) rdf_cb); if (DB_FAILURE_MACRO(stat)) { (VOID) psf_rdf_error(RDF_UNFIX, &rdf_cb->rdf_error, &psq_cb->psq_error); if (stat > status) status = stat; } return (status); }
/*{ ** Name: psy_kproc - Drop a database procedure definition from ** the system catalogs. ** ** Description: ** ** Inputs: ** ** Outputs: ** Exceptions: ** none ** ** Side Effects: ** Modifies system catalogs. ** ** History: ** 27-apr-88 (stec) ** Created. ** 12-mar-90 (andre) ** set rdr_2types_mask to 0. ** 22-may-90 (teg) ** init rdr_instr to RDF_NO_INSTR ** 12-jun-90 (andre) ** when trying to destroy a dbproc QEP, use "private" alias, which is ** always defined as opposed to the "public" alias which would not be ** defined if the dbproc is not grantable. ** 06-aug-92 (teresa) ** change interface to invalidate procedure by name, owner. ** must set rdr_flags_mask = RDR_PROCEDURE when invalidating the ** procedure cache object. ** 07-nov-92 (andre) ** we will no longer create private aliases for dbproc QPs ** 16-jun-94 (andre) ** it is dangerous to cast a (char *) into a (DB_CURSOR_ID *) and then ** dereference the resulting pointer because the chat ptr may not be ** pointing at memory not aligned on an appopriate boundary. Instead, ** we will allocate a DB_CURSOR_ID structure on the stack, initialize ** it and MEcopy() it into the char array */ DB_STATUS psy_kproc( PSY_CB *psy_cb, PSS_SESBLK *sess_cb) { RDF_CB rdf_cb; register RDR_RB *rdf_rb = &rdf_cb.rdf_rb; DB_STATUS status, stat; i4 err_code; pst_rdfcb_init(&rdf_cb, sess_cb); (VOID) MEcopy((PTR)&psy_cb->psy_tabname[0], sizeof(DB_DBP_NAME), (PTR)&rdf_rb->rdr_name.rdr_prcname); STRUCT_ASSIGN_MACRO(sess_cb->pss_user, rdf_rb->rdr_owner); rdf_rb->rdr_types_mask = RDR_PROCEDURE; rdf_rb->rdr_update_op = RDR_DELETE; status = rdf_call(RDF_UPDATE, (PTR) &rdf_cb); if (DB_FAILURE_MACRO(status)) { if (rdf_cb.rdf_error.err_code == E_RD0013_NO_TUPLE_FOUND) { /* Retry */ psy_cb->psy_error.err_code = E_PS0008_RETRY; } else { (VOID) psf_rdf_error(RDF_UPDATE, &rdf_cb.rdf_error, &psy_cb->psy_error); return (status); } } /* Try to destroy the procedure QP in QSF if things went OK. */ if (DB_SUCCESS_MACRO(status)) { QSF_RCB qsf_rb; PSS_DBPALIAS dbpid; DB_CURSOR_ID dbp_curs_id; /* Initialize the header of the QSF control block */ qsf_rb.qsf_type = QSFRB_CB; qsf_rb.qsf_ascii_id = QSFRB_ASCII_ID; qsf_rb.qsf_length = sizeof(qsf_rb); qsf_rb.qsf_owner = (PTR)DB_PSF_ID; qsf_rb.qsf_sid = sess_cb->pss_sessid; qsf_rb.qsf_feobj_id.qso_type = QSO_ALIAS_OBJ; qsf_rb.qsf_feobj_id.qso_lname = sizeof(dbpid); /* Identify the object first */ dbp_curs_id.db_cursor_id[0] = dbp_curs_id.db_cursor_id[1] = 0; (VOID) MEcopy((PTR)&psy_cb->psy_tabname[0], DB_TAB_MAXNAME, (PTR)dbp_curs_id.db_cur_name); MEcopy((PTR) &dbp_curs_id, sizeof(DB_CURSOR_ID), (PTR) dbpid); (VOID) MEcopy((PTR) &sess_cb->pss_user, DB_OWN_MAXNAME, (PTR) (dbpid + sizeof(DB_CURSOR_ID))); I4ASSIGN_MACRO(sess_cb->pss_udbid, *(i4 *) (dbpid + sizeof(DB_CURSOR_ID) + DB_OWN_MAXNAME)); (VOID)MEcopy((PTR) dbpid, sizeof(dbpid), (PTR) qsf_rb.qsf_feobj_id.qso_name); /* See if QEP for the alias already exists. */ qsf_rb.qsf_lk_state = QSO_SHLOCK; stat = qsf_call(QSO_JUST_TRANS, &qsf_rb); if (DB_FAILURE_MACRO(stat)) { if (qsf_rb.qsf_error.err_code != E_QS0019_UNKNOWN_OBJ) { (VOID) psf_error(E_PS037A_QSF_TRANS_ERR, qsf_rb.qsf_error.err_code, PSF_INTERR, &err_code, &psy_cb->psy_error, 0); if (stat > status) status = stat; goto exit; } else { /* Nothing to destroy, QP not in QSF */ goto exit; } } /* Now destroy the ALIAS and the QP objects in QSF */ stat = qsf_call(QSO_DESTROY, &qsf_rb); if (DB_FAILURE_MACRO(stat)) { (VOID) psf_error(E_PS0A09_CANTDESTROY, qsf_rb.qsf_error.err_code, PSF_INTERR, &err_code, &psy_cb->psy_error, 0); if (stat > status) status = stat; } } /* Invalidate procedure object from RDF cache */ pst_rdfcb_init(&rdf_cb, sess_cb); (VOID) MEcopy((PTR)&psy_cb->psy_tabname[0], sizeof(DB_DBP_NAME), (PTR)&rdf_rb->rdr_name.rdr_prcname); STRUCT_ASSIGN_MACRO(sess_cb->pss_user, rdf_rb->rdr_owner); rdf_rb->rdr_types_mask = RDR_PROCEDURE; status = rdf_call(RDF_INVALIDATE, (PTR) &rdf_cb); if (DB_FAILURE_MACRO(status)) { (VOID) psf_rdf_error(RDF_INVALIDATE, &rdf_cb.rdf_error, &psy_cb->psy_error); } exit: return (status); }
/*{ ** Name: ops_deallocate - deallocate resources for an optimization ** ** Description: ** This routine will deallocate the resources used for an optimization. ** Resources include any memory requested from the optimizer memory pool ** and any RDF cache objects which were locked in the global range ** table ** ** Inputs: ** global ptr to global state variable ** report TRUE if errors should be reported ** via the user's control block. ** partial_dbp partial deallocation required for ** statement within a procedure ** ** Outputs: ** Returns: ** VOID ** Exceptions: ** none ** ** Side Effects: ** memory resources released, RDF unfixed, ** QSF query tree memory released ** ** History: ** 29-jun-86 (seputis) ** initial creation ** 8-nov-88 (seputis) ** if no query run trace point is set then destroy the QP since ** SCF assumes optimizer cleans up after error ** 8-nov-88 (seputis) ** turn off CPU accounting if was off originally ** 28-jan-91 (seputis) ** added support for OPF ACTIVE flag ** 20-jul-93 (ed) ** changed name ops_lock for solaris, due to OS conflict ** 29-jul-93 (andre) ** rdr_types_mask must be initialized (to RDR_RELATION) before ** calling RDF_UNFIX. Otherwise RDF may end up complaining because we ** ask it to destroy a relation cache entry while RDR_PROCEDURE bit is ** set. ** 12-aug-93 (swm) ** Cast first parameter of CSaltr_session() to CS_SID to match ** revised CL interface specification. ** 02-Jun-1997 (shero03) ** Update the saved rdf_info_block after calling RDF. ** 02-Aug-2001 (hanal04) Bug 105360 INGSRV 1505 ** Plug the RDF memory leak introduced by inkdo01's new ** function oph_temphist(). ** 17-Dec-2003 (jenjo02) ** Added (CS_SID)NULL to CScnd_signal prototype. ** 6-Feb-2006 (kschendel) ** Fix some squirrely looking code that purported to avoid dangling ** references, but didn't really. (No symptoms known.) ** 14-nov-2007 (dougi) ** Add support for cached dynamic query plans. ** 20-may-2008 (dougi) ** Add support for table procedures. ** 29-may-2009 (wanfr01) Bug 122125 ** Need to add dbid to cache_dynamic queries for db uniqueness */ VOID ops_deallocate( OPS_STATE *global, bool report, bool partial_dbp) { DB_STATUS finalstatus; /* this status is returned to the user ** - it will contain the first error ** during resource deallocation */ DB_ERROR error; /* error code from offending facility */ finalstatus = E_DB_OK; error.err_code = 0; { /* close any fixed RDF objects - deallocate prior to closing the ** global memory stream */ OPV_IGVARS gvar; /* index into global range variable ** table */ OPV_GRT *gbase; /* ptr to base of array of ptrs ** to global range table elements */ OPV_IGVARS maxgvar; /* number of global range table ** elements allocated */ RDF_CB *rdfcb; /* ptr to rdf control block used ** unfix the relation info */ OPV_GBMVARS *rdfmap; /* ptr to map of global range ** variables which have RDF info ** fixed */ gbase = global->ops_rangetab.opv_base; maxgvar = global->ops_rangetab.opv_gv; rdfcb = &global->ops_rangetab.opv_rdfcb; rdfmap = &global->ops_rangetab.opv_mrdf; /* ** rdr_types_mask needs to be initialized - since we will be unfixing ** relation entries, RDR_RELATION seems like a good choice, although 0 ** would suffice as well */ rdfcb->rdf_rb.rdr_types_mask = RDR_RELATION; if (global->ops_cstate.opc_relation) { /* OPC allocates a RDF descriptor for cursors so deallocate ** if this is the case */ DB_STATUS opcrdfstatus; /* RDF return status */ rdfcb->rdf_info_blk = global->ops_cstate.opc_relation; opcrdfstatus = rdf_call( RDF_UNFIX, (PTR)rdfcb ); if ( (DB_FAILURE_MACRO(opcrdfstatus)) && (DB_SUCCESS_MACRO(finalstatus)) ) { finalstatus = opcrdfstatus; error.err_code = rdfcb->rdf_error.err_code; } global->ops_cstate.opc_relation = NULL; } if (maxgvar) { for ( gvar = -1; (gvar = BTnext((i4)gvar, (char *)rdfmap, (i4)maxgvar)) >=0;) { OPV_GRV *gvarp; /* ptr to global range variable to ** be deallocated */ if ((gvarp = gbase->opv_grv[gvar]) /* NULL if not allocated */ && (gvarp->opv_relation) /* not NULL if RDF has been ** called for this range variable */ && !(gvarp->opv_gmask & OPV_TPROC) /* not table procedure */ ) { /* if this element has been allocated and if it has an RDF ** cache element associated with it */ DB_STATUS rdfstatus; /* RDF return status */ gbase->opv_grv[gvar] = NULL; /* so we do not try to deallocate ** twice in case of an error */ rdfcb->rdf_info_blk = gvarp->opv_relation; rdfstatus = rdf_call( RDF_UNFIX, (PTR)rdfcb ); if ( (DB_FAILURE_MACRO(rdfstatus)) && (DB_SUCCESS_MACRO(finalstatus)) ) { finalstatus = rdfstatus; error.err_code = rdfcb->rdf_error.err_code; } gvarp->opv_relation = NULL; } if ((gvarp) && (gvarp->opv_ttmodel)) { /* if this element has been allocated and if it has an RDF ** cache element associated with a persistent table ** which provides histogram models. */ DB_STATUS rdfstatus; /* RDF return status */ rdfcb->rdf_info_blk = gvarp->opv_ttmodel; gvarp->opv_ttmodel = NULL; rdfstatus = rdf_call( RDF_UNFIX, (PTR)rdfcb ); if ( (DB_FAILURE_MACRO(rdfstatus)) && (DB_SUCCESS_MACRO(finalstatus)) ) { finalstatus = rdfstatus; error.err_code = rdfcb->rdf_error.err_code; } } } global->ops_rangetab.opv_gv = 0; } } if (partial_dbp) return; /* only deallocate the global range table ** for DBP, and keep the memory streams ** until the end */ if (global->ops_estate.opn_statistics && global->ops_estate.opn_reset_statistics) { /* statistics CPU accounting was turned on, and needs to be reset */ STATUS cs_status; i4 turn_off; turn_off = FALSE; /* turn off accounting */ global->ops_estate.opn_statistics = FALSE; cs_status = CSaltr_session((CS_SID)0, CS_AS_CPUSTATS, (PTR)&turn_off); if (cs_status != OK) { finalstatus = E_DB_ERROR; error.err_code = cs_status; } } /* deallocate ULM memory stream */ if (global->ops_mstate.ops_streamid == NULL) /* non-zero if allocated */ { /* check if ULM stream does not exist then this deallocation has ** already occurred so just return */ return; } else { DB_STATUS ulm1status;/* ULM return status */ global->ops_mstate.ops_ulmrcb.ulm_streamid_p = &global->ops_mstate.ops_streamid; /* ulm will NULL ops_streamid */ ulm1status = ulm_closestream( &global->ops_mstate.ops_ulmrcb ); if ( (DB_FAILURE_MACRO(ulm1status)) && (DB_SUCCESS_MACRO(finalstatus)) ) { finalstatus = ulm1status; error.err_code = global->ops_mstate.ops_ulmrcb.ulm_error.err_code; } } /* deallocate ULM temp buffer memory stream */ if ( global->ops_mstate.ops_tstreamid ) /* non-zero if allocated */ { DB_STATUS ulm2status; /* ULM return status */ global->ops_mstate.ops_ulmrcb.ulm_streamid_p = &global->ops_mstate.ops_tstreamid; /* ulm will NULL ops_tstreamid */ ulm2status = ulm_closestream( &global->ops_mstate.ops_ulmrcb ); if ( (DB_FAILURE_MACRO(ulm2status)) && (DB_SUCCESS_MACRO(finalstatus)) ) { finalstatus = ulm2status; error.err_code = global->ops_mstate.ops_ulmrcb.ulm_error.err_code; } } /* deallocate OPC ULM buffer memory stream */ if ( global->ops_mstate.ops_sstreamid ) /* non-zero if allocated */ { DB_STATUS ulm3status; /* ULM return status */ global->ops_mstate.ops_ulmrcb.ulm_streamid_p = &global->ops_mstate.ops_sstreamid; /* ulm will NULL ops_sstreamid */ ulm3status = ulm_closestream( &global->ops_mstate.ops_ulmrcb ); if ( (DB_FAILURE_MACRO(ulm3status)) && (DB_SUCCESS_MACRO(finalstatus)) ) { finalstatus = ulm3status; error.err_code = global->ops_mstate.ops_ulmrcb.ulm_error.err_code; } } if (!report #ifdef OPT_F032_NOEXECUTE || /* if trace flag is set then cleanup QSF memory since optimizer will ** generate an error to SCF and SCF assumes optimizer will cleanup */ (global->ops_cb->ops_check && (opt_strace( global->ops_cb, OPT_F032_NOEXECUTE) || opt_strace( global->ops_cb, OPT_F023_NOCOMP) ) ) #endif ) { /* an error or an asychronous abort has occurred so destroy the plan ** or shared plan , FIXME destroy the shared plan in the earlier ** exception handler */ DB_STATUS qsfqpstatus; /* QSF return status */ if(global->ops_qpinit) { /* deallocate QSF object for query plan if another error has occurred ** - in this case OPC has already created a new QP handle and has ** gotten a lock on it */ STRUCT_ASSIGN_MACRO(global->ops_caller_cb->opf_qep, global->ops_qsfcb.qsf_obj_id); /* get ** query plan id */ global->ops_qsfcb.qsf_lk_id = global->ops_qplk_id; /* get lock id for ** QSF */ qsfqpstatus = ops_qsfdestroy(global); /* destroy the query plan */ if ( (DB_FAILURE_MACRO(qsfqpstatus)) && (DB_SUCCESS_MACRO(finalstatus)) ) { finalstatus = qsfqpstatus; error.err_code = global->ops_qsfcb.qsf_error.err_code; } } else { /* OPC has not been reached so need to check for shared query plan */ if (!global->ops_procedure) { /* get query tree if it has not already been retrieved */ qsfqpstatus = ops_gqtree(global); if ( (DB_FAILURE_MACRO(qsfqpstatus)) && (DB_SUCCESS_MACRO(finalstatus)) ) { finalstatus = qsfqpstatus; error.err_code = global->ops_qsfcb.qsf_error.err_code; } } if (global->ops_qheader && (global->ops_qheader->pst_mask1 & PST_RPTQRY)) { /* shared query plan possible */ if (global->ops_procedure->pst_flags & PST_REPEAT_DYNAMIC) { char *p; global->ops_qsfcb.qsf_obj_id.qso_lname = sizeof(DB_CURSOR_ID) + sizeof(i4); MEfill(sizeof(global->ops_qsfcb.qsf_obj_id.qso_name), 0, global->ops_qsfcb.qsf_obj_id.qso_name); MEcopy((PTR)&global->ops_procedure-> pst_dbpid.db_cursor_id[0], sizeof (global->ops_procedure-> pst_dbpid.db_cursor_id[0]), (PTR)global->ops_qsfcb.qsf_obj_id.qso_name); p = (char *) global->ops_qsfcb.qsf_obj_id.qso_name + 2*sizeof(i4); MEcopy((PTR)"qp", sizeof("qp"), p); p = (char *) global->ops_qsfcb.qsf_obj_id.qso_name + sizeof(DB_CURSOR_ID); I4ASSIGN_MACRO(global->ops_caller_cb->opf_udbid, *(i4 *) p); } else /* must be proc or regular repeat query */ { global->ops_qsfcb.qsf_obj_id.qso_lname = sizeof (global->ops_procedure->pst_dbpid); MEcopy((PTR)&global->ops_procedure->pst_dbpid, sizeof (global->ops_procedure->pst_dbpid), (PTR)&global->ops_qsfcb.qsf_obj_id.qso_name[0]); } global->ops_qsfcb.qsf_obj_id.qso_type = QSO_QP_OBJ; global->ops_qsfcb.qsf_lk_state = QSO_SHLOCK; qsfqpstatus = qsf_call(QSO_GETHANDLE, &global->ops_qsfcb); if (DB_SUCCESS_MACRO(qsfqpstatus)) { qsfqpstatus = ops_qsfdestroy( global ); if ( (DB_FAILURE_MACRO(qsfqpstatus)) && (DB_SUCCESS_MACRO(finalstatus)) ) { finalstatus = qsfqpstatus; error.err_code = global->ops_qsfcb.qsf_error.err_code; } } else if (global->ops_qsfcb.qsf_error.err_code != E_QS0019_UNKNOWN_OBJ) { /* if object is not found then this is not a shared query */ finalstatus = qsfqpstatus; error.err_code = global->ops_qsfcb.qsf_error.err_code; } } } } /* release QSF memory allocated to query tree, make sure that this ** is done after the QP has been processed since pst_rptqry is still ** needed for above block */ { DB_STATUS qsfstatus; /* QSF return status */ STRUCT_ASSIGN_MACRO(global->ops_caller_cb->opf_query_tree, global->ops_qsfcb.qsf_obj_id); /* get ** query tree id */ global->ops_qsfcb.qsf_lk_id = global->ops_lk_id; /* get lock id for ** QSF */ qsfstatus = ops_qsfdestroy( global ); if ( (DB_FAILURE_MACRO(qsfstatus)) && (DB_SUCCESS_MACRO(finalstatus)) ) { finalstatus = qsfstatus; error.err_code = global->ops_qsfcb.qsf_error.err_code; } } /* signal that the session is exiting OPF and that another thread may enter */ if (global->ops_cb->ops_smask & OPS_MCONDITION) { DB_STATUS lockstatus; OPG_CB *servercb; servercb = global->ops_cb->ops_server; global->ops_cb->ops_smask &= (~OPS_MCONDITION); lockstatus = ops_exlock(global->ops_caller_cb, &servercb->opg_semaphore); /* check if server ** thread is available, obtain ** semaphore lock on critical variable */ servercb->opg_activeuser--; /* since exit is about to occur, and memory ** has already been deallocated, allow another ** user to enter OPF */ servercb->opg_waitinguser--; /* since exit is about to occur, and memory ** has already been deallocated, allow another ** user to enter OPF */ if (DB_FAILURE_MACRO(lockstatus) && (DB_SUCCESS_MACRO(finalstatus))) { finalstatus = lockstatus; error.err_code = global->ops_caller_cb->opf_errorblock.err_data; } else { if (servercb->opg_waitinguser > servercb->opg_activeuser) { STATUS csstatus; csstatus = CScnd_signal(&servercb->opg_condition, (CS_SID)NULL); /* signal only if some users are waiting */ if ((csstatus != OK) && (DB_SUCCESS_MACRO(finalstatus))) { finalstatus = E_DB_ERROR; error.err_code = csstatus; } } lockstatus = ops_unlock(global->ops_caller_cb, &servercb->opg_semaphore); /* check if server ** thread is available */ if (DB_FAILURE_MACRO(lockstatus) && (DB_SUCCESS_MACRO(finalstatus))) { finalstatus = lockstatus; error.err_code = global->ops_caller_cb->opf_errorblock.err_data; } } } if (DB_FAILURE_MACRO(finalstatus)) { if (report) opx_verror( finalstatus, E_OP0084_DEALLOCATION, error.err_code); /* report ** error and generate an exception */ else opx_rverror(global->ops_cb->ops_callercb, finalstatus, E_OP0084_DEALLOCATION, error.err_code); /* report error only but do not generate an ** exception */ } }
/*{ ** Name: opx_rverror - this routine will report another facility's error ** ** Description: ** This routine will log an error from another facility and the related ** optimizer error. ** ** Inputs: ** opfcb ptr to another facility's control block ** error optimizer error code to report ** facility ptr to facility's control block ** ** Outputs: ** Returns: ** VOID ** Exceptions: ** - internal exception generated ** ** Side Effects: ** the exception handling routines are responsible for ** deallocating OPF resources bound to this session. ** ** History: ** 3-jul-86 (seputis) ** initial creation ** 21-may-89 (jrb) ** now passes generic_error to opx_sccerror routine ** 24-oct-92 (andre) ** interfaces of ule_format() and opx_sccerror() have been changed to ** receive (DB_SQLSTATE *) ** 24-Oct-2008 (jonj) ** Replace ule_doformat with ule_format. [@history_line@]... */ VOID opx_rverror( OPF_CB *opfcb, DB_STATUS status, OPX_ERROR error, OPX_FACILITY facility) { DB_STATUS ule_status; /* return status from ule_format */ i4 ule_error; /* ule cannot format message */ char msg_buffer[DB_ERR_SIZE]; /* error message buffer */ i4 msg_buf_length; /* length of message returned */ i4 log; /* logging state */ DB_SQLSTATE sqlstate; opfcb->opf_errorblock.err_code = error; /* save error code */ opfcb->opf_errorblock.err_data = facility; /* save code ** from facility */ if ((error % 256) < 128) log = ULE_LOOKUP; /* lookup only user errors with range ** of 0-127 */ else log = ULE_LOG; /* log errors with range 128-255 */ #ifdef OPT_F031_WARNINGS /* if trace flag is set then warning or info errors will be reported */ if ( DB_SUCCESS_MACRO(status)) { OPS_CB *ops_cb; ops_cb = ops_getcb(); if (ops_cb && ( !ops_cb->ops_check || !opt_strace( ops_cb, OPT_F031_WARNINGS) )) return; } #endif ule_status = ule_format( error, (CL_SYS_ERR *)NULL, log, &sqlstate, msg_buffer, (i4) (sizeof(msg_buffer)-1), &msg_buf_length, &ule_error, 0); if (ule_status != E_DB_OK) { (VOID)STprintf(msg_buffer, "ULE error = %x\nOptimizer cannot be found - error no = %x Status = %x Facility error = %x \n", ule_error, error , status, facility); } else msg_buffer[msg_buf_length] = 0; /* null terminate */ /* FIXME - should check possible return status and generate a severe error ** unless it is simple (like cannot find message) */ { /* report any errors in the range 0 to 127 to the user */ DB_STATUS scf_status; if (facility) scf_status = opx_sccerror(E_DB_WARN, &sqlstate, error, msg_buffer,(i4)msg_buf_length); /* generate ** a warning, so that SCC_TRACE is ** used, this will ensure that ** SCC_ERROR will be called with ** the "facility" error code which ** will be the ingres user code ** which will be returned to the ** equel program */ else scf_status = opx_sccerror(status, &sqlstate, error, msg_buffer, (i4)msg_buf_length); if (scf_status != E_DB_OK) { TRdisplay( "Optimizer error = %x Status = %x Facility error = %x \n", error , status, facility); } } if (!facility) return; /* if facility error exists then ** report it in the same way */ ule_status = ule_format( facility, (CL_SYS_ERR *)NULL, log, &sqlstate, msg_buffer, (i4) (sizeof(msg_buffer)-1), &msg_buf_length, &ule_error, 0); if (ule_status != E_DB_OK) { (VOID)STprintf(msg_buffer, "ULE error = %x\nOptimizer error = %x Status = %x Facility error cannot be found - error no = %x \n", ule_error, error , status, facility); } else msg_buffer[msg_buf_length] = 0; /* null terminate */ { DB_STATUS scf1_status; scf1_status = opx_sccerror(status, &sqlstate, facility, msg_buffer, (i4)msg_buf_length); if (scf1_status != E_DB_OK) { TRdisplay( "Optimizer error = %x Status = %x Facility error = %x \n", error , status, facility); } } }
/*{ ** Name: opx_adfexception - handle ADF exceptions if possible ** ** Description: ** Routine will be called by exception handlers in the optimizer to ** handle arithmetic exceptions if possible ** ** Inputs: ** ops_cb OPF session control block ** ex_args exception handler arguments ** ** Outputs: ** Returns: ** exception status - EXCONTINUES, or EXRESIGNAL ** where EXRESIGNAL means that the exception is unknown ** Exceptions: ** OPF exception is generated for a fatal ADF exception ** ** Side Effects: ** none ** ** History: ** 20-jan-86 (seputis) ** initial creation ** 31-mar-92 (rog) ** Remove underscores from EX return statuses. ** 24-oct-92 (andre) ** interface of opx_sccerror() has been changed to receive ** (DB_SQLSTATE *) [@history_template@]... */ static STATUS opx_adfexception( OPS_CB *ops_cb, EX_ARGS *ex_args) { DB_STATUS status; ADF_CB *adf_scb; adf_scb = ops_cb->ops_adfcb; status = adx_handler(adf_scb, ex_args); if ((status == E_DB_WARN) && (adf_scb->adf_errcb.ad_errcode == E_AD0116_EX_UNKNOWN) ) { /* adf does not know about this error so resignal it */ return (EXRESIGNAL); } if (DB_SUCCESS_MACRO(status)) { /* adf will return OK status if it knowns about the error and the ** correct action is to continue */ #ifdef OPT_F031_WARNINGS /* if trace flag is set then warning or info errors will be reported */ if ( DB_SUCCESS_MACRO(status) && ops_cb->ops_check && opt_strace( ops_cb, OPT_F031_WARNINGS) ) opx_rverror( ops_cb->ops_callercb, E_DB_WARN, E_OP0701_ADF_EXCEPTION, (OPX_FACILITY)0); /* report ** warning is ** trace flag is set */ #endif return(EXCONTINUES); /* return if error is not ** serious */ } { OPX_ERROR adf_error; OPX_ERROR opf_error; ops_cb->ops_retstatus = status; if (adf_scb->adf_errcb.ad_errclass == ADF_USER_ERROR) { /* report the error message to the user */ adf_error = adf_scb->adf_errcb.ad_usererr; opf_error = E_OP0702_ADF_EXCEPTION; } else { /* report non-user error code */ adf_error = adf_scb->adf_errcb.ad_errcode; opf_error = E_OP0795_ADF_EXCEPTION; } opx_rverror(ops_cb->ops_callercb, E_DB_WARN, opf_error,(OPX_FACILITY)0); /* do not report facility error ** since opx_sccerror will report it ** in the next statement ** - need to use the formatted message ** the ADF provides since it may contain ** parameters */ (VOID) opx_sccerror(status, &adf_scb->adf_errcb.ad_sqlstate, adf_error, adf_scb->adf_errcb.ad_errmsgp, adf_scb->adf_errcb.ad_emsglen); } return (EXDECLARE); /* return to declaration point of ** exception handler */ }
DB_STATUS adu_dbmsinfo( ADF_CB *adf_scb, DB_DATA_VALUE *dv1, DB_DATA_VALUE *rdv) { i4 i = Adf_globs->Adi_num_dbis; i4 found = FALSE; ADF_DBMSINFO *dbi = Adf_globs->Adi_dbi; i4 dbi_size = sizeof(dbi->dbi_reqname); i4 in_size = ((DB_TEXT_STRING *)dv1->db_data)->db_t_count; char *in_str = (char *) ((DB_TEXT_STRING *)dv1->db_data)->db_t_text; register i4 j; register char *c1; register char *c2; char ch_tmp; ALIGN_RESTRICT *tbuf; DB_STATUS db_stat = E_DB_OK; i4 cmp; DB_DATA_VALUE tmp_dv; DB_ERROR err; ADK_MAP *kmap; char localbuf[2004]; bool uselocal = TRUE; if (in_size <= dbi_size) /* No possible match if input is bigger */ { /* Find the request in the dbmsinfo() request table */ while (i--) { cmp = TRUE; c1 = dbi->dbi_reqname; c2 = in_str; j = 0; while (j < in_size && *c1 != 0) { CMtolower(c2, &ch_tmp); if (*c1 != ch_tmp) { cmp = FALSE; break; } c1++; c2++; j++; } if ( cmp && (in_size == dbi_size || (*c1 == 0 && j == in_size)) ) { found = TRUE; break; } dbi++; } } if (!found) { ((DB_TEXT_STRING *)rdv->db_data)->db_t_count = 0; db_stat = E_DB_OK; } else { /* {@fix_me@} ... eventually, we have to handle 1 input, and ** lenspecs that are not FIXED LENGTH */ if (dbi->dbi_num_inputs || dbi->dbi_lenspec.adi_lncompute != ADI_FIXED) return(adu_error(adf_scb, E_AD9999_INTERNAL_ERROR, 0)); tmp_dv.db_datatype = dbi->dbi_dtr; tmp_dv.db_length = dbi->dbi_lenspec.adi_fixedsize; if (tmp_dv.db_length >= 2004) { uselocal = FALSE; tbuf = (ALIGN_RESTRICT *)MEreqmem(0, ((DB_GW4_MAXSTRING + DB_CNTSIZE - 1) / sizeof(ALIGN_RESTRICT)) + 1, FALSE, NULL); tmp_dv.db_data = (PTR)tbuf; } else tmp_dv.db_data = (PTR)&localbuf[0]; /* ** Is request one of the query constants? If so, use adu_dbconst() ** instead of the dbi function found in the dbi table. */ if (dbi == Adf_globs->Adk_bintim_map.adk_dbi) kmap = &Adf_globs->Adk_bintim_map; else if (dbi == Adf_globs->Adk_cpu_ms_map.adk_dbi) kmap = &Adf_globs->Adk_cpu_ms_map; else if (dbi == Adf_globs->Adk_et_sec_map.adk_dbi) kmap = &Adf_globs->Adk_et_sec_map; else if (dbi == Adf_globs->Adk_dio_cnt_map.adk_dbi) kmap = &Adf_globs->Adk_dio_cnt_map; else if (dbi == Adf_globs->Adk_bio_cnt_map.adk_dbi) kmap = &Adf_globs->Adk_bio_cnt_map; else if (dbi == Adf_globs->Adk_pfault_cnt_map.adk_dbi) kmap = &Adf_globs->Adk_pfault_cnt_map; else if (dbi == Adf_globs->Adk_curr_date_map.adk_dbi) kmap = &Adf_globs->Adk_curr_date_map; else if (dbi == Adf_globs->Adk_curr_time_map.adk_dbi) kmap = &Adf_globs->Adk_curr_time_map; else if (dbi == Adf_globs->Adk_curr_tstmp_map.adk_dbi) kmap = &Adf_globs->Adk_curr_tstmp_map; else if (dbi == Adf_globs->Adk_local_time_map.adk_dbi) kmap = &Adf_globs->Adk_local_time_map; else if (dbi == Adf_globs->Adk_local_tstmp_map.adk_dbi) kmap = &Adf_globs->Adk_local_tstmp_map; else kmap = NULL; if (kmap == NULL) db_stat = (*dbi->dbi_func)(dbi, NULL, &tmp_dv, &err); else db_stat = adu_dbconst(adf_scb, kmap, &tmp_dv); if (DB_SUCCESS_MACRO(db_stat)) { db_stat = adu_ascii(adf_scb, &tmp_dv, rdv); } if (!uselocal) MEfree((PTR)tbuf); } return (db_stat); }