Пример #1
0
/*{
** 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);
}
Пример #2
0
/*{
** 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);
}
Пример #3
0
/*{
** Name: opx_vrecover	- this routine return an error code without reporting
**
** Description:
**	This routine will not log or report to the user this recoverable error
**      to but instead exit to the caller who is expected to take corrective
**      action.
**
** Inputs:
**      error                           optimizer error code to report
**      facility                        facility's error code
**      status                          facility's return status
**
** Outputs:
**	Returns:
**	    VOID
**	Exceptions:
**	    - internal exception generated
**
** Side Effects:
**	    the exception handling routines are responsible for
**          deallocating OPF resources bound to this session.
**
** History:
**	3-jul-86 (seputis)
**          initial creation
[@history_line@]...
*/
VOID
opx_vrecover(
	DB_STATUS          status,
	OPX_ERROR          error,
	OPX_FACILITY       facility)
{
    OPS_CB              *opscb;			/* ptr to session control block
                                                ** for this optimization */
    opscb = ops_getcb();
    opscb->ops_retstatus = status;		/* save status code */
    opscb->ops_callercb->opf_errorblock.err_code = error; /* save error code */
    opscb->ops_callercb->opf_errorblock.err_data = facility; /* save code 
                                                ** from facility */
    if (DB_SUCCESS_MACRO(status))
    {
	return;					/* return if error is not
                                                ** serious */
    }
    EXsignal( (EX)EX_JNP_LJMP, (i4)1, (long)error); /* signal an optimizer long
                                                ** jump with error code */
}
Пример #4
0
/*{
** Name: ops_alter	- alter session or server state for OPF
**
** Description:
**      This routine contains all processing of the SET commands for the
**      optimizer.  These commands can be at the server or session level.
**      There is currently no protection mechanism available for which
**      users are able to access these SET commands.  There probably should
**      be a system catalog created to decide privileges and min and max
**      values allowable for a session.  Currently, all users can do anything
**      at all.  This routine will not do anything in terms of checking
**      privileges.
**
**      SET [[SESSION] | SERVER] CPUFACTOR <value>
**      SET [[SESSION] | SERVER] TIMEOUT   <value>
**      SET [[SESSION] | SERVER] QEP
**      SET [[SESSION] | SERVER] NOQEP
**      SET [[SESSION] | SERVER] RET_INTO <storage_structure>
**
**      FIXME need to use semaphores to access global structures.
**
** Inputs:
**      opf_cb                          ptr to caller's control block
**
** Outputs:
**	Returns:
**	    E_DB_OK
**	Exceptions:
**	    none
**
** Side Effects:
**	    none
**
** History:
**	30-jun-86 (seputis)
**          initial creation
[@history_line@]...
*/
DB_STATUS
ops_alter(
    OPF_CB             *opf_cb)
{
    DB_STATUS           status;			/* user return status */

    switch (opf_cb->opf_level)
    {
    case OPF_SERVER:
    {   /* change operating characteristics of the server */
        DB_STATUS	temp_status;
        /* get exclusive access before updating */
        status = ops_exlock(opf_cb,
                            &((OPS_CB *)(opf_cb->opf_scb))->ops_server->opg_semaphore);
        if (DB_FAILURE_MACRO(status))
            break;
        temp_status = ops_change( opf_cb,
                                  &((OPG_CB*)opf_cb->opf_server)->opg_alter);
        /* release exclusive access */
        status = ops_unlock(opf_cb,
                            &((OPS_CB *)(opf_cb->opf_scb))->ops_server->opg_semaphore);
        if (DB_SUCCESS_MACRO(status))
            status = temp_status;
        break;
    }
    case OPF_SESSION:
    {   /* change operating characteristics of this session */
        status = ops_change( opf_cb, &((OPS_CB *)(opf_cb->opf_scb))->ops_alter);
        break;
    }
    default:
# ifdef E_OP0089_ALTER
    {
        opx_rerror( opf_cb, E_OP0089_ALTER);
        return( E_DB_ERROR );
    }
#endif
    }
    return (status);
}
Пример #5
0
/*{
** Name: opx_float	- handle floating point exception in OPF
**
** Description:
**      This routine will process a floating point exception error
**	within the optimizer.  This will normally be done by skipping
**	the part of the search space which causes the floating point
**	exception. 
**
** Inputs:
**      error                           floating point error code
**	hard				TRUE - if HARD error occurs
**					which cannot be continued from
**
** Outputs:
**
**	Returns:
**	    VOID
**	Exceptions:
**	    none
**
** Side Effects:
**	    none
**
** History:
**      28-nov-90 (seputis)
**          initial creation
**	21-jan-91 (jkb) submitted for seputis
**	    correct potential UNIX floating point problem
**	18-apr-91 (seputis)
**	    - fix bug 36920
**	31-mar-92 (rog)
**	    Remove underscores from EX return statuses.
[@history_template@]...
*/
STATUS
opx_float(
	OPX_ERROR	    error,
	bool		    hard)
{
    OPS_CB             *opscb; /* session control block */
    OPF_CB             *opfcb; /* caller's control block */

    opscb = ops_getcb();	/* get optimizer session control block */
    opfcb = opscb->ops_state->ops_caller_cb; /* report unexpected exception
                                ** otherwise */
    if (opscb->ops_check 
	&&
	opt_strace( opscb, OPT_F048_FLOAT)
	&&
	!hard
	&&
	(opscb->ops_state->ops_gmask & OPS_BFPEXCEPTION)
	)
    {
	opscb->ops_state->ops_gmask |= OPS_FPEXCEPTION; /* mark
				** plan as having a floating point
				** exception */
	return(EXCONTINUES);	/* try to recover from floating point
				** exception unless a hard error occurs
				** or a plan has been found which did
				** not have a floating point exception */
    }
    if (DB_SUCCESS_MACRO(opscb->ops_retstatus))
    {
	opfcb->opf_errorblock.err_code = error; /* save error code */
	opscb->ops_retstatus = E_DB_WARN; /* change status only if more
				** severe */
    }
    opscb->ops_state->ops_gmask |= (OPS_FLSPACE | OPS_FLINT); /* indicate that
			    ** search space has been reduced */
    return(EXDECLARE);
}
Пример #6
0
/*{
** Name: opx_verror	- this routine will report another facility's error
**
** Description:
**      This routine will report an error from another facility
**      optimizer error.  It will check the status and see the error
**      is recoverable.  The routine will not return if the status is fatal
**      but instead generate an internal exception and
**      exit via the exception handling mechanism.  The error code will be
**      placed directly in the user's calling control block.  A ptr to this
**      block was placed in the session control block (which can be requested
**      from SCF)
**
** Inputs:
**      error                           optimizer error code to report
**      facility                        facility's error code
**      status                          facility's return status
**
** Outputs:
**	Returns:
**	    VOID
**	Exceptions:
**	    - internal exception generated
**
** Side Effects:
**	    the exception handling routines are responsible for
**          deallocating OPF resources bound to this session.
**
** History:
**	3-jul-86 (seputis)
**          initial creation
**	28-jan-91 (seputis)
**          added support for OPF ACTIVE flag
**	30-apr-92 (bryanp)
**	    Translate E_RD002A_DEADLOCK to E_OP0010_RDF_DEADLOCK.
[@history_line@]...
*/
VOID
opx_verror(
	DB_STATUS          status,
	OPX_ERROR          error,
	OPX_FACILITY       facility)
{
    OPS_CB              *opscb;			/* ptr to session control block
                                                ** for this optimization */
    opscb = ops_getcb();
    opscb->ops_retstatus = status;		/* save status code */
    if (facility == E_RD002A_DEADLOCK)
	error = E_OP0010_RDF_DEADLOCK;
    if ((facility == E_RD002B_LOCK_TIMER_EXPIRED)
	&&
	(opscb->ops_smask & OPS_MCONDITION))
    {
	error = E_OP000D_RETRY;			/* when an attempt is made to
						** report the RDF timeout error
						** then it should be translated
						** into a retry error, since an
						** undetected deadlock may have
						** occurred due to the ACTIVE flag */
	opscb->ops_server->opg_sretry++;	/* track number of retrys */
	opx_vrecover(status, E_OP000D_RETRY, facility); /* this routine will not
						** return */
    }
    else
	opx_rverror(opscb->ops_callercb, status, error, facility); 

    if (DB_SUCCESS_MACRO(status))
    {
	return;					/* return if error is not
                                                ** serious */
    }
    EXsignal( (EX)EX_JNP_LJMP, (i4)1, (long)error); /* signal an optimizer long
                                                ** jump with error code */
}
Пример #7
0
/*{
** Name: psy_kinteg	- Destroy one or more integrities for a table.
**
**  INTERNAL PSF call format: status = psy_kinteg(&psy_cb, sess_cb);
**
**  EXTERNAL call format:     status = psy_call(PSY_KINTEG, &psy_cb, sess_cb);
**
** Description:
**      The psy_kinteg function removes the definitions of one or more
**	integrities on a table from the system relations (integrities,
**	tree, and iiqrytext).
**	Optionally, one can tell this function to destroy all of the
**	integrities on the given table.
**
** Inputs:
**      psy_cb
**          .psy_tables[0]              Id of table from which to remove
**					integrities
**          .psy_numbs[]                Array of integrity id numbers telling
**					which integrities to destroy (at most
**					20)
**          .psy_numnms                 Number telling how many integrity
**					numbers there are.  Zero means to
**					destroy all of the integrities
**					on the given table.
**	    .psy_tabname[0]		Name of table from which to remove
**					integrities
**	sess_cb				Pointer to session control block
**					(Can be NULL)
**
** Outputs:
**      psy_cb
**	    .psy_error			Filled in if an error happens
**		.err_code		    What the error was
**		    E_PS0000_OK			Success
**		    E_PS0001_USER_ERROR		User made a mistake
**		    E_PS0002_INTERNAL_ERROR	Internal inconsistency in PSF
**	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:
**	    Removes query tree(s) representing predicates of integrities from
**	    tree relation, text of defining query (or queries) from iiqrytext
**	    relation, rows defining integrity (or integrities) from integrities
**	    relation.  If there are no more integrities on this table, will
**	    use DMF alter table function to indicate this.
**
** History:
**	02-oct-85 (jeff)
**          written
**	30-aug-88 (andre)
**	    check if the user specified integrity 0 to be deleted,
**	    and if so, warn that it doesn't exist (this will prevent someone
**	    from inadvertently deleting all integrities by specifying that
**	    integrity 0 be deleted.)
**	30-aug-88 (andre)
**	    When looking at individual integrities, return E_DB_ERROR if any
**	    errors were found when processing individual integrities.
**	12-mar-90 (andre)
**	    set rdr_2types_mask to 0.
**      22-may-90 (teg)
**          init rdr_instr to RDF_NO_INSTR
**	03-aug-1992 (barbara)
**	    Call pst_rdfcb_init to initialize RDF_CB before calling RDF.
**	    Invalidate infoblk from RDF cache after dropping integrity.
**	07-aug-92 (teresa)
**	    RDF_INVALID must be called for the base object that the
**	    integrity was defined on as well as for the integrity trees.
**	14-sep-92 (barbara)
**	    Set type field and tableid in the RDF cb used to invalidate
**	    the cached entries.
**	14-jul-93 (ed)
**	    replacing <dbms.h> by <gl.h> <sl.h> <iicommon.h> <dbdbms.h>
**	10-aug-93 (andre)
**	    removed declaration of rdf_call()
**	30-sep-93 (stephenb)
**	    Pass tablename from psy_cb to rdf_rb, so that we can use the
**	    information to audit in QEF.
*/
DB_STATUS
psy_kinteg(
    PSY_CB             *psy_cb,
    PSS_SESBLK	   *sess_cb)
{
    RDF_CB              rdf_cb;
    RDF_CB              rdf_inv_cb; 	/* For invalidation */
    register RDR_RB	*rdf_rb = &rdf_cb.rdf_rb;
    DB_STATUS		status = E_DB_OK;
    i4		err_code;
    register i4	i;

    /* Fill in RDF control block */
    pst_rdfcb_init(&rdf_cb, sess_cb);
    pst_rdfcb_init(&rdf_inv_cb, sess_cb);
    STRUCT_ASSIGN_MACRO(psy_cb->psy_tables[0], rdf_rb->rdr_tabid);
    STRUCT_ASSIGN_MACRO(psy_cb->psy_tables[0], rdf_inv_cb.rdf_rb.rdr_tabid);
    rdf_rb->rdr_types_mask = RDR_INTEGRITIES;
    rdf_inv_cb.rdf_rb.rdr_types_mask = RDR_INTEGRITIES;
    rdf_rb->rdr_update_op = RDR_DELETE;
    rdf_rb->rdr_name.rdr_tabname = psy_cb->psy_tabname[0];

    /* No integrity numbers means destroy all integrities. */
    if (psy_cb->psy_numnms == 0)
    {
        /* Zero integrity number means destroy all integs. */
        rdf_rb->rdr_qrymod_id = 0;
        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, &psy_cb->psy_error, 1,
                                 psf_trmwhite(sizeof(psy_cb->psy_tabname[0]),
                                              (char *) &psy_cb->psy_tabname[0]),
                                 &psy_cb->psy_tabname[0]);
            }
            else
            {
                (VOID) psf_rdf_error(RDF_UPDATE, &rdf_cb.rdf_error,
                                     &psy_cb->psy_error);
            }
            return (status);
        }

        /* Invalidate table info from RDF cache */

        /* first invalidate the object from the relation cache */
        status = rdf_call(RDF_INVALIDATE, (PTR) &rdf_inv_cb);
        if (DB_FAILURE_MACRO(status))
            (VOID) psf_rdf_error(RDF_INVALIDATE, &rdf_inv_cb.rdf_error,
                                 &psy_cb->psy_error);

        /* now invalidate any integrity trees from the cache */
        rdf_inv_cb.rdf_rb.rdr_2types_mask |= RDR2_CLASS;
        status = rdf_call(RDF_INVALIDATE, (PTR) &rdf_inv_cb);
        if (DB_FAILURE_MACRO(status))
            (VOID) psf_rdf_error(RDF_INVALIDATE, &rdf_inv_cb.rdf_error,
                                 &psy_cb->psy_error);
    }
    else
    {
        DB_STATUS   stat;

        /* Run through the integrity numbers, destroying each one */
        for (i = 0; i < psy_cb->psy_numnms; i++)
        {

            /* if user specified 0, complain and proceed with next integrity # */
            if ((rdf_rb->rdr_qrymod_id = psy_cb->psy_numbs[i]) == 0)
            {
                /* remember error to report later */
                status = (status > E_DB_ERROR) ? status : E_DB_ERROR;

                (VOID) psf_error(5203, 0L, PSF_USERERR, &err_code,
                                 &psy_cb->psy_error, 1,
                                 sizeof (rdf_rb->rdr_qrymod_id),
                                 &rdf_rb->rdr_qrymod_id);
                continue;
            }

            stat = rdf_call(RDF_UPDATE, (PTR) &rdf_cb);

            /* remember the highest status seen so far */
            status = (status > stat) ? status : stat;

            if (DB_FAILURE_MACRO(stat))
            {
                switch (rdf_cb.rdf_error.err_code)
                {
                case E_RD0002_UNKNOWN_TBL:
                    (VOID) psf_error(E_PS0903_TAB_NOTFOUND, 0L, PSF_USERERR,
                                     &err_code, &psy_cb->psy_error, 1,
                                     psf_trmwhite(sizeof(psy_cb->psy_tabname[0]),
                                                  (char *) &psy_cb->psy_tabname[0]),
                                     &psy_cb->psy_tabname[0]);
                    break;

                case E_RD0013_NO_TUPLE_FOUND:
                    (VOID) psf_error(5203, 0L, PSF_USERERR,
                                     &err_code, &psy_cb->psy_error, 1,
                                     sizeof (rdf_rb->rdr_qrymod_id),
                                     &rdf_rb->rdr_qrymod_id);
                    continue;

                default:
                    (VOID) psf_rdf_error(RDF_UPDATE, &rdf_cb.rdf_error,
                                         &psy_cb->psy_error);
                }

                return (status);
            }

            /* invalidate the integrity tree from the cache. */
            rdf_inv_cb.rdf_rb.rdr_sequence = psy_cb->psy_numbs[i];
            rdf_inv_cb.rdf_rb.rdr_2types_mask |= RDR2_ALIAS;
            status = rdf_call(RDF_INVALIDATE, (PTR) &rdf_inv_cb);
            if (DB_FAILURE_MACRO(status))
            {
                (VOID) psf_rdf_error(RDF_INVALIDATE, &rdf_inv_cb.rdf_error,
                                     &psy_cb->psy_error);
                break;
            }
        }
        /* now invalidate the integrity base object from the relation cache */
        if (DB_SUCCESS_MACRO(status))
        {
            rdf_inv_cb.rdf_rb.rdr_sequence = 0;
            rdf_inv_cb.rdf_rb.rdr_2types_mask &= ~RDR2_ALIAS;
            status = rdf_call(RDF_INVALIDATE, (PTR) &rdf_inv_cb);
            if (DB_FAILURE_MACRO(status))
            {
                (VOID) psf_rdf_error(RDF_INVALIDATE, &rdf_inv_cb.rdf_error,
                                     &psy_cb->psy_error);
            }
        }
    }

    return    (status);
}
Пример #8
0
VOID
opc_querycomp(
		OPS_STATE          *global)
{
    DB_STATUS	    	ret;

    global->ops_gmask |= OPS_OPCEXCEPTION;  /* mark facility as being in OPC */
#ifdef OPT_F033_OPF_TO_OPC
    if (opt_strace(global->ops_cb, OPT_F033_OPF_TO_OPC) == TRUE)
    {
	char	temp[OPT_PBLEN + 1];
	bool	init = 0;

	if (global->ops_cstate.opc_prbuf == NULL)
	{
	    global->ops_cstate.opc_prbuf = temp;
	    init++;
	}

	/* Trace all of 'global' */
        if (global->ops_statement != NULL)
        {
	    opt_state(global);
	}
	    
	if (init)
	{
	    global->ops_cstate.opc_prbuf = NULL;
	}
    }
#endif

    if ( opt_strace(global->ops_cb, OPT_F071_QEP_WITHOUT_COST ) == TRUE && global->ops_subquery)
    {
	opt_cotree_without_stats( global );
    }

    /* If this is CREATE TABLE, check for primary, unique, foreign key
    ** constraints to use for default base table structure. */
    if (global->ops_statement &&
	global->ops_statement->pst_type == PST_CREATE_TABLE_TYPE &&
	global->ops_statement->pst_specific.pst_createTable.
			pst_createTableFlags == PST_CRT_TABLE)
    {
	QEU_CB *qeucb = global->ops_statement->pst_specific.pst_createTable.pst_createTableQEUCB;
	DMU_CB *dmucb = (DMU_CB *) qeucb->qeu_d_cb;
	bool checkit = FALSE;

	if (BTtest(DMU_AUTOSTRUCT, dmucb->dmu_chars.dmu_indicators))
	    checkit = (dmucb->dmu_chars.dmu_flags & DMU_FLAG_AUTOSTRUCT) != 0;
	else
	    checkit = opt_strace(global->ops_cb, OPT_F084_TBLAUTOSTRUCT ) ||
			global->ops_cb->ops_alter.ops_autostruct != 0;
	if (checkit)
	    opc_checkcons(global->ops_statement, dmucb);
    }

    /* On entry for rule processing, assume ops_qpinit == TRUE. There	    */
    /* is no need to allocate a memory stream since we are contuing	    */
    /* processing on the QP that was started by the triggering statement. */
    if (global->ops_qpinit == FALSE)
    {
	/* First, lets open the stack ULM memory stream that OPC uses */
	opu_Osmemory_open(global);

	/* Tell QSF that we want to store an object; */
	global->ops_qsfcb.qsf_obj_id.qso_type = QSO_QP_OBJ;
	if (global->ops_procedure->pst_flags & PST_REPEAT_DYNAMIC)
	{
	    char	*p;

	    global->ops_qsfcb.qsf_obj_id.qso_lname = sizeof(DB_CURSOR_ID) + sizeof(i4);
	    MEfill(sizeof(global->ops_qsfcb.qsf_obj_id.qso_name), 0,
		   global->ops_qsfcb.qsf_obj_id.qso_name);
	    MEcopy((PTR)&global->ops_procedure->pst_dbpid.db_cursor_id[0],
		   sizeof (global->ops_procedure->pst_dbpid.db_cursor_id[0]),
		   (PTR)global->ops_qsfcb.qsf_obj_id.qso_name);
	    p = (char *) global->ops_qsfcb.qsf_obj_id.qso_name + 2*sizeof(i4);
	    if (global->ops_caller_cb->opf_locator)
		MEcopy((PTR)"ql", sizeof("ql"), p);
	    else MEcopy((PTR)"qp", sizeof("qp"), p);
	    p = (char *) global->ops_qsfcb.qsf_obj_id.qso_name + sizeof(DB_CURSOR_ID);
	    I4ASSIGN_MACRO(global->ops_caller_cb->opf_udbid, *(i4 *) p); 


	}
	else if (   global->ops_procedure->pst_isdbp == TRUE
	    || (   global->ops_qheader != NULL
		&& (global->ops_qheader->pst_mask1 & PST_RPTQRY)
	       )
	   )
	{
	    global->ops_qsfcb.qsf_obj_id.qso_lname = 
		sizeof (global->ops_procedure->pst_dbpid);
	    MEcopy((PTR)&global->ops_procedure->pst_dbpid, 
		   sizeof (global->ops_procedure->pst_dbpid),
		   (PTR)global->ops_qsfcb.qsf_obj_id.qso_name);
	}
	else
	{
	    global->ops_qsfcb.qsf_obj_id.qso_lname = 0;
	}

	/* Also allow for the case where a concurrent clash causes a new
	** object at an awkward point */
	if ((ret = qsf_call(QSO_CREATE, &global->ops_qsfcb)) != E_DB_OK &&
	    !(ret == E_DB_ERROR &&
		global->ops_qsfcb.qsf_error.err_code == E_QS001C_EXTRA_OBJECT) &&
	    !((global->ops_procedure->pst_flags & PST_SET_INPUT_PARAM)  &&
	     global->ops_qsfcb.qsf_error.err_code == E_QS001C_EXTRA_OBJECT))
	{
	    /* if object exists and we have a named query plan. */
	    if (global->ops_qsfcb.qsf_error.err_code
		    == E_QS000A_OBJ_ALREADY_EXISTS
	       )
	    {
		/* Log query info */
		QSO_OBID    *obj = &global->ops_qsfcb.qsf_obj_id;
		char	    *qrytype;
		char	    *objtype;
		char	    *objname;
		char	    *qrytext;
		char	    tmp[(DB_OWN_MAXNAME + DB_CURSOR_MAXNAME)  + 3 + 1];
		DB_STATUS   status;
		QSF_RCB	    qsf_rb;
		PSQ_QDESC   *qdesc;

		if (global->ops_procedure->pst_isdbp == TRUE)
		    qrytype = "database procedure";
		else if (global->ops_qheader != NULL
			 && (global->ops_qheader->pst_mask1 & PST_RPTQRY)
			)
		    qrytype = "repeat query";
		else
		    qrytype = "non-repeat query";

		objtype = "QSO_QP_OBJ";

		if (obj->qso_lname == 0)
		{
		    objname = "QSF object has no name";
		}
		else
		{
		    char	    fmt[30];
		    DB_CURSOR_ID    *curid;
		    char	    *user;
		    i4		    *dbid;

		    curid = (DB_CURSOR_ID *)obj->qso_name;
		    user = curid->db_cur_name + DB_CURSOR_MAXNAME;
		    dbid = (i4 *)(user + DB_OWN_MAXNAME);

		    STprintf(fmt, ":%%lx:%%lx:%%.%ds:%%.%ds:%%lx:",
			DB_CURSOR_MAXNAME, DB_OWN_MAXNAME);

		    STprintf(tmp, fmt, (i4)curid->db_cursor_id[0], 
			(i4)curid->db_cursor_id[1],
			curid->db_cur_name, user, (i4)(*dbid));

		    objname = tmp;
		}
 
		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_OPF_ID;
		qsf_rb.qsf_obj_id.qso_handle = global->ops_caller_cb->opf_thandle;

		qrytext = "Query text was not available.";

		if (qsf_rb.qsf_obj_id.qso_handle != NULL)
		{
		    status = qsf_call(QSO_INFO, &qsf_rb);

		    if (DB_SUCCESS_MACRO(status))
		    {
			qdesc = (PSQ_QDESC*) qsf_rb.qsf_root;

			qrytext = qdesc->psq_qrytext;
		    }
		}

		/* log an error */
		opx_lerror((OPX_ERROR)E_OP089F_QSF_FAILCREATE, (i4)4,
		    (PTR)qrytype, (PTR)objtype, (PTR)objname, (PTR)qrytext);
	    }

	    opx_verror(ret, E_OP0882_QSF_CREATE, 
		global->ops_qsfcb.qsf_error.err_code);
	}

	/* Put the handle for the QEP into the callers CB; 
	** - will be used for deallocation in case of an error
	** - both the object id and the lock id are needed in order to destroy
	** the object
	*/
	STRUCT_ASSIGN_MACRO(global->ops_qsfcb.qsf_obj_id,
	    global->ops_caller_cb->opf_qep);
	global->ops_qplk_id = global->ops_qsfcb.qsf_lk_id;
	global->ops_qpinit = TRUE;

	/* Allocate and initialize the QP. */
	opc_iqp_init(global);
    }

    /* Continue the QP compilation by adding the current statement */
    if (global->ops_statement != NULL)
    {
	opc_cqp_continue(global);
    }

    /* if it's time to stop compiling the query, then lets close stuff. */
    /* The caller is responsible for making one additional call to OPC	    */
    /* with ops_statement == NULL after all statements in the QP we are	    */
    /* currently building have been compiled. Note that this is a change    */
    /* from the previous version of this routine which required the extra   */
    /* call only if a db procedure was being compiled. Such a call must	    */
    /* also be made after the last statement in each rule list. This allows */
    /* OPC to link all conditionals statements in the rule list together    */
    /* before continuing with the next user statement to be compiled. */
    if (global->ops_statement == NULL)
    {
	/* We're finished compiling all of the statements, so lets finish
	** the QP
	*/
	opc_fqp_finish(global);

	/* The QP is only associated with the outer query, not a rule list  */
	if (!global->ops_inAfterRules && !global->ops_inBeforeRules)
	{
	    /* Tell QSF what the root of the QEP is; */
	    global->ops_qsfcb.qsf_root = (PTR) global->ops_cstate.opc_qp;
	    if ((ret = qsf_call(QSO_SETROOT, &global->ops_qsfcb)) != E_DB_OK)
	    {
		opx_verror(ret, E_OP0883_QSF_SETROOT, 
					global->ops_qsfcb.qsf_error.err_code);
	    }

	    if ((ret = qsf_call(QSO_UNLOCK, &global->ops_qsfcb)) != E_DB_OK)
	    {
		opx_verror(ret, E_OP089E_QSF_UNLOCK, 
		    global->ops_qsfcb.qsf_error.err_code);
	    }

	    /* Now lets close the stack ULM memory stream that OPC used */
	    opu_Csmemory_close(global);
	}
    }
    global->ops_gmask &= (~OPS_OPCEXCEPTION);  /* mark facility as leaving OPC */
}
Пример #9
0
/*{
** Name: psy_gproc - Get a database procedure definition from
**		     the system catalogs.
**
** Description:
**
** Inputs:
**	    psq_cb	    
**		psq_cursid
**		    db_cur_name	    dbproc name
**	    sess_cb
**		pss_user	    current user name
**		pss_dba		    dba name
**	    qsf_rb	    
**	    rdf_cb
**	    dbp_owner		    name of the owner whose dbproc will be
**				    looked up iff gproc_mask & PSS_DBP_BY_OWNER.
**	    gproc_mask		    mask used to specify the possible owners of
**				    the dbproc to look for
**		PSS_USRDBP	    look for dbproc owned by the current user
**		PSS_DBADBP	    look for dbproc owned by the DBA
**		PSS_INGDBP	    look for dbproc owned by $INGRES
**		PSS_DBP_BY_OWNER    look for dbproc owned by the specific user
**
**				    NOTE: if PSS_DBP_BY_OWNER is set,
**				          PSS_USRDBP, PSS_DBADBP, and PSS_INGDBP
**					  will be disregarded
**					  otherwise, we expect that PSS_USRDBP
**					  will be always set, while PSS_DBADBP
**					  and PSS_INGDBP may or may not be set
**
** Outputs:
**	    alt_user		    set to point the name of dbproc owner if
**				    different from cb->pss_user
**	    psq_cb
**		psq_error	    filled in if an error occurred
**
**	    ret_flags		    bits may be set to pass info to the caller
**		PSS_MISSING_DBPROC  dbproc not found
**
** Exceptions:
**	    none
**
** Returns
**	E_DB_OK, E_DB_ERROR
**
** Side Effects:
**	    Allocates memory.
**
** History:
**      27-apr-88 (stec)
**	    Created.
**	04-aug-88 (stec)
**	    Improve recovery of resources.
**	17-aug-88 (stec)
**	    Change bad STRUCT_ASSIGN statements.
**	28-sep-88 (stec)
**	    Do not lock object on cleanup.
**	28-sep-88 (stec)
**	    Must not unfix RDF entry.
**	16-mar-89 (andre)
**	    Added a new parameter - alt_user.
**	    psy_gproc will no longer reset pss_user or set pss_ruset.  Instead
**	    it may set the ptr passed to it to the name of the dbproc owner.
**	16-mar-89 (neil)
**	    Modified psy_gproc to access the procedure through the specified
**	    owner (psq_als_owner) if psq_alias_set is on.
**	27-apr-89 (andre)
**	    Further modify to search for dbprocs owned by $ingres if the search
**	    by user and DBA failed.  The search part of the function has been,
**	    essentially, rewritten.
**	12-mar-90 (andre)
**	    set rdr_2types_mask to 0.
**      22-may-90 (teg)
**          init rdr_instr to RDF_NO_INSTR
**	01-jun-90 (andre)
**	    Changed interface to allow caller to explicitly specify the possible
**	    owners of the dbproc to look for.
**	01-oct-91 (andre)
**	    Added ret_flags to the interface - this field will be used to pass
**	    additional info to the caller.  in particular, it will allow us to
**	    signal certain classes of errors (e.g. dbproc not found) without
**	    setting return status to E_DB_ERROR, thus enabling the caller to
**	    distinguish such errors from unexpected errors
**	15-oct-1993 (rog)
**	    We need to use ulm_copy() instead of MEcopy() when copying query
**	    text that might be more than 64k.
**	12-jan-94 (andre)
**	    As a part of fix for bug 58048, we must remove the assumption that 
**	    either PSS_USRDBP or PSS_DBP_BY_OWNER bit will always be set in 
**	    gproc_mask.  Now we will be prepared to handle PSS_DBP_BY_OWNER or
**	    one or more of PSS_USRDBP, PSS_DBADBP, and PSS_INGDBP.
**	13-jan-94 (andre)
**	    if we fail to find a dbproc, we will set PSS_MISSING_DBPROC in 
**	    *ret_flags, but leave it up to the caller to issue an error 
**	    message - this way the caller can decide whether this warrants an 
**	    error message and if so can choose his favourite error message
*/
DB_STATUS
psy_gproc(
	PSQ_CB		*psq_cb,
	PSS_SESBLK	*sess_cb,
	QSF_RCB		*qsf_rb,
	RDF_CB		*rdf_cb,
	DB_OWN_NAME	**alt_user,
	DB_OWN_NAME	*dbp_owner,
	i4		gproc_mask,
	i4		*ret_flags)
{
    DB_STATUS		status, stat;
    i4		err_code;
    RDD_QRYMOD		*pinfo;
    PSQ_QDESC		*qdesc;
    bool		leave_loop = TRUE;
    DB_PROCEDURE *dbp;
    SXF_ACCESS  access;
    i4	msgid;
    i4	local_status;

    *ret_flags = 0;

    /* First call RDF to retrieve the definition
    ** of the procedure.
    */

    /* Initialize the RDF control block */
    pst_rdfcb_init(rdf_cb, sess_cb);

    (VOID) MEcopy((PTR) psq_cb->psq_cursid.db_cur_name,
	sizeof (DB_DBP_NAME),
	(PTR) &rdf_cb->rdf_rb.rdr_name.rdr_prcname);
    rdf_cb->rdf_rb.rdr_types_mask = RDR_PROCEDURE | RDR_BY_NAME;

    /* assume that the dbproc is owned by the current user */
    *alt_user = (DB_OWN_NAME *) NULL;
    
    do
    {
	if (gproc_mask & (PSS_USRDBP | PSS_DBP_BY_OWNER))
	{
	    if (gproc_mask & PSS_USRDBP)
	    {
		STRUCT_ASSIGN_MACRO(sess_cb->pss_user, 
		    rdf_cb->rdf_rb.rdr_owner);
	    }
	    else
	    {
		STRUCT_ASSIGN_MACRO((*dbp_owner), rdf_cb->rdf_rb.rdr_owner);
		if (MEcmp((PTR)&sess_cb->pss_user, (PTR) dbp_owner,
			  sizeof(DB_OWN_NAME)))
		{
		    *alt_user = dbp_owner;		/* Try someone else */
		}
	    }

	    /* Get the text */
	    status = rdf_call(RDF_GETINFO, (PTR) rdf_cb);

	    /*
	    ** We do not want to continue search if:
	    ** 1) dbproc was found					    OR
	    ** 2) we got an error other that PROC_NOT_FOUND		    OR
	    ** 3) caller requested a dbproc owned by a specific user
	    **    (gproc_mask & PSS_DBP_BY_OWNER)			    OR
	    */
	    if (   DB_SUCCESS_MACRO(status)				    
		|| rdf_cb->rdf_error.err_code != E_RD0201_PROC_NOT_FOUND   
		|| gproc_mask & PSS_DBP_BY_OWNER)
	    {
	        break;
	    }
	}

	/* 
	** if we were told to check whether a dbproc is owned by the DBA, do so
	** unless the DBA is the current user and we have already established 
	** that the current user does not own a dbproc with this name
	*/
	if (   gproc_mask & PSS_DBADBP 
	    && (   ~gproc_mask & PSS_USRDBP
		|| MEcmp((PTR) &sess_cb->pss_user, 
		       (PTR) &sess_cb->pss_dba.db_tab_own, sizeof(DB_OWN_NAME))
	       )
	   )
	{
	    STRUCT_ASSIGN_MACRO(sess_cb->pss_dba.db_tab_own,
				rdf_cb->rdf_rb.rdr_owner);

	    /*
	    ** If we succeed and the DBA is different from the current user, 
	    ** the procedure text will have to be parsed in the context of 
	    ** dbproc's owner, i.e. DBA.  Note that if we were also asked to 
	    ** check whether the dbproc is owned by the current user and still 
	    ** found ourselves here, DBA must be different from the current user
	    */
	    if (   gproc_mask & PSS_USRDBP
		|| MEcmp((PTR) &sess_cb->pss_user,
		       (PTR) &sess_cb->pss_dba.db_tab_own, sizeof(DB_OWN_NAME)))
	    {
	        *alt_user = &sess_cb->pss_dba.db_tab_own;
	    }

	    /* Get the text */
	    status = rdf_call(RDF_GETINFO, (PTR) rdf_cb);

	    /*
	    ** We do not want to continue search if:
	    ** 1) dbproc was found				OR
	    ** 2) we got an error other that PROC_NOT_FOUND
	    */
	    if (DB_SUCCESS_MACRO(status) ||
	        rdf_cb->rdf_error.err_code != E_RD0201_PROC_NOT_FOUND)
	    {
		break;
	    }
	}

	if (gproc_mask & PSS_INGDBP)
	{
	    MEmove(sizeof(*sess_cb->pss_cat_owner), (PTR)sess_cb->pss_cat_owner,
		   ' ', DB_OWN_MAXNAME, (PTR) &rdf_cb->rdf_rb.rdr_owner); 
	}
	else
	{
	    /*
	    ** if user has not requested that a dbproc owned by $INGRES be
	    ** looked up, might as well get out of the loop
	    */
	    break;
	}
	
	/* 
	** if we were told to check whether a dbproc is owned by $ingres, do so
	** unless the $ingres is the current user and we have already 
	** established that the current user does not own a dbproc with this 
	** name or $ingres is the DBA and we have already established that the
	** DBA does not own a dbproc with this name
	*/
	if (   (   ~gproc_mask & PSS_USRDBP
	        || MEcmp((PTR)&sess_cb->pss_user, 
		       (PTR) &rdf_cb->rdf_rb.rdr_owner, sizeof(DB_OWN_NAME))
	       )
	    && (   ~gproc_mask & PSS_DBADBP
		|| MEcmp((PTR) &sess_cb->pss_dba.db_tab_own,
	               (PTR) &rdf_cb->rdf_rb.rdr_owner, sizeof(DB_OWN_NAME))
	       )
	   )
	{
	    /*
	    ** If we succeed, the procedure text will have to be parsed in
	    ** the context of the original owner, i.e. $ingres.
	    */
	    *alt_user = &rdf_cb->rdf_rb.rdr_owner;
	    /*
	    ** If we succeed and $ingres is not the current user, the procedure
	    ** text will have to be parsed in the context of dbproc's owner, 
	    ** i.e. $ingres.  Note that if we were also asked to check whether 
	    ** the dbproc is owned by the current user and still found ourselves
	    ** here, the current user must NOT be $ingres
	    */
	    if (   gproc_mask & PSS_USRDBP
		|| MEcmp((PTR) &sess_cb->pss_user,
		       (PTR) &rdf_cb->rdf_rb.rdr_owner, sizeof(DB_OWN_NAME)))
	    {
	        *alt_user = &sess_cb->pss_dba.db_tab_own;
	    }


	    /* Get the text */
	    status = rdf_call(RDF_GETINFO, (PTR) rdf_cb);
	}
	
	/* leave_loop has already been set to TRUE */
    } while (!leave_loop);

    if (DB_FAILURE_MACRO(status))
    {
	if (rdf_cb->rdf_error.err_code == E_RD0201_PROC_NOT_FOUND)
	{
	    /*
	    ** dbproc was not found - set a bit in ret_flags and reset status to
	    ** E_DB_OK to enable callers to distinguish between this and other
	    ** errors
	    */
	    status = E_DB_OK;
	    *ret_flags |= PSS_MISSING_DBPROC;
	}
	else
	{
	    (VOID) psf_rdf_error(RDF_GETINFO, &rdf_cb->rdf_error,
				 &psq_cb->psq_error);
	}
	return(status);
    }

    /* we get here only if the dbproc was found */
    
    /*
    ** If the procedure has a security label, validate it
    */
    dbp=rdf_cb->rdf_info_blk->rdr_dbp;

    /* 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_RCB);
    qsf_rb->qsf_owner = (PTR)DB_PSF_ID;
    qsf_rb->qsf_sid = sess_cb->pss_sessid;
    qsf_rb->qsf_obj_id.qso_type = QSO_QTEXT_OBJ;
    qsf_rb->qsf_obj_id.qso_lname = 0;

    /* Having retrieved the text place it in QSF
    ** because the parser expects it to be there.
    */
    status = qsf_call(QSO_CREATE, qsf_rb);

    if (DB_FAILURE_MACRO(status))
    {
	i4	    qerr = qsf_rb->qsf_error.err_code;

	if (qerr == E_QS0001_NOMEM)
	{
	    (VOID) psf_error(qerr, qerr,
		PSF_CALLERR, &err_code, &psq_cb->psq_error, 0);
	}
	else
	{
	    (VOID) psf_error(E_PS0A05_BADMEMREQ, qerr,
		PSF_INTERR, &err_code, &psq_cb->psq_error, 0);
	}

	goto cleanup2;
    }

    /* Object is locked exclusively now. */

    pinfo = rdf_cb->rdf_rb.rdr_procedure;

    /* Allocate enough memory for the query descriptor
    ** plus the length of text.
    */
    qsf_rb->qsf_sz_piece = sizeof(PSQ_QDESC) +
	pinfo->rdf_l_querytext + 3; /* one space, one null,
				    ** one for safety.
				    */

    status = qsf_call(QSO_PALLOC, qsf_rb);

    if (DB_FAILURE_MACRO(status))
    {
	i4	    qerr = qsf_rb->qsf_error.err_code;

	if (qerr == E_QS0001_NOMEM)
	{
	    (VOID) psf_error(qerr, qerr,
		PSF_CALLERR, &err_code, &psq_cb->psq_error, 0);
	}
	else
	{
	    (VOID) psf_error(E_PS0A05_BADMEMREQ, qerr,
		PSF_INTERR, &err_code, &psq_cb->psq_error, 0);
	}

	goto cleanup1;
    }

    qdesc = (PSQ_QDESC *) qsf_rb->qsf_piece;

    /* Initialize query descriptor. */
    qdesc->psq_qrysize = pinfo->rdf_l_querytext + 1; /* 1 trailing space */
    qdesc->psq_datasize = 0;
    qdesc->psq_dnum = 0;
    qdesc->psq_qrytext = (char *)(qdesc + 1); /* Ptr arithmetic, should point
				    ** right after the PSQ_QDESC.
				    */
    qdesc->psq_qrydata = (DB_DATA_VALUE **) NULL;

    /* QSF memory has been allocated now, copy
    ** the text from RDF.
    */
    ulm_copy((PTR) pinfo->rdf_querytext,
	     (i4) pinfo->rdf_l_querytext,
	     (PTR) qdesc->psq_qrytext);

    /* Add a space after the text and null terminate. */
    {
	char	*p;

	p = qdesc->psq_qrytext;		/* beginning of text */
	p += pinfo->rdf_l_querytext;	/* 1st char past end */
	*p++ = ' ';
	*p = '\0';			/* 2nd char past end */
    }

    /* Set root for the QSF object */
    qsf_rb->qsf_root = qsf_rb->qsf_piece;

    status = qsf_call(QSO_SETROOT, qsf_rb);

    if (DB_FAILURE_MACRO(status))
    {
	(VOID) psf_error(E_PS0A05_BADMEMREQ, qsf_rb->qsf_error.err_code,
		PSF_INTERR, &err_code, &psq_cb->psq_error, 0);
	goto cleanup1;
    }

    status = qsf_call(QSO_UNLOCK, qsf_rb);

    if (DB_FAILURE_MACRO(status))
    {
	(VOID) psf_error(E_PS0B05_CANT_UNLOCK, qsf_rb->qsf_error.err_code,
		PSF_INTERR, &err_code, &psq_cb->psq_error, 0);
	goto cleanup1;
    }

    psq_cb->psq_qid = qsf_rb->qsf_obj_id.qso_handle;

    return (status);

cleanup1:
    /* Destroy the object, it's already locked. */
    stat = qsf_call(QSO_DESTROY, qsf_rb);

    if (DB_FAILURE_MACRO(stat))
    {
	(VOID) psf_error(E_PS0A09_CANTDESTROY, qsf_rb->qsf_error.err_code,
		PSF_INTERR, &err_code, &psq_cb->psq_error, 0);
	if (stat > status)
	    status = stat;
    }

cleanup2:
    /* RDF object can be released now. */

    stat = rdf_call(RDF_UNFIX, (PTR) rdf_cb);

    if (DB_FAILURE_MACRO(stat))
    {
	(VOID) psf_rdf_error(RDF_UNFIX,
	    &rdf_cb->rdf_error, &psq_cb->psq_error);
	if (stat > status)
	    status = stat;
    }

    return (status);
}
Пример #10
0
/*{
** Name: psy_kproc - Drop a database procedure definition from
**		     the system catalogs.
**
** Description:
**
** Inputs:
**
** Outputs:

**	Exceptions:
**	    none
**
** Side Effects:
**	    Modifies system catalogs.
**
** History:
**      27-apr-88 (stec)
**	    Created.
**	12-mar-90 (andre)
**	    set rdr_2types_mask to 0.
**      22-may-90 (teg)
**          init rdr_instr to RDF_NO_INSTR
**	12-jun-90 (andre)
**	    when trying to destroy a dbproc QEP, use "private" alias, which is
**	    always defined as opposed to the "public" alias which would not be
**	    defined if the dbproc is not grantable.
**	06-aug-92 (teresa)
**	    change interface to invalidate procedure by name, owner.
**	    must set rdr_flags_mask = RDR_PROCEDURE when invalidating the
**	    procedure cache object.
**	07-nov-92 (andre)
**	    we will no longer create private aliases for dbproc QPs
**	16-jun-94 (andre)
**	    it is dangerous to cast a (char *) into a (DB_CURSOR_ID *) and then
**	    dereference the resulting pointer because the chat ptr may not be 
**	    pointing at memory not aligned on an appopriate boundary.  Instead,
**	    we will allocate a DB_CURSOR_ID structure on the stack, initialize 
**	    it and MEcopy() it into the char array
*/
DB_STATUS
psy_kproc(
	PSY_CB		*psy_cb,
	PSS_SESBLK	*sess_cb)
{
    RDF_CB		rdf_cb;
    register RDR_RB	*rdf_rb = &rdf_cb.rdf_rb;
    DB_STATUS		status, stat;
    i4		err_code;

    pst_rdfcb_init(&rdf_cb, sess_cb);
    (VOID) MEcopy((PTR)&psy_cb->psy_tabname[0], sizeof(DB_DBP_NAME),
	(PTR)&rdf_rb->rdr_name.rdr_prcname);
    STRUCT_ASSIGN_MACRO(sess_cb->pss_user, rdf_rb->rdr_owner);
    rdf_rb->rdr_types_mask = RDR_PROCEDURE;
    rdf_rb->rdr_update_op = RDR_DELETE;

    status = rdf_call(RDF_UPDATE, (PTR) &rdf_cb);

    if (DB_FAILURE_MACRO(status))
    {
	if (rdf_cb.rdf_error.err_code == E_RD0013_NO_TUPLE_FOUND)
	{
	    /* Retry */
	    psy_cb->psy_error.err_code = E_PS0008_RETRY;
	}
	else
	{
	    (VOID) psf_rdf_error(RDF_UPDATE, &rdf_cb.rdf_error,
		&psy_cb->psy_error);
	    return (status);
	}
    }

    /* Try to destroy the procedure QP in QSF if things went OK. */
    if (DB_SUCCESS_MACRO(status))
    {
    	QSF_RCB		qsf_rb;
	PSS_DBPALIAS	dbpid;
	DB_CURSOR_ID	dbp_curs_id;

	/* Initialize the header of 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;

	qsf_rb.qsf_feobj_id.qso_type = QSO_ALIAS_OBJ;
	qsf_rb.qsf_feobj_id.qso_lname = sizeof(dbpid);

	/* Identify the object first */
	dbp_curs_id.db_cursor_id[0] = dbp_curs_id.db_cursor_id[1] = 0;
	(VOID) MEcopy((PTR)&psy_cb->psy_tabname[0], DB_TAB_MAXNAME,
	    (PTR)dbp_curs_id.db_cur_name);
	MEcopy((PTR) &dbp_curs_id, sizeof(DB_CURSOR_ID), (PTR) dbpid);

	(VOID) MEcopy((PTR) &sess_cb->pss_user, DB_OWN_MAXNAME,
	    (PTR) (dbpid + sizeof(DB_CURSOR_ID)));

	I4ASSIGN_MACRO(sess_cb->pss_udbid,
		       *(i4 *) (dbpid + sizeof(DB_CURSOR_ID) + DB_OWN_MAXNAME));

	(VOID)MEcopy((PTR) dbpid, sizeof(dbpid),
	    (PTR) qsf_rb.qsf_feobj_id.qso_name);

	/* See if QEP for the alias already exists. */
	qsf_rb.qsf_lk_state = QSO_SHLOCK;
	stat = qsf_call(QSO_JUST_TRANS, &qsf_rb);

	if (DB_FAILURE_MACRO(stat))
	{
	    if (qsf_rb.qsf_error.err_code != E_QS0019_UNKNOWN_OBJ)
	    {
		(VOID) psf_error(E_PS037A_QSF_TRANS_ERR,
		    qsf_rb.qsf_error.err_code, PSF_INTERR,
		    &err_code, &psy_cb->psy_error, 0);
		if (stat > status)
		    status = stat;
		goto exit;
	    }
	    else
	    {
		/* Nothing to destroy, QP not in QSF */
		goto exit;
	    }
	}

	/* Now destroy the ALIAS and the QP objects in QSF */
	stat = qsf_call(QSO_DESTROY, &qsf_rb);

	if (DB_FAILURE_MACRO(stat))
	{
	    (VOID) psf_error(E_PS0A09_CANTDESTROY, qsf_rb.qsf_error.err_code,
		    PSF_INTERR, &err_code, &psy_cb->psy_error, 0);
	    if (stat > status)
		status = stat;
	}
    }

    /* Invalidate procedure object from RDF cache */
    pst_rdfcb_init(&rdf_cb, sess_cb);
    (VOID) MEcopy((PTR)&psy_cb->psy_tabname[0], sizeof(DB_DBP_NAME),
	(PTR)&rdf_rb->rdr_name.rdr_prcname);
    STRUCT_ASSIGN_MACRO(sess_cb->pss_user, rdf_rb->rdr_owner);
    rdf_rb->rdr_types_mask = RDR_PROCEDURE;
    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:
    return (status);
}
Пример #11
0
/*{
** Name: ops_deallocate	- deallocate resources for an optimization
**
** Description:
**      This routine will deallocate the resources used for an optimization.
**      Resources include any memory requested from the optimizer memory pool
**      and any RDF cache objects which were locked in the global range
**      table
**
** Inputs:
**      global                          ptr to global state variable
**      report                          TRUE if errors should be reported
**                                      via the user's control block.
**      partial_dbp                     partial deallocation required for
**                                      statement within a procedure
**
** Outputs:
**	Returns:
**	    VOID
**	Exceptions:
**	    none
**
** Side Effects:
**	    memory resources released, RDF unfixed, 
**          QSF query tree memory released
**
** History:
**	29-jun-86 (seputis)
**          initial creation
**	8-nov-88 (seputis)
**          if no query run trace point is set then destroy the QP since
**	    SCF assumes optimizer cleans up after error
**	8-nov-88 (seputis)
**          turn off CPU accounting if was off originally
**	28-jan-91 (seputis)
**	    added support for OPF ACTIVE flag
**      20-jul-93 (ed)
**	    changed name ops_lock for solaris, due to OS conflict
**	29-jul-93 (andre)
**	    rdr_types_mask must be initialized (to RDR_RELATION) before
**	    calling RDF_UNFIX.  Otherwise RDF may end up complaining because we
**	    ask it to destroy a relation cache entry while RDR_PROCEDURE bit is
**	    set.
**	12-aug-93 (swm)
**	    Cast first parameter of CSaltr_session() to CS_SID to match
**	    revised CL interface specification.
**	02-Jun-1997 (shero03)
**	    Update the saved rdf_info_block after calling RDF.
**      02-Aug-2001 (hanal04) Bug 105360 INGSRV 1505
**          Plug the RDF memory leak introduced by inkdo01's new
**          function oph_temphist().
**	17-Dec-2003 (jenjo02)
**	    Added (CS_SID)NULL to CScnd_signal prototype.
**	6-Feb-2006 (kschendel)
**	    Fix some squirrely looking code that purported to avoid dangling
**	    references, but didn't really.  (No symptoms known.)
**	14-nov-2007 (dougi)
**	    Add support for cached dynamic query plans.
**	20-may-2008 (dougi)
**	    Add support for table procedures.
**	29-may-2009 (wanfr01)    Bug 122125
**	    Need to add dbid to cache_dynamic queries for db uniqueness
*/
VOID
ops_deallocate(
	OPS_STATE          *global,
	bool               report,
	bool               partial_dbp)
{
    DB_STATUS           finalstatus;	/* this status is returned to the user
                                        ** - it will contain the first error
                                        ** during resource deallocation
                                        */
    DB_ERROR            error;          /* error code from offending facility
                                        */

    finalstatus = E_DB_OK;
    error.err_code = 0;

    {    /* close any fixed RDF objects - deallocate prior to closing the
         ** global memory stream 
         */

	OPV_IGVARS             gvar;	    /* index into global range variable
                                            ** table */
	OPV_GRT                *gbase;	    /* ptr to base of array of ptrs
                                            ** to global range table elements
                                            */
	OPV_IGVARS	       maxgvar;	    /* number of global range table
                                            ** elements allocated
                                            */
	RDF_CB                 *rdfcb;	    /* ptr to rdf control block used
                                            ** unfix the relation info */
	OPV_GBMVARS            *rdfmap;     /* ptr to map of global range
                                            ** variables which have RDF info
                                            ** fixed */

	gbase = global->ops_rangetab.opv_base;
        maxgvar = global->ops_rangetab.opv_gv;
	rdfcb = &global->ops_rangetab.opv_rdfcb;
        rdfmap = &global->ops_rangetab.opv_mrdf;

	/*
	** rdr_types_mask needs to be initialized - since we will be unfixing
	** relation entries, RDR_RELATION seems like a good choice, although 0
	** would suffice as well
	*/
	rdfcb->rdf_rb.rdr_types_mask = RDR_RELATION;
	
	if (global->ops_cstate.opc_relation)
	{   /* OPC allocates a RDF descriptor for cursors so deallocate
            ** if this is the case */
	    DB_STATUS	   opcrdfstatus; /* RDF return status */

	    rdfcb->rdf_info_blk = global->ops_cstate.opc_relation;
	    opcrdfstatus = rdf_call( RDF_UNFIX, (PTR)rdfcb );
	    if ( (DB_FAILURE_MACRO(opcrdfstatus)) && (DB_SUCCESS_MACRO(finalstatus)) )
	    {
		finalstatus = opcrdfstatus;
		error.err_code = rdfcb->rdf_error.err_code;
	    }
	    global->ops_cstate.opc_relation = NULL;
	}
	if (maxgvar)
	{
	    for ( gvar = -1; 
		 (gvar = BTnext((i4)gvar, (char *)rdfmap, (i4)maxgvar)) >=0;)
	    {
		OPV_GRV             *gvarp;	    /* ptr to global range variable to
						** be deallocated */

		if	((gvarp = gbase->opv_grv[gvar]) /* NULL if not allocated */
		     &&
		     (gvarp->opv_relation)	    /* not NULL if RDF has been
						** called for this range variable */
		     &&
		     !(gvarp->opv_gmask & OPV_TPROC)	/* not table procedure */
		    )
		{
		    /* if this element has been allocated and if it has an RDF
		    ** cache element associated with it */
		    DB_STATUS	   rdfstatus; /* RDF return status */

		    gbase->opv_grv[gvar] = NULL; /* so we do not try to deallocate
						** twice in case of an error */
		    rdfcb->rdf_info_blk = gvarp->opv_relation;
		    rdfstatus = rdf_call( RDF_UNFIX, (PTR)rdfcb );
		    if ( (DB_FAILURE_MACRO(rdfstatus)) && (DB_SUCCESS_MACRO(finalstatus)) )
		    {
			finalstatus = rdfstatus;
			error.err_code = rdfcb->rdf_error.err_code;
		    }
		    gvarp->opv_relation = NULL;
		}

		if ((gvarp) && (gvarp->opv_ttmodel))
		{
		    /* if this element has been allocated and if it has an RDF
		    ** cache element associated with a persistent table
                    ** which provides histogram models.
		    */
		    DB_STATUS      rdfstatus; /* RDF return status */

		    rdfcb->rdf_info_blk = gvarp->opv_ttmodel;
		    gvarp->opv_ttmodel = NULL;
		    rdfstatus = rdf_call( RDF_UNFIX, (PTR)rdfcb );
		    if ( (DB_FAILURE_MACRO(rdfstatus)) && (DB_SUCCESS_MACRO(finalstatus)) )
		    {
		        finalstatus = rdfstatus;
	                error.err_code = rdfcb->rdf_error.err_code;
		    }
		    
		}

	    }
	    global->ops_rangetab.opv_gv = 0;
	}
    }
    if (partial_dbp)
	return;					/* only deallocate the global range table
						** for DBP, and keep the memory streams
						** until the end */
    if (global->ops_estate.opn_statistics
	&&
	global->ops_estate.opn_reset_statistics)
    {	/* statistics CPU accounting was turned on, and needs to be reset */
	STATUS		cs_status;
	i4		turn_off;

	turn_off = FALSE;			/* turn off accounting */
	global->ops_estate.opn_statistics = FALSE;
	cs_status = CSaltr_session((CS_SID)0, CS_AS_CPUSTATS, (PTR)&turn_off);
	if (cs_status != OK)
	{
	    finalstatus = E_DB_ERROR;
	    error.err_code = cs_status;
	}
    }

    /* deallocate ULM memory stream */
    if (global->ops_mstate.ops_streamid == NULL)	/* non-zero if allocated */
    {
	/* check if ULM stream does not exist then this deallocation has
        ** already occurred so just return */
        return;
    }
    else
    {
	DB_STATUS            ulm1status;/* ULM return status */
	global->ops_mstate.ops_ulmrcb.ulm_streamid_p = 
	    &global->ops_mstate.ops_streamid; /* ulm will NULL ops_streamid */
	ulm1status = ulm_closestream( &global->ops_mstate.ops_ulmrcb );
	if ( (DB_FAILURE_MACRO(ulm1status)) && (DB_SUCCESS_MACRO(finalstatus)) )
	{
	    finalstatus = ulm1status;
	    error.err_code = global->ops_mstate.ops_ulmrcb.ulm_error.err_code;
	}
    }

    /* deallocate ULM temp buffer memory stream */
    if ( global->ops_mstate.ops_tstreamid )	/* non-zero if allocated */
    {
	DB_STATUS            ulm2status; /* ULM return status */
	global->ops_mstate.ops_ulmrcb.ulm_streamid_p
	    = &global->ops_mstate.ops_tstreamid; /* ulm will NULL ops_tstreamid */
	ulm2status = ulm_closestream( &global->ops_mstate.ops_ulmrcb );
	if ( (DB_FAILURE_MACRO(ulm2status)) && (DB_SUCCESS_MACRO(finalstatus)) )
	{
	    finalstatus = ulm2status;
	    error.err_code = global->ops_mstate.ops_ulmrcb.ulm_error.err_code;
	}
    }

    /* deallocate OPC ULM buffer memory stream */
    if ( global->ops_mstate.ops_sstreamid )	/* non-zero if allocated */
    {
	DB_STATUS            ulm3status; /* ULM return status */
	global->ops_mstate.ops_ulmrcb.ulm_streamid_p = &global->ops_mstate.ops_sstreamid;
	/* ulm will NULL ops_sstreamid */
	ulm3status = ulm_closestream( &global->ops_mstate.ops_ulmrcb );
	if ( (DB_FAILURE_MACRO(ulm3status)) && (DB_SUCCESS_MACRO(finalstatus)) )
	{
	    finalstatus = ulm3status;
	    error.err_code = global->ops_mstate.ops_ulmrcb.ulm_error.err_code;
	}
    }

    if (!report
#ifdef    OPT_F032_NOEXECUTE
	||
	/* if trace flag is set then cleanup QSF memory since optimizer will
	** generate an error to SCF and SCF assumes optimizer will cleanup
        */
	    (global->ops_cb->ops_check 
	    && 
	    (opt_strace( global->ops_cb, OPT_F032_NOEXECUTE)
	    || 
	    opt_strace( global->ops_cb, OPT_F023_NOCOMP)  )
	    )
#endif
       )
    {	/* an error or an asychronous abort has occurred so destroy the plan
        ** or shared plan , FIXME destroy the shared plan in the earlier
        ** exception handler */
	DB_STATUS	       qsfqpstatus;   /* QSF return status */
	if(global->ops_qpinit)
	{   /* deallocate QSF object for query plan if another error has occurred 
            ** - in this case OPC has already created a new QP handle and has
            ** gotten a lock on it */

	    STRUCT_ASSIGN_MACRO(global->ops_caller_cb->opf_qep, global->ops_qsfcb.qsf_obj_id); /* get
						** query plan id */
	    global->ops_qsfcb.qsf_lk_id = global->ops_qplk_id; /* get lock id for 
						** QSF */
	    qsfqpstatus = ops_qsfdestroy(global); /* destroy the query plan */
	    if ( (DB_FAILURE_MACRO(qsfqpstatus)) && (DB_SUCCESS_MACRO(finalstatus)) )
	    {
		finalstatus = qsfqpstatus;
		error.err_code = global->ops_qsfcb.qsf_error.err_code;
	    }
	}
	else 
	{   /* OPC has not been reached so need to check for shared query plan
            */
	    if (!global->ops_procedure)
	    {	/* get query tree if it has not already been retrieved */
		qsfqpstatus = ops_gqtree(global);
		if ( (DB_FAILURE_MACRO(qsfqpstatus)) && (DB_SUCCESS_MACRO(finalstatus)) )
		{
		    finalstatus = qsfqpstatus;
		    error.err_code = global->ops_qsfcb.qsf_error.err_code;
		}
	    }
	    if (global->ops_qheader && 
			(global->ops_qheader->pst_mask1 & PST_RPTQRY))
	    {	/* shared query plan possible */
		if (global->ops_procedure->pst_flags & PST_REPEAT_DYNAMIC)
		{
		    char	*p;

		    global->ops_qsfcb.qsf_obj_id.qso_lname = 
						sizeof(DB_CURSOR_ID) + sizeof(i4);
		    MEfill(sizeof(global->ops_qsfcb.qsf_obj_id.qso_name), 0,
			global->ops_qsfcb.qsf_obj_id.qso_name);
		    MEcopy((PTR)&global->ops_procedure->
						pst_dbpid.db_cursor_id[0],
			sizeof (global->ops_procedure->
						pst_dbpid.db_cursor_id[0]),
			(PTR)global->ops_qsfcb.qsf_obj_id.qso_name);
		    p = (char *) global->ops_qsfcb.qsf_obj_id.qso_name + 
								2*sizeof(i4);
		    MEcopy((PTR)"qp", sizeof("qp"), p);
		    p = (char *) global->ops_qsfcb.qsf_obj_id.qso_name + 
						sizeof(DB_CURSOR_ID);
		    I4ASSIGN_MACRO(global->ops_caller_cb->opf_udbid, *(i4 *) p);
		    
		}
		else	/* must be proc or regular repeat query */
		{
		    global->ops_qsfcb.qsf_obj_id.qso_lname = 
				sizeof (global->ops_procedure->pst_dbpid);
		    MEcopy((PTR)&global->ops_procedure->pst_dbpid, 
			    sizeof (global->ops_procedure->pst_dbpid),
			    (PTR)&global->ops_qsfcb.qsf_obj_id.qso_name[0]);
		}
		global->ops_qsfcb.qsf_obj_id.qso_type = QSO_QP_OBJ;
		global->ops_qsfcb.qsf_lk_state = QSO_SHLOCK;
		qsfqpstatus = qsf_call(QSO_GETHANDLE, &global->ops_qsfcb);
		if (DB_SUCCESS_MACRO(qsfqpstatus))
		{
		    qsfqpstatus = ops_qsfdestroy( global );
		    if ( (DB_FAILURE_MACRO(qsfqpstatus)) && (DB_SUCCESS_MACRO(finalstatus)) )
		    {
			finalstatus = qsfqpstatus;
			error.err_code = global->ops_qsfcb.qsf_error.err_code;
		    }
		}
		else if (global->ops_qsfcb.qsf_error.err_code != E_QS0019_UNKNOWN_OBJ)
		{   /* if object is not found then this is not a shared query */
		    finalstatus = qsfqpstatus;
		    error.err_code = global->ops_qsfcb.qsf_error.err_code;
		}
	    }
	}	
    }

    /* release QSF memory allocated to query tree, make sure that this
    ** is done after the QP has been processed since pst_rptqry is still
    ** needed for above block */
    {
	DB_STATUS	       qsfstatus;   /* QSF return status */

	STRUCT_ASSIGN_MACRO(global->ops_caller_cb->opf_query_tree, global->ops_qsfcb.qsf_obj_id); /* get
					    ** query tree id */
        global->ops_qsfcb.qsf_lk_id = global->ops_lk_id; /* get lock id for 
                                            ** QSF */
	qsfstatus = ops_qsfdestroy( global );
	if ( (DB_FAILURE_MACRO(qsfstatus)) && (DB_SUCCESS_MACRO(finalstatus)) )
	{
	    finalstatus = qsfstatus;
	    error.err_code = global->ops_qsfcb.qsf_error.err_code;
	}
    }

    /* signal that the session is exiting OPF and that another thread may enter */
    if (global->ops_cb->ops_smask & OPS_MCONDITION)
    {
	DB_STATUS   lockstatus;
	OPG_CB	    *servercb;

	servercb = global->ops_cb->ops_server;
	global->ops_cb->ops_smask &= (~OPS_MCONDITION);
	lockstatus = ops_exlock(global->ops_caller_cb, &servercb->opg_semaphore); 
					    /* check if server
					    ** thread is available, obtain
					    ** semaphore lock on critical variable */
	servercb->opg_activeuser--;	    /* since exit is about to occur, and memory
					    ** has already been deallocated, allow another
					    ** user to enter OPF */
	servercb->opg_waitinguser--;	    /* since exit is about to occur, and memory
					    ** has already been deallocated, allow another
					    ** user to enter OPF */
	if (DB_FAILURE_MACRO(lockstatus) && (DB_SUCCESS_MACRO(finalstatus)))
	{
	    finalstatus = lockstatus;
	    error.err_code = global->ops_caller_cb->opf_errorblock.err_data;
	}
	else
	{
	    if (servercb->opg_waitinguser > servercb->opg_activeuser)
	    {
		STATUS	    csstatus;
		csstatus = CScnd_signal(&servercb->opg_condition, (CS_SID)NULL);
						/* signal only if some users are waiting */
		if ((csstatus != OK) && (DB_SUCCESS_MACRO(finalstatus)))
		{
		    finalstatus = E_DB_ERROR;
		    error.err_code = csstatus;
		}
	    }
	    lockstatus = ops_unlock(global->ops_caller_cb, 
		&servercb->opg_semaphore);	/* check if server
						** thread is available */
	    if (DB_FAILURE_MACRO(lockstatus) && (DB_SUCCESS_MACRO(finalstatus)))
	    {
		finalstatus = lockstatus;
		error.err_code = global->ops_caller_cb->opf_errorblock.err_data;
	    }
	}
    }

    if (DB_FAILURE_MACRO(finalstatus))
    {
	if (report)
	    opx_verror( finalstatus, E_OP0084_DEALLOCATION, error.err_code); /* report
					    ** error and generate an exception */
	else
	    opx_rverror(global->ops_cb->ops_callercb, finalstatus,
		E_OP0084_DEALLOCATION, error.err_code);
					    /* report error only but do not generate an
					    ** exception */
    }
}
Пример #12
0
/*{
** Name: opx_rverror	- this routine will report another facility's error
**
** Description:
**      This routine will log an error from another facility and the related
**      optimizer error.  
**
** Inputs:
**      opfcb                           ptr to another facility's control block
**      error                           optimizer error code to report
**      facility                        ptr to facility's control block
**
** Outputs:
**	Returns:
**	    VOID
**	Exceptions:
**	    - internal exception generated
**
** Side Effects:
**	    the exception handling routines are responsible for
**          deallocating OPF resources bound to this session.
**
** History:
**	3-jul-86 (seputis)
**          initial creation
**	21-may-89 (jrb)
**	    now passes generic_error to opx_sccerror routine
**	24-oct-92 (andre)
**	    interfaces of ule_format() and opx_sccerror() have been changed to
**	    receive (DB_SQLSTATE *)
**	24-Oct-2008 (jonj)
**	    Replace ule_doformat with ule_format.
[@history_line@]...
*/
VOID
opx_rverror(
	OPF_CB             *opfcb,
	DB_STATUS          status,
	OPX_ERROR          error,
	OPX_FACILITY       facility)
{
    DB_STATUS	    ule_status;		/* return status from ule_format */
    i4         ule_error;          /* ule cannot format message */
    char	    msg_buffer[DB_ERR_SIZE]; /* error message buffer */
    i4         msg_buf_length;     /* length of message returned */
    i4         log;                /* logging state */
    DB_SQLSTATE	    sqlstate;

    opfcb->opf_errorblock.err_code = error;	/* save error code */
    opfcb->opf_errorblock.err_data = facility;	/* save code 
                                                ** from facility */
    if ((error % 256) < 128)
	log = ULE_LOOKUP;		/* lookup only user errors with range
					** of 0-127 */
    else
	log = ULE_LOG;			/* log errors with range 128-255 */

#ifdef    OPT_F031_WARNINGS
    /* if trace flag is set then warning or info errors will be reported */
    if ( DB_SUCCESS_MACRO(status))
    {
	OPS_CB	    *ops_cb;
	ops_cb = ops_getcb();
	if (ops_cb
	    &&
	    (   !ops_cb->ops_check 
		||
		!opt_strace( ops_cb, OPT_F031_WARNINGS)
	    ))
		return;
    }
#endif
    ule_status = ule_format( error, (CL_SYS_ERR *)NULL, log, &sqlstate,
	msg_buffer, (i4) (sizeof(msg_buffer)-1), &msg_buf_length,
	&ule_error, 0);
    if (ule_status != E_DB_OK)
    {
        (VOID)STprintf(msg_buffer, 
"ULE error = %x\nOptimizer cannot be found - error no = %x Status = %x Facility error = %x \n", 
	    ule_error, error , status, facility);
    }
    else
	msg_buffer[msg_buf_length] = 0;	/* null terminate */
    /* FIXME - should check possible return status and generate a severe error
    ** unless it is simple (like cannot find message) */
    {   /* report any errors in the range 0 to 127 to the user */
        DB_STATUS		scf_status;
	if (facility)
	    scf_status = opx_sccerror(E_DB_WARN, &sqlstate, error,
		msg_buffer,(i4)msg_buf_length);	/* generate
					    ** a warning, so that SCC_TRACE is
                                            ** used, this will ensure that
                                            ** SCC_ERROR will be called with
		                            ** the "facility" error code which
                                            ** will be the ingres user code
                                            ** which will be returned to the
                                            ** equel program */
	else
	    scf_status = opx_sccerror(status, &sqlstate, error, msg_buffer,
		(i4)msg_buf_length);
	if (scf_status != E_DB_OK)
	{
	    TRdisplay( 
		"Optimizer error = %x Status = %x Facility error = %x \n", 
                error , status, facility);
	}
    }
    if (!facility)
	return;				    /* if facility error exists then
					    ** report it in the same way */
    ule_status = ule_format( facility,  (CL_SYS_ERR *)NULL, log, &sqlstate,
	msg_buffer, (i4) (sizeof(msg_buffer)-1), &msg_buf_length,
	&ule_error, 0);
    if (ule_status != E_DB_OK)
    {
        (VOID)STprintf(msg_buffer, 
"ULE error = %x\nOptimizer error = %x Status = %x Facility error cannot be found - error no = %x \n", 
	    ule_error, error , status, facility);
    }
    else
	msg_buffer[msg_buf_length] = 0;	/* null terminate */
    {   
        DB_STATUS		scf1_status;
	scf1_status = opx_sccerror(status, &sqlstate, facility, msg_buffer,
	    (i4)msg_buf_length);
	if (scf1_status != E_DB_OK)
	{
	    TRdisplay( 
		"Optimizer error = %x Status = %x Facility error = %x \n", 
                error , status, facility);
	}
    }
}
Пример #13
0
/*{
** Name: opx_adfexception	- handle ADF exceptions if possible
**
** Description:
**      Routine will be called by exception handlers in the optimizer to
**	handle arithmetic exceptions if possible
**
** Inputs:
**      ops_cb                          OPF session control block
**      ex_args                         exception handler arguments
**
** Outputs:
**	Returns:
**	    exception status - EXCONTINUES, or EXRESIGNAL
**		where EXRESIGNAL means that the exception is unknown
**	Exceptions:
**	    OPF exception is generated for a fatal ADF exception
**
** Side Effects:
**	    none
**
** History:
**      20-jan-86 (seputis)
**          initial creation
**	31-mar-92 (rog)
**	    Remove underscores from EX return statuses.
**	24-oct-92 (andre)
**	    interface of opx_sccerror() has been changed to receive
**	    (DB_SQLSTATE *)
[@history_template@]...
*/
static STATUS
opx_adfexception(
	OPS_CB		   *ops_cb,
	EX_ARGS            *ex_args)
{
    DB_STATUS           status;
    ADF_CB              *adf_scb;

    adf_scb = ops_cb->ops_adfcb;
    status = adx_handler(adf_scb, ex_args);
    if ((status == E_DB_WARN) 
	&& 
	(adf_scb->adf_errcb.ad_errcode == E_AD0116_EX_UNKNOWN)
	)
    {	/* adf does not know about this error so resignal it */
	return (EXRESIGNAL);
    }
    if (DB_SUCCESS_MACRO(status))
    {	/* adf will return OK status if it knowns about the error and the
        ** correct action is to continue */
#ifdef    OPT_F031_WARNINGS
	/* if trace flag is set then warning or info errors will be reported */
	if ( DB_SUCCESS_MACRO(status)
	    &&
	    ops_cb->ops_check 
	    &&
	    opt_strace( ops_cb, OPT_F031_WARNINGS)
	   )
	    opx_rverror( ops_cb->ops_callercb, 
		E_DB_WARN, E_OP0701_ADF_EXCEPTION, (OPX_FACILITY)0); /* report 
						** warning is 
						** trace flag is set */
#endif
	return(EXCONTINUES);			/* return if error is not
                                                ** serious */
    }

    {
	OPX_ERROR	adf_error;
	OPX_ERROR	opf_error;
	ops_cb->ops_retstatus = status;
	if (adf_scb->adf_errcb.ad_errclass == ADF_USER_ERROR)
	{	/* report the error message to the user */
	    adf_error = adf_scb->adf_errcb.ad_usererr;
	    opf_error = E_OP0702_ADF_EXCEPTION;
	}
	else
	{	/* report non-user error code */
	    adf_error = adf_scb->adf_errcb.ad_errcode;
	    opf_error = E_OP0795_ADF_EXCEPTION;
	}
	opx_rverror(ops_cb->ops_callercb, E_DB_WARN, opf_error,(OPX_FACILITY)0);
					/* do not report facility error
					** since opx_sccerror will report it
					** in the next statement
                                        ** - need to use the formatted message
                                        ** the ADF provides since it may contain
                                        ** parameters */
	(VOID) opx_sccerror(status, &adf_scb->adf_errcb.ad_sqlstate,
	    adf_error, adf_scb->adf_errcb.ad_errmsgp,
	    adf_scb->adf_errcb.ad_emsglen);
    }
    return (EXDECLARE);		    /* return to declaration point of
					    ** exception handler */
}
Пример #14
0
DB_STATUS
adu_dbmsinfo(
ADF_CB             *adf_scb,
DB_DATA_VALUE      *dv1,
DB_DATA_VALUE      *rdv)
{
    i4			i = Adf_globs->Adi_num_dbis;
    i4			found = FALSE;
    ADF_DBMSINFO	*dbi = Adf_globs->Adi_dbi;
    i4			dbi_size = sizeof(dbi->dbi_reqname);
    i4			in_size  = ((DB_TEXT_STRING *)dv1->db_data)->db_t_count;
    char		*in_str  = (char *)
				    ((DB_TEXT_STRING *)dv1->db_data)->db_t_text;
    register i4	j;
    register char	*c1;
    register char	*c2;
    char		ch_tmp;
    ALIGN_RESTRICT	*tbuf;
    DB_STATUS		db_stat = E_DB_OK;
    i4			cmp;
    DB_DATA_VALUE	tmp_dv;
    DB_ERROR		err;
    ADK_MAP		*kmap;
    char		localbuf[2004];
    bool		uselocal = TRUE;


    if (in_size <= dbi_size)    /* No possible match if input is bigger */
    {
	/* Find the request in the dbmsinfo() request table */
	while (i--)
	{
	    cmp = TRUE;
	    c1  = dbi->dbi_reqname;
	    c2  = in_str;
	    j   = 0;
	    while (j < in_size  &&  *c1 != 0)
	    {
		CMtolower(c2, &ch_tmp);
		if (*c1 != ch_tmp)
		{
		    cmp = FALSE;
		    break;
		}
		c1++;
		c2++;
		j++;
	    }

	    if (    cmp
		&& (in_size == dbi_size  ||  (*c1 == 0  &&  j == in_size))
	       )
	    {
		found = TRUE;
		break;
	    }

	    dbi++;
	}
    }


    if (!found)
    {
	((DB_TEXT_STRING *)rdv->db_data)->db_t_count = 0;
	db_stat = E_DB_OK;
    }
    else
    {
	/* {@fix_me@} ... eventually, we have to handle 1 input, and
	**		    lenspecs that are not FIXED LENGTH
	*/
	if (dbi->dbi_num_inputs || dbi->dbi_lenspec.adi_lncompute != ADI_FIXED)
	    return(adu_error(adf_scb, E_AD9999_INTERNAL_ERROR, 0));

	tmp_dv.db_datatype = dbi->dbi_dtr;
	tmp_dv.db_length   = dbi->dbi_lenspec.adi_fixedsize;

	if (tmp_dv.db_length >= 2004)
	{
	    uselocal = FALSE;
	    tbuf = (ALIGN_RESTRICT *)MEreqmem(0,
					  ((DB_GW4_MAXSTRING + DB_CNTSIZE - 1) /
					  sizeof(ALIGN_RESTRICT)) + 1,
					  FALSE, NULL);
	    tmp_dv.db_data     = (PTR)tbuf;
	}
	else tmp_dv.db_data     = (PTR)&localbuf[0];

	/*
	** Is request one of the query constants?  If so, use adu_dbconst()
	** instead of the dbi function found in the dbi table.
	*/
	if      (dbi == Adf_globs->Adk_bintim_map.adk_dbi)
	    kmap = &Adf_globs->Adk_bintim_map;
	else if (dbi == Adf_globs->Adk_cpu_ms_map.adk_dbi)
	    kmap = &Adf_globs->Adk_cpu_ms_map;
	else if (dbi == Adf_globs->Adk_et_sec_map.adk_dbi)
	    kmap = &Adf_globs->Adk_et_sec_map;
	else if (dbi == Adf_globs->Adk_dio_cnt_map.adk_dbi)
	    kmap = &Adf_globs->Adk_dio_cnt_map;
	else if (dbi == Adf_globs->Adk_bio_cnt_map.adk_dbi)
	    kmap = &Adf_globs->Adk_bio_cnt_map;
	else if (dbi == Adf_globs->Adk_pfault_cnt_map.adk_dbi)
	    kmap = &Adf_globs->Adk_pfault_cnt_map;
	else if (dbi == Adf_globs->Adk_curr_date_map.adk_dbi)
	    kmap = &Adf_globs->Adk_curr_date_map;
	else if (dbi == Adf_globs->Adk_curr_time_map.adk_dbi)
	    kmap = &Adf_globs->Adk_curr_time_map;
	else if (dbi == Adf_globs->Adk_curr_tstmp_map.adk_dbi)
	    kmap = &Adf_globs->Adk_curr_tstmp_map;
	else if (dbi == Adf_globs->Adk_local_time_map.adk_dbi)
	    kmap = &Adf_globs->Adk_local_time_map;
	else if (dbi == Adf_globs->Adk_local_tstmp_map.adk_dbi)
	    kmap = &Adf_globs->Adk_local_tstmp_map;
	else
	    kmap = NULL;

	if (kmap == NULL)
	    db_stat = (*dbi->dbi_func)(dbi, NULL, &tmp_dv, &err);
	else
	    db_stat = adu_dbconst(adf_scb, kmap, &tmp_dv);
	
	if (DB_SUCCESS_MACRO(db_stat))
	{
	    db_stat = adu_ascii(adf_scb, &tmp_dv, rdv);
	}

	if (!uselocal)
	    MEfree((PTR)tbuf);
    }

    return (db_stat);
}