/*{ ** Name: QEU_DELETE - delete tuples from a table ** ** External QEF call: status = qef_call(QEU_DELETE, &qeu_cb); ** ** Description: ** Tuples are deleted from a table opened with the QEU_OPEN ** command. If no qualification is given, the current tuple is ** deleted. ** ** Inputs: ** qeu_cb ** .qeu_eflag designate error handling semantis ** for user errors. ** QEF_INTERNAL return error code. ** QEF_EXTERNAL send message to user. ** .qeu_acc_id table access id ** .qeu_tup_length tuple length of the table ** Only required for keyed delete ** .qeu_qual qualification function ** .qeu_qarg argument to qualification function ** .qeu_klen length of key - number of entries ** .qeu_key key for delete ** <qeu_key> is a pointer to an array of pointers of type DMR_ATTR_ENTRY ** .attr_number ** .attr_operation ** .attr_value_ptr ** .qeu_flag operation qualifier ** QEU_BY_TID remove tuple whose TID is in qeu_tid ** .qeu_tid contains TID of the tuple to be ** removed if (qeu_flag & QEU_BY_TID) ** ** Outputs: ** qeu_cb ** .qeu_count number of tuples retrieved ** .error.err_code One of the following ** E_QE0000_OK ** E_QE0002_INTERNAL_ERROR ** E_QE0004_NO_TRANSACTION ** E_QE0007_NO_CURSOR ** E_QE0017_BAD_CB ** E_QE0018_BAD_PARAM_IN_CB ** Returns: ** E_DB_OK ** E_DB_ERROR caller error ** E_DB_FATAL internal error ** Exceptions: ** none ** ** Side Effects: ** none ** ** History: ** 27-may-86 (daved) ** written ** 02-sep-86 (jennifer) ** Modified qeu_delete to return a count of tuples ** deleted. ** 21-oct-86 (daved) ** did above fix for case where dmf returns no more rows. ** 22-dec-86 (daved) ** return OK if deleting keyed records ** 10-dec-87 (puree) ** Converted all ulm_palloc to qec_palloc ** 04-jan-91 (andre) ** added functionality to delete tuples by TID ** 18-jun-92 (andre) ** do not allocate memory unless we will actually be reading tuples, ** i.e. if a key is specified ** 06-mar-96 (nanpr01) ** removed the dependency on DB_MAXTUP for increased tuple size ** project. Also added the check to make sure tuple size is set ** whoever called this routine. Also tuple size consistency is ** checked iff qeu_klen > 0. ** 24-Jan-2001 (jenjo02) ** Ensure that memory stream is closed before returning. ** 11-Apr-2008 (kschendel) ** Revised DMF qualification requirements, simplified for QEU. */ DB_STATUS qeu_delete( QEF_CB *qef_cb, QEU_CB *qeu_cb) { i4 err; i4 count; DMR_CB dmr_cb; DB_STATUS status; GLOBALREF QEF_S_CB *Qef_s_cb; ULM_RCB ulm; /* so we don't need to allocate a tuple buffer ** as a stack variable, use dynamic memory */ count = 0; qeu_cb->qeu_count = 0; qeu_cb->error.err_code = E_QE0000_OK; /* QEU_DELETE is only valid in a transaction */ if (qef_cb->qef_stat == QEF_NOTRAN) { qef_error(E_QE0004_NO_TRANSACTION, 0L, E_DB_ERROR, &err, &qeu_cb->error, 0); return (E_DB_ERROR); } dmr_cb.type = DMR_RECORD_CB; dmr_cb.length = sizeof(DMR_CB); dmr_cb.dmr_access_id = qeu_cb->qeu_acc_id; dmr_cb.dmr_q_fcn = NULL; /* position the cursor */ /* if there is a key, position by qual. Else, position all records */ if (qeu_cb->qeu_klen) { if (qeu_cb->qeu_tup_length <= 0) { qef_error(E_QE0018_BAD_PARAM_IN_CB, 0L, E_DB_ERROR, &err, &qeu_cb->error, 0); return (E_DB_ERROR); } /* allocate memory for a tuple only if planning to call qeu_get() */ STRUCT_ASSIGN_MACRO(Qef_s_cb->qef_d_ulmcb, ulm); /* Open stream and allocate tuple memory in one action */ ulm.ulm_flags = ULM_PRIVATE_STREAM | ULM_OPEN_AND_PALLOC; ulm.ulm_psize = ulm.ulm_blocksize = qeu_cb->qeu_tup_length; if ((status = qec_mopen(&ulm)) != E_DB_OK) { qef_error(E_QE001E_NO_MEM, 0L, E_DB_ERROR, &err, &qeu_cb->error, 0); return (status); } /* set the keys */ dmr_cb.dmr_position_type = DMR_QUAL; dmr_cb.dmr_attr_desc.ptr_address = (PTR) qeu_cb->qeu_key; dmr_cb.dmr_attr_desc.ptr_in_count = qeu_cb->qeu_klen; dmr_cb.dmr_attr_desc.ptr_size = sizeof (DMR_ATTR_ENTRY); dmr_cb.dmr_s_estimated_records = -1; /* row qualifier */ dmr_cb.dmr_q_fcn = (DB_STATUS (*)(void *,void *)) qeu_cb->qeu_qual; dmr_cb.dmr_q_arg = (PTR) qeu_cb->qeu_qarg; if (qeu_cb->qeu_qual != NULL) { dmr_cb.dmr_q_rowaddr = &qeu_cb->qeu_qarg->qeu_rowaddr; dmr_cb.dmr_q_retval = &qeu_cb->qeu_qarg->qeu_retval; } dmr_cb.dmr_flags_mask = 0; status = dmf_call(DMR_POSITION, &dmr_cb); if (status != E_DB_OK) { ulm_closestream(&ulm); if (dmr_cb.error.err_code == E_DM0055_NONEXT) return (E_DB_OK); qef_error(dmr_cb.error.err_code, 0L, status, &err, &qeu_cb->error, 0); return (status); } /* the tuple length will not change. Tell DMF about it */ dmr_cb.dmr_data.data_in_size = qeu_cb->qeu_tup_length; dmr_cb.dmr_data.data_address = ulm.ulm_pptr; } for (;;) { if (qeu_cb->qeu_klen) { /* get the tuple */ dmr_cb.dmr_flags_mask = DMR_NEXT; status = dmf_call(DMR_GET, &dmr_cb); if (status != E_DB_OK) { if (dmr_cb.error.err_code == E_DM0055_NONEXT) { status = E_DB_OK; break; } else { qef_error(dmr_cb.error.err_code, 0L, status, &err, &qeu_cb->error, 0); } break; } } /* ** delete the tuple: if deleting by TID, copy qeu_tid to dmr_tid and set ** dmr_flags_mask to DMR_BY_TID */ if (qeu_cb->qeu_flag & QEU_BY_TID) { dmr_cb.dmr_flags_mask = DMR_BY_TID; dmr_cb.dmr_tid = qeu_cb->qeu_tid; } /* otherwise delete the current tuple */ else { dmr_cb.dmr_flags_mask = DMR_CURRENT_POS; } status = dmf_call(DMR_DELETE, &dmr_cb); if (status != E_DB_OK) { qef_error(dmr_cb.error.err_code, 0L, status, &err, &qeu_cb->error, 0); break; } count++; if (qeu_cb->qeu_klen == 0) { /* we are only deleting current tuple */ break; } } if (qeu_cb->qeu_klen) { /* don't try to close a stream unless it was opened */ ulm_closestream(&ulm); } qeu_cb->qeu_count = count; return (status); }
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: QEU_REPLACE - replace tuple(s) in a table ** ** External QEF call: status = qef_call(QEU_REPLACE, &qeu_cb); ** ** Description: ** A tuple is replaced in a table opened with the QEU_OPEN ** command. ** If QEU_BY_TID is specified, ** the tuple with specified TID is repalced ** else if qeu_cb->kqeu_klen > 0 ** qeu_f_qual points to a function which will both determine whether the ** tuple should be updated and make appropriate changes to the tuple ** passed to it ** else ** replace the tuple which was read by position as specified by the caller ** ** Inputs: ** qeu_cb ** .qeu_eflag designate error handling semantis ** for user errors. ** QEF_INTERNAL return error code. ** QEF_EXTERNAL send message to user. ** .qeu_acc_id table access id ** .qeu_tup_length lenth of a tuple ** .qeu_input buffer containing new values for the ** tuple being replaced ** .qeu_qual qualification function for DMF ** .qeu_qarg argument to (*qeu_qual) () ** .qeu_klen length of key ** .qeu_key key for update ** <qeu_key> is a pointer to an array of pointers of type DMR_ATTR_ENTRY ** .attr_number ** .attr_operation ** .attr_value_ptr ** .qeu_flag operation qualifier ** QEU_BY_TID replace tuple whose TID is in ** qeu_tid ** .qeu_tid contains TID of the tuple to be ** replaced if (qeu_flag & QEU_BY_TID) ** .qeu_f_qual if !(qeu_klen > 0) this must point ** at a function which will decide ** whether and how the current tuple ** must be replaced ** .qeu_f_qarg argument to (*qeu_f_qual) () ** ** Outputs: ** qeu_cb ** .qeu_count number of tuples updated ** .error.err_code One of the following ** E_QE0000_OK ** E_QE0002_INTERNAL_ERROR ** E_QE0004_NO_TRANSACTION ** E_QE0007_NO_CURSOR ** E_QE0017_BAD_CB ** E_QE0018_BAD_PARAM_IN_CB ** Returns: ** E_DB_OK ** E_DB_ERROR caller error ** E_DB_FATAL internal error ** Exceptions: ** none ** ** Side Effects: ** none ** ** History: ** 18-jun-92 (andre) ** written ** 22-jun-92 (andre) ** changed the function to allow update one row by tid or to update ** multiple rows subject to qualification function ** 24-jun-92 (andre) ** another change to allow update of prepositioned tuple ** 13-sep-93 (robf) ** Extended to handle update multiple rows without ** requiring a key position. This is signalled when qeu_klen==0 ** and qeu_qual != NULL and qeu_f_qual!=NULL ** 30-nov-93 (robf) ** When updating multiple rows, keep going after first update. ** 24-Jan-2001 (jenjo02) ** Ensure that memory stream is closed before returning. ** 11-Apr-2008 (kschendel) ** Revised DMF qualification requirements, simplified for QEU. */ DB_STATUS qeu_replace( QEF_CB *qef_cb, QEU_CB *qeu_cb) { i4 err = 0L; DMR_CB dmr_cb; DB_STATUS status; GLOBALREF QEF_S_CB *Qef_s_cb; ULM_RCB ulm; i4 (*repl_func)(void *, void *); bool position_all=FALSE; bool mem_opened=FALSE; if (qeu_cb->qeu_flag & QEU_BY_TID) { /* ** if update_by_tid, no key(s), qualification function, or qualification ** function parameters should be passed; ** qeu_cb->qeu_input must point at a structure containing a ptr to the ** new value for the tuple of specified size */ if (qeu_cb->qeu_klen || qeu_cb->qeu_qual || qeu_cb->qeu_qarg || qeu_cb->qeu_f_qual || qeu_cb->qeu_f_qarg || !qeu_cb->qeu_input || !qeu_cb->qeu_input->dt_data || !qeu_cb->qeu_input->dt_size) { err = E_QE0018_BAD_PARAM_IN_CB; status = E_DB_ERROR; } } else if (qeu_cb->qeu_klen==0 && (repl_func = qeu_cb->qeu_f_qual) != NULL && qeu_cb->qeu_qual) { position_all=TRUE; /* ** Request to replace all qualifying in table, without key ** positioning */ if (!qeu_cb->qeu_qarg || !qeu_cb->qeu_f_qarg ) { err = E_QE0018_BAD_PARAM_IN_CB; status = E_DB_ERROR; } } else if (qeu_cb->qeu_klen == 0) { /* ** if asked to update the current tuple, no qualification function, or ** qualification function parameters should be passed; ** qeu_cb->qeu_input must point at a structure containing a ptr to ** the new value for the tuple of specified size */ if (qeu_cb->qeu_qual || qeu_cb->qeu_qarg || qeu_cb->qeu_f_qual || qeu_cb->qeu_f_qarg || !qeu_cb->qeu_input || !qeu_cb->qeu_input->dt_data || !qeu_cb->qeu_input->dt_size) { err = E_QE0018_BAD_PARAM_IN_CB; status = E_DB_ERROR; } } else if ((repl_func = qeu_cb->qeu_f_qual) == NULL) { /* ** if caller supplied a key, must specify the function which ** will determine whether and how the tuple must be updated */ err = E_QE0018_BAD_PARAM_IN_CB; status = E_DB_ERROR; } if (err) { (VOID) qef_error(err, 0L, status, &err, &qeu_cb->error, 0); return(status); } qeu_cb->qeu_count = 0; qeu_cb->error.err_code = E_QE0000_OK; /* QEU_REPLACE is only valid in a transaction */ if (qef_cb->qef_stat == QEF_NOTRAN) { qef_error(E_QE0004_NO_TRANSACTION, 0L, E_DB_ERROR, &err, &qeu_cb->error, 0); return (E_DB_ERROR); } dmr_cb.type = DMR_RECORD_CB; dmr_cb.length = sizeof(DMR_CB); dmr_cb.dmr_access_id = qeu_cb->qeu_acc_id; dmr_cb.dmr_q_fcn = NULL; /* if replacing by key, position the cursor */ if (qeu_cb->qeu_klen || position_all) { /* allocate memory for a tuple only if planning to call qeu_get() */ STRUCT_ASSIGN_MACRO(Qef_s_cb->qef_d_ulmcb, ulm); /* Open stream and allocate tuple memory in one action */ ulm.ulm_flags = ULM_PRIVATE_STREAM | ULM_OPEN_AND_PALLOC; ulm.ulm_psize = ulm.ulm_blocksize = qeu_cb->qeu_tup_length; if ((status = qec_mopen(&ulm)) != E_DB_OK) { qef_error(E_QE001E_NO_MEM, 0L, E_DB_ERROR, &err, &qeu_cb->error, 0); return (status); } mem_opened=TRUE; /* set the keys */ if(position_all) { dmr_cb.dmr_position_type = DMR_ALL; } else { dmr_cb.dmr_position_type = DMR_QUAL; dmr_cb.dmr_attr_desc.ptr_address = (PTR) qeu_cb->qeu_key; dmr_cb.dmr_attr_desc.ptr_in_count = qeu_cb->qeu_klen; dmr_cb.dmr_attr_desc.ptr_size = sizeof (DMR_ATTR_ENTRY); dmr_cb.dmr_s_estimated_records = -1; } /* row qualifier */ dmr_cb.dmr_q_fcn = (DB_STATUS (*)(void *,void *)) qeu_cb->qeu_qual; dmr_cb.dmr_q_arg = (PTR) qeu_cb->qeu_qarg; if (qeu_cb->qeu_qual != NULL) { dmr_cb.dmr_q_rowaddr = &qeu_cb->qeu_qarg->qeu_rowaddr; dmr_cb.dmr_q_retval = &qeu_cb->qeu_qarg->qeu_retval; } dmr_cb.dmr_flags_mask = 0; status = dmf_call(DMR_POSITION, &dmr_cb); if (status != E_DB_OK) { ulm_closestream(&ulm); if (dmr_cb.error.err_code == E_DM0055_NONEXT) return (E_DB_OK); qef_error(dmr_cb.error.err_code, 0L, status, &err, &qeu_cb->error, 0); return (status); } /* the tuple length will not change. Tell DMF about it */ dmr_cb.dmr_data.data_in_size = qeu_cb->qeu_tup_length; dmr_cb.dmr_data.data_address = ulm.ulm_pptr; } else { /* ** make dmr_data point at the new value for the tuple */ dmr_cb.dmr_data.data_address = qeu_cb->qeu_input->dt_data; dmr_cb.dmr_data.data_in_size = qeu_cb->qeu_input->dt_size; /* ** if (qeu_flag & QEU_BY_TID) ** indicate to dmr_replace() that we are replacing by tid ** else ** indicate to dmr_replace to replace the current tuple */ if (qeu_cb->qeu_flag & QEU_BY_TID) { dmr_cb.dmr_flags_mask = DMR_BY_TID; dmr_cb.dmr_tid = qeu_cb->qeu_tid; } else { dmr_cb.dmr_flags_mask = DMR_CURRENT_POS; } } for (;;) { if (qeu_cb->qeu_klen || position_all) { i4 ret_val; /* get the tuple */ dmr_cb.dmr_flags_mask = DMR_NEXT; status = dmf_call(DMR_GET, &dmr_cb); if (status != E_DB_OK) { if (dmr_cb.error.err_code == E_DM0055_NONEXT) { status = E_DB_OK; } else { err = dmr_cb.error.err_code; } break; } /* ** let caller's function determine whether and how the tuple must be ** changed; QEU_F_RETURN indicates that we must proceed; QEU_F_NEXT ** says "skip this tuple" */ ret_val = (*repl_func) (dmr_cb.dmr_data.data_address, qeu_cb->qeu_f_qarg); if (ret_val != QEU_F_RETURN) { continue; } /* will replace the current tuple */ dmr_cb.dmr_flags_mask = DMR_CURRENT_POS; } dmr_cb.dmr_attset = NULL; status = dmf_call(DMR_REPLACE, &dmr_cb); if (status != E_DB_OK) { err = dmr_cb.error.err_code; break; } else { qeu_cb->qeu_count++; } if (qeu_cb->qeu_klen == 0 && !position_all) { /* we were replacing a tuple by tid and are done */ break; } } if (status != E_DB_OK) { qef_error(err, 0L, status, &err, &qeu_cb->error, 0); } if (mem_opened) { /* don't try to close a stream unless it was opened */ ulm_closestream(&ulm); } return (status); }