DB_STATUS qee_p1_dsh_gen( QEF_RCB *v_qer_p, QEE_DSH *i_dsh_p) { DB_STATUS status = E_DB_OK; QEF_QP_CB *qp_p = i_dsh_p->dsh_qp_ptr; /* debugging aid */ QEE_DDB_CB *dde_p = i_dsh_p->dsh_ddb_cb; char cur_name[DB_CURSOR_MAXNAME + 1]; char *cbuf = v_qer_p->qef_cb->qef_trfmt; i4 cbufsize = v_qer_p->qef_cb->qef_trsize; qed_u0_trimtail(i_dsh_p->dsh_qp_id.db_cur_name, DB_CURSOR_MAXNAME, cur_name); STprintf(cbuf, "%s %p: ... query id: %x %x %s\n", IIQE_61_qefsess, (PTR) v_qer_p->qef_cb, i_dsh_p->dsh_qp_id.db_cursor_id[0], i_dsh_p->dsh_qp_id.db_cursor_id[1], cur_name); qec_tprintf(v_qer_p, cbufsize, cbuf); if (i_dsh_p->dsh_qp_status & DSH_QP_LOCKED) { STprintf(cbuf, "%s %p: ... query plan LOCKED by this session\n", IIQE_61_qefsess, (PTR) v_qer_p->qef_cb); qec_tprintf(v_qer_p, cbufsize, cbuf); } if (i_dsh_p->dsh_qp_status & DSH_QP_OBSOLETE) { STprintf(cbuf, "%s %p: ... query plan is OBSOLETE; to be destroyed\n", IIQE_61_qefsess, (PTR) v_qer_p->qef_cb); qec_tprintf(v_qer_p, cbufsize, cbuf); } if (i_dsh_p->dsh_qp_status & DSH_DEFERRED_CURSOR) { STprintf(cbuf, "%s %p: ... query plan contains a DEFERRED cursor\n", IIQE_61_qefsess, (PTR) v_qer_p->qef_cb); qec_tprintf(v_qer_p, cbufsize, cbuf); } if (i_dsh_p->dsh_positioned) { STprintf(cbuf, "%s %p: ... cursor is positioned\n", IIQE_61_qefsess, (PTR) v_qer_p->qef_cb); qec_tprintf(v_qer_p, cbufsize, cbuf); } return(E_DB_OK); }
DB_STATUS qee_p4_ldb_qid( 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; QEF_DDB_REQ *ddr_p = & v_qer_p->qef_r3_ddb_req; */ QEE_DDB_CB *qee_p = i_dsh_p->dsh_ddb_cb; DB_CURSOR_ID *ldb_qid_p = & qee_p->qee_d5_local_qid; char cur_name[DB_CURSOR_MAXNAME + 1]; char *cbuf = v_qer_p->qef_cb->qef_trfmt; i4 cbufsize = v_qer_p->qef_cb->qef_trsize; STprintf(cbuf, "%s %p: ...the LDB query id:\n", IIQE_61_qefsess, (PTR) v_qer_p->qef_cb); qec_tprintf(v_qer_p, cbufsize, cbuf); STprintf(cbuf, "%s %p: ... 1) DB_CURSOR_ID[0] %x,\n", IIQE_61_qefsess, (PTR) v_qer_p->qef_cb, ldb_qid_p->db_cursor_id[0]); qec_tprintf(v_qer_p, cbufsize, cbuf); STprintf(cbuf, "%s %p: ... 2) DB_CURSOR_ID[1] %x,\n", IIQE_61_qefsess, (PTR) v_qer_p->qef_cb, ldb_qid_p->db_cursor_id[1]); qec_tprintf(v_qer_p, cbufsize, cbuf); qed_u0_trimtail(ldb_qid_p->db_cur_name, DB_CURSOR_MAXNAME, cur_name); STprintf(cbuf, "%s %p: ... 3) DB_CUR_NAME %s\n", IIQE_61_qefsess, (PTR) v_qer_p->qef_cb, cur_name); qec_tprintf(v_qer_p, cbufsize, cbuf); return(E_DB_OK); }
DB_STATUS qee_p0_prt_dsh( QEF_RCB *v_qer_p, QEE_DSH *i_dsh_p) { DB_STATUS status = E_DB_OK; QEF_CB *qecb_p = v_qer_p->qef_cb; char *cbuf = v_qer_p->qef_cb->qef_trfmt; i4 cbufsize = v_qer_p->qef_cb->qef_trsize; if (TRUE) return(E_DB_OK); STprintf(cbuf, "%s %p: ...1.1) Generic DSH information\n", IIQE_61_qefsess, (PTR) v_qer_p->qef_cb); qec_tprintf(v_qer_p, cbufsize, cbuf); status = qee_p1_dsh_gen(v_qer_p, i_dsh_p); if (status) return(status); if (qecb_p->qef_c1_distrib & DB_3_DDB_SESS) { STprintf(cbuf, "%s %p: ...1.2) DDB-specific DSH information\n", IIQE_61_qefsess, (PTR) v_qer_p->qef_cb); qec_tprintf(v_qer_p, cbufsize, cbuf); status = qee_p2_dsh_ddb(v_qer_p, i_dsh_p); } return(status); }
/* ** Name: QEN_PRINT_ROW - This routine prints the current row for a given ** QEN_NODE ** ** Description: ** This routine prints out the current row for the given QEN_NODE. ** This is done with the help of ADF, who converts data into a ** printable form, similiar to what the terminal monitor needs to do. ** ** FIXME this really belongs in qenutl since it applies to any node, ** not just fsm-joins. ** ** Inputs: ** node - ** The qen_node that refers to the row. ** qef_rcb - ** The request control block that we get most of our query common ** info from, like cbs, the dsh, dsh rows, etc. ** ** Outputs: ** ** Returns: ** DB_STATUS ** Exceptions: ** none ** ** Side Effects: ** causes a row to be printed to the FE (via SCC_TRACE). ** ** History: ** 17-may-89 (eric) ** created ** 6-aug-04 (inkdo01) ** Drop increment of node_rcount - it's already incremented in the ** node handlers and this simply doubles its value. ** 13-Dec-2005 (kschendel) ** Can count on qen-ade-cx now. ** 11-Mar-2010 (hanal04) Bug 123415 ** Make sure QE99 and OP173 do not interleave output with ** using parallel query. ** 12-May-2010 (kschendel) Bug 123720 ** Above doesn't quite go far enough, mutex the buffer. ** Take qef_trsem for valid parallel-query output. */ DB_STATUS qen_print_row( QEN_NODE *node, QEF_RCB *qef_rcb, QEE_DSH *dsh ) { QEN_STATUS *qen_status = dsh->dsh_xaddrs[node->qen_num]->qex_status; QEN_ADF *qen_adf; DB_STATUS status = E_DB_OK; char *cbuf = dsh->dsh_qefcb->qef_trfmt; i4 cbufsize = dsh->dsh_qefcb->qef_trsize; qen_adf = node->qen_prow; /* Checked non-NULL by caller */ if (qen_status->node_rcount > 0) { /* process the row print expression */ status = qen_execute_cx(dsh, dsh->dsh_xaddrs[node->qen_num]->qex_prow); if (status != E_DB_OK) { # ifdef xDEBUG (VOID) qe2_chk_qp(dsh); # endif return (status); } /* Print in one operation to avoid interleaved output */ CSp_semaphore(1, &dsh->dsh_qefcb->qef_trsem); STprintf(cbuf, "Row %d of node %d\n%s\n\n", qen_status->node_rcount, node->qen_num, dsh->dsh_row[qen_adf->qen_output]); qec_tprintf(qef_rcb, cbufsize, cbuf); CSv_semaphore(&dsh->dsh_qefcb->qef_trsem); } return(E_DB_OK); }
DB_STATUS qee_p2_dsh_ddb( QEF_RCB *v_qer_p, QEE_DSH *i_dsh_p) { DB_STATUS status = E_DB_OK; QEF_CB *qecb_p = v_qer_p->qef_cb; QEF_QP_CB *qp_p = i_dsh_p->dsh_qp_ptr; /* debugging aid */ QEQ_DDQ_CB *ddq_p = & qp_p->qp_ddq_cb; QEE_DDB_CB *dde_p = i_dsh_p->dsh_ddb_cb; DD_TAB_NAME *tmptbl_p = (DD_TAB_NAME *) NULL; i4 *sts_p = (i4 *) NULL; i4 i; char namebuf[DB_TAB_MAXNAME + 1]; char cur_name[DB_CURSOR_MAXNAME + 1]; char *cbuf = v_qer_p->qef_cb->qef_trfmt; i4 cbufsize = v_qer_p->qef_cb->qef_trsize; if (! (qecb_p->qef_c1_distrib & DB_3_DDB_SESS) ) return(E_DB_OK); /* NOT a DDB session */ if (ddq_p->qeq_d3_elt_cnt == 0) { STprintf(cbuf, "%s %p: ... 0 temporary tables used by query\n", IIQE_61_qefsess, (PTR) v_qer_p->qef_cb); qec_tprintf(v_qer_p, cbufsize, cbuf); } else { if (ddq_p->qeq_d3_elt_cnt == 1) { STprintf(cbuf, "%s %p: ... 1 temporary table ", IIQE_61_qefsess, (PTR) v_qer_p->qef_cb); qec_tprintf(v_qer_p, cbufsize, cbuf); } else { STprintf(cbuf, "%s %p: ... %d temporary tables ", IIQE_61_qefsess, (PTR) v_qer_p->qef_cb, ddq_p->qeq_d3_elt_cnt); qec_tprintf(v_qer_p, cbufsize, cbuf); } STprintf(cbuf, "used by query\n"); qec_tprintf(v_qer_p, cbufsize, cbuf); /* print all the temporary table names */ for (i = 1, tmptbl_p = dde_p->qee_d1_tmp_p, sts_p = dde_p->qee_d2_sts_p; i <= ddq_p->qeq_d3_elt_cnt; i++, tmptbl_p++, sts_p++) if (*sts_p & QEE_01M_CREATED) { qed_u0_trimtail((char *) tmptbl_p, DB_TAB_MAXNAME, namebuf); STprintf(cbuf, "%s %p: ... %d) %s\n", IIQE_61_qefsess, (PTR) v_qer_p->qef_cb, i, namebuf); qec_tprintf(v_qer_p, cbufsize, cbuf); } } if (dde_p->qee_d3_status & QEE_01Q_CSR) { STprintf(cbuf, "%s %p: ... query pertains to a CURSOR\n", IIQE_61_qefsess, (PTR) v_qer_p->qef_cb); qec_tprintf(v_qer_p, cbufsize, cbuf); } if (dde_p->qee_d3_status & QEE_02Q_RPT) { STprintf(cbuf, "%s %p: ... this is a REPEAT query\n", IIQE_61_qefsess, (PTR) v_qer_p->qef_cb); qec_tprintf(v_qer_p, cbufsize, cbuf); } if (dde_p->qee_d3_status & QEE_03Q_DEF) { STprintf(cbuf, "%s %p: ... query has been DEFINED to the LDB\n", IIQE_61_qefsess, (PTR) v_qer_p->qef_cb); qec_tprintf(v_qer_p, cbufsize, cbuf); } if (dde_p->qee_d3_status & QEE_04Q_EOD) { STprintf(cbuf, "%s %p: ... query has NO more retrieved data coming back\n", IIQE_61_qefsess, (PTR) v_qer_p->qef_cb); qec_tprintf(v_qer_p, cbufsize, cbuf); } if (dde_p->qee_d3_status & QEE_05Q_CDB) { STprintf(cbuf, "%s %p: ... retrieval REROUTED thru the CDB, to be committed when done\n", IIQE_61_qefsess, (PTR) v_qer_p->qef_cb); qec_tprintf(v_qer_p, cbufsize, cbuf); } if (dde_p->qee_d3_status & QEE_06Q_TDS) { STprintf(cbuf, "%s %p: ... RQF returning a tuple descriptor to SCF\n", IIQE_61_qefsess, (PTR) v_qer_p->qef_cb); qec_tprintf(v_qer_p, cbufsize, cbuf); } if (dde_p->qee_d3_status & QEE_07Q_ATT) { STprintf(cbuf, "%s %p: ... tuple descriptor contains attribute names\n", IIQE_61_qefsess, (PTR) v_qer_p->qef_cb); qec_tprintf(v_qer_p, cbufsize, cbuf); } if (dde_p->qee_d4_given_qid.db_cursor_id[0] != 0) { /* null-terminate name part for printing */ qed_u0_trimtail( dde_p->qee_d4_given_qid.db_cur_name, DB_CURSOR_MAXNAME, cur_name); STprintf(cbuf, "%s %p: ... DDB query id: %x %x %s\n", IIQE_61_qefsess, (PTR) v_qer_p->qef_cb, dde_p->qee_d4_given_qid.db_cursor_id[0], dde_p->qee_d4_given_qid.db_cursor_id[1], cur_name); qec_tprintf(v_qer_p, cbufsize, cbuf); } if (dde_p->qee_d5_local_qid.db_cursor_id[0] != 0) { /* null-terminate name part for printing */ qed_u0_trimtail( dde_p->qee_d5_local_qid.db_cur_name, DB_CURSOR_MAXNAME, cur_name); STprintf(cbuf, "%s %p: ... LDB (sub)query id: %x %x %s\n", IIQE_61_qefsess, (PTR) v_qer_p->qef_cb, dde_p->qee_d5_local_qid.db_cursor_id[0], dde_p->qee_d5_local_qid.db_cursor_id[1], cur_name); qec_tprintf(v_qer_p, cbufsize, cbuf); } if (dde_p->qee_d6_dynamic_cnt > 0) { if (dde_p->qee_d6_dynamic_cnt == 1) { STprintf(cbuf, "%s %p: ... 1 DB_DATA_VALUE ", IIQE_61_qefsess, (PTR) v_qer_p->qef_cb); qec_tprintf(v_qer_p, cbufsize, cbuf); } else { STprintf(cbuf, "%s %p: ... %d DB_DATA_VALUEs ", IIQE_61_qefsess, (PTR) v_qer_p->qef_cb, dde_p->qee_d6_dynamic_cnt); qec_tprintf(v_qer_p, cbufsize, cbuf); } STprintf(cbuf, "for query\n"); qec_tprintf(v_qer_p, cbufsize, cbuf); } if (dde_p->qee_d3_status & QEE_01Q_CSR || dde_p->qee_d3_status & QEE_02Q_RPT) { if (dde_p->qee_d3_status & QEE_01Q_CSR) { STprintf(cbuf, "%s %p: ... LDB for this CURSOR query:\n", IIQE_61_qefsess, (PTR) v_qer_p->qef_cb); qec_tprintf(v_qer_p, cbufsize, cbuf); } else { STprintf(cbuf, "%s %p: ... LDB for this REPEAT query:\n", IIQE_61_qefsess, (PTR) v_qer_p->qef_cb); qec_tprintf(v_qer_p, cbufsize, cbuf); } /* print the LDB's information */ status = qed_w1_prt_ldbdesc(v_qer_p, & dde_p->qee_d11_ldbdesc); } return(E_DB_OK); }
/*{ ** Name: QEA_CALLPROC - call the named procedure ** ** Description: ** The current execution environment is saved and an ** environment is created in which to execute the ** named procedure. ** ** This procedure is only called when a nested procedure is invoked. ** This can occur the first time through, or if the procedure is not ** found (LOAD_QP) or the plan was deemed invalid (INVALID_QUERY) then ** the procedure is re-entered in this routine. ** ** If rules are turned off (QEF_T_NORULES) then this procedure returns ** immediately. ** ** Inputs: ** action Callproc action header ** qef_rcb ** call_dsh DSH doing the callproc ** function unused ** state unused ** ** Outputs: ** call_dsh ** .error.err_code one of the following ** E_QE0119_LOAD_QP - Load a procedure QP ** E_QE0125_RULES_INHIBIT - Rules are turned off. ** E_QE0000_OK ** Returns: ** E_DB_{OK,WARN,ERROR,FATAL} ** Exceptions: ** none ** ** Side Effects: ** none ** ** History: ** 20-apr-89 (paul) ** Moved from qeq.c ** 09-may-89 (neil) ** Added rule name tracing. ** 26-may-89 (paul) ** Increase statement #, cleanup DSH on error recovery. ** 31-may-89 (neil) ** Cleanup tracing; modify when context count is set; reset "saved ** resource" bit if procedure is loaded. ** 23-jun-89 (neil) ** Extended trace for nested procedures: Indicate procedure nesting ** level and rule depth. ** 26-sep-89 (neil) ** Support for SET NORULES. ** 02-jan-90 (neil) ** DSH initialization error handling improved to indicate problem ** specifics. ** 03-jan-90 (ralph) ** Change interface to QSO_JUST_TRANS ** 10-jan-90 (neil) ** Improved DSH cleanup on DSH initialization errors. Made sure ** to confirm allocation error, and to pass a FALSE "release" flag ** to qeq_cleanup. ** 09-feb-90 (neil) ** Auditing cleanup: only audit the firing of rules and only if ** auditing is on (for performance). ** 09-nov-92 (jhahn) ** Added handling for byrefs. ** 14-dec-92 (jhahn) ** Cleaned up handling of byrefs. ** 12-feb-93 (jhahn) ** Added support for statement level rules. (FIPS) ** 24-mar-93 (jhahn) ** Various fixes for support of statement level rules. (FIPS) ** 02-apr-93 (jhahn) ** Made set input procedures called from rules bump qef_rule_depth. ** 01-may-93 (jhahn) ** Undid above change. Instead added new action QEA_INVOKE_RULE. ** 06-jul-93 (robf) ** Pass security label to qeu_secaudit ** 01-sep-93 (jhahn) ** Added support for multiple query plans for set input procedures. ** 7-jan-94 (swm) ** Bug #58635 ** Added PTR cast for qsf_owner which has changed type to PTR. ** 18-may-94 (anitap) ** Bug #63465 ** If error in nested procedure, the whole transaction was being ** rolled back. ** 7-nov-95 (inkdo01) ** Changes to replace QEN_ADF structure instances by pointers in ** QEF_AHD structures. ** 24-jul-96 (inkdo01) ** Added support of global temp table proc parms. ** 4-mar-97 (inkdo01) ** Added display of error QE030B (row rule calls SET OF proc). ** 23-may-97 (inkdo01) ** Change QE030B to only pass procname, since it is mapped to a ** US error in qeferror, anyway. ** 17-aug-99 (thaju02) ** initialize dmt_show.db_tab_id.db_tab_base to 0 prior to calling ** dmt_show, to avoid falsely reporting E_QE0018. (b98431) ** 27-apr-01 (inkdo01) ** Add code to detect nested/dynamic calls to row procs. ** 15-mar-04 (inkdo01) ** dsh_tempTables is now an array of ptrs. ** 17-mar-04 (inkdo01) ** We be fixin' a bug in error handlin' when qeq_dsh() doesn't ** return a dsh. ** 13-may-04 (inkdo01) ** Preserve status across qeq_cleanup calls. ** 18-may-04 (inkdo01) ** Quick fix to eliminate QE0018 when QE030D (US09AF) happens. ** 13-Jul-2004 (schka24) ** Straighten out which dsh is used where, fix loss of error ** code when finding called qp leading to QE0018. ** 13-Dec-2005 (kschendel) ** Inlined QEN_ADF changed to pointer, fix here. ** 29-May-2008 (gefei01) ** Prototype change for qeq_dsh(). ** 22-Apr-2009 (hanal04) Bug 121970 ** In printrule tracing print the ahd_pcount not qef_pcount ** which is set to zero if we are in a sub-procedure. ** 21-Jun-2010 (kschendel) b123775 ** Combine is-tproc and in-progress args to qeq-dsh. ** Make dbp alias a real QSO_NAME. */ DB_STATUS qea_callproc( QEF_AHD *act, QEF_RCB *qef_rcb, QEE_DSH *call_dsh, i4 function, /* Unused */ i4 state ) /* Unused */ { i4 err; DB_STATUS status = E_DB_OK, savestat; QEF_CB *qef_cb = call_dsh->dsh_qefcb; PTR *cbs = call_dsh->dsh_cbs; QEE_DSH *proc_dsh; /* DSH for called dbp */ QEN_ADF *qen_adf; ADE_EXCB *ade_excb; QSF_RCB qsf_rcb; i4 tr1 = 0, tr2 = 0; /* Dummy trace values */ DB_ERROR e_error; /* To pass to qeu_secaudit */ i4 page_count; bool is_deferred = act->qhd_obj.qhd_callproc.ahd_proc_temptable != NULL; bool gttparm = act->qhd_obj.qhd_callproc.ahd_gttid.db_tab_base != 0; bool need_cleanup = FALSE; bool need_release; bool from_rule = act->qhd_obj.qhd_callproc.ahd_rulename.db_name[0] != EOS; QEE_TEMP_TABLE *proc_temptable; char *cbuf = qef_cb->qef_trfmt; i4 cbufsize = qef_cb->qef_trsize; i4 open_count; do { /* ** This action is called back if a request to CREATE a QP for a ** CALLPROC fails. In this case we just continue with error processing. ** No need for another error as CLEAN_RSRC is only set if a client on ** the outside issued an error knowing we have a stacked environment. ** (Note: as of the 123775 fixes, we shouldn't ever get here with ** CLEAN_RSRC set, since qeq-query no longer attempts to execute ** the action from the sequencer callback. I'm leaving the code ** here for now, though.) */ if ((qef_rcb->qef_intstate & QEF_CLEAN_RSRC) != 0) { call_dsh->dsh_error.err_code = E_QE0025_USER_ERROR; qef_rcb->qef_intstate &= ~QEF_CLEAN_RSRC; status = E_DB_ERROR; break; } if (is_deferred) { proc_temptable = call_dsh->dsh_tempTables[act->qhd_obj.qhd_callproc .ahd_proc_temptable->ttb_tempTableIndex]; if (proc_temptable->tt_statusFlags & TT_EMPTY) if (from_rule) break; /* empty ttab in statement rule - ** nothing to do at all */ else status = openTempTable(qef_rcb, call_dsh, act->qhd_obj.qhd_callproc .ahd_proc_temptable->ttb_tempTableIndex, gttparm); else status = qen_rewindTempTable(call_dsh, act->qhd_obj. qhd_callproc.ahd_proc_temptable->ttb_tempTableIndex); if (status != E_DB_OK) break; } /* If called from a rule & SET NORULES is on, then inhibit execution */ if ( from_rule && ult_check_macro(&qef_cb->qef_trace, QEF_T_NORULES, &tr1, &tr2) ) { /* Trace inhibited rule if required */ if (ult_check_macro(&qef_cb->qef_trace, QEF_T_RULES, &tr1, &tr2)) { char *rn = act->qhd_obj.qhd_callproc.ahd_rulename.db_name; STprintf(cbuf, "PRINTRULES: Rule '%.*s' suppressed\n", qec_trimwhite(DB_RULE_MAXNAME, rn), rn); qec_tprintf(qef_rcb, cbufsize, cbuf); } call_dsh->dsh_error.err_code = E_QE0125_RULES_INHIBIT; status = E_DB_ERROR; break; } /* If rules off */ /* ** Security audit rule firing - check that is first time (not ** recreation), is a rule and, for performance, that we really ** need to audit. */ if ( (qef_rcb->qef_intstate & QEF_DBPROC_QP) == 0 && (act->qhd_obj.qhd_callproc.ahd_rulename.db_name[0] != EOS) && (Qef_s_cb->qef_state & QEF_S_C2SECURE) ) { status = qeu_secaudit(FALSE, qef_cb->qef_ses_id, act->qhd_obj.qhd_callproc.ahd_rulename.db_name, (DB_OWN_NAME *)&act->qhd_obj.qhd_callproc.ahd_ruleowner, sizeof(act->qhd_obj.qhd_callproc.ahd_rulename), SXF_E_RULE, I_SX202F_RULE_ACCESS, SXF_A_SUCCESS | SXF_A_EXECUTE, &e_error); if (status != E_DB_OK) { call_dsh->dsh_error.err_code = e_error.err_code; break; } } /* Actually execute a CALLPROC. */ /* We generate an actual parameter list, save the current */ /* execution context, stack the DSH and setup the new */ /* execution context. Processing then continues with the */ /* new QP. */ /* Save the current execution context as represented by */ /* QEF_RCB and the current DSH. */ STRUCT_ASSIGN_MACRO(*qef_rcb, *call_dsh->dsh_saved_rcb); call_dsh->dsh_act_ptr = act; qen_adf = act->qhd_obj.qhd_callproc.ahd_procparams; if (qen_adf != NULL) { /* Compute the actual parameters for this procedure */ /* call. */ qef_rcb->qef_pcount = act->qhd_obj.qhd_callproc.ahd_pcount; ade_excb = (ADE_EXCB *)cbs[qen_adf->qen_pos]; ade_excb->excb_seg = ADE_SMAIN; status = ade_execute_cx(call_dsh->dsh_adf_cb, ade_excb); if (status != E_DB_OK) { status = qef_adf_error(&call_dsh->dsh_adf_cb->adf_errcb, status, qef_cb, &call_dsh->dsh_error); if (status != E_DB_OK) break; } } else { /* No actual parameters */ qef_rcb->qef_pcount = 0; } /* ** If tracing rules and first time through then display ** rule/procedure information. */ if ((qef_rcb->qef_intstate & QEF_DBPROC_QP) == 0) { if (ult_check_macro(&qef_cb->qef_trace, QEF_T_RULES, &tr1, &tr2)) { char *rn, *pn; /* Rule/procedure names */ rn = act->qhd_obj.qhd_callproc.ahd_rulename.db_name; pn = act->qhd_obj.qhd_callproc.ahd_dbpalias.qso_n_id.db_cur_name; /* Tailor trace for rules vs nested procedures */ STprintf(cbuf, *rn == EOS ? "PRINTRULES 1: Executing procedure '%.*s'\n" : "PRINTRULES 1: Executing procedure '%.*s' from rule '%.*s'\n", qec_trimwhite(DB_DBP_MAXNAME, pn), pn, qec_trimwhite(DB_RULE_MAXNAME, rn), rn); qec_tprintf(qef_rcb, cbufsize, cbuf); STprintf(cbuf, "PRINTRULES 2: Rule/procedure depth = %d/%d, parameters passed = %d\n", qef_rcb->qef_rule_depth, qef_rcb->qef_context_cnt + 1, act->qhd_obj.qhd_callproc.ahd_pcount); qec_tprintf(qef_rcb, cbufsize, cbuf); } /* If tracing rules */ } /* ** Indicate that we have nested one more level, generate an error if ** we are nested too deeply. Context count is actually set later. */ if (qef_cb->qef_max_stack < qef_rcb->qef_context_cnt + 1) { status = E_DB_ERROR; qef_error(E_QE0208_EXCEED_MAX_CALL_DEPTH, 0L, status, &err, &call_dsh->dsh_error, 1, sizeof(qef_cb->qef_max_stack), &qef_cb->qef_max_stack); call_dsh->dsh_error.err_code = E_QE0122_ALREADY_REPORTED; break; } if (gttparm) { STRUCT_ASSIGN_MACRO(act->qhd_obj.qhd_callproc.ahd_gttid, qef_rcb->qef_setInputId); /* copy temptab ID */ page_count = 1; is_deferred = TRUE; } else if (is_deferred) { DMT_CB *dmt_cb = proc_temptable->tt_dmtcb; DMT_SHW_CB dmt_show; DMT_TBL_ENTRY dmt_tbl_entry; dmt_show.type = DMT_SH_CB; dmt_show.length = sizeof(DMT_SHW_CB); dmt_show.dmt_session_id = qef_cb->qef_ses_id; dmt_show.dmt_db_id = qef_rcb->qef_db_id; dmt_show.dmt_tab_id.db_tab_base = 0; dmt_show.dmt_flags_mask = DMT_M_TABLE | DMT_M_ACCESS_ID; dmt_show.dmt_char_array.data_address = NULL; dmt_show.dmt_table.data_address = (PTR) &dmt_tbl_entry; dmt_show.dmt_table.data_in_size = sizeof(DMT_TBL_ENTRY); dmt_show.dmt_record_access_id = dmt_cb->dmt_record_access_id; status = dmf_call(DMT_SHOW, &dmt_show); if (status != E_DB_OK) { STRUCT_ASSIGN_MACRO(dmt_show.error, call_dsh->dsh_error); break; } page_count = dmt_tbl_entry.tbl_page_count; STRUCT_ASSIGN_MACRO(dmt_cb->dmt_id, qef_rcb->qef_setInputId); } else { page_count = -1; MEfill(sizeof(DB_TAB_ID), (u_char)0, (PTR)&qef_rcb->qef_setInputId); } STRUCT_ASSIGN_MACRO(act->qhd_obj.qhd_callproc.ahd_procedureID, qef_rcb->qef_dbpId); /* Get the id of the procedure to call */ STRUCT_ASSIGN_MACRO(act->qhd_obj.qhd_callproc.ahd_dbpalias.qso_n_id, qef_rcb->qef_qp); qef_rcb->qef_qso_handle = NULL; /* Set the full name of the procedure into the RCB in case */ /* we have to call PSF to define the procedure. */ qef_rcb->qef_dbpname = act->qhd_obj.qhd_callproc.ahd_dbpalias; /* Lookup this procedure name as a QSF alias. At this time */ /* we do not have a valid DB_CURSOR_ID because we do not */ /* have the timestamp for the QP object. Ask QSF to look */ /* this up for us. If found, we continue executing, if not */ /* return to SCF to define this procedure. */ qsf_rcb.qsf_type = QSFRB_CB; qsf_rcb.qsf_ascii_id = QSFRB_ASCII_ID; qsf_rcb.qsf_length = sizeof(QSF_RCB); qsf_rcb.qsf_owner = (PTR)DB_QEF_ID; qsf_rcb.qsf_sid = qef_rcb->qef_cb->qef_ses_id; qsf_rcb.qsf_feobj_id.qso_type = QSO_ALIAS_OBJ; qsf_rcb.qsf_feobj_id.qso_lname = sizeof(qsf_rcb.qsf_feobj_id.qso_name); MEcopy((PTR)&act->qhd_obj.qhd_callproc.ahd_dbpalias, sizeof(qsf_rcb.qsf_feobj_id.qso_name), (PTR)qsf_rcb.qsf_feobj_id.qso_name); qsf_rcb.qsf_lk_state = QSO_FREE; status = qsf_call(QSO_JUST_TRANS, &qsf_rcb); if (DB_FAILURE_MACRO(status)) { /* No such procedure in QSF, ask SCF to define it */ /* Tell SCF to call us back even if the porcedure */ /* cannot be loaded. We will need to clean up */ qef_rcb->qef_intstate |= QEF_DBPROC_QP; call_dsh->dsh_error.err_code = E_QE0119_LOAD_QP; break; } else { /* ** The procedure was found - make sure "saved" bit isn't on for ** the scope of this execution. It may get turned back on if ** the QP or DSH is found to be invalid but then we'll re-enter ** here (to try again) and turn it off. */ qef_rcb->qef_intstate &= ~QEF_DBPROC_QP; } /* Increase context count now that we've loaded the QP */ qef_rcb->qef_context_cnt++; /* Procedure in QSF, load the timestamp into the QEF_RCB */ /* to allow normal QEF processing to continue. */ MEcopy((PTR)qsf_rcb.qsf_obj_id.qso_name, sizeof(DB_CURSOR_ID), (PTR)&qef_rcb->qef_qp); status = qeq_dsh(qef_rcb, 0 , &proc_dsh, QEQDSH_IN_PROGRESS, page_count); if (DB_FAILURE_MACRO(status)) { char *rn, *pn; /* Rule/procedure names */ STRUCT_ASSIGN_MACRO(qef_rcb->error, call_dsh->dsh_error); if (call_dsh->dsh_error.err_code == E_QE0023_INVALID_QUERY) { /* No such procedure in QSF, ask SCF to define it */ /* Tell SCF to call us back even if the porcedure */ /* cannot be loaded. We will need to clean up */ qef_cb->qef_dsh = (PTR) call_dsh; qef_rcb->qef_qp = call_dsh->dsh_saved_rcb->qef_qp; qef_rcb->qef_intstate |= QEF_DBPROC_QP; call_dsh->dsh_error.err_code = E_QE0119_LOAD_QP; qef_rcb->qef_context_cnt--; break; } /* ** The QP DSH is invalid for some reason. Generate error and return. ** If any allocation error then change to useful error message. */ if ( call_dsh->dsh_error.err_code == E_UL0005_NOMEM || call_dsh->dsh_error.err_code == E_QS0001_NOMEM || call_dsh->dsh_error.err_code == E_QE001E_NO_MEM || call_dsh->dsh_error.err_code == E_QE000D_NO_MEMORY_LEFT || call_dsh->dsh_error.err_code == E_QE030B_RULE_PROC_MISMATCH) { pn = act->qhd_obj.qhd_callproc.ahd_dbpalias.qso_n_id.db_cur_name; rn = act->qhd_obj.qhd_callproc.ahd_rulename.db_name; if (*rn == EOS) rn = "NULL "; if (call_dsh->dsh_error.err_code == E_QE030B_RULE_PROC_MISMATCH) qef_error(E_QE030B_RULE_PROC_MISMATCH, 0L, status, &err, &call_dsh->dsh_error, 1, /* qec_trimwhite(DB_RULE_MAXNAME, rn), rn, */ qec_trimwhite(DB_DBP_MAXNAME, pn), pn); else qef_error(E_QE0199_CALL_ALLOC, 0L, status, &err, &call_dsh->dsh_error, 3, qec_trimwhite(DB_DBP_MAXNAME, pn), pn, qec_trimwhite(DB_RULE_MAXNAME, rn), rn, sizeof(qef_rcb->qef_context_cnt),&qef_rcb->qef_context_cnt); call_dsh->dsh_error.err_code = E_QE0122_ALREADY_REPORTED; } /* ** Now clean up and restore to state before routine entry. ** Pass in FALSE for release as if the DSH is NULL we do NOT want ** to cause cleanup to release all DSH's for this session ** (qee_cleanup). If the DSH is not NULL it will be cleaned up at ** the end of the query. */ need_cleanup = TRUE; need_release = FALSE; break; } if (proc_dsh->dsh_qp_ptr->qp_status & QEQP_ROWPROC) { char *pn; /* Row producing procs cannot be invoked by QEA_CALLPROC (which ** implies either nested proc call or dynamic SQL proc call). */ pn = act->qhd_obj.qhd_callproc.ahd_dbpalias.qso_n_id.db_cur_name; qef_error(E_QE030D_NESTED_ROWPROCS, 0L, E_DB_ERROR, &err, &call_dsh->dsh_error, 1, qec_trimwhite(DB_DBP_MAXNAME, pn), pn); status = E_DB_ERROR; break; } /* Found QP and DSH, stack old context */ proc_dsh->dsh_stack = call_dsh; proc_dsh->dsh_stmt_no = qef_cb->qef_stmt++; qef_cb->qef_dsh = (PTR) proc_dsh; qef_cb->qef_open_count++; /* Initialize procedure parameters (& user params - even if wrong) */ if (proc_dsh->dsh_qp_ptr->qp_ndbp_params != 0 || qef_rcb->qef_pcount > 0) { status = qee_dbparam(qef_rcb, proc_dsh, call_dsh, act->qhd_obj.qhd_callproc.ahd_params, act->qhd_obj.qhd_callproc.ahd_pcount, TRUE); if (DB_FAILURE_MACRO(status)) { /* If we fail after acquiring the DSH, we need to */ /* deallocate the DSH and recover back to the original */ /* calling state. */ STRUCT_ASSIGN_MACRO(proc_dsh->dsh_error, call_dsh->dsh_error); qef_cb->qef_open_count--; need_cleanup = TRUE; need_release = TRUE; break; } } if (is_deferred) { /* FIXME should error if it's null */ if (proc_dsh->dsh_qp_ptr->qp_setInput != NULL) STRUCT_ASSIGN_MACRO(qef_rcb->qef_setInputId, * (DB_TAB_ID *)(proc_dsh->dsh_row[proc_dsh->dsh_qp_ptr-> qp_setInput->vl_tab_id_index])); } } while (FALSE); if (need_cleanup) { /* error in a nested DB procedure, abort up to the beginning of the ** procedure if there are no other cursors opened. We ** guarantee that by decrementing the qef_open_count. If the ** count becomes zero, qeq_cleanup will abort to the last internal ** savepoint. Fix for bug 63465. */ savestat = status; open_count = qef_cb->qef_open_count; while (qef_cb->qef_open_count > 0) qef_cb->qef_open_count--; status = qeq_cleanup(qef_rcb, status, need_release); status = savestat; qef_cb->qef_open_count = open_count; qef_cb->qef_dsh = (PTR) call_dsh; qef_rcb->qef_context_cnt--; qef_rcb->qef_pcount = call_dsh->dsh_saved_rcb->qef_pcount; qef_rcb->qef_usr_param = call_dsh->dsh_saved_rcb->qef_usr_param; qef_rcb->qef_qp = call_dsh->dsh_saved_rcb->qef_qp; qef_rcb->qef_qso_handle = call_dsh->dsh_saved_rcb->qef_qso_handle; call_dsh->dsh_qef_rowcount = call_dsh->dsh_saved_rcb->qef_rowcount; call_dsh->dsh_qef_targcount = call_dsh->dsh_saved_rcb->qef_targcount; call_dsh->dsh_qef_output = call_dsh->dsh_saved_rcb->qef_output; call_dsh->dsh_qef_count = call_dsh->dsh_saved_rcb->qef_count; } return (status); }
DB_STATUS qel_c0_cre_lnk( QEF_RCB *v_qer_p ) { DB_STATUS status; QEF_CB *qef_cb = v_qer_p->qef_cb; QES_DDB_SES *dds_p = & v_qer_p->qef_cb->qef_c2_ddb_ses; QED_DDL_INFO *ddl_p = & v_qer_p->qef_r3_ddb_req.qer_d7_ddl_info; DD_0LDB_PLUS *plus_p = & ddl_p->qed_d6_tab_info_p-> dd_t9_ldb_p->dd_i2_ldb_plus; DD_CAPS *caps_p = & plus_p->dd_p3_ldb_caps; DD_LDB_DESC ldb, /* for replicating LDB desc */ *ldb_p = & ldb, *cdb_p = & dds_p->qes_d4_ddb_p-> dd_d3_cdb_info.dd_i1_ldb_desc, *ddl_ldb_p = & ddl_p->qed_d6_tab_info_p-> dd_t9_ldb_p->dd_i1_ldb_desc; QEC_D9_TABLEINFO tabinfo; /* used for table info of link */ QEC_D2_LDBIDS ldbids; /* used for internal LDB id info */ QEC_D5_LONG_LDBNAMES longnames; /* used for excessively long LDB ** name */ QEC_L16_TABLES tables; /* used for IITABLES-style info */ QEC_D6_OBJECTS objects; /* used for object info */ QEC_L6_INDEXES indexes; QEC_MIN_CAP_LVLS pre_mins, aft_mins; QEC_LINK link, /* used as global control block */ *link_p = & link; QEQ_1CAN_QRY del, ins, sel, upd, /* used for ordering canned query */ *upd_p = & upd; u_i4 len; SYSTIME now; bool log_ddl_56 = FALSE, log_err_59 = FALSE; i4 i4_1, i4_2; QEC_INDEX_ID ndx_ids[QEK_0MAX_NDX_COUNT + 1]; /* working space for index ids */ RQB_BIND rq_bind[QEC_CAT_COL_COUNT_MAX + 1]; QEC_D7_OBJECT_BASE obj_base, *base_p = & obj_base; i4 xact_mode; char *cbuf = v_qer_p->qef_cb->qef_trfmt; i4 cbufsize = v_qer_p->qef_cb->qef_trsize; if (ult_check_macro(& qef_cb->qef_trace, QEF_TRACE_DDB_LOG_DDL_56, & i4_1, & i4_2)) { log_ddl_56 = TRUE; } if (ult_check_macro(& qef_cb->qef_trace, QEF_TRACE_DDB_LOG_ERR_59, & i4_1, & i4_2)) { log_err_59 = TRUE; } sel.qeq_c2_rqf_bind_p = rq_bind; /* must set up */ del.qeq_c2_rqf_bind_p = (RQB_BIND *) NULL; ins.qeq_c2_rqf_bind_p = (RQB_BIND *) NULL; upd.qeq_c2_rqf_bind_p = (RQB_BIND *) NULL; /* 1. set up control block */ if (dds_p->qes_d7_ses_state == QES_4ST_REFRESH) /* REGISTER WITH REFRESH ? */ STRUCT_ASSIGN_MACRO(ddl_p->qed_d7_obj_id, tabinfo.d9_1_obj_id); /* yes */ else /* no */ { tabinfo.d9_1_obj_id.db_tab_base = 0; /* unknown */ tabinfo.d9_1_obj_id.db_tab_index = 0; /* always 0 for non-index */ } link_p->qec_1_ddl_info_p = ddl_p; link_p->qec_2_tableinfo_p = & tabinfo; link_p->qec_3_ldb_id = 0; link_p->qec_4_col_cnt = 0; MEfill(DB_DB_MAXNAME, ' ', link_p->qec_5_ldb_alias); link_p->qec_6_select_p = & sel; link_p->qec_7_ldbids_p = & ldbids; link_p->qec_8_longnames_p = & longnames; link_p->qec_9_tables_p = & tables; link_p->qec_10_haves = QEC_07_CREATE; if (caps_p->dd_c6_name_case == DD_2CASE_UPPER) link_p->qec_10_haves |= QEC_06_UPPER_LDB; if (caps_p->dd_c1_ldb_caps & DD_7CAP_USE_PHYSICAL_SOURCE) link_p->qec_10_haves |= QEC_10_USE_PHY_SRC; if (caps_p->dd_c2_ldb_caps & DD_201CAP_DIFF_ARCH) link_p->qec_10_haves |= QEC_11_LDB_DIFF_ARCH; /* make a copy of the LDB descriptor for non-$ingrs access if necessary */ if (ddl_ldb_p->dd_l1_ingres_b) { /* make a copy for non-$ingres access */ STRUCT_ASSIGN_MACRO(*ddl_ldb_p, ldb); ldb_p->dd_l1_ingres_b = FALSE; ldb_p->dd_l5_ldb_id = DD_0_IS_UNASSIGNED; } else { /* use provided LDB descriptor but determine if LDB has a long name */ qed_u0_trimtail( ddl_ldb_p->dd_l3_ldb_name, (u_i4) DD_256_MAXDBNAME, ldb_p->dd_l3_ldb_name); len = STlength(ldb_p->dd_l3_ldb_name); if (len > DB_DB_MAXNAME) link_p->qec_10_haves |= QEC_04_LONG_LDBNAME; ldb_p = ddl_ldb_p; } link_p->qec_11_ldb_obj_cnt = 0; link_p->qec_12_indexes_p = & indexes; link_p->qec_13_objects_p = & objects; link_p->qec_15_ndx_cnt = 0; link_p->qec_16_ndx_ids_p = ndx_ids; link_p->qec_19_ldb_p = ldb_p; link_p->qec_20_rqf_bind_p = rq_bind; link_p->qec_21_delete_p = & del; link_p->qec_22_insert_p = & ins; link_p->qec_23_update_p = & upd; status = qed_u8_gmt_now(v_qer_p, link_p->qec_24_cur_time); if (status) return(status); link_p->qec_24_cur_time[DD_25_DATE_SIZE] = EOS; link_p->qec_25_pre_mins_p = & pre_mins; link_p->qec_26_aft_mins_p = & aft_mins; link_p->qec_27_select_cnt = 0; link_p->qec_28_iistats_cnt = 0; TMnow(& now); link_p->qec_17_ts1 = now.TM_secs; link_p->qec_18_ts2 = now.TM_msecs; /* 2. inform TPF of update intention on CDB (note that only CREATE does ** LDB retrievals */ /* 2.1 2PC is required if DDL concurrency is off. */ if (dds_p->qes_d9_ctl_info & QES_01CTL_DDL_CONCURRENCY_ON) xact_mode = QEK_4TPF_1PC; else xact_mode = QEK_3TPF_UPDATE; status = qet_t5_register(v_qer_p, cdb_p, DB_SQL, xact_mode); if (status) return(status); if (log_ddl_56) { /* display beginning, CDB and LDB info */ STprintf(cbuf, "\n%s %p: %s REGISTRATION begins%s\n", IIQE_61_qefsess, (PTR) v_qer_p->qef_cb, IIQE_65_tracing, IIQE_62_3dots); qec_tprintf(v_qer_p, cbufsize, cbuf); STprintf(cbuf, "%s %p: ...the CDB:\n", IIQE_61_qefsess, (PTR) v_qer_p->qef_cb); qec_tprintf(v_qer_p, cbufsize, cbuf); qed_w1_prt_ldbdesc(v_qer_p, cdb_p); STprintf(cbuf, "%s %p: ...the LDB:\n", IIQE_61_qefsess, (PTR) v_qer_p->qef_cb); qec_tprintf(v_qer_p, cbufsize, cbuf); qed_w1_prt_ldbdesc(v_qer_p, ldb_p); STprintf(cbuf, "\n"); qec_tprintf(v_qer_p, cbufsize, cbuf); } /* 3. update OBJECT_BASE in II_DD_DB_OBJECT_BASE */ upd_p->qeq_c1_can_id = UPD_716_DD_DDB_OBJECT_BASE; upd_p->qeq_c3_ptr_u.d7_object_base_p = base_p; upd_p->qeq_c4_ldb_p = cdb_p; status = qel_u1_update(v_qer_p, link_p); if (status) goto END_TRACING; /* 4. enter phase 1: set up necessary information */ status = qel_c1_cre_p1(v_qer_p, link_p); if (status) goto END_TRACING; /* 2. enter phase 2: promote information into STAR catalogs */ status = qel_c2_cre_p2(v_qer_p, link_p); if (status) v_qer_p->qef_cb->qef_abort = TRUE; END_TRACING: if (log_ddl_56) { /* display end tracing message */ STprintf(cbuf, "%s %p: %s REGISTRATION ends\n\n", IIQE_61_qefsess, (PTR) v_qer_p->qef_cb, IIQE_65_tracing); qec_tprintf(v_qer_p, cbufsize, cbuf); } return(status); }