/*{ ** Name: opv_varnode - make a range variable node ** ** Description: ** This procedure allocates and initializes a query tree PST_VAR node. ** ** Inputs: ** global ptr to global state variable ** datavalue datatype info of node to create ** variable range variable number - index ** into the global range table ** attribute dmf attribute of range variable to be ** assigned to var node. ** ** Outputs: ** Returns: ** ptr to PST_QNODE initialized to be a var node ** Exceptions: ** none ** ** Side Effects: ** none ** ** History: ** 8-apr-86 (seputis) ** initial creation ** 9-jul-91 (seputis) ** remove obsolete trace point [@history_line@]... */ PST_QNODE * opv_varnode( OPS_STATE *global, DB_DATA_VALUE *datatype, OPV_IGVARS variable, DB_ATT_ID *dmfattr) { register PST_QNODE *qnode; /* ptr used for symbol allocation */ qnode = (PST_QNODE *) opu_memory( global, (i4) sizeof(PST_QNODE)); /* allocate storage for query tree node ** to be used for creation of var node */ qnode->pst_left = NULL; qnode->pst_right = NULL; qnode->pst_sym.pst_type = PST_VAR; /* create VAR node type */ STRUCT_ASSIGN_MACRO(*datatype, qnode->pst_sym.pst_dataval); qnode->pst_sym.pst_dataval.db_data = NULL; qnode->pst_sym.pst_len = sizeof(PST_VAR_NODE); qnode->pst_sym.pst_value.pst_s_var.pst_vno = variable; STRUCT_ASSIGN_MACRO(*dmfattr, qnode->pst_sym.pst_value.pst_s_var.pst_atno); MEfill(sizeof(qnode->pst_sym.pst_value.pst_s_var.pst_atname), ' ', (PTR)&qnode->pst_sym.pst_value.pst_s_var.pst_atname); /* init attribute ** name */ return( qnode ); }
/*{ ** Name: opu_compare - compare two values with the same type ** ** Description: ** This routine will compare two values of the same type. ** ** Inputs: ** global ptr to global state variable ** vp1 ptr to first value ** vp2 ptr to second value ** datatype ptr to datatype info on values ** ** Outputs: ** Returns: ** -1 if vp1 < vp2 ** 0 if vp1 = vp2 ** 1 if vp1 > vp2 ** Exceptions: ** none ** ** Side Effects: ** none ** ** History: ** 21-jun-86 (seputis) ** initial creation [@history_line@]... */ i4 opu_compare( OPS_STATE *global, PTR vp1, PTR vp2, DB_DATA_VALUE *datatype) { i4 adc_cmp_result; DB_DATA_VALUE vpdv1; DB_DATA_VALUE vpdv2; DB_STATUS comparestatus; STRUCT_ASSIGN_MACRO(*datatype, vpdv1); STRUCT_ASSIGN_MACRO(vpdv1, vpdv2); vpdv2.db_data = vp2; vpdv1.db_data = vp1; comparestatus = adc_compare(global->ops_adfcb, &vpdv1, &vpdv2, &adc_cmp_result); # ifdef E_OP078C_ADC_COMPARE if (comparestatus != E_DB_OK) opx_verror( comparestatus, E_OP078C_ADC_COMPARE, global->ops_adfcb->adf_errcb.ad_errcode); # endif return (adc_cmp_result); }
DB_STATUS qee_d9_undefall( QEF_RCB *qef_rcb) { DB_STATUS status = E_DB_OK, sav_status = E_DB_OK; DB_ERROR sav_error; QES_DDB_SES *dds_p = & qef_rcb->qef_cb->qef_c2_ddb_ses; PTR qso_handle; QES_RPT_HANDLE *hand_p; i4 i; for (i = 0, hand_p = dds_p->qes_d12_handle_p; hand_p != (QES_RPT_HANDLE *) NULL; ++i, hand_p = hand_p->qes_2_next) { status = qee_d8_undefrpt(qef_rcb, hand_p->qes_3_qso_handle); if (status) { sav_status = status; STRUCT_ASSIGN_MACRO(qef_rcb->error, sav_error); } } if (status == E_DB_OK && sav_status) { status = sav_status; STRUCT_ASSIGN_MACRO(sav_error, qef_rcb->error); } return(status); }
/*{ ** Name: psy_create_synonym - Insert a tuple into IISYNONYM. ** ** Description: ** Call RDF_UPDATE to insert a tuple into IISYNONYM. ** Inputs: ** psy_cb PSY control block. ** sess_cb PSF session control block. ** Outputs: ** Exceptions: ** none ** Returns: ** E_DB_OK synonym tuple has been inserted successfully; ** error status from RDF otherwise ** ** Side Effects: ** Modifies system catalogs. ** ** History: ** 19-apr-90 (andre) ** Created. ** 22-may-90 (teg) ** init rdr_instr to RDF_NO_INSTR ** 03-aug-92 (barbara) ** Invalidate base object's infoblk from the RDF cache. ** 10-aug-93 (andre) ** fixed causes of compiler warnings */ DB_STATUS psy_create_synonym( PSY_CB *psy_cb, PSS_SESBLK *sess_cb) { RDF_CB rdf_cb; register RDR_RB *rdf_rb = &rdf_cb.rdf_rb; DB_STATUS status; i4 err_code; /* Initialize the RDF request block. */ pst_rdfcb_init(&rdf_cb, sess_cb); STRUCT_ASSIGN_MACRO(sess_cb->pss_user, rdf_rb->rdr_owner); rdf_rb->rdr_2types_mask = (RDF_TYPES) RDR2_SYNONYM; rdf_rb->rdr_update_op = RDR_APPEND; rdf_rb->rdr_qrytuple = psy_cb->psy_tupptr; rdf_rb->rdr_tabid.db_tab_base = DM_B_SYNONYM_TAB_ID; rdf_rb->rdr_tabid.db_tab_index = DM_I_SYNONYM_TAB_ID; /* Insert a tuple into IISYNONYM */ status = rdf_call(RDF_UPDATE, (PTR) &rdf_cb); if (DB_FAILURE_MACRO(status)) { if (rdf_cb.rdf_error.err_code == E_RD0143_CREATE_SYNONYM) { DB_IISYNONYM *syn = (DB_IISYNONYM *) psy_cb->psy_tupptr; (VOID) psf_error(E_PS0454_CREATE_SYN_ERROR, 0L, PSF_USERERR, &err_code, &psy_cb->psy_error, 1, psf_trmwhite(sizeof(DB_SYNNAME), (char *) &syn->db_synname), &syn->db_synname); } else { (VOID) psf_rdf_error(RDF_UPDATE, &rdf_cb.rdf_error, &psy_cb->psy_error); } return (status); } /* Invalidate the base object's info block from the RDF cache */ { DB_IISYNONYM *syn_tuple = (DB_IISYNONYM *) psy_cb->psy_tupptr; pst_rdfcb_init(&rdf_cb, sess_cb); STRUCT_ASSIGN_MACRO(syn_tuple->db_syntab_id, rdf_rb->rdr_tabid); status = rdf_call(RDF_INVALIDATE, (PTR) &rdf_cb); if (DB_FAILURE_MACRO(status)) { (VOID) psf_rdf_error(RDF_INVALIDATE, &rdf_cb.rdf_error, &psy_cb->psy_error); } } return (status); }
DB_STATUS qeq_a2_fetch( QEF_RCB *v_qer_p, QEF_AHD *i_act_p, bool *o_tupread_p, bool *o_eod_p ) { DB_STATUS status, ignore; DB_ERROR sav_error; QEE_DSH *dsh_p = (QEE_DSH *)(v_qer_p->qef_cb->qef_dsh); QEE_DDB_CB *qee_p = dsh_p->dsh_ddb_cb; QES_DDB_SES *dds_p = & v_qer_p->qef_cb->qef_c2_ddb_ses; QEQ_D1_QRY *sub_p = & i_act_p->qhd_obj.qhd_d1_qry; RQR_CB rqr, *rqr_p = & rqr; RQB_BIND *bind; MEfill(sizeof(rqr), '\0', (PTR) & rqr); rqr_p->rqr_session = dds_p->qes_d3_rqs_p; /* RQF session id */ rqr_p->rqr_q_language = sub_p->qeq_q1_lang; rqr_p->rqr_timeout = sub_p->qeq_q2_quantum; rqr_p->rqr_1_site = sub_p->qeq_q5_ldb_p; rqr_p->rqr_col_count = sub_p->qeq_q6_col_cnt; rqr_p->rqr_bind_addrs = (RQB_BIND *) qee_p->qee_d9_bind_p; /* must use invariant array */ status = qed_u3_rqf_call(RQR_T_FETCH, rqr_p, v_qer_p); if (status) { /* must flush before returning */ STRUCT_ASSIGN_MACRO(v_qer_p->error, sav_error); ignore = qeq_a3_flush(v_qer_p, sub_p->qeq_q5_ldb_p); STRUCT_ASSIGN_MACRO(sav_error, v_qer_p->error); return(status); } bind = rqr_p->rqr_bind_addrs; /* fix for b55503 FIXME: more general fix needed */ if(bind->rqb_r_dt_id < 0 && bind->rqb_addr[bind->rqb_length-1] > 0) { /* nullable and null byte on */ MEfill(bind->rqb_length-1, '\0', (PTR) bind->rqb_addr); } *o_eod_p = rqr_p->rqr_end_of_data; *o_tupread_p = ! rqr_p->rqr_end_of_data; return(E_DB_OK); }
DB_STATUS qeu_d2_des_tab( QEF_RCB *v_qer_p) { DB_STATUS status; /* QES_DDB_SES *dds_p = & v_qer_p->qef_cb->qef_c2_ddb_ses; */ QEF_DDB_REQ *ddr_p = & v_qer_p->qef_r3_ddb_req; QED_QUERY_INFO *ddq_p = & ddr_p->qer_d4_qry_info; QED_DDL_INFO *ddl_p = & ddr_p->qer_d7_ddl_info; DD_1LDB_INFO ldb_info, *ldb_p = & ldb_info; /* 1. execute DESTROY TABLE statement */ STRUCT_ASSIGN_MACRO(*ddl_p->qed_d5_qry_info_p, *ddq_p); STRUCT_ASSIGN_MACRO(ddl_p->qed_d6_tab_info_p->dd_t9_ldb_p->dd_i1_ldb_desc, ldb_p->dd_i1_ldb_desc); ddr_p->qer_d2_ldb_info_p = ldb_p; /* 2. execute DESTROY TABLE statement */ status = qed_e4_exec_qry(v_qer_p); if (status) { /* forgive error */ status = qed_u9_log_forgiven(v_qer_p); if (status) return(status); } /* 3. destroy the link and hence all dependent views */ status = qel_d0_des_lnk(v_qer_p); if (status) { /* forgive error */ status = qed_u9_log_forgiven(v_qer_p); if (status) return(status); } return(E_DB_OK); }
/*{ ** Name: opj_uvar - get the attribute number of the union view var node ** ** Description: ** This routine will calculate the attribute number of the union view ** given the equivalence class of this var node ** ** Inputs: ** subquery ptr to subquery containing equivalence ** class of var node ** qual ptr to var node ** ** Outputs: ** attidp ptr to attribute ID for union view ** Returns: ** Exceptions: ** none ** ** Side Effects: ** none ** ** History: ** 28-jun-89 (seputis) ** initial creation [@history_template@]... */ static VOID opj_uvar( OPS_SUBQUERY *subquery, PST_QNODE *qual, OPV_IVARS varno, DB_ATT_ID *attidp) { OPZ_BMATTS *attrmap; /* bit map of attributes in the ** equivalence class */ OPZ_IATTS attno; /* attribute currently being looked at */ OPZ_IATTS maxattr; /* maximum attribute */ OPZ_AT *abase; maxattr = subquery->ops_attrs.opz_av; abase = subquery->ops_attrs.opz_base; /* ptr to base of array of ptrs ** to joinop attributes */ attrmap = &subquery->ops_eclass.ope_base->ope_eqclist [subquery->ops_attrs.opz_base->opz_attnums [qual->pst_sym.pst_value.pst_s_var.pst_atno.db_att_id ]->opz_equcls ]->ope_attrmap; for (attno = -1; (attno = BTnext((i4)attno, (char *)attrmap, maxattr) ) >= 0;) { if (abase->opz_attnums[attno]->opz_varnm == varno) { /* found the union view attribute number so copy it in */ STRUCT_ASSIGN_MACRO(abase->opz_attnums[attno]->opz_attnm, *attidp); break; } } if (attno < 0) opx_error(E_OP0384_NOATTS); /* attribute not found when ** expected */ }
DB_STATUS psy_csequence( PSY_CB *psy_cb, PSS_SESBLK *sess_cb) { RDF_CB rdf_cb; RDR_RB *rdf_rb = &rdf_cb.rdf_rb; DB_STATUS status; /* Assign user */ STRUCT_ASSIGN_MACRO(sess_cb->pss_user, psy_cb->psy_tuple.psy_sequence.dbs_owner); /* zero out RDF_CB and init common elements */ pst_rdfcb_init(&rdf_cb, sess_cb); rdf_rb->rdr_l_querytext = 0; rdf_rb->rdr_querytext = NULL; rdf_rb->rdr_2types_mask = RDR2_SEQUENCE; /* Sequence definition */ rdf_rb->rdr_update_op = RDR_APPEND; rdf_rb->rdr_qrytuple = (PTR)&psy_cb->psy_tuple.psy_sequence; /* sequence tup */ /* Create new sequence in iisequence */ status = rdf_call(RDF_UPDATE, (PTR) &rdf_cb); if (status != E_DB_OK) { _VOID_ psf_rdf_error(RDF_UPDATE, &rdf_cb.rdf_error, &psy_cb->psy_error); } /* If RDF error */ return (status); } /* psy_csequence */
DB_STATUS qee_d6_malloc( i4 i_space, QEF_RCB *qef_rcb, PTR *o_pp) { GLOBALREF QEF_S_CB *Qef_s_cb; QEF_CB *qef_cb = qef_rcb->qef_cb; DB_STATUS status = E_DB_OK; ULM_RCB ulm; o_pp = (PTR *) NULL; /* allocate space in QEF memory */ STRUCT_ASSIGN_MACRO(Qef_s_cb->qef_d_ulmcb, ulm); /* 1. allocate from session's stream */ ulm.ulm_streamid_p = &qef_cb->qef_c3_streamid; ulm.ulm_psize = i_space; if (status = qec_malloc(&ulm)) { qef_rcb->error.err_code = ulm.ulm_error.err_code; return(status); } qef_cb->qef_c4_streamsize += i_space; o_pp = (PTR *) ulm.ulm_pptr; return(E_DB_OK); }
/*{ ** Name: ops_gqtree - get query tree from QSF ** ** Description: ** This procedure will get a query tree from QSF ** and initialize the global QSF control block ** ** Inputs: ** global ptr to global state variable ** ** Outputs: ** global->ops_qsfcb initialized ** Returns: ** QSF status ** Exceptions: ** none ** ** Side Effects: ** none ** ** History: ** 26-jan-88 (seputis) ** initial creation ** 7-jan-94 (swm) ** Bug #58635 ** Added PTR cast for qsf_owner which has changed type to PTR. ** 10-Jan-2001 (jenjo02) ** Initialize qsf_sid with session's SID. [@history_template@]... */ DB_STATUS ops_gqtree( OPS_STATE *global) { /* get the query tree from QSF */ DB_STATUS qsfstatus; /* QSF return status */ global->ops_qsfcb.qsf_length = sizeof(QSF_RCB); /* initialize header ** for control block */ global->ops_qsfcb.qsf_type = QSFRB_CB; global->ops_qsfcb.qsf_owner = (PTR)DB_OPF_ID; global->ops_qsfcb.qsf_ascii_id = QSFRB_ASCII_ID; global->ops_qsfcb.qsf_sid = global->ops_cb->ops_sid; STRUCT_ASSIGN_MACRO(global->ops_caller_cb->opf_query_tree, global->ops_qsfcb.qsf_obj_id); /* move the name to the QSF control ** block */ global->ops_qsfcb.qsf_lk_state = QSO_EXLOCK; /* lock exclusively so ** that this object can be destroyed ** later */ qsfstatus = qsf_call( QSO_LOCK, &global->ops_qsfcb); /* get exclusive ** access to object */ if (DB_SUCCESS_MACRO(qsfstatus)) { global->ops_lk_id = global->ops_qsfcb.qsf_lk_id; /* save the lock id ** so that the object can be destroyed ** later */ global->ops_procedure = (PST_PROCEDURE *)global->ops_qsfcb.qsf_root; /* save ** the ptr to procedure header which ** should be the root */ } return(qsfstatus); }
static bool ad0_cpmchk( ADULcstate *str, /* string to look for PM chars in */ u_char *endstr) /* end of str */ { ADULcstate st; STRUCT_ASSIGN_MACRO(*str, st); while (adulptr(&st) < endstr) { switch (adultrans(&st)/COL_MULTI) { case DB_PAT_ONE: case DB_PAT_ANY: case DB_PAT_LBRAC: /* Don't want to look for RBRAC */ return (TRUE); default: adulnext(&st); break; } } return (FALSE); }
DB_STATUS qeq_c2_delete( QEF_RCB *v_qer_p, QEE_DSH *i_dsh_p ) { DB_STATUS status = E_DB_OK; QES_DDB_SES *dds_p = & v_qer_p->qef_cb->qef_c2_ddb_ses; QES_QRY_SES *qss_p = & dds_p->qes_d8_union.u2_qry_ses; QEE_DDB_CB *qee_p = i_dsh_p->dsh_ddb_cb; QEF_QP_CB *qp_p = i_dsh_p->dsh_qp_ptr; QEQ_DDQ_CB *ddq_p = & qp_p->qp_ddq_cb; bool log_qry_55 = FALSE, log_err_59 = FALSE; i4 i4_1, i4_2; RQR_CB rqr, *rqr_p = & rqr; if (ult_check_macro(& v_qer_p->qef_cb->qef_trace, QEF_TRACE_DDB_LOG_QRY_55, & i4_1, & i4_2)) { log_qry_55 = TRUE; qeq_p34_del_csr(v_qer_p, i_dsh_p); } if (ult_check_macro(& v_qer_p->qef_cb->qef_trace, QEF_TRACE_DDB_LOG_ERR_59, & i4_1, & i4_2)) log_err_59 = TRUE; /* 2. set up to call RQR_DELETE */ MEfill(sizeof(rqr), '\0', (PTR) & rqr); rqr_p->rqr_session = dds_p->qes_d3_rqs_p; /* RQF session id */ rqr_p->rqr_tabl_name = ddq_p->qeq_d7_deltable; rqr_p->rqr_own_name = ddq_p->qeq_d9_delown; /* pass owner/table name for ** CURSOR DELETE */ rqr_p->rqr_timeout = QEK_0_TIME_QUANTUM; rqr_p->rqr_q_language = qss_p->qes_q2_lang; rqr_p->rqr_1_site = qss_p->qes_q3_ldb_p; STRUCT_ASSIGN_MACRO(qee_p->qee_d5_local_qid, rqr_p->rqr_qid); qss_p->qes_q1_qry_status |= QES_03Q_PHASE2; /* enter phase 2 for update */ status = qed_u3_rqf_call(RQR_DELETE, rqr_p, v_qer_p); if (status) { if (log_err_59 && ! log_qry_55) qeq_p34_del_csr(v_qer_p, i_dsh_p); } else { qss_p->qes_q1_qry_status &= ~QES_03Q_PHASE2; /* enter phase 2 for update */ v_qer_p->qef_rowcount = rqr_p->rqr_tupcount; v_qer_p->qef_count = rqr_p->rqr_tupcount; } return(status); }
void gcd_api_xaStart( GCD_PCB *pcb ) { pcb->api.name = "IIapi_xaStart()"; pcb->api.parm.start.xs_genParm.gp_callback = gcd_start_cmpl; pcb->api.parm.start.xs_genParm.gp_closure = (PTR)pcb; pcb->api.parm.start.xs_connHandle = pcb->ccb->cib->conn; pcb->api.parm.start.xs_flags = pcb->data.tran.xa_flags; STRUCT_ASSIGN_MACRO(pcb->data.tran.distXID, pcb->api.parm.start.xs_tranID); IIapi_xaStart( &pcb->api.parm.start ); return; }
void gcd_api_xaRollback( GCD_PCB *pcb ) { pcb->api.name = "IIapi_xaRollback()"; pcb->api.parm.xaroll.xr_genParm.gp_callback = gcd_gen_cmpl; pcb->api.parm.xaroll.xr_genParm.gp_closure = (PTR)pcb; pcb->api.parm.xaroll.xr_connHandle = pcb->ccb->cib->conn; pcb->api.parm.xaroll.xr_flags = pcb->data.tran.xa_flags; STRUCT_ASSIGN_MACRO(pcb->data.tran.distXID, pcb->api.parm.xaroll.xr_tranID); IIapi_xaRollback( &pcb->api.parm.xaroll ); return; }
/* PSY_SQLVIEW - IS THIS AN SQL VIEW ** ** Description: ** This routine takes a range entry and determines if it is an ** SQL view. This routine assumes that we know that the range entry ** refers to a view. ** ** History: ** 29-sep-92 (andre) ** RDF may choose to allocate a new info block and return its address ** in rdf_info_blk - we need to copy it over to pss_rdrinfo to avoid ** memory leak and other assorted unpleasantries */ DB_STATUS psy_sqlview( PSS_RNGTAB *rngvar, PSS_SESBLK *sess_cb, DB_ERROR *err_blk, i4 *issql) { DB_STATUS status = E_DB_OK; RDF_CB rdf_cb; PST_PROCEDURE *pnode; PST_QTREE *vtree; i4 err_code; *issql = FALSE; pst_rdfcb_init(&rdf_cb, sess_cb); STRUCT_ASSIGN_MACRO(rngvar->pss_tabid, rdf_cb.rdf_rb.rdr_tabid); rdf_cb.rdf_rb.rdr_types_mask = RDR_VIEW | RDR_QTREE ; rdf_cb.rdf_rb.rdr_qtuple_count = 1; rdf_cb.rdf_info_blk = rngvar->pss_rdrinfo; status = rdf_call(RDF_GETINFO, (PTR) &rdf_cb); /* ** RDF may choose to allocate a new info block and return its address in ** rdf_info_blk - we need to copy it over to pss_rdrinfo to avoid memory ** leak and other assorted unpleasantries */ rngvar->pss_rdrinfo = rdf_cb.rdf_info_blk; if (DB_FAILURE_MACRO(status)) { if (rdf_cb.rdf_error.err_code == E_RD0002_UNKNOWN_TBL) { (VOID) psf_error(E_PS0903_TAB_NOTFOUND, rdf_cb.rdf_error.err_code, PSF_INTERR, &err_code, err_blk, 1, psf_trmwhite(sizeof(DB_TAB_NAME), (char *) &rngvar->pss_tabname), &rngvar->pss_tabname); } else { (VOID) psf_rdf_error(RDF_GETINFO, &rdf_cb.rdf_error, err_blk); } return (status); } pnode = (PST_PROCEDURE *) rdf_cb.rdf_info_blk->rdr_view->qry_root_node; vtree = pnode->pst_stmts->pst_specific.pst_tree; if (vtree->pst_qtree->pst_sym.pst_value.pst_s_root.pst_qlang == DB_SQL) *issql = TRUE; return (status); }
void gcd_api_xaEnd( GCD_PCB *pcb ) { pcb->api.name = "IIapi_xaEnd()"; pcb->api.parm.end.xe_genParm.gp_callback = gcd_end_cmpl; pcb->api.parm.end.xe_genParm.gp_closure = (PTR)pcb; pcb->api.parm.end.xe_connHandle = pcb->ccb->cib->conn; pcb->api.parm.end.xe_flags = pcb->data.tran.xa_flags; STRUCT_ASSIGN_MACRO(pcb->data.tran.distXID, pcb->api.parm.end.xe_tranID); pcb->ccb->cib->tran = NULL; pcb->result.flags |= PCB_RSLT_XACT_END; IIapi_xaEnd( &pcb->api.parm.end ); return; }
/*{ ** Name: psq_tout - Copy a text chain to QSF memory ** ** Description: ** This function copies a text chain to QSF memory, as a text object. ** It allocates it as a contiguous piece. ** ** Inputs: ** rngtab if non-NULL, range statements will be ** generated for all entries of the range table ** that are active (pss_used && pss_rgno >= 0); ** should be non-NULL only for QUEL queries ** header Pointer to chain header ** mstream Pointer to unopened memory stream ** err_blk Filled in if an error happens ** ** Outputs: ** mstream Filled with object id for new text ** object ** err_blk Filled in if an error happened ** Returns: ** E_DB_OK Success ** E_DB_ERROR Non-catastrophic failure ** E_DB_FATAL Catastrophic failure ** Exceptions: ** none ** ** Side Effects: ** Allocates memory ** ** History: ** 18-jul-86 (jeff) ** written ** 2-sep-86 (seputis) ** changed MEcopy routine parameter to be &hp->psq_tsize ** 6-may-87 (daved) ** clear mstream lock id after unlocking memory stream ** 29-jun-87 (daved) ** emit the range table entries if a range table is provided. ** 10-aug-93 (andre) ** removed declaration of qsf_call() */ DB_STATUS psq_tout( PSS_SESBLK *sess_cb, PSS_USRRANGE *rngtab, PTR header, PSF_MSTREAM *mstream, DB_ERROR *err_blk) { DB_STATUS status; i4 err_code; u_char *buf; QSF_RCB qsf_rb; /* Open the QSF memory stream for the text object */ status = psf_mopen(sess_cb, QSO_QTEXT_OBJ, mstream, err_blk); if (status != E_DB_OK) return (status); status = psq_store_text(sess_cb, rngtab, header, mstream, (PTR *) &buf, (bool) FALSE, err_blk); if (DB_FAILURE_MACRO(status)) return(status); /* Set the root of the object */ status = psf_mroot(sess_cb, mstream, (PTR) buf, err_blk); if (status != E_DB_OK) return (status); /* Unlock the object */ qsf_rb.qsf_type = QSFRB_CB; qsf_rb.qsf_ascii_id = QSFRB_ASCII_ID; qsf_rb.qsf_length = sizeof(qsf_rb); qsf_rb.qsf_owner = (PTR)DB_PSF_ID; qsf_rb.qsf_sid = sess_cb->pss_sessid; STRUCT_ASSIGN_MACRO(mstream->psf_mstream, qsf_rb.qsf_obj_id); qsf_rb.qsf_lk_id = mstream->psf_mlock; status = qsf_call(QSO_UNLOCK, &qsf_rb); if (status != E_DB_OK) { (VOID) psf_error(E_PS0375_UNLOCK_QSF_TEXT, qsf_rb.qsf_error.err_code, PSF_INTERR, &err_code, err_blk, 0); return (status); } mstream->psf_mlock = 0; return (E_DB_OK); }
/*{ ** Name: psq_topen - Open a query text chain ** ** Description: ** This function opens a query text chain by opening a memory stream, ** allocating a header, and filling it in. ** ** Inputs: ** header Place to put pointer to header ** memleft Pointer to memory left ** err_blk Filled in if an error happens ** ** Outputs: ** header Filled in with pointer to header ** err_blk Filled in if an error happened ** Returns: ** E_DB_OK Success ** E_DB_ERROR Non-catastrophic failure ** E_DB_FATAL Catastrophic failure ** Exceptions: ** none ** ** Side Effects: ** Allocates memory ** ** History: ** 18-jul-86 (jeff) ** written ** 02-sep-86 (seputis) ** err_blk becomes a DB_ERROR * */ DB_STATUS psq_topen( PTR *header, SIZE_TYPE *memleft, DB_ERROR *err_blk) { ULM_RCB ulm_rcb; DB_STATUS status; i4 err_code; PSQ_THEAD *hp; extern PSF_SERVBLK *Psf_srvblk; /* Open the stream and allocate memory for the header */ ulm_rcb.ulm_facility = DB_PSF_ID; ulm_rcb.ulm_poolid = Psf_srvblk->psf_poolid; ulm_rcb.ulm_blocksize = 512; ulm_rcb.ulm_memleft = memleft; ulm_rcb.ulm_streamid_p = &ulm_rcb.ulm_streamid; ulm_rcb.ulm_flags = ULM_SHARED_STREAM | ULM_OPEN_AND_PALLOC; ulm_rcb.ulm_psize = sizeof(PSQ_THEAD); if ((status = ulm_openstream(&ulm_rcb)) != E_DB_OK) { if (ulm_rcb.ulm_error.err_code == E_UL0005_NOMEM) { psf_error(E_PS0F02_MEMORY_FULL, 0L, PSF_CALLERR, &err_code, err_blk, 0); } else (VOID) psf_error(E_PS0370_OPEN_TEXT_CHAIN, ulm_rcb.ulm_error.err_code, PSF_INTERR, &err_code, err_blk, 0); return (status); } *header = ulm_rcb.ulm_pptr; /* Fill in the header */ hp = (PSQ_THEAD*) ulm_rcb.ulm_pptr; hp->psq_first = (PSQ_TEXT *) NULL; hp->psq_last = (PSQ_TEXT *) NULL; hp->psq_tsize = 0; STRUCT_ASSIGN_MACRO(ulm_rcb, hp->psq_tmem); hp->psq_tmem.ulm_streamid_p = &hp->psq_tmem.ulm_streamid; return (E_DB_OK); }
/*{ ** Name: opx_sccerror - report error to user ** ** Description: ** Report a message to the user ** ** Inputs: ** status status of error ** msg_buffer ptr to message ** error ingres error number ** ** Outputs: ** Returns: ** VOID ** Exceptions: ** none ** ** Side Effects: ** fatal status will cause query to be aborted, and previous text sent ** to user to be flushed ** ** History: ** 15-apr-87 (seputis) ** initial creation ** 21-may-89 (jrb) ** changed interface to this routine to accept generic error ** 28-may-92 (seputis) ** - dump query for any error which is logged ** 24-oct-92 (andre) ** replaced generic error (i4) with sqlstate (DB_SQLSTATE *) in ** the interface of opx_sccerror() ** 13-nov-92 (andre) ** If sqlstate is not passed into opx_sccerror(), set scf_sqlstate ** to MISC_ING_ERRORS" [@history_line@]... [@history_template@]... */ static DB_STATUS opx_sccerror( DB_STATUS status, DB_SQLSTATE *sqlstate, OPX_ERROR error, char *msg_buffer, i4 msg_length) { SCF_CB scf_cb; DB_STATUS scf_status; scf_cb.scf_length = sizeof(scf_cb); scf_cb.scf_type = SCF_CB_TYPE; scf_cb.scf_facility = DB_OPF_ID; scf_cb.scf_nbr_union.scf_local_error = error; if (sqlstate) STRUCT_ASSIGN_MACRO((*sqlstate), scf_cb.scf_aux_union.scf_sqlstate); else MEcopy((PTR) SS50000_MISC_ERRORS, DB_SQLSTATE_STRING_LEN, (PTR) scf_cb.scf_aux_union.scf_sqlstate.db_sqlstate); scf_cb.scf_len_union.scf_blength = msg_length; scf_cb.scf_ptr_union.scf_buffer = msg_buffer; scf_cb.scf_session = DB_NOSESSION; if (DB_SUCCESS_MACRO(status)) scf_status = scf_call(SCC_TRACE, &scf_cb); else { /* Dump the session that caused this error */ if ((error % 256) >= 128) scs_avformat(); /* dump info on internal ** consistency checks only, ** i.e. do not dump for errors like ** OP0008 */ scf_status = scf_call(SCC_ERROR, &scf_cb); } if (scf_status != E_DB_OK) { TRdisplay("SCF error displaying OPF message to user\n"); TRdisplay("OPF message is :%s",msg_buffer); } return (scf_status); }
/*{ ** Name: psq_tclose - Close the memory stream for a text chain ** ** Description: ** This function closes the memory stream for a text chain, deallocating ** the memory. ** ** Inputs: ** header Pointer to header of text chain ** err_blk Filled in if an error happens ** ** Outputs: ** err_blk Filled in if an error happened ** Returns: ** E_DB_OK Success ** E_DB_ERROR Non-catastrophic failure ** E_DB_FATAL Catastrophic failure ** Exceptions: ** none ** ** Side Effects: ** Deallocates memory ** ** History: ** 18-jul-86 (jeff) ** written */ DB_STATUS psq_tclose( PTR header, DB_ERROR *err_blk) { DB_STATUS status; ULM_RCB ulm_rcb; i4 err_code; STRUCT_ASSIGN_MACRO(((PSQ_THEAD*)header)->psq_tmem, ulm_rcb); status = ulm_closestream(&ulm_rcb); if (status != E_DB_OK) { (VOID) psf_error(E_PS0372_CLOSE_TEXT_CHAIN, ulm_rcb.ulm_error.err_code, PSF_INTERR, &err_code, err_blk, 0); return (status); } return (E_DB_OK); }
/*{ ** Name: psf_munlock - Unlock a QSO object stream ** ** Description: ** This function unlocks the specified QSO object. ** ** Inputs: ** sess_cb Ptr to session's CB. ** mstream Pointer to the memory stream ** .psf_mstream.qso_handle Object handle ** err_block Pointer to error control block ** ** Outputs: ** mstream Pointer to the memory stream ** .psf_mlock Lock id returned by QSF ** err_blk Filled in with error information. ** E_PS0B05_CANT_UNLOCK Error when unlocking object type. ** ** Returns: ** E_DB_OK Success ** E_DB_ERROR Non-catastrophic failure ** ** Exceptions: ** none ** ** Side Effects: ** none ** ** History: ** 29-nov-93 (rblumer) ** Written. */ DB_STATUS psf_munlock( PSS_SESBLK *sess_cb, PSF_MSTREAM *mstream, DB_ERROR *err_blk) { DB_STATUS status; i4 err_code; sess_cb->pss_qsf_rcb.qsf_lk_id = mstream->psf_mlock; STRUCT_ASSIGN_MACRO(mstream->psf_mstream, sess_cb->pss_qsf_rcb.qsf_obj_id); status = qsf_call(QSO_UNLOCK, &sess_cb->pss_qsf_rcb); if (status != E_DB_OK) { (VOID) psf_error(E_PS0B05_CANT_UNLOCK, sess_cb->pss_qsf_rcb.qsf_error.err_code, PSF_INTERR, &err_code, err_blk, 0); return (status); } mstream->psf_mlock = 0; return (E_DB_OK); } /* end psf_munlock */
DB_STATUS qet_t9_ok_w_ldbs( QEE_DSH *i_dsh_p, QEF_RCB *v_qer_p, bool *o1_ok_p) { DB_STATUS status_0 = E_DB_OK, status_t = E_DB_OK, status_u = E_DB_OK; DB_ERROR ulm_err, tpf_err; QES_DDB_SES *dds_p = & v_qer_p->qef_cb->qef_c2_ddb_ses; TPR_CB tpr_cb, *tpr_p = & tpr_cb; QEF_QP_CB *qp_p = i_dsh_p->dsh_qp_ptr; QEF_AHD *act_p = qp_p->qp_ahd; QEQ_D1_QRY *subqry_p; ULM_RCB ulm; i4 w_ldbcnt; TPR_W_LDB *wldb1_p = (TPR_W_LDB *) NULL, *wldb2_p = (TPR_W_LDB *) NULL; *o1_ok_p = TRUE; /* assume */ if (qp_p->qp_qmode == QEQP_01QM_RETRIEVE) return(E_DB_OK); /* read-only query */ /* assume that there are update sites within this query plan */ /* allocate stream to build list of LDB ptrs; note that this ** stream must be closed upon return from this routine */ STRUCT_ASSIGN_MACRO(Qef_s_cb->qef_s_ulmcb, ulm); ulm.ulm_blocksize = sizeof(TPR_W_LDB); /* allocation size */ status_u = qec_mopen(&ulm); if (status_u) { v_qer_p->error.err_code = ulm.ulm_error.err_code; return(status_u); } /* traverse the action list to build an LDB ptr list */ MEfill(sizeof(tpr_cb), '\0', (PTR) & tpr_cb); tpr_p->tpr_session = dds_p->qes_d2_tps_p; /* TPF session CB ptr */ tpr_p->tpr_rqf = dds_p->qes_d3_rqs_p; /* RQF session CB ptr */ tpr_cb.tpr_15_w_ldb_p = (TPR_W_LDB *) NULL; w_ldbcnt = 0; act_p = qp_p->qp_ahd; while (act_p != (QEF_AHD *) NULL && status_u == E_DB_OK) { if (act_p->ahd_atype == QEA_D1_QRY) { subqry_p = & act_p->qhd_obj.qhd_d1_qry; if (subqry_p->qeq_q3_ctl_info & QEQ_002_USER_UPDATE) { /* an update site */ w_ldbcnt++; ulm.ulm_psize = sizeof(TPR_W_LDB); status_u = qec_malloc(&ulm); if (status_u) { STRUCT_ASSIGN_MACRO(ulm.ulm_error, ulm_err); goto dismantle_9; } else { /* allocation ok */ wldb2_p = (TPR_W_LDB *) ulm.ulm_pptr; if (wldb1_p == (TPR_W_LDB *) NULL) { /* first in list */ tpr_cb.tpr_15_w_ldb_p = wldb1_p = wldb2_p; wldb2_p->tpr_1_prev_p = wldb2_p->tpr_2_next_p = (TPR_W_LDB *) NULL; } else { /* append to list */ wldb1_p->tpr_2_next_p = wldb2_p; wldb2_p->tpr_1_prev_p = wldb1_p; wldb2_p->tpr_2_next_p = (TPR_W_LDB *) NULL; } wldb2_p->tpr_3_ldb_p = subqry_p->qeq_q5_ldb_p; } } } act_p = act_p->ahd_next; /* advance */ } /* call TPF if any update sites */ if (tpr_cb.tpr_15_w_ldb_p != (TPR_W_LDB *) NULL) { status_t = qed_u17_tpf_call(TPF_OK_W_LDBS, & tpr_cb, v_qer_p); if (status_t) STRUCT_ASSIGN_MACRO(tpr_cb.tpr_error, tpf_err); else *o1_ok_p = tpr_cb.tpr_14_w_ldbs_ok; } dismantle_9: /* must always close stream */ status_0 = ulm_closestream(&ulm); if (status_u) { /* return previous ulm error */ STRUCT_ASSIGN_MACRO(ulm_err, v_qer_p->error); return(status_u); } if (status_t) { /* return tpf error */ STRUCT_ASSIGN_MACRO(tpf_err, v_qer_p->error); return(status_t); } if (status_0) { /* return close-stream ulm error */ STRUCT_ASSIGN_MACRO(ulm.ulm_error, v_qer_p->error); } return(status_0); }
/*{ ** Name: psy_dpermit - Define a permit. ** ** INTERNAL PSF call format: status = psy_dpermit(&psy_cb, sess_cb); ** ** EXTERNAL call format: status = psy_call(PSY_DPERMIT, &psy_cb, sess_cb); ** ** Description: ** Given all of the parameters necessary to CREATE/DEFINE a permit on a ** table or view, this function will store the permission in the system ** catalogs. This will include storing the query tree in the tree table, ** storing the text of the query in the iiqrytext table (really done by ** QEF), storing a row in the protect table, and issuing an "alter table" ** operation to DMF to indicate that there are permissions on the given ** table. ** ** Inputs: ** psy_cb ** .psy_qrytext Id of query text as stored in QSF. ** .psy_cols[] Array of columns on which to grant ** permission ** .psy_numcols Number of columns listed above; 0 means ** give permission on all columns ** .psy_intree QSF id of query tree representing the ** where clause in the permit ** .psy_opctl Bit map of defined operations ** .psy_opmap Bit map of permitted operations ** .psy_user Name of user who will get permission ** .psy_terminal Terminal at which permission is given ** (blank if none specified) ** .psy_timbgn Time of day at which the permission ** begins (minutes since 00:00) ** .psy_timend Time of day at which the permission ends ** (minutes since 00:00) ** .psy_daybgn Day of week at which the permission ** begins (0 = Sunday) ** .psy_dayend Day of week at which the permission ends ** (0 = Sunday) ** .psy_grant ** PSY_CPERM CREATE/DEFINE PERMIT ** .psy_tblq head of table queue ** .psy_colq head of column queue ** .psy_usrq head of user queue ** .psy_qlen length of first iiqrytext ** .psy_flags useful info ** PSY_EXCLUDE_COLUMNS user specified a list of columns to ** which privilege should not apply ** sess_cb Pointer to session control block ** (Can be NULL) ** ** Outputs: ** psy_cb ** .psy_txtid Id of query text as stored in the ** iiqrytext system relation. ** .psy_error Filled in if error happens ** Returns: ** E_DB_OK Function completed normally. ** E_DB_WARN Function completed with warning(s); ** E_DB_ERROR Function failed; non-catastrophic error ** E_DB_FATAL Function failed; catastrophic error ** Exceptions: ** none ** ** Side Effects: ** Stores text of query in iiqrytext relation, query tree in tree ** relation, row in protect relation identifying the permit. Does ** an alter table DMF operation to indicate that there are permissions ** on the table. ** ** History: ** 02-oct-85 (jeff) ** written ** 03-sep-86 (seputis) ** changed some psy_cb. to psy_cb-> ** added .db_att_id reference ** changed rdr_cb. rdr_cb-> ** 02-dec-86 (daved) ** bug fixing. check for permit on tables owned by user and not ** view. ** 29-apr-87 (stec) ** Implemented changes for GRANT statement. ** 10-may-88 (stec) ** Make changes for db procs. ** 03-oct-88 (andre) ** Modified call to pst_rgent to pass 0 as a query mode since it is ** clearly not PSQ_DESTROY ** 06-feb-89 (ralph) ** Added support for 300 attributes: ** Use DB_COL_BITS in place of DB_MAX_COLS ** Loop over domset array using DB_COL_WORDS ** 06-mar-89 (ralph) ** GRANT Enhancements, Phase 1: ** Initialize new DB_PROTECTION fields, dbp_seq and dbp_gtype ** 03-apr-89 (ralph) ** GRANT Enhancements, Phase 2: ** Use DBGR_USER when initializing dbp_gtype ** 08-may-89 (ralph) ** Initialize reserved field to blanks (was \0) ** 04-jun-89 (ralph) ** Initialize dbp_fill1 to zero ** Fix unix portability problems ** 02-nov-89 (neil) ** Alerters: Allowed privileges for events. ** 1-mar-90 (andre) ** If processing a GRANT on tables, check if ** ALL-TO-ALL or RETRIEVE-TO-ALL has already been granted, and if so, ** mark psy_mask appropriately. ** If user tried to CREATE ALL/RETRIEVE-TO-ALL, and one already exists, ** skip to the exit. ** 12-mar-90 (andre) ** set rdr_2types_mask to 0. ** 22-may-90 (teg) ** init rdr_instr to RDF_NO_INSTR ** 08-aug-90 (ralph) ** Initialize new fields in iiprotect tuple ** 14-dec-90 (ralph) ** Disallow use of GRANT by non-DBA if xORANGE ** 11-jan-90 (ralph) ** Allow user "$ingres" to use GRANT if xORANGE. ** This was done for CREATEDB (UPGRADEFE). ** 20-feb-91 (andre) ** For CREATE/DEFINE PERMIT, grantee type was stored in ** psy_cb->psy_gtype. ** 24-jun-91 (andre) ** IIPROTECT tuples for table permits will contain exactly one ** privilege. IIQRYTEXT template built for table-wide privileges ** contains a placeholder for a privilege name which will be filled in ** with each of the table-wide privileges being granted, one at a time. ** PSY_CB.psy_opmap will be set to correspond with privilege name ** stored in the IIQRYTEXT permit. ** 16-jul-91 (andre) ** responsibility for splitting permit tuples will passed on to ** qeu_cprot(). If a permit specified only one privilege, we will ** substitute the appropriate privilege name here and will not ask ** qeu_cprot() to split tuples. ** 06-aug-91 (andre) ** before proceeding to CREATE a permit on a view owned by the current ** user, we will call psy_tbl_grant_check() to ensure that this user ** may create a permit on his view. If the object is not owned by the ** current user, we will not try to verify that the user may ** CREATE/DEFINE a permit since (until the relevant FE changes are ** made) we intend to continue allowing any user with CATUPD to ** CREATE/DEFINE permits on catalogs and the dba will be allowed to ** CREATE/DEFINE permits on extended catalogs ** 11-nov-91 (rblumer) ** merged from 6.4: 26-feb-91 (andre) ** PST_QTREE was changed to store the range table as an array of ** pointers to PST_RNGENTRY structure. ** 14-feb-92 (andre) ** we will no longer have to fill in privilege name for permits ** specifying one privilege - it will be handled in respective ** grammars. ** 15-jun-92 (barbara) ** For Sybil, change interface to pst_rgent(), Star returns from ** psy_dpermit before permits get stored. ** 07-jul-92 (andre) ** DB_PROTECTION tuple will contain an indicator of how the permit was ** created, i.e. whether it was created using SQL or QUEL and if the ** former, then whether it was created using GRANT statement. Having ** this information will facilitate merging similar and identical ** permit tuples. ** 14-jul-92 (andre) ** semantics of GRANT ALL [PRIVILEGES] is different from that of ** CREATE PERMIT ALL in that the former (as dictated by SQL92) means ** "grant all privileges which the current auth id posesses WGO" ** whereas the latter (as is presently interpreted) means "grant all ** privileges that can be defined on the object" which in case of ** tables and views means SELECT, INSERT, DELETE, UPDATE. ** psy_tbl_grant_check() (function responsible for determining whether ** a user may grant specified privilege on a specified table or view) ** will have to be notified whether we are processing GRANT ALL. Its ** behaviour will change as follows: ** - if processing GRANT ALL and psy_tbl_grant_check() determines ** that the user does not possess some (but not all) of the ** privileges passed to it by the caller it will not treat it as an ** error, but will instead inform the caller of privileges that the ** user does not posess, ** - if processing GRANT ALL and psy_tbl_grant_check() determines ** that the user does not possess any of the privileges passed to ** it by the caller it will treat it as an error ** - if processing a statement other than GRANT ALL and ** psy_tbl_grant_check() determines that the user does not possess ** some of the privileges passed to it by the caller it will treat ** it as an error ** 16-jul-92 (andre) ** if a permit being created depends on some privileges, build a ** structure describing these privileges and store its address in ** rdf_cb->rdr_indep. ** 18-jul-92 (andre) ** we will no longer be telling QEF to turn off DMT_ALL_PROT or ** DMT_RETRIEVE_PRO when a user creates ALL/RETRIEVE TO ALL permit. ** QEF will figure out on its own whether PUBLIC now has RETRIEVE or ** ALL on a table/view ** 20-jul-92 (andre) ** if user specified a list of columns to which privilege(s) should ** not apply, set dbp_domset correctly ** 03-aug-92 (barbara) ** Invalidate base table infoblk from RDF cache for CREATE PERMIT ** and CREATE SEC_ALARM. ** 16-sep-92 (andre) ** privilege maps are build using bitwise ops, so care should be ** exercised when accessing it using BT*() functions ** 17-jun-93 (andre) ** changed interface of psy_secaudit() to accept PSS_SESBLK ** 5-jul-93 (robf) ** changed interface of psy_secaudit() to accept security label ** 7-jan-94 (swm) ** Bug #58635 ** Added PTR cast for qsf_owner which has changed type to PTR. ** 06-mar-96 (nanpr01) ** Move the QSF request block initialization up. because if ** pst_rgnent returns a failure status code, subsequent QSF ** calls get bad control block error. */ DB_STATUS psy_dpermit( PSY_CB *psy_cb, PSS_SESBLK *sess_cb) { RDF_CB rdf_cb; register RDR_RB *rdf_rb = &rdf_cb.rdf_rb; QSF_RCB qsf_rb; DB_STATUS status; DB_STATUS stat; DB_PROTECTION ptuple; register DB_PROTECTION *protup = &ptuple; i4 *domset = ptuple.dbp_domset; register i4 i, j; i4 err_code; PSS_RNGTAB *rngvar; PSS_USRRANGE *rngtab; PST_PROCEDURE *pnode; PST_QTREE *qtree; DB_ERROR *err_blk = &psy_cb->psy_error; i4 textlen; i4 tree_lock = 0; i4 text_lock = 0; DB_TAB_ID tabids[PST_NUMVARS]; PSQ_INDEP_OBJECTS indep_objs; PSQ_OBJPRIV obj_priv; /* space for independent DELETE */ PSQ_COLPRIV col_privs[2]; /* ** space for independent INSERT and ** UPDATE */ PST_VRMAP varmap; PSY_TBL *psy_tbl; DB_TIME_ID timeid; DB_NAME *objname; /* ** For CREATE/DEFINE PERMIT execute code below. */ /* initialize the QSF control block */ qsf_rb.qsf_type = QSFRB_CB; qsf_rb.qsf_ascii_id = QSFRB_ASCII_ID; qsf_rb.qsf_length = sizeof(qsf_rb); qsf_rb.qsf_owner = (PTR)DB_PSF_ID; qsf_rb.qsf_sid = sess_cb->pss_sessid; rngtab = &sess_cb->pss_auxrng; /* table info is stored in the only entry in the table queue */ psy_tbl = (PSY_TBL *) psy_cb->psy_tblq.q_next; status = pst_rgent(sess_cb, rngtab, -1, "", PST_SHWID, (DB_TAB_NAME *) NULL, (DB_TAB_OWN *) NULL, &psy_tbl->psy_tabid, TRUE, &rngvar, (i4) 0, err_blk); if (DB_FAILURE_MACRO(status)) goto exit; /* In STAR, we do not actually store permits */ if (sess_cb->pss_distrib & DB_3_DDB_SESS) { qsf_rb.qsf_lk_state = QSO_EXLOCK; goto exit; } /* Fill in the RDF request block */ pst_rdfcb_init(&rdf_cb, sess_cb); /* The table which is receiving the permit */ STRUCT_ASSIGN_MACRO(psy_tbl->psy_tabid, rdf_rb->rdr_tabid); /* Tell RDF we're doing a permit definition */ rdf_rb->rdr_update_op = RDR_APPEND; rdf_rb->rdr_types_mask = RDR_PROTECT; rdf_rb->rdr_qrytuple = (PTR) protup; /* initialize independent object structure */ indep_objs.psq_objs = (PSQ_OBJ *) NULL; indep_objs.psq_objprivs = (PSQ_OBJPRIV *) NULL; indep_objs.psq_colprivs = (PSQ_COLPRIV *) NULL; indep_objs.psq_grantee = &sess_cb->pss_user; rdf_rb->rdr_indep = (PTR) &indep_objs; /* ** populate the IIPROTECT tuple */ /* Zero out the template */ (VOID)MEfill(sizeof(ptuple), (u_char) 0, (PTR) protup); /* store grantee type */ protup->dbp_gtype = psy_cb->psy_gtype; /* Init reserved block */ (VOID)MEfill(sizeof(protup->dbp_reserve), (u_char) ' ', (PTR) protup->dbp_reserve); /* Init obj name */ STRUCT_ASSIGN_MACRO(psy_tbl->psy_tabnm, protup->dbp_obname); /*@FIX_ME@ Where does this come from? */ protup->dbp_obstat = ' '; /* store the object type indicator */ if (psy_tbl->psy_mask & PSY_OBJ_IS_TABLE) { protup->dbp_obtype = DBOB_TABLE; } else if (psy_tbl->psy_mask & PSY_OBJ_IS_VIEW) { protup->dbp_obtype = DBOB_VIEW; } else { protup->dbp_obtype = DBOB_INDEX; } STRUCT_ASSIGN_MACRO(psy_tbl->psy_owner, protup->dbp_obown); STRUCT_ASSIGN_MACRO(sess_cb->pss_user, protup->dbp_grantor); TMnow((SYSTIME *)&timeid); protup->dbp_timestamp.db_tim_high_time = timeid.db_tim_high_time; protup->dbp_timestamp.db_tim_low_time = timeid.db_tim_low_time; /* The table on which we're giving permission */ STRUCT_ASSIGN_MACRO(psy_tbl->psy_tabid, protup->dbp_tabid); /* Beginning and ending times of day */ protup->dbp_pdbgn = psy_cb->psy_timbgn; protup->dbp_pdend = psy_cb->psy_timend; /* Beginning and ending days of week */ protup->dbp_pwbgn = psy_cb->psy_daybgn; protup->dbp_pwend = psy_cb->psy_dayend; if (psy_cb->psy_numcols != 0 && ~psy_cb->psy_flags & PSY_EXCLUDE_COLUMNS) { /* user specified a list of columns to which privilege(s) will apply */ /* Bit map of permitted columns */ psy_fill_attmap(domset, ((i4) 0)); for (i = 0; i < psy_cb->psy_numcols; i++) { BTset((i4)psy_cb->psy_cols[i].db_att_id, (char *) domset); } } else { /* ** user specified table-wide privilege(s) or a list of columns L s.t. ** privilege(s) will apply to the entire table except for columns in L */ psy_fill_attmap(domset, ~((i4) 0)); if (psy_cb->psy_flags & PSY_EXCLUDE_COLUMNS) { /* ** exclude specified columns from the list of columns to which ** privilege(s) will apply */ for (i = 0; i < psy_cb->psy_numcols; i++) { BTclear((i4) psy_cb->psy_cols[i].db_att_id, (char *) domset); } } } if (rngvar->pss_tabdesc->tbl_status_mask & DMT_VIEW) { /* ** if view is owned by the current user, psy_tbl_grant_check() will ** determine if the permit can, indeed, be created; as long as we are ** preserving the kludge that allows users with CATUPD create permits on ** catalogs and DBAs to create permits on extended catalogs, we shall ** not call psy_tbl_grant_check() on view not owned by the current user, ** since it is likely to result in psy_tbl_grant_check() complaining ** about inadequate permissions */ if (!MEcmp((PTR) &rngvar->pss_ownname, (PTR) &sess_cb->pss_user, sizeof(sess_cb->pss_user))) { i4 tbl_wide_privs; PSY_COL_PRIVS col_specific_privs, *csp, indep_col_specific_privs; DB_TAB_ID indep_id; i4 indep_tbl_wide_privs; bool insuf_privs, quel_view; i4 val1, val2; /* ** build maps of table-wide and column-specific privileges for ** psy_tbl_grant_check() ** if a column list was specified with CREATE PERMIT and ** privileges specified in the statement include a set of ** privileges S s.t. for all P in S, P can only be specified as ** table-wide with GRANT statement (currently this includes ** SELECT, INSERT, DELETE), we will make ** psy_tbl_grant_check() think that privileges in S are ** table-wide. ** This will work correctly since if the view was defined over ** some objects owned by other user(s), for every P in S we ** would need table-wide privilege WGO on the underlying object. ** ** For the purposes of providing more descriptive output for ** trace point ps131, if column-list was specified, we will pass ** the map of attributes even if column-specific UPDATE was not ** specified */ if (psy_cb->psy_numcols != 0 && (psy_cb->psy_opmap & DB_REPLACE || ult_check_macro(&sess_cb->pss_trace, 3, &val1, &val2) ) ) { i4 *ip; csp = &col_specific_privs; /* ** column-specific UPDATE privilege will not be translated into ** a table-wide privilege since GRANT allows for specification ** of column-specific UPDATE privilege */ csp->psy_col_privs = psy_cb->psy_opmap & DB_REPLACE; tbl_wide_privs = psy_cb->psy_opmap & ~DB_REPLACE; /* ** if creating a permit on a set of columns and UPDATE is not ** one of the privileges named in the statement, store the ** attribute map in the first element of the attribute map list */ ip = (csp->psy_col_privs) ? csp->psy_attmap[PSY_UPDATE_ATTRMAP].map : csp->psy_attmap->map; /* copy the attribute map */ for (i = 0; i < DB_COL_WORDS; i++, ip++) { *ip = domset[i]; } } else { tbl_wide_privs = psy_cb->psy_opmap; csp = (PSY_COL_PRIVS *) NULL; } status = psy_tbl_grant_check(sess_cb, (i4) PSQ_PROT, &rngvar->pss_tabid, &tbl_wide_privs, csp, &indep_id, &indep_tbl_wide_privs, &indep_col_specific_privs, psy_cb->psy_flags, &insuf_privs, &quel_view, &psy_cb->psy_error); if (DB_FAILURE_MACRO(status)) { goto exit; } if (insuf_privs) { /* must audit failure to create a permit */ if ( Psf_srvblk->psf_capabilities & PSF_C_C2SECURE ) { DB_ERROR e_error; /* Must audit CREATE PERMIT failure. */ status = psy_secaudit(FALSE, sess_cb, (char *)&rngvar->pss_tabdesc->tbl_name, &rngvar->pss_tabdesc->tbl_owner, sizeof(DB_TAB_NAME), SXF_E_TABLE, I_SX2016_PROT_TAB_CREATE, SXF_A_FAIL | SXF_A_CREATE, &e_error); status = (status > E_DB_ERROR) ? status : E_DB_ERROR; } goto exit; } else if (quel_view) { goto exit; } /* ** If user is trying to grant one or more of ** INSERT/DELETE/UPDATE on his/her view whose underlying table ** or view is owned by another user, psy_tbl_grant_check() will ** return id of the underlying object along with map of ** privileges. We will convert maps of independent privileges ** into elements of independent privilege list and pass them ** along to QEF */ if ( indep_id.db_tab_base != (i4) 0 && ( indep_id.db_tab_base != rngvar->pss_tabid.db_tab_base || indep_id.db_tab_index != rngvar->pss_tabid.db_tab_index ) ) { if (indep_tbl_wide_privs & DB_DELETE) { /* ** the only expected independent table-wide privilege ** is DELETE */ obj_priv.psq_next = (PSQ_OBJPRIV *) NULL; obj_priv.psq_objtype = PSQ_OBJTYPE_IS_TABLE; obj_priv.psq_privmap = (i4) DB_DELETE; obj_priv.psq_objid.db_tab_base = indep_id.db_tab_base; obj_priv.psq_objid.db_tab_index = indep_id.db_tab_index; indep_objs.psq_objprivs = &obj_priv; } if (indep_col_specific_privs.psy_col_privs) { i4 i, j; PSQ_COLPRIV *csp; i4 *att_map, *p; i4 priv_map = 0; /* ** privilege map is built using bitwise operators, but ** here using BTnext() makes code much more palatable, ** so convert a privilege map */ if (indep_col_specific_privs.psy_col_privs & DB_APPEND) BTset(DB_APPP, (char *) &priv_map); if (indep_col_specific_privs.psy_col_privs & DB_REPLACE) BTset(DB_REPP, (char *) &priv_map); for (i = -1, csp = col_privs; (i = BTnext(i, (char *) &priv_map, BITS_IN(priv_map))) != -1; csp++ ) { csp->psq_next = indep_objs.psq_colprivs; indep_objs.psq_colprivs = csp; csp->psq_objtype = PSQ_OBJTYPE_IS_TABLE; csp->psq_tabid.db_tab_base = indep_id.db_tab_base; csp->psq_tabid.db_tab_index = indep_id.db_tab_index; switch (i) { case DB_APPP: /* INSERT privilege */ { csp->psq_privmap = (i4) DB_APPEND; att_map = indep_col_specific_privs. psy_attmap[PSY_INSERT_ATTRMAP].map; break; } case DB_REPP: { csp->psq_privmap = (i4) DB_REPLACE; att_map = indep_col_specific_privs. psy_attmap[PSY_UPDATE_ATTRMAP].map; break; } } for (p = csp->psq_attrmap, j = 0; j < DB_COL_WORDS; j++) { *p++ = *att_map++; } } } } } else { /* ** either this is a catalog and the user has CATUPD or ** this is an extended catalog and the user is the DBA; ** since we may be allowing a user to create a permit by ** circumventing the permit system, we only need to ascertain that ** this is an SQL view */ i4 issql = 0; status = psy_sqlview(rngvar, sess_cb, err_blk, &issql); if (status) { goto exit; } if (!issql) { /* can only have permits on SQL views */ psf_error(3598L, 0L, PSF_USERERR, &err_code, err_blk, 1, psf_trmwhite(sizeof(rngvar->pss_tabname), (char *) &rngvar->pss_tabname), &rngvar->pss_tabname); status = E_DB_ERROR; goto exit; } } } /* Name of user getting permission */ STRUCT_ASSIGN_MACRO(psy_cb->psy_user, protup->dbp_owner); /* Terminal at which permission given */ STRUCT_ASSIGN_MACRO(psy_cb->psy_terminal, protup->dbp_term); /* Give RDF pointer to query tree, if any */ if (!psy_cb->psy_istree) { rdf_rb->rdr_qry_root_node = (PTR) NULL; } else { PST_VRMAP varset; i4 j; STRUCT_ASSIGN_MACRO(psy_cb->psy_intree, qsf_rb.qsf_obj_id); qsf_rb.qsf_lk_state = QSO_EXLOCK; status = qsf_call(QSO_LOCK, &qsf_rb); if (DB_FAILURE_MACRO(status)) { (VOID) psf_error(E_PS0D19_QSF_INFO, qsf_rb.qsf_error.err_code, PSF_INTERR, &err_code, err_blk, 0); goto exit; } tree_lock = qsf_rb.qsf_lk_id; pnode = (PST_PROCEDURE *) qsf_rb.qsf_root; qtree = (PST_QTREE *) pnode->pst_stmts->pst_specific.pst_tree; rdf_rb->rdr_qry_root_node = (PTR) pnode; /* check for no views in the qualification. */ (VOID)psy_varset(qtree->pst_qtree, &varset); j = BTnext(-1, (char *) &varset, BITS_IN(varset)); for ( ; j >= 0; j = BTnext(j, (char *) &varset, BITS_IN(varset))) { status = pst_rgent(sess_cb, rngtab, -1, "", PST_SHWID, (DB_TAB_NAME *) NULL, (DB_TAB_OWN *) NULL, &qtree->pst_rangetab[j]->pst_rngvar, TRUE, &rngvar, (i4) 0, err_blk); if (status) goto exit; if (rngvar->pss_tabdesc->tbl_status_mask & DMT_VIEW) { psf_error(3597L, 0L, PSF_USERERR, &err_code, err_blk, 1, psf_trmwhite(sizeof(rngvar->pss_tabname), (char *) &rngvar->pss_tabname), &rngvar->pss_tabname); status = E_DB_ERROR; goto exit; } } } /* Give RDF a pointer to the query text to be stored in iiqrytext */ STRUCT_ASSIGN_MACRO(psy_cb->psy_qrytext, qsf_rb.qsf_obj_id); qsf_rb.qsf_lk_state = QSO_EXLOCK; status = qsf_call(QSO_LOCK, &qsf_rb); if (DB_FAILURE_MACRO(status)) { (VOID) psf_error(E_PS0D19_QSF_INFO, qsf_rb.qsf_error.err_code, PSF_INTERR, &err_code, err_blk, 0); goto exit; } text_lock = qsf_rb.qsf_lk_id; MEcopy((char *) qsf_rb.qsf_root, sizeof(i4), (char *) &textlen); rdf_rb->rdr_l_querytext = textlen; rdf_rb->rdr_querytext = ((char *) qsf_rb.qsf_root) + sizeof(i4); rdf_rb->rdr_status = (sess_cb->pss_lang == DB_SQL) ? DB_SQL : 0; /* determine if the permit specifies exactly one privilege */ if (BTcount((char *) &psy_cb->psy_opmap, BITS_IN(psy_cb->psy_opmap)) > 1) { /* ** if permit specified more than one privilege, notify QEF that it will ** have to split the permit into multiple IIPROTECT tuples */ rdf_rb->rdr_instr |= RDF_SPLIT_PERM; } else if (psy_cb->psy_opmap & DB_RETRIEVE) { /* ** if qeu_cprot() will not be splitting the permit into multiple tuples ** and RETRIEVE is the privilege mentioned in it, set the two bits ** associated with DB_RETRIEVE */ psy_cb->psy_opmap |= DB_TEST | DB_AGGREGATE; psy_cb->psy_opctl |= DB_TEST | DB_AGGREGATE; } /* Null out the DMU control block pointer, just in case */ rdf_rb->rdr_dmu_cb = (PTR) NULL; /* produce list of dependent tables */ rdf_rb->rdr_cnt_base_id = 0; if (psy_cb->psy_istree && qtree->pst_qtree) { j = 0; (VOID)psy_varset(qtree->pst_qtree, &varmap); for (i = -1; (i = BTnext(i, (char*) &varmap, PST_NUMVARS)) > -1;) { /* if this is the table that is getting the permit, ignore */ if (qtree->pst_rangetab[i]->pst_rngvar.db_tab_base != psy_tbl->psy_tabid.db_tab_base || qtree->pst_rangetab[i]->pst_rngvar.db_tab_index != psy_tbl->psy_tabid.db_tab_index ) { rdf_rb->rdr_cnt_base_id++; STRUCT_ASSIGN_MACRO(qtree->pst_rangetab[i]->pst_rngvar, tabids[j++]); } } rdf_rb->rdr_base_id = tabids; } protup->dbp_popctl = psy_cb->psy_opctl; protup->dbp_popset = psy_cb->psy_opmap; /* ** store an indication of whether this permit is being created using SQL or ** QUEL */ protup->dbp_flags = (sess_cb->pss_lang == DB_SQL) ? DBP_SQL_PERM : (i2) 0; protup->dbp_flags |= DBP_65_PLUS_PERM; /* Now let RDF do all the work of the permit definition */ status = rdf_call(RDF_UPDATE, (PTR) &rdf_cb); if (DB_FAILURE_MACRO(status)) { if (rdf_cb.rdf_error.err_code == E_RD0002_UNKNOWN_TBL) { (VOID) psf_error(E_PS0903_TAB_NOTFOUND, 0L, PSF_USERERR, &err_code, err_blk, 1, psf_trmwhite(sizeof(psy_tbl->psy_tabnm), (char *) &psy_tbl->psy_tabnm), &psy_tbl->psy_tabnm); } else { (VOID) psf_rdf_error(RDF_UPDATE, &rdf_cb.rdf_error, &psy_cb->psy_error); } goto exit; } /* ** Invalidate base object's infoblk from RDF cache. */ pst_rdfcb_init(&rdf_cb, sess_cb); STRUCT_ASSIGN_MACRO(psy_cb->psy_tables[0], rdf_rb->rdr_tabid); status = rdf_call(RDF_INVALIDATE, (PTR) &rdf_cb); if (DB_FAILURE_MACRO(status)) { (VOID) psf_rdf_error(RDF_INVALIDATE, &rdf_cb.rdf_error, &psy_cb->psy_error); } exit: qsf_rb.qsf_lk_state = QSO_EXLOCK; if (psy_cb->psy_istree) { /* Destroy query tree */ STRUCT_ASSIGN_MACRO(psy_cb->psy_intree, qsf_rb.qsf_obj_id); if ((qsf_rb.qsf_lk_id = tree_lock) == 0) { stat = qsf_call(QSO_LOCK, &qsf_rb); if (DB_FAILURE_MACRO(stat)) { (VOID) psf_error(E_PS0D18_QSF_LOCK, qsf_rb.qsf_error.err_code, PSF_INTERR, &err_code, &psy_cb->psy_error, 0); if (!status || stat == E_DB_FATAL) status = stat; } tree_lock = qsf_rb.qsf_lk_id; } stat = qsf_call(QSO_DESTROY, &qsf_rb); if (DB_FAILURE_MACRO(stat)) { (VOID) psf_error(E_PS0D1A_QSF_DESTROY, qsf_rb.qsf_error.err_code, PSF_INTERR, &err_code, &psy_cb->psy_error, 0); if (!status || stat == E_DB_FATAL) status = stat; } tree_lock = 0; } /* Destroy query text */ STRUCT_ASSIGN_MACRO(psy_cb->psy_qrytext, qsf_rb.qsf_obj_id); if ((qsf_rb.qsf_lk_id = text_lock) == 0) { stat = qsf_call(QSO_LOCK, &qsf_rb); if (DB_FAILURE_MACRO(stat)) { (VOID) psf_error(E_PS0D18_QSF_LOCK, qsf_rb.qsf_error.err_code, PSF_INTERR, &err_code, &psy_cb->psy_error, 0); if (!status || stat == E_DB_FATAL) status = stat; } text_lock = qsf_rb.qsf_lk_id; } stat = qsf_call(QSO_DESTROY, &qsf_rb); if (DB_FAILURE_MACRO(stat)) { (VOID) psf_error(E_PS0D1A_QSF_DESTROY, qsf_rb.qsf_error.err_code, PSF_INTERR, &err_code, &psy_cb->psy_error, 0); if (!status || stat == E_DB_FATAL) status = stat; } return (status); }
/* ** { ** Name: QEA_RUPDATE - update the current cursor ** ** External QEF call: status = qef_call(QEQ_REPLACE, &qef_rcb); ** ** Description: ** The current row in the named cursor (QP) is ** updated and sent to DMF ** ** Inputs: ** action Update current row of cursor action. ** qef_rcb ** assoc_dsh DSH for QP for cursor to be updated. ** reset ** state DSH_CT_INITIAL if this is an action call ** DSH_CT_CONTINUE for call back after processing ** a rule action list. ** ** Outputs: ** qef_rcb ** .qef_remnull SET if an aggregate computation found a NULL val ** .qef_rowcount number of rows replaced ** .qef_targcount number of attempted replaces ** .error.err_code one of the following ** E_QE0000_OK ** E_QE0017_BAD_CB ** E_QE0018_BAD_PARAM_IN_CB ** E_QE0019_NON_INTERNAL_FAIL ** E_QE0002_INTERNAL_ERROR ** E_QE0008_CURSOR_NOT_OPENED ** E_QE0021_NO_ROW ** E_QE0009_NO_PERMISSION ** E_QE000A_READ_ONLY ** E_QE0012_DUPLICATE_KEY ** E_QE0010_DUPLIATE_ROW ** E_QE0011_AMBIGUOUS_REPLACE ** E_QE0013_INTEGRITY_FAILED ** E_QE0024_TRANSACTION_ABORTED ** E_QE0034_LOCK_QUOTA_EXCEEDED ** E_QE0035_LOCK_RESOURCE_BUSY ** E_QE0036_LOCK_TIMER_EXPIRED ** E_QE002A_DEADLOCK ** Returns: ** E_DB_{OK,WARN,ERROR,FATAL} ** Exceptions: ** none ** ** Side Effects: ** none ** ** History: ** 11-JUN-86 (daved) ** written ** 22-may-87 (daved) ** catch cursor not positioned errors ** 14-oct-87 (puree) ** make sure that qen_error is called in case of E_DB_ERROR from ** qeq_validate. ** 02-feb-88 (puree) ** added reset flag to qeq_validate and all qea_xxxx call sequence. ** 29-aug-88 (puree) ** implement replace cursor by tid if the cursor was position on ** a secondary index table and by current position if the cursor ** is positioned on the base table. ** fix duplicate handling error. ** 12-oct-88 (puree) ** If a table validation fails during cursor replace, abort the ** cursor. ** 23-feb-89 (paul) ** Clean up qef_cb state before returning. ** 17-apr-89 (paul) ** Processing cursor updates integrated into qeq_query. Update cursor ** logic moved from qeq.c to this file (qearupd.c). This routine is ** a simplified version of what was previously called qeq_replace. ** 25-sep-89 (paul) ** Added support for using TIDs as parameters to procedures invoked ** from rules. ** 25-jan-90 (nancy) -- set status to E_DB_OK when replace cursor ** causes dups and duplicate handling is set to SKIP_DUPS. ** 29-jan-90 (nancy) -- fix bug 8388 (8575), use assoc dsh for replace ** by tid. ** 29-jun-90 (davebf) ** Handle rows which were accessed by TID only (bug 31113) ** 5-Nov-1993 (fred) ** Remove any remaining large object temporaries. ** 7-Apr-1994 (fred) ** Commented out large object removal pending better way... ** 7-nov-95 (inkdo01) ** Changes to replace QEN_ADF structure instances by pointers in ** QEF_AHD structures. ** 29-dec-03 (inkdo01) ** DSH is now parameter, "function" replaces "reset". ** 5-feb-04 (inkdo01) ** Add support for partitioned tables. ** 12-mar-04 (inkdo01) ** Fix to handle bigtids on byte-swapped machines. ** 19-mar-04 (inkdo01) ** Fix for bigtids and rules. ** 12-may-04 (inkdo01) ** Call qeq_part_open unconditionally - it'll determine whether ** partition cbs are already prepared. ** 8-Jul-2004 (schka24) ** Still some tid byte-ordering confusion on x86, make tid handling ** more portable. ** 26-aug-04 (inkdo01) ** Add global base array support for update buffer. ** 24-Feb-05 (hweho01) ** The copying of tid needs to be handled differently if ** TID_SWAP is defined, so the tid value can be preserved. ** Star #13864021. ** 28-Feb-2005 (schka24) ** Rework the above fix, it turns out that the underlying problem ** was the 4byte-tidp flag not getting set. Now that it's set ** properly, obey it here. Also, do partition opens against the ** cursor query, not the RUP -- it's the one with the valid list.. ** 18-Jul-2005 (schka24) ** Well, I fixed by-tid updates, but not true in-place updates! ** Use new ahd_ruporig machinery to get at the current partition ** number for in-place updating. ** 13-Dec-2005 (kschendel) ** Can count on qen-ade-cx now. ** 16-Jan-2006 (kschendel) ** Access qen-status thru xaddrs. ** 20-june-06 (dougi) ** Add support for BEFORE triggers. ** 1-Nov-2006 (kschendel) ** Some fixes to BEFORE triggers, make sure things are set up. ** 7-mar-2007 (dougi) ** Slight change to address the DMR_CB (broken by BEFORE changes). ** 8-Sep-2008 (kibro01) b120693 ** Remove unused action parameter from qeq_part_open ** 09-Sep-2009 (thaju02) B122374 ** If BEFORE trigger has been executed, do not use ahd_upd_colmap. ** ahd_upd_colmap may not reflect cols updated by the rule/proc. ** 15-Jan-2010 (jonj) ** SIR 121619 MVCC: If E_DM0029_ROW_UPDATE_CONFLICT returned, ** invalidate the QP and retry. ** 1-Jul-2010 (kschendel) b124004 ** Minor changes for RUP from scrollable keyset cursors; the ** fetched row is always in dsh-qef-output. */ DB_STATUS qea_rupdate( QEF_AHD *act, QEF_RCB *qef_rcb, QEE_DSH *dsh, QEE_DSH *assoc_dsh, i4 function, i4 state ) { i4 err; DB_STATUS status = E_DB_OK; QEF_CB *qef_cb = dsh->dsh_qefcb; ADF_CB *adfcb = dsh->dsh_adf_cb; DMR_CB *dmr_cb, *pdmr_cb; QEN_ADF *qen_adf; ADE_EXCB *ade_excb; PTR *assoc_cbs = assoc_dsh->dsh_cbs; PTR output, save_addr; char *tidinput; /* location of tid */ DB_TID8 oldbigtid, newbigtid; u_i2 oldpartno = 0; u_i2 newpartno = 0; i4 odmr_cb_ix; /* CB number of DMR_CB */ i4 orig_node; status = E_DB_OK; for (;;) { /* A cursor update affects only a single row. If we are called back */ /* after rules processing simply return. */ if (state == DSH_CT_CONTINUE) break; /* Address the DMR_CB used to access the row. The odmr_cb_ix is in ** the associated (cursor) QP context. We'll adjust for partitioning ** a bit later. */ odmr_cb_ix = act->qhd_obj.qhd_qep.ahd_odmr_cb; dmr_cb = (DMR_CB*) assoc_cbs[odmr_cb_ix]; if (status == DSH_CT_CONTINUE3) { /* Resuming from a BEFORE trigger, reset variables */ MEcopy(dsh->dsh_row[act->qhd_obj.qhd_qep.u1.s1.ahd_a_tid], sizeof(DB_TID8), (PTR) &newbigtid); MEcopy(dsh->dsh_row[act->qhd_obj.qhd_qep.u1.s1.ahd_b_tid], sizeof(DB_TID8), (PTR) &oldbigtid); oldpartno = oldbigtid.tid.tid_partno; newpartno = newbigtid.tid.tid_partno; output = dsh->dsh_row[act->qhd_obj.qhd_qep.u1.s1.ahd_a_row]; if (act->qhd_obj.qhd_qep.ahd_part_def != NULL) dmr_cb = (DMR_CB *) assoc_cbs[odmr_cb_ix + oldpartno + 1]; } else { /* Normal path */ dsh->dsh_qef_remnull = 0; dsh->dsh_qef_rowcount = 0; /* Use fetch row for holding update row if need be */ output = assoc_dsh->dsh_row[assoc_dsh->dsh_qp_ptr->qp_fetch_ahd->qhd_obj.qhd_qep.ahd_ruprow]; /* make sure we have a positioned record */ if (assoc_dsh->dsh_positioned == FALSE) { /* no record could be valid in this action's updatable control block. ** Nor do we know what we will be looking at when we access the ** update control block index number */ dsh->dsh_error.err_code = E_QE0021_NO_ROW; status = E_DB_ERROR; break; } /* check that this query plan has update privilege */ if ((assoc_dsh->dsh_qp_ptr->qp_status & QEQP_UPDATE) == 0) { /* no permission */ dsh->dsh_error.err_code = E_QE0009_NO_PERMISSION; status = E_DB_ERROR; break; } if (qef_cb->qef_c1_distrib & DB_3_DDB_SESS) /* distributed? */ { /* DDB processing */ status = qeq_c5_replace(qef_rcb, dsh); if (status == E_DB_OK) dsh->dsh_qef_rowcount = 1; else dsh->dsh_qef_rowcount = 0; return(status); } /* LDB processing */ /* process the qualification expression */ qen_adf = act->qhd_obj.qhd_qep.ahd_constant; if (qen_adf != NULL) { ade_excb = (ADE_EXCB*) dsh->dsh_cbs[qen_adf->qen_pos]; if (dsh->dsh_qp_ptr->qp_status & QEQP_GLOBAL_BASEARRAY) dsh->dsh_row[qen_adf->qen_uoutput] = output; else ade_excb->excb_bases[ADE_ZBASE + qen_adf->qen_uoutput] = output; status = qen_execute_cx(dsh, ade_excb); if (status != E_DB_OK) break; /* handle condition where qualification failed. */ if (ade_excb->excb_value != ADE_TRUE) { dsh->dsh_qef_targcount = 1; dsh->dsh_qef_rowcount = 0; break; } } /* REPLACE THE TUPLE ** if the cursor is positioned on the base table (ahd_tidoffset is ** -1), replace the tuple at the current position. Otherwise the ** cursor must have been positioned via a secondary index. Get ** the tid, re-fetch the original row by tid, and replace the ** base table tuple by the tid. */ if (act->qhd_obj.qhd_qep.ahd_tidoffset == -1) { /* If partitioned, dig the current partition number out of ** the node status for the orig (or kjoin/tjoin) node that ** fetched the row in the first place. OPC has kindly put ** the node number of same into ahd_ruporig. */ if (act->qhd_obj.qhd_qep.ahd_part_def != NULL) { orig_node = act->qhd_obj.qhd_qep.ahd_ruporig; if (orig_node == -1) { TRdisplay("%@ qea_rupd: missing ahd_ruporig\n"); dsh->dsh_error.err_code = E_QE0002_INTERNAL_ERROR; status = E_DB_ERROR; break; } oldpartno = assoc_dsh->dsh_xaddrs[orig_node]-> qex_status->node_ppart_num; dmr_cb = (DMR_CB *) assoc_cbs[odmr_cb_ix + oldpartno + 1]; } dmr_cb->dmr_flags_mask = DMR_CURRENT_POS; } else { /* set the tid */ tidinput = (char *) assoc_dsh->dsh_row[act->qhd_obj.qhd_qep.ahd_tidrow] + act->qhd_obj.qhd_qep.ahd_tidoffset; if (act->qhd_obj.qhd_qep.ahd_qepflag & AHD_4BYTE_TIDP) { I4ASSIGN_MACRO(*tidinput, oldbigtid.tid_i4.tid ); oldbigtid.tid_i4.tpf = 0; } else { I8ASSIGN_MACRO(*tidinput, oldbigtid); } oldpartno = oldbigtid.tid.tid_partno; newpartno = oldpartno; /* Check for partitioning and set up DMR_CB. */ if (act->qhd_obj.qhd_qep.ahd_part_def) { /* Open against "get" action. The RUP action dmtix and ** flags are the same as the cursor's, thanks to OPC. */ status = qeq_part_open(qef_rcb, assoc_dsh, NULL, 0, odmr_cb_ix, act->qhd_obj.qhd_qep.ahd_dmtix, oldpartno); if (status != E_DB_OK) { dsh->dsh_error.err_code = assoc_dsh->dsh_error.err_code; return(status); } pdmr_cb = (DMR_CB *)assoc_cbs[odmr_cb_ix + oldpartno+1]; STRUCT_ASSIGN_MACRO(dmr_cb->dmr_data, pdmr_cb->dmr_data); dmr_cb = pdmr_cb; } dmr_cb->dmr_tid = oldbigtid.tid_i4.tid; dmr_cb->dmr_flags_mask = DMR_BY_TID; /* get the tuple to be updated. */ save_addr = dmr_cb->dmr_data.data_address; dmr_cb->dmr_data.data_address = output; status = dmf_call(DMR_GET, dmr_cb); dmr_cb->dmr_data.data_address = save_addr; if (status != E_DB_OK) { dsh->dsh_error.err_code = dmr_cb->error.err_code; return (status); } } /* If we have rules, save a copy of the row before updating */ if (act->qhd_obj.qhd_qep.ahd_after_act != NULL || act->qhd_obj.qhd_qep.ahd_before_act != NULL) { MEcopy(output, act->qhd_obj.qhd_qep.ahd_repsize, dsh->dsh_row[act->qhd_obj.qhd_qep.u1.s1.ahd_b_row]); oldbigtid.tid_i4.tpf = 0; oldbigtid.tid_i4.tid = dmr_cb->dmr_tid; oldbigtid.tid.tid_partno = oldpartno; } /* process the update expression */ qen_adf = act->qhd_obj.qhd_qep.ahd_current; ade_excb = (ADE_EXCB*) dsh->dsh_cbs[qen_adf->qen_pos]; if (dsh->dsh_qp_ptr->qp_status & QEQP_GLOBAL_BASEARRAY) dsh->dsh_row[qen_adf->qen_uoutput] = output; else ade_excb->excb_bases[ADE_ZBASE+qen_adf->qen_uoutput] = output; status = qen_execute_cx(dsh, ade_excb); if (status != E_DB_OK) break; /* Check for partitioning and see if we changed target partition. */ if (act->qhd_obj.qhd_qep.ahd_part_def && (act->qhd_obj.qhd_qep.ahd_qepflag & AHD_PCOLS_UPDATE)) { status = adt_whichpart_no(adfcb, act->qhd_obj.qhd_qep.ahd_part_def, output, &newpartno); if (status != E_DB_OK) return(status); } /* Process BEFORE triggers (if any). */ if (act->qhd_obj.qhd_qep.ahd_before_act != NULL) { /* ** Place the TID in a known location so it can be used ** as a parameter to the procedure fired by the rule. */ newbigtid.tid_i4.tpf = 0; newbigtid.tid_i4.tid = dmr_cb->dmr_tid; newbigtid.tid.tid_partno = newpartno; MEcopy ((PTR)&newbigtid, sizeof(DB_TID8), dsh->dsh_row[act->qhd_obj.qhd_qep.u1.s1.ahd_a_tid]); MEcopy ((PTR)&oldbigtid, sizeof(DB_TID8), dsh->dsh_row[act->qhd_obj.qhd_qep.u1.s1.ahd_b_tid]); MEcopy(output, act->qhd_obj.qhd_qep.ahd_repsize, dsh->dsh_row[act->qhd_obj.qhd_qep.u1.s1.ahd_a_row]); dsh->dsh_ctx_act[dsh->dsh_depth_act].dsh_ct_ptr = act; dsh->dsh_ctx_act[dsh->dsh_depth_act].dsh_ct_status = DSH_CT_CONTINUE3; dsh->dsh_depth_act++; dsh->dsh_act_ptr = act->qhd_obj.qhd_qep.ahd_before_act; dsh->dsh_error.err_code = E_QE0120_RULE_ACTION_LIST; status = E_DB_ERROR; break; } } /* end of !DSH_CT_CONTINUE3 */ state = DSH_CT_INITIAL; /* signal resumption after ** BEFORE trigger */ if (act->qhd_obj.qhd_qep.ahd_qepflag & AHD_PCOLS_UPDATE && oldpartno != newpartno) { /* Partition has changed for row in partitioned table. ** Delete from 1st partition and insert into next. ** We have to hope that DMF can keep it all straight. */ status = dmf_call(DMR_DELETE, dmr_cb); if (status != E_DB_OK) { if (dmr_cb->error.err_code == E_DM0055_NONEXT) dsh->dsh_error.err_code = 4599; else dsh->dsh_error.err_code = dmr_cb->error.err_code; break; } /* Get output partition DMR_CB, then do DMR_PUT. ** Don't change the fetching DSH's current dmr-cb in case ** we're running a true in-place cursor. */ status = qeq_part_open(qef_rcb, assoc_dsh, NULL, 0, odmr_cb_ix, act->qhd_obj.qhd_qep.ahd_dmtix, newpartno); if (status != E_DB_OK) { dsh->dsh_error.err_code = assoc_dsh->dsh_error.err_code; return(status); } dmr_cb = (DMR_CB *)assoc_cbs[odmr_cb_ix + newpartno+1]; dsh->dsh_qef_targcount = 1; /* Final preparation of new partition DMR_CB. */ dmr_cb->dmr_flags_mask = 0; dmr_cb->dmr_val_logkey = 0; dmr_cb->dmr_data.data_address = output; dmr_cb->dmr_data.data_in_size = act->qhd_obj.qhd_qep.ahd_repsize; if (act->qhd_obj.qhd_qep.ahd_duphandle != QEF_SKIP_DUP) dmr_cb->dmr_flags_mask |= DMR_DUP_ROLLBACK; status = dmf_call(DMR_PUT, dmr_cb); } else { dsh->dsh_qef_targcount = 1; if ((act->qhd_obj.qhd_qep.ahd_upd_colmap) && (act->qhd_obj.qhd_qep.ahd_before_act == NULL)) dmr_cb->dmr_attset = (char *)act->qhd_obj.qhd_qep.ahd_upd_colmap; else dmr_cb->dmr_attset = (char *)0; if (act->qhd_obj.qhd_qep.ahd_duphandle != QEF_SKIP_DUP) dmr_cb->dmr_flags_mask |= DMR_DUP_ROLLBACK; status = dmf_call(DMR_REPLACE, dmr_cb); } if (status == E_DB_OK || ((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) && act->qhd_obj.qhd_qep.ahd_duphandle == QEF_SKIP_DUP)) { if (status == E_DB_OK) { dsh->dsh_qef_rowcount = 1; /* Look for rules to apply */ if (act->qhd_obj.qhd_qep.ahd_after_act != NULL) { /* ** Place the TID in a known location so it can be used ** as a parameter to the procedure fired by the rule. */ newbigtid.tid_i4.tpf = 0; newbigtid.tid_i4.tid = dmr_cb->dmr_tid; newbigtid.tid.tid_partno = newpartno; MEcopy ((PTR)&newbigtid, sizeof(DB_TID8), dsh->dsh_row[act->qhd_obj.qhd_qep.u1.s1.ahd_a_tid]); MEcopy ((PTR)&oldbigtid, sizeof(DB_TID8), dsh->dsh_row[act->qhd_obj.qhd_qep.u1.s1.ahd_b_tid]); MEcopy(output, act->qhd_obj.qhd_qep.ahd_repsize, dsh->dsh_row[act->qhd_obj.qhd_qep.u1.s1.ahd_a_row]); dsh->dsh_ctx_act[dsh->dsh_depth_act].dsh_ct_ptr = act; dsh->dsh_ctx_act[dsh->dsh_depth_act].dsh_ct_status = DSH_CT_CONTINUE; dsh->dsh_depth_act++; dsh->dsh_act_ptr = act->qhd_obj.qhd_qep.ahd_after_act; dsh->dsh_error.err_code = E_QE0120_RULE_ACTION_LIST; status = E_DB_ERROR; break; } } else { dsh->dsh_qef_rowcount = 0; status = E_DB_OK; } break; } if (dmr_cb->error.err_code == E_DM0055_NONEXT) dsh->dsh_error.err_code = 4599; else if ( dmr_cb->error.err_code == E_DM0029_ROW_UPDATE_CONFLICT ) { dsh->dsh_qp_status |= DSH_QP_OBSOLETE; dsh->dsh_error.err_code = E_QE0023_INVALID_QUERY; status = E_DB_WARN; } else dsh->dsh_error.err_code = dmr_cb->error.err_code; break; } return (status); }
/*{ ** Name: psq_cbreturn - Clear call and session CB after processing. ** ** Description: ** This routine is a common routine that clears up the call (psq_cb) and ** session CB (sess_cb) after processing a query. The routine ** psq_parseqry still does its own work as it handles various errors ** associated with textual queries. ** ** Inputs: ** psq_cb Pointer to call CB. ** sess_cb Pointer to the session control block ** ** Outputs: ** psq_cb ** .psq_result Result query tree. ** Returns: ** DB_STATUS ** Exceptions: ** None ** ** Side Effects: ** None ** ** History: ** 21-apr-89 (neil) ** Extracted this from psq_parseqry to allow it to be called from ** other routines as well. ** 15-jun-92 (barbara) ** Sybil merge. Pass in sess control block to pst_clrrng. ** 25-may-1993 (rog) ** Moved clean-up/exit code here from psq_parseqry() above, and added ** status argument so that we know whether to execute the good exit ** code or the bad exit code. ** 10-aug-93 (andre) ** fixed cause of a compiler warning ** 27-aug-93 (andre) ** (part of fix for bug 54348) ** moved code responsible for destroying a dbproc QEP into a separate ** function (psq_destr_dbp_qep()) which will be called from ** psq_cbreturn() and from psq_recreate() if an error occurs AFTER the ** dbproc QEP QSF object has been created ** 16-mar-94 (andre) ** use psf_retry() to determine whether we are going to retry parsing ** this query and, therefore, whether we should destroy any QSF objects ** created during the just completed attempt ** 28-jan-2004 (schka24) ** Close partition def memory if open. ** 15-Mar-2006 (kschendel) ** Close function-arg stream if open. ** 28-nov-2007 (dougi) ** Different logic for PSQ_REPDYN (for cached dynamic queries). */ DB_STATUS psq_cbreturn( PSQ_CB *psq_cb, PSS_SESBLK *sess_cb, DB_STATUS ret_val) { DB_STATUS status; i4 err_code; QSF_RCB qsf_rb; qsf_rb.qsf_type = QSFRB_CB; qsf_rb.qsf_ascii_id = QSFRB_ASCII_ID; qsf_rb.qsf_length = sizeof(qsf_rb); qsf_rb.qsf_owner = (PTR)DB_PSF_ID; qsf_rb.qsf_sid = sess_cb->pss_sessid; /* Tasks that are common to both a normal return and an error return. */ do /* Something to break out of */ { /* Clear any cached stack blocks as we're going to ** trash the memory stream in here anyway. */ sess_cb->pss_stk_freelist = NULL; /* Other stuff that shouldn't be left dangling */ sess_cb->pss_yyvars = NULL; /* ** Clear out the user's range table. */ status = pst_clrrng(sess_cb, &sess_cb->pss_usrrange, &psq_cb->psq_error); if (status == E_DB_FATAL) ret_val = status; /* ** Clear out the auxliary range table. */ status = pst_clrrng(sess_cb, &sess_cb->pss_auxrng, &psq_cb->psq_error); if (status == E_DB_FATAL) ret_val = status; /* ** If the statement has emitted query text, close the stream. */ if (sess_cb->pss_tchain != (PTR) NULL) { status = psq_tclose(sess_cb->pss_tchain, &psq_cb->psq_error); if (status == E_DB_FATAL) ret_val = status; sess_cb->pss_tchain = (PTR) NULL; } if (sess_cb->pss_tchain2 != (PTR) NULL) { status = psq_tclose(sess_cb->pss_tchain2, &psq_cb->psq_error); if (status == E_DB_FATAL) ret_val = status; sess_cb->pss_tchain2 = (PTR) NULL; } /* Close partition definition working memory stream if in use */ if (sess_cb->pss_ses_flag & PSS_PARTDEF_STREAM_OPEN) { status = ulm_closestream(&sess_cb->pss_partdef_stream); /* Toss any error */ sess_cb->pss_ses_flag &= ~PSS_PARTDEF_STREAM_OPEN; } /* Close nested-function-call arg list stack if it was needed */ if (sess_cb->pss_funarg_stream != NULL) { ULM_RCB ulm; ulm.ulm_facility = DB_PSF_ID; ulm.ulm_poolid = Psf_srvblk->psf_poolid; ulm.ulm_streamid_p = &sess_cb->pss_funarg_stream; ulm.ulm_memleft = &sess_cb->pss_memleft; status = ulm_closestream(&ulm); /* Ignore error */ sess_cb->pss_funarg_stream = NULL; } } while (0); for (; ret_val == E_DB_OK; ) /* Something to break out of */ { /* ** This is the path we take for a successful exit. ** If we have a problem here, we break out of this loop and ** fall through to the failure exit code. */ /* ** Set the QSF id of the return object and unlock it, if any. */ if (sess_cb->pss_ostream.psf_mstream.qso_handle != (PTR) NULL) { qsf_rb.qsf_obj_id.qso_handle = sess_cb->pss_ostream.psf_mstream.qso_handle; qsf_rb.qsf_lk_id = sess_cb->pss_ostream.psf_mlock; if (psq_cb->psq_mode == PSQ_REPDYN) { /* If cached dynamic qp already exists, destroy parse ** tree object. */ if (ret_val = qsf_call(QSO_DESTROY, &qsf_rb)) { (VOID) psf_error(E_PS0A09_CANTDESTROY, qsf_rb.qsf_error.err_code, PSF_INTERR, &err_code, &psq_cb->psq_error, 0); /* break out to the failure code. */ break; } } else { /* If not cached dynamic, copy object ID and unlock ** parse tree. */ STRUCT_ASSIGN_MACRO(sess_cb->pss_ostream.psf_mstream, psq_cb->psq_result); if (ret_val = qsf_call(QSO_UNLOCK, &qsf_rb)) { (VOID) psf_error(E_PS0B05_CANT_UNLOCK, qsf_rb.qsf_error.err_code, PSF_INTERR, &err_code, &psq_cb->psq_error, 0); /* break out to the failure code. */ break; } } sess_cb->pss_ostream.psf_mlock = 0; } /* ** Unlock the text stream if it was used. ** this is unlocked after the text stream is created. ** (Don't know why this was taken out.) */ #ifdef NO if (sess_cb->pss_tstream.psf_mstream.qso_handle != (PTR) NULL) { qsf_rb.qsf_obj_id.qso_handle = sess_cb->pss_tstream.psf_mstream.qso_handle; qsf_rb.qsf_lk_id = sess_cb->pss_tstream.psf_mlock; if (ret_val = qsf_call(QSO_UNLOCK, &qsf_rb)) { (VOID) psf_error(E_PS0B05_CANT_UNLOCK, qsf_rb.qsf_error.err_code, PSF_INTERR, &err_code, &psq_cb->psq_error, 0); /* break out to the failure code. */ break; } sess_cb->pss_tstream.psf_mlock = 0; } #endif /* Unlock the control block stream if it was used */ if (sess_cb->pss_cbstream.psf_mstream.qso_handle != (PTR) NULL) { qsf_rb.qsf_obj_id.qso_handle = sess_cb->pss_cbstream.psf_mstream.qso_handle; qsf_rb.qsf_lk_id = sess_cb->pss_cbstream.psf_mlock; if (ret_val = qsf_call(QSO_UNLOCK, &qsf_rb)) { (VOID) psf_error(E_PS0B05_CANT_UNLOCK, qsf_rb.qsf_error.err_code, PSF_INTERR, &err_code, &psq_cb->psq_error, 0); /* break out to the failure code. */ break; } sess_cb->pss_cbstream.psf_mlock = 0; } /* ** We need to deallocate memory if the same query is to be tried ** again. This is supposed to fix The 'drop table, nonexistent_table' ** memory leak problem. */ if (psf_retry(sess_cb, psq_cb, ret_val)) { if (sess_cb->pss_ostream.psf_mstream.qso_handle != (PTR) NULL) { (VOID) psf_mclose(sess_cb, &sess_cb->pss_ostream, &psq_cb->psq_error); sess_cb->pss_ostream.psf_mstream.qso_handle = (PTR) NULL; } if (sess_cb->pss_tstream.psf_mstream.qso_handle != (PTR) NULL) { (VOID) psf_mclose(sess_cb, &sess_cb->pss_tstream, &psq_cb->psq_error); sess_cb->pss_tstream.psf_mstream.qso_handle = (PTR) NULL; } if (sess_cb->pss_cbstream.psf_mstream.qso_handle != (PTR) NULL) { (VOID) psf_mclose(sess_cb, &sess_cb->pss_cbstream, &psq_cb->psq_error); sess_cb->pss_cbstream.psf_mstream.qso_handle = (PTR) NULL; } } /* end with no output streams */ sess_cb->pss_ostream.psf_mstream.qso_handle = (PTR) NULL; sess_cb->pss_tstream.psf_mstream.qso_handle = (PTR) NULL; sess_cb->pss_cbstream.psf_mstream.qso_handle = (PTR) NULL; if (ret_val == E_DB_OK) { /* ** this IF statement is here to keep acc from complaining - we would ** never reach this point unless ret_val was E_DB_OK */ return (ret_val); } } /* This is the failure exit code. */ /* ** On an error, the yacc error handling function will call psf_error. ** All that's necessary here is to return a status indicating that ** an error has occurred. If an output object has been allocated, ** and the error caused the statement to fail, deallocate the object ** before returning. Same for miscellaneous objects, like control ** blocks and query text. */ if (ret_val == E_DB_ERROR || ret_val == E_DB_FATAL || ret_val == E_DB_SEVERE) { /* ** In case of CREATE PROCEDURE statement we also need to ** destroy the QEP object in QSF if it was created. */ if (sess_cb->pss_ostream.psf_mstream.qso_handle != (PTR) NULL && psq_cb->psq_mode == PSQ_CREDBP ) { DB_STATUS stat; stat = psq_destr_dbp_qep(sess_cb, sess_cb->pss_ostream.psf_mstream.qso_handle, &psq_cb->psq_error); if (stat > ret_val) ret_val = stat; } if (sess_cb->pss_ostream.psf_mstream.qso_handle != (PTR) NULL) { (VOID) psf_mclose(sess_cb, &sess_cb->pss_ostream, &psq_cb->psq_error); sess_cb->pss_ostream.psf_mstream.qso_handle = (PTR) NULL; } if (sess_cb->pss_tstream.psf_mstream.qso_handle != (PTR) NULL) { (VOID) psf_mclose(sess_cb, &sess_cb->pss_tstream, &psq_cb->psq_error); sess_cb->pss_tstream.psf_mstream.qso_handle = (PTR) NULL; } if (sess_cb->pss_cbstream.psf_mstream.qso_handle != (PTR) NULL) { (VOID) psf_mclose(sess_cb, &sess_cb->pss_cbstream, &psq_cb->psq_error); sess_cb->pss_cbstream.psf_mstream.qso_handle = (PTR) NULL; } } /* ** If the statement was a "define cursor" or a "define repeat cursor", ** we have to deallocate the cursor control block, if it was allocated. */ if (sess_cb->pss_cstream != (PTR) NULL) { status = psq_delcursor(sess_cb->pss_crsr, &sess_cb->pss_curstab, &sess_cb->pss_memleft, &psq_cb->psq_error); if (status == E_DB_FATAL) ret_val = status; } return(ret_val); }
/* ** Name: 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_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 */
/*{ ** Name: DI_slave_write - Request a slave to writes page(s) to a file on disk. ** ** Description: ** This routine was created to make DIwrite more readable once ** error checking had been added. See DIwrite for comments. ** ** Inputs: ** f Pointer to the DI file ** context needed to do I/O. ** diop Pointer to dilru file context. ** buf Pointer to page(s) to write. ** page Value indicating page(s) to write. ** num_of_pages number of pages to write ** ** Outputs: ** err_code Pointer to a variable used ** to return operating system ** errors. ** Returns: ** OK ** other errors. ** Exceptions: ** none ** ** Side Effects: ** none ** ** History: ** 30-nov-1992 (rmuth) ** Created. ** 10-oct-1993 (mikem) ** bug #47624 ** Bug 47624 resulted in CSsuspend()'s from the DI system being woken ** up early. Mainline DI would then procede while the slave would ** actually be processing the requested asynchronous action. Various ** bad things could happen after this depending on timing: (mainline ** DI would change the slave control block before slave read it, ** mainline DI would call DIlru_release() and ignore it failing which ** would cause the control block to never be freed eventually leading ** to the server hanging when it ran out of slave control blocks, ... ** ** Fixes were made to scf to hopefully eliminate the unwanted ** CSresume()'s. In addition defensive code has been added to DI ** to catch cases of returning from CSresume while the slave is ** operating, and to check for errors from DIlru_release(). Before ** causing a slave to take action the master will set the slave ** control block status to DI_INPROGRESS, the slave in turn will not ** change this status until it has completed the operation. ** ** The off by one error was caused by the CSsuspend called by ** DI_slave_send() returning early in the case of a DIwrite() of one ** page. The old write loop would increment disl->pre_seek before the ** slave had actually read the control block so the slave would write ** the data from page N to the N+1 location in the file. The ** DI_INPROGRESS flag should stop this, and at least in the one page ** write case we no longer increment disl->pre_seek. ** 23-aug-1993 (bryanp) ** If segment isn't yet mapped, map it! ** 01-oct-1998 (somsa01) ** Return DI_NODISKSPACE when we are out of disk space. */ static STATUS DI_slave_write( DI_IO *f, DI_OP *diop, char *buf, i4 page, i4 num_of_pages, CL_ERR_DESC *err_code) { register DI_SLAVE_CB *disl; ME_SEG_INFO *seginfo; bool direct_write; STATUS big_status = OK, small_status = OK; STATUS intern_status = OK, status; /* unix variables */ int bytes_to_write; do { disl = diop->di_evcb; bytes_to_write = (f->io_bytes_per_page * (num_of_pages)); /* ** Determine whether we're writing from shared memory, and set ** up the segment ID and offset correctly. */ seginfo = ME_find_seg( buf, (char *)buf + bytes_to_write, &ME_segpool); if (seginfo != 0 && (seginfo->flags & ME_SLAVEMAPPED_MASK) == 0) { status = DI_lru_slmapmem(seginfo, &intern_status, &small_status); if (status) break; } if (seginfo != 0 && (seginfo->flags & ME_SLAVEMAPPED_MASK) != 0) { direct_write = TRUE; MEcopy( (PTR)seginfo->key, sizeof(disl->seg_key), (PTR)disl->seg_key); disl->seg_offset = (char *)buf - (char *)seginfo->addr; } else { direct_write = FALSE; seginfo = ME_find_seg(disl->buf, disl->buf, &ME_segpool); if (seginfo) { MEcopy( (PTR)seginfo->key, sizeof(disl->seg_key), (PTR)disl->seg_key); disl->seg_offset= (char *)disl->buf - (char *)seginfo->addr; } else { small_status = DI_BADWRITE; break; } } /* Send file properties to slave */ FPROP_COPY(f->io_fprop,disl->io_fprop); disl->pre_seek = (OFFSET_TYPE)(f->io_bytes_per_page) * (OFFSET_TYPE)(page); disl->file_op = DI_SL_WRITE; /* ** Write the data */ do { if (direct_write) disl->length = bytes_to_write; else { disl->length = min(bytes_to_write, Cs_srv_block.cs_size_io_buf); MEcopy((PTR)buf, disl->length, (PTR)disl->buf); } DI_slave_send( disl->dest_slave_no, diop, &big_status, &small_status, &intern_status); if (( big_status != OK ) || (small_status != OK )) break; if ((small_status = disl->status) != OK ) { STRUCT_ASSIGN_MACRO(disl->errcode, *err_code); } if ((small_status != OK) || (disl->length == 0)) { switch( err_code->errnum ) { case EFBIG: small_status = DI_BADEXTEND; break; case ENOSPC: small_status = DI_NODISKSPACE; break; #ifdef EDQUOT case EDQUOT: small_status = DI_EXCEED_LIMIT; break; #endif default: small_status = DI_BADWRITE; break; } break; } bytes_to_write -= disl->length; buf += disl->length; if (bytes_to_write > 0) disl->pre_seek += (OFFSET_TYPE)disl->length; } while ( bytes_to_write > 0); } while (FALSE); if (big_status != OK ) small_status = big_status; if (small_status != OK ) DIlru_set_di_error( &small_status, err_code, intern_status, DI_GENERAL_ERR); return( small_status ); }
static i4 ad0_clmatch( ADULcstate *pat, /* the string holding the pattern matching char */ u_char *endpat, /* end of the pattern string */ ADULcstate *str, /* the other string */ u_char *endstr, /* end of the string */ bool bignore) /* If TRUE, ignore blanks and null chars */ { i4 oldc; i4 found; i4 bfound; i4 ret_val = -1; auto ADULcstate sst, pst; oldc = 0; adulnext(pat); /* Look for an empty range, if found, just ignore it */ while (adulptr(pat) < endpat) { if (adultrans(pat)/COL_MULTI == DB_PAT_RBRAC) { /* empty range, ignore it */ adulnext(pat); return (ad0_3clexc_pm(pat, endpat, str, endstr, FALSE, bignore)); } else { if (bignore && (adulspace(pat) || adultrans(pat) == 0)) adulnext(pat); else break; } } /* find a non-blank, non-null char in s, if ignoring these */ while (adulptr(str) < endstr) { if (bignore && (adulspace(str) || adultrans(str) == 0)) { adulnext(str); continue; } /* search for a match on 'c' */ found = 0; /* assume failure */ bfound = 0; /* assume failure */ while (adulptr(pat) < endpat) { switch(adultrans(pat)/COL_MULTI) { case DB_PAT_RBRAC: { adulnext(pat); if (bfound) { /* ** Since we found a blank or null char in the pattern ** range, and blanks and null chars are being ignored, ** try this first to see if the two are equal by ** ignoring the range altogether. */ STRUCT_ASSIGN_MACRO(*pat, pst); STRUCT_ASSIGN_MACRO(*str, sst); ret_val = ad0_3clexc_pm(&pst, endpat, &sst, endstr, FALSE, bignore); } if (ret_val != 0 && found) { adulnext(str); ret_val = ad0_3clexc_pm(pat, endpat, str, endstr, FALSE, bignore); } return (ret_val); } case AD_DASH_CHAR: if (oldc == 0 || (adulnext(pat), adulptr(pat) >= endpat)) return (-1); /* not found ... really an error */ if (oldc - adultrans(str) <= 0 && adulcmp(pat, str) >= 0) found++; break; default: oldc = adultrans(pat); if (bignore && (adulspace(pat) || oldc == 0)) bfound++; if (adultrans(str) == oldc) found++; } adulnext(pat); } return (-1); /* no match ... this should actually be an error, ** because if we reach here, we would have an LBRAC ** without an associated RBRAC. */ } return (1); }
static i4 ad0_cpmatch( ADULcstate *pat, /* the string holding the pattern matching char */ u_char *endpat, /* pointer to end of pattern char string */ ADULcstate *str, /* the string to be checked */ u_char *endstr, /* pointer to end of string */ bool bignore) /* if TRUE, we ignore blanks and null chars */ { ADULcstate psave; ADULcstate ssave; u_i4 c; u_i4 d; adulnext(pat); /* ** Skip over blanks and null chars if requested -- This fixes a ** bug where "a* " would not match "aaa". The extra space after ** the '*' is often put in by EQUEL programs. */ while ( adulptr(pat) < endpat && bignore && (adulspace(pat) || (c = adultrans(pat)) == 0) ) { adulnext(pat); } if (adulptr(pat) >= endpat) return (0); /* a match if no more chars in p */ /* ** If the next character in "pat" is not another ** pattern matching character, then scan until ** first matching char and continue comparison. */ c = adultrans(pat)/COL_MULTI; if (c != DB_PAT_ANY && c != DB_PAT_LBRAC && c != DB_PAT_ONE) { while (adulptr(str) < endstr) { d = adultrans(str)/COL_MULTI; if ( adulcmp(pat, str) == 0 || d == DB_PAT_ANY || d == DB_PAT_LBRAC || d == DB_PAT_ONE ) { STRUCT_ASSIGN_MACRO(*pat, psave); STRUCT_ASSIGN_MACRO(*str, ssave); if (ad0_3clexc_pm(&psave, endpat, &ssave, endstr, FALSE, bignore) == 0) return (0); } adulnext(str); } } else { while (adulptr(str) < endstr) { STRUCT_ASSIGN_MACRO(*pat, psave); STRUCT_ASSIGN_MACRO(*str, ssave); if (ad0_3clexc_pm(&psave, endpat, &ssave, endstr, FALSE, bignore) == 0) return (0); /* match */ _VOID_ adultrans(str); adulnext(str); } } return (-1); /* no match */ }