DB_STATUS qet_t4_savept( QEF_CB *qef_cb) { i4 err; DB_STATUS status; TPR_CB tpr_cb, *tpr_p = & tpr_cb; if (qef_cb->qef_rcb->qef_spoint == 0) { qef_error(E_QE0018_BAD_PARAM_IN_CB, 0L, E_DB_WARN, &err, &qef_cb->qef_rcb->error, 0); return (E_DB_WARN); } /* Must be in a transaction */ if (qef_cb->qef_stat == QEF_NOTRAN) { if (qef_cb->qef_rcb->qef_flag == DB_QUEL) { qef_error(E_QE0004_NO_TRANSACTION, 0L, E_DB_WARN, &err, &qef_cb->qef_rcb->error, 0); return (E_DB_WARN); } else if (qef_cb->qef_auto == QEF_ON) { /* savepoint not allowed when autocommit is on */ qef_error(2178L, 0L, E_DB_WARN, &err, &qef_cb->qef_rcb->error, 0); return (E_DB_WARN); } } /* Cannot set a savepoint if there are open cursors */ if (qef_cb->qef_open_count > 0) { qef_error(E_QE0020_OPEN_CURSOR, 0L, E_DB_WARN, &err, &qef_cb->qef_rcb->error, 0); return (E_DB_WARN); } MEfill(sizeof(tpr_cb), '\0', (PTR) & tpr_cb); tpr_p->tpr_session = qef_cb->qef_c2_ddb_ses.qes_d2_tps_p; tpr_p->tpr_rqf = qef_cb->qef_c2_ddb_ses.qes_d3_rqs_p; tpr_p->tpr_save_name = qef_cb->qef_rcb->qef_spoint; if (qef_cb->qef_rcb->qef_flag == DB_QUEL) tpr_p->tpr_lang_type = DB_QUEL; else if (qef_cb->qef_rcb->qef_flag == DB_SQL) tpr_p->tpr_lang_type = DB_SQL; else tpr_p->tpr_lang_type = DB_NOLANG; status = qed_u17_tpf_call(TPF_SAVEPOINT, tpr_p, qef_cb->qef_rcb); return(status); }
/*{ ** Name: QEU_CLOSE - close an opened table ** ** External QEF call: status = qef_call(QEU_CLOSE, &qeu_cb); ** ** Description: ** Close a table opened through the QEU_OPEN command. ** ** 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 ** ** Outputs: ** qeu_cb ** .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 ** 14-may-87 (daved) ** zero the access id to cause an error in DMF if a table is ** closed twice. */ DB_STATUS qeu_close( QEF_CB *qef_cb, QEU_CB *qeu_cb) { i4 err; DMT_CB dmt_cb; DB_STATUS status; /* QEU_CLOSE 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); } MEfill(sizeof(DMT_CB), 0, (PTR) &dmt_cb); dmt_cb.type = DMT_TABLE_CB; dmt_cb.length = sizeof(DMT_CB); dmt_cb.dmt_flags_mask = 0; dmt_cb.dmt_record_access_id = qeu_cb->qeu_acc_id; status = dmf_call(DMT_CLOSE, &dmt_cb); if (status != E_DB_OK) { qef_error(dmt_cb.error.err_code, 0L, status, &err, &qeu_cb->error, 0); } else qef_cb->qef_open_count--; qeu_cb->qeu_acc_id = (PTR) NULL; return (status); }
DB_STATUS qeu_d3_cre_view( QEF_CB *qef_cb, QEUQ_CB *i_quq_p) { DB_STATUS status; i4 ignore; DB_ERROR err_stub; status = qeu_d6_cre_view(qef_cb, i_quq_p); if (status) qef_error(i_quq_p->error.err_code, 0L, status, & ignore, & err_stub, 0); return(status); }
/*{ ** Name: qeu_cevent - Store event information for one event. ** ** External QEF call: status = qef_call(QEU_CEVENT, &qeuq_cb); ** ** Description: ** Add the event tuple and the event query text to the appropriate ** tables (iievent and iiqrytext). ** ** Most of the event tuple was filled by the parser from the CREATE EVENT ** statement, except that since this is the first access to iievent, ** the uniqueness of the event name (within the current user scope) is ** validated here. First, all events that have the same name and ** owner are fetched (the iievent table is hashed on name and owner ** so this is a singleton keyed retrieval). If there are any then ** the event is a duplicate and an error is returned. If this is ** unique then the event is entered into iievent. ** ** To allow permissions to apply to events, an event tuple includes ** a "dummy table id" (much like database procedures). This id is ** retrieved from DMU_GET_TABID. ** ** An internal qrytext id (time-stamp) is created and all the qrytext ** tuples associated with the event are entered into iiqrytext. ** Note that the size of CREATE EVENT query text is never likely to ** be more than one iiqrytext tuple, but the code allows more than ** one tuple in case a WITH clause is added in the future (extending ** the length of the statement). ** ** The current "create date" is retrieved from ADF (using date("now")). ** ** Inputs: ** qef_cb QEF session control block ** qeuq_cb ** .qeuq_eflag Designate error handling for user errors. ** QEF_INTERNAL Return error code. ** QEF_EXTERNAL Send message to user. ** .qeuq_cq Number of query text tuples. ** .qeuq_qry_tup Query text tuples. ** .qeuq_culd Number of event tuples. Must be 1. ** .qeuq_uld_tup Event tuple: ** .dbe_name Event name. ** .dbe_owner Event owner. ** .dbe_type Event type. ** The remaining fields are filled here. ** .qeuq_db_id Database id. ** .qeuq_d_id DMF session id. ** ** Outputs: ** qeuq_cb ** .error.err_code E_QE0002_INTERNAL_ERROR ** E_QE0017_BAD_CB ** E_QE0018_BAD_PARAM_IN_CB ** E_QE0022_ABORTED ** E_QE020A_EVENT_EXISTS (ret E_QE0025_USER_ERROR) ** Returns: ** E_DB_{OK, WARN, ERROR, FATAL} ** Exceptions: ** none ** ** History: ** 28-aug-89 (neil) ** Written for Terminator II/alerters. ** 09-feb-90 (neil) ** Added auditing functionality. ** 03-mar-90 (neil) ** Clear adf_constants before calling ADF. The problem was that the ** session CB may have been pointing at "old" data which had been ** reused for other things. ** 19-may-93 (anitap) ** Added support to create implicit schema for dbevent. ** 07-jul-93 (anitap) ** Added two arguments qef_rcb & qeuq_cb to qea_schema() instead of ** PTR. ** Changed assignment of flag to IMPLICIT_SCHEMA. ** 21-sep-93 (stephenb) ** Replace generic I_SX2032_EVENT_ACCESS with I_SX2032_EVENT_CREATE. ** 27-oct-93 (andre) ** As a part of fix for bug 51852 (which was reported in 6.4 but can ** and will manifest itself in 6.5 as soon as someone places some ** stress on the DBMS), we want to use the dbevent id (really ** guaranteed to be unique) instead of timestamps (allegedly unique, ** but in fact may be non-unique if several objects get created in ** rapid succession on a reasonably fast box) to identify IIQRYTEXT ** tuples associated with a given dbevent. This id (pumped through ** randomizing function) will be used to key into IIQRYTEXT */ DB_STATUS qeu_cevent( QEF_CB *qef_cb, QEUQ_CB *qeuq_cb) { DB_IIEVENT *evtuple; /* New event tuple */ DB_IIEVENT evtuple_temp; /* Tuple and */ DMR_ATTR_ENTRY evkey_array[2]; /* keys for uniqueness check */ DMR_ATTR_ENTRY *evkey_ptr_array[2]; DMU_CB dmu_cb; /* For unique table-id request */ DB_DATA_VALUE evcreate_dv; /* For create date */ DB_IIQRYTEXT *qtuple; /* Event text */ DB_TAB_ID randomized_id; i4 i; /* Querytext counter */ QEF_DATA *next; /* and data pointer */ DB_STATUS status, local_status; DB_ERROR e_error; i4 error; bool tbl_opened = FALSE; QEU_CB tranqeu; /* May need a transaction */ bool transtarted = FALSE; QEU_CB qeu; QEF_DATA qef_data; i4 flag = IMPLICIT_SCHEMA; QEF_RCB *qef_rcb = (QEF_RCB *)NULL; for (;;) /* Dummy for loop for error breaks */ { /* Validate CB and parameters */ if (qeuq_cb->qeuq_type != QEUQCB_CB || qeuq_cb->qeuq_length != sizeof(QEUQ_CB)) { status = E_DB_ERROR; error = E_QE0017_BAD_CB; break; } if ( (qeuq_cb->qeuq_cq == 0 || qeuq_cb->qeuq_qry_tup == NULL) || (qeuq_cb->qeuq_culd != 1 || qeuq_cb->qeuq_uld_tup == NULL) || (qeuq_cb->qeuq_db_id == NULL) || (qeuq_cb->qeuq_d_id == 0)) { status = E_DB_ERROR; error = E_QE0018_BAD_PARAM_IN_CB; break; } /* ** Check to see if transaction is in progress, if so set a local ** transaction, otherwise we'll use the user's transaction. */ if (qef_cb->qef_stat == QEF_NOTRAN) { tranqeu.qeu_type = QEUCB_CB; tranqeu.qeu_length = sizeof(QEUCB_CB); tranqeu.qeu_db_id = qeuq_cb->qeuq_db_id; tranqeu.qeu_d_id = qeuq_cb->qeuq_d_id; tranqeu.qeu_flag = 0; status = qeu_btran(qef_cb, &tranqeu); if (status != E_DB_OK) { error = tranqeu.error.err_code; break; } transtarted = TRUE; } /* Escalate the transaction to MST */ if (qef_cb->qef_auto == QEF_OFF) qef_cb->qef_stat = QEF_MSTRAN; evtuple = (DB_IIEVENT *)qeuq_cb->qeuq_uld_tup->dt_data; /* Validate that the event name/owner is unique */ qeu.qeu_type = QEUCB_CB; qeu.qeu_length = sizeof(QEUCB_CB); qeu.qeu_tab_id.db_tab_base = DM_B_EVENT_TAB_ID; qeu.qeu_tab_id.db_tab_index = DM_I_EVENT_TAB_ID; qeu.qeu_db_id = qeuq_cb->qeuq_db_id; qeu.qeu_lk_mode = DMT_IX; qeu.qeu_flag = DMT_U_DIRECT; qeu.qeu_access_mode = DMT_A_WRITE; qeu.qeu_mask = 0; status = qeu_open(qef_cb, &qeu); if (status != E_DB_OK) { error = qeu.error.err_code; break; } tbl_opened = TRUE; /* Retrieve the same named/owned event - if not there then ok */ qeu.qeu_count = 1; qeu.qeu_tup_length = sizeof(DB_IIEVENT); qeu.qeu_output = &qef_data; qef_data.dt_next = NULL; qef_data.dt_size = sizeof(DB_IIEVENT); qef_data.dt_data = (PTR)&evtuple_temp; qeu.qeu_getnext = QEU_REPO; qeu.qeu_klen = 2; /* Keyed on name and owner */ qeu.qeu_key = evkey_ptr_array; evkey_ptr_array[0] = &evkey_array[0]; evkey_ptr_array[0]->attr_number = DM_1_EVENT_KEY; evkey_ptr_array[0]->attr_operator = DMR_OP_EQ; evkey_ptr_array[0]->attr_value = (char *)&evtuple->dbe_name; evkey_ptr_array[1] = &evkey_array[1]; evkey_ptr_array[1]->attr_number = DM_2_EVENT_KEY; evkey_ptr_array[1]->attr_operator = DMR_OP_EQ; evkey_ptr_array[1]->attr_value = (char *)&evtuple->dbe_owner; qeu.qeu_qual = NULL; qeu.qeu_qarg = NULL; status = qeu_get(qef_cb, &qeu); if (status == E_DB_OK) /* Found the same event! */ { (VOID)qef_error(E_QE020A_EVENT_EXISTS, 0L, E_DB_ERROR, &error, &qeuq_cb->error, 1, qec_trimwhite(sizeof(evtuple->dbe_name), (char *)&evtuple->dbe_name), (PTR)&evtuple->dbe_name); error = E_QE0025_USER_ERROR; break; } if (qeu.error.err_code != E_QE0015_NO_MORE_ROWS) { error = qeu.error.err_code; /* Some other error */ break; } /* The event is unique - append it */ status = E_DB_OK; /* ** Get unique event id (a table id) from DMF. This id enables ** permissions to be associated with the event. */ dmu_cb.type = DMU_UTILITY_CB; dmu_cb.length = sizeof(DMU_CB); dmu_cb.dmu_flags_mask = 0; dmu_cb.dmu_tran_id = qef_cb->qef_dmt_id; dmu_cb.dmu_db_id = qeuq_cb->qeuq_db_id; status = dmf_call(DMU_GET_TABID, &dmu_cb); if (status != E_DB_OK) { error = dmu_cb.error.err_code; break; } evtuple->dbe_uniqueid.db_tab_base = dmu_cb.dmu_tbl_id.db_tab_base; evtuple->dbe_uniqueid.db_tab_index = dmu_cb.dmu_tbl_id.db_tab_index; /* ** use dbevent id to generate randomized id which will be used to ** identify IIQRYTEXT tuples associated with this dbevent */ randomized_id.db_tab_base = ulb_rev_bits(evtuple->dbe_uniqueid.db_tab_base); randomized_id.db_tab_index = ulb_rev_bits(evtuple->dbe_uniqueid.db_tab_index); /* set text id to "randomized" id */ evtuple->dbe_txtid.db_qry_high_time = randomized_id.db_tab_base; evtuple->dbe_txtid.db_qry_low_time = randomized_id.db_tab_index; /* Get the create date of the event */ evcreate_dv.db_datatype = DB_DTE_TYPE; evcreate_dv.db_prec = 0; evcreate_dv.db_length = sizeof(DB_DATE); evcreate_dv.db_data = (PTR)&evtuple->dbe_create; evcreate_dv.db_collID = -1; qef_cb->qef_adf_cb->adf_constants = NULL; status = adu_datenow(qef_cb->qef_adf_cb, &evcreate_dv); if (status != E_DB_OK) { error = qeu.error.err_code; break; } /* Insert single event tuple */ qeu.qeu_count = 1; qeu.qeu_tup_length = sizeof(DB_IIEVENT); qeu.qeu_input = qeuq_cb->qeuq_uld_tup; /* Which points at evtuple */ status = qeu_append(qef_cb, &qeu); if (status != E_DB_OK) { error = qeu.error.err_code; break; } status = qeu_close(qef_cb, &qeu); if (status != E_DB_OK) { error = qeu.error.err_code; break; } tbl_opened = FALSE; /* ** Update all query text tuples with query id - validate list. Even ** though we will probably have just one text tuple this is set up ** for syntactic extensions to the CREATE EVENT statement. */ next = qeuq_cb->qeuq_qry_tup; for (i = 0; i < qeuq_cb->qeuq_cq; i++) { qtuple = (DB_IIQRYTEXT *)next->dt_data; next = next->dt_next; qtuple->dbq_txtid.db_qry_high_time = randomized_id.db_tab_base; qtuple->dbq_txtid.db_qry_low_time = randomized_id.db_tab_index; if (i < (qeuq_cb->qeuq_cq -1) && next == NULL) { error = E_QE0018_BAD_PARAM_IN_CB; status = E_DB_ERROR; break; } } /* for all query text tuples */ if (status != E_DB_OK) break; /* Insert all query text tuples */ qeu.qeu_tab_id.db_tab_base = DM_B_QRYTEXT_TAB_ID; qeu.qeu_tab_id.db_tab_index = 0L; qeu.qeu_mask = 0; status = qeu_open(qef_cb, &qeu); if (status != E_DB_OK) { error = qeu.error.err_code; break; } tbl_opened = TRUE; qeu.qeu_count = qeuq_cb->qeuq_cq; qeu.qeu_tup_length = sizeof(DB_IIQRYTEXT); qeu.qeu_input = qeuq_cb->qeuq_qry_tup; status = qeu_append(qef_cb, &qeu); if (status != E_DB_OK) { error = qeu.error.err_code; break; } status = qeu_close(qef_cb, &qeu); if (status != E_DB_OK) { error = qeu.error.err_code; break; } tbl_opened = FALSE; status = qea_schema(qef_rcb, qeuq_cb, qef_cb, (DB_SCHEMA_NAME *)&evtuple->dbe_owner, flag); if (status != E_DB_OK) { error = qeuq_cb->error.err_code; break; } if (transtarted) /* If we started a transaction */ { status = qeu_etran(qef_cb, &tranqeu); if (status != E_DB_OK) { error = tranqeu.error.err_code; break; } } /* Audit CREATE EVENT */ if ( Qef_s_cb->qef_state & QEF_S_C2SECURE ) { status = qeu_secaudit(FALSE, qef_cb->qef_ses_id, evtuple->dbe_name.db_ev_name, &evtuple->dbe_owner, DB_EVENT_MAXNAME, SXF_E_EVENT, I_SX2032_EVENT_CREATE, SXF_A_SUCCESS | SXF_A_CREATE, &e_error); if (status != E_DB_OK) break; } qeuq_cb->error.err_code = E_QE0000_OK; return (E_DB_OK); } /* End dummy for */ /* call qef_error to handle error messages */ (VOID) qef_error(error, 0L, status, &error, &qeuq_cb->error, 0); /* Close off all the tables. */ local_status = E_DB_OK; if (tbl_opened) /* If system table opened, close it */ { local_status = qeu_close(qef_cb, &qeu); if (local_status != E_DB_OK) { (VOID) qef_error(qeu.error.err_code, 0L, local_status, &error, &qeuq_cb->error, 0); if (local_status > status) status = local_status; } } if (transtarted) /* If we started a transaction */ { local_status = qeu_atran(qef_cb, &tranqeu); if (local_status != E_DB_OK) { (VOID) qef_error(tranqeu.error.err_code, 0L, local_status, &error, &qeuq_cb->error, 0); if (local_status > status) status = local_status; } } return (status); } /* qeu_cevent */
/* ** Name: qeu_ev_used_with_alarm ** ** Description: ** Determines whether a security alarm is using this event ** ** Inputs: ** event_id - Event id ** ** History: ** 7-dec-93 (robf) ** Created ** 21-dec-93 (robf) ** Lookup by id now. ** 09-Mar-99 (schte01) ** Removed extraneous status assignment which caused compiler warning. ** 06-Aug-2002 (jenjo02) ** Init qeu_mask before calling qeu_open() lest DMF think we're ** passing bogus lock information (QEU_TIMEOUT,QEU_MAXLOCKS). */ static DB_STATUS qeu_ev_used_with_alarm( QEF_CB *qef_cb, QEUQ_CB *qeuq_cb, DB_TAB_ID *event_id ) { QEU_CB aqeu; QEF_DATA aqef_data; DB_SECALARM alarm; DB_STATUS status=E_DB_OK; bool loop=FALSE; bool found=FALSE; i4 error=0; do { /* Process security alarms */ aqeu.qeu_type = QEUCB_CB; aqeu.qeu_length = sizeof(QEUCB_CB); aqeu.qeu_tab_id.db_tab_base = DM_B_IISECALARM_TAB_ID; aqeu.qeu_tab_id.db_tab_index = DM_I_IISECALARM_TAB_ID; aqeu.qeu_db_id = qeuq_cb->qeuq_db_id; aqeu.qeu_lk_mode = DMT_S; aqeu.qeu_flag = QEU_BYPASS_PRIV; aqeu.qeu_access_mode = DMT_A_READ; aqeu.qeu_mask = 0; status = qeu_open(qef_cb, &aqeu); if(status!=E_DB_OK) break; aqeu.qeu_getnext = QEU_REPO; aqeu.qeu_klen = 0; aqeu.qeu_qual = 0; aqeu.qeu_qarg = 0; aqeu.qeu_count = 1; aqeu.qeu_tup_length = sizeof(DB_SECALARM); aqeu.qeu_output = &aqef_data; aqef_data.dt_next = 0; aqef_data.dt_size = sizeof(DB_SECALARM); aqef_data.dt_data = (PTR)&alarm; while (status == E_DB_OK) { /* Read all iisecalarm records. */ status = qeu_get(qef_cb, &aqeu); if ((status != E_DB_OK) && (aqeu.error.err_code == E_QE0015_NO_MORE_ROWS)) { status = E_DB_OK; break; } else if ((status == E_DB_OK) && (aqeu.qeu_count != 1)) { error = E_US2476_9334_IISECALARM_ERROR; if (status < E_DB_ERROR) status = E_DB_ERROR; break; } if (event_id->db_tab_base==alarm.dba_eventid.db_tab_base && event_id->db_tab_index==alarm.dba_eventid.db_tab_index) { found=TRUE; break; } aqeu.qeu_getnext = QEU_NOREPO; aqeu.qeu_klen = 0; } status = qeu_close(qef_cb, &aqeu); if (status != E_DB_OK) { error= E_US2476_9334_IISECALARM_ERROR; } } while (loop); /* ** Report any errors */ if(error) { i4 err; DB_ERROR err_blk; _VOID_ qef_error(error, 0L, status, &err, &err_blk, 0); } if(status==E_DB_OK) { if(found) status=E_DB_WARN; else status=E_DB_OK; } return status; }
DB_STATUS qee_d8_undefrpt( QEF_RCB *qef_rcb, PTR i_qso_handle) { DB_STATUS status = E_DB_OK, sav_status = E_DB_OK; DB_ERROR sav_err; i4 err; GLOBALREF QEF_S_CB *Qef_s_cb; QEE_DSH *dsh_p = (QEE_DSH *)NULL; QEF_QP_CB *qp; bool have_qp = FALSE; QSF_RCB qsf_rcb; ULM_RCB ulm; ULH_RCB ulh_rcb; struct { PTR qso_handle; CS_SID session_id; } ulh_name; /* 1. acquire the QP using the handle */ qsf_rcb.qsf_next = (QSF_RCB *)NULL; qsf_rcb.qsf_prev = (QSF_RCB *)NULL; qsf_rcb.qsf_length = sizeof(QSF_RCB); qsf_rcb.qsf_type = QSFRB_CB; qsf_rcb.qsf_owner = (PTR)DB_QEF_ID; qsf_rcb.qsf_ascii_id = QSFRB_ASCII_ID; qsf_rcb.qsf_sid = qef_rcb->qef_cb->qef_ses_id; ulh_rcb.ulh_hashid = Qef_s_cb->qef_ulhid; qsf_rcb.qsf_obj_id.qso_handle = i_qso_handle; qsf_rcb.qsf_lk_state = QSO_SHLOCK; status = qsf_call(QSO_LOCK, &qsf_rcb); if (status) { qef_rcb->error.err_code = E_QE0019_NON_INTERNAL_FAILURE; return(status); } have_qp = TRUE; qp = (QEF_QP_CB *) qsf_rcb.qsf_root; /* For sharable QP, sometimes the QP may have been destroyed by ** another session. So check for a NULL root. If so, release the ** lock and return. */ if (qp == (QEF_QP_CB *) NULL) { qsf_call(QSO_UNLOCK, &qsf_rcb); return(E_DB_OK); } /* 2. gotten the QP, acquire the DSH in ULH's cache */ STRUCT_ASSIGN_MACRO(Qef_s_cb->qef_d_ulmcb, ulm); ulh_name.qso_handle = qsf_rcb.qsf_obj_id.qso_handle; ulh_name.session_id = qef_rcb->qef_cb->qef_ses_id; status = ulh_getmember(&ulh_rcb, (unsigned char *) &qp->qp_id, (i4)sizeof(DB_CURSOR_ID), (unsigned char *) & ulh_name, (i4)sizeof(ulh_name), ULH_DESTROYABLE, 0); if (DB_FAILURE_MACRO(status)) { qef_error(ulh_rcb.ulh_error.err_code, 0L, status, & err, &qef_rcb->error, 0); qef_rcb->error.err_code = E_QE0102_CATALOG_DSH_OBJECT; } else { dsh_p = (QEE_DSH *)(ulh_rcb.ulh_object->ulh_uptr); ulm.ulm_streamid_p = &ulh_rcb.ulh_object->ulh_streamid; if (dsh_p != (QEE_DSH *)NULL) { /* 3. reset the defined state of the REPEAT QUERY in the DSH */ dsh_p->dsh_ddb_cb->qee_d3_status &= ~QEE_03Q_DEF; /* 4. must release the acquired DSH */ ulh_rcb.ulh_object = (ULH_OBJECT *)dsh_p->dsh_handle; } status = ulh_release(& ulh_rcb); if (status != E_DB_OK) { qef_error(ulh_rcb.ulh_error.err_code, 0L, status, & err, &qef_rcb->error, 0); qef_rcb->error.err_code = E_QE0104_RELEASE_DSH_OBJECT; } /* must fall thru to release the QP */ } /* 5. release the QP */ if (have_qp) { qsf_call(QSO_UNLOCK, & qsf_rcb); } if (status == E_DB_OK && sav_status) { status = sav_status; STRUCT_ASSIGN_MACRO(sav_err, qef_rcb->error); } return(status); }
/*{ ** Name: QEA_CALLPROC - call the named procedure ** ** Description: ** The current execution environment is saved and an ** environment is created in which to execute the ** named procedure. ** ** This procedure is only called when a nested procedure is invoked. ** This can occur the first time through, or if the procedure is not ** found (LOAD_QP) or the plan was deemed invalid (INVALID_QUERY) then ** the procedure is re-entered in this routine. ** ** If rules are turned off (QEF_T_NORULES) then this procedure returns ** immediately. ** ** Inputs: ** action Callproc action header ** qef_rcb ** call_dsh DSH doing the callproc ** function unused ** state unused ** ** Outputs: ** call_dsh ** .error.err_code one of the following ** E_QE0119_LOAD_QP - Load a procedure QP ** E_QE0125_RULES_INHIBIT - Rules are turned off. ** E_QE0000_OK ** Returns: ** E_DB_{OK,WARN,ERROR,FATAL} ** Exceptions: ** none ** ** Side Effects: ** none ** ** History: ** 20-apr-89 (paul) ** Moved from qeq.c ** 09-may-89 (neil) ** Added rule name tracing. ** 26-may-89 (paul) ** Increase statement #, cleanup DSH on error recovery. ** 31-may-89 (neil) ** Cleanup tracing; modify when context count is set; reset "saved ** resource" bit if procedure is loaded. ** 23-jun-89 (neil) ** Extended trace for nested procedures: Indicate procedure nesting ** level and rule depth. ** 26-sep-89 (neil) ** Support for SET NORULES. ** 02-jan-90 (neil) ** DSH initialization error handling improved to indicate problem ** specifics. ** 03-jan-90 (ralph) ** Change interface to QSO_JUST_TRANS ** 10-jan-90 (neil) ** Improved DSH cleanup on DSH initialization errors. Made sure ** to confirm allocation error, and to pass a FALSE "release" flag ** to qeq_cleanup. ** 09-feb-90 (neil) ** Auditing cleanup: only audit the firing of rules and only if ** auditing is on (for performance). ** 09-nov-92 (jhahn) ** Added handling for byrefs. ** 14-dec-92 (jhahn) ** Cleaned up handling of byrefs. ** 12-feb-93 (jhahn) ** Added support for statement level rules. (FIPS) ** 24-mar-93 (jhahn) ** Various fixes for support of statement level rules. (FIPS) ** 02-apr-93 (jhahn) ** Made set input procedures called from rules bump qef_rule_depth. ** 01-may-93 (jhahn) ** Undid above change. Instead added new action QEA_INVOKE_RULE. ** 06-jul-93 (robf) ** Pass security label to qeu_secaudit ** 01-sep-93 (jhahn) ** Added support for multiple query plans for set input procedures. ** 7-jan-94 (swm) ** Bug #58635 ** Added PTR cast for qsf_owner which has changed type to PTR. ** 18-may-94 (anitap) ** Bug #63465 ** If error in nested procedure, the whole transaction was being ** rolled back. ** 7-nov-95 (inkdo01) ** Changes to replace QEN_ADF structure instances by pointers in ** QEF_AHD structures. ** 24-jul-96 (inkdo01) ** Added support of global temp table proc parms. ** 4-mar-97 (inkdo01) ** Added display of error QE030B (row rule calls SET OF proc). ** 23-may-97 (inkdo01) ** Change QE030B to only pass procname, since it is mapped to a ** US error in qeferror, anyway. ** 17-aug-99 (thaju02) ** initialize dmt_show.db_tab_id.db_tab_base to 0 prior to calling ** dmt_show, to avoid falsely reporting E_QE0018. (b98431) ** 27-apr-01 (inkdo01) ** Add code to detect nested/dynamic calls to row procs. ** 15-mar-04 (inkdo01) ** dsh_tempTables is now an array of ptrs. ** 17-mar-04 (inkdo01) ** We be fixin' a bug in error handlin' when qeq_dsh() doesn't ** return a dsh. ** 13-may-04 (inkdo01) ** Preserve status across qeq_cleanup calls. ** 18-may-04 (inkdo01) ** Quick fix to eliminate QE0018 when QE030D (US09AF) happens. ** 13-Jul-2004 (schka24) ** Straighten out which dsh is used where, fix loss of error ** code when finding called qp leading to QE0018. ** 13-Dec-2005 (kschendel) ** Inlined QEN_ADF changed to pointer, fix here. ** 29-May-2008 (gefei01) ** Prototype change for qeq_dsh(). ** 22-Apr-2009 (hanal04) Bug 121970 ** In printrule tracing print the ahd_pcount not qef_pcount ** which is set to zero if we are in a sub-procedure. ** 21-Jun-2010 (kschendel) b123775 ** Combine is-tproc and in-progress args to qeq-dsh. ** Make dbp alias a real QSO_NAME. */ DB_STATUS qea_callproc( QEF_AHD *act, QEF_RCB *qef_rcb, QEE_DSH *call_dsh, i4 function, /* Unused */ i4 state ) /* Unused */ { i4 err; DB_STATUS status = E_DB_OK, savestat; QEF_CB *qef_cb = call_dsh->dsh_qefcb; PTR *cbs = call_dsh->dsh_cbs; QEE_DSH *proc_dsh; /* DSH for called dbp */ QEN_ADF *qen_adf; ADE_EXCB *ade_excb; QSF_RCB qsf_rcb; i4 tr1 = 0, tr2 = 0; /* Dummy trace values */ DB_ERROR e_error; /* To pass to qeu_secaudit */ i4 page_count; bool is_deferred = act->qhd_obj.qhd_callproc.ahd_proc_temptable != NULL; bool gttparm = act->qhd_obj.qhd_callproc.ahd_gttid.db_tab_base != 0; bool need_cleanup = FALSE; bool need_release; bool from_rule = act->qhd_obj.qhd_callproc.ahd_rulename.db_name[0] != EOS; QEE_TEMP_TABLE *proc_temptable; char *cbuf = qef_cb->qef_trfmt; i4 cbufsize = qef_cb->qef_trsize; i4 open_count; do { /* ** This action is called back if a request to CREATE a QP for a ** CALLPROC fails. In this case we just continue with error processing. ** No need for another error as CLEAN_RSRC is only set if a client on ** the outside issued an error knowing we have a stacked environment. ** (Note: as of the 123775 fixes, we shouldn't ever get here with ** CLEAN_RSRC set, since qeq-query no longer attempts to execute ** the action from the sequencer callback. I'm leaving the code ** here for now, though.) */ if ((qef_rcb->qef_intstate & QEF_CLEAN_RSRC) != 0) { call_dsh->dsh_error.err_code = E_QE0025_USER_ERROR; qef_rcb->qef_intstate &= ~QEF_CLEAN_RSRC; status = E_DB_ERROR; break; } if (is_deferred) { proc_temptable = call_dsh->dsh_tempTables[act->qhd_obj.qhd_callproc .ahd_proc_temptable->ttb_tempTableIndex]; if (proc_temptable->tt_statusFlags & TT_EMPTY) if (from_rule) break; /* empty ttab in statement rule - ** nothing to do at all */ else status = openTempTable(qef_rcb, call_dsh, act->qhd_obj.qhd_callproc .ahd_proc_temptable->ttb_tempTableIndex, gttparm); else status = qen_rewindTempTable(call_dsh, act->qhd_obj. qhd_callproc.ahd_proc_temptable->ttb_tempTableIndex); if (status != E_DB_OK) break; } /* If called from a rule & SET NORULES is on, then inhibit execution */ if ( from_rule && ult_check_macro(&qef_cb->qef_trace, QEF_T_NORULES, &tr1, &tr2) ) { /* Trace inhibited rule if required */ if (ult_check_macro(&qef_cb->qef_trace, QEF_T_RULES, &tr1, &tr2)) { char *rn = act->qhd_obj.qhd_callproc.ahd_rulename.db_name; STprintf(cbuf, "PRINTRULES: Rule '%.*s' suppressed\n", qec_trimwhite(DB_RULE_MAXNAME, rn), rn); qec_tprintf(qef_rcb, cbufsize, cbuf); } call_dsh->dsh_error.err_code = E_QE0125_RULES_INHIBIT; status = E_DB_ERROR; break; } /* If rules off */ /* ** Security audit rule firing - check that is first time (not ** recreation), is a rule and, for performance, that we really ** need to audit. */ if ( (qef_rcb->qef_intstate & QEF_DBPROC_QP) == 0 && (act->qhd_obj.qhd_callproc.ahd_rulename.db_name[0] != EOS) && (Qef_s_cb->qef_state & QEF_S_C2SECURE) ) { status = qeu_secaudit(FALSE, qef_cb->qef_ses_id, act->qhd_obj.qhd_callproc.ahd_rulename.db_name, (DB_OWN_NAME *)&act->qhd_obj.qhd_callproc.ahd_ruleowner, sizeof(act->qhd_obj.qhd_callproc.ahd_rulename), SXF_E_RULE, I_SX202F_RULE_ACCESS, SXF_A_SUCCESS | SXF_A_EXECUTE, &e_error); if (status != E_DB_OK) { call_dsh->dsh_error.err_code = e_error.err_code; break; } } /* Actually execute a CALLPROC. */ /* We generate an actual parameter list, save the current */ /* execution context, stack the DSH and setup the new */ /* execution context. Processing then continues with the */ /* new QP. */ /* Save the current execution context as represented by */ /* QEF_RCB and the current DSH. */ STRUCT_ASSIGN_MACRO(*qef_rcb, *call_dsh->dsh_saved_rcb); call_dsh->dsh_act_ptr = act; qen_adf = act->qhd_obj.qhd_callproc.ahd_procparams; if (qen_adf != NULL) { /* Compute the actual parameters for this procedure */ /* call. */ qef_rcb->qef_pcount = act->qhd_obj.qhd_callproc.ahd_pcount; ade_excb = (ADE_EXCB *)cbs[qen_adf->qen_pos]; ade_excb->excb_seg = ADE_SMAIN; status = ade_execute_cx(call_dsh->dsh_adf_cb, ade_excb); if (status != E_DB_OK) { status = qef_adf_error(&call_dsh->dsh_adf_cb->adf_errcb, status, qef_cb, &call_dsh->dsh_error); if (status != E_DB_OK) break; } } else { /* No actual parameters */ qef_rcb->qef_pcount = 0; } /* ** If tracing rules and first time through then display ** rule/procedure information. */ if ((qef_rcb->qef_intstate & QEF_DBPROC_QP) == 0) { if (ult_check_macro(&qef_cb->qef_trace, QEF_T_RULES, &tr1, &tr2)) { char *rn, *pn; /* Rule/procedure names */ rn = act->qhd_obj.qhd_callproc.ahd_rulename.db_name; pn = act->qhd_obj.qhd_callproc.ahd_dbpalias.qso_n_id.db_cur_name; /* Tailor trace for rules vs nested procedures */ STprintf(cbuf, *rn == EOS ? "PRINTRULES 1: Executing procedure '%.*s'\n" : "PRINTRULES 1: Executing procedure '%.*s' from rule '%.*s'\n", qec_trimwhite(DB_DBP_MAXNAME, pn), pn, qec_trimwhite(DB_RULE_MAXNAME, rn), rn); qec_tprintf(qef_rcb, cbufsize, cbuf); STprintf(cbuf, "PRINTRULES 2: Rule/procedure depth = %d/%d, parameters passed = %d\n", qef_rcb->qef_rule_depth, qef_rcb->qef_context_cnt + 1, act->qhd_obj.qhd_callproc.ahd_pcount); qec_tprintf(qef_rcb, cbufsize, cbuf); } /* If tracing rules */ } /* ** Indicate that we have nested one more level, generate an error if ** we are nested too deeply. Context count is actually set later. */ if (qef_cb->qef_max_stack < qef_rcb->qef_context_cnt + 1) { status = E_DB_ERROR; qef_error(E_QE0208_EXCEED_MAX_CALL_DEPTH, 0L, status, &err, &call_dsh->dsh_error, 1, sizeof(qef_cb->qef_max_stack), &qef_cb->qef_max_stack); call_dsh->dsh_error.err_code = E_QE0122_ALREADY_REPORTED; break; } if (gttparm) { STRUCT_ASSIGN_MACRO(act->qhd_obj.qhd_callproc.ahd_gttid, qef_rcb->qef_setInputId); /* copy temptab ID */ page_count = 1; is_deferred = TRUE; } else if (is_deferred) { DMT_CB *dmt_cb = proc_temptable->tt_dmtcb; DMT_SHW_CB dmt_show; DMT_TBL_ENTRY dmt_tbl_entry; dmt_show.type = DMT_SH_CB; dmt_show.length = sizeof(DMT_SHW_CB); dmt_show.dmt_session_id = qef_cb->qef_ses_id; dmt_show.dmt_db_id = qef_rcb->qef_db_id; dmt_show.dmt_tab_id.db_tab_base = 0; dmt_show.dmt_flags_mask = DMT_M_TABLE | DMT_M_ACCESS_ID; dmt_show.dmt_char_array.data_address = NULL; dmt_show.dmt_table.data_address = (PTR) &dmt_tbl_entry; dmt_show.dmt_table.data_in_size = sizeof(DMT_TBL_ENTRY); dmt_show.dmt_record_access_id = dmt_cb->dmt_record_access_id; status = dmf_call(DMT_SHOW, &dmt_show); if (status != E_DB_OK) { STRUCT_ASSIGN_MACRO(dmt_show.error, call_dsh->dsh_error); break; } page_count = dmt_tbl_entry.tbl_page_count; STRUCT_ASSIGN_MACRO(dmt_cb->dmt_id, qef_rcb->qef_setInputId); } else { page_count = -1; MEfill(sizeof(DB_TAB_ID), (u_char)0, (PTR)&qef_rcb->qef_setInputId); } STRUCT_ASSIGN_MACRO(act->qhd_obj.qhd_callproc.ahd_procedureID, qef_rcb->qef_dbpId); /* Get the id of the procedure to call */ STRUCT_ASSIGN_MACRO(act->qhd_obj.qhd_callproc.ahd_dbpalias.qso_n_id, qef_rcb->qef_qp); qef_rcb->qef_qso_handle = NULL; /* Set the full name of the procedure into the RCB in case */ /* we have to call PSF to define the procedure. */ qef_rcb->qef_dbpname = act->qhd_obj.qhd_callproc.ahd_dbpalias; /* Lookup this procedure name as a QSF alias. At this time */ /* we do not have a valid DB_CURSOR_ID because we do not */ /* have the timestamp for the QP object. Ask QSF to look */ /* this up for us. If found, we continue executing, if not */ /* return to SCF to define this procedure. */ qsf_rcb.qsf_type = QSFRB_CB; qsf_rcb.qsf_ascii_id = QSFRB_ASCII_ID; qsf_rcb.qsf_length = sizeof(QSF_RCB); qsf_rcb.qsf_owner = (PTR)DB_QEF_ID; qsf_rcb.qsf_sid = qef_rcb->qef_cb->qef_ses_id; qsf_rcb.qsf_feobj_id.qso_type = QSO_ALIAS_OBJ; qsf_rcb.qsf_feobj_id.qso_lname = sizeof(qsf_rcb.qsf_feobj_id.qso_name); MEcopy((PTR)&act->qhd_obj.qhd_callproc.ahd_dbpalias, sizeof(qsf_rcb.qsf_feobj_id.qso_name), (PTR)qsf_rcb.qsf_feobj_id.qso_name); qsf_rcb.qsf_lk_state = QSO_FREE; status = qsf_call(QSO_JUST_TRANS, &qsf_rcb); if (DB_FAILURE_MACRO(status)) { /* No such procedure in QSF, ask SCF to define it */ /* Tell SCF to call us back even if the porcedure */ /* cannot be loaded. We will need to clean up */ qef_rcb->qef_intstate |= QEF_DBPROC_QP; call_dsh->dsh_error.err_code = E_QE0119_LOAD_QP; break; } else { /* ** The procedure was found - make sure "saved" bit isn't on for ** the scope of this execution. It may get turned back on if ** the QP or DSH is found to be invalid but then we'll re-enter ** here (to try again) and turn it off. */ qef_rcb->qef_intstate &= ~QEF_DBPROC_QP; } /* Increase context count now that we've loaded the QP */ qef_rcb->qef_context_cnt++; /* Procedure in QSF, load the timestamp into the QEF_RCB */ /* to allow normal QEF processing to continue. */ MEcopy((PTR)qsf_rcb.qsf_obj_id.qso_name, sizeof(DB_CURSOR_ID), (PTR)&qef_rcb->qef_qp); status = qeq_dsh(qef_rcb, 0 , &proc_dsh, QEQDSH_IN_PROGRESS, page_count); if (DB_FAILURE_MACRO(status)) { char *rn, *pn; /* Rule/procedure names */ STRUCT_ASSIGN_MACRO(qef_rcb->error, call_dsh->dsh_error); if (call_dsh->dsh_error.err_code == E_QE0023_INVALID_QUERY) { /* No such procedure in QSF, ask SCF to define it */ /* Tell SCF to call us back even if the porcedure */ /* cannot be loaded. We will need to clean up */ qef_cb->qef_dsh = (PTR) call_dsh; qef_rcb->qef_qp = call_dsh->dsh_saved_rcb->qef_qp; qef_rcb->qef_intstate |= QEF_DBPROC_QP; call_dsh->dsh_error.err_code = E_QE0119_LOAD_QP; qef_rcb->qef_context_cnt--; break; } /* ** The QP DSH is invalid for some reason. Generate error and return. ** If any allocation error then change to useful error message. */ if ( call_dsh->dsh_error.err_code == E_UL0005_NOMEM || call_dsh->dsh_error.err_code == E_QS0001_NOMEM || call_dsh->dsh_error.err_code == E_QE001E_NO_MEM || call_dsh->dsh_error.err_code == E_QE000D_NO_MEMORY_LEFT || call_dsh->dsh_error.err_code == E_QE030B_RULE_PROC_MISMATCH) { pn = act->qhd_obj.qhd_callproc.ahd_dbpalias.qso_n_id.db_cur_name; rn = act->qhd_obj.qhd_callproc.ahd_rulename.db_name; if (*rn == EOS) rn = "NULL "; if (call_dsh->dsh_error.err_code == E_QE030B_RULE_PROC_MISMATCH) qef_error(E_QE030B_RULE_PROC_MISMATCH, 0L, status, &err, &call_dsh->dsh_error, 1, /* qec_trimwhite(DB_RULE_MAXNAME, rn), rn, */ qec_trimwhite(DB_DBP_MAXNAME, pn), pn); else qef_error(E_QE0199_CALL_ALLOC, 0L, status, &err, &call_dsh->dsh_error, 3, qec_trimwhite(DB_DBP_MAXNAME, pn), pn, qec_trimwhite(DB_RULE_MAXNAME, rn), rn, sizeof(qef_rcb->qef_context_cnt),&qef_rcb->qef_context_cnt); call_dsh->dsh_error.err_code = E_QE0122_ALREADY_REPORTED; } /* ** Now clean up and restore to state before routine entry. ** Pass in FALSE for release as if the DSH is NULL we do NOT want ** to cause cleanup to release all DSH's for this session ** (qee_cleanup). If the DSH is not NULL it will be cleaned up at ** the end of the query. */ need_cleanup = TRUE; need_release = FALSE; break; } if (proc_dsh->dsh_qp_ptr->qp_status & QEQP_ROWPROC) { char *pn; /* Row producing procs cannot be invoked by QEA_CALLPROC (which ** implies either nested proc call or dynamic SQL proc call). */ pn = act->qhd_obj.qhd_callproc.ahd_dbpalias.qso_n_id.db_cur_name; qef_error(E_QE030D_NESTED_ROWPROCS, 0L, E_DB_ERROR, &err, &call_dsh->dsh_error, 1, qec_trimwhite(DB_DBP_MAXNAME, pn), pn); status = E_DB_ERROR; break; } /* Found QP and DSH, stack old context */ proc_dsh->dsh_stack = call_dsh; proc_dsh->dsh_stmt_no = qef_cb->qef_stmt++; qef_cb->qef_dsh = (PTR) proc_dsh; qef_cb->qef_open_count++; /* Initialize procedure parameters (& user params - even if wrong) */ if (proc_dsh->dsh_qp_ptr->qp_ndbp_params != 0 || qef_rcb->qef_pcount > 0) { status = qee_dbparam(qef_rcb, proc_dsh, call_dsh, act->qhd_obj.qhd_callproc.ahd_params, act->qhd_obj.qhd_callproc.ahd_pcount, TRUE); if (DB_FAILURE_MACRO(status)) { /* If we fail after acquiring the DSH, we need to */ /* deallocate the DSH and recover back to the original */ /* calling state. */ STRUCT_ASSIGN_MACRO(proc_dsh->dsh_error, call_dsh->dsh_error); qef_cb->qef_open_count--; need_cleanup = TRUE; need_release = TRUE; break; } } if (is_deferred) { /* FIXME should error if it's null */ if (proc_dsh->dsh_qp_ptr->qp_setInput != NULL) STRUCT_ASSIGN_MACRO(qef_rcb->qef_setInputId, * (DB_TAB_ID *)(proc_dsh->dsh_row[proc_dsh->dsh_qp_ptr-> qp_setInput->vl_tab_id_index])); } } while (FALSE); if (need_cleanup) { /* error in a nested DB procedure, abort up to the beginning of the ** procedure if there are no other cursors opened. We ** guarantee that by decrementing the qef_open_count. If the ** count becomes zero, qeq_cleanup will abort to the last internal ** savepoint. Fix for bug 63465. */ savestat = status; open_count = qef_cb->qef_open_count; while (qef_cb->qef_open_count > 0) qef_cb->qef_open_count--; status = qeq_cleanup(qef_rcb, status, need_release); status = savestat; qef_cb->qef_open_count = open_count; qef_cb->qef_dsh = (PTR) call_dsh; qef_rcb->qef_context_cnt--; qef_rcb->qef_pcount = call_dsh->dsh_saved_rcb->qef_pcount; qef_rcb->qef_usr_param = call_dsh->dsh_saved_rcb->qef_usr_param; qef_rcb->qef_qp = call_dsh->dsh_saved_rcb->qef_qp; qef_rcb->qef_qso_handle = call_dsh->dsh_saved_rcb->qef_qso_handle; call_dsh->dsh_qef_rowcount = call_dsh->dsh_saved_rcb->qef_rowcount; call_dsh->dsh_qef_targcount = call_dsh->dsh_saved_rcb->qef_targcount; call_dsh->dsh_qef_output = call_dsh->dsh_saved_rcb->qef_output; call_dsh->dsh_qef_count = call_dsh->dsh_saved_rcb->qef_count; } return (status); }
/*{ ** Name: qeu_dsecalarm - Drop single or all alarm definition. ** ** External QEF call: status = qef_call(QEU_DSECALM, &qeuq_cb); ** ** Description: ** Drop the alarm tuple, the alarm text from the appropriate tables ** (iisecalarm, iiqrytext and update the table "relstat" field. An ** alarm can be dropped either by name (when the DROP SECURITY_ALARM ** statement is issued) or by object id (when its associated object ** is dropped). ** ** When originating from the DROP SECURITY_ALARM statement the single ** alarm tuple is deleted based on its name - provided in the ** qeuq_uld_tup parameter. In this case the single alarm is fetched ** (to collect the text, table id) and deleted. If it wasn't ** found then an error is returned. ** ** When originating from a DROP TABLE statement (this is similar to ** the DROP INTEGRITY ON table ALL), all tuples that satisfy the ** table-id are fetched (to collect their text ids) and dropped. ** If none are found no error is returned. ** ** For each alarm that is dropped the text tuples are ** also dropped based on the ids collected from the fetched alarm. ** ** The way this routine works is the following: ** ** set up QEU CB's for iisecalarm, iiqrytext and open tables; ** if (DROP SECURITY_ALARM) then ** set up iisecalarm "qualified" name and owner; ** else ** set up iisecalarm "keyed" on DROP object id; ** endif; ** for (all alarm tuples found) loop ** get alarm tuple; ** if (not found) then ** if (DROP SECURITY_ALARM) then ** error - alarm does not exist; ** break; ** else ** clear error; ** break; ** endif; ** endif; ** set up iiqrytext keys based on alarm text id; ** for (all text tuples found) loop ** get text tuple; ** delete text tuple; ** endloop; ** delete current alarm tuple; ** if (DROP SECURITY_ALARM) then ** endloop; ** endif; ** endloop; ** close tables; ** ** Inputs: ** qef_cb QEF session control block ** qeuq_cb ** .qeuq_eflag Designate error handling for user errors. ** QEF_INTERNAL Return error code. ** QEF_EXTERNAL Send message to user. ** .qeuq_rtbl Table id of alarm - if DROP TABLE. If DROP ** SECURITY_ALARM then this is ignored. ** .qeuq_cr Must be 1 if DROP SECURITY_ALARM, 0 ** if DROP TABLE. ** .qeuq_uld_tup Alarm tuple to be deleted - if DROP ** SECURITY_ALARM, otherwise this is ignored: ** .dba_alarmname alarm name *or* ** .dba_alarmno Alarm number ** .qeuq_db_id Database id. ** .qeuq_d_id DMF session id. ** from_drop_alarm TRUE if called from DROP SECURITY_ALARM ** ** Outputs: ** qeuq_cb ** .error.err_code E_QE0002_INTERNAL_ERROR ** E_QE0017_BAD_CB ** E_QE0018_BAD_PARAM_IN_CB ** E_QE0022_ABORTED ** Returns: ** E_DB_{OK, WARN, ERROR, FATAL} ** Exceptions: ** none ** ** History: ** 26-nov-93 (robf) ** Written for Secure 2.0 ** 30-dec-93 (robf) ** Don't write audit records if called implicitly during drop ** of a table. ** 16-feb-94 (robf) ** Check DROP ALL flag from qeuq_cb.qeuq_permit_mask & QEU_DROP_ALL, ** so we loop appropriately when there are several alarms on ** the object to be dropped. */ DB_STATUS qeu_dsecalarm( QEF_CB *qef_cb, QEUQ_CB *qeuq_cb, bool from_drop_alarm) { QEU_CB tranqeu; /* For transaction request */ bool transtarted = FALSE; QEU_CB aqeu; /* For iisecalarm table */ QEF_DATA aqef_data; DB_SECALARM *atuple_name; /* Input tuple with name or id */ DB_SECALARM atuple; /* Tuple currently being deleted */ bool alarm_opened = FALSE; DMR_ATTR_ENTRY akey_array[3]; DMR_ATTR_ENTRY *akey_ptr_array[3]; QEU_CB qqeu; /* For iiqrytext table */ QEU_QUAL_PARAMS qparams; DB_IIQRYTEXT qtuple; QEF_DATA qqef_data; bool qtext_opened = FALSE; DMR_ATTR_ENTRY qkey_array[2]; DMR_ATTR_ENTRY *qkey_ptr_array[2]; bool drop_specific_alarm; /* TRUE if dropping a specific ** alarm */ char obj_type; char *alarm_name; DB_STATUS status, local_status; i4 error; DB_ERROR e_error; SXF_ACCESS access; SXF_EVENT evtype; DB_OWN_NAME objowner; for (;;) /* Dummy for loop for error breaks */ { MEfill(sizeof(objowner),' ',(PTR)&objowner); /* Validate CB and parameters */ if (qeuq_cb->qeuq_type != QEUQCB_CB || qeuq_cb->qeuq_length != sizeof(QEUQ_CB)) { status = E_DB_ERROR; error = E_QE0017_BAD_CB; break; } if ( (qeuq_cb->qeuq_rtbl == NULL && qeuq_cb->qeuq_cr == 0) || (qeuq_cb->qeuq_db_id == NULL) || (qeuq_cb->qeuq_d_id == 0)) { status = E_DB_ERROR; error = E_QE0018_BAD_PARAM_IN_CB; break; } drop_specific_alarm = from_drop_alarm; /* ** If passed DROP ALL then not dropping specific alarm */ if(qeuq_cb->qeuq_permit_mask & QEU_DROP_ALL) drop_specific_alarm=FALSE; /* ** Check to see if transaction is in progress, if so set a local ** transaction, otherwise we'll use the user's transaction. */ if (qef_cb->qef_stat == QEF_NOTRAN) { tranqeu.qeu_type = QEUCB_CB; tranqeu.qeu_length = sizeof(QEUCB_CB); tranqeu.qeu_db_id = qeuq_cb->qeuq_db_id; tranqeu.qeu_d_id = qeuq_cb->qeuq_d_id; tranqeu.qeu_flag = 0; tranqeu.qeu_mask = 0; status = qeu_btran(qef_cb, &tranqeu); if (status != E_DB_OK) { error = tranqeu.error.err_code; break; } transtarted = TRUE; } /* Escalate the transaction to MST */ if (qef_cb->qef_auto == QEF_OFF) qef_cb->qef_stat = QEF_MSTRAN; /* Open iisecalarm, iiqrytext tables */ aqeu.qeu_type = QEUCB_CB; aqeu.qeu_length = sizeof(QEUCB_CB); aqeu.qeu_db_id = qeuq_cb->qeuq_db_id; aqeu.qeu_lk_mode = DMT_IX; aqeu.qeu_flag = DMT_U_DIRECT; aqeu.qeu_access_mode = DMT_A_WRITE; aqeu.qeu_mask = 0; STRUCT_ASSIGN_MACRO(aqeu, qqeu); /* Quick initialization */ /* Open iisecalarm */ aqeu.qeu_tab_id.db_tab_base = DM_B_IISECALARM_TAB_ID; aqeu.qeu_tab_id.db_tab_index = DM_I_IISECALARM_TAB_ID; status = qeu_open(qef_cb, &aqeu); if (status != E_DB_OK) { error = aqeu.error.err_code; break; } alarm_opened = TRUE; qqeu.qeu_tab_id.db_tab_base = DM_B_QRYTEXT_TAB_ID; /* Open iiqrytext */ qqeu.qeu_tab_id.db_tab_index = DM_I_QRYTEXT_TAB_ID; status = qeu_open(qef_cb, &qqeu); if (status != E_DB_OK) { error = qqeu.error.err_code; break; } qtext_opened = TRUE; aqeu.qeu_count = 1; /* Initialize alarm-specific qeu */ aqeu.qeu_tup_length = sizeof(DB_SECALARM); aqeu.qeu_output = &aqef_data; aqef_data.dt_next = NULL; aqef_data.dt_size = sizeof(DB_SECALARM); aqef_data.dt_data = (PTR)&atuple; qqeu.qeu_count = 1; /* Initialize qtext-specific qeu */ qqeu.qeu_tup_length = sizeof(DB_IIQRYTEXT); qqeu.qeu_output = &qqef_data; qqef_data.dt_next = NULL; qqef_data.dt_size = sizeof(DB_IIQRYTEXT); qqef_data.dt_data = (PTR)&qtuple; /* ** If DROP SECURITY_ALARM then position iisecalarm table based on ** alarm name or numbr ** and drop the specific alarm (if we can't find it issue an error). ** Positioning is done via qeu_qalarm_by_name/id. ** If DROP TABLE then fetch and drop ALL alarms applied to the table. */ aqeu.qeu_getnext = QEU_REPO; if (from_drop_alarm) { /* ** Might be scanning for database/installation alarms ** or special DROP ALL processing. */ atuple_name = (DB_SECALARM *)qeuq_cb->qeuq_uld_tup->dt_data; alarm_name=(char*)&atuple_name->dba_alarmname; /* ** alarmno -1 indicates all alarms when qualifying */ if(qeuq_cb->qeuq_permit_mask & QEU_DROP_ALL) atuple_name->dba_alarmno= -1; /* Get alarm that matches alarm name (qualified) */ qparams.qeu_qparms[0] = (PTR) atuple_name; aqeu.qeu_klen = 0; /* Not keyed */ aqeu.qeu_qual = qeu_qalarm_by_name; aqeu.qeu_qarg = &qparams; } else /* DROP TABLE */ { /* Get alarm that applies to specific table id (keyed) */ obj_type=DBOB_TABLE; alarm_name="unknown"; aqeu.qeu_klen = 3; aqeu.qeu_key = akey_ptr_array; akey_ptr_array[0] = &akey_array[0]; akey_ptr_array[1] = &akey_array[1]; akey_ptr_array[2] = &akey_array[2]; akey_ptr_array[0]->attr_number = DM_1_IISECALARM_KEY; akey_ptr_array[0]->attr_operator = DMR_OP_EQ; akey_ptr_array[0]->attr_value = (char*)&obj_type; akey_ptr_array[1]->attr_number = DM_2_IISECALARM_KEY; akey_ptr_array[1]->attr_operator = DMR_OP_EQ; akey_ptr_array[1]->attr_value = (char *)&qeuq_cb->qeuq_rtbl->db_tab_base; akey_ptr_array[2]->attr_number = DM_3_IISECALARM_KEY; akey_ptr_array[2]->attr_operator = DMR_OP_EQ; akey_ptr_array[2]->attr_value = (char *)&qeuq_cb->qeuq_rtbl->db_tab_index; aqeu.qeu_qual = NULL; aqeu.qeu_qarg = NULL; } for (;;) /* For all alarm tuples found */ { status = qeu_get(qef_cb, &aqeu); if (status != E_DB_OK) { if (aqeu.error.err_code == E_QE0015_NO_MORE_ROWS) { if (drop_specific_alarm) { (VOID)qef_error(E_US2473_9331_ALARM_ABSENT, 0L, E_DB_ERROR, &error, &qeuq_cb->error, 1, qec_trimwhite(sizeof(atuple_name->dba_alarmname), alarm_name), (PTR)alarm_name); error = E_QE0000_OK; status=E_DB_OK; } else /* No [more] alarms for table */ { error = E_QE0000_OK; status = E_DB_OK; } } else /* Other error */ { error = aqeu.error.err_code; } break; } /* If no alarms found */ aqeu.qeu_getnext = QEU_NOREPO; aqeu.qeu_klen = 0; status = E_DB_OK; /* Postion iiqrytxt table for query id associated with this alarm */ qkey_ptr_array[0] = &qkey_array[0]; qkey_ptr_array[1] = &qkey_array[1]; qqeu.qeu_getnext = QEU_REPO; qqeu.qeu_klen = 2; qqeu.qeu_key = qkey_ptr_array; qkey_ptr_array[0]->attr_number = DM_1_QRYTEXT_KEY; qkey_ptr_array[0]->attr_operator = DMR_OP_EQ; qkey_ptr_array[0]->attr_value = (char *)&atuple.dba_txtid.db_qry_high_time; qkey_ptr_array[1]->attr_number = DM_2_QRYTEXT_KEY; qkey_ptr_array[1]->attr_operator = DMR_OP_EQ; qkey_ptr_array[1]->attr_value = (char *)&atuple.dba_txtid.db_qry_low_time; qqeu.qeu_qual = NULL; qqeu.qeu_qarg = NULL; for (;;) /* For all query text tuples */ { status = qeu_get(qef_cb, &qqeu); if (status != E_DB_OK) { error = qqeu.error.err_code; break; } qqeu.qeu_klen = 0; qqeu.qeu_getnext = QEU_NOREPO; status = qeu_delete(qef_cb, &qqeu); if (status != E_DB_OK) { error = qqeu.error.err_code; break; } } /* For all query text tuples */ if (error != E_QE0015_NO_MORE_ROWS) break; if(atuple.dba_objtype==DBOB_TABLE) { DMT_CHAR_ENTRY char_spec; DMT_CB dmt_cb; /* ** Alter the table relstat to flag alarms. This ** validates that the table exists and ensures that we ** get an exclusive lock on it. */ char_spec.char_id = DMT_C_ALARM; char_spec.char_value = DMT_C_ON; MEfill(sizeof(DMT_CB), 0, (PTR) &dmt_cb); dmt_cb.dmt_flags_mask = 0; dmt_cb.dmt_db_id = qeuq_cb->qeuq_db_id; dmt_cb.dmt_char_array.data_in_size = sizeof(DMT_CHAR_ENTRY); dmt_cb.dmt_char_array.data_address = (PTR)&char_spec; dmt_cb.length = sizeof(DMT_CB); dmt_cb.type = DMT_TABLE_CB; dmt_cb.dmt_id.db_tab_base = atuple.dba_objid.db_tab_base; dmt_cb.dmt_id.db_tab_index = atuple.dba_objid.db_tab_index; dmt_cb.dmt_tran_id = qef_cb->qef_dmt_id; status = dmf_call(DMT_ALTER, &dmt_cb); if (status != E_DB_OK) { error = dmt_cb.error.err_code; if (error == E_DM0054_NONEXISTENT_TABLE) { error = E_QE0025_USER_ERROR; status = E_DB_OK; /* Still remove the alarm */ } else { /* ** Some other error */ break; } } } else if(!(atuple.dba_flags&DBA_ALL_DBS)) { /* ** Check access to the database, also get the security label ** for later use */ status=qeu_db_exists(qef_cb, qeuq_cb, (DB_DB_NAME *)&atuple.dba_objname, SXF_A_CONTROL, &objowner); if(status==E_DB_ERROR) { /* Error, no access to database */ break; } else if (status==E_DB_WARN) { /* Database not found */ status=E_DB_ERROR; /* E_US2474_9332_ALARM_NO_DB */ (VOID)qef_error(9332, 0L, E_DB_ERROR, &error, &qeuq_cb->error, 1, qec_trimwhite(sizeof(atuple.dba_objname), (char *)&atuple.dba_objname), (PTR)&atuple.dba_objname); break; } } /* Now delete the current alarm tuple */ status = qeu_delete(qef_cb, &aqeu); if (status != E_DB_OK) { error = aqeu.error.err_code; break; } /* ** If doing a specific DROP SECURITY_ALARM we're done with this ** loop. ** Otherwise continue with next alarm applied to table. */ if (drop_specific_alarm) break; } /* For all alarm found */ if (status != E_DB_OK) break; break; } /* End dummy for loop */ /* Handle any error messages */ if (status != E_DB_OK) (VOID) qef_error(error, 0L, status, &error, &qeuq_cb->error, 0); /* Close off all the tables and transaction */ if (alarm_opened) { local_status = qeu_close(qef_cb, &aqeu); if (local_status != E_DB_OK) { (VOID) qef_error(aqeu.error.err_code, 0L, local_status, &error, &qeuq_cb->error, 0); if (local_status > status) status = local_status; } } if (qtext_opened) { local_status = qeu_close(qef_cb, &qqeu); if (local_status != E_DB_OK) { (VOID) qef_error(qqeu.error.err_code, 0L, local_status, &error, &qeuq_cb->error, 0); if (local_status > status) status = local_status; } } if (transtarted) { if (status == E_DB_OK) local_status = qeu_etran(qef_cb, &tranqeu); else local_status = qeu_atran(qef_cb, &tranqeu); if (local_status != E_DB_OK) { (VOID) qef_error(tranqeu.error.err_code, 0L, local_status, &error, &qeuq_cb->error, 0); if (local_status > status) status = local_status; } } /* ** Dropping an alarm is a control operation on the base object ** (database/table). */ if( from_drop_alarm==TRUE && Qef_s_cb->qef_state & QEF_S_C2SECURE ) { if(atuple.dba_objtype==DBOB_DATABASE) { evtype=SXF_E_DATABASE; /* ** Database label/owner should be set in db_exists request above */ } else { evtype=SXF_E_TABLE; } if(status==E_DB_OK) access=(SXF_A_CONTROL|SXF_A_SUCCESS); else access=(SXF_A_CONTROL|SXF_A_FAIL); if(qeu_secaudit(FALSE, qef_cb->qef_ses_id, (char *)&atuple.dba_objname, &objowner, sizeof(atuple.dba_objname), evtype, I_SX202E_ALARM_DROP, access, &e_error)!=E_DB_OK) { error = e_error.err_code; status=E_DB_ERROR; } } if(status!=E_DB_OK) { (VOID) qef_error(E_QE028C_DROP_ALARM_ERR, 0L, local_status, &error, &qeuq_cb->error, 0); qeuq_cb->error.err_code= E_QE0025_USER_ERROR; } return (status); } /* qeu_dsecalarm */
/*{ ** Name: QEU_APPEND - append rows to table ** ** External QEF call: status = qef_call(QEU_APPEND, &qeu_cb); ** ** Description: ** This routine appends N tuples to an opened table. The table ** must have been opened with the QEU_OPEN command. This operation ** is valid only in an internal transaction (see QET.C). ** ** 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_count number of tuples to append ** .qeu_tup_length lenth of each tuple ** .qeu_input input buffer ** ** ** Outputs: ** qeu_cb ** .qeu_count Number of tuples appended ** .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 ** 14-jul-93 (ed) ** replacing <dbms.h> by <gl.h> <sl.h> <iicommon.h> <dbdbms.h> ** 26-jul-93 (walt) ** Initialize the local variable "status" in qeu_append to E_DB_OK. ** If there are no rows to append it's possible to hit the closing ** return(status) statement without ever assigning status a ** non-garbage value. ** 01-feb-94 (stial01) ** BUG 66409: copy from is hanging if DM0151_SI_DUPLICATE_KEY_STMT, ** If this error occurs process it like the other duplicate errors. */ DB_STATUS qeu_append( QEF_CB *qef_cb, QEU_CB *qeu_cb) { i4 err; DMR_CB dmr_cb; i4 count; /* number of tuples to appended */ DB_STATUS status = E_DB_OK; QEF_DATA *dataptr; i4 i; i4 num_appended; /* number of tuples appended */ count = qeu_cb->qeu_count; qeu_cb->qeu_count = 0; /* QEU_APPEND 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_flags_mask = 0; dmr_cb.dmr_access_id = qeu_cb->qeu_acc_id; dmr_cb.dmr_tid = 0; /* not used */ dataptr = qeu_cb->qeu_input; /* start appending rows */ num_appended = 0; for (i = 0; i < count; i++) { dmr_cb.dmr_data.data_address = dataptr->dt_data; dmr_cb.dmr_data.data_in_size = dataptr->dt_size; status = dmf_call(DMR_PUT, &dmr_cb); if (status != E_DB_OK) { /* *** FIXME *** This is insanely stupid -- dup rows/keys ** are just ignored. That was bad enough for COPY FROM, ** which no longer comes here, but it seems that a bunch of ** the QEU hurlers EXPECT a silent success on dup key/row. ** Someday, root that crap out, and allow this routine to ** treat errors in some rational manner... */ if (dmr_cb.error.err_code == E_DM0046_DUPLICATE_RECORD || dmr_cb.error.err_code == E_DM0045_DUPLICATE_KEY || dmr_cb.error.err_code == E_DM0048_SIDUPLICATE_KEY || dmr_cb.error.err_code == E_DM0150_DUPLICATE_KEY_STMT || dmr_cb.error.err_code == E_DM0151_SIDUPLICATE_KEY_STMT) { status = E_DB_OK; qeu_cb->error.err_code = dmr_cb.error.err_code; } else { qef_error(dmr_cb.error.err_code, 0L, status, &err, &qeu_cb->error, 0); return (status); } } else { /* successful append */ num_appended++; } /* next next record */ dataptr = dataptr->dt_next; } /* tell user how many rows were appended */ qeu_cb->qeu_count = num_appended; return (status); }
/* ** Name: qeu_db_exists ** ** Description: ** Checks whether a particular database exists, including MAC ** access where appropriate. Denied access due to MAC will be ** audited here, and a no-such-database error returned to the ** caller. Successfull access should be audited by the caller. ** ** Inputs: ** dbname - Database name to check ** ** access - SXF-access on the database ** ** Outputs: ** dbowner - Owner of database ** ** Returns: ** E_DB_OK - Exists ** E_DB_WARN - Doesn't exists ** (error) - Something went wrong ** ** History: ** 3-dec-93 (robf) ** Created */ DB_STATUS qeu_db_exists(QEF_CB * qef_cb, QEUQ_CB *qeuq_cb, DB_DB_NAME *dbname, i4 access, DB_OWN_NAME *dbowner) { DB_STATUS status=E_DB_OK; bool tbl_opened=FALSE; bool loop=FALSE; DU_DATABASE dbtuple; bool not_found=TRUE; i4 error=0; QEU_CB qeu; QEF_DATA qef_data; DMR_ATTR_ENTRY key_array[1]; DMR_ATTR_ENTRY *key_ptr_array[1]; DB_ERROR err_blk; do { qeu.qeu_type = QEUCB_CB; qeu.qeu_length = sizeof(QEUCB_CB); qeu.qeu_tab_id.db_tab_base = DM_B_DATABASE_TAB_ID; qeu.qeu_tab_id.db_tab_index = DM_I_DATABASE_TAB_ID; qeu.qeu_db_id = qeuq_cb->qeuq_db_id; qeu.qeu_lk_mode = DMT_IS; qeu.qeu_access_mode = DMT_A_READ; qeu.qeu_flag = 0; qeu.qeu_mask = 0; status = qeu_open(qef_cb, &qeu); if (status != E_DB_OK) { error = E_QE022D_IIDATABASE; status = (status > E_DB_SEVERE) ? status : E_DB_SEVERE; break; } tbl_opened = TRUE; qeu.qeu_count = 1; qeu.qeu_tup_length = sizeof(DU_DATABASE); qeu.qeu_output = &qef_data; qef_data.dt_next = 0; qef_data.dt_size = sizeof(DU_DATABASE); qef_data.dt_data = (PTR)&dbtuple; qeu.qeu_getnext = QEU_REPO; qeu.qeu_klen = 1; key_ptr_array[0]= &key_array[0]; qeu.qeu_key = key_ptr_array; key_ptr_array[0]->attr_number = DM_1_DATABASE_KEY; key_ptr_array[0]->attr_operator = DMR_OP_EQ; key_ptr_array[0]->attr_value = (char *) dbname; qeu.qeu_qual = 0; qeu.qeu_qarg = 0; status = qeu_get(qef_cb, &qeu); if (((status != E_DB_OK) && (qeu.error.err_code != E_QE0015_NO_MORE_ROWS)) || ((status == E_DB_OK) && (qeu.qeu_count != 1)) ) { error = E_QE022D_IIDATABASE; status = (status > E_DB_SEVERE) ? status : E_DB_SEVERE; break; } if (status != E_DB_OK) { not_found=TRUE; status=E_DB_OK; } else { not_found=FALSE; } status = qeu_close(qef_cb, &qeu); tbl_opened = FALSE; if (status != E_DB_OK) { error = E_QE022D_IIDATABASE; status = (status > E_DB_SEVERE) ? status : E_DB_SEVERE; break; } /* ** Check MAC access to the database, if we found it. */ if(not_found==TRUE) break; if(dbowner) STRUCT_ASSIGN_MACRO(dbtuple.du_own, *dbowner); } while(loop); if(tbl_opened) { (VOID) qeu_close(qef_cb, &qeu); } if(not_found && status==E_DB_OK) status=E_DB_WARN; if(error) { (VOID) qef_error(error, 0L, status, &error, &qeuq_cb->error, 0); } return status; }
/* ** Name: qeu_gen_alarm_name ** ** Description: ** Generates a default alarm name when none has been specified ** ** Name will consist of a $ followed by first 5 chars of the object name ** (blank padded if necessary), followed by _X_ where X is D or T ** followed by the hex representation of the alarm id. Before ** returning to the caller, we will call cui_idxlate() to convert name to ** the case appropriate for the database to which we are connected. ** ** Inputs: ** obj_name - Object name ** ** obj_type - Object type ** ** qef_rcb - RCB ** ** alarm_name - Where to put result. ** ** alarm_id - Unique id for number. ** ** Outputs: ** ** alarm_name - Name ** ** History: ** 26-nov-93 (robf) ** Created ** 2-Dec-2010 (kschendel) SIR 124685 ** Warning fixes, CMcpychar not to be used with single letter ** ascii constants. (array out of bounds warnings.) */ static DB_STATUS qeu_gen_alarm_name( i4 obj_type, char *obj_name, QEF_RCB *qef_rcb, DB_TAB_ID *alarm_id, char *alarm_name, i4 *err_code ) { DB_STATUS status = E_DB_OK; QEF_CB *qef_cb = qef_rcb->qef_cb; u_i4 cui_flags = ( * ( qef_cb->qef_dbxlate ) ) | CUI_ID_DLM | CUI_ID_NORM; u_i4 ret_mode; u_i4 len_untrans, len_trans = DB_ALARM_MAXNAME; u_char untrans_str[DB_ALARM_MAXNAME]; i4 j; char *p = (char *) untrans_str; char *limit; char id_str[20], *id_p = id_str; DB_ERROR err_blk; *p++ = '$'; for (j = 0; j < 5; j++) CMcpyinc(obj_name, p); *p++ = '_'; if(obj_type==DBOB_TABLE) *p++ = 'T'; else if(obj_type==DBOB_DATABASE) *p++ = 'D'; else { /* Unknown object type */ *err_code=E_QE0018_BAD_PARAM_IN_CB; return E_DB_ERROR; } *p++ = '_'; /* convert alarm id into a hex string */ seedToDigits(alarm_id, id_str, qef_rcb ); /* append id string to the name built so far */ for (; *id_p != EOS; CMcpyinc(id_p, p)) ; /* remember length of the name */ len_untrans = p - (char *) untrans_str; status = cui_idxlate(untrans_str, &len_untrans, (u_char *) alarm_name, &len_trans, cui_flags, &ret_mode, &qef_rcb->error); if (DB_FAILURE_MACRO(status)) { /* ** cui_idxlate errors have two params currently. ** We report here to avoid errors in generic code which ** doens't have params. */ (VOID) qef_error(qef_rcb->error.err_code, 0L, status, err_code, &err_blk, 2, sizeof(ERx("System generated alarm name"))-1, ERx("System generated alarm name"), len_untrans, untrans_str); /* Assume passed bad input */ *err_code=E_QE0018_BAD_PARAM_IN_CB; return status; } /* blank pad */ p = alarm_name + len_trans; limit = alarm_name + DB_ALARM_MAXNAME; while (p < limit) *p++ = ' '; return(E_DB_OK); }
/*{ ** Name: QEU_OPEN - open a table ** ** External QEF call: status = qef_call(QEU_OPEN, &qeu_cb); ** ** Description: ** A table is opened. A transaction must be in progress when ** this routine is called. This routine must be called before any ** of qeu_delete, qeu_append or qeu_get is called. ** Tables are opened without DMT_NOWAIT being set and are opened for ** direct update. ** ** Inputs: ** qeu_cb ** .qeu_flag zero or QEU_SHOW_STAT ** indicates if internal request for ** statistics. ** .qeu_eflag designate error handling semantis ** for user errors. ** QEF_INTERNAL return error code. ** QEF_EXTERNAL send message to user. ** .qeu_tab_id table id ** .qeu_db_id database id ** .qeu_lk_mode lock mode ** DMT_X exclusive table lock ** DMT_S shared table lock ** DMT_IX exclusive page lock ** DMT_IS shared table lock ** DMT_SIX shared table lock with ability ** to exclusive lock pages ** .qeu_access_mode access mode ** DMT_A_READ ** DMT_A_WRITE ** ** Outputs: ** qeu_cb ** .qeu_acc_id table access id ** .error.err_code One of the following ** E_QE0000_OK ** E_QE0002_INTERNAL_ERROR ** E_QE0004_NO_TRANSACTION ** E_QE0017_BAD_CB ** E_QE0018_BAD_PARAM_IN_CB ** E_QE0022_ABORTED ** <DMF error messages> ** 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 ** 18-jul-89 (jennifer) ** Added a flag to indicate that an internal request ** for statistical information is being requested. ** This solves a B1 security problem where statistics ** could be unpredicatable if B1 labels were checked. ** For an internal request they aren't checked, for a ** normal query on the iihistogram and iistatistics ** table they are checked. ** 23-jan-91 (seputis) ** added support for timeout and maxlocks ** 25-mar-99 (shust01) ** Initialized dmt_mustlock. On rare occasions storage happened ** to be equal to a 1 (TRUE), causing locks to be taken out even ** though readlock=nolock was set. ** 07-mar-2000 (gupsh01) ** Do not handle error E_DM006A_TRAN_ACCESS_CONFLICT here as it will ** be handled by the calling facility. (BUG 100777). ** 14-feb-03 (inkdo01) ** Special check for non-existant iisequence catalog, so message ** can be issued that database doesn't support sequences. ** */ DB_STATUS qeu_open( QEF_CB *qef_cb, QEU_CB *qeu_cb) { DMT_CB dmt_cb; DB_STATUS status; i4 err; DMT_CHAR_ENTRY lockmode[2]; i4 lockcount; MEfill(sizeof(DMT_CB), 0, (PTR) &dmt_cb); dmt_cb.type = DMT_TABLE_CB; dmt_cb.length = sizeof(DMT_CB); dmt_cb.dmt_db_id = qeu_cb->qeu_db_id; STRUCT_ASSIGN_MACRO(qeu_cb->qeu_tab_id, dmt_cb.dmt_id); dmt_cb.dmt_flags_mask = 0; if (qeu_cb->qeu_flag & QEU_SHOW_STAT) dmt_cb.dmt_flags_mask |= DMT_SHOW_STAT; if (qeu_cb->qeu_flag & QEU_BYPASS_PRIV) dmt_cb.dmt_flags_mask |= DMT_DBMS_REQUEST; dmt_cb.dmt_lock_mode = qeu_cb->qeu_lk_mode; dmt_cb.dmt_update_mode = DMT_U_DIRECT; dmt_cb.dmt_mustlock = FALSE; dmt_cb.dmt_access_mode = qeu_cb->qeu_access_mode; lockcount = 0; if (qeu_cb->qeu_mask & QEU_TIMEOUT) { lockmode[lockcount].char_id = DMT_C_TIMEOUT_LOCK; lockmode[lockcount].char_value = qeu_cb->qeu_timeout; lockcount++; } if (qeu_cb->qeu_mask & QEU_MAXLOCKS) { lockmode[lockcount].char_id = DMT_C_PG_LOCKS_MAX; lockmode[lockcount].char_value = qeu_cb->qeu_maxlocks; lockcount++; } if (lockcount > 0) { dmt_cb.dmt_char_array.data_address = (PTR)lockmode; dmt_cb.dmt_char_array.data_in_size = sizeof(lockmode[0]) * lockcount; dmt_cb.dmt_char_array.data_out_size = 0; } else dmt_cb.dmt_char_array.data_in_size = 0; dmt_cb.dmt_sequence = qef_cb->qef_stmt; /* QEU_OPEN 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); } dmt_cb.dmt_tran_id = qef_cb->qef_dmt_id; status = dmf_call(DMT_OPEN, &dmt_cb); if (status == E_DB_OK) { qeu_cb->qeu_acc_id = dmt_cb.dmt_record_access_id; qef_cb->qef_open_count++; } else { /* ** Do not handle the dmf error E_DM006A_TRAN_ACCESS_CONFLICT here ** as it is being handled by the calling facility BUG: 100777 **/ if (dmt_cb.error.err_code == E_DM006A_TRAN_ACCESS_CONFLICT) { qeu_cb->error.err_code = dmt_cb.error.err_code; qeu_cb->error.err_data = dmt_cb.error.err_data; } else if (dmt_cb.error.err_code == E_DM0054_NONEXISTENT_TABLE && qeu_cb->qeu_tab_id.db_tab_base == DM_B_SEQ_TAB_ID) qef_error(E_QE00A1_IISEQ_NOTDEFINED, 0L, status, &err, &qeu_cb->error, 0); else qef_error(dmt_cb.error.err_code, 0L, status, &err, &qeu_cb->error, 0); } return (status); }
/*{ ** Name: QEU_GET - get tuples from an open table ** ** External QEF call: status = qef_call(QEU_GET, &qeu_cb); ** ** Description: ** Tuples are retrieved from an open table. ** ** 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 length of retrieved tuple ** .qeu_count number of tuples to retrieve ** .qeu_getnext reposition ** QEU_REPO repostion using key ** QEU_NOREPO continue from previous call to ** this routine ** .qeu_klen length of key - number of entries ** .qeu_key key for retrieve ** .qeu_qual qualification function ** .qeu_qarg argument to qualification function ** .qeu_flag operation qualifier ** QEU_BY_TID get tuple by TID - will only be ** considered if !QEU_REPO ** .qeu_tid contains TID of the tuple to be ** retrieved ** .qeu_output output buffer ** <qeu_key> is a pointer to an array of pointers of type DMR_ATTR_ENTRY ** .attr_number ** .attr_operation ** .attr_value_ptr ** ** 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 ** E_QE0015_NO_MORE_ROWS ** E_QE0022_ABORTED ** E_QE0015_NO_MORE_ROWS ** .qeu_output output buffer ** Returns: ** E_DB_OK ** E_DB_WARN ** E_DB_ERROR caller error ** E_DB_FATAL internal error ** Exceptions: ** none ** ** Side Effects: ** the output buffers are filled in ** ** History: ** 27-may-86 (daved) ** written ** 31-jul-86 (jennifer) ** Modified qeu_get to not allocate output ** from memory stream, but to assume output ** array is already initialized. ** 20-aug-86 (jennifer) ** When dmf returns nonext, then qef must ** return no-more-rows. ** 10-oct-87 (puree) ** Same as above even during positioning. ** 04-jan-90 (andre) ** return tid of the last tuple which was successfully read in ** QU_CB->qeu_tid ** 17-jun-92 (andre) ** add support for retrieval by TID - qeu_gentext should NOT be set to ** QEU_REPO ** 27-jul-96 (ramra01) ** Alter table project: Position only flag on qeu_get. ** 11-Apr-2008 (kschendel) ** Revised DMF qualification requirements, simplified for QEU. */ DB_STATUS qeu_get( QEF_CB *qef_cb, QEU_CB *qeu_cb) { i4 err; DMR_CB dmr_cb; i4 count; /* number of tuples returned */ i4 i; DB_STATUS status; PTR tuple; QEF_DATA *dataptr; count = qeu_cb->qeu_count; /* number of rows to get */ qeu_cb->qeu_count = 0; /* QEU_GET 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_tid = 0; /* not used */ dmr_cb.dmr_q_fcn = NULL; /* if positioning the cursor */ if (qeu_cb->qeu_getnext == QEU_REPO) { /* if there is a key, position by qual. Else, position all records */ if (qeu_cb->qeu_klen == 0) dmr_cb.dmr_position_type = DMR_ALL; else { /* 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) { if (dmr_cb.error.err_code == E_DM0055_NONEXT) qeu_cb->error.err_code = E_QE0015_NO_MORE_ROWS; else { qef_error(dmr_cb.error.err_code, 0L, status, &err, &qeu_cb->error, 0); } return (status); } } if (qeu_cb->qeu_flag & QEU_POSITION_ONLY) return (E_DB_OK); /* We can now start getting records */ /* point to space for the first tuple */ /* the tuple length will not change. Tell DMF about it */ dmr_cb.dmr_data.data_in_size = qeu_cb->qeu_tup_length; /* assign the beginning of the output chain */ dataptr = qeu_cb->qeu_output; tuple = dataptr->dt_data; i = 0; /* ** if qeu_getnexdt was not set to QEU_REPO and QEU_BY_TID was set in ** qeu_flag, tell dmr_get() to get a tuple with specified TID; otherwise ** tell it to get the next row */ if (qeu_cb->qeu_getnext != QEU_REPO && 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_NEXT; } for (;;) { /* get the tuple */ dmr_cb.dmr_data.data_address = tuple; status = dmf_call(DMR_GET, &dmr_cb); if (status != E_DB_OK) { if (dmr_cb.error.err_code == E_DM0055_NONEXT) { qeu_cb->error.err_code = E_QE0015_NO_MORE_ROWS; break; } else { qef_error(dmr_cb.error.err_code, 0L, status, &err, &qeu_cb->error, 0); return (status); } } /* save TID of the last tuple read */ qeu_cb->qeu_tid = dmr_cb.dmr_tid; /* ** get space for next tuple - if retrieving by TID we never want to get ** more than one tuple */ if (++i < count && dmr_cb.dmr_flags_mask != DMR_BY_TID) { /* move to next entry in the output chain */ dataptr = dataptr->dt_next; tuple = dataptr->dt_data; } else break; } /* assign output value */ qeu_cb->qeu_count = i; return (status); }
/*{ ** 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_devent - Drop an event definition. ** ** External QEF call: status = qef_call(QEU_DEVENT, &qeuq_cb); ** ** Description: ** Drop the event tuple and the event text from the appropriate ** tables (iievent and iiqrytext). An event may only be dropped ** by name as a result of the DROP EVENT statement. ** ** The single event tuple is deleted based on its name and owner (since ** the iievent table is hashed on name and owner this is a singleton ** keyed retrieval). If the event tuple wasn't fetched, then an error ** is returned to the user. ** ** If the event was found then all permits applied to this event ** are dropped (using qeu_dprot with the dummy event/table ids and ** without a permit number to indicate ALL protection tuples). In ** this case qeu_dprot need not recheck that the event does exist. ** Note that the qeu_dprot routine will open and close iiqrytext ** to remove the text associated with the event permit. ** ** Following permit removal all query text tuples associated with the ** CREATE EVENT statement are removed from iiqrytext based on the ** query text ids in the fetched event tuple. ** ** Inputs: ** qef_cb QEF session control block ** qeuq_cb ** .qeuq_eflag Designate error handling for user errors. ** QEF_INTERNAL Return error code. ** QEF_EXTERNAL Send message to user. ** .qeuq_culd Number of event tuples. Must be 1. ** .qeuq_uld_tup Event tuple: ** .dbe_name Event name. ** .dbe_owner Event owner. ** .dbe_type Event type - ignored until there are more. ** Remaining fields are assigned and used here. ** .qeuq_db_id Database id. ** .qeuq_d_id DMF session id. ** ** Outputs: ** qeuq_cb ** .error.err_code E_QE0002_INTERNAL_ERROR ** E_QE0017_BAD_CB ** E_QE0018_BAD_PARAM_IN_CB ** E_QE0022_ABORTED ** E_QE020B_EVENT_ABSENT (ret E_QE0025_USER_ERROR) ** Returns: ** E_DB_{OK, WARN, ERROR, FATAL} ** Exceptions: ** none ** ** History: ** 28-aug-89 (neil) ** Written for Terminator II/alerters. ** 09-feb-90 (neil) ** Added auditing functionality. ** 03-mar-90 (neil) ** Modify interface to que_dprot to indicate from DROP EVENT. ** 24-jun-92 (andre) ** after deleting IIEVENT tuple, call qeu_d_cascade to handle ** destruction of IIPROTECT, IIQRYTEXT tuples and marking dependent ** dbprocs dormant ** 08-sep-92 (andre) ** before calling qeu_d_cascade(), reset QEU_DROP_TEMP_TABLE in ** qeuq_flag_mask ** 24-jun-93 (robf) ** Perform MAC access check prior to drop of event. If no access is ** allowed then treat as non-existent event. ** 10-sep-93 (andre) ** before calling qeu_d_cascade(), set QEU_FORCE_QP_INVALIDATION in ** qeuq_flag_mask ** 21-sep-93 (stephenb) ** Replace generic I_SX2032_EVENT_ACCESS with I_SX203C_EVENT_DROP. ** 08-oct-93 (andre) ** qeu_d_cascade() expects one more parameter - an address of a ** DMT_TBL_ENTRY describing table/view/index being dropped; for all ** other types of objects, NULL must be passed ** 14-oct-93 (robf) ** Make sure access check is on tuple being deleted, not input tuple. ** 7-dec-93 (robf) ** Check if event is in used by an alarm, if so reject the operation. ** 7-jun-94 (robf) ** audit the security label for the event correctly on B1, this ** ensures level auditing picks up the change. (Previously we were ** auditing the input tuple security label, which was empty, ** not the delete tuple security label). Also don't try to ** but this makes the case clearer) ** 12-oct-94 (ramra01) ** Initialize variable local_status before use - 65258 ** 13-jun-96 (nick) ** Above change didn't actually work. ** */ DB_STATUS qeu_devent( QEF_CB *qef_cb, QEUQ_CB *qeuq_cb) { QEU_CB tranqeu; /* For transaction request */ bool transtarted = FALSE; QEU_CB evqeu; /* For iievent table */ QEF_DATA evqef_data; DB_IIEVENT *evtuple; /* Input tuple with name and owner */ DB_IIEVENT evtuple_del; /* Tuple currently being deleted */ bool event_opened = FALSE; DMR_ATTR_ENTRY evkey_array[2]; /* Key values from iievent */ DMR_ATTR_ENTRY *evkey_ptr_array[2]; DB_STATUS status; DB_STATUS local_status = E_DB_OK; i4 error; DB_ERROR err; for (;;) /* Dummy for loop for error breaks */ { /* Validate CB and parameters */ if (qeuq_cb->qeuq_type != QEUQCB_CB || qeuq_cb->qeuq_length != sizeof(QEUQ_CB)) { status = E_DB_ERROR; error = E_QE0017_BAD_CB; break; } if ( (qeuq_cb->qeuq_culd != 1 || qeuq_cb->qeuq_uld_tup == NULL) || (qeuq_cb->qeuq_db_id == NULL) || (qeuq_cb->qeuq_d_id == 0)) { status = E_DB_ERROR; error = E_QE0018_BAD_PARAM_IN_CB; break; } /* ** Check to see if transaction is in progress, if so set a local ** transaction, otherwise we'll use the user's transaction. */ if (qef_cb->qef_stat == QEF_NOTRAN) { tranqeu.qeu_type = QEUCB_CB; tranqeu.qeu_length = sizeof(QEUCB_CB); tranqeu.qeu_db_id = qeuq_cb->qeuq_db_id; tranqeu.qeu_d_id = qeuq_cb->qeuq_d_id; tranqeu.qeu_flag = 0; status = qeu_btran(qef_cb, &tranqeu); if (status != E_DB_OK) { error = tranqeu.error.err_code; break; } transtarted = TRUE; } /* Escalate the transaction to MST */ if (qef_cb->qef_auto == QEF_OFF) qef_cb->qef_stat = QEF_MSTRAN; evtuple = (DB_IIEVENT *)qeuq_cb->qeuq_uld_tup->dt_data; /* Open iievent tables */ evqeu.qeu_type = QEUCB_CB; evqeu.qeu_length = sizeof(QEUCB_CB); evqeu.qeu_db_id = qeuq_cb->qeuq_db_id; evqeu.qeu_lk_mode = DMT_IX; evqeu.qeu_flag = DMT_U_DIRECT; evqeu.qeu_access_mode = DMT_A_WRITE; evqeu.qeu_mask = 0; evqeu.qeu_tab_id.db_tab_base = DM_B_EVENT_TAB_ID; /* Open iievent */ evqeu.qeu_tab_id.db_tab_index = DM_I_EVENT_TAB_ID; status = qeu_open(qef_cb, &evqeu); if (status != E_DB_OK) { error = evqeu.error.err_code; break; } event_opened = TRUE; evqeu.qeu_count = 1; /* Initialize event-specific qeu */ evqeu.qeu_tup_length = sizeof(DB_IIEVENT); evqeu.qeu_output = &evqef_data; evqef_data.dt_next = NULL; evqef_data.dt_size = sizeof(DB_IIEVENT); evqef_data.dt_data = (PTR)&evtuple_del; /* ** Position iievent table based on name & owner and drop specific ** event. If we can't find it issue an error. */ evqeu.qeu_getnext = QEU_REPO; /* Get event that matches (keyed on) event name and owner */ evqeu.qeu_klen = 2; evqeu.qeu_key = evkey_ptr_array; evkey_ptr_array[0] = &evkey_array[0]; evkey_ptr_array[0]->attr_number = DM_1_EVENT_KEY; evkey_ptr_array[0]->attr_operator = DMR_OP_EQ; evkey_ptr_array[0]->attr_value = (char *)&evtuple->dbe_name; evkey_ptr_array[1] = &evkey_array[1]; evkey_ptr_array[1]->attr_number = DM_2_EVENT_KEY; evkey_ptr_array[1]->attr_operator = DMR_OP_EQ; evkey_ptr_array[1]->attr_value = (char *)&evtuple->dbe_owner; evqeu.qeu_qual = NULL; evqeu.qeu_qarg = NULL; status = qeu_get(qef_cb, &evqeu); if (status != E_DB_OK) { if (evqeu.error.err_code == E_QE0015_NO_MORE_ROWS) { (VOID)qef_error(E_QE020B_EVENT_ABSENT, 0L, E_DB_ERROR, &error, &qeuq_cb->error, 1, qec_trimwhite(sizeof(evtuple->dbe_name), (char *)&evtuple->dbe_name), (PTR)&evtuple->dbe_name); error = E_QE0025_USER_ERROR; } else /* Other error */ { error = evqeu.error.err_code; } break; } /* If no event found */ break; } /* End dummy for loop */ /* Handle any error messages */ if (status != E_DB_OK) { (VOID) qef_error(error, 0L, status, &error, &qeuq_cb->error, 0); } else { QEUQ_CB dqeuq; STRUCT_ASSIGN_MACRO(*qeuq_cb, dqeuq); dqeuq.qeuq_flag_mask &= ~QEU_DROP_TEMP_TABLE; dqeuq.qeuq_flag_mask |= QEU_FORCE_QP_INVALIDATION; dqeuq.qeuq_rtbl = &evtuple_del.dbe_uniqueid; STRUCT_ASSIGN_MACRO(evtuple_del.dbe_txtid, dqeuq.qeuq_qid); dqeuq.qeuq_uld_tup = &evqef_data; /* ** Check if dbevent used by alarm, if so we can't drop it */ if(qeu_ev_used_with_alarm(qef_cb, qeuq_cb, &evtuple_del.dbe_uniqueid) !=E_DB_OK) { (VOID) qef_error(E_US2479_9337_ALARM_USES_EVENT, 0L, local_status, &error, &qeuq_cb->error, 2, qec_trimwhite(sizeof(evtuple->dbe_owner), (char*)&evtuple->dbe_owner), (PTR)&evtuple->dbe_owner, qec_trimwhite(sizeof(evtuple->dbe_name), (char*)&evtuple->dbe_name), (PTR)&evtuple->dbe_name); error = E_QE0025_USER_ERROR; status=E_DB_ERROR; } if(status==E_DB_OK) { /* ** perform cascading destruction - qeu_d_cascade() handles its ** own error reporting */ STRUCT_ASSIGN_MACRO(*qeuq_cb, dqeuq); dqeuq.qeuq_flag_mask &= ~((i4) QEU_DROP_TEMP_TABLE); dqeuq.qeuq_rtbl = &evtuple_del.dbe_uniqueid; STRUCT_ASSIGN_MACRO(evtuple_del.dbe_txtid, dqeuq.qeuq_qid); dqeuq.qeuq_uld_tup = &evqef_data; /* perform cascading destruction of the dbevent */ status = qeu_d_cascade(qef_cb, &dqeuq, (DB_QMODE) DB_EVENT, (DMT_TBL_ENTRY *) NULL); if (status != E_DB_OK) { STRUCT_ASSIGN_MACRO(dqeuq.error, qeuq_cb->error); } } } /* Audit DROP EVENT if so far so good */ if ( status == E_DB_OK && Qef_s_cb->qef_state & QEF_S_C2SECURE ) { DB_ERROR e_error; status = qeu_secaudit(FALSE, qef_cb->qef_ses_id, evtuple->dbe_name.db_ev_name, &evtuple->dbe_owner, DB_EVENT_MAXNAME, SXF_E_EVENT, I_SX203C_EVENT_DROP, SXF_A_SUCCESS | SXF_A_DROP, &e_error); } /* Close off all the tables and transaction */ if (event_opened) { local_status = qeu_close(qef_cb, &evqeu); if (local_status != E_DB_OK) { (VOID) qef_error(evqeu.error.err_code, 0L, local_status, &error, &qeuq_cb->error, 0); if (local_status > status) status = local_status; } } if (transtarted) { if (status == E_DB_OK) local_status = qeu_etran(qef_cb, &tranqeu); else local_status = qeu_atran(qef_cb, &tranqeu); if (local_status != E_DB_OK) { (VOID) qef_error(tranqeu.error.err_code, 0L, local_status, &error, &qeuq_cb->error, 0); if (local_status > status) status = local_status; } } return (status); } /* qeu_devent */
DB_STATUS qeu_csecalarm( QEF_CB *qef_cb, QEUQ_CB *qeuq_cb) { DB_IIQRYTEXT *qtuple; /* Alarm text */ DB_SECALARM *atuple; /* New alarm tuple */ DB_SECALARM atuple_temp; /* Tuple to check for uniqueness */ DB_STATUS status, local_status; i4 error=0; bool transtarted = FALSE; bool tbl_opened = FALSE; i4 i; /* Querytext tuple counter */ QEF_DATA *next; /* and data pointer */ QEU_CB tranqeu; QEU_CB qeu; QEU_QUAL_PARAMS qparams; DB_QRY_ID qryid; /* Ids for query text */ QEF_DATA qef_data; bool loop=FALSE; QEF_RCB qef_rcb; i4 number; DMR_ATTR_ENTRY akey_array[3]; DMR_ATTR_ENTRY *akey_ptr_array[3]; DMT_CHAR_ENTRY char_spec; /* DMT_ALTER specification */ DMT_CB dmt_cb; DB_ERROR e_error; SXF_ACCESS access; SXF_EVENT evtype; DB_OWN_NAME objowner; do { MEfill(sizeof(objowner),' ',(PTR)&objowner); /* Validate CB and parameters */ if (qeuq_cb->qeuq_type != QEUQCB_CB || qeuq_cb->qeuq_length != sizeof(QEUQ_CB)) { status = E_DB_ERROR; error = E_QE0017_BAD_CB; break; } if ( qeuq_cb->qeuq_cq == 0 || qeuq_cb->qeuq_qry_tup == NULL || ( qeuq_cb->qeuq_uld_tup == NULL) || (qeuq_cb->qeuq_db_id == NULL) || (qeuq_cb->qeuq_d_id == 0)) { status = E_DB_ERROR; error = E_QE0018_BAD_PARAM_IN_CB; break; } qef_rcb.qef_cb = qef_cb; qef_rcb.qef_db_id = qeuq_cb->qeuq_db_id; qef_cb->qef_dbid = qeuq_cb->qeuq_db_id; /* ** Check to see if transaction is in progress, if so set a local ** transaction, otherwise we'll use the user's transaction. */ if (qef_cb->qef_stat == QEF_NOTRAN) { tranqeu.qeu_type = QEUCB_CB; tranqeu.qeu_length = sizeof(QEUCB_CB); tranqeu.qeu_db_id = qeuq_cb->qeuq_db_id; tranqeu.qeu_d_id = qeuq_cb->qeuq_d_id; tranqeu.qeu_flag = 0; tranqeu.qeu_mask = 0; status = qeu_btran(qef_cb, &tranqeu); if (status != E_DB_OK) { error = tranqeu.error.err_code; break; } transtarted = TRUE; } /* Escalate the transaction to MST */ if (qef_cb->qef_auto == QEF_OFF) qef_cb->qef_stat = QEF_MSTRAN; atuple = (DB_SECALARM *)qeuq_cb->qeuq_uld_tup->dt_data; /* For database alarms, make sure the database exists */ if(atuple->dba_objtype==DBOB_DATABASE && !(atuple->dba_flags&DBA_ALL_DBS)) { status=qeu_db_exists(qef_cb, qeuq_cb, (DB_DB_NAME *)&atuple->dba_objname, SXF_A_CONTROL, &objowner); if(status==E_DB_ERROR) { /* Error checking database name */ break; } else if (status==E_DB_WARN) { /* Database not found */ status=E_DB_ERROR; /* E_US2474_9332_ALARM_NO_DB */ (VOID)qef_error(9332, 0L, E_DB_ERROR, &error, &qeuq_cb->error, 1, qec_trimwhite(sizeof(atuple->dba_objname), (char *)&atuple->dba_objname), (PTR)&atuple->dba_objname); break; } } else if(atuple->dba_objtype==DBOB_TABLE) { /* ** Alter the table relstat to flag alarms exist. This validates that ** the table exists and ensures that we get an exclusive lock on it. */ char_spec.char_id = DMT_C_ALARM; /* create alarm code */ char_spec.char_value = DMT_C_ON; MEfill(sizeof(DMT_CB), 0, (PTR) &dmt_cb); dmt_cb.dmt_flags_mask = 0; dmt_cb.dmt_db_id = qeuq_cb->qeuq_db_id; dmt_cb.dmt_char_array.data_in_size = sizeof(DMT_CHAR_ENTRY); dmt_cb.dmt_char_array.data_address = (PTR)&char_spec; dmt_cb.length = sizeof(DMT_CB); dmt_cb.type = DMT_TABLE_CB; dmt_cb.dmt_id.db_tab_base = atuple->dba_objid.db_tab_base; dmt_cb.dmt_id.db_tab_index = atuple->dba_objid.db_tab_index; dmt_cb.dmt_tran_id = qef_cb->qef_dmt_id; status = dmf_call(DMT_ALTER, &dmt_cb); if (status != E_DB_OK) { error = dmt_cb.error.err_code; break; } } /* Get a unique query id */ TMnow((SYSTIME *)&qryid); atuple->dba_txtid.db_qry_high_time = qryid.db_qry_high_time; atuple->dba_txtid.db_qry_low_time = qryid.db_qry_low_time; /* Get a unique alarm id */ status = qea_reserveID(&atuple->dba_alarmid, qef_cb, &qef_rcb.error); if (status != E_DB_OK) { error = qef_rcb.error.err_code; break; } /* ** Generate an alarm name if needed, all blanks indicates no ** name specified. This is required for uniqueness check below. */ if(!STskipblank( (char*)&atuple->dba_alarmname, sizeof(atuple->dba_alarmname))) { status=qeu_gen_alarm_name( atuple->dba_objtype, (char*)&atuple->dba_objname, &qef_rcb, &atuple->dba_alarmid, (char*)&atuple->dba_alarmname, &error); if(status!=E_DB_OK) break; } /* Validate that the alarm name is unique */ qeu.qeu_type = QEUCB_CB; qeu.qeu_length = sizeof(QEUCB_CB); qeu.qeu_tab_id.db_tab_base = DM_B_IISECALARM_TAB_ID; qeu.qeu_tab_id.db_tab_index = DM_I_IISECALARM_TAB_ID; qeu.qeu_db_id = qeuq_cb->qeuq_db_id; qeu.qeu_lk_mode = DMT_IX; qeu.qeu_flag = DMT_U_DIRECT; qeu.qeu_access_mode = DMT_A_WRITE; qeu.qeu_mask = 0; status = qeu_open(qef_cb, &qeu); if (status != E_DB_OK) { error = qeu.error.err_code; break; } tbl_opened = TRUE; atuple->dba_alarmno=0; /* Retrieve the same named alarm - if not there then ok */ qeu.qeu_count = 1; qeu.qeu_tup_length = sizeof(DB_SECALARM); qeu.qeu_output = &qef_data; qef_data.dt_next = NULL; qef_data.dt_size = sizeof(DB_SECALARM); qef_data.dt_data = (PTR)&atuple_temp; qeu.qeu_getnext = QEU_REPO; qeu.qeu_klen = 0; /* Not keyed */ qparams.qeu_qparms[0] = (PTR) atuple; /* What we're looking for */ qeu.qeu_qual = qeu_qalarm_by_name; qeu.qeu_qarg = &qparams; status = qeu_get(qef_cb, &qeu); if (status == E_DB_OK) /* Found the same alarm! */ { (VOID)qef_error(E_US2472_9330_ALARM_EXISTS, 0L, E_DB_ERROR, &error, &qeuq_cb->error, 1, qec_trimwhite(sizeof(atuple->dba_alarmname), (char *)&atuple->dba_alarmname), (PTR)&atuple->dba_alarmname); error = E_QE0025_USER_ERROR; break; } if (qeu.error.err_code != E_QE0015_NO_MORE_ROWS) { /* Some other error */ error = qeu.error.err_code; break; } status = qeu_close(qef_cb, &qeu); if (status != E_DB_OK) { error = qeu.error.err_code; break; } tbl_opened=FALSE; /* ** Generate a unique alarm number. This is primarily for ** backwards compatibility with "anonymous" alarms which had ** to be dropped by number, not name. */ status = qeu_open(qef_cb, &qeu); if (status != E_DB_OK) { error = qeu.error.err_code; break; } tbl_opened = TRUE; qeu.qeu_count = 1; qeu.qeu_tup_length = sizeof(DB_SECALARM); qeu.qeu_input = &qef_data; qeu.qeu_output = &qef_data; qef_data.dt_next = 0; qef_data.dt_size = sizeof(DB_SECALARM); qef_data.dt_data = (PTR) &atuple_temp; qeu.qeu_getnext = QEU_REPO; qeu.qeu_klen = 3; qeu.qeu_key = akey_ptr_array; akey_ptr_array[0] = &akey_array[0]; akey_ptr_array[1] = &akey_array[1]; akey_ptr_array[2] = &akey_array[2]; akey_ptr_array[0]->attr_number = DM_1_IISECALARM_KEY; akey_ptr_array[0]->attr_operator = DMR_OP_EQ; akey_ptr_array[0]->attr_value = (char*) &atuple->dba_objtype; akey_ptr_array[1]->attr_number = DM_2_IISECALARM_KEY; akey_ptr_array[1]->attr_operator = DMR_OP_EQ; akey_ptr_array[1]->attr_value = (char*) &atuple->dba_objid.db_tab_base; akey_ptr_array[2]->attr_number = DM_3_IISECALARM_KEY; akey_ptr_array[2]->attr_operator = DMR_OP_EQ; akey_ptr_array[2]->attr_value = (char*) &atuple->dba_objid.db_tab_index; qeu.qeu_qual = 0; qeu.qeu_qarg = 0; /* ** Get all alarm tuples for this object ** and determine the next alarm number. */ status = E_DB_OK; number = 0; while (status == E_DB_OK) { status = qeu_get(qef_cb, &qeu); if (status != E_DB_OK) { error = qeu.error.err_code; break; } qeu.qeu_getnext = QEU_NOREPO; qeu.qeu_klen = 0; if (atuple_temp.dba_alarmno > number) number = atuple_temp.dba_alarmno; } if (error != E_QE0015_NO_MORE_ROWS) break; /* ** We have to add 1 to derive the next alarm number. */ atuple->dba_alarmno=number+1; /* Save the alarm tuple */ status = E_DB_OK; /* Insert single alarm tuple */ qeu.qeu_count = 1; qeu.qeu_tup_length = sizeof(DB_SECALARM); qeu.qeu_input = qeuq_cb->qeuq_uld_tup; status = qeu_append(qef_cb, &qeu); if (status != E_DB_OK) { error = qeu.error.err_code; break; } status = qeu_close(qef_cb, &qeu); if (status != E_DB_OK) { error = qeu.error.err_code; break; } tbl_opened = FALSE; /* Update all query text tuples with query id - validate list */ next = qeuq_cb->qeuq_qry_tup; for (i = 0; i < qeuq_cb->qeuq_cq; i++) { qtuple = (DB_IIQRYTEXT *)next->dt_data; next = next->dt_next; qtuple->dbq_txtid.db_qry_high_time = qryid.db_qry_high_time; qtuple->dbq_txtid.db_qry_low_time = qryid.db_qry_low_time; if (i < (qeuq_cb->qeuq_cq -1) && next == NULL) { error = E_QE0018_BAD_PARAM_IN_CB; status = E_DB_ERROR; break; } } /* for all query text tuples */ if (status != E_DB_OK) break; /* Insert all query text tuples */ qeu.qeu_tab_id.db_tab_base = DM_B_QRYTEXT_TAB_ID; qeu.qeu_tab_id.db_tab_index = 0L; status = qeu_open(qef_cb, &qeu); if (status != E_DB_OK) { error = qeu.error.err_code; break; } tbl_opened = TRUE; qeu.qeu_count = qeuq_cb->qeuq_cq; qeu.qeu_tup_length = sizeof(DB_IIQRYTEXT); qeu.qeu_input = qeuq_cb->qeuq_qry_tup; status = qeu_append(qef_cb, &qeu); if (status != E_DB_OK) { error = qeu.error.err_code; break; } status = qeu_close(qef_cb, &qeu); if (status != E_DB_OK) { error = qeu.error.err_code; break; } tbl_opened = FALSE; if (transtarted) /* If we started a transaction */ { status = qeu_etran(qef_cb, &tranqeu); if (status != E_DB_OK) { error = tranqeu.error.err_code; break; } } } while(loop); /* call qef_error to handle error messages */ if(error) (VOID) qef_error(error, 0L, status, &error, &qeuq_cb->error, 0); /* Close off all the tables. */ local_status = E_DB_OK; if (tbl_opened) /* If system table opened, close it */ { local_status = qeu_close(qef_cb, &qeu); if (local_status != E_DB_OK) { (VOID) qef_error(qeu.error.err_code, 0L, local_status, &error, &qeuq_cb->error, 0); if (local_status > status) status = local_status; } } if (transtarted) /* If we started a transaction */ { local_status = qeu_atran(qef_cb, &tranqeu); if (local_status != E_DB_OK) { (VOID) qef_error(tranqeu.error.err_code, 0L, local_status, &error, &qeuq_cb->error, 0); if (local_status > status) status = local_status; } } if ( Qef_s_cb->qef_state & QEF_S_C2SECURE ) { if(atuple->dba_objtype==DBOB_DATABASE) { evtype=SXF_E_DATABASE; } else { evtype=SXF_E_TABLE; } /* ** Creating an alarm is a control operation on the base object ** (database/table) */ if(status==E_DB_OK) access=(SXF_A_CONTROL|SXF_A_SUCCESS); else access=(SXF_A_CONTROL|SXF_A_FAIL); if(qeu_secaudit(FALSE, qef_cb->qef_ses_id, (char *)&atuple->dba_objname, &objowner, sizeof(atuple->dba_objname), evtype, I_SX202D_ALARM_CREATE, access, &e_error)!=E_DB_OK) { error = e_error.err_code; status=E_DB_ERROR; } } /* ** Log QEF create error */ if(status!=E_DB_OK) { (VOID) qef_error(E_QE028B_CREATE_ALARM_ERR, 0L, local_status, &error, &qeuq_cb->error, 0); qeuq_cb->error.err_code= E_QE0025_USER_ERROR; } return (status); } /* qeu_csecalarm */
/* ** Name: qeu_evraise ** ** Description: ** This routine raises an event, it processes the external request ** QEU_RAISE_EVENT, typically when raising the event associated with ** a security alarm. ** ** Note this *does* do event tracing (SET PRINTEVENTS/LOGEVENTS) ** but does *not* do security checks/auditing on the operation, this ** is assumed to be handled at a higher level. ** ** Inputs: ** qef_rcb.evname - Event name ** qef_rcb.evowner - Event owner ** qef_rcb.evtext - Event text ** qef_rcb.ev_l_text- Length of text ** ** History: ** 26-nov-93 (robf) ** Created for secure 2.0 ** 12-Jan-1998 (kinpa04/merja01) ** Remove (i4) casting of session id. This caused the ** session ID to get truncated on axp_osf while raising events. ** 10-Jan-2001 (jenjo02) ** We know this session's id; pass it to SCF. ** 30-Dec-2005 (kschendel) ** Update call to qef-adf-error. ** */ DB_STATUS qeu_evraise( QEF_CB *qef_cb, QEF_RCB *qef_rcb ) { DB_DATA_VALUE tm; /* Timestamp */ DB_DATE tm_date; SCF_ALERT scfa; SCF_CB scf_cb; SCF_SCI sci_list[1]; DB_ALERT_NAME alert; i4 err; char *errstr; DB_STATUS status=E_DB_OK; i4 tr1 = 0, tr2 = 0; /* Dummy trace values */ /* ** Build alert name */ STRUCT_ASSIGN_MACRO(*qef_rcb->qef_evname, alert.dba_alert); STRUCT_ASSIGN_MACRO(*qef_rcb->qef_evowner, alert.dba_owner); scf_cb.scf_length = sizeof(SCF_CB); scf_cb.scf_type = SCF_CB_TYPE; scf_cb.scf_facility = DB_QEF_ID; scf_cb.scf_session = qef_cb->qef_ses_id; /* Get the database name */ scf_cb.scf_ptr_union.scf_sci = (SCI_LIST *) sci_list; scf_cb.scf_len_union.scf_ilength = 1; sci_list[0].sci_length = sizeof(DB_DB_NAME); sci_list[0].sci_code = SCI_DBNAME; sci_list[0].sci_aresult = (char *) &alert.dba_dbname; sci_list[0].sci_rlength = NULL; status = scf_call(SCU_INFORMATION, &scf_cb); if (status != E_DB_OK) { _VOID_ qef_error(E_QE022F_SCU_INFO_ERROR, 0L, status, &err, &qef_rcb->error, 0); return E_DB_ERROR; } /* Format SCF event request block */ scf_cb.scf_ptr_union.scf_alert_parms = &scfa; scfa.scfa_name = &alert; scfa.scfa_text_length = 0; scfa.scfa_user_text = NULL; scfa.scfa_flags = 0; if (qef_rcb->qef_ev_l_text > 0) /* No need for empty strings */ { if (qef_rcb->qef_ev_l_text > DB_EVDATA_MAX) qef_rcb->qef_ev_l_text = DB_EVDATA_MAX; scfa.scfa_text_length = qef_rcb->qef_ev_l_text; scfa.scfa_user_text = qef_rcb->qef_evtext; } tm.db_datatype = DB_DTE_TYPE; /* Get time stamp for the event */ tm.db_prec = 0; tm.db_length = sizeof(tm_date); tm.db_data = (PTR)&tm_date; tm.db_collID = -1; status = adu_datenow(qef_cb->qef_adf_cb, &tm); if (status != E_DB_OK) { if ((status = qef_adf_error(&qef_cb->qef_adf_cb->adf_errcb, status, qef_cb, &qef_rcb->error)) != E_DB_OK) return (status); } scfa.scfa_when = &tm_date; /* If tracing and/or logging events then display event information */ if (ult_check_macro(&qef_cb->qef_trace, QEF_T_EVENTS, &tr1, &tr2)) qea_evtrace(qef_rcb, QEF_T_EVENTS, &alert, &tm, (i4)qef_rcb->qef_ev_l_text, (char*)qef_rcb->qef_evtext); if (ult_check_macro(&qef_cb->qef_trace, QEF_T_LGEVENTS, &tr1, &tr2)) qea_evtrace(qef_rcb, QEF_T_LGEVENTS, &alert, &tm, 0, (char *)NULL); /* ** Raise the event in SCF */ status = scf_call(SCE_RAISE, &scf_cb); if (status != E_DB_OK) { char *enm, *onm; /* Event and owner names */ enm = (char *)&alert.dba_alert; onm = (char *)&alert.dba_owner; errstr="RAISE"; switch (scf_cb.scf_error.err_code) { case E_SC0270_NO_EVENT_MESSAGE: _VOID_ qef_error(E_QE019A_EVENT_MESSAGE, 0L, status, &err, &qef_rcb->error, 1, (i4)STlength(errstr), errstr); break; case E_SC0280_NO_ALERT_INIT: _VOID_ qef_error(E_QE0200_NO_EVENTS, 0L, status, &err, &qef_rcb->error, 1, (i4)STlength(errstr), errstr); break; default: _VOID_ qef_error(E_QE020F_EVENT_SCF_FAIL, 0L, status, &err, &qef_rcb->error, 4, (i4)STlength(errstr), errstr, (i4)sizeof(i4), (PTR)&scf_cb.scf_error.err_code, qec_trimwhite(DB_OWN_MAXNAME, onm), onm, qec_trimwhite(DB_EVENT_MAXNAME, enm), enm); break; } qef_rcb->error.err_code = E_QE0025_USER_ERROR; status = E_DB_ERROR; } /* If SCF not ok */ 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); }