Ejemplo n.º 1
0
DB_STATUS
qet_t4_savept(
QEF_CB         *qef_cb)
{
    i4	err;
    DB_STATUS   status;
    TPR_CB	tpr_cb,
		*tpr_p = & tpr_cb;


    if (qef_cb->qef_rcb->qef_spoint == 0)
    {
        qef_error(E_QE0018_BAD_PARAM_IN_CB, 0L, E_DB_WARN, &err,
		  &qef_cb->qef_rcb->error, 0);
        return (E_DB_WARN);
    }

    /* Must be in a transaction */

    if (qef_cb->qef_stat == QEF_NOTRAN)
    {
	if (qef_cb->qef_rcb->qef_flag == DB_QUEL)
	{
	    qef_error(E_QE0004_NO_TRANSACTION, 0L, E_DB_WARN, &err,
		      &qef_cb->qef_rcb->error, 0);
	    return (E_DB_WARN);
	}
	else if (qef_cb->qef_auto == QEF_ON)
	{
	    /* savepoint not allowed when autocommit is on */
	    qef_error(2178L, 0L, E_DB_WARN, &err, &qef_cb->qef_rcb->error, 0);
	    return (E_DB_WARN);
	}
    }

    /* Cannot set a savepoint if there are open cursors */

    if (qef_cb->qef_open_count > 0)
    {
        qef_error(E_QE0020_OPEN_CURSOR, 0L, E_DB_WARN, &err,
		  &qef_cb->qef_rcb->error, 0);
        return (E_DB_WARN);
    }

    MEfill(sizeof(tpr_cb), '\0', (PTR) & tpr_cb);
    tpr_p->tpr_session = qef_cb->qef_c2_ddb_ses.qes_d2_tps_p;
    tpr_p->tpr_rqf = qef_cb->qef_c2_ddb_ses.qes_d3_rqs_p;
    tpr_p->tpr_save_name = qef_cb->qef_rcb->qef_spoint;

    if (qef_cb->qef_rcb->qef_flag == DB_QUEL)
	tpr_p->tpr_lang_type = DB_QUEL;
    else if (qef_cb->qef_rcb->qef_flag == DB_SQL)
	tpr_p->tpr_lang_type = DB_SQL;
    else
	tpr_p->tpr_lang_type = DB_NOLANG;

    status = qed_u17_tpf_call(TPF_SAVEPOINT, tpr_p, qef_cb->qef_rcb);

    return(status);
}
Ejemplo n.º 2
0
/*{
** Name: QEU_CLOSE      - close an opened table
**
** External QEF call:       status = qef_call(QEU_CLOSE, &qeu_cb);
**
** Description:
**      Close a table opened through the QEU_OPEN command. 
**
** Inputs:
**      qeu_cb
**	    .qeu_eflag			    designate error handling semantis
**					    for user errors.
**		QEF_INTERNAL		    return error code.
**		QEF_EXTERNAL		    send message to user.
**          .qeu_acc_id			    table access id
**
** Outputs:
**      qeu_cb
**          .error.err_code                 One of the following
**                                          E_QE0000_OK
**                                          E_QE0002_INTERNAL_ERROR
**                                          E_QE0004_NO_TRANSACTION
**                                          E_QE0007_NO_CURSOR
**                                          E_QE0017_BAD_CB
**                                          E_QE0018_BAD_PARAM_IN_CB
**      Returns:
**          E_DB_OK
**          E_DB_ERROR                      caller error
**          E_DB_FATAL                      internal error
**      Exceptions:
**          none
**
** Side Effects:
**          none
**
** History:
**      27-may-86 (daved)
**          written
**	14-may-87 (daved)
**	    zero the access id to cause an error in DMF if a table is
**	    closed twice.
*/
DB_STATUS
qeu_close(
QEF_CB      *qef_cb,
QEU_CB      *qeu_cb)
{
    i4     err;
    DMT_CB      dmt_cb;
    DB_STATUS   status;

    /* QEU_CLOSE is only valid in a transaction */
    if (qef_cb->qef_stat == QEF_NOTRAN)
    {
        qef_error(E_QE0004_NO_TRANSACTION, 0L, E_DB_ERROR, &err,
            &qeu_cb->error, 0);
        return (E_DB_ERROR);
    }
    MEfill(sizeof(DMT_CB), 0, (PTR) &dmt_cb);
    dmt_cb.type         = DMT_TABLE_CB;
    dmt_cb.length       = sizeof(DMT_CB);
    dmt_cb.dmt_flags_mask   = 0;
    dmt_cb.dmt_record_access_id = qeu_cb->qeu_acc_id;
    status = dmf_call(DMT_CLOSE, &dmt_cb);
    if (status != E_DB_OK)
    {
        qef_error(dmt_cb.error.err_code, 0L, status, &err, &qeu_cb->error, 0);
    }
    else
	qef_cb->qef_open_count--;
    qeu_cb->qeu_acc_id = (PTR) NULL;
    return (status);
}
Ejemplo n.º 3
0
DB_STATUS
qeu_d3_cre_view(
QEF_CB          *qef_cb,
QEUQ_CB		*i_quq_p)
{
    DB_STATUS	status;
    i4	ignore;
    DB_ERROR	err_stub;
    
    
    status = qeu_d6_cre_view(qef_cb, i_quq_p);
    if (status)
	qef_error(i_quq_p->error.err_code, 0L, status, & ignore,
		  & err_stub, 0);

    return(status);
}    
Ejemplo n.º 4
0
/*{
** Name: qeu_cevent 	- Store event information for one event.
**
** External QEF call:   status = qef_call(QEU_CEVENT, &qeuq_cb);
**
** Description:
**	Add the event tuple and the event query text to the appropriate
**	tables (iievent and iiqrytext).
**
**	Most of the event tuple was filled by the parser from the CREATE EVENT
**	statement, except that since this is the first access to iievent,
**	the uniqueness of the event name (within the current user scope) is
**	validated here.  First, all events that have the same name and
**	owner are fetched (the iievent table is hashed on name and owner
**	so this is a singleton keyed retrieval).  If there are any then
**	the event is a duplicate and an error is returned.  If this is
**	unique then the event is entered into iievent.
**
**	To allow permissions to apply to events, an event tuple includes
**	a "dummy table id" (much like database procedures).  This id is
**	retrieved from DMU_GET_TABID.
**
**	An internal qrytext id (time-stamp) is created and all the qrytext
**	tuples associated with the event are entered into iiqrytext.
**	Note that the size of CREATE EVENT query text is never likely to
**	be more than one iiqrytext tuple, but the code allows more than
**	one tuple in case a WITH clause is added in the future (extending
**	the length of the statement).
**
**	The current "create date" is retrieved from ADF (using date("now")).
**
** Inputs:
**      qef_cb                  QEF session control block
**      qeuq_cb
**	    .qeuq_eflag	        Designate error handling for user errors.
**		QEF_INTERNAL	Return error code.
**		QEF_EXTERNAL	Send message to user.
**	    .qeuq_cq		Number of query text tuples.
**	    .qeuq_qry_tup	Query text tuples.
**	    .qeuq_culd		Number of event tuples.  Must be 1.
**	    .qeuq_uld_tup	Event tuple:
**		.dbe_name	Event name.
**		.dbe_owner	Event owner.
**		.dbe_type	Event type.
**				The remaining fields are filled here.
**	    .qeuq_db_id		Database id.
**	    .qeuq_d_id		DMF session id.
**
** Outputs:
**      qeuq_cb
**	    .error.err_code	E_QE0002_INTERNAL_ERROR
**				E_QE0017_BAD_CB
**				E_QE0018_BAD_PARAM_IN_CB
**				E_QE0022_ABORTED
**				E_QE020A_EVENT_EXISTS (ret E_QE0025_USER_ERROR)
**	Returns:
**	    E_DB_{OK, WARN, ERROR, FATAL}
**	Exceptions:
**	    none
**
** History:
**	28-aug-89 (neil)
**	    Written for Terminator II/alerters.
**	09-feb-90 (neil)
**	   Added auditing functionality.
**	03-mar-90 (neil)
**	   Clear adf_constants before calling ADF.  The problem was that the
**	   session CB may have been pointing at "old" data which had been
**	   reused for other things.
**	19-may-93 (anitap)
**	    Added support to create implicit schema for dbevent.
**	07-jul-93 (anitap)
**	    Added two arguments qef_rcb & qeuq_cb to qea_schema() instead of
**	    PTR.
**	    Changed assignment of flag to IMPLICIT_SCHEMA.
**	21-sep-93 (stephenb)
**	    Replace generic I_SX2032_EVENT_ACCESS with I_SX2032_EVENT_CREATE. 
**	27-oct-93 (andre)
**	    As a part of fix for bug 51852 (which was reported in 6.4 but can
**	    and will manifest itself in 6.5 as soon as someone places some 
**	    stress on the DBMS), we want to use the dbevent id (really 
**	    guaranteed to be unique) instead of timestamps (allegedly unique, 
**	    but in fact may be non-unique if several objects get created in 
**	    rapid succession on a reasonably fast box) to identify IIQRYTEXT 
**	    tuples associated with a given dbevent.  This id (pumped through 
**	    randomizing function) will be used to key into IIQRYTEXT 
*/
DB_STATUS
qeu_cevent(
QEF_CB          *qef_cb,
QEUQ_CB		    *qeuq_cb)
{
    DB_IIEVENT    	*evtuple;	/* New event tuple */
    DB_IIEVENT    	evtuple_temp;	/* Tuple and 			   */
    DMR_ATTR_ENTRY  	evkey_array[2];	/*       keys for uniqueness check */
    DMR_ATTR_ENTRY  	*evkey_ptr_array[2];
    DMU_CB		dmu_cb;		/* For unique table-id request */
    DB_DATA_VALUE	evcreate_dv;	/* For create date */
    DB_IIQRYTEXT	*qtuple;	/* Event text */
    DB_TAB_ID		randomized_id;
    i4		    	i;		/* Querytext counter  */
    QEF_DATA	    	*next;		/*   and data pointer */
    DB_STATUS	    	status, local_status;
    DB_ERROR		e_error;
    i4	    	error;
    bool	    	tbl_opened = FALSE;
    QEU_CB	    	tranqeu;	/* May need a transaction */
    bool	    	transtarted = FALSE;
    QEU_CB	    	qeu;
    QEF_DATA	    	qef_data;
    i4			flag = IMPLICIT_SCHEMA;
    QEF_RCB	        *qef_rcb = (QEF_RCB *)NULL;

    for (;;)	/* Dummy for loop for error breaks */
    {
	/* Validate CB and parameters */
	if (qeuq_cb->qeuq_type != QEUQCB_CB ||
            qeuq_cb->qeuq_length != sizeof(QEUQ_CB))
	{
	    status = E_DB_ERROR;
	    error = E_QE0017_BAD_CB;
	    break;
	}
	if (   (qeuq_cb->qeuq_cq == 0   || qeuq_cb->qeuq_qry_tup == NULL)
            || (qeuq_cb->qeuq_culd != 1 || qeuq_cb->qeuq_uld_tup == NULL)
            || (qeuq_cb->qeuq_db_id == NULL)
            || (qeuq_cb->qeuq_d_id == 0))
	{
	    status = E_DB_ERROR;
	    error = E_QE0018_BAD_PARAM_IN_CB;
	    break;
	}

	/*
	** Check to see if transaction is in progress, if so set a local
	** transaction, otherwise we'll use the user's transaction.
	*/
	if (qef_cb->qef_stat == QEF_NOTRAN)
	{
	    tranqeu.qeu_type = QEUCB_CB;
	    tranqeu.qeu_length = sizeof(QEUCB_CB);
	    tranqeu.qeu_db_id = qeuq_cb->qeuq_db_id;
	    tranqeu.qeu_d_id = qeuq_cb->qeuq_d_id;
	    tranqeu.qeu_flag = 0;
	    status = qeu_btran(qef_cb, &tranqeu);
	    if (status != E_DB_OK)
	    {
		error = tranqeu.error.err_code;
		break;
	    }
	    transtarted = TRUE;
	}
	/* Escalate the transaction to MST */
	if (qef_cb->qef_auto == QEF_OFF)
	    qef_cb->qef_stat = QEF_MSTRAN;

	evtuple = (DB_IIEVENT *)qeuq_cb->qeuq_uld_tup->dt_data;

	/* Validate that the event name/owner is unique */
	qeu.qeu_type = QEUCB_CB;
        qeu.qeu_length = sizeof(QEUCB_CB);
        qeu.qeu_tab_id.db_tab_base  = DM_B_EVENT_TAB_ID;
        qeu.qeu_tab_id.db_tab_index  = DM_I_EVENT_TAB_ID;
        qeu.qeu_db_id = qeuq_cb->qeuq_db_id;
        qeu.qeu_lk_mode = DMT_IX;
        qeu.qeu_flag = DMT_U_DIRECT;
        qeu.qeu_access_mode = DMT_A_WRITE;
	qeu.qeu_mask = 0;
	status = qeu_open(qef_cb, &qeu);
	if (status != E_DB_OK)
	{
	    error = qeu.error.err_code;
	    break;
	}
	tbl_opened = TRUE;

	/* Retrieve the same named/owned event - if not there then ok */
	qeu.qeu_count = 1;
        qeu.qeu_tup_length = sizeof(DB_IIEVENT);
	qeu.qeu_output = &qef_data;
	qef_data.dt_next = NULL;
        qef_data.dt_size = sizeof(DB_IIEVENT);
        qef_data.dt_data = (PTR)&evtuple_temp;
	qeu.qeu_getnext = QEU_REPO;
	qeu.qeu_klen = 2;			/* Keyed on name and owner */
	qeu.qeu_key = evkey_ptr_array;
	evkey_ptr_array[0] = &evkey_array[0];
	evkey_ptr_array[0]->attr_number = DM_1_EVENT_KEY;
	evkey_ptr_array[0]->attr_operator = DMR_OP_EQ;
	evkey_ptr_array[0]->attr_value = (char *)&evtuple->dbe_name;
	evkey_ptr_array[1] = &evkey_array[1];
	evkey_ptr_array[1]->attr_number = DM_2_EVENT_KEY;
	evkey_ptr_array[1]->attr_operator = DMR_OP_EQ;
	evkey_ptr_array[1]->attr_value = (char *)&evtuple->dbe_owner;
	qeu.qeu_qual = NULL;
	qeu.qeu_qarg = NULL;
	status = qeu_get(qef_cb, &qeu);
	if (status == E_DB_OK)		/* Found the same event! */
	{
	    (VOID)qef_error(E_QE020A_EVENT_EXISTS, 0L, E_DB_ERROR,
			    &error, &qeuq_cb->error, 1,
			    qec_trimwhite(sizeof(evtuple->dbe_name),
					  (char *)&evtuple->dbe_name),
			    (PTR)&evtuple->dbe_name);
	    error = E_QE0025_USER_ERROR;
	    break;
	}
	if (qeu.error.err_code != E_QE0015_NO_MORE_ROWS)
	{
	    error = qeu.error.err_code;	 /* Some other error */
	    break;
	}
	/* The event is unique - append it */

	status = E_DB_OK;

	/*
	** Get unique event id (a table id) from DMF.  This id enables
	** permissions to be associated with the event.
	*/
	dmu_cb.type = DMU_UTILITY_CB;
	dmu_cb.length = sizeof(DMU_CB);
	dmu_cb.dmu_flags_mask = 0;
	dmu_cb.dmu_tran_id = qef_cb->qef_dmt_id;
	dmu_cb.dmu_db_id = qeuq_cb->qeuq_db_id;
	status = dmf_call(DMU_GET_TABID, &dmu_cb);
	if (status != E_DB_OK)
	{
	    error = dmu_cb.error.err_code;
	    break;
	}
	evtuple->dbe_uniqueid.db_tab_base  = dmu_cb.dmu_tbl_id.db_tab_base;
	evtuple->dbe_uniqueid.db_tab_index = dmu_cb.dmu_tbl_id.db_tab_index;

	/*
	** use dbevent id to generate randomized id which will be used to 
	** identify IIQRYTEXT tuples associated with this dbevent
	*/
	randomized_id.db_tab_base = 
	    ulb_rev_bits(evtuple->dbe_uniqueid.db_tab_base);
	randomized_id.db_tab_index = 
	    ulb_rev_bits(evtuple->dbe_uniqueid.db_tab_index);

	/* set text id to "randomized" id */
	evtuple->dbe_txtid.db_qry_high_time = randomized_id.db_tab_base;
	evtuple->dbe_txtid.db_qry_low_time  = randomized_id.db_tab_index;

	/* Get the create date of the event */
	evcreate_dv.db_datatype = DB_DTE_TYPE;
	evcreate_dv.db_prec = 0;
	evcreate_dv.db_length = sizeof(DB_DATE);
	evcreate_dv.db_data = (PTR)&evtuple->dbe_create;
	evcreate_dv.db_collID = -1;
	qef_cb->qef_adf_cb->adf_constants = NULL;
	status = adu_datenow(qef_cb->qef_adf_cb, &evcreate_dv);
	if (status != E_DB_OK)
	{
	    error = qeu.error.err_code;
	    break;
	}

	/* Insert single event tuple */
	qeu.qeu_count = 1;
        qeu.qeu_tup_length = sizeof(DB_IIEVENT);
	qeu.qeu_input = qeuq_cb->qeuq_uld_tup; /* Which points at evtuple */
	status = qeu_append(qef_cb, &qeu);
	if (status != E_DB_OK)
	{
	    error = qeu.error.err_code;
	    break;
	}
	status = qeu_close(qef_cb, &qeu);
	if (status != E_DB_OK)
	{
	    error = qeu.error.err_code;
	    break;
	}
	tbl_opened = FALSE;

	/*
	** Update all query text tuples with query id - validate list.  Even
	** though we will probably have just one text tuple this is set up
	** for syntactic extensions to the CREATE EVENT statement.
	*/
	next = qeuq_cb->qeuq_qry_tup;
	for (i = 0; i < qeuq_cb->qeuq_cq; i++)
	{
	    qtuple = (DB_IIQRYTEXT *)next->dt_data;
	    next = next->dt_next;
	    qtuple->dbq_txtid.db_qry_high_time = randomized_id.db_tab_base;
	    qtuple->dbq_txtid.db_qry_low_time  = randomized_id.db_tab_index;
	    if (i < (qeuq_cb->qeuq_cq -1) && next == NULL)
	    {
		error = E_QE0018_BAD_PARAM_IN_CB;
		status = E_DB_ERROR;
		break;
	    }
	} /* for all query text tuples */
	if (status != E_DB_OK)
	    break;

	/* Insert all query text tuples */
	qeu.qeu_tab_id.db_tab_base = DM_B_QRYTEXT_TAB_ID;
	qeu.qeu_tab_id.db_tab_index = 0L;
	qeu.qeu_mask = 0;
	status = qeu_open(qef_cb, &qeu);
	if (status != E_DB_OK)
	{
	    error = qeu.error.err_code;
	    break;
	}
	tbl_opened = TRUE;
	qeu.qeu_count = qeuq_cb->qeuq_cq;
        qeu.qeu_tup_length = sizeof(DB_IIQRYTEXT);
	qeu.qeu_input = qeuq_cb->qeuq_qry_tup;
	status = qeu_append(qef_cb, &qeu);
	if (status != E_DB_OK)
	{
	    error = qeu.error.err_code;
	    break;
	}
	status = qeu_close(qef_cb, &qeu);
	if (status != E_DB_OK)
	{
	    error = qeu.error.err_code;
	    break;
	}
	tbl_opened = FALSE;

        status = qea_schema(qef_rcb, qeuq_cb, qef_cb, 
		(DB_SCHEMA_NAME *)&evtuple->dbe_owner, flag);
        if (status != E_DB_OK)
        {
           error = qeuq_cb->error.err_code;
           break;
        }

	if (transtarted)		   /* If we started a transaction */
	{
	    status = qeu_etran(qef_cb, &tranqeu);
	    if (status != E_DB_OK)
	    {
		error = tranqeu.error.err_code;
		break;
	    }
	}


	/* Audit CREATE EVENT */
	if ( Qef_s_cb->qef_state & QEF_S_C2SECURE )
	{
	    status = qeu_secaudit(FALSE, qef_cb->qef_ses_id, 
		  evtuple->dbe_name.db_ev_name, &evtuple->dbe_owner, DB_EVENT_MAXNAME,
		  SXF_E_EVENT, I_SX2032_EVENT_CREATE, 
		  SXF_A_SUCCESS | SXF_A_CREATE, &e_error);

	    if (status != E_DB_OK)
		break;
	}

	qeuq_cb->error.err_code = E_QE0000_OK;
	return (E_DB_OK);
    } /* End dummy for */

    /* call qef_error to handle error messages */
    (VOID) qef_error(error, 0L, status, &error, &qeuq_cb->error, 0);

    /* Close off all the tables. */
    local_status = E_DB_OK;
    if (tbl_opened)		    /* If system table opened, close it */
    {
	local_status = qeu_close(qef_cb, &qeu);
	if (local_status != E_DB_OK)
	{
	    (VOID) qef_error(qeu.error.err_code, 0L, local_status, &error,
		    	     &qeuq_cb->error, 0);
	    if (local_status > status)
		status = local_status;
	}
    }

    if (transtarted)		   /* If we started a transaction */
    {
        local_status = qeu_atran(qef_cb, &tranqeu);
        if (local_status != E_DB_OK)
	{
	    (VOID) qef_error(tranqeu.error.err_code, 0L, local_status,
			     &error, &qeuq_cb->error, 0);
	    if (local_status > status)
		status = local_status;
	}
    }
    return (status);
} /* qeu_cevent */
Ejemplo n.º 5
0
/*
** Name: qeu_ev_used_with_alarm
**
** Description:
**	Determines whether a security alarm is using this event
**
** Inputs:
**	event_id	- Event id
**	
** History:
**	7-dec-93 (robf)
**	    Created
**	21-dec-93 (robf)
**	    Lookup by id now.
**	09-Mar-99 (schte01)
**	    Removed extraneous status assignment which caused compiler warning.
**	06-Aug-2002 (jenjo02)
**	    Init qeu_mask before calling qeu_open() lest DMF think we're
**	    passing bogus lock information (QEU_TIMEOUT,QEU_MAXLOCKS).
*/
static DB_STATUS
qeu_ev_used_with_alarm(
QEF_CB          *qef_cb,
QEUQ_CB		*qeuq_cb,
DB_TAB_ID	*event_id
)
{
    QEU_CB		aqeu;
    QEF_DATA		aqef_data;
    DB_SECALARM		alarm;
    DB_STATUS		status=E_DB_OK;
    bool		loop=FALSE;
    bool		found=FALSE;
    i4		error=0;

    do
    {
	/* Process security alarms */
	aqeu.qeu_type = QEUCB_CB;
	aqeu.qeu_length = sizeof(QEUCB_CB);
        aqeu.qeu_tab_id.db_tab_base  = DM_B_IISECALARM_TAB_ID;
        aqeu.qeu_tab_id.db_tab_index  = DM_I_IISECALARM_TAB_ID;
        aqeu.qeu_db_id = qeuq_cb->qeuq_db_id;
        aqeu.qeu_lk_mode = DMT_S;
        aqeu.qeu_flag = QEU_BYPASS_PRIV;
        aqeu.qeu_access_mode = DMT_A_READ;
	aqeu.qeu_mask = 0;
	status = qeu_open(qef_cb, &aqeu);
	if(status!=E_DB_OK)
		break;
	aqeu.qeu_getnext = QEU_REPO;
	aqeu.qeu_klen = 0;
	aqeu.qeu_qual = 0;
	aqeu.qeu_qarg = 0;
        aqeu.qeu_count = 1;
        aqeu.qeu_tup_length = sizeof(DB_SECALARM);
        aqeu.qeu_output = &aqef_data;
        aqef_data.dt_next = 0;
        aqef_data.dt_size = sizeof(DB_SECALARM);
        aqef_data.dt_data = (PTR)&alarm;

	while (status == E_DB_OK)
	{
	    /* Read all iisecalarm records. */


	    status = qeu_get(qef_cb, &aqeu);
	    if ((status != E_DB_OK) &&
		(aqeu.error.err_code == E_QE0015_NO_MORE_ROWS))
	    {
		status = E_DB_OK;
		break;
	    }
	    else if ((status == E_DB_OK) && (aqeu.qeu_count != 1))
	    {
		error = E_US2476_9334_IISECALARM_ERROR;
		if (status < E_DB_ERROR)
		    status = E_DB_ERROR;
		break;
	    }
	    if (event_id->db_tab_base==alarm.dba_eventid.db_tab_base &&
		event_id->db_tab_index==alarm.dba_eventid.db_tab_index)
	    {
		found=TRUE;
		break;
	    }
	    aqeu.qeu_getnext = QEU_NOREPO;
	    aqeu.qeu_klen = 0;
	}
        status = qeu_close(qef_cb, &aqeu);    
	if (status != E_DB_OK)
	{
	    error= E_US2476_9334_IISECALARM_ERROR;
	}
    } while (loop);

    /*
    ** Report any errors
    */
    if(error)
    {
	    i4		err;
	    DB_ERROR		err_blk;
	    _VOID_ qef_error(error, 0L, status, &err,
			     &err_blk, 0);
    }
    if(status==E_DB_OK)
    {
	    if(found)
		status=E_DB_WARN;
	    else
		status=E_DB_OK;
    }
    
    return status;
}
Ejemplo n.º 6
0
DB_STATUS qee_d8_undefrpt(
    QEF_RCB	    *qef_rcb,
    PTR	    i_qso_handle)
{
    DB_STATUS
    status = E_DB_OK,
    sav_status = E_DB_OK;
    DB_ERROR
    sav_err;
    i4	    err;
    GLOBALREF QEF_S_CB *Qef_s_cb;
    QEE_DSH	    *dsh_p   = (QEE_DSH *)NULL;
    QEF_QP_CB	    *qp;
    bool	    have_qp = FALSE;
    QSF_RCB	    qsf_rcb;
    ULM_RCB	    ulm;
    ULH_RCB	    ulh_rcb;

    struct
    {
        PTR	qso_handle;
        CS_SID	session_id;
    } ulh_name;



    /* 1.  acquire the QP using the handle */


    qsf_rcb.qsf_next = (QSF_RCB *)NULL;
    qsf_rcb.qsf_prev = (QSF_RCB *)NULL;
    qsf_rcb.qsf_length = sizeof(QSF_RCB);
    qsf_rcb.qsf_type = QSFRB_CB;
    qsf_rcb.qsf_owner = (PTR)DB_QEF_ID;
    qsf_rcb.qsf_ascii_id = QSFRB_ASCII_ID;
    qsf_rcb.qsf_sid = qef_rcb->qef_cb->qef_ses_id;
    ulh_rcb.ulh_hashid = Qef_s_cb->qef_ulhid;

    qsf_rcb.qsf_obj_id.qso_handle = i_qso_handle;

    qsf_rcb.qsf_lk_state = QSO_SHLOCK;
    status = qsf_call(QSO_LOCK, &qsf_rcb);
    if (status)
    {
        qef_rcb->error.err_code = E_QE0019_NON_INTERNAL_FAILURE;
        return(status);
    }

    have_qp = TRUE;
    qp = (QEF_QP_CB *) qsf_rcb.qsf_root;

    /* For sharable QP, sometimes the QP may have been destroyed by
    ** another session.  So check for a NULL root.  If so, release the
    ** lock and return. */

    if (qp == (QEF_QP_CB *) NULL)
    {
        qsf_call(QSO_UNLOCK, &qsf_rcb);
        return(E_DB_OK);
    }

    /* 2.  gotten the QP, acquire the DSH in ULH's cache */

    STRUCT_ASSIGN_MACRO(Qef_s_cb->qef_d_ulmcb, ulm);

    ulh_name.qso_handle = qsf_rcb.qsf_obj_id.qso_handle;
    ulh_name.session_id = qef_rcb->qef_cb->qef_ses_id;

    status = ulh_getmember(&ulh_rcb, (unsigned char *) &qp->qp_id,
                           (i4)sizeof(DB_CURSOR_ID),  (unsigned char *) & ulh_name,
                           (i4)sizeof(ulh_name), ULH_DESTROYABLE, 0);

    if (DB_FAILURE_MACRO(status))
    {
        qef_error(ulh_rcb.ulh_error.err_code, 0L, status, & err,
                  &qef_rcb->error, 0);
        qef_rcb->error.err_code = E_QE0102_CATALOG_DSH_OBJECT;
    }
    else
    {
        dsh_p = (QEE_DSH *)(ulh_rcb.ulh_object->ulh_uptr);
        ulm.ulm_streamid_p = &ulh_rcb.ulh_object->ulh_streamid;

        if (dsh_p != (QEE_DSH *)NULL)
        {
            /* 3.  reset the defined state of the REPEAT QUERY in the DSH */

            dsh_p->dsh_ddb_cb->qee_d3_status &= ~QEE_03Q_DEF;

            /* 4.  must release the acquired DSH */

            ulh_rcb.ulh_object = (ULH_OBJECT *)dsh_p->dsh_handle;
        }
        status = ulh_release(& ulh_rcb);
        if (status != E_DB_OK)
        {
            qef_error(ulh_rcb.ulh_error.err_code, 0L, status, & err,
                      &qef_rcb->error, 0);
            qef_rcb->error.err_code = E_QE0104_RELEASE_DSH_OBJECT;
        }

        /* must fall thru to release the QP */
    }

    /* 5.  release the QP */

    if (have_qp)
    {
        qsf_call(QSO_UNLOCK, & qsf_rcb);
    }
    if (status == E_DB_OK && sav_status)
    {
        status = sav_status;
        STRUCT_ASSIGN_MACRO(sav_err, qef_rcb->error);
    }
    return(status);
}
Ejemplo n.º 7
0
/*{
** 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);
}
Ejemplo n.º 8
0
/*{
** Name: qeu_dsecalarm 	- Drop single or all alarm definition.
**
** External QEF call:   status = qef_call(QEU_DSECALM, &qeuq_cb);
**
** Description:
**	Drop the alarm tuple, the alarm text from the appropriate tables 
**	(iisecalarm, iiqrytext and update the table "relstat" field. An
**	alarm can be dropped either by name (when the DROP SECURITY_ALARM
**      statement is issued) or by object id (when its associated object 
**      is dropped).
**
**	When originating from the DROP SECURITY_ALARM  statement the single 
**	alarm tuple is deleted based on its name - provided in the
**	qeuq_uld_tup parameter.  In this case the single alarm is fetched
**	(to collect the text, table id) and deleted.  If it wasn't
**	found then an error is returned.  
**
**	When originating from a DROP TABLE statement (this is similar to
**	the DROP INTEGRITY ON table ALL), all tuples that satisfy the
**	table-id are fetched (to collect their text ids) and dropped.
**	If none are found no error is returned.  
**
**	For each alarm that is dropped the text tuples are
**	also dropped based on the ids collected from the fetched alarm.
**
**	The way this routine works is the following:
**
**	    set up QEU CB's for iisecalarm, iiqrytext and open tables;
**	    if (DROP SECURITY_ALARM) then
**		set up iisecalarm "qualified" name and owner;
**	    else
**		set up iisecalarm "keyed" on DROP object id;
**	    endif;
**	    for (all alarm tuples found) loop
**		get alarm tuple;
**		if (not found) then
**		    if (DROP SECURITY_ALARM) then
**			error - alarm does not exist;
**			break;
**		    else
**			clear error;
**			break;
**		    endif;
**		endif;
**		set up iiqrytext keys based on alarm text id;
**		for (all text tuples found) loop
**		    get text tuple;
**		    delete text tuple;
**		endloop;
**		delete current alarm tuple;
**		if (DROP SECURITY_ALARM) then
**		    endloop;
**		endif;
**	    endloop;
**	    close tables;
**
** Inputs:
**      qef_cb                  QEF session control block
**      qeuq_cb
**	    .qeuq_eflag	        Designate error handling for user errors.
**		QEF_INTERNAL	Return error code.
**		QEF_EXTERNAL	Send message to user.
**	    .qeuq_rtbl		Table id of alarm - if DROP TABLE.  If DROP
**				SECURITY_ALARM then this is ignored.
**	    .qeuq_cr		Must be 1 if DROP SECURITY_ALARM, 0 
**				if DROP TABLE.
**	    .qeuq_uld_tup	Alarm tuple to be deleted - if DROP 
**				SECURITY_ALARM, otherwise this is ignored:
**		.dba_alarmname	alarm name *or*
**		.dba_alarmno	Alarm number
**	    .qeuq_db_id		Database id.
**	    .qeuq_d_id		DMF session id.
**	from_drop_alarm		TRUE if called from DROP SECURITY_ALARM
**	
** Outputs:
**      qeuq_cb
**	    .error.err_code	E_QE0002_INTERNAL_ERROR
**				E_QE0017_BAD_CB
**				E_QE0018_BAD_PARAM_IN_CB
**				E_QE0022_ABORTED
**	Returns:
**	    E_DB_{OK, WARN, ERROR, FATAL}
**	Exceptions:
**	    none
**
** History:
**	26-nov-93 (robf)
**	    Written for Secure 2.0
**	30-dec-93 (robf)
**          Don't  write audit records if called implicitly during drop
**	    of a table.
**	16-feb-94 (robf)
**          Check DROP ALL flag from  qeuq_cb.qeuq_permit_mask & QEU_DROP_ALL,
**	    so we loop appropriately when there are several alarms on
**	    the object to be dropped.
*/
DB_STATUS
qeu_dsecalarm(
QEF_CB          *qef_cb,
QEUQ_CB		*qeuq_cb,
bool		from_drop_alarm)
{
    QEU_CB	    	tranqeu;	/* For transaction request */
    bool	    	transtarted = FALSE;	    
    QEU_CB	    	aqeu;		/* For iisecalarm table */
    QEF_DATA	    	aqef_data;
    DB_SECALARM	    	*atuple_name;	/* Input tuple with name or id */
    DB_SECALARM	    	atuple;		/* Tuple currently being deleted */
    bool	    	alarm_opened = FALSE;
    DMR_ATTR_ENTRY  	akey_array[3];
    DMR_ATTR_ENTRY  	*akey_ptr_array[3];
    QEU_CB	    	qqeu;		/* For iiqrytext table */
    QEU_QUAL_PARAMS	qparams;
    DB_IIQRYTEXT	qtuple;
    QEF_DATA	    	qqef_data;
    bool	    	qtext_opened = FALSE;
    DMR_ATTR_ENTRY  	qkey_array[2];
    DMR_ATTR_ENTRY  	*qkey_ptr_array[2];
    bool		drop_specific_alarm;	/* TRUE if dropping a specific
						** alarm */
    char		obj_type;
    char		*alarm_name;
    DB_STATUS	    	status, local_status;
    i4	    	error;
    DB_ERROR 		e_error;
    SXF_ACCESS		access;
    SXF_EVENT		evtype;
    DB_OWN_NAME		objowner;

    for (;;)	/* Dummy for loop for error breaks */
    {
	MEfill(sizeof(objowner),' ',(PTR)&objowner);

	/* Validate CB and parameters */
	if (qeuq_cb->qeuq_type != QEUQCB_CB ||
            qeuq_cb->qeuq_length != sizeof(QEUQ_CB))	
	{
	    status = E_DB_ERROR;
	    error = E_QE0017_BAD_CB;
	    break;
	}
	if (   (qeuq_cb->qeuq_rtbl == NULL && qeuq_cb->qeuq_cr == 0)
            || (qeuq_cb->qeuq_db_id == NULL)
            || (qeuq_cb->qeuq_d_id == 0))
	{
	    status = E_DB_ERROR;
	    error = E_QE0018_BAD_PARAM_IN_CB;
	    break;
	}

	drop_specific_alarm = from_drop_alarm;

	/*
	** If passed DROP ALL then not dropping  specific alarm
	*/
	if(qeuq_cb->qeuq_permit_mask & QEU_DROP_ALL)
		drop_specific_alarm=FALSE;


	/* 
	** Check to see if transaction is in progress, if so set a local
	** transaction, otherwise we'll use the user's transaction.
	*/
	if (qef_cb->qef_stat == QEF_NOTRAN)
	{
	    tranqeu.qeu_type = QEUCB_CB;
	    tranqeu.qeu_length = sizeof(QEUCB_CB);
	    tranqeu.qeu_db_id = qeuq_cb->qeuq_db_id;
	    tranqeu.qeu_d_id = qeuq_cb->qeuq_d_id;
	    tranqeu.qeu_flag = 0;
	    tranqeu.qeu_mask = 0;
	    status = qeu_btran(qef_cb, &tranqeu);
	    if (status != E_DB_OK)
	    {	
		error = tranqeu.error.err_code;
		break;	
	    }	    
	    transtarted = TRUE;
	}
	/* Escalate the transaction to MST */
	if (qef_cb->qef_auto == QEF_OFF)
	    qef_cb->qef_stat = QEF_MSTRAN;


	/* Open iisecalarm, iiqrytext tables */
	aqeu.qeu_type = QEUCB_CB;
        aqeu.qeu_length = sizeof(QEUCB_CB);
        aqeu.qeu_db_id = qeuq_cb->qeuq_db_id;
        aqeu.qeu_lk_mode = DMT_IX;
        aqeu.qeu_flag = DMT_U_DIRECT;
        aqeu.qeu_access_mode = DMT_A_WRITE;
	aqeu.qeu_mask = 0;
	STRUCT_ASSIGN_MACRO(aqeu, qqeu);	/* Quick initialization */

	/* Open iisecalarm */
        aqeu.qeu_tab_id.db_tab_base = DM_B_IISECALARM_TAB_ID;    
        aqeu.qeu_tab_id.db_tab_index = DM_I_IISECALARM_TAB_ID; 	
	status = qeu_open(qef_cb, &aqeu);
	if (status != E_DB_OK)
	{
	    error = aqeu.error.err_code;
	    break;
	}
	alarm_opened = TRUE;

        qqeu.qeu_tab_id.db_tab_base = DM_B_QRYTEXT_TAB_ID; /* Open iiqrytext */
        qqeu.qeu_tab_id.db_tab_index = DM_I_QRYTEXT_TAB_ID; 	
	status = qeu_open(qef_cb, &qqeu);
	if (status != E_DB_OK)
	{
	    error = qqeu.error.err_code;
	    break;
	}
	qtext_opened = TRUE;

	aqeu.qeu_count = 1;	   	    /* Initialize alarm-specific qeu */
        aqeu.qeu_tup_length = sizeof(DB_SECALARM);
	aqeu.qeu_output = &aqef_data;
	aqef_data.dt_next = NULL;
        aqef_data.dt_size = sizeof(DB_SECALARM);
        aqef_data.dt_data = (PTR)&atuple;

	qqeu.qeu_count = 1;	   	    /* Initialize qtext-specific qeu */
        qqeu.qeu_tup_length = sizeof(DB_IIQRYTEXT);
	qqeu.qeu_output = &qqef_data;
	qqef_data.dt_next = NULL;
        qqef_data.dt_size = sizeof(DB_IIQRYTEXT);
        qqef_data.dt_data = (PTR)&qtuple;

	/*
	** If DROP SECURITY_ALARM then position iisecalarm table based on 
	** alarm name or numbr
	** and drop the specific alarm (if we can't find it issue an error).
	** Positioning is done via qeu_qalarm_by_name/id.  
	** If DROP TABLE then fetch and drop ALL alarms applied to the table.
	*/
	aqeu.qeu_getnext = QEU_REPO;
	if (from_drop_alarm)		
	{
	    /*
	    ** Might be scanning for database/installation alarms
	    ** or special DROP ALL processing.
	    */
            atuple_name   = (DB_SECALARM *)qeuq_cb->qeuq_uld_tup->dt_data;
	    alarm_name=(char*)&atuple_name->dba_alarmname;

	    /*
	    ** alarmno -1 indicates all alarms when qualifying
	    */
	    if(qeuq_cb->qeuq_permit_mask & QEU_DROP_ALL)
		atuple_name->dba_alarmno= -1;
	    /* Get alarm that matches alarm name (qualified) */
	    qparams.qeu_qparms[0] = (PTR) atuple_name;
	    aqeu.qeu_klen = 0;				/* Not keyed */
	    aqeu.qeu_qual = qeu_qalarm_by_name;
	    aqeu.qeu_qarg = &qparams;
	}
	else				/* DROP TABLE */
	{
	    /* Get alarm that applies to specific table id (keyed) */
	    obj_type=DBOB_TABLE;
	    alarm_name="unknown";

	    aqeu.qeu_klen = 3;
	    aqeu.qeu_key = akey_ptr_array;
	    akey_ptr_array[0] = &akey_array[0];
	    akey_ptr_array[1] = &akey_array[1];
	    akey_ptr_array[2] = &akey_array[2];

	    akey_ptr_array[0]->attr_number = DM_1_IISECALARM_KEY;
	    akey_ptr_array[0]->attr_operator = DMR_OP_EQ;
	    akey_ptr_array[0]->attr_value = (char*)&obj_type;

	    akey_ptr_array[1]->attr_number = DM_2_IISECALARM_KEY;
	    akey_ptr_array[1]->attr_operator = DMR_OP_EQ;
	    akey_ptr_array[1]->attr_value =
				    (char *)&qeuq_cb->qeuq_rtbl->db_tab_base;
	    akey_ptr_array[2]->attr_number = DM_3_IISECALARM_KEY;
	    akey_ptr_array[2]->attr_operator = DMR_OP_EQ;
	    akey_ptr_array[2]->attr_value =
				    (char *)&qeuq_cb->qeuq_rtbl->db_tab_index;
	    aqeu.qeu_qual = NULL;
	    aqeu.qeu_qarg = NULL;
	}
	for (;;)		/* For all alarm tuples found */
	{
	    status = qeu_get(qef_cb, &aqeu);
	    if (status != E_DB_OK)
	    {
		if (aqeu.error.err_code == E_QE0015_NO_MORE_ROWS)
		{
		    if (drop_specific_alarm)
		    {
			(VOID)qef_error(E_US2473_9331_ALARM_ABSENT, 0L,
				    E_DB_ERROR, &error, &qeuq_cb->error, 1,
				    qec_trimwhite(sizeof(atuple_name->dba_alarmname),
						alarm_name),
				    (PTR)alarm_name);
			error = E_QE0000_OK;
			status=E_DB_OK;
		    }
		    else	/* No [more] alarms for table */
		    {
			error = E_QE0000_OK;
			status = E_DB_OK;
		    }
		}
		else	/* Other error */
		{
		    error = aqeu.error.err_code;
		}
		break;
	    } /* If no alarms found */
	    aqeu.qeu_getnext = QEU_NOREPO;
            aqeu.qeu_klen = 0;
	    
	    status = E_DB_OK;

            /* Postion iiqrytxt table for query id associated with this alarm */
	    qkey_ptr_array[0] = &qkey_array[0];
	    qkey_ptr_array[1] = &qkey_array[1];
	    qqeu.qeu_getnext = QEU_REPO;
	    qqeu.qeu_klen = 2;       
	    qqeu.qeu_key = qkey_ptr_array;
	    qkey_ptr_array[0]->attr_number = DM_1_QRYTEXT_KEY;
	    qkey_ptr_array[0]->attr_operator = DMR_OP_EQ;
	    qkey_ptr_array[0]->attr_value =
				(char *)&atuple.dba_txtid.db_qry_high_time;
	    qkey_ptr_array[1]->attr_number = DM_2_QRYTEXT_KEY;
	    qkey_ptr_array[1]->attr_operator = DMR_OP_EQ;
	    qkey_ptr_array[1]->attr_value =
				(char *)&atuple.dba_txtid.db_qry_low_time;
	    qqeu.qeu_qual = NULL;
	    qqeu.qeu_qarg = NULL;
	    for (;;)		/* For all query text tuples */
	    {
		status = qeu_get(qef_cb, &qqeu);
		if (status != E_DB_OK)
		{
		    error = qqeu.error.err_code;
		    break;
		}
		qqeu.qeu_klen = 0;
		qqeu.qeu_getnext = QEU_NOREPO;
		status = qeu_delete(qef_cb, &qqeu);
		if (status != E_DB_OK)
		{
		    error = qqeu.error.err_code;
		    break;
		}
	    } /* For all query text tuples */
	    if (error != E_QE0015_NO_MORE_ROWS)
		break;

	    if(atuple.dba_objtype==DBOB_TABLE)
	    {
    		DMT_CHAR_ENTRY  	char_spec;	
    		DMT_CB	    	dmt_cb;
	    	/* 
            	** Alter the table relstat to flag alarms. This 
		** validates that the table exists and ensures that we 
		** get an exclusive lock on it.
           	*/
	    	char_spec.char_id = DMT_C_ALARM;    
	    	char_spec.char_value = DMT_C_ON;
		MEfill(sizeof(DMT_CB), 0, (PTR) &dmt_cb);
	    	dmt_cb.dmt_flags_mask = 0;
	    	dmt_cb.dmt_db_id = qeuq_cb->qeuq_db_id;
	    	dmt_cb.dmt_char_array.data_in_size = sizeof(DMT_CHAR_ENTRY);
	    	dmt_cb.dmt_char_array.data_address = (PTR)&char_spec;
	    	dmt_cb.length = sizeof(DMT_CB);
	    	dmt_cb.type = DMT_TABLE_CB;
	    	dmt_cb.dmt_id.db_tab_base  = atuple.dba_objid.db_tab_base;
	    	dmt_cb.dmt_id.db_tab_index = atuple.dba_objid.db_tab_index;
	    	dmt_cb.dmt_tran_id = qef_cb->qef_dmt_id;
	    	status = dmf_call(DMT_ALTER, &dmt_cb);
	    	if (status != E_DB_OK)
    	    	{
		    error = dmt_cb.error.err_code;
		    if (error == E_DM0054_NONEXISTENT_TABLE)
		    {
			error = E_QE0025_USER_ERROR;
			status = E_DB_OK;	/* Still remove the alarm */
		    }
		    else
		    {
			/* 
			** Some other error
			*/
	        	break;
		    }
	    	}
	     }
	     else if(!(atuple.dba_flags&DBA_ALL_DBS))
	     {
		/*
		** Check access to the  database, also get the security label
		** for later use
		*/
	    	status=qeu_db_exists(qef_cb, qeuq_cb,
		    (DB_DB_NAME *)&atuple.dba_objname, SXF_A_CONTROL, &objowner);
	    	if(status==E_DB_ERROR)
	    	{
			/* Error, no access to database */
			break;
	    	}
	    	else  if  (status==E_DB_WARN)
	    	{
			/* Database not found */
			status=E_DB_ERROR;
			/* E_US2474_9332_ALARM_NO_DB */
	        	(VOID)qef_error(9332, 0L, E_DB_ERROR,
			    &error, &qeuq_cb->error, 1,
			    qec_trimwhite(sizeof(atuple.dba_objname),
					  (char *)&atuple.dba_objname),
			    (PTR)&atuple.dba_objname);
			break;
		}
	    }
	    /* Now delete the current alarm tuple */
	    status = qeu_delete(qef_cb, &aqeu);
	    if (status != E_DB_OK)
	    {
		error = aqeu.error.err_code;
		break;
	    }
		
	    /*
	    ** If  doing a specific DROP SECURITY_ALARM we're done with this 
	    ** loop. 
	    ** Otherwise continue with next alarm applied to table.
	    */
	    if (drop_specific_alarm)
		break;
	} /* For all alarm found */

	if (status != E_DB_OK)
	    break;

	break;
    } /* End dummy for loop */

    /* Handle any error messages */
    if (status != E_DB_OK)
	(VOID) qef_error(error, 0L, status, &error, &qeuq_cb->error, 0);
    
    /* Close off all the tables and transaction */
    if (alarm_opened)
    {
	local_status = qeu_close(qef_cb, &aqeu);    
	if (local_status != E_DB_OK)
	{
	    (VOID) qef_error(aqeu.error.err_code, 0L, local_status, 
			     &error, &qeuq_cb->error, 0);
	    if (local_status > status)
		status = local_status;
	}
    }
    if (qtext_opened)
    {
	local_status = qeu_close(qef_cb, &qqeu);    
	if (local_status != E_DB_OK)
	{
	    (VOID) qef_error(qqeu.error.err_code, 0L, local_status, 
			     &error, &qeuq_cb->error, 0);
	    if (local_status > status)
		status = local_status;
	}
    }
    if (transtarted)
    {
	if (status == E_DB_OK)
	    local_status = qeu_etran(qef_cb, &tranqeu);
	else
	    local_status = qeu_atran(qef_cb, &tranqeu);
	if (local_status != E_DB_OK)
	{
	    (VOID) qef_error(tranqeu.error.err_code, 0L, local_status, 
			     &error, &qeuq_cb->error, 0);
	    if (local_status > status)
		status = local_status;
	}
    }
    /*
    ** Dropping an alarm is a control operation on the base object
    ** (database/table).
    */
    if( from_drop_alarm==TRUE && Qef_s_cb->qef_state & QEF_S_C2SECURE )
    {
        if(atuple.dba_objtype==DBOB_DATABASE)
        {
	    evtype=SXF_E_DATABASE;
	    /*
	    ** Database label/owner should be set in db_exists request above
	    */
        }
        else
        {
	    evtype=SXF_E_TABLE;
        }
        if(status==E_DB_OK)
	    access=(SXF_A_CONTROL|SXF_A_SUCCESS);
        else
	    access=(SXF_A_CONTROL|SXF_A_FAIL);
        if(qeu_secaudit(FALSE, qef_cb->qef_ses_id,
		(char *)&atuple.dba_objname,
		&objowner,
		sizeof(atuple.dba_objname), 
		evtype,
		I_SX202E_ALARM_DROP,
		access,
		&e_error)!=E_DB_OK)
        {
	    error = e_error.err_code;
	    status=E_DB_ERROR;
        }
    }
    if(status!=E_DB_OK)
    {
    	(VOID) qef_error(E_QE028C_DROP_ALARM_ERR, 0L, local_status, 
		     &error, &qeuq_cb->error, 0);
	qeuq_cb->error.err_code= E_QE0025_USER_ERROR;
    }
    return (status);
} /* qeu_dsecalarm */
Ejemplo n.º 9
0
/*{
** Name: QEU_APPEND     - append rows to table
**
** External QEF call:   status = qef_call(QEU_APPEND, &qeu_cb);
**
** Description:
**      This routine appends N tuples to an opened table. The table
** must have been opened with the QEU_OPEN command. This operation
** is valid only in an internal transaction (see QET.C).
**
** Inputs:
**       qeu_cb
**	    .qeu_eflag			    designate error handling semantis
**					    for user errors.
**		QEF_INTERNAL		    return error code.
**		QEF_EXTERNAL		    send message to user.
**          .qeu_acc_id                     table access id
**          .qeu_count                      number of tuples to append
**          .qeu_tup_length                 lenth of each tuple
**          .qeu_input                      input buffer
**					    
**
** Outputs:
**      qeu_cb
**          .qeu_count                      Number of tuples appended
**          .error.err_code                 One of the following
**                                          E_QE0000_OK
**                                          E_QE0002_INTERNAL_ERROR
**                                          E_QE0004_NO_TRANSACTION
**                                          E_QE0007_NO_CURSOR
**                                          E_QE0017_BAD_CB
**                                          E_QE0018_BAD_PARAM_IN_CB
**      Returns:
**          E_DB_OK
**          E_DB_ERROR                      caller error
**          E_DB_FATAL                      internal error
**      Exceptions:
**          none
**
** Side Effects:
**          none
**
** History:
**      27-may-86 (daved)
**          written
**	14-jul-93 (ed)
**	    replacing <dbms.h> by <gl.h> <sl.h> <iicommon.h> <dbdbms.h>
**	26-jul-93 (walt)
**	    Initialize the local variable "status" in qeu_append to E_DB_OK.
**	    If there are no rows to append it's possible to hit the closing
**	    return(status) statement without ever assigning status a
**	    non-garbage value.
**      01-feb-94 (stial01)
**          BUG 66409: copy from is hanging if DM0151_SI_DUPLICATE_KEY_STMT,
**          If this error occurs process it like the other duplicate errors. 
*/
DB_STATUS
qeu_append(
QEF_CB      *qef_cb,
QEU_CB      *qeu_cb)
{
    i4     err;
    DMR_CB      dmr_cb;
    i4     count;              /* number of tuples to appended */
    DB_STATUS   status = E_DB_OK;
    QEF_DATA    *dataptr;
    i4          i;
    i4		num_appended;	    /* number of tuples appended */

    count = qeu_cb->qeu_count;
    qeu_cb->qeu_count = 0;

    /* QEU_APPEND is only valid in a transaction */
    if (qef_cb->qef_stat == QEF_NOTRAN)
    {
        qef_error(E_QE0004_NO_TRANSACTION, 0L, E_DB_ERROR, &err,
            &qeu_cb->error, 0);
        return (E_DB_ERROR);
    }
    dmr_cb.type                 = DMR_RECORD_CB;
    dmr_cb.length               = sizeof(DMR_CB);
    dmr_cb.dmr_flags_mask	= 0;
    dmr_cb.dmr_access_id        = qeu_cb->qeu_acc_id;
    dmr_cb.dmr_tid              = 0;                    /* not used */
    dataptr                     = qeu_cb->qeu_input;    
    /* start appending rows */
    num_appended = 0;
    for (i = 0; i < count; i++)
    {
        dmr_cb.dmr_data.data_address = dataptr->dt_data;
        dmr_cb.dmr_data.data_in_size = dataptr->dt_size;
        status = dmf_call(DMR_PUT, &dmr_cb);
        if (status != E_DB_OK)
        {
	    /* *** FIXME *** This is insanely stupid -- dup rows/keys
	    ** are just ignored.  That was bad enough for COPY FROM,
	    ** which no longer comes here, but it seems that a bunch of
	    ** the QEU hurlers EXPECT a silent success on dup key/row.
	    ** Someday, root that crap out, and allow this routine to
	    ** treat errors in some rational manner...
	    */

	    if (dmr_cb.error.err_code == E_DM0046_DUPLICATE_RECORD ||
		  dmr_cb.error.err_code == E_DM0045_DUPLICATE_KEY ||
		  dmr_cb.error.err_code == E_DM0048_SIDUPLICATE_KEY ||
		  dmr_cb.error.err_code == E_DM0150_DUPLICATE_KEY_STMT ||
		  dmr_cb.error.err_code == E_DM0151_SIDUPLICATE_KEY_STMT)
	    {
		status = E_DB_OK;
		qeu_cb->error.err_code = dmr_cb.error.err_code;
	    }
	    else
	    {
		qef_error(dmr_cb.error.err_code, 0L, status, 
					&err, &qeu_cb->error, 0);
		return (status);
	    }
        }
        else
        {
            /* successful append */
            num_appended++;
        }
        /* next next record */
        dataptr = dataptr->dt_next;
    }
    /* tell user how many rows were appended */
    qeu_cb->qeu_count = num_appended;
    return (status);
}
Ejemplo n.º 10
0
/*
** Name: qeu_db_exists
**
** Description:
**	Checks whether a particular database exists, including MAC
**	access where appropriate. Denied access due to MAC will be
**	audited here, and a no-such-database error returned to the
**	caller. Successfull access should be audited by the caller.
**
** Inputs:
**	dbname	- Database name to check
**
**	access  - SXF-access on the database
**
** Outputs:
**	dbowner - Owner of database
**
** Returns:
**	E_DB_OK - Exists
**	E_DB_WARN - Doesn't exists
**	(error)   - Something went wrong
**
** History:
**	3-dec-93 (robf)
**	   Created
*/
DB_STATUS
qeu_db_exists(QEF_CB * qef_cb, QEUQ_CB *qeuq_cb, DB_DB_NAME *dbname, 
	i4 access, 
	DB_OWN_NAME *dbowner)
{
    DB_STATUS 	status=E_DB_OK;
    bool      	tbl_opened=FALSE;
    bool      	loop=FALSE;
    DU_DATABASE	dbtuple;
    bool	not_found=TRUE;
    i4 	error=0;
    QEU_CB	    qeu;
    QEF_DATA	    qef_data;
    DMR_ATTR_ENTRY  key_array[1];
    DMR_ATTR_ENTRY  *key_ptr_array[1];
    DB_ERROR	    err_blk;

    do
    {
	qeu.qeu_type = QEUCB_CB;
	qeu.qeu_length = sizeof(QEUCB_CB);
	qeu.qeu_tab_id.db_tab_base  = DM_B_DATABASE_TAB_ID;
	qeu.qeu_tab_id.db_tab_index  = DM_I_DATABASE_TAB_ID;
	qeu.qeu_db_id = qeuq_cb->qeuq_db_id;
	qeu.qeu_lk_mode = DMT_IS;
	qeu.qeu_access_mode = DMT_A_READ;
	qeu.qeu_flag = 0;
	qeu.qeu_mask = 0; 

	status = qeu_open(qef_cb, &qeu);
	if (status != E_DB_OK)
	{
		error = E_QE022D_IIDATABASE;
		status = (status > E_DB_SEVERE) ? status : E_DB_SEVERE;
		break;
	}
	tbl_opened = TRUE;

	qeu.qeu_count = 1;
	qeu.qeu_tup_length = sizeof(DU_DATABASE);
	qeu.qeu_output = &qef_data;
	qef_data.dt_next = 0;
	qef_data.dt_size = sizeof(DU_DATABASE);
	qef_data.dt_data = (PTR)&dbtuple;
	qeu.qeu_getnext = QEU_REPO;
	qeu.qeu_klen = 1;
	key_ptr_array[0]= &key_array[0];
	qeu.qeu_key = key_ptr_array;
	key_ptr_array[0]->attr_number = DM_1_DATABASE_KEY;
	key_ptr_array[0]->attr_operator = DMR_OP_EQ;
	key_ptr_array[0]->attr_value = (char *) dbname;
	qeu.qeu_qual = 0;
	qeu.qeu_qarg = 0;

	status = qeu_get(qef_cb, &qeu);
	if (((status != E_DB_OK) &&
		 (qeu.error.err_code != E_QE0015_NO_MORE_ROWS)) ||
		((status == E_DB_OK) &&
		 (qeu.qeu_count != 1))
	   )
	{
		error = E_QE022D_IIDATABASE;
		status = (status > E_DB_SEVERE) ? status : E_DB_SEVERE;
		break;
	}

	if (status != E_DB_OK)
	{
		not_found=TRUE;
		status=E_DB_OK;
	}
	else
	{
		not_found=FALSE;
	}
		
	status = qeu_close(qef_cb, &qeu);
	tbl_opened = FALSE;
	if (status != E_DB_OK)
	{
		error = E_QE022D_IIDATABASE;
		status = (status > E_DB_SEVERE) ? status : E_DB_SEVERE;
		break;
	}
	/*
	** Check MAC access to the database, if  we found it.
	*/
	if(not_found==TRUE)
		break;

	 if(dbowner)
		STRUCT_ASSIGN_MACRO(dbtuple.du_own, *dbowner);
    } while(loop);

    if(tbl_opened)
    {
	(VOID) qeu_close(qef_cb, &qeu);
    }
    if(not_found && status==E_DB_OK)
	status=E_DB_WARN;
    if(error)
    {
	    (VOID) qef_error(error, 0L, status, 
			     &error, &qeuq_cb->error, 0);
    }
    return status;
}
Ejemplo n.º 11
0
/*
** Name: qeu_gen_alarm_name
**
** Description:
**	Generates a default alarm name when none has been specified
**
**	Name will consist of a $ followed by first 5 chars of the object name
**	(blank padded if necessary), followed by _X_ where X is D or T 
**	followed by the hex representation of the alarm id.  Before
**	returning to the caller, we will call cui_idxlate() to convert name to
**	the case appropriate for the database to which we are connected.
**
** Inputs:
**	obj_name - Object name
**
**	obj_type - Object type
**
**	qef_rcb	 - RCB
**
**	alarm_name - Where to put result.
**
**	alarm_id   - Unique id for number.
**	
** Outputs:
**
**	alarm_name  - Name
** 
** History:
**	26-nov-93 (robf)
**	   Created
**	2-Dec-2010 (kschendel) SIR 124685
**	    Warning fixes, CMcpychar not to be used with single letter
**	    ascii constants.  (array out of bounds warnings.)
*/
static DB_STATUS
qeu_gen_alarm_name(
    i4                   obj_type,
    char                 *obj_name,
    QEF_RCB		 *qef_rcb,
    DB_TAB_ID		 *alarm_id,
    char		 *alarm_name,
    i4		 *err_code
)
{
    DB_STATUS	status = E_DB_OK;
    QEF_CB      *qef_cb = qef_rcb->qef_cb;
    u_i4	cui_flags =
		    ( * ( qef_cb->qef_dbxlate ) ) | CUI_ID_DLM | CUI_ID_NORM;
    u_i4   ret_mode;
    u_i4	len_untrans, len_trans = DB_ALARM_MAXNAME;
    u_char	untrans_str[DB_ALARM_MAXNAME];
    i4		j;
    char	*p = (char *) untrans_str;
    char	*limit;
    char	id_str[20], *id_p = id_str;
    DB_ERROR	err_blk;

    *p++ = '$';
    for (j = 0; j < 5; j++)
	CMcpyinc(obj_name, p);
    *p++ = '_';
    if(obj_type==DBOB_TABLE)
	*p++ = 'T';
    else if(obj_type==DBOB_DATABASE)
	*p++ = 'D';
    else
    {
	/* Unknown object type */
	*err_code=E_QE0018_BAD_PARAM_IN_CB;
	return E_DB_ERROR;
    }
    *p++ = '_';

    /* convert alarm id into a hex string */
    seedToDigits(alarm_id, id_str, qef_rcb );

    /* append id string to the name built so far */
    for (; *id_p != EOS; CMcpyinc(id_p, p))
    ;

    /* remember length of the name */
    len_untrans = p - (char *) untrans_str;

    status = cui_idxlate(untrans_str, &len_untrans, (u_char *) alarm_name,
	&len_trans, cui_flags, &ret_mode, &qef_rcb->error);
    if (DB_FAILURE_MACRO(status))
    {
	/*
	** cui_idxlate errors have two params currently.
	** We report here to avoid errors in generic code which
	** doens't have params.
	*/
        (VOID) qef_error(qef_rcb->error.err_code, 0L, status, 
			     err_code, &err_blk, 2,
			     sizeof(ERx("System generated alarm name"))-1,
			     ERx("System generated alarm name"),
			     len_untrans,
			     untrans_str);
	/* Assume passed bad input */
	*err_code=E_QE0018_BAD_PARAM_IN_CB;
	return status;
    }

    /* blank pad */
    p = alarm_name + len_trans;
    limit = alarm_name + DB_ALARM_MAXNAME;
    while (p < limit)
	*p++ = ' ';

    return(E_DB_OK);
}	
Ejemplo n.º 12
0
/*{
** Name: QEU_OPEN       - open a table
**
** External QEF call:   status = qef_call(QEU_OPEN, &qeu_cb);
**
** Description:
**      A table is opened. A transaction must be in progress when
** this routine is called. This routine must be called before any
** of qeu_delete, qeu_append or qeu_get is called.
** Tables are opened without DMT_NOWAIT being set and are opened for
** direct update.
**
** Inputs:
**       qeu_cb
**          .qeu_flag                       zero or QEU_SHOW_STAT
**                                          indicates if internal request for 
**                                          statistics.
**	    .qeu_eflag			    designate error handling semantis
**					    for user errors.
**		QEF_INTERNAL		    return error code.
**		QEF_EXTERNAL		    send message to user.
**          .qeu_tab_id                     table id
**          .qeu_db_id                      database id
**          .qeu_lk_mode                    lock mode
**              DMT_X                       exclusive table lock
**              DMT_S                       shared table lock
**              DMT_IX                      exclusive page lock
**              DMT_IS                      shared table lock
**              DMT_SIX                     shared table lock with ability
**                                          to exclusive lock pages
**          .qeu_access_mode                access mode
**              DMT_A_READ
**              DMT_A_WRITE
**
** Outputs:
**      qeu_cb
**          .qeu_acc_id                     table access id
**          .error.err_code                 One of the following
**                                          E_QE0000_OK
**                                          E_QE0002_INTERNAL_ERROR
**                                          E_QE0004_NO_TRANSACTION
**                                          E_QE0017_BAD_CB
**                                          E_QE0018_BAD_PARAM_IN_CB
**                                          E_QE0022_ABORTED
**                                          <DMF error messages>
**      Returns:
**          E_DB_OK
**          E_DB_ERROR                      caller error
**          E_DB_FATAL                      internal error
**      Exceptions:
**          none
**
** Side Effects:
**          none
**
** History:
**      27-may-86 (daved)
**          written
**      18-jul-89 (jennifer)
**          Added a flag to indicate that an internal request 
**          for statistical information is being requested.
**          This solves a B1 security problem where statistics
**          could be unpredicatable if B1 labels were checked.
**          For an internal request they aren't checked, for a 
**          normal query on the iihistogram and iistatistics 
**          table they are checked.
**	23-jan-91 (seputis)
**	    added support for timeout and maxlocks
**	25-mar-99 (shust01)
**	    Initialized dmt_mustlock.  On rare occasions storage happened
**	    to be equal to a 1 (TRUE), causing locks to be taken out even
**	    though readlock=nolock was set.
**	07-mar-2000 (gupsh01)
**	    Do not handle error E_DM006A_TRAN_ACCESS_CONFLICT here as it will
**	    be handled by the calling facility. (BUG 100777).
**	14-feb-03 (inkdo01)
**	    Special check for non-existant iisequence catalog, so message
**	    can be issued that database doesn't support sequences.
**	    
*/
DB_STATUS
qeu_open(
QEF_CB          *qef_cb,
QEU_CB         *qeu_cb)
{
    DMT_CB      dmt_cb;
    DB_STATUS   status;
    i4     err;
    DMT_CHAR_ENTRY  lockmode[2];
    i4		lockcount;

    MEfill(sizeof(DMT_CB), 0, (PTR) &dmt_cb);
    dmt_cb.type         = DMT_TABLE_CB;
    dmt_cb.length       = sizeof(DMT_CB);
    dmt_cb.dmt_db_id    = qeu_cb->qeu_db_id;
    STRUCT_ASSIGN_MACRO(qeu_cb->qeu_tab_id, dmt_cb.dmt_id);
    dmt_cb.dmt_flags_mask  = 0;
    if (qeu_cb->qeu_flag & QEU_SHOW_STAT)
	dmt_cb.dmt_flags_mask |= DMT_SHOW_STAT;
    if (qeu_cb->qeu_flag & QEU_BYPASS_PRIV)
	dmt_cb.dmt_flags_mask |= DMT_DBMS_REQUEST;
    dmt_cb.dmt_lock_mode   = qeu_cb->qeu_lk_mode;
    dmt_cb.dmt_update_mode = DMT_U_DIRECT;
    dmt_cb.dmt_mustlock    = FALSE;
    dmt_cb.dmt_access_mode = qeu_cb->qeu_access_mode;
    lockcount = 0;
    if (qeu_cb->qeu_mask & QEU_TIMEOUT)
    {
	lockmode[lockcount].char_id = DMT_C_TIMEOUT_LOCK;
	lockmode[lockcount].char_value = qeu_cb->qeu_timeout;
	lockcount++;
    }
    if (qeu_cb->qeu_mask & QEU_MAXLOCKS)
    {
	lockmode[lockcount].char_id = DMT_C_PG_LOCKS_MAX;
	lockmode[lockcount].char_value = qeu_cb->qeu_maxlocks;
	lockcount++;
    }
    if (lockcount > 0)
    {
	dmt_cb.dmt_char_array.data_address = (PTR)lockmode;
	dmt_cb.dmt_char_array.data_in_size = sizeof(lockmode[0]) * lockcount;
	dmt_cb.dmt_char_array.data_out_size = 0;
    }
    else
	dmt_cb.dmt_char_array.data_in_size = 0;

    dmt_cb.dmt_sequence	   = qef_cb->qef_stmt;

    /* QEU_OPEN is only valid in a transaction */
    if (qef_cb->qef_stat == QEF_NOTRAN)
    {
        qef_error(E_QE0004_NO_TRANSACTION, 0L, E_DB_ERROR, &err,
            &qeu_cb->error, 0);
        return (E_DB_ERROR);
    }
    dmt_cb.dmt_tran_id = qef_cb->qef_dmt_id;
    status = dmf_call(DMT_OPEN, &dmt_cb);
    if (status == E_DB_OK)
    {
        qeu_cb->qeu_acc_id = dmt_cb.dmt_record_access_id;
        qef_cb->qef_open_count++;
    }
    else 
    {
	/* 
	** Do not handle the dmf error E_DM006A_TRAN_ACCESS_CONFLICT here  
	** as it is being handled by the calling facility BUG: 100777 
	**/
	if (dmt_cb.error.err_code == E_DM006A_TRAN_ACCESS_CONFLICT)
	{
	    qeu_cb->error.err_code = dmt_cb.error.err_code;
	    qeu_cb->error.err_data = dmt_cb.error.err_data;
	}
	else if (dmt_cb.error.err_code == E_DM0054_NONEXISTENT_TABLE &&
	    qeu_cb->qeu_tab_id.db_tab_base == DM_B_SEQ_TAB_ID)
         qef_error(E_QE00A1_IISEQ_NOTDEFINED, 0L, status, &err, 
						&qeu_cb->error, 0);
	else qef_error(dmt_cb.error.err_code, 0L, status, &err, 
						&qeu_cb->error, 0);
    }
    return (status);
}
Ejemplo n.º 13
0
/*{
** Name: QEU_GET        - get tuples from an open table
**
** External QEF call:   status = qef_call(QEU_GET, &qeu_cb);
**
** Description:
**      Tuples are retrieved from an open table. 
**
** Inputs:
**       qeu_cb
**	    .qeu_eflag			    designate error handling semantis
**					    for user errors.
**		QEF_INTERNAL		    return error code.
**		QEF_EXTERNAL		    send message to user.
**          .qeu_acc_id                     table access id
**          .qeu_tup_length                 length of retrieved tuple
**          .qeu_count                      number of tuples to retrieve
**          .qeu_getnext                    reposition	
**              QEU_REPO		    repostion using key
**		QEU_NOREPO		    continue from previous call to
**					    this routine
**          .qeu_klen                       length of key - number of entries
**          .qeu_key                        key for retrieve
**          .qeu_qual                       qualification function
**          .qeu_qarg                       argument to qualification function
**	    .qeu_flag			    operation qualifier
**		QEU_BY_TID		    get tuple by TID - will only be
**					    considered if !QEU_REPO
**	    .qeu_tid                        contains TID of the tuple to be
**					    retrieved
**          .qeu_output                     output buffer
**      <qeu_key> is a pointer to an array of pointers of type DMR_ATTR_ENTRY
**              .attr_number
**              .attr_operation
**              .attr_value_ptr
**
** Outputs:
**      qeu_cb
**          .qeu_count                      number of tuples retrieved
**          .error.err_code                 One of the following
**                                          E_QE0000_OK
**                                          E_QE0002_INTERNAL_ERROR
**                                          E_QE0004_NO_TRANSACTION
**                                          E_QE0007_NO_CURSOR
**                                          E_QE0017_BAD_CB
**                                          E_QE0018_BAD_PARAM_IN_CB
**                                          E_QE0015_NO_MORE_ROWS
**                                          E_QE0022_ABORTED
**					    E_QE0015_NO_MORE_ROWS
**          .qeu_output                     output buffer
**      Returns:
**          E_DB_OK
**          E_DB_WARN
**          E_DB_ERROR                      caller error
**          E_DB_FATAL                      internal error
**      Exceptions:
**          none
**
** Side Effects:
**          the output buffers are filled in
**
** History:
**      27-may-86 (daved)
**          written
**      31-jul-86 (jennifer)
**          Modified qeu_get to not allocate output
**          from memory stream, but to assume output
**          array is already initialized.
**      20-aug-86 (jennifer)
**          When dmf returns nonext, then qef must
**          return no-more-rows.
**	10-oct-87 (puree)
**	    Same as above even during positioning.
**	04-jan-90 (andre)
**	    return tid of the last tuple which was successfully read in
**	    QU_CB->qeu_tid
**	17-jun-92 (andre)
**	    add support for retrieval by TID - qeu_gentext should NOT be set to
**	    QEU_REPO
**	27-jul-96 (ramra01)
**	    Alter table project: Position only flag on qeu_get.
**	11-Apr-2008 (kschendel)
**	    Revised DMF qualification requirements, simplified for QEU.
*/
DB_STATUS
qeu_get(
QEF_CB          *qef_cb,
QEU_CB          *qeu_cb)
{
    i4     err;
    DMR_CB      dmr_cb;
    i4     count;          /* number of tuples returned */
    i4		i;
    DB_STATUS   status;
    PTR         tuple;
    QEF_DATA    *dataptr;

    count = qeu_cb->qeu_count;		/* number of rows to get */
    qeu_cb->qeu_count = 0;

    /* QEU_GET is only valid in a transaction */
    if (qef_cb->qef_stat == QEF_NOTRAN)
    {
        qef_error(E_QE0004_NO_TRANSACTION, 0L, E_DB_ERROR, &err,
            &qeu_cb->error, 0);
        return (E_DB_ERROR);
    }
    dmr_cb.type                 = DMR_RECORD_CB;
    dmr_cb.length               = sizeof(DMR_CB);
    dmr_cb.dmr_access_id        = qeu_cb->qeu_acc_id;
    dmr_cb.dmr_tid              = 0;                    /* not used */
    dmr_cb.dmr_q_fcn		= NULL;
    /* if positioning the cursor */
    if (qeu_cb->qeu_getnext == QEU_REPO)
    {
        /* if there is a key, position by qual. Else, position all records */
        if (qeu_cb->qeu_klen == 0)
            dmr_cb.dmr_position_type = DMR_ALL;
        else
        {
            /* set the keys */
            dmr_cb.dmr_position_type = DMR_QUAL;
	    dmr_cb.dmr_attr_desc.ptr_address    = (PTR) qeu_cb->qeu_key;
	    dmr_cb.dmr_attr_desc.ptr_in_count   = qeu_cb->qeu_klen;
	    dmr_cb.dmr_attr_desc.ptr_size	= sizeof (DMR_ATTR_ENTRY);
	    dmr_cb.dmr_s_estimated_records	= -1;
        }
        /* row qualifier */
        dmr_cb.dmr_q_fcn = (DB_STATUS (*)(void *,void *)) qeu_cb->qeu_qual;
        dmr_cb.dmr_q_arg = (PTR) qeu_cb->qeu_qarg;
	if (qeu_cb->qeu_qual != NULL)
	{
	    dmr_cb.dmr_q_rowaddr = &qeu_cb->qeu_qarg->qeu_rowaddr;
	    dmr_cb.dmr_q_retval = &qeu_cb->qeu_qarg->qeu_retval;
	}
        dmr_cb.dmr_flags_mask = 0;
        status = dmf_call(DMR_POSITION, &dmr_cb);
        if (status != E_DB_OK)
        {
            if (dmr_cb.error.err_code == E_DM0055_NONEXT)
                qeu_cb->error.err_code = E_QE0015_NO_MORE_ROWS;
            else
            {
                qef_error(dmr_cb.error.err_code, 0L, status, &err, 
		    &qeu_cb->error, 0);
            }
            return (status);
        }
    }

    if (qeu_cb->qeu_flag & QEU_POSITION_ONLY)
       return (E_DB_OK);

    /* We can now start getting records */
    /* point to space for the first tuple */
    /* the tuple length will not change. Tell DMF about it */
    dmr_cb.dmr_data.data_in_size = qeu_cb->qeu_tup_length;

    /* assign the beginning of the output chain */
    dataptr = qeu_cb->qeu_output;
    tuple = dataptr->dt_data;
    i = 0;

    /*
    ** if qeu_getnexdt was not set to QEU_REPO and QEU_BY_TID was set in
    ** qeu_flag, tell dmr_get() to get a tuple with specified TID; otherwise
    ** tell it to get the next row
    */
    if (qeu_cb->qeu_getnext != QEU_REPO && qeu_cb->qeu_flag & QEU_BY_TID)
    {
	dmr_cb.dmr_flags_mask = DMR_BY_TID;
	dmr_cb.dmr_tid = qeu_cb->qeu_tid;
    }
    else
    {
	dmr_cb.dmr_flags_mask = DMR_NEXT;
    }

    for (;;)
    {
        /* get the tuple */
        dmr_cb.dmr_data.data_address = tuple;
        status = dmf_call(DMR_GET, &dmr_cb);
        if (status != E_DB_OK)
        {
            if (dmr_cb.error.err_code == E_DM0055_NONEXT)
	    {
		qeu_cb->error.err_code = E_QE0015_NO_MORE_ROWS;
                break;
	    }
            else
            {
                qef_error(dmr_cb.error.err_code, 0L, status, &err, 
		    &qeu_cb->error, 0);
                return (status);
            }
        }

	/* save TID of the last tuple read */
	qeu_cb->qeu_tid = dmr_cb.dmr_tid;

        /*
	** get space for next tuple - if retrieving by TID we never want to get
	** more than one tuple
	*/
        if (++i < count && dmr_cb.dmr_flags_mask != DMR_BY_TID)
        {
            /* move to next entry in the output chain */
            dataptr = dataptr->dt_next;
            tuple = dataptr->dt_data;
        }
        else
            break;
    }
    /* assign output value */
    qeu_cb->qeu_count = i;
    return (status);
}
Ejemplo n.º 14
0
/*{
** Name: QEU_DELETE     - delete tuples from a table
**
** External QEF call:   status = qef_call(QEU_DELETE, &qeu_cb);
**
** Description:
**      Tuples are deleted from a table opened with the QEU_OPEN
** command. If no qualification is given, the current tuple is 
** deleted.
**
** Inputs:
**       qeu_cb
**	    .qeu_eflag			    designate error handling semantis
**					    for user errors.
**		QEF_INTERNAL		    return error code.
**		QEF_EXTERNAL		    send message to user.
**          .qeu_acc_id                     table access id
**          .qeu_tup_length                 tuple length of the table
**					    Only required for keyed delete
**          .qeu_qual                       qualification function
**          .qeu_qarg                       argument to qualification function
**          .qeu_klen                       length of key - number of entries
**          .qeu_key                        key for delete
**      <qeu_key> is a pointer to an array of pointers of type DMR_ATTR_ENTRY
**              .attr_number
**              .attr_operation
**              .attr_value_ptr
**	    .qeu_flag			    operation qualifier
**		QEU_BY_TID		    remove tuple whose TID is in qeu_tid
**	    .qeu_tid			    contains TID of the tuple to be
**					    removed if (qeu_flag & QEU_BY_TID)
**
** Outputs:
**      qeu_cb
**          .qeu_count                      number of tuples retrieved
**          .error.err_code                 One of the following
**                                          E_QE0000_OK
**                                          E_QE0002_INTERNAL_ERROR
**                                          E_QE0004_NO_TRANSACTION
**                                          E_QE0007_NO_CURSOR
**                                          E_QE0017_BAD_CB
**                                          E_QE0018_BAD_PARAM_IN_CB
**      Returns:
**          E_DB_OK
**          E_DB_ERROR                      caller error
**          E_DB_FATAL                      internal error
**      Exceptions:
**          none
**
** Side Effects:
**          none
**
** History:
**      27-may-86 (daved)
**          written
**      02-sep-86 (jennifer)
**          Modified qeu_delete to return a count of tuples 
**          deleted.
**	21-oct-86 (daved)
**	    did above fix for case where dmf returns no more rows.
**	22-dec-86 (daved)
**	    return OK if deleting keyed records
**      10-dec-87 (puree)
**          Converted all ulm_palloc to qec_palloc
**	04-jan-91 (andre)
**	    added functionality to delete tuples by TID
**	18-jun-92 (andre)
**	    do not allocate memory unless we will actually be reading tuples,
**	    i.e. if a key is specified
**	06-mar-96 (nanpr01)
**	    removed the dependency on DB_MAXTUP for increased tuple size
**	    project. Also added the check to make sure tuple size is set
**	    whoever called this routine.  Also tuple size consistency is
**	    checked iff qeu_klen > 0.
**	24-Jan-2001 (jenjo02)
**	    Ensure that memory stream is closed before returning.
**	11-Apr-2008 (kschendel)
**	    Revised DMF qualification requirements, simplified for QEU.
*/
DB_STATUS
qeu_delete(
QEF_CB          *qef_cb,
QEU_CB          *qeu_cb)
{
    i4         err;
    i4              count;
    DMR_CB          dmr_cb;
    DB_STATUS       status;
    GLOBALREF QEF_S_CB *Qef_s_cb;
    ULM_RCB         ulm;        /* so we don't need to allocate a tuple buffer
                                ** as a stack variable, use dynamic memory
                                */

    count = 0;
    qeu_cb->qeu_count = 0;
    qeu_cb->error.err_code = E_QE0000_OK;

    /* QEU_DELETE is only valid in a transaction */
    if (qef_cb->qef_stat == QEF_NOTRAN)
    {
        qef_error(E_QE0004_NO_TRANSACTION, 0L, E_DB_ERROR, &err,
            &qeu_cb->error, 0);
        return (E_DB_ERROR);
    }
    dmr_cb.type                 = DMR_RECORD_CB;
    dmr_cb.length               = sizeof(DMR_CB);
    dmr_cb.dmr_access_id        = qeu_cb->qeu_acc_id;
    dmr_cb.dmr_q_fcn		= NULL;

    /* position the cursor */
    /* if there is a key, position by qual. Else, position all records */
    if (qeu_cb->qeu_klen)
    {
        if (qeu_cb->qeu_tup_length <= 0)
        {
            qef_error(E_QE0018_BAD_PARAM_IN_CB, 0L, E_DB_ERROR, &err,
                &qeu_cb->error, 0);
            return (E_DB_ERROR);
        }
	/* allocate memory for a tuple only if planning to call qeu_get() */
	
	STRUCT_ASSIGN_MACRO(Qef_s_cb->qef_d_ulmcb, ulm);
	/* Open stream and allocate tuple memory in one action */
	ulm.ulm_flags = ULM_PRIVATE_STREAM | ULM_OPEN_AND_PALLOC;
	ulm.ulm_psize = ulm.ulm_blocksize = qeu_cb->qeu_tup_length;

	if ((status = qec_mopen(&ulm)) != E_DB_OK)
	{
	    qef_error(E_QE001E_NO_MEM, 0L, E_DB_ERROR, &err,
		&qeu_cb->error, 0);
	    return (status);
	}

        /* set the keys */
        dmr_cb.dmr_position_type = DMR_QUAL;
        dmr_cb.dmr_attr_desc.ptr_address    = (PTR) qeu_cb->qeu_key;
        dmr_cb.dmr_attr_desc.ptr_in_count   = qeu_cb->qeu_klen;
	dmr_cb.dmr_attr_desc.ptr_size	    = sizeof (DMR_ATTR_ENTRY);
	dmr_cb.dmr_s_estimated_records	    = -1;

        /* row qualifier */
        dmr_cb.dmr_q_fcn = (DB_STATUS (*)(void *,void *)) qeu_cb->qeu_qual;
        dmr_cb.dmr_q_arg = (PTR) qeu_cb->qeu_qarg;
	if (qeu_cb->qeu_qual != NULL)
	{
	    dmr_cb.dmr_q_rowaddr = &qeu_cb->qeu_qarg->qeu_rowaddr;
	    dmr_cb.dmr_q_retval = &qeu_cb->qeu_qarg->qeu_retval;
	}
	dmr_cb.dmr_flags_mask = 0;
        status = dmf_call(DMR_POSITION, &dmr_cb);
        if (status != E_DB_OK)
        {
	    ulm_closestream(&ulm);
	    if (dmr_cb.error.err_code == E_DM0055_NONEXT)
		return (E_DB_OK);

            qef_error(dmr_cb.error.err_code, 0L, status, &err, &qeu_cb->error, 0);
            return (status);
        }
        /* the tuple length will not change. Tell DMF about it */
	dmr_cb.dmr_data.data_in_size = qeu_cb->qeu_tup_length;
	dmr_cb.dmr_data.data_address = ulm.ulm_pptr;
    }

    for (;;)
    {
        if (qeu_cb->qeu_klen)
	{
            /* get the tuple */
            dmr_cb.dmr_flags_mask = DMR_NEXT;
            status = dmf_call(DMR_GET, &dmr_cb);
            if (status != E_DB_OK)
            {
                if (dmr_cb.error.err_code == E_DM0055_NONEXT)
		{
		    status = E_DB_OK;
                    break;
		}
                else
                {
                    qef_error(dmr_cb.error.err_code, 0L, status, 
                        &err, &qeu_cb->error, 0);
                }
                break;
            }
	}
	/*
	** delete the tuple: if deleting by TID, copy qeu_tid to dmr_tid and set
	** dmr_flags_mask to DMR_BY_TID
	*/
	if (qeu_cb->qeu_flag & QEU_BY_TID)
	{
	    dmr_cb.dmr_flags_mask = DMR_BY_TID;
	    dmr_cb.dmr_tid = qeu_cb->qeu_tid;
	}
	/* otherwise delete the current tuple */
	else
	{
	    dmr_cb.dmr_flags_mask = DMR_CURRENT_POS;
	}

        status = dmf_call(DMR_DELETE, &dmr_cb);
        if (status != E_DB_OK)
        {
            qef_error(dmr_cb.error.err_code, 0L, status, 
                &err, &qeu_cb->error, 0);
            break;
        }
	count++;
	if (qeu_cb->qeu_klen == 0)
	{
	    /* we are only deleting current tuple */
	    break;        
        }
    }
    
    if (qeu_cb->qeu_klen)
    {
	/* don't try to close a stream unless it was opened */
	ulm_closestream(&ulm);
    }
    
    qeu_cb->qeu_count = count;
    return (status);
}
Ejemplo n.º 15
0
/*{
** Name: qeu_devent 	- Drop an event definition.
**
** External QEF call:   status = qef_call(QEU_DEVENT, &qeuq_cb);
**
** Description:
**	Drop the event tuple and the event text from the appropriate
**	tables (iievent and iiqrytext).  An event may only be dropped
**	by name as a result of the DROP EVENT statement.
**
**	The single event tuple is deleted based on its name and owner (since
**	the iievent table is hashed on name and owner this is a singleton
**	keyed retrieval).  If the event tuple wasn't fetched, then an error
**	is returned to the user.
**
**	If the event was found then all permits applied to this event
**	are dropped (using qeu_dprot with the dummy event/table ids and
**	without a permit number to indicate ALL protection tuples).  In
**	this case qeu_dprot need not recheck that the event does exist.
**	Note that the qeu_dprot routine will open and close iiqrytext
**	to remove the text associated with the event permit.
**
**	Following permit removal all query text tuples associated with the
**	CREATE EVENT statement are removed from iiqrytext based on the
**	query text ids in the fetched event tuple.
**
** Inputs:
**      qef_cb                  QEF session control block
**      qeuq_cb
**	    .qeuq_eflag	        Designate error handling for user errors.
**		QEF_INTERNAL	Return error code.
**		QEF_EXTERNAL	Send message to user.
**	    .qeuq_culd		Number of event tuples.  Must be 1.
**	    .qeuq_uld_tup	Event tuple:
**		.dbe_name	Event name.
**		.dbe_owner	Event owner.
**		.dbe_type	Event type - ignored until there are more.
**				Remaining fields are assigned and used here.
**	    .qeuq_db_id		Database id.
**	    .qeuq_d_id		DMF session id.
**
** Outputs:
**      qeuq_cb
**	    .error.err_code	E_QE0002_INTERNAL_ERROR
**				E_QE0017_BAD_CB
**				E_QE0018_BAD_PARAM_IN_CB
**				E_QE0022_ABORTED
**				E_QE020B_EVENT_ABSENT (ret E_QE0025_USER_ERROR)
**	Returns:
**	    E_DB_{OK, WARN, ERROR, FATAL}
**	Exceptions:
**	    none
**
** History:
**	28-aug-89 (neil)
**	    Written for Terminator II/alerters.
**	09-feb-90 (neil)
**	   Added auditing functionality.
**	03-mar-90 (neil)
**	   Modify interface to que_dprot to indicate from DROP EVENT.
**	24-jun-92 (andre)
**	    after deleting IIEVENT tuple, call qeu_d_cascade to handle
**	    destruction of IIPROTECT, IIQRYTEXT tuples and marking dependent
**	    dbprocs dormant
**	08-sep-92 (andre)
**	    before calling qeu_d_cascade(), reset QEU_DROP_TEMP_TABLE in
**	    qeuq_flag_mask
**	24-jun-93 (robf)
**	    Perform MAC access check prior to drop of event. If no access is
**	    allowed then treat as non-existent event.
**	10-sep-93 (andre)
**	    before calling qeu_d_cascade(), set QEU_FORCE_QP_INVALIDATION in
**	    qeuq_flag_mask
**	21-sep-93 (stephenb)
**	    Replace generic I_SX2032_EVENT_ACCESS with I_SX203C_EVENT_DROP.
**	08-oct-93 (andre)
**	    qeu_d_cascade() expects one more parameter - an address of a 
**	    DMT_TBL_ENTRY describing table/view/index being dropped; for all 
**	    other types of objects, NULL must be passed
**	14-oct-93 (robf)
**          Make sure access check is on tuple being  deleted, not input tuple.
**	7-dec-93 (robf)
**          Check if event is in used by an alarm, if so reject the operation.
**	7-jun-94 (robf)
**          audit the security label for the event correctly on B1, this 
**	    ensures level auditing picks up the change. (Previously we were 
**	    auditing the input tuple security label, which was empty,
**	    not the delete tuple security label). Also don't try to
**	    but this makes the case clearer)
**	12-oct-94 (ramra01)
**	    Initialize variable local_status before use - 65258
**	13-jun-96 (nick)
**	    Above change didn't actually work.
**
*/
DB_STATUS
qeu_devent(
QEF_CB          *qef_cb,
QEUQ_CB		*qeuq_cb)
{
    QEU_CB	    	tranqeu;	/* For transaction request */
    bool	    	transtarted = FALSE;
    QEU_CB	    	evqeu;		/* For iievent table */
    QEF_DATA	    	evqef_data;
    DB_IIEVENT	    	*evtuple;	/* Input tuple with name and owner */
    DB_IIEVENT	    	evtuple_del;	/* Tuple currently being deleted */
    bool	    	event_opened = FALSE;
    DMR_ATTR_ENTRY  	evkey_array[2];	/* Key values from iievent */
    DMR_ATTR_ENTRY  	*evkey_ptr_array[2];
    DB_STATUS	    	status;
    DB_STATUS		local_status = E_DB_OK;
    i4	    	error;
    DB_ERROR		err;

    for (;;)	/* Dummy for loop for error breaks */
    {
	/* Validate CB and parameters */
	if (qeuq_cb->qeuq_type != QEUQCB_CB ||
            qeuq_cb->qeuq_length != sizeof(QEUQ_CB))
	{
	    status = E_DB_ERROR;
	    error = E_QE0017_BAD_CB;
	    break;
	}
	if (   (qeuq_cb->qeuq_culd != 1 || qeuq_cb->qeuq_uld_tup == NULL)
            || (qeuq_cb->qeuq_db_id == NULL)
            || (qeuq_cb->qeuq_d_id == 0))
	{
	    status = E_DB_ERROR;
	    error = E_QE0018_BAD_PARAM_IN_CB;
	    break;
	}
	/*
	** Check to see if transaction is in progress, if so set a local
	** transaction, otherwise we'll use the user's transaction.
	*/
	if (qef_cb->qef_stat == QEF_NOTRAN)
	{
	    tranqeu.qeu_type = QEUCB_CB;
	    tranqeu.qeu_length = sizeof(QEUCB_CB);
	    tranqeu.qeu_db_id = qeuq_cb->qeuq_db_id;
	    tranqeu.qeu_d_id = qeuq_cb->qeuq_d_id;
	    tranqeu.qeu_flag = 0;
	    status = qeu_btran(qef_cb, &tranqeu);
	    if (status != E_DB_OK)
	    {
		error = tranqeu.error.err_code;
		break;
	    }
	    transtarted = TRUE;
	}
	/* Escalate the transaction to MST */
	if (qef_cb->qef_auto == QEF_OFF)
	    qef_cb->qef_stat = QEF_MSTRAN;

	evtuple  = (DB_IIEVENT *)qeuq_cb->qeuq_uld_tup->dt_data;

	/* Open iievent tables */
	evqeu.qeu_type = QEUCB_CB;
        evqeu.qeu_length = sizeof(QEUCB_CB);
        evqeu.qeu_db_id = qeuq_cb->qeuq_db_id;
        evqeu.qeu_lk_mode = DMT_IX;
        evqeu.qeu_flag = DMT_U_DIRECT;
        evqeu.qeu_access_mode = DMT_A_WRITE;
	evqeu.qeu_mask = 0;

        evqeu.qeu_tab_id.db_tab_base  = DM_B_EVENT_TAB_ID;   /* Open iievent */
        evqeu.qeu_tab_id.db_tab_index = DM_I_EVENT_TAB_ID; 
	status = qeu_open(qef_cb, &evqeu);
	if (status != E_DB_OK)
	{
	    error = evqeu.error.err_code;
	    break;
	}
	event_opened = TRUE;

	evqeu.qeu_count = 1;	   	    /* Initialize event-specific qeu */
        evqeu.qeu_tup_length = sizeof(DB_IIEVENT);
	evqeu.qeu_output = &evqef_data;
	evqef_data.dt_next = NULL;
        evqef_data.dt_size = sizeof(DB_IIEVENT);
        evqef_data.dt_data = (PTR)&evtuple_del;

	/*
	** Position iievent table based on name & owner and drop specific
	** event.  If we can't find it issue an error.
	*/
	evqeu.qeu_getnext = QEU_REPO;

	/* Get event that matches (keyed on) event name and owner */
	evqeu.qeu_klen = 2;
	evqeu.qeu_key = evkey_ptr_array;
	evkey_ptr_array[0] = &evkey_array[0];
	evkey_ptr_array[0]->attr_number = DM_1_EVENT_KEY;
	evkey_ptr_array[0]->attr_operator = DMR_OP_EQ;
	evkey_ptr_array[0]->attr_value = (char *)&evtuple->dbe_name;
	evkey_ptr_array[1] = &evkey_array[1];
	evkey_ptr_array[1]->attr_number = DM_2_EVENT_KEY;
	evkey_ptr_array[1]->attr_operator = DMR_OP_EQ;
	evkey_ptr_array[1]->attr_value = (char *)&evtuple->dbe_owner;
	evqeu.qeu_qual = NULL;
	evqeu.qeu_qarg = NULL;
	status = qeu_get(qef_cb, &evqeu);
	if (status != E_DB_OK)
	{
	    if (evqeu.error.err_code == E_QE0015_NO_MORE_ROWS)
	    {
		(VOID)qef_error(E_QE020B_EVENT_ABSENT, 0L,
				E_DB_ERROR, &error, &qeuq_cb->error, 1,
				qec_trimwhite(sizeof(evtuple->dbe_name),
					      (char *)&evtuple->dbe_name),
				(PTR)&evtuple->dbe_name);
		error = E_QE0025_USER_ERROR;
	    }
	    else	/* Other error */
	    {
		error = evqeu.error.err_code;
	    }
	    break;
	} /* If no event found */
	
	break;
    } /* End dummy for loop */

    /* Handle any error messages */
    if (status != E_DB_OK)
    {
	(VOID) qef_error(error, 0L, status, &error, &qeuq_cb->error, 0);
    }
    else
    {
	QEUQ_CB	    dqeuq;
	STRUCT_ASSIGN_MACRO(*qeuq_cb, dqeuq);
	dqeuq.qeuq_flag_mask &= ~QEU_DROP_TEMP_TABLE;
	dqeuq.qeuq_flag_mask |= QEU_FORCE_QP_INVALIDATION;
	dqeuq.qeuq_rtbl = &evtuple_del.dbe_uniqueid;
	STRUCT_ASSIGN_MACRO(evtuple_del.dbe_txtid, dqeuq.qeuq_qid);
	dqeuq.qeuq_uld_tup = &evqef_data;
	/*
	** Check if dbevent used by alarm, if so we can't drop it
	*/
	if(qeu_ev_used_with_alarm(qef_cb, qeuq_cb, &evtuple_del.dbe_uniqueid)
				!=E_DB_OK)
	{
	        (VOID) qef_error(E_US2479_9337_ALARM_USES_EVENT, 
			0L, local_status,
			 &error, &qeuq_cb->error, 2,
			 qec_trimwhite(sizeof(evtuple->dbe_owner),
					(char*)&evtuple->dbe_owner),
			 (PTR)&evtuple->dbe_owner,
			 qec_trimwhite(sizeof(evtuple->dbe_name),
					(char*)&evtuple->dbe_name),
			 (PTR)&evtuple->dbe_name);
		error = E_QE0025_USER_ERROR;
		status=E_DB_ERROR;
	}
	
	if(status==E_DB_OK)
	{
		/*
		** perform cascading destruction - qeu_d_cascade() handles its
		** own error reporting
		*/
		STRUCT_ASSIGN_MACRO(*qeuq_cb, dqeuq);
		dqeuq.qeuq_flag_mask &= ~((i4) QEU_DROP_TEMP_TABLE);
		dqeuq.qeuq_rtbl = &evtuple_del.dbe_uniqueid;
		STRUCT_ASSIGN_MACRO(evtuple_del.dbe_txtid, dqeuq.qeuq_qid);
		dqeuq.qeuq_uld_tup = &evqef_data;

	/* perform cascading destruction of the dbevent */
	status = qeu_d_cascade(qef_cb, &dqeuq, (DB_QMODE) DB_EVENT, 
	    (DMT_TBL_ENTRY *) NULL);

		if (status != E_DB_OK)
		{
		    STRUCT_ASSIGN_MACRO(dqeuq.error, qeuq_cb->error);
		}
	}
    }

    /* Audit DROP EVENT if so far so good */
    if ( status == E_DB_OK && Qef_s_cb->qef_state & QEF_S_C2SECURE )
    {
	DB_ERROR    e_error;
	status = qeu_secaudit(FALSE, qef_cb->qef_ses_id, 
	      evtuple->dbe_name.db_ev_name, &evtuple->dbe_owner, DB_EVENT_MAXNAME,
	      SXF_E_EVENT, I_SX203C_EVENT_DROP, SXF_A_SUCCESS | SXF_A_DROP,
	      &e_error);
    }

    /* Close off all the tables and transaction */
    if (event_opened)
    {
	local_status = qeu_close(qef_cb, &evqeu);
	if (local_status != E_DB_OK)
	{
	    (VOID) qef_error(evqeu.error.err_code, 0L, local_status,
			     &error, &qeuq_cb->error, 0);
	    if (local_status > status)
		status = local_status;
	}
    }
    if (transtarted)
    {
	if (status == E_DB_OK)
	    local_status = qeu_etran(qef_cb, &tranqeu);
	else
	    local_status = qeu_atran(qef_cb, &tranqeu);
	if (local_status != E_DB_OK)
	{
	    (VOID) qef_error(tranqeu.error.err_code, 0L, local_status,
			     &error, &qeuq_cb->error, 0);
	    if (local_status > status)
		status = local_status;
	}
    }
    return (status);
} /* qeu_devent */
Ejemplo n.º 16
0
DB_STATUS
qeu_csecalarm(
QEF_CB          *qef_cb,
QEUQ_CB		    *qeuq_cb)
{
    DB_IIQRYTEXT	*qtuple;	/* Alarm text */
    DB_SECALARM    	*atuple;	/* New alarm tuple */
    DB_SECALARM    	atuple_temp;	/* Tuple to check for uniqueness */
    DB_STATUS	    	status, local_status;
    i4	    	error=0;
    bool	    	transtarted = FALSE;	    
    bool	    	tbl_opened = FALSE;
    i4		    	i;		/* Querytext tuple counter */
    QEF_DATA	    	*next;		/*	     and data pointer       */
    QEU_CB	    	tranqeu;
    QEU_CB	    	qeu;
    QEU_QUAL_PARAMS	qparams;
    DB_QRY_ID	    	qryid;		/* Ids for query text */
    QEF_DATA	    	qef_data;
    bool		loop=FALSE;
    QEF_RCB		qef_rcb;
    i4		number;
    DMR_ATTR_ENTRY  	akey_array[3];
    DMR_ATTR_ENTRY  	*akey_ptr_array[3];
    DMT_CHAR_ENTRY  	char_spec;	/* DMT_ALTER specification */
    DMT_CB	    	dmt_cb;
    DB_ERROR 		e_error;
    SXF_ACCESS		access;
    SXF_EVENT		evtype;
    DB_OWN_NAME		objowner;

    do
    {
	MEfill(sizeof(objowner),' ',(PTR)&objowner);

	/* Validate CB and parameters */
	if (qeuq_cb->qeuq_type != QEUQCB_CB ||
            qeuq_cb->qeuq_length != sizeof(QEUQ_CB))	
	{
	    status = E_DB_ERROR;
	    error = E_QE0017_BAD_CB;
	    break;
	}
	if (   qeuq_cb->qeuq_cq == 0 || qeuq_cb->qeuq_qry_tup == NULL
            || ( qeuq_cb->qeuq_uld_tup == NULL)
            || (qeuq_cb->qeuq_db_id == NULL)
            || (qeuq_cb->qeuq_d_id == 0))
	{
	    status = E_DB_ERROR;
	    error = E_QE0018_BAD_PARAM_IN_CB;
	    break;
	}
        qef_rcb.qef_cb = qef_cb;
        qef_rcb.qef_db_id = qeuq_cb->qeuq_db_id;
        qef_cb->qef_dbid = qeuq_cb->qeuq_db_id;
		
	/* 
	** Check to see if transaction is in progress, if so set a local
	** transaction, otherwise we'll use the user's transaction.
	*/
	if (qef_cb->qef_stat == QEF_NOTRAN)
	{
	    tranqeu.qeu_type = QEUCB_CB;
	    tranqeu.qeu_length = sizeof(QEUCB_CB);
	    tranqeu.qeu_db_id = qeuq_cb->qeuq_db_id;
	    tranqeu.qeu_d_id = qeuq_cb->qeuq_d_id;
	    tranqeu.qeu_flag = 0;
	    tranqeu.qeu_mask = 0;
	    status = qeu_btran(qef_cb, &tranqeu);
	    if (status != E_DB_OK)
	    {	
		error = tranqeu.error.err_code;
		break;	
	    }	    
	    transtarted = TRUE;
	}
	/* Escalate the transaction to MST */
	if (qef_cb->qef_auto == QEF_OFF)
	    qef_cb->qef_stat = QEF_MSTRAN;

	atuple = (DB_SECALARM *)qeuq_cb->qeuq_uld_tup->dt_data;

        /* For  database alarms, make sure the database exists */
	if(atuple->dba_objtype==DBOB_DATABASE &&
	   !(atuple->dba_flags&DBA_ALL_DBS))
	{
	    status=qeu_db_exists(qef_cb, qeuq_cb, 
		(DB_DB_NAME *)&atuple->dba_objname, SXF_A_CONTROL, &objowner);
	    if(status==E_DB_ERROR)
	    {
		/* Error checking database name */
		break;
	    }
	    else  if  (status==E_DB_WARN)
	    {
		/* Database not found */
		status=E_DB_ERROR;
		/* E_US2474_9332_ALARM_NO_DB */
	        (VOID)qef_error(9332, 0L, E_DB_ERROR,
			    &error, &qeuq_cb->error, 1,
			    qec_trimwhite(sizeof(atuple->dba_objname),
					  (char *)&atuple->dba_objname),
			    (PTR)&atuple->dba_objname);
		break;
	    }
	}
	else if(atuple->dba_objtype==DBOB_TABLE)
	{
	    /* 
            ** Alter the table relstat to flag alarms exist. This validates that
            ** the table exists and ensures that we get an exclusive lock on it.
            */
	    char_spec.char_id = DMT_C_ALARM;      /* create alarm code */
	    char_spec.char_value = DMT_C_ON;
	    MEfill(sizeof(DMT_CB), 0, (PTR) &dmt_cb);
	    dmt_cb.dmt_flags_mask = 0;
	    dmt_cb.dmt_db_id = qeuq_cb->qeuq_db_id;
	    dmt_cb.dmt_char_array.data_in_size = sizeof(DMT_CHAR_ENTRY);
	    dmt_cb.dmt_char_array.data_address = (PTR)&char_spec;
	    dmt_cb.length = sizeof(DMT_CB);
	    dmt_cb.type = DMT_TABLE_CB;
	    dmt_cb.dmt_id.db_tab_base  = atuple->dba_objid.db_tab_base;
	    dmt_cb.dmt_id.db_tab_index = atuple->dba_objid.db_tab_index;
	    dmt_cb.dmt_tran_id = qef_cb->qef_dmt_id;
	    status = dmf_call(DMT_ALTER, &dmt_cb);
	    if (status != E_DB_OK)
    	    {
	        error = dmt_cb.error.err_code;
	        break;
	    }
	}
	/* Get a unique query id */
	TMnow((SYSTIME *)&qryid);
	atuple->dba_txtid.db_qry_high_time = qryid.db_qry_high_time;
	atuple->dba_txtid.db_qry_low_time  = qryid.db_qry_low_time;

	/* Get a unique alarm id */
        
        status = qea_reserveID(&atuple->dba_alarmid, 
			qef_cb, &qef_rcb.error);

	if (status != E_DB_OK)
	{   
		error = qef_rcb.error.err_code;  
		break; 
	}
	/*
	** Generate an alarm name if needed, all blanks indicates no
	** name specified. This is required for uniqueness check below.
	*/
	if(!STskipblank( (char*)&atuple->dba_alarmname, 
				sizeof(atuple->dba_alarmname)))
	{
		status=qeu_gen_alarm_name(
			atuple->dba_objtype,
			(char*)&atuple->dba_objname,
			&qef_rcb,
			&atuple->dba_alarmid,
			(char*)&atuple->dba_alarmname,
			&error);
		if(status!=E_DB_OK)
			break;
	}
	/* Validate that the alarm name is unique */
	qeu.qeu_type = QEUCB_CB;
        qeu.qeu_length = sizeof(QEUCB_CB);
        qeu.qeu_tab_id.db_tab_base  = DM_B_IISECALARM_TAB_ID;
        qeu.qeu_tab_id.db_tab_index  = DM_I_IISECALARM_TAB_ID;
        qeu.qeu_db_id = qeuq_cb->qeuq_db_id;
        qeu.qeu_lk_mode = DMT_IX;
        qeu.qeu_flag = DMT_U_DIRECT;
        qeu.qeu_access_mode = DMT_A_WRITE;
	qeu.qeu_mask = 0;
	status = qeu_open(qef_cb, &qeu);
	if (status != E_DB_OK)
	{
	    error = qeu.error.err_code;
	    break;
	}
	tbl_opened = TRUE;
	atuple->dba_alarmno=0;

	/* Retrieve the same named alarm - if not there then ok */
	qeu.qeu_count = 1;
        qeu.qeu_tup_length = sizeof(DB_SECALARM);
	qeu.qeu_output = &qef_data;
	qef_data.dt_next = NULL;
        qef_data.dt_size = sizeof(DB_SECALARM);
        qef_data.dt_data = (PTR)&atuple_temp;
	qeu.qeu_getnext = QEU_REPO;
	qeu.qeu_klen = 0;				/* Not keyed */
	qparams.qeu_qparms[0] = (PTR) atuple;	/* What we're looking for */
	qeu.qeu_qual = qeu_qalarm_by_name;
	qeu.qeu_qarg = &qparams;
	status = qeu_get(qef_cb, &qeu);
	if (status == E_DB_OK)		/* Found the same alarm! */
	{
	    (VOID)qef_error(E_US2472_9330_ALARM_EXISTS, 0L, E_DB_ERROR,
			    &error, &qeuq_cb->error, 1,
			    qec_trimwhite(sizeof(atuple->dba_alarmname),
					  (char *)&atuple->dba_alarmname),
			    (PTR)&atuple->dba_alarmname);
	    error = E_QE0025_USER_ERROR;
	    break;
	}
	if (qeu.error.err_code != E_QE0015_NO_MORE_ROWS)
	{
	    /* Some other error */
	    error = qeu.error.err_code;
	    break;
	}
	status = qeu_close(qef_cb, &qeu);
	if (status != E_DB_OK)
	{
	    error = qeu.error.err_code;
	    break;
	}
	tbl_opened=FALSE;
	/*
	** Generate a unique alarm number. This is primarily for
	** backwards compatibility with "anonymous" alarms which had
	** to be dropped by number, not name.
	*/
	
	status = qeu_open(qef_cb, &qeu);
	if (status != E_DB_OK)
	{
	    error = qeu.error.err_code;
	    break;
	}
	tbl_opened = TRUE;
	qeu.qeu_count = 1;
        qeu.qeu_tup_length = sizeof(DB_SECALARM);
	qeu.qeu_input = &qef_data;
	qeu.qeu_output = &qef_data;
	qef_data.dt_next = 0;
        qef_data.dt_size = sizeof(DB_SECALARM);
        qef_data.dt_data = (PTR) &atuple_temp;
	
	qeu.qeu_getnext = QEU_REPO;
	qeu.qeu_klen = 3;       
	qeu.qeu_key = akey_ptr_array;
	akey_ptr_array[0] = &akey_array[0];
	akey_ptr_array[1] = &akey_array[1];
	akey_ptr_array[2] = &akey_array[2];

	akey_ptr_array[0]->attr_number = DM_1_IISECALARM_KEY;
	akey_ptr_array[0]->attr_operator = DMR_OP_EQ;
	akey_ptr_array[0]->attr_value = (char*) &atuple->dba_objtype;

	akey_ptr_array[1]->attr_number = DM_2_IISECALARM_KEY;
	akey_ptr_array[1]->attr_operator = DMR_OP_EQ;
	akey_ptr_array[1]->attr_value = (char*) &atuple->dba_objid.db_tab_base;
        
	akey_ptr_array[2]->attr_number = DM_3_IISECALARM_KEY;
	akey_ptr_array[2]->attr_operator = DMR_OP_EQ;
	akey_ptr_array[2]->attr_value = (char*) &atuple->dba_objid.db_tab_index;
        
	qeu.qeu_qual = 0;
	qeu.qeu_qarg = 0;
     
	/* 
        ** Get all alarm tuples for this object
        ** and determine the next alarm number.
        */
	status = E_DB_OK;
	number = 0;
	while (status == E_DB_OK)
	{
            status = qeu_get(qef_cb, &qeu);
	    if (status != E_DB_OK)
	    {
		error = qeu.error.err_code;
		break;
	    }
	    qeu.qeu_getnext = QEU_NOREPO;
            qeu.qeu_klen = 0;
	    if (atuple_temp.dba_alarmno > number)
                number = atuple_temp.dba_alarmno;
	}
	if (error != E_QE0015_NO_MORE_ROWS)
	    break;
 
	/* 
        ** We have to add 1 to derive the next alarm number.
	*/
	atuple->dba_alarmno=number+1;

	/* Save the alarm tuple */
	status = E_DB_OK;
		
	/* Insert single alarm tuple */
	qeu.qeu_count = 1;
        qeu.qeu_tup_length = sizeof(DB_SECALARM);
	qeu.qeu_input = qeuq_cb->qeuq_uld_tup;
	status = qeu_append(qef_cb, &qeu);
	if (status != E_DB_OK)
	{
	    error = qeu.error.err_code;
	    break;
	}
	status = qeu_close(qef_cb, &qeu);    
	if (status != E_DB_OK)
	{
	    error = qeu.error.err_code;
	    break;
	}
	tbl_opened = FALSE;

	/* Update all query text tuples with query id - validate list */
	next = qeuq_cb->qeuq_qry_tup;
	for (i = 0; i < qeuq_cb->qeuq_cq; i++)
	{
	    qtuple = (DB_IIQRYTEXT *)next->dt_data;
	    next = next->dt_next;
	    qtuple->dbq_txtid.db_qry_high_time = qryid.db_qry_high_time;
	    qtuple->dbq_txtid.db_qry_low_time  = qryid.db_qry_low_time;
	    if (i < (qeuq_cb->qeuq_cq -1) && next == NULL)
	    {
		error = E_QE0018_BAD_PARAM_IN_CB;
		status = E_DB_ERROR;
		break;
	    }
	} /* for all query text tuples */
	if (status != E_DB_OK)
	    break;

	/* Insert all query text tuples */
	qeu.qeu_tab_id.db_tab_base = DM_B_QRYTEXT_TAB_ID;
	qeu.qeu_tab_id.db_tab_index = 0L;
	status = qeu_open(qef_cb, &qeu);
	if (status != E_DB_OK)
	{
	    error = qeu.error.err_code;
	    break;
	}
	tbl_opened = TRUE;
	qeu.qeu_count = qeuq_cb->qeuq_cq;
        qeu.qeu_tup_length = sizeof(DB_IIQRYTEXT);
	qeu.qeu_input = qeuq_cb->qeuq_qry_tup;
	status = qeu_append(qef_cb, &qeu);
	if (status != E_DB_OK)
	{
	    error = qeu.error.err_code;
	    break;
	}
	status = qeu_close(qef_cb, &qeu);    
	if (status != E_DB_OK)
	{
	    error = qeu.error.err_code;
	    break;
	}
	tbl_opened = FALSE;
	
	if (transtarted)		   /* If we started a transaction */
	{
	    status = qeu_etran(qef_cb, &tranqeu);
	    if (status != E_DB_OK)
	    {
		error = tranqeu.error.err_code;
		break;
	    }
	}
    }
    while(loop);

    /* call qef_error to handle error messages */
    if(error)
	    (VOID) qef_error(error, 0L, status, &error, &qeuq_cb->error, 0);
    
    /* Close off all the tables. */
    local_status = E_DB_OK;
    if (tbl_opened)		    /* If system table opened, close it */
    {
	local_status = qeu_close(qef_cb, &qeu);
	if (local_status != E_DB_OK)
	{
	    (VOID) qef_error(qeu.error.err_code, 0L, local_status, &error, 
		    	     &qeuq_cb->error, 0);
	    if (local_status > status)
		status = local_status;
	}
    }

    if (transtarted)		   /* If we started a transaction */
    {
        local_status = qeu_atran(qef_cb, &tranqeu);
        if (local_status != E_DB_OK)
	{
	    (VOID) qef_error(tranqeu.error.err_code, 0L, local_status, 
			     &error, &qeuq_cb->error, 0);
	    if (local_status > status)
		status = local_status;
	}
    }
  
    if ( Qef_s_cb->qef_state & QEF_S_C2SECURE )
    {
	if(atuple->dba_objtype==DBOB_DATABASE)
	{
	    evtype=SXF_E_DATABASE;
	}
	else
	{
	    evtype=SXF_E_TABLE;
	}
	/*
	** Creating an alarm is a control operation on the base object
	** (database/table)
	*/
	if(status==E_DB_OK)
	    access=(SXF_A_CONTROL|SXF_A_SUCCESS);
	else
	    access=(SXF_A_CONTROL|SXF_A_FAIL);
	if(qeu_secaudit(FALSE, qef_cb->qef_ses_id,
		    (char *)&atuple->dba_objname,
		    &objowner,
		    sizeof(atuple->dba_objname),
		    evtype,
		    I_SX202D_ALARM_CREATE,
		    access,
		    &e_error)!=E_DB_OK)
	{
		error = e_error.err_code;
		status=E_DB_ERROR;
	}
    }

    /*
    ** Log QEF create error
    */
    if(status!=E_DB_OK)
    {
    	(VOID) qef_error(E_QE028B_CREATE_ALARM_ERR, 0L, local_status, 
		     &error, &qeuq_cb->error, 0);
	qeuq_cb->error.err_code= E_QE0025_USER_ERROR;
    }
    return (status);
} /* qeu_csecalarm */
Ejemplo n.º 17
0
/*
** Name: qeu_evraise
**
** Description:
**	This routine raises an event, it processes the external request
**	QEU_RAISE_EVENT, typically when raising the event associated with
**	a security alarm.
**
**	Note this *does* do event tracing (SET PRINTEVENTS/LOGEVENTS)
**	but does *not* do security checks/auditing on the operation, this
**	is assumed to be handled at a higher level.
**
** Inputs:
**	qef_rcb.evname   - Event name
**	qef_rcb.evowner  - Event owner
**	qef_rcb.evtext   - Event text 
**	qef_rcb.ev_l_text- Length of text
**
** History:
**	26-nov-93 (robf)
**         Created for secure 2.0
**	12-Jan-1998 (kinpa04/merja01)
**		Remove (i4) casting of session id.  This caused the 
**		session ID to get truncated on axp_osf while raising events.
**	10-Jan-2001 (jenjo02)
**	    We know this session's id; pass it to SCF.
**	30-Dec-2005 (kschendel)
**	    Update call to qef-adf-error.
**
*/
DB_STATUS
qeu_evraise(
	QEF_CB  *qef_cb,
	QEF_RCB *qef_rcb
)
{
    DB_DATA_VALUE tm;					/* Timestamp */
    DB_DATE	tm_date;
    SCF_ALERT	scfa;					
    SCF_CB	scf_cb;				
    SCF_SCI		sci_list[1];
    DB_ALERT_NAME alert;
    i4	err;
    char	*errstr;
    DB_STATUS   status=E_DB_OK;
    i4	tr1 = 0, tr2 = 0;			/* Dummy trace values */

    /*
    ** Build alert name
    */
    STRUCT_ASSIGN_MACRO(*qef_rcb->qef_evname, alert.dba_alert);
    STRUCT_ASSIGN_MACRO(*qef_rcb->qef_evowner, alert.dba_owner);

    scf_cb.scf_length	= sizeof(SCF_CB);
    scf_cb.scf_type	= SCF_CB_TYPE;
    scf_cb.scf_facility	= DB_QEF_ID;
    scf_cb.scf_session	= qef_cb->qef_ses_id;

    /* Get the database name */
    scf_cb.scf_ptr_union.scf_sci   = (SCI_LIST *) sci_list;
    scf_cb.scf_len_union.scf_ilength = 1;
    sci_list[0].sci_length  = sizeof(DB_DB_NAME);
    sci_list[0].sci_code    = SCI_DBNAME;
    sci_list[0].sci_aresult = (char *) &alert.dba_dbname;
    sci_list[0].sci_rlength = NULL;
    status = scf_call(SCU_INFORMATION, &scf_cb);
    if (status != E_DB_OK)
    {
         _VOID_ qef_error(E_QE022F_SCU_INFO_ERROR, 0L, status, &err,
			     &qef_rcb->error, 0);
	return E_DB_ERROR;
    }

    /* Format SCF event request block */
    scf_cb.scf_ptr_union.scf_alert_parms = &scfa;

    scfa.scfa_name = &alert;
    scfa.scfa_text_length = 0;
    scfa.scfa_user_text = NULL;
    scfa.scfa_flags = 0;

    if (qef_rcb->qef_ev_l_text > 0)		/* No need for empty strings */
    {
	if (qef_rcb->qef_ev_l_text > DB_EVDATA_MAX)
	    qef_rcb->qef_ev_l_text = DB_EVDATA_MAX;
	scfa.scfa_text_length = qef_rcb->qef_ev_l_text;
	scfa.scfa_user_text = qef_rcb->qef_evtext;
    }
    tm.db_datatype = DB_DTE_TYPE; 	/* Get time stamp for the event */
    tm.db_prec = 0;
    tm.db_length = sizeof(tm_date);
    tm.db_data = (PTR)&tm_date;
    tm.db_collID = -1;
    status = adu_datenow(qef_cb->qef_adf_cb, &tm);
    if (status != E_DB_OK)
    {
	    if ((status = qef_adf_error(&qef_cb->qef_adf_cb->adf_errcb,
			status, qef_cb, &qef_rcb->error)) != E_DB_OK)
		return (status);
    }
    scfa.scfa_when = &tm_date;

    /* If tracing and/or logging events then display event information */
    if (ult_check_macro(&qef_cb->qef_trace, QEF_T_EVENTS, &tr1, &tr2))
         qea_evtrace(qef_rcb, QEF_T_EVENTS, &alert, &tm, 
			(i4)qef_rcb->qef_ev_l_text,
			(char*)qef_rcb->qef_evtext);

    if (ult_check_macro(&qef_cb->qef_trace, QEF_T_LGEVENTS, &tr1, &tr2))
        qea_evtrace(qef_rcb, QEF_T_LGEVENTS, &alert, &tm, 0, (char *)NULL);

    /*
    ** Raise the event in SCF
    */
    status = scf_call(SCE_RAISE, &scf_cb);
    if (status != E_DB_OK)
    {
	char	*enm, *onm;	/* Event and owner names */

	enm = (char *)&alert.dba_alert;
	onm = (char *)&alert.dba_owner;
	errstr="RAISE";
	switch (scf_cb.scf_error.err_code)
	{
	  case E_SC0270_NO_EVENT_MESSAGE:
	    _VOID_ qef_error(E_QE019A_EVENT_MESSAGE, 0L, status, &err,
			     &qef_rcb->error, 1,
			     (i4)STlength(errstr), errstr);
	    break;
	  case E_SC0280_NO_ALERT_INIT:
	    _VOID_ qef_error(E_QE0200_NO_EVENTS, 0L, status, &err,
			     &qef_rcb->error, 1,
			     (i4)STlength(errstr), errstr);
	    break;
	  default:
	    _VOID_ qef_error(E_QE020F_EVENT_SCF_FAIL, 0L, status, &err,
			     &qef_rcb->error, 4,
			     (i4)STlength(errstr), errstr,
			     (i4)sizeof(i4),
					(PTR)&scf_cb.scf_error.err_code,
			     qec_trimwhite(DB_OWN_MAXNAME, onm), onm,
			     qec_trimwhite(DB_EVENT_MAXNAME, enm), enm);
	    break;
	}
	qef_rcb->error.err_code = E_QE0025_USER_ERROR;
	status = E_DB_ERROR;
    } /* If SCF not ok */
    return status;
}
Ejemplo n.º 18
0
/*{
** Name: QEU_REPLACE     - replace tuple(s) in a table
**
** External QEF call:   status = qef_call(QEU_REPLACE, &qeu_cb);
**
** Description:
**      A tuple is replaced in a table opened with the QEU_OPEN
** command.
** If QEU_BY_TID is specified,
**	the tuple with specified TID is repalced
** else if qeu_cb->kqeu_klen > 0
**	qeu_f_qual points to a function which will both determine whether the
**	tuple should be updated and make appropriate changes to the tuple
**      passed to it
** else
**	replace the tuple which was read by position as specified by the caller
**
** Inputs:
**       qeu_cb
**	    .qeu_eflag			    designate error handling semantis
**					    for user errors.
**		QEF_INTERNAL		    return error code.
**		QEF_EXTERNAL		    send message to user.
**          .qeu_acc_id                     table access id
**          .qeu_tup_length                 lenth of a tuple
**          .qeu_input                      buffer containing new values for the
**					    tuple being replaced
**	    .qeu_qual			    qualification function for DMF
**	    .qeu_qarg			    argument to (*qeu_qual) ()
**          .qeu_klen                       length of key 
**          .qeu_key                        key for update
**      <qeu_key> is a pointer to an array of pointers of type DMR_ATTR_ENTRY
**              .attr_number
**              .attr_operation
**              .attr_value_ptr
**	    .qeu_flag			    operation qualifier
**		QEU_BY_TID		    replace tuple whose TID is in
**					    qeu_tid
**	    .qeu_tid			    contains TID of the tuple to be
**					    replaced if (qeu_flag & QEU_BY_TID)
**	    .qeu_f_qual			    if !(qeu_klen > 0) this must point
**					    at a function which will decide
**					    whether and how the current tuple
**					    must be replaced
**	    .qeu_f_qarg			    argument to (*qeu_f_qual) ()
**	    
** Outputs:
**      qeu_cb
**	    .qeu_count			    number of tuples updated
**          .error.err_code                 One of the following
**                                          E_QE0000_OK
**                                          E_QE0002_INTERNAL_ERROR
**                                          E_QE0004_NO_TRANSACTION
**                                          E_QE0007_NO_CURSOR
**                                          E_QE0017_BAD_CB
**                                          E_QE0018_BAD_PARAM_IN_CB
**      Returns:
**          E_DB_OK
**          E_DB_ERROR                      caller error
**          E_DB_FATAL                      internal error
**      Exceptions:
**          none
**
** Side Effects:
**          none
**
** History:
**      18-jun-92 (andre)
**          written
**	22-jun-92 (andre)
**	    changed the function to allow update one row by tid or to update
**	    multiple rows subject to qualification function
**	24-jun-92 (andre)
**	    another change to allow update of prepositioned tuple
**	13-sep-93 (robf)
**	    Extended to handle update multiple rows without
**	    requiring a key position. This is signalled when qeu_klen==0
**	    and qeu_qual != NULL and qeu_f_qual!=NULL
**	30-nov-93 (robf)
**          When updating multiple rows, keep going after first update.
**	24-Jan-2001 (jenjo02)
**	    Ensure that memory stream is closed before returning.
**	11-Apr-2008 (kschendel)
**	    Revised DMF qualification requirements, simplified for QEU.
*/
DB_STATUS
qeu_replace(
QEF_CB          *qef_cb,
QEU_CB          *qeu_cb)
{
    i4		    err = 0L;
    DMR_CB		    dmr_cb;
    DB_STATUS		    status;
    GLOBALREF QEF_S_CB	    *Qef_s_cb;
    ULM_RCB		    ulm;
    i4			    (*repl_func)(void *, void *);
    bool		    position_all=FALSE;
    bool		    mem_opened=FALSE;

    if (qeu_cb->qeu_flag & QEU_BY_TID)
    {
	/*
	** if update_by_tid, no key(s), qualification function, or qualification
	** function parameters should be passed;
	** qeu_cb->qeu_input must point at a structure containing a ptr to the
	** new value for the tuple of specified size
	*/
	if (qeu_cb->qeu_klen || qeu_cb->qeu_qual || qeu_cb->qeu_qarg ||
	    qeu_cb->qeu_f_qual || qeu_cb->qeu_f_qarg || !qeu_cb->qeu_input ||
	    !qeu_cb->qeu_input->dt_data || !qeu_cb->qeu_input->dt_size)
	{
	    err = E_QE0018_BAD_PARAM_IN_CB;
	    status = E_DB_ERROR;
	}
    }
    else if (qeu_cb->qeu_klen==0 &&  
	    (repl_func = qeu_cb->qeu_f_qual) != NULL &&
	    qeu_cb->qeu_qual)
    {
	position_all=TRUE;
	/*
	** Request to replace all qualifying in table, without key 
	** positioning
	*/
	if (!qeu_cb->qeu_qarg || 
	    !qeu_cb->qeu_f_qarg 
	    )
	{
	    err = E_QE0018_BAD_PARAM_IN_CB;
	    status = E_DB_ERROR;
	}
    }
    else if (qeu_cb->qeu_klen == 0)
    {
	/*
	** if asked to update the current tuple, no qualification function, or
	** qualification function parameters should be passed;
	** qeu_cb->qeu_input must point at a structure containing a ptr to
	** the new value for the tuple of specified size
	*/
	if (qeu_cb->qeu_qual || qeu_cb->qeu_qarg || qeu_cb->qeu_f_qual ||
	    qeu_cb->qeu_f_qarg || !qeu_cb->qeu_input ||
	    !qeu_cb->qeu_input->dt_data || !qeu_cb->qeu_input->dt_size)
	{
	    err = E_QE0018_BAD_PARAM_IN_CB;
	    status = E_DB_ERROR;
	}
    }
    else if ((repl_func = qeu_cb->qeu_f_qual) == NULL)
    {
	/*
	** if caller supplied a key, must specify the function which
	** will determine whether and how the tuple must be updated
	*/
	err = E_QE0018_BAD_PARAM_IN_CB;
	status = E_DB_ERROR;
    }

    if (err)
    {
	(VOID) qef_error(err, 0L, status, &err, &qeu_cb->error, 0);
	return(status);
    }

    qeu_cb->qeu_count = 0;
    qeu_cb->error.err_code = E_QE0000_OK;

    /* QEU_REPLACE is only valid in a transaction */
    if (qef_cb->qef_stat == QEF_NOTRAN)
    {
        qef_error(E_QE0004_NO_TRANSACTION, 0L, E_DB_ERROR, &err,
            &qeu_cb->error, 0);
        return (E_DB_ERROR);
    }

    dmr_cb.type                 = DMR_RECORD_CB;
    dmr_cb.length               = sizeof(DMR_CB);
    dmr_cb.dmr_access_id        = qeu_cb->qeu_acc_id;
    dmr_cb.dmr_q_fcn		= NULL;

    /* if replacing by key, position the cursor */
    if (qeu_cb->qeu_klen || position_all)
    {
	/* allocate memory for a tuple only if planning to call qeu_get() */
	
	STRUCT_ASSIGN_MACRO(Qef_s_cb->qef_d_ulmcb, ulm);
	/* Open stream and allocate tuple memory in one action */
	ulm.ulm_flags = ULM_PRIVATE_STREAM | ULM_OPEN_AND_PALLOC;
	ulm.ulm_psize = ulm.ulm_blocksize = qeu_cb->qeu_tup_length;

	if ((status = qec_mopen(&ulm)) != E_DB_OK)
	{
	    qef_error(E_QE001E_NO_MEM, 0L, E_DB_ERROR, &err,
		&qeu_cb->error, 0);
	    return (status);
	}
	mem_opened=TRUE;

        /* set the keys */
	if(position_all)
	{
		dmr_cb.dmr_position_type = DMR_ALL;
	}
	else
	{
		dmr_cb.dmr_position_type = DMR_QUAL;
		dmr_cb.dmr_attr_desc.ptr_address    = (PTR) qeu_cb->qeu_key;
		dmr_cb.dmr_attr_desc.ptr_in_count   = qeu_cb->qeu_klen;
		dmr_cb.dmr_attr_desc.ptr_size	    = sizeof (DMR_ATTR_ENTRY);
		dmr_cb.dmr_s_estimated_records	    = -1;
	}
        /* row qualifier */
        dmr_cb.dmr_q_fcn = (DB_STATUS (*)(void *,void *)) qeu_cb->qeu_qual;
        dmr_cb.dmr_q_arg = (PTR) qeu_cb->qeu_qarg;
	if (qeu_cb->qeu_qual != NULL)
	{
	    dmr_cb.dmr_q_rowaddr = &qeu_cb->qeu_qarg->qeu_rowaddr;
	    dmr_cb.dmr_q_retval = &qeu_cb->qeu_qarg->qeu_retval;
	}
	dmr_cb.dmr_flags_mask = 0;
        status = dmf_call(DMR_POSITION, &dmr_cb);
        if (status != E_DB_OK)
        {
	    ulm_closestream(&ulm);

	    if (dmr_cb.error.err_code == E_DM0055_NONEXT)
		return (E_DB_OK);
            qef_error(dmr_cb.error.err_code, 0L, status, &err, &qeu_cb->error, 0);
            return (status);
        }

	/* the tuple length will not change. Tell DMF about it */
	dmr_cb.dmr_data.data_in_size = qeu_cb->qeu_tup_length;
	dmr_cb.dmr_data.data_address = ulm.ulm_pptr;
    }
    else
    {
	/*
	** make dmr_data point at the new value for the tuple
	*/
	dmr_cb.dmr_data.data_address = qeu_cb->qeu_input->dt_data;
	dmr_cb.dmr_data.data_in_size = qeu_cb->qeu_input->dt_size;

	/*
	** if (qeu_flag & QEU_BY_TID)
	**    indicate to dmr_replace() that we are replacing by tid
	** else
	**    indicate to dmr_replace to replace the current tuple
	*/

	if (qeu_cb->qeu_flag & QEU_BY_TID)
	{	
	    dmr_cb.dmr_flags_mask = DMR_BY_TID;
	    dmr_cb.dmr_tid = qeu_cb->qeu_tid;
	}
	else
	{
	    dmr_cb.dmr_flags_mask = DMR_CURRENT_POS;
	}
    }

    for (;;)
    {
        if (qeu_cb->qeu_klen || position_all)
	{
	    i4	ret_val;

            /* get the tuple */
            dmr_cb.dmr_flags_mask = DMR_NEXT;
            status = dmf_call(DMR_GET, &dmr_cb);
            if (status != E_DB_OK)
            {
                if (dmr_cb.error.err_code == E_DM0055_NONEXT)
		{
		    status = E_DB_OK;
		}
		else
		{
		    err = dmr_cb.error.err_code;
		}
                break;
            }

	    /*
	    ** let caller's function determine whether and how the tuple must be
	    ** changed; QEU_F_RETURN indicates that we must proceed; QEU_F_NEXT
	    ** says "skip this tuple"
	    */
	    ret_val = (*repl_func) (dmr_cb.dmr_data.data_address,
		qeu_cb->qeu_f_qarg);

	    if (ret_val != QEU_F_RETURN)
	    {
		continue;
	    }

	    /* will replace the current tuple */
	    dmr_cb.dmr_flags_mask = DMR_CURRENT_POS;
	}

	dmr_cb.dmr_attset = NULL;
	status = dmf_call(DMR_REPLACE, &dmr_cb);
	if (status != E_DB_OK)
	{
	    err = dmr_cb.error.err_code;
	    break;
	}
	else
	{
	    qeu_cb->qeu_count++;
	}

	if (qeu_cb->qeu_klen == 0 && !position_all)
	{
	    /* we were replacing a tuple by tid and are done */
	    break;
	}
    }

    if (status != E_DB_OK)
    {
	qef_error(err, 0L, status, &err, &qeu_cb->error, 0);
    }

    if (mem_opened)
    {
	/* don't try to close a stream unless it was opened */
	ulm_closestream(&ulm);
    }
    
    return (status);
}