/* ** Name: sxapo_close - close an audit trail ** ** Description: ** This routine closes an audit trail that has previously been opened ** by a call to sxap_open. ** ** Overview of algorithm:- ** ** Call SAclose. ** close the memory stream ascociated with this audit trail. ** ** Inputs: ** sxf_rscb The SXF_RSCB structure associated with this ** audit trail ** ** Outputs: ** err_code Error code returned to the caller. ** ** Returns: ** DB_STATUS ** ** History: ** 6-jan-94 (stephenb) ** Initial creation. ** 11-feb-94 (stephenb) ** Update SA call to current spec. */ sxapo_close( SXF_RSCB *rscb, i4 *err_code) { SXAPO_RSCB *sxapo_rscb = (SXAPO_RSCB *)rscb->sxf_sxap; STATUS cl_stat; CL_ERR_DESC cl_err; DB_STATUS status; ULM_RCB ulm_rcb; i4 local_err; *err_code = E_SX0000_OK; for(;;) { if (!sxapo_rscb) { *err_code = E_SX0004_BAD_PARAMETER; _VOID_ ule_format(*err_code, NULL, ULE_LOG, NULL, NULL, 0L, NULL, &local_err, 0); break; } /* ** incriment stats counter */ Sxf_svcb->sxf_stats->close_count++; cl_stat = SAclose(&sxapo_rscb->sxapo_desc, &cl_err); if (cl_stat != OK) { *err_code = E_SX1018_FILE_ACCESS_ERROR; _VOID_ ule_format(*err_code, &cl_err, ULE_LOG, NULL, NULL, 0L, NULL, &local_err, 0); } /* ** Close memory stream */ ulm_rcb.ulm_facility = DB_SXF_ID; ulm_rcb.ulm_streamid_p = &sxapo_rscb->rs_memory; ulm_rcb.ulm_memleft = &Sxf_svcb->sxf_pool_sz; status = ulm_closestream(&ulm_rcb); if (status != E_DB_OK) { *err_code = E_SX106B_MEMORY_ERROR; _VOID_ ule_format(ulm_rcb.ulm_error.err_code, NULL, ULE_LOG, NULL, NULL, 0L, NULL, &local_err, 0); _VOID_ ule_format(*err_code, NULL, ULE_LOG, NULL, NULL, 0L, NULL, &local_err, 0); } /* ULM has nullified rs_memory */ rscb->sxf_sxap = NULL; break; } if (*err_code != E_SX0000_OK) { *err_code = E_SX1026_SXAP_CLOSE; status = E_DB_ERROR; } return (status); }
/* ** Name: SXC_DESTROY_SCB - destroy a SXF session control block ** ** Description: ** This routine frees all the resourses associated with a session control ** block (SXF_SCB). ** ** Overview of algorithm:- ** ** Release the SCB's lock list. ** Close the SCB's memory stream. ** ** Inputs: ** scb pointer to session control block to be destroyed ** ** Outputs: ** err_code ** ** Returns: ** DB_STATUS ** History: ** 25-sept-92 (markg) ** Initial creation. ** 26-oct-1992 (markg) ** Updated error handling. ** 10-mar-1993 (markg) ** Fixed problem where errors returned from ulm were not getting ** handled correctly. ** 10-may-1993 (robf) ** Added handling for database cb in session. */ DB_STATUS sxc_destroy_scb( SXF_SCB *scb, i4 *err_code) { DB_STATUS status = E_DB_OK; i4 local_err; CL_ERR_DESC cl_err; ULM_RCB ulm_rcb; *err_code = E_SX0000_OK; for (;;) { if (LKrelease(LK_ALL, scb->sxf_lock_list, NULL, NULL, NULL, &cl_err) != OK) { *err_code = E_SX1008_BAD_LOCK_RELEASE; _VOID_ ule_format(*err_code, &cl_err, ULE_LOG, NULL, NULL, 0L, NULL, &local_err, 0); } /* ** Release database cb */ sxc_freedbcb(scb, scb->sxf_db_info); ulm_rcb.ulm_facility = DB_SXF_ID; ulm_rcb.ulm_streamid_p = &scb->sxf_scb_mem; ulm_rcb.ulm_memleft = &Sxf_svcb->sxf_pool_sz; status = ulm_closestream(&ulm_rcb); if (status != E_DB_OK) { *err_code = E_SX106B_MEMORY_ERROR; _VOID_ ule_format(ulm_rcb.ulm_error.err_code, NULL, ULE_LOG, NULL, NULL, 0L, NULL, &local_err, 0); _VOID_ ule_format(*err_code, NULL, ULE_LOG, NULL, NULL, 0L, NULL, &local_err, 0); } /* ULM has nullified sxf_scb_mem */ break; } /* Handle any errors */ if (*err_code != E_SX0000_OK) { if (*err_code > E_SXF_INTERNAL) *err_code = E_SX1007_BAD_SCB_DESTROY; if (status == E_DB_OK) status = E_DB_ERROR; } return (status); }
DB_STATUS tpd_s2_clear_all_sps( TPR_CB *v_tpr_p) { DB_STATUS status = E_DB_OK; TPD_SS_CB *sscb_p = (TPD_SS_CB *) v_tpr_p->tpr_session; TPD_DX_CB *dxcb_p = & sscb_p->tss_dx_cb; TPD_LX_CB *lxcb_p = (TPD_LX_CB *) NULL; TPD_LM_CB *lxlm_p = & dxcb_p->tdx_22_lx_ulmcb; TPD_LM_CB *splm_p = & dxcb_p->tdx_23_sp_ulmcb; ULM_RCB ulm; /* 1. MUST reinitialize every LDB's savepoint count */ lxcb_p = (TPD_LX_CB *) lxlm_p->tlm_3_frst_ptr; /* first LX CB in list */ while (lxcb_p != (TPD_LX_CB *) NULL) { lxcb_p->tlx_sp_cnt = 0; lxcb_p = lxcb_p->tlx_22_next_p; /* advance to next LX CB */ } if (splm_p->tlm_1_streamid == (PTR) NULL) return(E_DB_OK); /* session has no outstanding savepoints */ /* 2. MUST close the memory stream opend for savepoints */ ulm.ulm_facility = DB_QEF_ID; /* borrow QEF's id */ ulm.ulm_streamid_p = &splm_p->tlm_1_streamid; /* use before nulling */ ulm.ulm_memleft = & Tpf_svcb_p->tsv_7_ulm_memleft.ts4_2_i4; splm_p->tlm_2_cnt = 0; splm_p->tlm_3_frst_ptr = splm_p->tlm_4_last_ptr = (PTR) NULL; status = ulm_closestream(& ulm); if (status != E_DB_OK) { return( tpd_u1_error(E_TP0017_ULM_CLOSE_FAILED, v_tpr_p) ); } /* ULM has nullified tlm_1_streamid */ return(E_DB_OK); }
/*{ ** Name: psq_tclose - Close the memory stream for a text chain ** ** Description: ** This function closes the memory stream for a text chain, deallocating ** the memory. ** ** Inputs: ** header Pointer to header of text chain ** err_blk Filled in if an error happens ** ** Outputs: ** err_blk Filled in if an error happened ** Returns: ** E_DB_OK Success ** E_DB_ERROR Non-catastrophic failure ** E_DB_FATAL Catastrophic failure ** Exceptions: ** none ** ** Side Effects: ** Deallocates memory ** ** History: ** 18-jul-86 (jeff) ** written */ DB_STATUS psq_tclose( PTR header, DB_ERROR *err_blk) { DB_STATUS status; ULM_RCB ulm_rcb; i4 err_code; STRUCT_ASSIGN_MACRO(((PSQ_THEAD*)header)->psq_tmem, ulm_rcb); status = ulm_closestream(&ulm_rcb); if (status != E_DB_OK) { (VOID) psf_error(E_PS0372_CLOSE_TEXT_CHAIN, ulm_rcb.ulm_error.err_code, PSF_INTERR, &err_code, err_blk, 0); return (status); } return (E_DB_OK); }
/*{ ** Name: OPU_CSMEMORY_CLOSE - Close the stack ULM memory stream ** ** Description: ** This routine closes the ULM memory stream that was used ** for the stack style memory allocation and deallocation. [@comment_line@]... ** ** Inputs: ** global - ** State info for the current query. ** global->ops_mstate.ops_ulmrcb - ** The ULM control block. ** global->ops_mstate.ops_sstreamid - ** The stream id. ** ** Outputs: ** ** Returns: ** Nothing ** Exceptions: ** none ** ** Side Effects: ** none ** ** History: ** 19-July-87 (eric) ** written ** 11-oct-2006 (hayke02) ** Send E_OP0002_NOMEMORY to errlog.log. This change fixes bug 116309. [@history_template@]... */ VOID opu_Csmemory_close( OPS_STATE *global) { DB_STATUS ulmstatus; /* return status from ULM */ /* store the stream id */ global->ops_mstate.ops_ulmrcb.ulm_streamid_p = &global->ops_mstate.ops_sstreamid; /* ULM will nullify ops_sstreamid */ if ( (ulmstatus = ulm_closestream( &global->ops_mstate.ops_ulmrcb )) != E_DB_OK ) { if (global->ops_mstate.ops_ulmrcb.ulm_error.err_code == E_UL0005_NOMEM) { opx_lerror(E_OP0002_NOMEMORY, 0, 0, 0, 0, 0); opx_error( E_OP0002_NOMEMORY); /* out of memory */ } #ifdef E_OP0093_ULM_ERROR else opx_verror( ulmstatus, E_OP0093_ULM_ERROR, global->ops_mstate.ops_ulmrcb.ulm_error.err_code); /* check for error */ #endif } }
/*{ ** Name: psq_cbreturn - Clear call and session CB after processing. ** ** Description: ** This routine is a common routine that clears up the call (psq_cb) and ** session CB (sess_cb) after processing a query. The routine ** psq_parseqry still does its own work as it handles various errors ** associated with textual queries. ** ** Inputs: ** psq_cb Pointer to call CB. ** sess_cb Pointer to the session control block ** ** Outputs: ** psq_cb ** .psq_result Result query tree. ** Returns: ** DB_STATUS ** Exceptions: ** None ** ** Side Effects: ** None ** ** History: ** 21-apr-89 (neil) ** Extracted this from psq_parseqry to allow it to be called from ** other routines as well. ** 15-jun-92 (barbara) ** Sybil merge. Pass in sess control block to pst_clrrng. ** 25-may-1993 (rog) ** Moved clean-up/exit code here from psq_parseqry() above, and added ** status argument so that we know whether to execute the good exit ** code or the bad exit code. ** 10-aug-93 (andre) ** fixed cause of a compiler warning ** 27-aug-93 (andre) ** (part of fix for bug 54348) ** moved code responsible for destroying a dbproc QEP into a separate ** function (psq_destr_dbp_qep()) which will be called from ** psq_cbreturn() and from psq_recreate() if an error occurs AFTER the ** dbproc QEP QSF object has been created ** 16-mar-94 (andre) ** use psf_retry() to determine whether we are going to retry parsing ** this query and, therefore, whether we should destroy any QSF objects ** created during the just completed attempt ** 28-jan-2004 (schka24) ** Close partition def memory if open. ** 15-Mar-2006 (kschendel) ** Close function-arg stream if open. ** 28-nov-2007 (dougi) ** Different logic for PSQ_REPDYN (for cached dynamic queries). */ DB_STATUS psq_cbreturn( PSQ_CB *psq_cb, PSS_SESBLK *sess_cb, DB_STATUS ret_val) { DB_STATUS status; i4 err_code; QSF_RCB qsf_rb; 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; /* Tasks that are common to both a normal return and an error return. */ do /* Something to break out of */ { /* Clear any cached stack blocks as we're going to ** trash the memory stream in here anyway. */ sess_cb->pss_stk_freelist = NULL; /* Other stuff that shouldn't be left dangling */ sess_cb->pss_yyvars = NULL; /* ** Clear out the user's range table. */ status = pst_clrrng(sess_cb, &sess_cb->pss_usrrange, &psq_cb->psq_error); if (status == E_DB_FATAL) ret_val = status; /* ** Clear out the auxliary range table. */ status = pst_clrrng(sess_cb, &sess_cb->pss_auxrng, &psq_cb->psq_error); if (status == E_DB_FATAL) ret_val = status; /* ** If the statement has emitted query text, close the stream. */ if (sess_cb->pss_tchain != (PTR) NULL) { status = psq_tclose(sess_cb->pss_tchain, &psq_cb->psq_error); if (status == E_DB_FATAL) ret_val = status; sess_cb->pss_tchain = (PTR) NULL; } if (sess_cb->pss_tchain2 != (PTR) NULL) { status = psq_tclose(sess_cb->pss_tchain2, &psq_cb->psq_error); if (status == E_DB_FATAL) ret_val = status; sess_cb->pss_tchain2 = (PTR) NULL; } /* Close partition definition working memory stream if in use */ if (sess_cb->pss_ses_flag & PSS_PARTDEF_STREAM_OPEN) { status = ulm_closestream(&sess_cb->pss_partdef_stream); /* Toss any error */ sess_cb->pss_ses_flag &= ~PSS_PARTDEF_STREAM_OPEN; } /* Close nested-function-call arg list stack if it was needed */ if (sess_cb->pss_funarg_stream != NULL) { ULM_RCB ulm; ulm.ulm_facility = DB_PSF_ID; ulm.ulm_poolid = Psf_srvblk->psf_poolid; ulm.ulm_streamid_p = &sess_cb->pss_funarg_stream; ulm.ulm_memleft = &sess_cb->pss_memleft; status = ulm_closestream(&ulm); /* Ignore error */ sess_cb->pss_funarg_stream = NULL; } } while (0); for (; ret_val == E_DB_OK; ) /* Something to break out of */ { /* ** This is the path we take for a successful exit. ** If we have a problem here, we break out of this loop and ** fall through to the failure exit code. */ /* ** Set the QSF id of the return object and unlock it, if any. */ if (sess_cb->pss_ostream.psf_mstream.qso_handle != (PTR) NULL) { qsf_rb.qsf_obj_id.qso_handle = sess_cb->pss_ostream.psf_mstream.qso_handle; qsf_rb.qsf_lk_id = sess_cb->pss_ostream.psf_mlock; if (psq_cb->psq_mode == PSQ_REPDYN) { /* If cached dynamic qp already exists, destroy parse ** tree object. */ if (ret_val = qsf_call(QSO_DESTROY, &qsf_rb)) { (VOID) psf_error(E_PS0A09_CANTDESTROY, qsf_rb.qsf_error.err_code, PSF_INTERR, &err_code, &psq_cb->psq_error, 0); /* break out to the failure code. */ break; } } else { /* If not cached dynamic, copy object ID and unlock ** parse tree. */ STRUCT_ASSIGN_MACRO(sess_cb->pss_ostream.psf_mstream, psq_cb->psq_result); if (ret_val = qsf_call(QSO_UNLOCK, &qsf_rb)) { (VOID) psf_error(E_PS0B05_CANT_UNLOCK, qsf_rb.qsf_error.err_code, PSF_INTERR, &err_code, &psq_cb->psq_error, 0); /* break out to the failure code. */ break; } } sess_cb->pss_ostream.psf_mlock = 0; } /* ** Unlock the text stream if it was used. ** this is unlocked after the text stream is created. ** (Don't know why this was taken out.) */ #ifdef NO if (sess_cb->pss_tstream.psf_mstream.qso_handle != (PTR) NULL) { qsf_rb.qsf_obj_id.qso_handle = sess_cb->pss_tstream.psf_mstream.qso_handle; qsf_rb.qsf_lk_id = sess_cb->pss_tstream.psf_mlock; if (ret_val = qsf_call(QSO_UNLOCK, &qsf_rb)) { (VOID) psf_error(E_PS0B05_CANT_UNLOCK, qsf_rb.qsf_error.err_code, PSF_INTERR, &err_code, &psq_cb->psq_error, 0); /* break out to the failure code. */ break; } sess_cb->pss_tstream.psf_mlock = 0; } #endif /* Unlock the control block stream if it was used */ if (sess_cb->pss_cbstream.psf_mstream.qso_handle != (PTR) NULL) { qsf_rb.qsf_obj_id.qso_handle = sess_cb->pss_cbstream.psf_mstream.qso_handle; qsf_rb.qsf_lk_id = sess_cb->pss_cbstream.psf_mlock; if (ret_val = qsf_call(QSO_UNLOCK, &qsf_rb)) { (VOID) psf_error(E_PS0B05_CANT_UNLOCK, qsf_rb.qsf_error.err_code, PSF_INTERR, &err_code, &psq_cb->psq_error, 0); /* break out to the failure code. */ break; } sess_cb->pss_cbstream.psf_mlock = 0; } /* ** We need to deallocate memory if the same query is to be tried ** again. This is supposed to fix The 'drop table, nonexistent_table' ** memory leak problem. */ if (psf_retry(sess_cb, psq_cb, ret_val)) { if (sess_cb->pss_ostream.psf_mstream.qso_handle != (PTR) NULL) { (VOID) psf_mclose(sess_cb, &sess_cb->pss_ostream, &psq_cb->psq_error); sess_cb->pss_ostream.psf_mstream.qso_handle = (PTR) NULL; } if (sess_cb->pss_tstream.psf_mstream.qso_handle != (PTR) NULL) { (VOID) psf_mclose(sess_cb, &sess_cb->pss_tstream, &psq_cb->psq_error); sess_cb->pss_tstream.psf_mstream.qso_handle = (PTR) NULL; } if (sess_cb->pss_cbstream.psf_mstream.qso_handle != (PTR) NULL) { (VOID) psf_mclose(sess_cb, &sess_cb->pss_cbstream, &psq_cb->psq_error); sess_cb->pss_cbstream.psf_mstream.qso_handle = (PTR) NULL; } } /* end with no output streams */ sess_cb->pss_ostream.psf_mstream.qso_handle = (PTR) NULL; sess_cb->pss_tstream.psf_mstream.qso_handle = (PTR) NULL; sess_cb->pss_cbstream.psf_mstream.qso_handle = (PTR) NULL; if (ret_val == E_DB_OK) { /* ** this IF statement is here to keep acc from complaining - we would ** never reach this point unless ret_val was E_DB_OK */ return (ret_val); } } /* This is the failure exit code. */ /* ** On an error, the yacc error handling function will call psf_error. ** All that's necessary here is to return a status indicating that ** an error has occurred. If an output object has been allocated, ** and the error caused the statement to fail, deallocate the object ** before returning. Same for miscellaneous objects, like control ** blocks and query text. */ if (ret_val == E_DB_ERROR || ret_val == E_DB_FATAL || ret_val == E_DB_SEVERE) { /* ** In case of CREATE PROCEDURE statement we also need to ** destroy the QEP object in QSF if it was created. */ if (sess_cb->pss_ostream.psf_mstream.qso_handle != (PTR) NULL && psq_cb->psq_mode == PSQ_CREDBP ) { DB_STATUS stat; stat = psq_destr_dbp_qep(sess_cb, sess_cb->pss_ostream.psf_mstream.qso_handle, &psq_cb->psq_error); if (stat > ret_val) ret_val = stat; } if (sess_cb->pss_ostream.psf_mstream.qso_handle != (PTR) NULL) { (VOID) psf_mclose(sess_cb, &sess_cb->pss_ostream, &psq_cb->psq_error); sess_cb->pss_ostream.psf_mstream.qso_handle = (PTR) NULL; } if (sess_cb->pss_tstream.psf_mstream.qso_handle != (PTR) NULL) { (VOID) psf_mclose(sess_cb, &sess_cb->pss_tstream, &psq_cb->psq_error); sess_cb->pss_tstream.psf_mstream.qso_handle = (PTR) NULL; } if (sess_cb->pss_cbstream.psf_mstream.qso_handle != (PTR) NULL) { (VOID) psf_mclose(sess_cb, &sess_cb->pss_cbstream, &psq_cb->psq_error); sess_cb->pss_cbstream.psf_mstream.qso_handle = (PTR) NULL; } } /* ** If the statement was a "define cursor" or a "define repeat cursor", ** we have to deallocate the cursor control block, if it was allocated. */ if (sess_cb->pss_cstream != (PTR) NULL) { status = psq_delcursor(sess_cb->pss_crsr, &sess_cb->pss_curstab, &sess_cb->pss_memleft, &psq_cb->psq_error); if (status == E_DB_FATAL) ret_val = status; } return(ret_val); }
/* ** Name: sxapo_open - open an audit trail ** ** Description: ** This routine is used to open an audit trail that can, in theory, be used ** for either reading or writing audit records, although reading of ** operating system audit records is not currently supported. SXF supports ** the ability to have a maximum of one audit trail open for writing at ** a time. This routine ** returns an access identifier (actually a pointer to a SXAPO_RSCB ** structure) that must be specified for all other operations requested ** on this trail. if no filename is specified the current audit trail ** will be opened. ** ** Overview of algorithm:- ** ** Validate the parameters passed to the routine. ** Open a memory stream and allocate and build a SXAPO_RSCB. ** If filename is NULL get the name of the current audit trail. ** Call the SAopen routine to perform the physical open call. ** ** ** Inputs: ** filename Name of the audit trail to open, if this is NULL ** the current audit trail will be opened. ** mode either SXF_READ of SXF_WRITE (must currently ** be SXF_WRITE). ** sxf_rscb the SXF_RSCB for the audit trail ** ** Outputs: ** sxf_rscb Access identifier for audit file. ** err_code Error code returned to the caller. ** ** Returns: ** DB_STATUS ** ** History: ** 6-jan-94 (stephenb) ** Initial Creation. ** 7-feb-94 (stephenb) ** log error E_SX002E_OSAUDIT_NO_READ since we don't do it anywhere ** else yet. ** 11-feb-94 (stephenb) ** Update SA call to current spec. */ DB_STATUS sxapo_open( PTR filename, i4 mode, SXF_RSCB *sxf_rscb, i4 *filesize, PTR sptr, i4 *err_code) { ULM_RCB ulm_rcb; DB_STATUS status = E_DB_OK; i4 local_err; bool stream_open = FALSE; SXAPO_RSCB *sxapo_rscb; STATUS cl_stat; CL_ERR_DESC cl_err; *err_code = E_SX0000_OK; for (;;) { /* validate parameters, write is currently the only valid mode */ if (sxf_rscb == NULL) { *err_code = E_SX0004_BAD_PARAMETER; break; } else if (mode != SXF_WRITE) { *err_code = E_SX002E_OSAUDIT_NO_READ; /* ** Log this here since we don't yet do it anywhere else. */ _VOID_ ule_format(*err_code, NULL, ULE_LOG, NULL, NULL, 0L, NULL, &local_err, 0); break; } /* ** Open a memory stream and allocate some memory for the SXAPO_RSCB */ ulm_rcb.ulm_facility = DB_SXF_ID; ulm_rcb.ulm_poolid = Sxf_svcb->sxf_pool_id; ulm_rcb.ulm_blocksize = 0; ulm_rcb.ulm_memleft = &Sxf_svcb->sxf_pool_sz; ulm_rcb.ulm_streamid_p = &ulm_rcb.ulm_streamid; /* No other allocations on this stream - make it private */ /* Open stream and allocate SXAPO_RSCB with one call */ ulm_rcb.ulm_flags = ULM_PRIVATE_STREAM | ULM_OPEN_AND_PALLOC; ulm_rcb.ulm_psize = sizeof (SXAPO_RSCB); status = ulm_openstream(&ulm_rcb); if (status != E_DB_OK) { if(ulm_rcb.ulm_error.err_code == E_UL0005_NOMEM) *err_code = E_SX1002_NO_MEMORY; else *err_code = E_SX106B_MEMORY_ERROR; _VOID_ ule_format(ulm_rcb.ulm_error.err_code, NULL, ULE_LOG, NULL, NULL, 0L, NULL, &local_err, 0); _VOID_ ule_format(*err_code, NULL, ULE_LOG, NULL, NULL, 0L, NULL, &local_err, 0); break; } stream_open = TRUE; sxf_rscb->sxf_sxap = ulm_rcb.ulm_pptr; sxapo_rscb = (SXAPO_RSCB *) sxf_rscb->sxf_sxap; sxapo_rscb->rs_memory = ulm_rcb.ulm_streamid; /* ** Filename should not be supplied for OS audit trail writes */ if (filename) { *err_code = E_SX101E_INVALID_FILENAME; break; } else { /* ** Auditing must be enabled to use "current" file */ if (Sxapo_cb->sxapo_status & SXAPO_STOPAUDIT) { _VOID_ ule_format(E_SX10A7_NO_CURRENT_FILE, NULL, ULE_LOG, NULL, NULL, 0L, NULL, &local_err, 0); *err_code = E_SX0015_FILE_NOT_FOUND; break; } } /* ** Open the audit trail with SAopen */ cl_stat = SAopen(NULL, SA_WRITE, &sxapo_rscb->sxapo_desc, &cl_err); if (cl_stat != OK) { *err_code = E_SX1018_FILE_ACCESS_ERROR; _VOID_ ule_format(*err_code, &cl_err, ULE_LOG, NULL, NULL, 0L, NULL, &local_err, 0); break; } break; } /* ** Handle any errors */ if (*err_code != E_SX0000_OK) { if (stream_open) _VOID_ ulm_closestream(&ulm_rcb); if (*err_code > E_SXF_INTERNAL) { _VOID_ ule_format(E_SX10B6_OSAUDIT_OPEN_FAILED, NULL, ULE_LOG, NULL, NULL, 0L, NULL, &local_err, 0); *err_code = E_SX1023_SXAP_OPEN; } if (status == E_DB_OK) status = E_DB_ERROR; } else { /* ** Incriment stats counter */ Sxf_svcb->sxf_stats->open_write++; } return (status); }
DB_STATUS qet_t9_ok_w_ldbs( QEE_DSH *i_dsh_p, QEF_RCB *v_qer_p, bool *o1_ok_p) { DB_STATUS status_0 = E_DB_OK, status_t = E_DB_OK, status_u = E_DB_OK; DB_ERROR ulm_err, tpf_err; QES_DDB_SES *dds_p = & v_qer_p->qef_cb->qef_c2_ddb_ses; TPR_CB tpr_cb, *tpr_p = & tpr_cb; QEF_QP_CB *qp_p = i_dsh_p->dsh_qp_ptr; QEF_AHD *act_p = qp_p->qp_ahd; QEQ_D1_QRY *subqry_p; ULM_RCB ulm; i4 w_ldbcnt; TPR_W_LDB *wldb1_p = (TPR_W_LDB *) NULL, *wldb2_p = (TPR_W_LDB *) NULL; *o1_ok_p = TRUE; /* assume */ if (qp_p->qp_qmode == QEQP_01QM_RETRIEVE) return(E_DB_OK); /* read-only query */ /* assume that there are update sites within this query plan */ /* allocate stream to build list of LDB ptrs; note that this ** stream must be closed upon return from this routine */ STRUCT_ASSIGN_MACRO(Qef_s_cb->qef_s_ulmcb, ulm); ulm.ulm_blocksize = sizeof(TPR_W_LDB); /* allocation size */ status_u = qec_mopen(&ulm); if (status_u) { v_qer_p->error.err_code = ulm.ulm_error.err_code; return(status_u); } /* traverse the action list to build an LDB ptr list */ MEfill(sizeof(tpr_cb), '\0', (PTR) & tpr_cb); tpr_p->tpr_session = dds_p->qes_d2_tps_p; /* TPF session CB ptr */ tpr_p->tpr_rqf = dds_p->qes_d3_rqs_p; /* RQF session CB ptr */ tpr_cb.tpr_15_w_ldb_p = (TPR_W_LDB *) NULL; w_ldbcnt = 0; act_p = qp_p->qp_ahd; while (act_p != (QEF_AHD *) NULL && status_u == E_DB_OK) { if (act_p->ahd_atype == QEA_D1_QRY) { subqry_p = & act_p->qhd_obj.qhd_d1_qry; if (subqry_p->qeq_q3_ctl_info & QEQ_002_USER_UPDATE) { /* an update site */ w_ldbcnt++; ulm.ulm_psize = sizeof(TPR_W_LDB); status_u = qec_malloc(&ulm); if (status_u) { STRUCT_ASSIGN_MACRO(ulm.ulm_error, ulm_err); goto dismantle_9; } else { /* allocation ok */ wldb2_p = (TPR_W_LDB *) ulm.ulm_pptr; if (wldb1_p == (TPR_W_LDB *) NULL) { /* first in list */ tpr_cb.tpr_15_w_ldb_p = wldb1_p = wldb2_p; wldb2_p->tpr_1_prev_p = wldb2_p->tpr_2_next_p = (TPR_W_LDB *) NULL; } else { /* append to list */ wldb1_p->tpr_2_next_p = wldb2_p; wldb2_p->tpr_1_prev_p = wldb1_p; wldb2_p->tpr_2_next_p = (TPR_W_LDB *) NULL; } wldb2_p->tpr_3_ldb_p = subqry_p->qeq_q5_ldb_p; } } } act_p = act_p->ahd_next; /* advance */ } /* call TPF if any update sites */ if (tpr_cb.tpr_15_w_ldb_p != (TPR_W_LDB *) NULL) { status_t = qed_u17_tpf_call(TPF_OK_W_LDBS, & tpr_cb, v_qer_p); if (status_t) STRUCT_ASSIGN_MACRO(tpr_cb.tpr_error, tpf_err); else *o1_ok_p = tpr_cb.tpr_14_w_ldbs_ok; } dismantle_9: /* must always close stream */ status_0 = ulm_closestream(&ulm); if (status_u) { /* return previous ulm error */ STRUCT_ASSIGN_MACRO(ulm_err, v_qer_p->error); return(status_u); } if (status_t) { /* return tpf error */ STRUCT_ASSIGN_MACRO(tpf_err, v_qer_p->error); return(status_t); } if (status_0) { /* return close-stream ulm error */ STRUCT_ASSIGN_MACRO(ulm.ulm_error, v_qer_p->error); } return(status_0); }
/*{ ** 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: QEU_DELETE - delete tuples from a table ** ** External QEF call: status = qef_call(QEU_DELETE, &qeu_cb); ** ** Description: ** Tuples are deleted from a table opened with the QEU_OPEN ** command. If no qualification is given, the current tuple is ** deleted. ** ** Inputs: ** qeu_cb ** .qeu_eflag designate error handling semantis ** for user errors. ** QEF_INTERNAL return error code. ** QEF_EXTERNAL send message to user. ** .qeu_acc_id table access id ** .qeu_tup_length tuple length of the table ** Only required for keyed delete ** .qeu_qual qualification function ** .qeu_qarg argument to qualification function ** .qeu_klen length of key - number of entries ** .qeu_key key for delete ** <qeu_key> is a pointer to an array of pointers of type DMR_ATTR_ENTRY ** .attr_number ** .attr_operation ** .attr_value_ptr ** .qeu_flag operation qualifier ** QEU_BY_TID remove tuple whose TID is in qeu_tid ** .qeu_tid contains TID of the tuple to be ** removed if (qeu_flag & QEU_BY_TID) ** ** Outputs: ** qeu_cb ** .qeu_count number of tuples retrieved ** .error.err_code One of the following ** E_QE0000_OK ** E_QE0002_INTERNAL_ERROR ** E_QE0004_NO_TRANSACTION ** E_QE0007_NO_CURSOR ** E_QE0017_BAD_CB ** E_QE0018_BAD_PARAM_IN_CB ** Returns: ** E_DB_OK ** E_DB_ERROR caller error ** E_DB_FATAL internal error ** Exceptions: ** none ** ** Side Effects: ** none ** ** History: ** 27-may-86 (daved) ** written ** 02-sep-86 (jennifer) ** Modified qeu_delete to return a count of tuples ** deleted. ** 21-oct-86 (daved) ** did above fix for case where dmf returns no more rows. ** 22-dec-86 (daved) ** return OK if deleting keyed records ** 10-dec-87 (puree) ** Converted all ulm_palloc to qec_palloc ** 04-jan-91 (andre) ** added functionality to delete tuples by TID ** 18-jun-92 (andre) ** do not allocate memory unless we will actually be reading tuples, ** i.e. if a key is specified ** 06-mar-96 (nanpr01) ** removed the dependency on DB_MAXTUP for increased tuple size ** project. Also added the check to make sure tuple size is set ** whoever called this routine. Also tuple size consistency is ** checked iff qeu_klen > 0. ** 24-Jan-2001 (jenjo02) ** Ensure that memory stream is closed before returning. ** 11-Apr-2008 (kschendel) ** Revised DMF qualification requirements, simplified for QEU. */ DB_STATUS qeu_delete( QEF_CB *qef_cb, QEU_CB *qeu_cb) { i4 err; i4 count; DMR_CB dmr_cb; DB_STATUS status; GLOBALREF QEF_S_CB *Qef_s_cb; ULM_RCB ulm; /* so we don't need to allocate a tuple buffer ** as a stack variable, use dynamic memory */ count = 0; qeu_cb->qeu_count = 0; qeu_cb->error.err_code = E_QE0000_OK; /* QEU_DELETE is only valid in a transaction */ if (qef_cb->qef_stat == QEF_NOTRAN) { qef_error(E_QE0004_NO_TRANSACTION, 0L, E_DB_ERROR, &err, &qeu_cb->error, 0); return (E_DB_ERROR); } dmr_cb.type = DMR_RECORD_CB; dmr_cb.length = sizeof(DMR_CB); dmr_cb.dmr_access_id = qeu_cb->qeu_acc_id; dmr_cb.dmr_q_fcn = NULL; /* position the cursor */ /* if there is a key, position by qual. Else, position all records */ if (qeu_cb->qeu_klen) { if (qeu_cb->qeu_tup_length <= 0) { qef_error(E_QE0018_BAD_PARAM_IN_CB, 0L, E_DB_ERROR, &err, &qeu_cb->error, 0); return (E_DB_ERROR); } /* allocate memory for a tuple only if planning to call qeu_get() */ STRUCT_ASSIGN_MACRO(Qef_s_cb->qef_d_ulmcb, ulm); /* Open stream and allocate tuple memory in one action */ ulm.ulm_flags = ULM_PRIVATE_STREAM | ULM_OPEN_AND_PALLOC; ulm.ulm_psize = ulm.ulm_blocksize = qeu_cb->qeu_tup_length; if ((status = qec_mopen(&ulm)) != E_DB_OK) { qef_error(E_QE001E_NO_MEM, 0L, E_DB_ERROR, &err, &qeu_cb->error, 0); return (status); } /* set the keys */ dmr_cb.dmr_position_type = DMR_QUAL; dmr_cb.dmr_attr_desc.ptr_address = (PTR) qeu_cb->qeu_key; dmr_cb.dmr_attr_desc.ptr_in_count = qeu_cb->qeu_klen; dmr_cb.dmr_attr_desc.ptr_size = sizeof (DMR_ATTR_ENTRY); dmr_cb.dmr_s_estimated_records = -1; /* row qualifier */ dmr_cb.dmr_q_fcn = (DB_STATUS (*)(void *,void *)) qeu_cb->qeu_qual; dmr_cb.dmr_q_arg = (PTR) qeu_cb->qeu_qarg; if (qeu_cb->qeu_qual != NULL) { dmr_cb.dmr_q_rowaddr = &qeu_cb->qeu_qarg->qeu_rowaddr; dmr_cb.dmr_q_retval = &qeu_cb->qeu_qarg->qeu_retval; } dmr_cb.dmr_flags_mask = 0; status = dmf_call(DMR_POSITION, &dmr_cb); if (status != E_DB_OK) { ulm_closestream(&ulm); if (dmr_cb.error.err_code == E_DM0055_NONEXT) return (E_DB_OK); qef_error(dmr_cb.error.err_code, 0L, status, &err, &qeu_cb->error, 0); return (status); } /* the tuple length will not change. Tell DMF about it */ dmr_cb.dmr_data.data_in_size = qeu_cb->qeu_tup_length; dmr_cb.dmr_data.data_address = ulm.ulm_pptr; } for (;;) { if (qeu_cb->qeu_klen) { /* get the tuple */ dmr_cb.dmr_flags_mask = DMR_NEXT; status = dmf_call(DMR_GET, &dmr_cb); if (status != E_DB_OK) { if (dmr_cb.error.err_code == E_DM0055_NONEXT) { status = E_DB_OK; break; } else { qef_error(dmr_cb.error.err_code, 0L, status, &err, &qeu_cb->error, 0); } break; } } /* ** delete the tuple: if deleting by TID, copy qeu_tid to dmr_tid and set ** dmr_flags_mask to DMR_BY_TID */ if (qeu_cb->qeu_flag & QEU_BY_TID) { dmr_cb.dmr_flags_mask = DMR_BY_TID; dmr_cb.dmr_tid = qeu_cb->qeu_tid; } /* otherwise delete the current tuple */ else { dmr_cb.dmr_flags_mask = DMR_CURRENT_POS; } status = dmf_call(DMR_DELETE, &dmr_cb); if (status != E_DB_OK) { qef_error(dmr_cb.error.err_code, 0L, status, &err, &qeu_cb->error, 0); break; } count++; if (qeu_cb->qeu_klen == 0) { /* we are only deleting current tuple */ break; } } if (qeu_cb->qeu_klen) { /* don't try to close a stream unless it was opened */ ulm_closestream(&ulm); } qeu_cb->qeu_count = count; return (status); }
/*{ ** Name: QEU_REPLACE - replace tuple(s) in a table ** ** External QEF call: status = qef_call(QEU_REPLACE, &qeu_cb); ** ** Description: ** A tuple is replaced in a table opened with the QEU_OPEN ** command. ** If QEU_BY_TID is specified, ** the tuple with specified TID is repalced ** else if qeu_cb->kqeu_klen > 0 ** qeu_f_qual points to a function which will both determine whether the ** tuple should be updated and make appropriate changes to the tuple ** passed to it ** else ** replace the tuple which was read by position as specified by the caller ** ** Inputs: ** qeu_cb ** .qeu_eflag designate error handling semantis ** for user errors. ** QEF_INTERNAL return error code. ** QEF_EXTERNAL send message to user. ** .qeu_acc_id table access id ** .qeu_tup_length lenth of a tuple ** .qeu_input buffer containing new values for the ** tuple being replaced ** .qeu_qual qualification function for DMF ** .qeu_qarg argument to (*qeu_qual) () ** .qeu_klen length of key ** .qeu_key key for update ** <qeu_key> is a pointer to an array of pointers of type DMR_ATTR_ENTRY ** .attr_number ** .attr_operation ** .attr_value_ptr ** .qeu_flag operation qualifier ** QEU_BY_TID replace tuple whose TID is in ** qeu_tid ** .qeu_tid contains TID of the tuple to be ** replaced if (qeu_flag & QEU_BY_TID) ** .qeu_f_qual if !(qeu_klen > 0) this must point ** at a function which will decide ** whether and how the current tuple ** must be replaced ** .qeu_f_qarg argument to (*qeu_f_qual) () ** ** Outputs: ** qeu_cb ** .qeu_count number of tuples updated ** .error.err_code One of the following ** E_QE0000_OK ** E_QE0002_INTERNAL_ERROR ** E_QE0004_NO_TRANSACTION ** E_QE0007_NO_CURSOR ** E_QE0017_BAD_CB ** E_QE0018_BAD_PARAM_IN_CB ** Returns: ** E_DB_OK ** E_DB_ERROR caller error ** E_DB_FATAL internal error ** Exceptions: ** none ** ** Side Effects: ** none ** ** History: ** 18-jun-92 (andre) ** written ** 22-jun-92 (andre) ** changed the function to allow update one row by tid or to update ** multiple rows subject to qualification function ** 24-jun-92 (andre) ** another change to allow update of prepositioned tuple ** 13-sep-93 (robf) ** Extended to handle update multiple rows without ** requiring a key position. This is signalled when qeu_klen==0 ** and qeu_qual != NULL and qeu_f_qual!=NULL ** 30-nov-93 (robf) ** When updating multiple rows, keep going after first update. ** 24-Jan-2001 (jenjo02) ** Ensure that memory stream is closed before returning. ** 11-Apr-2008 (kschendel) ** Revised DMF qualification requirements, simplified for QEU. */ DB_STATUS qeu_replace( QEF_CB *qef_cb, QEU_CB *qeu_cb) { i4 err = 0L; DMR_CB dmr_cb; DB_STATUS status; GLOBALREF QEF_S_CB *Qef_s_cb; ULM_RCB ulm; i4 (*repl_func)(void *, void *); bool position_all=FALSE; bool mem_opened=FALSE; if (qeu_cb->qeu_flag & QEU_BY_TID) { /* ** if update_by_tid, no key(s), qualification function, or qualification ** function parameters should be passed; ** qeu_cb->qeu_input must point at a structure containing a ptr to the ** new value for the tuple of specified size */ if (qeu_cb->qeu_klen || qeu_cb->qeu_qual || qeu_cb->qeu_qarg || qeu_cb->qeu_f_qual || qeu_cb->qeu_f_qarg || !qeu_cb->qeu_input || !qeu_cb->qeu_input->dt_data || !qeu_cb->qeu_input->dt_size) { err = E_QE0018_BAD_PARAM_IN_CB; status = E_DB_ERROR; } } else if (qeu_cb->qeu_klen==0 && (repl_func = qeu_cb->qeu_f_qual) != NULL && qeu_cb->qeu_qual) { position_all=TRUE; /* ** Request to replace all qualifying in table, without key ** positioning */ if (!qeu_cb->qeu_qarg || !qeu_cb->qeu_f_qarg ) { err = E_QE0018_BAD_PARAM_IN_CB; status = E_DB_ERROR; } } else if (qeu_cb->qeu_klen == 0) { /* ** if asked to update the current tuple, no qualification function, or ** qualification function parameters should be passed; ** qeu_cb->qeu_input must point at a structure containing a ptr to ** the new value for the tuple of specified size */ if (qeu_cb->qeu_qual || qeu_cb->qeu_qarg || qeu_cb->qeu_f_qual || qeu_cb->qeu_f_qarg || !qeu_cb->qeu_input || !qeu_cb->qeu_input->dt_data || !qeu_cb->qeu_input->dt_size) { err = E_QE0018_BAD_PARAM_IN_CB; status = E_DB_ERROR; } } else if ((repl_func = qeu_cb->qeu_f_qual) == NULL) { /* ** if caller supplied a key, must specify the function which ** will determine whether and how the tuple must be updated */ err = E_QE0018_BAD_PARAM_IN_CB; status = E_DB_ERROR; } if (err) { (VOID) qef_error(err, 0L, status, &err, &qeu_cb->error, 0); return(status); } qeu_cb->qeu_count = 0; qeu_cb->error.err_code = E_QE0000_OK; /* QEU_REPLACE is only valid in a transaction */ if (qef_cb->qef_stat == QEF_NOTRAN) { qef_error(E_QE0004_NO_TRANSACTION, 0L, E_DB_ERROR, &err, &qeu_cb->error, 0); return (E_DB_ERROR); } dmr_cb.type = DMR_RECORD_CB; dmr_cb.length = sizeof(DMR_CB); dmr_cb.dmr_access_id = qeu_cb->qeu_acc_id; dmr_cb.dmr_q_fcn = NULL; /* if replacing by key, position the cursor */ if (qeu_cb->qeu_klen || position_all) { /* allocate memory for a tuple only if planning to call qeu_get() */ STRUCT_ASSIGN_MACRO(Qef_s_cb->qef_d_ulmcb, ulm); /* Open stream and allocate tuple memory in one action */ ulm.ulm_flags = ULM_PRIVATE_STREAM | ULM_OPEN_AND_PALLOC; ulm.ulm_psize = ulm.ulm_blocksize = qeu_cb->qeu_tup_length; if ((status = qec_mopen(&ulm)) != E_DB_OK) { qef_error(E_QE001E_NO_MEM, 0L, E_DB_ERROR, &err, &qeu_cb->error, 0); return (status); } mem_opened=TRUE; /* set the keys */ if(position_all) { dmr_cb.dmr_position_type = DMR_ALL; } else { dmr_cb.dmr_position_type = DMR_QUAL; dmr_cb.dmr_attr_desc.ptr_address = (PTR) qeu_cb->qeu_key; dmr_cb.dmr_attr_desc.ptr_in_count = qeu_cb->qeu_klen; dmr_cb.dmr_attr_desc.ptr_size = sizeof (DMR_ATTR_ENTRY); dmr_cb.dmr_s_estimated_records = -1; } /* row qualifier */ dmr_cb.dmr_q_fcn = (DB_STATUS (*)(void *,void *)) qeu_cb->qeu_qual; dmr_cb.dmr_q_arg = (PTR) qeu_cb->qeu_qarg; if (qeu_cb->qeu_qual != NULL) { dmr_cb.dmr_q_rowaddr = &qeu_cb->qeu_qarg->qeu_rowaddr; dmr_cb.dmr_q_retval = &qeu_cb->qeu_qarg->qeu_retval; } dmr_cb.dmr_flags_mask = 0; status = dmf_call(DMR_POSITION, &dmr_cb); if (status != E_DB_OK) { ulm_closestream(&ulm); if (dmr_cb.error.err_code == E_DM0055_NONEXT) return (E_DB_OK); qef_error(dmr_cb.error.err_code, 0L, status, &err, &qeu_cb->error, 0); return (status); } /* the tuple length will not change. Tell DMF about it */ dmr_cb.dmr_data.data_in_size = qeu_cb->qeu_tup_length; dmr_cb.dmr_data.data_address = ulm.ulm_pptr; } else { /* ** make dmr_data point at the new value for the tuple */ dmr_cb.dmr_data.data_address = qeu_cb->qeu_input->dt_data; dmr_cb.dmr_data.data_in_size = qeu_cb->qeu_input->dt_size; /* ** if (qeu_flag & QEU_BY_TID) ** indicate to dmr_replace() that we are replacing by tid ** else ** indicate to dmr_replace to replace the current tuple */ if (qeu_cb->qeu_flag & QEU_BY_TID) { dmr_cb.dmr_flags_mask = DMR_BY_TID; dmr_cb.dmr_tid = qeu_cb->qeu_tid; } else { dmr_cb.dmr_flags_mask = DMR_CURRENT_POS; } } for (;;) { if (qeu_cb->qeu_klen || position_all) { i4 ret_val; /* get the tuple */ dmr_cb.dmr_flags_mask = DMR_NEXT; status = dmf_call(DMR_GET, &dmr_cb); if (status != E_DB_OK) { if (dmr_cb.error.err_code == E_DM0055_NONEXT) { status = E_DB_OK; } else { err = dmr_cb.error.err_code; } break; } /* ** let caller's function determine whether and how the tuple must be ** changed; QEU_F_RETURN indicates that we must proceed; QEU_F_NEXT ** says "skip this tuple" */ ret_val = (*repl_func) (dmr_cb.dmr_data.data_address, qeu_cb->qeu_f_qarg); if (ret_val != QEU_F_RETURN) { continue; } /* will replace the current tuple */ dmr_cb.dmr_flags_mask = DMR_CURRENT_POS; } dmr_cb.dmr_attset = NULL; status = dmf_call(DMR_REPLACE, &dmr_cb); if (status != E_DB_OK) { err = dmr_cb.error.err_code; break; } else { qeu_cb->qeu_count++; } if (qeu_cb->qeu_klen == 0 && !position_all) { /* we were replacing a tuple by tid and are done */ break; } } if (status != E_DB_OK) { qef_error(err, 0L, status, &err, &qeu_cb->error, 0); } if (mem_opened) { /* don't try to close a stream unless it was opened */ ulm_closestream(&ulm); } return (status); }
/*{ ** Name: psq_bgn_session - Begin a parser session. ** ** INTERNAL PSF call format: status = psq_bgn_session(&psq_cb, &sess_cb); ** ** EXTERNAL call format: status = psq_call(PSQ_BGN_SESSION, &psq_cb, &sess_cb); ** ** Description: ** The psq_bgn_session function begins a parser session. It should be ** called each time a new user connects to a server. There may be ** many parser sessions per database server. There should be one parser ** session for each invocation of the database system that is connected ** to the server. When starting a parser session, one has to tell it ** what query language to use, and other session parameters. ** ** Inputs: ** psq_cb ** .psq_qlang The query language to use. ** .psq_decimal ** .psf_decspec TRUE indicates that the decimal marker ** has been specified. FALSE means use the ** default (a "."). ** .psf_decimal The character to use as a decimal marker ** (if specified). ** .psq_distrib Indicator for whether distributed ** statements and constructs should be ** accepted. ** .psq_sessid Session id ** .psq_server address of server control block ** .psq_adf_cb Pointer to session's ADF_CB ** .psq_dbid Database id for this session. ** .psq_user User name of ** .psq_dba User name of dba ** .psq_group Group id of session ** .psq_aplid Application id of session ** .psq_flag bitmask containing the following flags: ** .psq_catupd TRUE means catalogs updateable ** .psq_warnings Set to TRUE if user wishes to see ** warnings on unsupported commands ** .psq_idxstruct Structure for creating new indexes ** (e.g. DB_ISAM_STORE) ** .psq_udbid Unique database id for this session. ** .psq_ustat User status flags from SCS_ICS ** .psq_dbxlate Case translation semantics for the db ** sess_cb Pointer to session control block ** (Can be NULL) ** ** Outputs: ** psq_cb ** .psq_error Error information ** .err_code What error occurred ** E_PS0000_OK Success ** E_PS0001_INTERNAL_ERROR Internal PSF problem ** E_PS0201_BAD_QLANG Bad query language specifier ** E_PS0203_NO_DECIMAL No decimal marker specified ** E_PS0204_BAD_DISTRIB Bad distributed ** specification ** E_PS0205_SRV_NOT_INIT Server not initialized ** E_PS0206_TOO_MANY_SESS Too many sessions at one ** time ** 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_SEVERE Session is to be aborted ** E_DB_FATAL Function failed; catastrophic error ** Exceptions: ** none ** ** Side Effects: ** Causes memory to be allocated. ** Increments the session count in the server control block. ** ** History: ** 01-oct-85 (jeff) ** written ** 28-jul-86 (jeff) ** Added initialization of pss_catupd and pss_idxstruct ** 26-aug-86 (seputis) ** Removed definition of yaccstream ** 13-apr-87 (puree) ** Initialize prototype list for dynamic SQL. ** 24-apr-87 (stec) ** init pss_project. ** 11-may-87 (stec) ** store psq_udbid to pss_dbid. ** 04-sep-87 (stec) ** Added critical region code where needed. ** 02-oct-87 (stec) ** Added pss_journaling initialization. ** 13-jun-88 (stec) ** Added initialization of pss_ruset for DB procs. ** 08-mar-89 (andre) ** Copy dba_drop_all from PSQ_CB to PSS_SESBLK. ** 15-mar-89 (ralph) ** GRANT Enhancements, Phase 1: ** Copy psq_aplid to pss_aplid; ** Copy psq_group to pss_group. ** 16-mar-89 (neil) ** Initialized rule field. ** 27-jul-89 (jrb) ** Copy numeric literals flag into session cb. ** 27-oct-89 (ralph) ** Copy user status flags to session control block. ** 11-oct-89 (ralph) ** Initialize pss_rgset and pss_raset. ** 28-dec-89 (andre) ** Copy fips_mode from PSQ_CB to PSS_SESBLK. ** 13-feb-90 (andre) ** set scf_stype to SCU_EXCLUSIVE before calling scu_swait. ** 12-sep-90 (sandyh) ** Added support for session memory value calculated from psf ** memory startup parameter. ** 15-nov-90 (andre) ** check the return status after calling SCF to acquire or to release a ** semaphore. ** If an error occurred when trying to acquire the semaphore, return ** E_DB_SEVERE to abort the session. ** If an error occurred when trying to release the semaphore, return ** E_DB_FATAL to bring down the server. ** 17-may-91 (andre) ** store DBA name into sess_cb->pss_dbaname and NULL-terminate. ** 08-nov-91 (rblumer) ** merged from 6.4: 25-jul-91 (andre) ** if (psq_cb->psq_flag & PSQ_STRIP_NL_IN_STRCONST), set bit ** PSS_STRIP_NL_IN_STRCONST in sess_cb->pss_ses_flag. this will ** indicate that we are connected to an older FE, so the scanners ** will continue to strip NLs inside quoted strings; ** this is required to fix bug 38098 ** 14-jan-92 (barbara) ** Included ddb.h for Star. Updated to check for distributed ** specification. ** 26-feb-92 (andre) ** if PSQ_REPAIR_SYSCAT is set in psq_cb->psq_flag, set ** PSS_REPAIR_SYSCAT in sess_cb->pss_ses_flags ** 30-mar-1992 (bryanp) ** Fill in pss_sess_owner with a session-unique owner name for use ** by temporary tables which are owned by this session. ** 02-jun-92 (andre) ** initialize pss_dependencies_stream to NULL to avloid use of illegal ** address throughout the parser. ** 24-nov-92 (ralph) ** CREATE SCHEMA: ** Initialize pss_prvgoval ** 22-dec-92 (rblumer) ** initialize pointer for statement-level rule list. ** 14-jan-93 (andre) ** remember whether we are running UPGRADEDB - this will enable us to ** decide whether IIDEVICES can be dropped - which is needed by ** UPGRADEDB ** 15-mar-93 (ralph) ** DELIM_IDENT: initialize pss_dbxlate to zero ** 08-apr-93 (andre) ** names of rule list headers in sess_cb have changed (and their ** number has doubled) ** 26-mar-93 (ralph) ** DELIM_IDENT: Must initialize pss_dbxlate from psq_cb.psq_dbxlate ** and pss_cat_owner from psq_cat_owner. ** 10-aug-93 (andre) ** fixed cause of a compiler warning ** 08-sep-93 (swm) ** Changed sizeof(DB_SESSID) to sizeof(CS_SID) to reflect recent CL ** interface revision. ** 20-sep-93 (rogerk) ** Changed default table create semantics to be WITH JOURNALING. ** Initialized the pss_ses_flag setting to include PSS_JOURNALING ** which mimics the user requesting "set journaling" to indicate that ** tables created should be journaled. ** 08-oct-93 (rblumer) ** increased values allowed in pss_trace vector, using PSS_TVALS. ** 18-oct-93 (rogerk) ** Added support for journal default override. Check psf server ** control block flag for PSF_NO_JNL_DEFAULT override before setting ** the session parse flag to assume journaling on table creates. ** 15-nov-93 (andre) ** add code to initialize a newly added sess_cb->pss_flattening_flags ** 01-nov-93 (anitap) ** if PSQ_INGRES_PRIV is set in psq_cb->psq_flag, set ** PSS_INGRES_PRIV in sess_cb->pss_ses_flags. ** 17-dec-93 (rblumer) ** "FIPS mode" no longer exists. It was replaced some time ago by ** several feature-specific flags (e.g. flatten_nosingleton and ** direct_cursor_mode). So I removed all FIPS_MODE flags. ** 02-jan-94 (andre) ** if starting a local session, call DMF to determine whether the ** database to which we are connected is being journaled and record ** that information by setting (or not setting) PSS_JOURNALED_DB bit ** in pss_ses_flags ** 7-jan-94 (swm) ** Bug #58635 ** Added PTR cast for pss_owner which has changed type to PTR. ** 17-mar-94 (robf) ** Add support for PSQ_SELECT_ALL flag ** 13-Feb-1995 (canor01) ** initialize the pss_audit field in the session control block ** 09-Oct-1998 (jenjo02) ** Removed SCF semaphore functions, inlining the CS calls instead. ** 23-mar-1999 (thaju02) ** Modified '$Sess' to use #define DB_SESS_TEMP_OWNER. (B94067) ** 01-Dec-2000 (hanal04) Bug 100680 INGSRV 1123 ** If PSQ_RULE_UPD_PREFETCH is set turn on PSS_RULE_UPD_PREFETCH ** in the session control block to signify that we should use ** the prefetch stategy required to ensure consitent behaviour in ** updating rules fired by updates. ** 10-Jan-2001 (jenjo02) ** Remove callback to SCF to get session id and ADF_CB; ** *ADF_CB now supplied by scsinit in PSQ_CB. ** 30-Jan-2004 (schka24) ** Get rid of a type-cast warning on adf cb. ** 3-Feb-2005 (schka24) ** Num-literals renamed to parser-compat, fix here. ** 15-june-06 (dougi) ** Add support for "before" triggers. ** 30-aug-06 (thaju02) ** If PSQ_RULE_DEL_PREFETCH is set turn on PSS_RULE_DEL_PREFETCH ** in the session control block, for prefetch strategy to ** be applied for deletes. (B116355) ** 26-Oct-2009 (kiria01) SIR 121883 ** Scalar sub-query support: Added copy of ** psq_flag.PSQ_NOCHK_SINGLETON_CARD to session flag ** for defaulting SET CARDINALITY_CHECK ** November 2009 (stephenb) ** Batch execution; initilization of new fields. ** 29-apr-2010 (stephenb) ** Init batch_copy_optim. ** 04-may-2010 (miket) SIR 122403 ** Init new sess_cb->pss_stmt_flags2. ** 19-May-2010 (kiria01) b123766 ** Get cardinality check default from server block not psq_cb ** 21-Jul-2010 (kschendel) SIR 124104 ** Initialize default compression from facility cb. ** 14-Oct-2010 (kschendel) SIR 124544 ** Initialize default result structure from facility cb. ** 19-Nov-2010 (kiria01) SIR 124690 ** Add support for setting installation wide collation defaults. */ DB_STATUS psq_bgn_session( register PSQ_CB *psq_cb, register PSS_SESBLK *sess_cb) { i4 err_code; i4 i; DB_STATUS status = E_DB_OK; STATUS sem_status; i4 sem_errno; bool leave_loop = TRUE; ULM_RCB ulm_rcb; /* ** No error to begin with. */ psq_cb->psq_error.err_code = E_PS0000_OK; /* ** Do as much validity checking as possible before allocating any memory. ** That way, there won't be any cleaning up to do for the majority of ** errors. */ /* ** Check for server initialized. This code could be placed within ** critical region, but this is not necessary, since this is a flag ** test. */ if (!Psf_srvblk->psf_srvinit) { (VOID) psf_error(E_PS0205_SRV_NOT_INIT, 0L, PSF_CALLERR, &err_code, &psq_cb->psq_error, 0); return (E_DB_ERROR); } /* ** Check for valid language spec. */ if (psq_cb->psq_qlang != DB_QUEL && psq_cb->psq_qlang != DB_SQL) { (VOID) psf_error(E_PS0201_BAD_QLANG, 0L, PSF_CALLERR, &err_code, &psq_cb->psq_error, 0); return (E_DB_ERROR); } /* ** Check whether language is allowed in this server. This will be useful ** when we have configurable servers, where some query languages can be ** used and some can't. This code could be placed within a critical region ** but it is not necessary, since this is a flag test only. */ if ((psq_cb->psq_qlang & Psf_srvblk->psf_lang_allowed) == 0) { (VOID) psf_error(E_PS0202_QLANG_NOT_ALLOWED, 0L, PSF_CALLERR, &err_code, &psq_cb->psq_error, 0); return (E_DB_ERROR); } /* ** Make sure that the decimal character is actually specified. */ if (!psq_cb->psq_decimal.db_decspec) { (VOID) psf_error(E_PS0203_NO_DECIMAL, 0L, PSF_CALLERR, &err_code, &psq_cb->psq_error, 0); return (E_DB_ERROR); } /* Check distributed specification ** ** a=local_server, b=distrib_server, c=distrib_session ** ** a,b ** ** 00 01 11 10 ** ----------------- ** c | | | | | ** 0 | 1 | 1 | 0 | 0 | ** | | | | | ** ----------------- ==> ERROR ** | | | | | ** 1 | 1 | 0 | 0 | 1 | ** | | | | | ** ----------------- */ if ( !(psq_cb->psq_distrib & (DB_1_LOCAL_SVR | DB_3_DDB_SESS)) || ((~psq_cb->psq_distrib & DB_2_DISTRIB_SVR) && (psq_cb->psq_distrib & DB_3_DDB_SESS)) ) { psf_error(E_PS0204_BAD_DISTRIB, 0L, PSF_CALLERR, &err_code, &psq_cb->psq_error,0); return (E_DB_ERROR); } /* ** Check for too many sessions in server at one time. ** This code must be executed as a critical region. */ do /* something to break out of */ { /* get the semaphore */ if (sem_status = CSp_semaphore(1, &Psf_srvblk->psf_sem)) /* exclusive */ { status = E_DB_SEVERE; /* abort the session */ sem_errno = E_PS020A_BGNSES_GETSEM_FAILURE; break; } if (Psf_srvblk->psf_nmsess >= Psf_srvblk->psf_mxsess) { (VOID) psf_error(E_PS0208_TOO_MANY_SESS, 0L, PSF_CALLERR, &err_code, &psq_cb->psq_error, 0); status = E_DB_ERROR; break; } /* Increment the session count */ Psf_srvblk->psf_nmsess++; sess_cb->pss_psessid = ++Psf_srvblk->psf_sess_num; /* leave_loop has already been set to TRUE */ } while (!leave_loop); /* if semaphore has been successfully acquired, try to release it */ if (sem_status == OK) { if (sem_status = CSv_semaphore(&Psf_srvblk->psf_sem)) { status = E_DB_FATAL; /* bring down the server */ sem_errno = E_PS020B_BGNSES_RELSEM_FAILURE; } } /* ** if an error was encountered while trying to get or to release a ** semaphore, report it here */ if (sem_status != OK) { (VOID) psf_error(sem_errno, sem_status, PSF_INTERR, &err_code, &psq_cb->psq_error, 0); } if (DB_FAILURE_MACRO(status)) { return(status); } /* ** Initialize the case translation semantics stuff */ sess_cb->pss_dbxlate = psq_cb->psq_dbxlate; sess_cb->pss_cat_owner = psq_cb->psq_cat_owner; /* ** Copy the user name and dba name to the session control block. */ STRUCT_ASSIGN_MACRO(psq_cb->psq_user.db_tab_own, sess_cb->pss_user); STRUCT_ASSIGN_MACRO(psq_cb->psq_dba, sess_cb->pss_dba); STRUCT_ASSIGN_MACRO(psq_cb->psq_group, sess_cb->pss_group); STRUCT_ASSIGN_MACRO(psq_cb->psq_aplid, sess_cb->pss_aplid); /* copy DBA name into sess_cb->pss_dbaname and NULL-terminate */ { u_i2 dba_name_len; dba_name_len = (u_i2) psf_trmwhite((u_i4) sizeof(sess_cb->pss_dba), (char *) &sess_cb->pss_dba); MEcopy((PTR) &sess_cb->pss_dba, dba_name_len, (PTR) sess_cb->pss_dbaname); sess_cb->pss_dbaname[dba_name_len] = EOS; } /* ** Build a DB_OWN_NAME which contains a session-unique owner name. This ** owner name will be used for temporary tables which are owned by this ** session. */ { char temp_sess_id[10]; STmove(DB_SESS_TEMP_OWNER, ' ', sizeof(sess_cb->pss_sess_owner), (char *)&sess_cb->pss_sess_owner); /* ** We can't convert directly into the sess_owner field because CVlx ** null-terminates the result, and we don't want the trailing null */ CVlx(sess_cb->pss_psessid, temp_sess_id); MEcopy(temp_sess_id, 8, &sess_cb->pss_sess_owner.db_own_name[5]); } /* ** Start with per-user quota of memory. Note that user may have overridden ** the default value at server startup in which case we will use calculated ** amount (pool/sessions); otherwise, default amount will be used. */ sess_cb->pss_memleft = (Psf_srvblk->psf_sess_mem) ? Psf_srvblk->psf_sess_mem : PSF_SESMEM; /* ** Initialize the user range table. */ if (pst_rginit(&sess_cb->pss_usrrange) != E_DB_OK) { return (E_DB_FATAL); } /* ** Initialize the auxiliary range table. */ if (pst_rginit(&sess_cb->pss_auxrng) != E_DB_OK) { return (E_DB_FATAL); } /* ** Open a memory stream for the symbol table. The symbol table is ** composed of a list of blocks. ** Allocate the symbol table at the same time. */ ulm_rcb.ulm_facility = DB_PSF_ID; ulm_rcb.ulm_poolid = Psf_srvblk->psf_poolid; ulm_rcb.ulm_blocksize = sizeof(PSS_SYMBLK); ulm_rcb.ulm_memleft = &sess_cb->pss_memleft; /* Set pointer to stream handle for ULM */ ulm_rcb.ulm_streamid_p = &sess_cb->pss_symstr; /* Open a private, thread-safe stream */ ulm_rcb.ulm_flags = ULM_PRIVATE_STREAM | ULM_OPEN_AND_PALLOC; ulm_rcb.ulm_psize = sizeof(PSS_SYMBLK); if (ulm_openstream(&ulm_rcb) != E_DB_OK) { if (ulm_rcb.ulm_error.err_code == E_UL0005_NOMEM) { (VOID) psf_error(E_PS0F02_MEMORY_FULL, 0L, PSF_CALLERR, &err_code, &psq_cb->psq_error, 0); } else { (VOID) psf_error(E_PS0A02_BADALLOC, ulm_rcb.ulm_error.err_code, PSF_INTERR, &err_code, &psq_cb->psq_error, 0); } return((ulm_rcb.ulm_error.err_code == E_UL0004_CORRUPT) ? E_DB_FATAL : E_DB_ERROR); } sess_cb->pss_symtab = (PSS_SYMBLK*) ulm_rcb.ulm_pptr; sess_cb->pss_symtab->pss_sbnext = (PSS_SYMBLK *) NULL; /* ** Allocate the YACC_CB. */ if ((status = psl_yalloc(sess_cb->pss_symstr, &sess_cb->pss_memleft, (PTR *) &sess_cb->pss_yacc, &psq_cb->psq_error)) != E_DB_OK) { /* ** If the allocation failed, remember to close the streams, so the ** memory associated with it will be freed. */ (VOID) ulm_closestream(&ulm_rcb); return (status); } /* ** Fill in the control block header. */ sess_cb->pss_next = (PSS_SESBLK *) NULL; sess_cb->pss_prev = (PSS_SESBLK *) NULL; sess_cb->pss_length = sizeof(PSS_SESBLK); sess_cb->pss_type = PSS_SBID; sess_cb->pss_owner = (PTR)DB_PSF_ID; sess_cb->pss_ascii_id = PSSSES_ID; /* ** Initialize the session control block. */ /* Save the session id */ sess_cb->pss_sessid = psq_cb->psq_sessid; /* Set pointer to session's ADF_CB */ sess_cb->pss_adfcb = (ADF_CB *) psq_cb->psq_adfcb; /* No cursors yet */ sess_cb->pss_numcursors = 0; /* Language has already been validated */ sess_cb->pss_lang = psq_cb->psq_qlang; /* Decimal spec has already been validated */ sess_cb->pss_decimal = psq_cb->psq_decimal.db_decimal; /* Distributed spec has already been validated */ sess_cb->pss_distrib = psq_cb->psq_distrib; /* Save the database id */ sess_cb->pss_dbid = psq_cb->psq_dbid; /* Save the unique database id */ sess_cb->pss_udbid = psq_cb->psq_udbid; /* Initialize QSF_RCB for use by psfmem.c functions */ sess_cb->pss_qsf_rcb.qsf_type = QSFRB_CB; sess_cb->pss_qsf_rcb.qsf_ascii_id = QSFRB_ASCII_ID; sess_cb->pss_qsf_rcb.qsf_length = sizeof(sess_cb->pss_qsf_rcb); sess_cb->pss_qsf_rcb.qsf_owner = (PTR)DB_PSF_ID; sess_cb->pss_qsf_rcb.qsf_sid = sess_cb->pss_sessid; /* ** so session reset all bit flags */ sess_cb->pss_stmt_flags = sess_cb->pss_stmt_flags2 = sess_cb->pss_dbp_flags = sess_cb->pss_ses_flag = 0L; sess_cb->pss_flattening_flags = 0; /* ** Default table create semantics are to assume journaling unless ** the PSF_NO_JNL_DEFAULT override is set. */ if ((Psf_srvblk->psf_flags & PSF_NO_JNL_DEFAULT) == 0) sess_cb->pss_ses_flag |= PSS_JOURNALING; /* catalog update flag */ if (psq_cb->psq_flag & PSQ_CATUPD) sess_cb->pss_ses_flag |= PSS_CATUPD; /* warnings on unsupported commands */ if (psq_cb->psq_flag & PSQ_WARNINGS) sess_cb->pss_ses_flag |= PSS_WARNINGS; /* INDICATE if the DBA may DROP everyone's tables */ if (psq_cb->psq_flag & PSQ_DBA_DROP_ALL) sess_cb->pss_ses_flag |= PSS_DBA_DROP_ALL; /* INDICATE if the session may SELECT everyone's tables */ if (psq_cb->psq_flag & PSQ_SELECT_ALL) sess_cb->pss_ses_flag |= PSS_SELECT_ALL; /* ** indicate that the session is allowed to INSERT/DELETE/UPDATE an index ** which is a catalog (but not an extended catalog */ if (psq_cb->psq_flag & PSQ_REPAIR_SYSCAT) sess_cb->pss_ses_flag |= PSS_REPAIR_SYSCAT; /* ** indicate that the session allows $ingres to drop/add constraint on ** tables owned by other users */ if (psq_cb->psq_flag & PSQ_INGRES_PRIV) sess_cb->pss_ses_flag |= PSS_INGRES_PRIV; if (psq_cb->psq_flag & PSQ_ROW_SEC_KEY) sess_cb->pss_ses_flag |= PSS_ROW_SEC_KEY; /* See if passwords, roles allowed */ if (psq_cb->psq_flag & PSQ_PASSWORD_NONE) sess_cb->pss_ses_flag |= PSS_PASSWORD_NONE; if (psq_cb->psq_flag & PSQ_ROLE_NONE) sess_cb->pss_ses_flag |= PSS_ROLE_NONE; if (psq_cb->psq_flag & PSQ_ROLE_NEED_PW) sess_cb->pss_ses_flag |= PSS_ROLE_NEED_PW; /* remember whether we are running UPGRADEDB */ if (psq_cb->psq_flag & PSQ_RUNNING_UPGRADEDB) sess_cb->pss_ses_flag |= PSS_RUNNING_UPGRADEDB; /* Pick up serverwide default for card check */ if (Psf_srvblk->psf_flags & PSF_NOCHK_SINGLETON_CARD) sess_cb->pss_ses_flag |= PSS_NOCHK_SINGLETON_CARD; /* Initialize pss_project. */ sess_cb->pss_ses_flag |= PSS_PROJECT; /* pss_project = TRUE */ /* init last statement */ sess_cb->pss_last_sname[0] = EOS; /* batch optimization switch starts undefined */ sess_cb->batch_copy_optim = PSS_BATCH_OPTIM_UNDEF; /* ** if starting a local session, determine whether the database is being ** journaled */ if (~psq_cb->psq_distrib & DB_3_DDB_SESS) { DMC_CB dmc_cb, *dmc = &dmc_cb; DMC_CHAR_ENTRY dmc_char; MEfill(sizeof(dmc_cb), (u_char) 0, (PTR) dmc); dmc->type = DMC_CONTROL_CB; dmc->length = sizeof(*dmc); dmc->dmc_op_type = DMC_DATABASE_OP; dmc->dmc_session_id = (PTR) sess_cb->pss_sessid; dmc->dmc_flags_mask = DMC_JOURNAL; dmc->dmc_char_array.data_address= (PTR) &dmc_char; dmc->dmc_char_array.data_out_size = sizeof(dmc_char); dmc->dmc_db_id = (char *) sess_cb->pss_dbid; status = dmf_call(DMC_SHOW, (PTR) dmc); if (DB_FAILURE_MACRO(status)) { (VOID) psf_error(E_PS020E_CANT_GET_DB_JOUR_STATUS, dmc->error.err_code, PSF_INTERR, &err_code, &psq_cb->psq_error, 0); return(status); } if (dmc_char.char_value == DMC_C_ON) { sess_cb->pss_ses_flag |= PSS_JOURNALED_DB; } } /* Save the storage structure for indexes */ sess_cb->pss_idxstruct = psq_cb->psq_idxstruct; /* Make session copy of parser compatability settings */ sess_cb->pss_parser_compat = psq_cb->psq_parser_compat; /* remember if NLs inside string constants need to be stripped */ if (psq_cb->psq_flag & PSQ_STRIP_NL_IN_STRCONST) sess_cb->pss_ses_flag |= PSS_STRIP_NL_IN_STRCONST; /* no rule tree yet */ sess_cb->pss_row_lvl_usr_rules = sess_cb->pss_row_lvl_sys_rules = sess_cb->pss_stmt_lvl_usr_rules = sess_cb->pss_stmt_lvl_sys_rules = sess_cb->pss_row_lvl_usr_before_rules = sess_cb->pss_row_lvl_sys_before_rules = sess_cb->pss_stmt_lvl_usr_before_rules = sess_cb->pss_stmt_lvl_sys_before_rules = (PST_STATEMENT *) NULL; if (psq_cb->psq_flag & PSQ_RULE_DEL_PREFETCH) sess_cb->pss_ses_flag |= PSS_RULE_DEL_PREFETCH; if(psq_cb->psq_flag2 & PSQ_RULE_UPD_PREFETCH) sess_cb->pss_ses_flag |= PSS_RULE_UPD_PREFETCH; /* copy user status flags to session control block */ sess_cb->pss_ustat = psq_cb->psq_ustat; /* ** Initialize lots of pointer to NULL because nothing is happening yet. */ sess_cb->pss_qbuf = sess_cb->pss_nxtchar = sess_cb->pss_prvtok = sess_cb->pss_bgnstmt = sess_cb->pss_endbuf = sess_cb->pss_prvgoval = (u_char *) NULL; /* initialize pss_audit */ sess_cb->pss_audit = NULL; for (i = 0; i < PSS_CURTABSIZE; i++) { sess_cb->pss_curstab.pss_curque[i] = (PSC_CURBLK *) NULL; } /* initialize prototype list for dynamic SQL */ sess_cb->pss_proto = (PST_PROTO *) NULL; /* ** pss_dependencies_stream, when not NULL, is expected to point at a valid ** stream descriptor. After closing the stream we always reset ** pss_dependencies_stream to NULL, but in some cases we may end up checking ** pss_dependencies_stream before ever opening (and closing it). As a ** result, you may end up using invalid address as a stream pointer. ** Initializing it here to NULL will ensure that it is non-NULL iff it ** points at a valid open stream descriptor. */ sess_cb->pss_dependencies_stream = (PSF_MSTREAM *) NULL; /* No trace flags set */ /* expect lint message */ ult_init_macro(&sess_cb->pss_trace, PSS_TBITS, PSS_TVALS, PSS_TVAO); /* Cursor id set to 0, no cursors open yet */ sess_cb->pss_crsid = 0; sess_cb->pss_create_compression = Psf_srvblk->psf_create_compression; /* SCF can pass a client requested result_structure, but if it ** doesn't, init from server default. */ if (psq_cb->psq_result_struct != 0) { sess_cb->pss_result_struct = psq_cb->psq_result_struct; sess_cb->pss_result_compression = psq_cb->psq_result_compression; } else { sess_cb->pss_result_struct = Psf_srvblk->psf_result_struct; sess_cb->pss_result_compression = Psf_srvblk->psf_result_compression; } if (psq_cb->psq_def_coll > DB_NOCOLLATION) sess_cb->pss_def_coll = psq_cb->psq_def_coll; else sess_cb->pss_def_coll = Psf_srvblk->psf_def_coll; if (psq_cb->psq_def_unicode_coll > DB_NOCOLLATION) sess_cb->pss_def_unicode_coll = psq_cb->psq_def_unicode_coll; else sess_cb->pss_def_unicode_coll = Psf_srvblk->psf_def_unicode_coll; return (E_DB_OK); }
/*{ ** Name: gwi_remove - remove a gateway index ** ** Description: ** This function removes extended gateway index catalog information. A ** DMF external interface is used to update, namely delete, the extended ** gateway index catalog, iigwX_index. This request must be made before ** gateway index removal can be considered complete. ** ** The GWF tcb cache for the base table is discarded since it is no longer ** current. ** ** Inputs: ** gw_rcb-> gateway request control block ** session_id an established session id ** dmu-> ** dmu_db_id database id ** dmu_tran_id transaction id ** dmu_tbl_id base table id ** dmu_idx_id INGRES index id ** gw_id gateway id, derived from DBMS type ** ** Output: ** gw_rcb-> ** error.err_code One of the following error numbers. ** E_GW0600_NO_MEM ** E_GW0400_BAD_GWID ** E_GW0006_XIDX_OPEN_FAILED ** Returns: ** E_DB_OK Function completed normally. ** E_DB_ERROR Function completed abnormally with ** error.err_code. ** History: ** 28-Apr-1989 (alexh) ** Created. ** 2-apr-90 (bryanp) ** If this gateway has no extended system catalogs, nothing to do. ** 09-apr-90 (linda) ** Added error handling, single return point. ** 18-apr-90 (bryanp) ** Return E_GW0600_NO_MEM when out of ULM memory. ** 28-mar-91 (linda) ** Fixed 2 problems: (a) error on tuple delete from dmf was logged ** but did not cause this routine to return a bad status; (b) call to ** DMR_DELETE required DMR_CURRENT_POS in flags mask. ** 7-oct-92 (daveb) ** prototyped. Cast arg to gwu_copen (db_id is PTR). */ DB_STATUS gwi_remove(GW_RCB *gw_rcb) { GW_SESSION *session = (GW_SESSION *)gw_rcb->gwr_session_id; DMT_CB dmt; DMR_CB dmr; ULM_RCB ulm_rcb; DM_DATA xidx_buff; i4 gw_id = gw_rcb->gwr_gw_id; i4 xidx_sz = Gwf_facility->gwf_gw_info[gw_id].gwf_xidx_sz; DMR_ATTR_ENTRY attkey[2]; DMR_ATTR_ENTRY *attkey_ptr[2]; DB_TAB_ID sav_idx_id; DB_ERROR err; DB_STATUS status; DB_STATUS sav_status; for (;;) { if ((gw_id <= 0) || (gw_id >= GW_GW_COUNT) || (Gwf_facility->gwf_gw_info[gw_id].gwf_gw_exist == 0)) { (VOID) gwf_error(E_GW0400_BAD_GWID, (i4)0, GWF_INTERR, 1, sizeof(gw_rcb->gwr_gw_id), &gw_rcb->gwr_gw_id); gw_rcb->gwr_error.err_code = E_GW0208_GWI_REGISTER_ERROR; status = E_DB_ERROR; break; } if (xidx_sz == 0) { status = E_DB_OK; break; } /* copy ulm_rcb */ STRUCT_ASSIGN_MACRO(session->gws_ulm_rcb, ulm_rcb); xidx_buff.data_in_size = xidx_sz; ulm_rcb.ulm_blocksize = xidx_buff.data_in_size; /* allocate a iigwX_index buffer from a temporary memory stream */ if ((status = ulm_openstream(&ulm_rcb)) != E_DB_OK) { (VOID) gwf_error(ulm_rcb.ulm_error.err_code, GWF_INTERR, 0); (VOID) gwf_error(E_GW0312_ULM_OPENSTREAM_ERROR, GWF_INTERR, 3, sizeof(*ulm_rcb.ulm_memleft), ulm_rcb.ulm_memleft, sizeof(ulm_rcb.ulm_sizepool), &ulm_rcb.ulm_sizepool, sizeof(ulm_rcb.ulm_blocksize), &ulm_rcb.ulm_blocksize); if (ulm_rcb.ulm_error.err_code == E_UL0005_NOMEM) gw_rcb->gwr_error.err_code = E_GW0600_NO_MEM; else gw_rcb->gwr_error.err_code = E_GW0209_GWI_REMOVE_ERROR; break; } ulm_rcb.ulm_psize = ulm_rcb.ulm_blocksize; if ((status = ulm_palloc(&ulm_rcb)) != E_DB_OK) { (VOID) gwf_error(ulm_rcb.ulm_error.err_code, GWF_INTERR, 0); (VOID) gwf_error(E_GW0314_ULM_PALLOC_ERROR, GWF_INTERR, 4, sizeof(*ulm_rcb.ulm_memleft), ulm_rcb.ulm_memleft, sizeof(ulm_rcb.ulm_sizepool), &ulm_rcb.ulm_sizepool, sizeof(ulm_rcb.ulm_blocksize), &ulm_rcb.ulm_blocksize, sizeof(ulm_rcb.ulm_psize), &ulm_rcb.ulm_psize); if (ulm_rcb.ulm_error.err_code == E_UL0005_NOMEM) gw_rcb->gwr_error.err_code = E_GW0600_NO_MEM; else gw_rcb->gwr_error.err_code = E_GW0209_GWI_REMOVE_ERROR; if ((status = ulm_closestream(&ulm_rcb)) != E_DB_OK) { (VOID) gwf_error(ulm_rcb.ulm_error.err_code, GWF_INTERR, 0); (VOID) gwf_error(E_GW0313_ULM_CLOSESTREAM_ERROR, GWF_INTERR, 1, sizeof(*ulm_rcb.ulm_memleft), ulm_rcb.ulm_memleft); } status = E_DB_ERROR; /* reset after closestream call */ break; } xidx_buff.data_address = ulm_rcb.ulm_pptr; /* initialize dmt_sequence */ dmt.dmt_sequence = gw_rcb->gwr_gw_sequence; /* set up position for iigwXX_index catalog*/ attkey[0].attr_number = 1; attkey[0].attr_operator = DMR_OP_EQ; attkey[0].attr_value = (char *)&gw_rcb->gwr_tab_id.db_tab_base; attkey[1].attr_number = 2; attkey[1].attr_operator = DMR_OP_EQ; attkey[1].attr_value = (char *)&gw_rcb->gwr_tab_id.db_tab_index; attkey_ptr[0] = &attkey[0]; attkey_ptr[1] = &attkey[1]; dmr.type = DMR_RECORD_CB; dmr.length = sizeof(DMR_CB); dmr.dmr_flags_mask = 0; dmr.dmr_position_type = DMR_QUAL; dmr.dmr_attr_desc.ptr_in_count = 2; dmr.dmr_attr_desc.ptr_size = sizeof(DMR_ATTR_ENTRY); dmr.dmr_attr_desc.ptr_address = (PTR)&attkey_ptr[0]; dmr.dmr_access_id = dmt.dmt_record_access_id; dmr.dmr_q_fcn = NULL; /* open the iigwX_index catalog */ if ((status = gwu_copen(&dmt, &dmr, session->gws_scf_session_id, (PTR)gw_rcb->gwr_database_id, gw_id, gw_rcb->gwr_xact_id, &gw_rcb->gwr_tab_id, &session->gws_gw_info[gw_id].gws_xidx_tab_name, DMT_A_WRITE, TRUE, &err)) != E_DB_OK) { switch (dmt.error.err_code) { case E_DM0042_DEADLOCK: gw_rcb->gwr_error.err_code = E_GW0327_DMF_DEADLOCK; break; default: (VOID) gwf_error(err.err_code, GWF_INTERR, 0); gw_rcb->gwr_error.err_code = E_GW0209_GWI_REMOVE_ERROR; break; } if ((status = ulm_closestream(&ulm_rcb)) != E_DB_OK) { (VOID) gwf_error(ulm_rcb.ulm_error.err_code, GWF_INTERR, 0); (VOID) gwf_error(E_GW0313_ULM_CLOSESTREAM_ERROR, GWF_INTERR, 1, sizeof(*ulm_rcb.ulm_memleft), ulm_rcb.ulm_memleft); gw_rcb->gwr_error.err_code = E_GW0209_GWI_REMOVE_ERROR; } break; } dmr.dmr_flags_mask = DMR_NEXT; STRUCT_ASSIGN_MACRO(xidx_buff, dmr.dmr_data); dmr.dmr_char_array.data_address = 0; /* ** Delete the index entry with index and base table id */ do { status = (*Dmf_cptr)(DMR_GET, &dmr); } while (status == E_DB_OK && MEcmp((PTR)dmr.dmr_data.data_address, (PTR)&gw_rcb->gwr_tab_id, sizeof(DB_TAB_ID)) ); if (status == E_DB_OK) { dmr.dmr_flags_mask |= DMR_CURRENT_POS; if ((status = (*Dmf_cptr)(DMR_DELETE, &dmr)) != E_DB_OK) { switch (dmt.error.err_code) { case E_DM0042_DEADLOCK: gw_rcb->gwr_error.err_code = E_GW0327_DMF_DEADLOCK; break; default: (VOID) gwf_error(dmr.error.err_code, GWF_INTERR, 0); (VOID) gwf_error(E_GW0322_DMR_DELETE_ERROR, GWF_INTERR, 2, sizeof(gw_rcb->gwr_tab_id.db_tab_base), &gw_rcb->gwr_tab_id.db_tab_base, sizeof(gw_rcb->gwr_tab_id.db_tab_index), &gw_rcb->gwr_tab_id.db_tab_index); gw_rcb->gwr_error.err_code = E_GW0209_GWI_REMOVE_ERROR; break; } if (dmt.error.err_code == E_DM0042_DEADLOCK) break; /* (Else no break; we still want to close index catalog.) */ } } else /* status != E_DB_OK */ { switch (dmt.error.err_code) { case E_DM0042_DEADLOCK: gw_rcb->gwr_error.err_code = E_GW0327_DMF_DEADLOCK; break; default: (VOID) gwf_error(dmr.error.err_code, GWF_INTERR, 0); (VOID) gwf_error(E_GW0321_DMR_GET_ERROR, GWF_INTERR, 2, sizeof(gw_rcb->gwr_tab_id.db_tab_base), &gw_rcb->gwr_tab_id.db_tab_base, sizeof(gw_rcb->gwr_tab_id.db_tab_index), &gw_rcb->gwr_tab_id.db_tab_index); gw_rcb->gwr_error.err_code = E_GW0209_GWI_REMOVE_ERROR; break; } if (dmt.error.err_code == E_DM0042_DEADLOCK) break; /* (Else no break; we still want to close index catalog.) */ } sav_status = status; /* in case of non-deadlock error above */ if ((status = (*Dmf_cptr)(DMT_CLOSE, &dmt)) != E_DB_OK) { switch (dmt.error.err_code) { case E_DM0042_DEADLOCK: gw_rcb->gwr_error.err_code = E_GW0327_DMF_DEADLOCK; break; default: (VOID) gwf_error(dmt.error.err_code, GWF_INTERR, 0); (VOID) gwf_error(E_GW0325_DMT_CLOSE_ERROR, GWF_INTERR, 2, sizeof(dmt.dmt_id.db_tab_base), &dmt.dmt_id.db_tab_base, sizeof(dmt.dmt_id.db_tab_index), &dmt.dmt_id.db_tab_index); gw_rcb->gwr_error.err_code = E_GW0209_GWI_REMOVE_ERROR; break; } } /* ** delete tcb from GWF cache since its index info cannot be current. */ /* ** First save index's tab_id, set base to 0 for call. */ _VOID_ MEcopy((PTR)&gw_rcb->gwr_tab_id, sizeof(DB_TAB_ID), (PTR)&sav_idx_id); gw_rcb->gwr_tab_id.db_tab_index = 0; if ((status = gwu_deltcb(gw_rcb, GWU_TCB_OPTIONAL, &err)) != E_DB_OK) { (VOID) gwf_error(err.err_code, GWF_INTERR, 0); gw_rcb->gwr_error.err_code = E_GW0209_GWI_REMOVE_ERROR; _VOID_ MEcopy((PTR)&sav_idx_id, sizeof(DB_TAB_ID), (PTR)&gw_rcb->gwr_tab_id); break; } _VOID_ MEcopy((PTR)&sav_idx_id, sizeof(DB_TAB_ID), (PTR)&gw_rcb->gwr_tab_id); if ((status = ulm_closestream(&ulm_rcb)) != E_DB_OK) { (VOID) gwf_error(ulm_rcb.ulm_error.err_code, GWF_INTERR, 0); (VOID) gwf_error(E_GW0313_ULM_CLOSESTREAM_ERROR, GWF_INTERR, 1, sizeof(ulm_rcb.ulm_error.err_code), &ulm_rcb.ulm_error.err_code); gw_rcb->gwr_error.err_code = E_GW0209_GWI_REMOVE_ERROR; break; } /* ** If we get here, things went okay after the tuple delete. Recheck ** status from that call. */ if (sav_status == E_DB_OK) { gw_rcb->gwr_error.err_code = E_DB_OK; } else { status = sav_status; gw_rcb->gwr_error.err_code = E_GW0209_GWI_REMOVE_ERROR; } break; } return(status); }
/* ** Name: gwi_register - register a gateway index ** ** Description: ** This function registers extended gateway index catalog information. A ** DMF external interface is used to update, namely put, the extended ** gateway catalog, iigwX_index. This request must be made before ** gateway index registration can be considered complete. ** ** The GWF tcb cache for the base table is discarded since it is no longer ** current. ** ** Inputs: ** gw_rcb-> gateway request control block ** session_id an established session id ** dmu-> ** dmu_db_id database id ** dmu_tran_id transaction id ** dmu_tbl_id base table id ** dmu_idx_id INGRES index id ** gw_id gateway id, derived from DBMS type ** in_vdata2 source of the gateway index. ** ** Output: ** gw_rcb-> ** error.err_code One of the following error numbers. ** E_GW0600_NO_MEM ** E_GW0400_BAD_GWID ** E_GW0208_GWI_REGISTER_ERROR ** E_GW0006_XIDX_OPEN_FAILED ** Returns: ** E_DB_OK Function completed normally. ** E_DB_ERROR Function completed abnormally with ** error.err_code. ** History: ** 28-Apr-1989 (alexh) ** Created. ** 2-apr-90 (bryanp) ** If gateway has no extended system catalog, nothing to do. ** 09-apr-90 (linda) ** Add error handling and single return point. ** 18-apr-90 (bryanp) ** Return E_GW0600_NO_MEM when out of ULM memory. ** 1-jul-91 (rickh) ** If the gateway exit returns an error, don't clobber the status ** word when we close the stream! Also, if the exit has already ** reported the problem, spare us the uninformative yet alarming ** error-babble of higher facilities. ** 7-oct-92 (robf) ** Still create Xrelation & Xattribute entries even if no Xindex ** table - a gateway may need rel/attr entires but not the ** index one ** 7-oct-92 (daveb) ** Hand the exit the session pointer, in case it wants to add ** an exit-private SCB. Prototyped. Removed dead vars xrel_sz ** and sav_idx_id. Cast db_id arg to gwu_copen; it's a PTR. ** 17-nov-92 (robf) ** Changed calls to gwf_display() to use array rather than ** arg list. */ DB_STATUS gwi_register(GW_RCB *gw_rcb) { GWX_RCB gwx; ULM_RCB ulm_rcb; GW_SESSION *session = (GW_SESSION *)gw_rcb->gwr_session_id; DMT_CB dmt; DMR_CB dmr; i4 gw_id = gw_rcb->gwr_gw_id; i4 xidx_sz = Gwf_facility->gwf_gw_info[gw_id].gwf_xidx_sz; DB_STATUS status; DB_STATUS ulm_status; DB_ERROR err; char trbuf[GWF_MAX_MSGLEN + 1]; /* last char for `\n' */ if(GWF_MAIN_MACRO(12)) { gwf_display(gwf_scctalk, 0, trbuf, sizeof(trbuf) - 1, "GWI_REGISTER: REGISTER INDEX entry\n"); } for (;;) { if ((gw_id <= 0) || (gw_id >= GW_GW_COUNT) || (Gwf_facility->gwf_gw_info[gw_id].gwf_gw_exist == 0)) { (VOID) gwf_error(E_GW0400_BAD_GWID, (i4)0, GWF_INTERR, 1, sizeof(gw_id), &gw_id); gw_rcb->gwr_error.err_code = E_GW0208_GWI_REGISTER_ERROR; status = E_DB_ERROR; break; } /* ** Allocate a memory stream for the life of this operation. Used as ** storage for temporary structures. Note that it is allocated from ** the session's GWF memory stream. */ STRUCT_ASSIGN_MACRO(session->gws_ulm_rcb, ulm_rcb); ulm_rcb.ulm_blocksize = xidx_sz; if ((status = ulm_openstream(&ulm_rcb)) != E_DB_OK) { (VOID) gwf_error(ulm_rcb.ulm_error.err_code, GWF_INTERR, 0); (VOID) gwf_error(E_GW0312_ULM_OPENSTREAM_ERROR, GWF_INTERR, 3, sizeof(*ulm_rcb.ulm_memleft), ulm_rcb.ulm_memleft, sizeof(ulm_rcb.ulm_sizepool), &ulm_rcb.ulm_sizepool, sizeof(ulm_rcb.ulm_blocksize), &ulm_rcb.ulm_blocksize); if (ulm_rcb.ulm_error.err_code == E_UL0005_NOMEM) gw_rcb->gwr_error.err_code = E_GW0600_NO_MEM; else gw_rcb->gwr_error.err_code = E_GW0208_GWI_REGISTER_ERROR; break; } /* ** Only process extended index info if this gateway has an ** extended index catalog */ if (Gwf_facility->gwf_gw_info[gw_id].gwf_xidx_sz > 0) { gwx.xrcb_tab_id = &gw_rcb->gwr_tab_id; /* STRUCT_ASSIGN_MACRO(gw_rcb->gwr_tab_id, gwx.xrcb_tab_id); */ gwx.xrcb_gw_id = gw_id; STRUCT_ASSIGN_MACRO(gw_rcb->gwr_in_vdata2, gwx.xrcb_var_data2); /* allocate iigwX_index tuple buffer */ gwx.xrcb_var_data1.data_in_size = ulm_rcb.ulm_psize = ulm_rcb.ulm_blocksize; if ((status = ulm_palloc(&ulm_rcb)) != E_DB_OK) { (VOID) gwf_error(ulm_rcb.ulm_error.err_code, GWF_INTERR, 0); (VOID) gwf_error(E_GW0314_ULM_PALLOC_ERROR, GWF_INTERR, 4, sizeof(*ulm_rcb.ulm_memleft), ulm_rcb.ulm_memleft, sizeof(ulm_rcb.ulm_sizepool), &ulm_rcb.ulm_sizepool, sizeof(ulm_rcb.ulm_blocksize), &ulm_rcb.ulm_blocksize, sizeof(ulm_rcb.ulm_psize), &ulm_rcb.ulm_psize); if (ulm_rcb.ulm_error.err_code == E_UL0005_NOMEM) gw_rcb->gwr_error.err_code = E_GW0600_NO_MEM; else gw_rcb->gwr_error.err_code = E_GW0208_GWI_REGISTER_ERROR; break; } gwx.xrcb_var_data1.data_address = ulm_rcb.ulm_pptr; /* request exit format */ if ((status = (*Gwf_facility->gwf_gw_info[gw_id].gwf_gw_exits [GWX_VIDXF]) (&gwx)) != E_DB_OK) { if ( gwx.xrcb_error.err_code == E_GW050E_ALREADY_REPORTED ) { gw_rcb->gwr_error.err_code = E_GW050E_ALREADY_REPORTED; } else { (VOID) gwf_error(gwx.xrcb_error.err_code, GWF_INTERR, 0); gw_rcb->gwr_error.err_code = E_GW0208_GWI_REGISTER_ERROR; } if ((ulm_status = ulm_closestream(&ulm_rcb)) != E_DB_OK) { (VOID) gwf_error(ulm_rcb.ulm_error.err_code, GWF_INTERR, 0); (VOID) gwf_error(E_GW0313_ULM_CLOSESTREAM_ERROR, GWF_INTERR, 1, sizeof(*ulm_rcb.ulm_memleft), ulm_rcb.ulm_memleft); break; } break; } else { /* initialize dmt_sequence */ dmt.dmt_sequence = gw_rcb->gwr_gw_sequence; /* request DMF to append tuples */ status = gwu_copen(&dmt, &dmr, session->gws_scf_session_id, (PTR) gw_rcb->gwr_database_id, gw_id, gw_rcb->gwr_xact_id, &gw_rcb->gwr_tab_id, &session->gws_gw_info[gw_id].gws_xidx_tab_name, DMT_A_WRITE, FALSE, &err); /* put the iigwX_index tuple */ if ( status == E_DB_OK) { STRUCT_ASSIGN_MACRO(gwx.xrcb_var_data1, dmr.dmr_data); if ((status = (*Dmf_cptr)(DMR_PUT, &dmr)) == E_DB_OK) { status = (*Dmf_cptr)(DMT_CLOSE, &dmt); if (status != E_DB_OK) { /* Handle error from close */ (VOID) gwf_error(dmt.error.err_code, GWF_INTERR, 0); gw_rcb->gwr_error.err_code = E_GW0208_GWI_REGISTER_ERROR; break; } } else { /* Handle error from put */ switch (dmt.error.err_code) { case E_DM0042_DEADLOCK: gw_rcb->gwr_error.err_code = E_GW0327_DMF_DEADLOCK; break; default: (VOID) gwf_error(dmt.error.err_code, GWF_INTERR, 0); gw_rcb->gwr_error.err_code = E_GW0208_GWI_REGISTER_ERROR; break; } break; } } else { /* Handle error from gwu_copen() */ (VOID) gwf_error(err.err_code, GWF_INTERR, 0); gw_rcb->gwr_error.err_code = E_GW0208_GWI_REGISTER_ERROR; break; } /* ** delete tcb from GWF cache since its index info cannot be ** current. ** **** Not clear that we care about this. We probably can't remove **** an index if it is being used and it is only referenced in its **** own tcb. */ #if 0 /* ** Save the index's table id, set db_tab_index to 0 for the call. */ _VOID_ MEcopy((PTR)&gw_rcb->gwr_tab_id, sizeof(DB_TAB_ID), (PTR)&sav_idx_id); gw_rcb->gwr_tab_id.db_tab_index = 0; if ((status = gwu_deltcb(gw_rcb, GWU_TCB_OPTIONAL, &err)) != E_DB_OK) { (VOID) gwf_error(err.err_code, GWF_INTERR, 0); gw_rcb->gwr_error.err_code = E_GW0208_GWI_REGISTER_ERROR; _VOID_ MEcopy((PTR)&sav_idx_id, sizeof(DB_TAB_ID), (PTR)&gw_rcb->gwr_tab_id); break; } _VOID_ MEcopy((PTR)&sav_idx_id, sizeof(DB_TAB_ID), (PTR)&gw_rcb->gwr_tab_id); #endif /* 0 */ } } /* End if Xindex processing */ /* ** Append a tuple to iigwX_relation catalog for this index. */ if ((status = gwi_map_idx_rel(gw_rcb, &dmt, &dmr, &ulm_rcb)) != E_DB_OK) { _VOID_ gwf_error(gw_rcb->gwr_error.err_code, GWF_INTERR, 0); gw_rcb->gwr_error.err_code = E_GW0208_GWI_REGISTER_ERROR; break; } /* ** Now append iigwX_attribute tuples. */ if ((status = gwi_map_idx_att(gw_rcb, &ulm_rcb)) != E_DB_OK) { _VOID_ gwf_error(gw_rcb->gwr_error.err_code, GWF_INTERR, 0); gw_rcb->gwr_error.err_code = E_GW0208_GWI_REGISTER_ERROR; break; } /* close the temporary stream */ if ((status = ulm_closestream(&ulm_rcb)) != E_DB_OK) { (VOID) gwf_error(ulm_rcb.ulm_error.err_code, GWF_INTERR, 0); (VOID) gwf_error(E_GW0313_ULM_CLOSESTREAM_ERROR, GWF_INTERR, 1, sizeof(*ulm_rcb.ulm_memleft), ulm_rcb.ulm_memleft); gw_rcb->gwr_error.err_code = E_GW0208_GWI_REGISTER_ERROR; break; } /* If we get here everything is okay. */ break; } if (status == E_DB_OK) gw_rcb->gwr_error.err_code = E_DB_OK; return(status); }