Esempio n. 1
0
/*{
** Name: opv_varnode	- make a range variable node
**
** Description:
**      This procedure allocates and initializes a query tree PST_VAR node.
**
** Inputs:
**      global                          ptr to global state variable
**      datavalue                       datatype info of node to create
**      variable                        range variable number - index
**                                      into the global range table
**      attribute                       dmf attribute of range variable to be
**					assigned to var node.
**
** Outputs:
**	Returns:
**	    ptr to PST_QNODE initialized to be a var node
**	Exceptions:
**	    none
**
** Side Effects:
**	    none
**
** History:
**	8-apr-86 (seputis)
**          initial creation
**	9-jul-91 (seputis)
**	    remove obsolete trace point
[@history_line@]...
*/
PST_QNODE *
opv_varnode(
	OPS_STATE          *global,
	DB_DATA_VALUE      *datatype,
	OPV_IGVARS         variable,
	DB_ATT_ID	   *dmfattr)
{
    register PST_QNODE *qnode;      /* ptr used for symbol allocation */

    qnode = (PST_QNODE *) opu_memory( global, (i4) sizeof(PST_QNODE));
                                    /* allocate storage for query tree node
                                    ** to be used for creation of var node
                                    */
    qnode->pst_left = NULL;
    qnode->pst_right = NULL;
    qnode->pst_sym.pst_type = PST_VAR; /* create VAR node type */
    STRUCT_ASSIGN_MACRO(*datatype, qnode->pst_sym.pst_dataval);
    qnode->pst_sym.pst_dataval.db_data = NULL;
    qnode->pst_sym.pst_len = sizeof(PST_VAR_NODE);
    qnode->pst_sym.pst_value.pst_s_var.pst_vno = variable;
    STRUCT_ASSIGN_MACRO(*dmfattr, qnode->pst_sym.pst_value.pst_s_var.pst_atno);
    MEfill(sizeof(qnode->pst_sym.pst_value.pst_s_var.pst_atname), ' ', 
	(PTR)&qnode->pst_sym.pst_value.pst_s_var.pst_atname); /* init attribute
				    ** name */
    return( qnode );
}
Esempio n. 2
0
/*{
** Name: opu_compare	- compare two values with the same type
**
** Description:
**      This routine will compare two values of the same type.
**
** Inputs:
**      global                          ptr to global state variable
**      vp1                             ptr to first value
**      vp2                             ptr to second value
**      datatype                        ptr to datatype info on values
**
** Outputs:
**	Returns:
**	    -1 if vp1 < vp2
**          0  if vp1 = vp2
**          1  if vp1 > vp2
**	Exceptions:
**	    none
**
** Side Effects:
**	    none
**
** History:
**	21-jun-86 (seputis)
**          initial creation
[@history_line@]...
*/
i4
opu_compare(
	OPS_STATE          *global,
	PTR                vp1,
	PTR                vp2,
	DB_DATA_VALUE      *datatype)
{
    i4			adc_cmp_result;
    DB_DATA_VALUE	vpdv1;
    DB_DATA_VALUE	vpdv2;
    DB_STATUS		comparestatus;

    STRUCT_ASSIGN_MACRO(*datatype, vpdv1);
    STRUCT_ASSIGN_MACRO(vpdv1, vpdv2);
    vpdv2.db_data = vp2;
    vpdv1.db_data = vp1;
    comparestatus = adc_compare(global->ops_adfcb, &vpdv1, &vpdv2,
	&adc_cmp_result);
# ifdef E_OP078C_ADC_COMPARE
    if (comparestatus != E_DB_OK)
	opx_verror( comparestatus, E_OP078C_ADC_COMPARE, 
	    global->ops_adfcb->adf_errcb.ad_errcode);
# endif
    return (adc_cmp_result);
}
Esempio n. 3
0
DB_STATUS
qee_d9_undefall(
    QEF_RCB		*qef_rcb)
{
    DB_STATUS	    status = E_DB_OK,
                    sav_status = E_DB_OK;
    DB_ERROR	    sav_error;
    QES_DDB_SES	    *dds_p = & qef_rcb->qef_cb->qef_c2_ddb_ses;
    PTR		    qso_handle;
    QES_RPT_HANDLE  *hand_p;
    i4		    i;


    for (i = 0, hand_p = dds_p->qes_d12_handle_p;
            hand_p != (QES_RPT_HANDLE *) NULL;
            ++i, hand_p = hand_p->qes_2_next)
    {
        status = qee_d8_undefrpt(qef_rcb, hand_p->qes_3_qso_handle);
        if (status)
        {
            sav_status = status;
            STRUCT_ASSIGN_MACRO(qef_rcb->error, sav_error);
        }
    }

    if (status == E_DB_OK && sav_status)
    {
        status = sav_status;
        STRUCT_ASSIGN_MACRO(sav_error, qef_rcb->error);
    }
    return(status);
}
Esempio n. 4
0
/*{
** Name: psy_create_synonym - Insert a tuple into IISYNONYM.
**
** Description:
**	Call RDF_UPDATE to insert a tuple into IISYNONYM.
** Inputs:
**	psy_cb		PSY control block.
**	sess_cb		PSF session control block.
** Outputs:
**	Exceptions:
**	    none
** Returns:
**	E_DB_OK			synonym tuple has been inserted successfully;
**	error status from RDF	otherwise
**
** Side Effects:
**	    Modifies system catalogs.
**
** History:
**      19-apr-90 (andre)
**	    Created.
**      22-may-90 (teg)
**          init rdr_instr to RDF_NO_INSTR
**	03-aug-92 (barbara)
**	    Invalidate base object's infoblk from the RDF cache.
**	10-aug-93 (andre)
**	    fixed causes of compiler warnings
*/
DB_STATUS
psy_create_synonym(
	PSY_CB	   *psy_cb,
	PSS_SESBLK *sess_cb)
{
    RDF_CB		rdf_cb;
    register RDR_RB	*rdf_rb = &rdf_cb.rdf_rb;
    DB_STATUS		status;
    i4		err_code;

    /* Initialize the RDF request block. */
    pst_rdfcb_init(&rdf_cb, sess_cb);
    STRUCT_ASSIGN_MACRO(sess_cb->pss_user, rdf_rb->rdr_owner);
    rdf_rb->rdr_2types_mask = (RDF_TYPES) RDR2_SYNONYM;
    rdf_rb->rdr_update_op = RDR_APPEND;
    rdf_rb->rdr_qrytuple = psy_cb->psy_tupptr;
    rdf_rb->rdr_tabid.db_tab_base = DM_B_SYNONYM_TAB_ID;
    rdf_rb->rdr_tabid.db_tab_index = DM_I_SYNONYM_TAB_ID;

    /* Insert a tuple into IISYNONYM */
    status = rdf_call(RDF_UPDATE, (PTR) &rdf_cb);

    if (DB_FAILURE_MACRO(status))
    {
	if (rdf_cb.rdf_error.err_code == E_RD0143_CREATE_SYNONYM)
	{
	    DB_IISYNONYM	*syn = (DB_IISYNONYM *) psy_cb->psy_tupptr;
	    
	    (VOID) psf_error(E_PS0454_CREATE_SYN_ERROR, 0L, PSF_USERERR,
		&err_code, &psy_cb->psy_error, 1,
		psf_trmwhite(sizeof(DB_SYNNAME), (char *) &syn->db_synname),
		&syn->db_synname);
	}
	else
	{
	    (VOID) psf_rdf_error(RDF_UPDATE, &rdf_cb.rdf_error,
		&psy_cb->psy_error);
	}

	return (status);
    }

    /* Invalidate the base object's info block from the RDF cache */
    {
	DB_IISYNONYM	*syn_tuple = (DB_IISYNONYM *) psy_cb->psy_tupptr;

	pst_rdfcb_init(&rdf_cb, sess_cb);
	STRUCT_ASSIGN_MACRO(syn_tuple->db_syntab_id, rdf_rb->rdr_tabid);

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

	if (DB_FAILURE_MACRO(status))
	{
	    (VOID) psf_rdf_error(RDF_INVALIDATE, &rdf_cb.rdf_error,
				&psy_cb->psy_error);
	}
    }
    return (status);
}
Esempio n. 5
0
DB_STATUS
qeq_a2_fetch(
    QEF_RCB		*v_qer_p,
    QEF_AHD		*i_act_p,
    bool		*o_tupread_p,
    bool		*o_eod_p )
{
    DB_STATUS	    status,
                    ignore;
    DB_ERROR	    sav_error;
    QEE_DSH	    *dsh_p = (QEE_DSH *)(v_qer_p->qef_cb->qef_dsh);
    QEE_DDB_CB	    *qee_p = dsh_p->dsh_ddb_cb;
    QES_DDB_SES	    *dds_p = & v_qer_p->qef_cb->qef_c2_ddb_ses;
    QEQ_D1_QRY	    *sub_p = & i_act_p->qhd_obj.qhd_d1_qry;
    RQR_CB	    rqr,
                *rqr_p = & rqr;
    RQB_BIND	    *bind;


    MEfill(sizeof(rqr), '\0', (PTR) & rqr);

    rqr_p->rqr_session = dds_p->qes_d3_rqs_p;   /* RQF session id */
    rqr_p->rqr_q_language = sub_p->qeq_q1_lang;
    rqr_p->rqr_timeout = sub_p->qeq_q2_quantum;
    rqr_p->rqr_1_site = sub_p->qeq_q5_ldb_p;
    rqr_p->rqr_col_count = sub_p->qeq_q6_col_cnt;
    rqr_p->rqr_bind_addrs = (RQB_BIND *) qee_p->qee_d9_bind_p;
    /* must use invariant array */
    status = qed_u3_rqf_call(RQR_T_FETCH, rqr_p, v_qer_p);
    if (status)
    {
        /* must flush before returning */

        STRUCT_ASSIGN_MACRO(v_qer_p->error, sav_error);
        ignore = qeq_a3_flush(v_qer_p, sub_p->qeq_q5_ldb_p);
        STRUCT_ASSIGN_MACRO(sav_error, v_qer_p->error);
        return(status);
    }

    bind = rqr_p->rqr_bind_addrs;

    /* fix for b55503  FIXME: more general fix needed */
    if(bind->rqb_r_dt_id < 0 && bind->rqb_addr[bind->rqb_length-1] > 0)
    {
        /* nullable and null byte on */
        MEfill(bind->rqb_length-1, '\0', (PTR) bind->rqb_addr);
    }

    *o_eod_p = rqr_p->rqr_end_of_data;
    *o_tupread_p = ! rqr_p->rqr_end_of_data;

    return(E_DB_OK);
}
Esempio n. 6
0
DB_STATUS
qeu_d2_des_tab(
QEF_RCB		*v_qer_p)
{
    DB_STATUS		status;
/*
    QES_DDB_SES		*dds_p = & v_qer_p->qef_cb->qef_c2_ddb_ses;
*/
    QEF_DDB_REQ	    	*ddr_p = & v_qer_p->qef_r3_ddb_req;
    QED_QUERY_INFO	*ddq_p = & ddr_p->qer_d4_qry_info;
    QED_DDL_INFO	*ddl_p = & ddr_p->qer_d7_ddl_info;
    DD_1LDB_INFO	ldb_info,
			*ldb_p = & ldb_info;


    /* 1.  execute DESTROY TABLE statement */

    STRUCT_ASSIGN_MACRO(*ddl_p->qed_d5_qry_info_p, *ddq_p);
    STRUCT_ASSIGN_MACRO(ddl_p->qed_d6_tab_info_p->dd_t9_ldb_p->dd_i1_ldb_desc,
	ldb_p->dd_i1_ldb_desc);
    ddr_p->qer_d2_ldb_info_p = ldb_p;

    /* 2.  execute DESTROY TABLE statement */

    status = qed_e4_exec_qry(v_qer_p);    
    if (status)
    {
	/* forgive error */

	status = qed_u9_log_forgiven(v_qer_p);
	if (status)
	    return(status);
    }

    /* 3.  destroy the link and hence all dependent views */

    status = qel_d0_des_lnk(v_qer_p);
    if (status)
    {
	/* forgive error */

	status = qed_u9_log_forgiven(v_qer_p);
	if (status)
	    return(status);
    }

    return(E_DB_OK);
}    
Esempio n. 7
0
/*{
** Name: opj_uvar	- get the attribute number of the union view var node
**
** Description:
**      This routine will calculate the attribute number of the union view 
**      given the equivalence class of this var node 
**
** Inputs:
**      subquery                        ptr to subquery containing equivalence
**					class of var node
**      qual                            ptr to var node
**
** Outputs:
**      attidp                          ptr to attribute ID for union view
**	Returns:
**	Exceptions:
**	    none
**
** Side Effects:
**	    none
**
** History:
**      28-jun-89 (seputis)
**          initial creation
[@history_template@]...
*/
static VOID
opj_uvar(
	OPS_SUBQUERY       *subquery,
	PST_QNODE          *qual,
	OPV_IVARS	   varno,
	DB_ATT_ID	   *attidp)
{
    OPZ_BMATTS	    *attrmap;	/* bit map of attributes in the
			    ** equivalence class */
    OPZ_IATTS	    attno;  /* attribute currently being looked at */
    OPZ_IATTS	    maxattr; /* maximum attribute */
    OPZ_AT	    *abase;

    maxattr = subquery->ops_attrs.opz_av;
    abase = subquery->ops_attrs.opz_base;   /* ptr to base of array of ptrs
				** to joinop attributes */
    attrmap = &subquery->ops_eclass.ope_base->ope_eqclist
	[subquery->ops_attrs.opz_base->opz_attnums
	    [qual->pst_sym.pst_value.pst_s_var.pst_atno.db_att_id
	    ]->opz_equcls
	]->ope_attrmap;
    for (attno = -1; 
	 (attno = BTnext((i4)attno, (char *)attrmap, maxattr)
	 ) >= 0;)
    {
	if (abase->opz_attnums[attno]->opz_varnm == varno)
	{   /* found the union view attribute number so copy it in */
	    STRUCT_ASSIGN_MACRO(abase->opz_attnums[attno]->opz_attnm, *attidp);
	    break;
	}
    }
    if (attno < 0)
	opx_error(E_OP0384_NOATTS); /* attribute not found when
			    ** expected */
}
Esempio n. 8
0
DB_STATUS
psy_csequence(
	PSY_CB	   *psy_cb,
	PSS_SESBLK *sess_cb)
{
    RDF_CB		rdf_cb;
    RDR_RB		*rdf_rb = &rdf_cb.rdf_rb;
    DB_STATUS		status;

    /* Assign user */
    STRUCT_ASSIGN_MACRO(sess_cb->pss_user,
			psy_cb->psy_tuple.psy_sequence.dbs_owner);

    /* zero out RDF_CB and init common elements */
    pst_rdfcb_init(&rdf_cb, sess_cb);

    rdf_rb->rdr_l_querytext	= 0;
    rdf_rb->rdr_querytext	= NULL; 

    rdf_rb->rdr_2types_mask  = RDR2_SEQUENCE;		/* Sequence definition */
    rdf_rb->rdr_update_op   = RDR_APPEND;
    rdf_rb->rdr_qrytuple    = (PTR)&psy_cb->psy_tuple.psy_sequence; /* sequence tup */

    /* Create new sequence in iisequence */
    status = rdf_call(RDF_UPDATE, (PTR) &rdf_cb);   
    if (status != E_DB_OK)
    {
	_VOID_ psf_rdf_error(RDF_UPDATE, &rdf_cb.rdf_error, &psy_cb->psy_error);
    } /* If RDF error */

    return (status);
} /* psy_csequence */
Esempio n. 9
0
DB_STATUS
qee_d6_malloc(
    i4		i_space,
    QEF_RCB		*qef_rcb,
    PTR		*o_pp)
{
    GLOBALREF	    QEF_S_CB *Qef_s_cb;
    QEF_CB	    *qef_cb = qef_rcb->qef_cb;
    DB_STATUS	    status = E_DB_OK;
    ULM_RCB	    ulm;


    o_pp = (PTR *) NULL;

    /* allocate space in QEF memory */

    STRUCT_ASSIGN_MACRO(Qef_s_cb->qef_d_ulmcb, ulm);

    /* 1.  allocate from session's stream */

    ulm.ulm_streamid_p = &qef_cb->qef_c3_streamid;
    ulm.ulm_psize = i_space;
    if (status = qec_malloc(&ulm))
    {
        qef_rcb->error.err_code = ulm.ulm_error.err_code;
        return(status);
    }
    qef_cb->qef_c4_streamsize += i_space;
    o_pp =  (PTR *) ulm.ulm_pptr;


    return(E_DB_OK);
}
Esempio n. 10
0
/*{
** Name: ops_gqtree	- get query tree from QSF
**
** Description:
**      This procedure will get a query tree from QSF
**      and initialize the global QSF control block
**
** Inputs:
**      global                          ptr to global state variable
**
** Outputs:
**      global->ops_qsfcb               initialized
**	Returns:
**	    QSF status
**	Exceptions:
**	    none
**
** Side Effects:
**	    none
**
** History:
**      26-jan-88 (seputis)
**          initial creation
**	 7-jan-94 (swm)
**	    Bug #58635
**	    Added PTR cast for qsf_owner which has changed type to PTR.
**	10-Jan-2001 (jenjo02)
**	    Initialize qsf_sid with session's SID.
[@history_template@]...
*/
DB_STATUS
ops_gqtree(
	OPS_STATE          *global)
{
    /* get the query tree from QSF */
    DB_STATUS	       qsfstatus;  /* QSF return status */

    global->ops_qsfcb.qsf_length = sizeof(QSF_RCB); /* initialize header
				    ** for control block */
    global->ops_qsfcb.qsf_type = QSFRB_CB;
    global->ops_qsfcb.qsf_owner = (PTR)DB_OPF_ID;
    global->ops_qsfcb.qsf_ascii_id = QSFRB_ASCII_ID;
    global->ops_qsfcb.qsf_sid = global->ops_cb->ops_sid;

    STRUCT_ASSIGN_MACRO(global->ops_caller_cb->opf_query_tree, global->ops_qsfcb.qsf_obj_id);
				    /* move the name to the QSF control 
				    ** block */
    global->ops_qsfcb.qsf_lk_state = QSO_EXLOCK; /* lock exclusively so 
				    ** that this object can be destroyed 
				    ** later */

    qsfstatus = qsf_call( QSO_LOCK, &global->ops_qsfcb); /* get exclusive 
				    ** access to object */
    if (DB_SUCCESS_MACRO(qsfstatus))
    {
        global->ops_lk_id = global->ops_qsfcb.qsf_lk_id; /* save the lock id 
					** so that the object can be destroyed 
                                        ** later */
	global->ops_procedure = (PST_PROCEDURE *)global->ops_qsfcb.qsf_root; /* save 
                                        ** the ptr to procedure header which
                                        ** should be the root */
    }
    return(qsfstatus);
}
Esempio n. 11
0
static  bool
ad0_cpmchk(
ADULcstate	*str,	    /* string to look for PM chars in */
u_char		*endstr)    /* end of str */
{
    ADULcstate	st;

    STRUCT_ASSIGN_MACRO(*str, st);

    while (adulptr(&st) < endstr)
    {
	switch (adultrans(&st)/COL_MULTI)
	{
	  case DB_PAT_ONE:
	  case DB_PAT_ANY:
	  case DB_PAT_LBRAC:	/* Don't want to look for RBRAC */
	    return (TRUE);

	  default:
	    adulnext(&st);
	    break;
	}
    }
    
    return (FALSE);
}
Esempio n. 12
0
DB_STATUS 
qeq_c2_delete(
QEF_RCB		*v_qer_p,
QEE_DSH		*i_dsh_p )
{
    DB_STATUS	    status = E_DB_OK;
    QES_DDB_SES	    *dds_p = & v_qer_p->qef_cb->qef_c2_ddb_ses;
    QES_QRY_SES	    *qss_p = & dds_p->qes_d8_union.u2_qry_ses;
    QEE_DDB_CB	    *qee_p = i_dsh_p->dsh_ddb_cb;
    QEF_QP_CB	    *qp_p = i_dsh_p->dsh_qp_ptr;
    QEQ_DDQ_CB	    *ddq_p = & qp_p->qp_ddq_cb;	
    bool	    log_qry_55 = FALSE,
                    log_err_59 = FALSE;
    i4         i4_1, i4_2;
    RQR_CB	    rqr,
		    *rqr_p = & rqr;


    if (ult_check_macro(& v_qer_p->qef_cb->qef_trace, QEF_TRACE_DDB_LOG_QRY_55,
        & i4_1, & i4_2))
    {
        log_qry_55 = TRUE;
	qeq_p34_del_csr(v_qer_p, i_dsh_p);
    }
    if (ult_check_macro(& v_qer_p->qef_cb->qef_trace, QEF_TRACE_DDB_LOG_ERR_59,
        & i4_1, & i4_2))
        log_err_59 = TRUE;


    /* 2.  set up to call RQR_DELETE */

    MEfill(sizeof(rqr), '\0', (PTR) & rqr);
    rqr_p->rqr_session = dds_p->qes_d3_rqs_p;   /* RQF session id */
    rqr_p->rqr_tabl_name = ddq_p->qeq_d7_deltable;
    rqr_p->rqr_own_name = ddq_p->qeq_d9_delown;
						/* pass owner/table name for
						** CURSOR DELETE */
    rqr_p->rqr_timeout = QEK_0_TIME_QUANTUM;
    rqr_p->rqr_q_language = qss_p->qes_q2_lang;
    rqr_p->rqr_1_site = qss_p->qes_q3_ldb_p;
    STRUCT_ASSIGN_MACRO(qee_p->qee_d5_local_qid, rqr_p->rqr_qid);

    qss_p->qes_q1_qry_status |= QES_03Q_PHASE2;
						/* enter phase 2 for update */
    status = qed_u3_rqf_call(RQR_DELETE, rqr_p, v_qer_p);
    if (status)
    {
	if (log_err_59 && ! log_qry_55)
	    qeq_p34_del_csr(v_qer_p, i_dsh_p);
    }
    else
    {
    	qss_p->qes_q1_qry_status &= ~QES_03Q_PHASE2;
						/* enter phase 2 for update */
	v_qer_p->qef_rowcount = rqr_p->rqr_tupcount;
	v_qer_p->qef_count = rqr_p->rqr_tupcount;
    }
    return(status);
}
Esempio n. 13
0
void
gcd_api_xaStart( GCD_PCB *pcb )
{
    pcb->api.name = "IIapi_xaStart()";
    pcb->api.parm.start.xs_genParm.gp_callback = gcd_start_cmpl;
    pcb->api.parm.start.xs_genParm.gp_closure = (PTR)pcb;
    pcb->api.parm.start.xs_connHandle =  pcb->ccb->cib->conn;
    pcb->api.parm.start.xs_flags = pcb->data.tran.xa_flags;
    STRUCT_ASSIGN_MACRO(pcb->data.tran.distXID, pcb->api.parm.start.xs_tranID);

    IIapi_xaStart( &pcb->api.parm.start );
    return;
}
Esempio n. 14
0
void
gcd_api_xaRollback( GCD_PCB *pcb )
{
    pcb->api.name = "IIapi_xaRollback()";
    pcb->api.parm.xaroll.xr_genParm.gp_callback = gcd_gen_cmpl;
    pcb->api.parm.xaroll.xr_genParm.gp_closure = (PTR)pcb;
    pcb->api.parm.xaroll.xr_connHandle =  pcb->ccb->cib->conn;
    pcb->api.parm.xaroll.xr_flags = pcb->data.tran.xa_flags;
    STRUCT_ASSIGN_MACRO(pcb->data.tran.distXID, pcb->api.parm.xaroll.xr_tranID);

    IIapi_xaRollback( &pcb->api.parm.xaroll );
    return;
}
Esempio n. 15
0
/*  PSY_SQLVIEW - IS THIS AN SQL VIEW
**
**  Description:
**	This routine takes a range entry and determines if it is an
**  SQL view. This routine assumes that we know that the range entry
**  refers to a view.
**
** History:
**	29-sep-92 (andre)
**	    RDF may choose to allocate a new info block and return its address
**	    in rdf_info_blk - we need to copy it over to pss_rdrinfo to avoid
**	    memory leak and other assorted unpleasantries
*/
DB_STATUS
psy_sqlview(
	PSS_RNGTAB	    *rngvar,
	PSS_SESBLK	    *sess_cb,
	DB_ERROR	    *err_blk,
	i4		    *issql)
{
    DB_STATUS	    status = E_DB_OK;
    RDF_CB	    rdf_cb;
    PST_PROCEDURE   *pnode;
    PST_QTREE	    *vtree;
    i4	    err_code;

    *issql = FALSE;
    pst_rdfcb_init(&rdf_cb, sess_cb);
    STRUCT_ASSIGN_MACRO(rngvar->pss_tabid, rdf_cb.rdf_rb.rdr_tabid);
    rdf_cb.rdf_rb.rdr_types_mask = RDR_VIEW | RDR_QTREE ;
    rdf_cb.rdf_rb.rdr_qtuple_count = 1;
    rdf_cb.rdf_info_blk = rngvar->pss_rdrinfo;
    status = rdf_call(RDF_GETINFO, (PTR) &rdf_cb);

    /*
    ** RDF may choose to allocate a new info block and return its address in
    ** rdf_info_blk - we need to copy it over to pss_rdrinfo to avoid memory
    ** leak and other assorted unpleasantries
    */
    rngvar->pss_rdrinfo = rdf_cb.rdf_info_blk;
    
    if (DB_FAILURE_MACRO(status))
    {
	if (rdf_cb.rdf_error.err_code == E_RD0002_UNKNOWN_TBL)
	{
	    (VOID) psf_error(E_PS0903_TAB_NOTFOUND, rdf_cb.rdf_error.err_code,
		PSF_INTERR, &err_code, err_blk, 1,
		psf_trmwhite(sizeof(DB_TAB_NAME), 
		    (char *) &rngvar->pss_tabname),
		&rngvar->pss_tabname);
	}
	else
	{
	    (VOID) psf_rdf_error(RDF_GETINFO, &rdf_cb.rdf_error, err_blk);
	}
	return (status);
    }
    pnode = (PST_PROCEDURE *) rdf_cb.rdf_info_blk->rdr_view->qry_root_node;
    vtree = pnode->pst_stmts->pst_specific.pst_tree;
    if (vtree->pst_qtree->pst_sym.pst_value.pst_s_root.pst_qlang == DB_SQL)
	*issql = TRUE;

    return (status);
}
Esempio n. 16
0
void
gcd_api_xaEnd( GCD_PCB *pcb )
{
    pcb->api.name = "IIapi_xaEnd()";
    pcb->api.parm.end.xe_genParm.gp_callback = gcd_end_cmpl;
    pcb->api.parm.end.xe_genParm.gp_closure = (PTR)pcb;
    pcb->api.parm.end.xe_connHandle =  pcb->ccb->cib->conn;
    pcb->api.parm.end.xe_flags = pcb->data.tran.xa_flags;
    STRUCT_ASSIGN_MACRO(pcb->data.tran.distXID, pcb->api.parm.end.xe_tranID);

    pcb->ccb->cib->tran = NULL;
    pcb->result.flags |= PCB_RSLT_XACT_END;

    IIapi_xaEnd( &pcb->api.parm.end );
    return;
}
Esempio n. 17
0
/*{
** Name: psq_tout	- Copy a text chain to QSF memory
**
** Description:
**      This function copies a text chain to QSF memory, as a text object.
**	It allocates it as a contiguous piece.
**
** Inputs:
**	rngtab			if non-NULL, range statements will be
**				generated for all entries of the range table
**				that are active (pss_used && pss_rgno >= 0);
**				should be non-NULL only for QUEL queries
**      header                  Pointer to chain header
**	mstream			Pointer to unopened memory stream
**	err_blk			Filled in if an error happens
**
** Outputs:
**      mstream                 Filled with object id for new text
**				object
**	err_blk			Filled in if an error happened
**	Returns:
**	    E_DB_OK		Success
**	    E_DB_ERROR		Non-catastrophic failure
**	    E_DB_FATAL		Catastrophic failure
**	Exceptions:
**	    none
**
** Side Effects:
**	    Allocates memory
**
** History:
**      18-jul-86 (jeff)
**          written
**      2-sep-86 (seputis)
**          changed MEcopy routine parameter to be &hp->psq_tsize
**	6-may-87 (daved)
**	    clear mstream lock id after unlocking memory stream
**	29-jun-87 (daved)
**	    emit the range table entries if a range table is provided.
**	10-aug-93 (andre)
**	    removed declaration of qsf_call()
*/
DB_STATUS
psq_tout(
	PSS_SESBLK	   *sess_cb,
	PSS_USRRANGE	   *rngtab,
	PTR                header,
	PSF_MSTREAM	   *mstream,
	DB_ERROR	   *err_blk)
{
    DB_STATUS           status;
    i4		err_code;
    u_char		*buf;
    QSF_RCB		qsf_rb;

    /* Open the QSF memory stream for the text object */
    status = psf_mopen(sess_cb, QSO_QTEXT_OBJ, mstream, err_blk);
    if (status != E_DB_OK)
	return (status);

    status = psq_store_text(sess_cb, rngtab, header, mstream, 
	(PTR *) &buf, (bool) FALSE, err_blk);
    if (DB_FAILURE_MACRO(status))
	return(status);

    /* Set the root of the object */
    status = psf_mroot(sess_cb, mstream, (PTR) buf, err_blk);
    if (status != E_DB_OK)
	return (status);

    /* Unlock the object */
    qsf_rb.qsf_type = QSFRB_CB;
    qsf_rb.qsf_ascii_id = QSFRB_ASCII_ID;
    qsf_rb.qsf_length = sizeof(qsf_rb);
    qsf_rb.qsf_owner = (PTR)DB_PSF_ID;
    qsf_rb.qsf_sid = sess_cb->pss_sessid;
    STRUCT_ASSIGN_MACRO(mstream->psf_mstream, qsf_rb.qsf_obj_id);
    qsf_rb.qsf_lk_id = mstream->psf_mlock;
    status = qsf_call(QSO_UNLOCK, &qsf_rb);
    if (status != E_DB_OK)
    {
	(VOID) psf_error(E_PS0375_UNLOCK_QSF_TEXT,
	    qsf_rb.qsf_error.err_code, PSF_INTERR, &err_code, err_blk, 0);
	return (status);
    }
    mstream->psf_mlock = 0;

    return (E_DB_OK);
}
Esempio n. 18
0
/*{
** Name: psq_topen	- Open a query text chain
**
** Description:
**      This function opens a query text chain by opening a memory stream,
**	allocating a header, and filling it in. 
**
** Inputs:
**      header                          Place to put pointer to header
**	memleft				Pointer to memory left
**	err_blk				Filled in if an error happens
**
** Outputs:
**      header                          Filled in with pointer to header
**	err_blk				Filled in if an error happened
**	Returns:
**	    E_DB_OK			Success
**	    E_DB_ERROR			Non-catastrophic failure
**	    E_DB_FATAL			Catastrophic failure
**	Exceptions:
**	    none
**
** Side Effects:
**	    Allocates memory
**
** History:
**      18-jul-86 (jeff)
**          written
**      02-sep-86 (seputis)
**          err_blk becomes a DB_ERROR *
*/
DB_STATUS
psq_topen(
	PTR                *header,
	SIZE_TYPE	   *memleft,
	DB_ERROR	   *err_blk)
{
    ULM_RCB             ulm_rcb;
    DB_STATUS		status;
    i4		err_code;
    PSQ_THEAD		*hp;
    extern PSF_SERVBLK	*Psf_srvblk;

    /* Open the stream and allocate memory for the header */
    ulm_rcb.ulm_facility = DB_PSF_ID;
    ulm_rcb.ulm_poolid = Psf_srvblk->psf_poolid;
    ulm_rcb.ulm_blocksize = 512;
    ulm_rcb.ulm_memleft = memleft;
    ulm_rcb.ulm_streamid_p = &ulm_rcb.ulm_streamid;
    ulm_rcb.ulm_flags = ULM_SHARED_STREAM | ULM_OPEN_AND_PALLOC;
    ulm_rcb.ulm_psize = sizeof(PSQ_THEAD);
    if ((status = ulm_openstream(&ulm_rcb)) != E_DB_OK)
    {
	if (ulm_rcb.ulm_error.err_code == E_UL0005_NOMEM)
	{
	    psf_error(E_PS0F02_MEMORY_FULL, 0L, PSF_CALLERR, 
		&err_code, err_blk, 0);
	}
	else
	    (VOID) psf_error(E_PS0370_OPEN_TEXT_CHAIN,
		ulm_rcb.ulm_error.err_code, PSF_INTERR, &err_code, err_blk, 0);
	return (status);
    }

    *header = ulm_rcb.ulm_pptr;

    /* Fill in the header */
    hp		    = (PSQ_THEAD*) ulm_rcb.ulm_pptr;
    hp->psq_first   = (PSQ_TEXT *) NULL;
    hp->psq_last    = (PSQ_TEXT *) NULL;
    hp->psq_tsize   = 0;
    STRUCT_ASSIGN_MACRO(ulm_rcb, hp->psq_tmem);
    hp->psq_tmem.ulm_streamid_p = &hp->psq_tmem.ulm_streamid;

    return (E_DB_OK);
}
Esempio n. 19
0
/*{
** Name: opx_sccerror	- report error to user
**
** Description:
**      Report a message to the user
**
** Inputs:
**      status                          status of error
**      msg_buffer                      ptr to message
**      error                           ingres error number
**
** Outputs:
**	Returns:
**	    VOID
**	Exceptions:
**	    none
**
** Side Effects:
**	    fatal status will cause query to be aborted, and previous text sent
**          to user to be flushed
**
** History:
**      15-apr-87 (seputis)
**          initial creation
**	21-may-89 (jrb)
**	    changed interface to this routine to accept generic error
**      28-may-92 (seputis)
**          - dump query for any error which is logged
**	24-oct-92 (andre)
**	    replaced generic error (i4) with sqlstate (DB_SQLSTATE *) in
**	    the interface of opx_sccerror()
**	13-nov-92 (andre)
**	    If sqlstate is not passed into opx_sccerror(), set scf_sqlstate 
**	    to MISC_ING_ERRORS"

[@history_line@]...
[@history_template@]...
*/
static DB_STATUS
opx_sccerror(
	DB_STATUS	   status,
	DB_SQLSTATE	   *sqlstate,
	OPX_ERROR          error,
	char               *msg_buffer,
	i4                msg_length)
{
    SCF_CB                 scf_cb;
    DB_STATUS              scf_status;

    scf_cb.scf_length = sizeof(scf_cb);
    scf_cb.scf_type = SCF_CB_TYPE;
    scf_cb.scf_facility = DB_OPF_ID;
    scf_cb.scf_nbr_union.scf_local_error = error;
    if (sqlstate)
	STRUCT_ASSIGN_MACRO((*sqlstate), scf_cb.scf_aux_union.scf_sqlstate);
    else
	MEcopy((PTR) SS50000_MISC_ERRORS, DB_SQLSTATE_STRING_LEN,
	    (PTR) scf_cb.scf_aux_union.scf_sqlstate.db_sqlstate);
    scf_cb.scf_len_union.scf_blength = msg_length;
    scf_cb.scf_ptr_union.scf_buffer = msg_buffer;
    scf_cb.scf_session = DB_NOSESSION;
    if (DB_SUCCESS_MACRO(status))
	scf_status = scf_call(SCC_TRACE, &scf_cb);
    else
    {
	/* Dump the session that caused this error */
	if ((error % 256) >= 128)
	    scs_avformat();	/* dump info on internal
				** consistency checks only,
				** i.e. do not dump for errors like
				** OP0008 */
	scf_status = scf_call(SCC_ERROR, &scf_cb);
    }
    if (scf_status != E_DB_OK)
    {
	TRdisplay("SCF error displaying OPF message to user\n");
	TRdisplay("OPF message is :%s",msg_buffer);
    }
    return (scf_status);
}
Esempio n. 20
0
/*{
** Name: psq_tclose	- Close the memory stream for a text chain
**
** Description:
**      This function closes the memory stream for a text chain, deallocating
**	the memory.
**
** Inputs:
**      header                          Pointer to header of text chain
**	err_blk				Filled in if an error happens
**
** Outputs:
**      err_blk                         Filled in if an error happened
**	Returns:
**	    E_DB_OK			Success
**	    E_DB_ERROR			Non-catastrophic failure
**	    E_DB_FATAL			Catastrophic failure
**	Exceptions:
**	    none
**
** Side Effects:
**	    Deallocates memory
**
** History:
**      18-jul-86 (jeff)
**          written
*/
DB_STATUS
psq_tclose(
	PTR		   header,
	DB_ERROR           *err_blk)
{
    DB_STATUS           status;
    ULM_RCB		ulm_rcb;
    i4		err_code;

    STRUCT_ASSIGN_MACRO(((PSQ_THEAD*)header)->psq_tmem, ulm_rcb);
    status = ulm_closestream(&ulm_rcb);
    if (status != E_DB_OK)
    {
	(VOID) psf_error(E_PS0372_CLOSE_TEXT_CHAIN,
	    ulm_rcb.ulm_error.err_code, PSF_INTERR, &err_code, err_blk, 0);
	return (status);
    }

    return (E_DB_OK);
}
Esempio n. 21
0
/*{
** Name: psf_munlock - Unlock a QSO object stream
**
** Description:
**      This function unlocks the specified QSO object.
**
** Inputs:
**	sess_cb				Ptr to session's CB.
**      mstream                         Pointer to the memory stream
**	    .psf_mstream.qso_handle	Object handle
**	err_block			Pointer to error control block
**
** Outputs:
**      mstream                         Pointer to the memory stream
**	    .psf_mlock			Lock id returned by QSF
**      err_blk                         Filled in with error information.
**	    E_PS0B05_CANT_UNLOCK	Error when unlocking object type.
**
**	Returns:
**	    E_DB_OK			Success
**	    E_DB_ERROR			Non-catastrophic failure
**
**	Exceptions:
**	    none
**
** Side Effects:
**	    none
**
** History:
**	29-nov-93 (rblumer)
**          Written.
*/
DB_STATUS
psf_munlock(
	PSS_SESBLK	   *sess_cb,
	PSF_MSTREAM     *mstream,
	DB_ERROR	*err_blk)
{
    DB_STATUS		status;
    i4		err_code;

    sess_cb->pss_qsf_rcb.qsf_lk_id	 = mstream->psf_mlock;
    STRUCT_ASSIGN_MACRO(mstream->psf_mstream, sess_cb->pss_qsf_rcb.qsf_obj_id);

    status = qsf_call(QSO_UNLOCK, &sess_cb->pss_qsf_rcb);
    if (status != E_DB_OK)
    {
	(VOID) psf_error(E_PS0B05_CANT_UNLOCK, sess_cb->pss_qsf_rcb.qsf_error.err_code, 
	    PSF_INTERR, &err_code, err_blk, 0);
	return (status);
    }

    mstream->psf_mlock = 0;
    return (E_DB_OK);

}  /* end psf_munlock */
Esempio n. 22
0
DB_STATUS
qet_t9_ok_w_ldbs(
QEE_DSH		*i_dsh_p,
QEF_RCB		*v_qer_p,
bool		*o1_ok_p)
{
    DB_STATUS	    status_0 = E_DB_OK,
		    status_t = E_DB_OK,
		    status_u = E_DB_OK;		
    DB_ERROR	    ulm_err,
		    tpf_err;
    QES_DDB_SES	    *dds_p = & v_qer_p->qef_cb->qef_c2_ddb_ses;
    TPR_CB	    tpr_cb,
		    *tpr_p = & tpr_cb;
    QEF_QP_CB	    *qp_p = i_dsh_p->dsh_qp_ptr;
    QEF_AHD	    *act_p = qp_p->qp_ahd;
    QEQ_D1_QRY	    *subqry_p;
    ULM_RCB	    ulm;
    i4		    w_ldbcnt;
    TPR_W_LDB	    *wldb1_p = (TPR_W_LDB *) NULL,
		    *wldb2_p = (TPR_W_LDB *) NULL;


    *o1_ok_p = TRUE;	/* assume */

    if (qp_p->qp_qmode == QEQP_01QM_RETRIEVE)
	return(E_DB_OK);	    /* read-only query */

    /* assume that there are update sites within this query plan */

    /* allocate stream to build list of LDB ptrs; note that this 
    ** stream must be closed upon return from this routine */

    STRUCT_ASSIGN_MACRO(Qef_s_cb->qef_s_ulmcb, ulm);
    ulm.ulm_blocksize = sizeof(TPR_W_LDB);  /* allocation size */

    status_u = qec_mopen(&ulm);
    if (status_u)
    {
	v_qer_p->error.err_code = ulm.ulm_error.err_code;
	return(status_u);
    }

    /* traverse the action list to build an LDB ptr list */

    MEfill(sizeof(tpr_cb), '\0', (PTR) & tpr_cb);
    tpr_p->tpr_session = dds_p->qes_d2_tps_p;	/* TPF session CB ptr */
    tpr_p->tpr_rqf = dds_p->qes_d3_rqs_p;	/* RQF session CB ptr */
    tpr_cb.tpr_15_w_ldb_p = (TPR_W_LDB *) NULL;
    w_ldbcnt = 0;
    act_p = qp_p->qp_ahd; 
    while (act_p != (QEF_AHD *) NULL && status_u == E_DB_OK)
    {
	if (act_p->ahd_atype == QEA_D1_QRY)
	{
	    subqry_p = & act_p->qhd_obj.qhd_d1_qry;

	    if (subqry_p->qeq_q3_ctl_info & QEQ_002_USER_UPDATE)
	    {
		/* an update site */

		w_ldbcnt++;

		ulm.ulm_psize = sizeof(TPR_W_LDB);
		status_u = qec_malloc(&ulm);
		if (status_u)
		{
		    STRUCT_ASSIGN_MACRO(ulm.ulm_error, ulm_err);
		    goto dismantle_9;
		}
		else
		{
		    /* allocation ok */

		    wldb2_p = (TPR_W_LDB *) ulm.ulm_pptr;

		    if (wldb1_p == (TPR_W_LDB *) NULL)
		    {
			/* first in list */

			tpr_cb.tpr_15_w_ldb_p = 
			    wldb1_p = wldb2_p;  
			wldb2_p->tpr_1_prev_p = 
			    wldb2_p->tpr_2_next_p = (TPR_W_LDB *) NULL;
		    }
		    else
		    {
			/* append to list */

			wldb1_p->tpr_2_next_p = wldb2_p;  
			wldb2_p->tpr_1_prev_p = wldb1_p;
			wldb2_p->tpr_2_next_p = (TPR_W_LDB *) NULL;
		    }

		    wldb2_p->tpr_3_ldb_p = subqry_p->qeq_q5_ldb_p;
		}
  	    }
	}
	act_p = act_p->ahd_next;	/* advance */
    }
    /* call TPF if any update sites */

    if (tpr_cb.tpr_15_w_ldb_p != (TPR_W_LDB *) NULL)
    {
	status_t = qed_u17_tpf_call(TPF_OK_W_LDBS, & tpr_cb, v_qer_p);
	if (status_t)
	    STRUCT_ASSIGN_MACRO(tpr_cb.tpr_error, tpf_err);
	else
	    *o1_ok_p = tpr_cb.tpr_14_w_ldbs_ok;
    }

dismantle_9:

    /* must always close stream */

    status_0 = ulm_closestream(&ulm);

    if (status_u)
    {
	/* return previous ulm error */

	STRUCT_ASSIGN_MACRO(ulm_err, v_qer_p->error);
	return(status_u);
    }

    if (status_t)
    {
	/* return tpf error */

	STRUCT_ASSIGN_MACRO(tpf_err, v_qer_p->error);
	return(status_t);
    }

    if (status_0)
    {
	/* return close-stream ulm error */

	STRUCT_ASSIGN_MACRO(ulm.ulm_error, v_qer_p->error);
    }
    
    return(status_0);
}
Esempio n. 23
0
/*{
** Name: psy_dpermit	- Define a permit.
**
**  INTERNAL PSF call format: status = psy_dpermit(&psy_cb, sess_cb);
**
**  EXTERNAL call format:     status = psy_call(PSY_DPERMIT, &psy_cb, sess_cb);
**
** Description:
**	Given all of the parameters necessary to CREATE/DEFINE a permit on a
**	table or view, this function will store the permission in the system
**	catalogs.  This will include storing the query tree in the tree table,
**	storing the text of the query in the iiqrytext table (really done by
**	QEF), storing a row in the protect table, and issuing an "alter table"
**	operation to DMF to indicate that there are permissions on the given
**	table.
**
** Inputs:
**      psy_cb
**	    .psy_qrytext		Id of query text as stored in QSF.
**	    .psy_cols[]			Array of columns on which to grant
**					permission
**	    .psy_numcols		Number of columns listed above; 0 means
**					give permission on all columns
**          .psy_intree                 QSF id of query tree representing the
**					where clause in the permit
**          .psy_opctl                  Bit map of defined   operations
**          .psy_opmap                  Bit map of permitted operations
**          .psy_user                   Name of user who will get permission
**          .psy_terminal               Terminal at which permission is given
**					(blank if none specified)
**          .psy_timbgn                 Time of day at which the permission
**					begins (minutes since 00:00)
**          .psy_timend                 Time of day at which the permission ends
**					(minutes since 00:00)
**          .psy_daybgn                 Day of week at which the permission
**					begins (0 = Sunday)
**          .psy_dayend                 Day of week at which the permission ends
**					(0 = Sunday)
**	    .psy_grant
**		PSY_CPERM		CREATE/DEFINE PERMIT
**	    .psy_tblq			head of table queue
**	    .psy_colq			head of column queue
**	    .psy_usrq			head of user queue
**	    .psy_qlen			length of first iiqrytext
**	    .psy_flags			useful info
**		PSY_EXCLUDE_COLUMNS	user specified a list of columns to
**					which privilege should not apply
**	sess_cb				Pointer to session control block
**					(Can be NULL)
**
** Outputs:
**      psy_cb
**          .psy_txtid                  Id of query text as stored in the
**					iiqrytext system relation.
**	    .psy_error			Filled in if error happens
**	Returns:
**	    E_DB_OK			Function completed normally.
**	    E_DB_WARN			Function completed with warning(s);
**	    E_DB_ERROR			Function failed; non-catastrophic error
**	    E_DB_FATAL			Function failed; catastrophic error
**	Exceptions:
**	    none
**
** Side Effects:
**	    Stores text of query in iiqrytext relation, query tree in tree
**	    relation, row in protect relation identifying the permit.  Does
**	    an alter table DMF operation to indicate that there are permissions
**	    on the table.
**
** History:
**	02-oct-85 (jeff)
**          written
**      03-sep-86 (seputis)
**          changed some psy_cb. to psy_cb->
**          added .db_att_id reference
**          changed rdr_cb. rdr_cb->
**	02-dec-86 (daved)
**	    bug fixing. check for permit on tables owned by user and not
**	    view.
**	29-apr-87 (stec)
**	    Implemented changes for GRANT statement.
**	10-may-88 (stec)
**	    Make changes for db procs.
**	03-oct-88 (andre)
**	    Modified call to pst_rgent to pass 0 as a query mode since it is
**	    clearly not PSQ_DESTROY
**	06-feb-89 (ralph)
**	    Added support for 300 attributes:
**		Use DB_COL_BITS in place of DB_MAX_COLS
**		Loop over domset array using DB_COL_WORDS
**	06-mar-89 (ralph)
**	    GRANT Enhancements, Phase 1:
**	    Initialize new DB_PROTECTION fields, dbp_seq and dbp_gtype
**	03-apr-89 (ralph)
**	    GRANT Enhancements, Phase 2:
**	    Use DBGR_USER when initializing dbp_gtype
**	08-may-89 (ralph)
**	    Initialize reserved field to blanks (was \0)
**	04-jun-89 (ralph)
**	    Initialize dbp_fill1 to zero
**	    Fix unix portability problems
**	02-nov-89 (neil)
**	    Alerters: Allowed privileges for events.
**	1-mar-90 (andre)
**	    If processing a GRANT on tables, check if 
**	    ALL-TO-ALL or RETRIEVE-TO-ALL has already been granted, and if so,
**	    mark psy_mask appropriately.
**	    If user tried to CREATE ALL/RETRIEVE-TO-ALL, and one already exists,
**	    skip to the exit.
**	12-mar-90 (andre)
**	    set rdr_2types_mask to 0.
**      22-may-90 (teg)
**          init rdr_instr to RDF_NO_INSTR
**	08-aug-90 (ralph)
**	    Initialize new fields in iiprotect tuple
**	14-dec-90 (ralph)
**	    Disallow use of GRANT by non-DBA if xORANGE
**	11-jan-90 (ralph)
**	    Allow user "$ingres" to use GRANT if xORANGE.
**	    This was done for CREATEDB (UPGRADEFE).
**	20-feb-91 (andre)
**	    For CREATE/DEFINE PERMIT, grantee type was stored in
**	    psy_cb->psy_gtype.
**	24-jun-91 (andre)
**	    IIPROTECT tuples for table permits will contain exactly one
**	    privilege.  IIQRYTEXT template built for table-wide privileges
**	    contains a placeholder for a privilege name which will be filled in
**	    with each of the table-wide privileges being granted, one at a time.
**	    PSY_CB.psy_opmap will be set to correspond with privilege name
**	    stored in the IIQRYTEXT permit.
**	16-jul-91 (andre)
**	    responsibility for splitting permit tuples will passed on to
**	    qeu_cprot().  If a permit specified only one privilege, we will
**	    substitute the appropriate privilege name here and will not ask
**	    qeu_cprot() to split tuples.
**	06-aug-91 (andre)
**	    before proceeding to CREATE a permit on a view owned by the current
**	    user, we will call psy_tbl_grant_check() to ensure that this user
**	    may create a permit on his view.  If the object is not owned by the
**	    current user, we will not try to verify that the user may
**	    CREATE/DEFINE a permit since (until the relevant FE changes are
**	    made) we intend to continue allowing any user with CATUPD to
**	    CREATE/DEFINE permits on catalogs and the dba will be allowed to
**	    CREATE/DEFINE permits on extended catalogs
**	11-nov-91 (rblumer)
**	  merged from 6.4:  26-feb-91 (andre)
**	    PST_QTREE was changed to store the range table as an array of
**	    pointers to PST_RNGENTRY structure.
**	14-feb-92 (andre)
**	    we will no longer have to fill in privilege name for permits
**	    specifying one privilege - it will be handled in respective
**	    grammars.
**	15-jun-92 (barbara)
**	    For Sybil, change interface to pst_rgent(), Star returns from
**	    psy_dpermit before permits get stored.
**	07-jul-92 (andre)
**	    DB_PROTECTION tuple will contain an indicator of how the permit was
**	    created, i.e. whether it was created using SQL or QUEL and if the
**	    former, then whether it was created using GRANT statement.  Having
**	    this information will facilitate merging similar and identical
**	    permit tuples.
**	14-jul-92 (andre)
**	    semantics of GRANT ALL [PRIVILEGES] is different from that of
**	    CREATE PERMIT ALL in that the former (as dictated by SQL92) means
**	    "grant all privileges which the current auth id posesses WGO"
**	    whereas the latter (as is presently interpreted) means "grant all
**	    privileges that can be defined on the object" which in case of
**	    tables and views means SELECT, INSERT, DELETE, UPDATE.
**	    psy_tbl_grant_check() (function responsible for determining whether
**	    a user may grant specified privilege on a specified table or view)
**	    will have to be notified whether we are processing GRANT ALL.  Its
**	    behaviour will change as follows:
**	      - if processing GRANT ALL and psy_tbl_grant_check() determines
**	        that the user does not possess some (but not all) of the
**		privileges passed to it by the caller it will not treat it as an
**		error, but will instead inform the caller of privileges that the
**		user does not posess,
**	      - if processing GRANT ALL and psy_tbl_grant_check() determines
**	        that the user does not possess any of the privileges passed to
**		it by the caller it will treat it as an error
**	      - if processing a statement other than GRANT ALL and
**	        psy_tbl_grant_check() determines that the user does not possess
**		some of the privileges passed to it by the caller it will treat
**		it as an error
**	16-jul-92 (andre)
**	    if a permit being created depends on some privileges, build a
**	    structure describing these privileges and store its address in
**	    rdf_cb->rdr_indep.
**	18-jul-92 (andre)
**	    we will no longer be telling QEF to turn off DMT_ALL_PROT or
**	    DMT_RETRIEVE_PRO when a user creates ALL/RETRIEVE TO ALL permit.
**	    QEF will figure out on its own whether PUBLIC now has RETRIEVE or
**	    ALL on a table/view
**	20-jul-92 (andre)
**	    if user specified a list of columns to which privilege(s) should
**	    not apply, set dbp_domset correctly
**	03-aug-92 (barbara)
**	    Invalidate base table infoblk from RDF cache for CREATE PERMIT
**	    and CREATE SEC_ALARM.
**	16-sep-92 (andre)
**	    privilege maps are build using bitwise ops, so care should be
**	    exercised when accessing it using BT*() functions
**	17-jun-93 (andre)
**	    changed interface of psy_secaudit() to accept PSS_SESBLK
**	5-jul-93 (robf)
**	    changed interface of  psy_secaudit() to accept security label
**	 7-jan-94 (swm)
**	    Bug #58635
**	    Added PTR cast for qsf_owner which has changed type to PTR.
**	06-mar-96 (nanpr01)
**	    Move the QSF request block initialization up. because if  
**	    pst_rgnent returns a failure status code, subsequent QSF
**	    calls get bad control block error.
*/
DB_STATUS
psy_dpermit(
	PSY_CB             *psy_cb,
	PSS_SESBLK	   *sess_cb)
{
    RDF_CB              rdf_cb;
    register RDR_RB	*rdf_rb = &rdf_cb.rdf_rb;
    QSF_RCB		qsf_rb;
    DB_STATUS		status;
    DB_STATUS		stat;
    DB_PROTECTION	ptuple;
    register DB_PROTECTION *protup = &ptuple;
    i4			*domset	= ptuple.dbp_domset;
    register i4	i, j;
    i4		err_code;
    PSS_RNGTAB		*rngvar;
    PSS_USRRANGE	*rngtab;
    PST_PROCEDURE	*pnode;
    PST_QTREE		*qtree;
    DB_ERROR		*err_blk = &psy_cb->psy_error;
    i4			textlen;
    i4			tree_lock   = 0;
    i4			text_lock   = 0;
    DB_TAB_ID		tabids[PST_NUMVARS];
    PSQ_INDEP_OBJECTS   indep_objs;
    PSQ_OBJPRIV         obj_priv;       /* space for independent DELETE */
    PSQ_COLPRIV         col_privs[2];   /*
                                        ** space for independent INSERT and
					** UPDATE
					*/
    PST_VRMAP		varmap;
    PSY_TBL		*psy_tbl;
    DB_TIME_ID		timeid;
    DB_NAME             *objname;

    /*
    ** For CREATE/DEFINE PERMIT execute code below.
    */

    /* initialize the QSF control block */
    qsf_rb.qsf_type	= QSFRB_CB;
    qsf_rb.qsf_ascii_id = QSFRB_ASCII_ID;
    qsf_rb.qsf_length	= sizeof(qsf_rb);
    qsf_rb.qsf_owner	= (PTR)DB_PSF_ID;
    qsf_rb.qsf_sid	= sess_cb->pss_sessid;

    rngtab = &sess_cb->pss_auxrng;

    /* table info is stored in the only entry in the table queue */
    psy_tbl = (PSY_TBL *) psy_cb->psy_tblq.q_next;

    status = pst_rgent(sess_cb, rngtab, -1, "", PST_SHWID,
	(DB_TAB_NAME *) NULL, (DB_TAB_OWN *) NULL,
	&psy_tbl->psy_tabid, TRUE, &rngvar, (i4) 0, err_blk);
	
    if (DB_FAILURE_MACRO(status))
	goto exit;

    /* In STAR, we do not actually store permits */
    if (sess_cb->pss_distrib & DB_3_DDB_SESS)
    {
	qsf_rb.qsf_lk_state = QSO_EXLOCK;
	goto exit;
    }

    /* Fill in the RDF request block */
    pst_rdfcb_init(&rdf_cb, sess_cb);

    /* The table which is receiving the permit */
    STRUCT_ASSIGN_MACRO(psy_tbl->psy_tabid, rdf_rb->rdr_tabid);
    
    /* Tell RDF we're doing a permit definition */
    rdf_rb->rdr_update_op   = RDR_APPEND;

    rdf_rb->rdr_types_mask = RDR_PROTECT;
    rdf_rb->rdr_qrytuple = (PTR) protup;

    /* initialize independent object structure */
    indep_objs.psq_objs	= (PSQ_OBJ *) NULL;
    indep_objs.psq_objprivs = (PSQ_OBJPRIV *) NULL;
    indep_objs.psq_colprivs = (PSQ_COLPRIV *) NULL;
    indep_objs.psq_grantee  = &sess_cb->pss_user;

    rdf_rb->rdr_indep	    = (PTR) &indep_objs;

    /*
    ** populate the IIPROTECT tuple
    */

    /* Zero out the template */
    (VOID)MEfill(sizeof(ptuple), (u_char) 0, (PTR) protup);

    /* store grantee type */
    protup->dbp_gtype = psy_cb->psy_gtype;

    /* Init reserved block */
    (VOID)MEfill(sizeof(protup->dbp_reserve),
	(u_char) ' ', (PTR) protup->dbp_reserve);

    /* Init obj name */
    STRUCT_ASSIGN_MACRO(psy_tbl->psy_tabnm, protup->dbp_obname);

    /*@FIX_ME@ Where does this come from? */
    protup->dbp_obstat = ' ';

    /* store the object type indicator */
    if (psy_tbl->psy_mask & PSY_OBJ_IS_TABLE)
    {
	protup->dbp_obtype = DBOB_TABLE;
    }
    else if (psy_tbl->psy_mask & PSY_OBJ_IS_VIEW)
    {
	protup->dbp_obtype = DBOB_VIEW;
    }
    else
    {
	protup->dbp_obtype = DBOB_INDEX;
    }

    STRUCT_ASSIGN_MACRO(psy_tbl->psy_owner, protup->dbp_obown);

    STRUCT_ASSIGN_MACRO(sess_cb->pss_user, protup->dbp_grantor);

    TMnow((SYSTIME *)&timeid);
    protup->dbp_timestamp.db_tim_high_time = timeid.db_tim_high_time;
    protup->dbp_timestamp.db_tim_low_time  = timeid.db_tim_low_time;

    /* The table on which we're giving permission */
    STRUCT_ASSIGN_MACRO(psy_tbl->psy_tabid, protup->dbp_tabid);

    /* Beginning and ending times of day */
    protup->dbp_pdbgn = psy_cb->psy_timbgn;
    protup->dbp_pdend = psy_cb->psy_timend;

    /* Beginning and ending days of week */
    protup->dbp_pwbgn = psy_cb->psy_daybgn;
    protup->dbp_pwend = psy_cb->psy_dayend;

    if (psy_cb->psy_numcols != 0 && ~psy_cb->psy_flags & PSY_EXCLUDE_COLUMNS)
    {
	/* user specified a list of columns to which privilege(s) will apply */
	
	/* Bit map of permitted columns */
	psy_fill_attmap(domset, ((i4) 0));

	for (i = 0; i < psy_cb->psy_numcols; i++)
	{
	    BTset((i4)psy_cb->psy_cols[i].db_att_id, (char *) domset);
	}	
    }
    else
    {
	/*
	** user specified table-wide privilege(s) or a list of columns L s.t.
	** privilege(s) will apply to the entire table except for columns in L
	*/

	psy_fill_attmap(domset, ~((i4) 0));

	if (psy_cb->psy_flags & PSY_EXCLUDE_COLUMNS)
	{
	    /*
	    ** exclude specified columns from the list of columns to which
	    ** privilege(s) will apply
	    */
	    for (i = 0; i < psy_cb->psy_numcols; i++)
	    {
		BTclear((i4) psy_cb->psy_cols[i].db_att_id, (char *) domset);
	    }
	}
    }

    if (rngvar->pss_tabdesc->tbl_status_mask & DMT_VIEW)
    {
	/*
	** if view is owned by the current user, psy_tbl_grant_check() will
	** determine if the permit can, indeed, be created;  as long as we are
	** preserving the kludge that allows users with CATUPD create permits on
	** catalogs and DBAs to create permits on extended catalogs, we shall
	** not call psy_tbl_grant_check() on view not owned by the current user,
	** since it is likely to result in psy_tbl_grant_check() complaining
	** about inadequate permissions
	*/
	if (!MEcmp((PTR) &rngvar->pss_ownname, (PTR) &sess_cb->pss_user,
	    sizeof(sess_cb->pss_user)))
	{
	    i4			    tbl_wide_privs;
	    PSY_COL_PRIVS	    col_specific_privs, *csp,
				    indep_col_specific_privs;
	    DB_TAB_ID		    indep_id;
	    i4			    indep_tbl_wide_privs;
	    bool		    insuf_privs, quel_view;
	    i4		    val1, val2;

	    /*
	    ** build maps of table-wide and column-specific privileges for
	    ** psy_tbl_grant_check()
	    ** if a column list was specified with CREATE PERMIT and
	    ** privileges specified in the statement include a set of
	    ** privileges S s.t. for all P in S, P can only be specified as
	    ** table-wide with GRANT statement (currently this includes
	    ** SELECT, INSERT, DELETE), we will make 
	    ** psy_tbl_grant_check() think that privileges in S are
	    ** table-wide.
	    ** This will work correctly since if the view was defined over
	    ** some objects owned by other user(s), for every P in S we
	    ** would need table-wide privilege WGO on the underlying object.
	    **
	    ** For the purposes of providing more descriptive output for
	    ** trace point ps131, if column-list was specified, we will pass
	    ** the map of attributes even if column-specific UPDATE was not
	    ** specified
	    */

	    if (psy_cb->psy_numcols != 0 &&
		(psy_cb->psy_opmap & DB_REPLACE ||
		 ult_check_macro(&sess_cb->pss_trace, 3, &val1, &val2)
		)
	       )
	    {
		i4	    *ip;

		csp = &col_specific_privs;

		/*
		** column-specific UPDATE privilege will not be translated into
		** a table-wide privilege since GRANT allows for specification
		** of column-specific UPDATE privilege
		*/
		csp->psy_col_privs = psy_cb->psy_opmap & DB_REPLACE;
		tbl_wide_privs = psy_cb->psy_opmap & ~DB_REPLACE;

		/*
		** if creating a permit on a set of columns and UPDATE is not
		** one of the privileges named in the statement, store the
		** attribute map in the first element of the attribute map list
		*/
		ip = (csp->psy_col_privs)
		    ? csp->psy_attmap[PSY_UPDATE_ATTRMAP].map
		    : csp->psy_attmap->map;

		/* copy the attribute map */
		for (i = 0; i < DB_COL_WORDS; i++, ip++)
		{
		    *ip = domset[i];
		}
	    }
	    else
	    {
		tbl_wide_privs = psy_cb->psy_opmap;
		csp = (PSY_COL_PRIVS *) NULL;
	    }

	    status = psy_tbl_grant_check(sess_cb, (i4) PSQ_PROT,
		&rngvar->pss_tabid, &tbl_wide_privs, csp, &indep_id,
		&indep_tbl_wide_privs, &indep_col_specific_privs,
		psy_cb->psy_flags, &insuf_privs, &quel_view,
		&psy_cb->psy_error);
	    if (DB_FAILURE_MACRO(status))
	    {
		goto exit;
	    }

	    if (insuf_privs)
	    {
		/* must audit failure to create a permit */
		if ( Psf_srvblk->psf_capabilities & PSF_C_C2SECURE )
		{
		    DB_ERROR	e_error;

		    /* Must audit CREATE PERMIT failure. */
		    status = psy_secaudit(FALSE, sess_cb,
			    (char *)&rngvar->pss_tabdesc->tbl_name,
			    &rngvar->pss_tabdesc->tbl_owner,
			    sizeof(DB_TAB_NAME), SXF_E_TABLE,
			    I_SX2016_PROT_TAB_CREATE, SXF_A_FAIL | SXF_A_CREATE,
			    &e_error);
		    
		    status = (status > E_DB_ERROR) ? status : E_DB_ERROR;
		}
		goto exit;
	    }
	    else if (quel_view)
	    {
		goto exit;
	    }
	    
	    /*
	    ** If user is trying to grant one or more of
	    ** INSERT/DELETE/UPDATE on his/her view whose underlying table
	    ** or view is owned by another user, psy_tbl_grant_check() will
	    ** return id of the underlying object along with map of
	    ** privileges.  We will convert maps of independent privileges
	    ** into elements of independent privilege list and pass them
	    ** along to QEF
	    */
	    if (   indep_id.db_tab_base != (i4) 0
		&& (   indep_id.db_tab_base != rngvar->pss_tabid.db_tab_base
		    || indep_id.db_tab_index !=
			   rngvar->pss_tabid.db_tab_index
		   )
	       )
	    {
		if (indep_tbl_wide_privs & DB_DELETE)
		{
		    /*
		    ** the only expected independent table-wide privilege
		    ** is DELETE
		    */
		    obj_priv.psq_next		= (PSQ_OBJPRIV *) NULL;
		    obj_priv.psq_objtype		= PSQ_OBJTYPE_IS_TABLE;
		    obj_priv.psq_privmap		= (i4) DB_DELETE;
		    obj_priv.psq_objid.db_tab_base	= indep_id.db_tab_base;
		    obj_priv.psq_objid.db_tab_index = indep_id.db_tab_index;
		    indep_objs.psq_objprivs		= &obj_priv;
		}

		if (indep_col_specific_privs.psy_col_privs)
		{
		    i4		i, j;
		    PSQ_COLPRIV	*csp;
		    i4		*att_map, *p;
		    i4		priv_map = 0;

		    /*
		    ** privilege map is built using bitwise operators, but
		    ** here using BTnext() makes code much more palatable,
		    ** so convert a privilege map
		    */
		    if (indep_col_specific_privs.psy_col_privs & DB_APPEND)
			BTset(DB_APPP, (char *) &priv_map);
		    if (indep_col_specific_privs.psy_col_privs & DB_REPLACE)
			BTset(DB_REPP, (char *) &priv_map);

		    for (i = -1, csp = col_privs;
			 (i = BTnext(i, (char *) &priv_map, BITS_IN(priv_map)))
			      != -1;
			  csp++
			)
		    {
			csp->psq_next = indep_objs.psq_colprivs;
			indep_objs.psq_colprivs = csp;
			csp->psq_objtype = PSQ_OBJTYPE_IS_TABLE;
			csp->psq_tabid.db_tab_base = indep_id.db_tab_base;
			csp->psq_tabid.db_tab_index = indep_id.db_tab_index;
			switch (i)
			{
			    case DB_APPP:	    /* INSERT privilege */
			    {
				csp->psq_privmap = (i4) DB_APPEND;
				att_map = indep_col_specific_privs.
				    psy_attmap[PSY_INSERT_ATTRMAP].map;
				break;
			    }
			    case DB_REPP:
			    {
				csp->psq_privmap = (i4) DB_REPLACE;
				att_map = indep_col_specific_privs.
				    psy_attmap[PSY_UPDATE_ATTRMAP].map;
				break;
			    }
			}

			for (p = csp->psq_attrmap, j = 0;
			     j < DB_COL_WORDS;
			     j++)
			{
			    *p++ = *att_map++;
			}
		    }
		}
	    }
	}
	else
	{
	    /*
	    ** either this is a catalog and the user has CATUPD or
	    ** this is an extended catalog and the user is the DBA;
	    ** since we may be allowing a user to create a permit by
	    ** circumventing the permit system, we only need to ascertain that
	    ** this is an SQL view
	    */
	    i4	    issql = 0;

	    status = psy_sqlview(rngvar, sess_cb, err_blk, &issql);
	    if (status)
	    {
		goto exit;
	    }
	    if (!issql)
	    {
		/* can only have permits on SQL views */
		psf_error(3598L, 0L, PSF_USERERR, &err_code, err_blk, 1, 
		    psf_trmwhite(sizeof(rngvar->pss_tabname),
			(char *) &rngvar->pss_tabname),
		    &rngvar->pss_tabname);
		status = E_DB_ERROR;
		goto exit;
	    }
	}
    }
    /* Name of user getting permission */
    STRUCT_ASSIGN_MACRO(psy_cb->psy_user, protup->dbp_owner);

    /* Terminal at which permission given */
    STRUCT_ASSIGN_MACRO(psy_cb->psy_terminal, protup->dbp_term);

    /* Give RDF pointer to query tree, if any */
    if (!psy_cb->psy_istree)
    {
	rdf_rb->rdr_qry_root_node = (PTR) NULL;
    }
    else
    {
	PST_VRMAP   varset;
	i4	    j;

	STRUCT_ASSIGN_MACRO(psy_cb->psy_intree, qsf_rb.qsf_obj_id);
	qsf_rb.qsf_lk_state = QSO_EXLOCK;
	status = qsf_call(QSO_LOCK, &qsf_rb);
	if (DB_FAILURE_MACRO(status))
	{
	    (VOID) psf_error(E_PS0D19_QSF_INFO, qsf_rb.qsf_error.err_code,
		PSF_INTERR, &err_code, err_blk, 0);
	    goto exit;
	}

	tree_lock		= qsf_rb.qsf_lk_id;
	pnode = (PST_PROCEDURE *) qsf_rb.qsf_root;
	qtree = (PST_QTREE *) pnode->pst_stmts->pst_specific.pst_tree;
	rdf_rb->rdr_qry_root_node = (PTR) pnode;
	/* check for no views in the qualification.
	*/
	(VOID)psy_varset(qtree->pst_qtree, &varset);	
	j = BTnext(-1, (char *) &varset, BITS_IN(varset));
	for ( ; j >= 0; j = BTnext(j, (char *) &varset, BITS_IN(varset)))
	{
	    status = pst_rgent(sess_cb, rngtab, -1, "", PST_SHWID,
		(DB_TAB_NAME *) NULL, (DB_TAB_OWN *) NULL,
		&qtree->pst_rangetab[j]->pst_rngvar, TRUE,
		&rngvar, (i4) 0, err_blk);
	    if (status)
		goto exit;		

	    if (rngvar->pss_tabdesc->tbl_status_mask & DMT_VIEW)
	    {
		psf_error(3597L, 0L, PSF_USERERR, &err_code, err_blk, 1,
		    psf_trmwhite(sizeof(rngvar->pss_tabname),
			(char *) &rngvar->pss_tabname),
		    &rngvar->pss_tabname);
		    status = E_DB_ERROR;
		    goto exit;
	    }
	}
    }
    
    /* Give RDF a pointer to the query text to be stored in iiqrytext */
    STRUCT_ASSIGN_MACRO(psy_cb->psy_qrytext, qsf_rb.qsf_obj_id);
    qsf_rb.qsf_lk_state = QSO_EXLOCK;
    status = qsf_call(QSO_LOCK, &qsf_rb);
    if (DB_FAILURE_MACRO(status))
    {
	(VOID) psf_error(E_PS0D19_QSF_INFO, qsf_rb.qsf_error.err_code,
	    PSF_INTERR, &err_code, err_blk, 0);
	goto exit;
    }

    text_lock = qsf_rb.qsf_lk_id;

    MEcopy((char *) qsf_rb.qsf_root, sizeof(i4), (char *) &textlen);
    rdf_rb->rdr_l_querytext = textlen;
    rdf_rb->rdr_querytext = ((char *) qsf_rb.qsf_root) + sizeof(i4);
    rdf_rb->rdr_status = (sess_cb->pss_lang == DB_SQL) ? DB_SQL : 0;

    /* determine if the permit specifies exactly one privilege */
    if (BTcount((char *) &psy_cb->psy_opmap, BITS_IN(psy_cb->psy_opmap)) > 1)
    {
	/*
	** if permit specified more than one privilege, notify QEF that it will
	** have to split the permit into multiple IIPROTECT tuples
	*/
	rdf_rb->rdr_instr |= RDF_SPLIT_PERM;
    }
    else if (psy_cb->psy_opmap & DB_RETRIEVE)
    {
	/*
	** if qeu_cprot() will not be splitting the permit into multiple tuples
	** and RETRIEVE is the privilege mentioned in it, set the two bits
	** associated with DB_RETRIEVE
	*/
	psy_cb->psy_opmap |= DB_TEST | DB_AGGREGATE;
	psy_cb->psy_opctl |= DB_TEST | DB_AGGREGATE;
    }

    /* Null out the DMU control block pointer, just in case */
    rdf_rb->rdr_dmu_cb = (PTR) NULL;

    /* produce list of dependent tables */
    rdf_rb->rdr_cnt_base_id = 0;
    if (psy_cb->psy_istree && qtree->pst_qtree) 
    {
	j = 0;
	(VOID)psy_varset(qtree->pst_qtree, &varmap);
	for (i = -1; (i = BTnext(i, (char*) &varmap, PST_NUMVARS)) > -1;)
	{
	    /* if this is the table that is getting the permit, ignore */
	    if (qtree->pst_rangetab[i]->pst_rngvar.db_tab_base != 
		    psy_tbl->psy_tabid.db_tab_base
		||
		qtree->pst_rangetab[i]->pst_rngvar.db_tab_index !=
		    psy_tbl->psy_tabid.db_tab_index
	    )
	    {
		rdf_rb->rdr_cnt_base_id++;
		STRUCT_ASSIGN_MACRO(qtree->pst_rangetab[i]->pst_rngvar,
		    tabids[j++]);
	    }
	}
	rdf_rb->rdr_base_id = tabids;
    }

    protup->dbp_popctl = psy_cb->psy_opctl;
    protup->dbp_popset = psy_cb->psy_opmap;
    
    /*
    ** store an indication of whether this permit is being created using SQL or
    ** QUEL
    */
    protup->dbp_flags = (sess_cb->pss_lang == DB_SQL) ? DBP_SQL_PERM : (i2) 0;
    protup->dbp_flags |= DBP_65_PLUS_PERM;

    /* Now let RDF do all the work of the permit definition */
    status = rdf_call(RDF_UPDATE, (PTR) &rdf_cb);
    if (DB_FAILURE_MACRO(status))
    {
	if (rdf_cb.rdf_error.err_code == E_RD0002_UNKNOWN_TBL)
	{
	    (VOID) psf_error(E_PS0903_TAB_NOTFOUND, 0L, PSF_USERERR,
		&err_code, err_blk, 1,
		psf_trmwhite(sizeof(psy_tbl->psy_tabnm),
		    (char *) &psy_tbl->psy_tabnm),
		&psy_tbl->psy_tabnm);
	}
	else
	{
	    (VOID) psf_rdf_error(RDF_UPDATE, &rdf_cb.rdf_error,
		&psy_cb->psy_error);
	}
	goto exit;
    }

    /*
    ** Invalidate base object's infoblk from RDF cache.
    */
    pst_rdfcb_init(&rdf_cb, sess_cb);
    STRUCT_ASSIGN_MACRO(psy_cb->psy_tables[0], rdf_rb->rdr_tabid);
    status = rdf_call(RDF_INVALIDATE, (PTR) &rdf_cb);
    if (DB_FAILURE_MACRO(status))
    {
	(VOID) psf_rdf_error(RDF_INVALIDATE, &rdf_cb.rdf_error,
				&psy_cb->psy_error);
    }

exit:

    qsf_rb.qsf_lk_state = QSO_EXLOCK;

    if (psy_cb->psy_istree)
    {
	/* Destroy query tree */
	STRUCT_ASSIGN_MACRO(psy_cb->psy_intree, qsf_rb.qsf_obj_id);

	if ((qsf_rb.qsf_lk_id = tree_lock) == 0)
	{
	    stat = qsf_call(QSO_LOCK, &qsf_rb);
	    if (DB_FAILURE_MACRO(stat))
	    {
		(VOID) psf_error(E_PS0D18_QSF_LOCK,
		    qsf_rb.qsf_error.err_code, PSF_INTERR,
		    &err_code, &psy_cb->psy_error, 0);
		if (!status || stat == E_DB_FATAL)
		    status = stat;
	    }
	    tree_lock = qsf_rb.qsf_lk_id;
	}

	stat = qsf_call(QSO_DESTROY, &qsf_rb);
	if (DB_FAILURE_MACRO(stat))
	{
	    (VOID) psf_error(E_PS0D1A_QSF_DESTROY,
		qsf_rb.qsf_error.err_code, PSF_INTERR,
		&err_code, &psy_cb->psy_error, 0);
	    if (!status || stat == E_DB_FATAL)
		status = stat;
	}

	tree_lock = 0;
    }

    /* Destroy query text */
    STRUCT_ASSIGN_MACRO(psy_cb->psy_qrytext, qsf_rb.qsf_obj_id);

    if ((qsf_rb.qsf_lk_id = text_lock) == 0)
    {
	stat = qsf_call(QSO_LOCK, &qsf_rb);
	if (DB_FAILURE_MACRO(stat))
	{
	    (VOID) psf_error(E_PS0D18_QSF_LOCK, qsf_rb.qsf_error.err_code,
		PSF_INTERR, &err_code, &psy_cb->psy_error, 0);
	    if (!status || stat == E_DB_FATAL)
		status = stat;
	}
	text_lock = qsf_rb.qsf_lk_id;
    }

    stat = qsf_call(QSO_DESTROY, &qsf_rb);
    if (DB_FAILURE_MACRO(stat))
    {
	(VOID) psf_error(E_PS0D1A_QSF_DESTROY, qsf_rb.qsf_error.err_code,
	    PSF_INTERR, &err_code, &psy_cb->psy_error, 0);
	if (!status || stat == E_DB_FATAL)
	    status = stat;
    }

    return (status);
}
Esempio n. 24
0
/*
** {
** Name: QEA_RUPDATE		- update the current cursor
**
**  External QEF call:	    status = qef_call(QEQ_REPLACE, &qef_rcb);
**
** Description:
**      The current row in the named cursor (QP) is
**  updated and sent to DMF 
**
** Inputs:
**	action			Update current row of cursor action.
**      qef_rcb
**	assoc_dsh		DSH for QP for cursor to be updated.
**	reset
**	state			DSH_CT_INITIAL if this is an action call
**				DSH_CT_CONTINUE for call back after processing
**				a rule action list.
**
** Outputs:
**      qef_rcb
**	    .qef_remnull	SET if an aggregate computation found a NULL val
**	    .qef_rowcount	number of rows replaced
**	    .qef_targcount	number of attempted replaces 
**	    .error.err_code	one of the following
**				E_QE0000_OK
**				E_QE0017_BAD_CB
**				E_QE0018_BAD_PARAM_IN_CB
**				E_QE0019_NON_INTERNAL_FAIL
**				E_QE0002_INTERNAL_ERROR
**				E_QE0008_CURSOR_NOT_OPENED
**				E_QE0021_NO_ROW
**				E_QE0009_NO_PERMISSION
**				E_QE000A_READ_ONLY
**				E_QE0012_DUPLICATE_KEY
**				E_QE0010_DUPLIATE_ROW
**				E_QE0011_AMBIGUOUS_REPLACE
**				E_QE0013_INTEGRITY_FAILED
**				E_QE0024_TRANSACTION_ABORTED
**				E_QE0034_LOCK_QUOTA_EXCEEDED
**				E_QE0035_LOCK_RESOURCE_BUSY
**				E_QE0036_LOCK_TIMER_EXPIRED
**				E_QE002A_DEADLOCK
**	Returns:
**	    E_DB_{OK,WARN,ERROR,FATAL}
**	Exceptions:
**	    none
**
** Side Effects:
**	    none
**
** History:
**	11-JUN-86 (daved)
**          written
**	22-may-87 (daved)
**	    catch cursor not positioned errors
**	14-oct-87 (puree)
**	    make sure that qen_error is called in case of E_DB_ERROR from
**	    qeq_validate.
**	02-feb-88 (puree)
**	    added reset flag to qeq_validate and all qea_xxxx call sequence.
**	29-aug-88 (puree)
**	    implement replace cursor by tid if the cursor was position on
**	    a secondary index table and by current position if the cursor
**	    is positioned on the base table.
**	    fix duplicate handling error.
**	12-oct-88 (puree)
**	    If a table validation fails during cursor replace, abort the
**	    cursor.
**	23-feb-89 (paul)
**	    Clean up qef_cb state before returning.
**	17-apr-89 (paul)
**	    Processing cursor updates integrated into qeq_query. Update cursor
**	    logic moved from qeq.c to this file (qearupd.c). This routine is
**	    a simplified version of what was previously called qeq_replace.
**	25-sep-89 (paul)
**	    Added support for using TIDs as parameters to procedures invoked
**	    from rules.
**	25-jan-90 (nancy) -- set status to E_DB_OK when replace cursor
**	    causes dups and duplicate handling is set to SKIP_DUPS.
**	29-jan-90 (nancy) -- fix bug 8388 (8575), use assoc dsh for replace
**	    by tid.
**	29-jun-90 (davebf)
**	    Handle rows which were accessed by TID only  (bug 31113)
**       5-Nov-1993 (fred)
**          Remove any remaining large object temporaries.
**       7-Apr-1994 (fred)
**          Commented out large object removal pending better way...
**	7-nov-95 (inkdo01)
**	    Changes to replace QEN_ADF structure instances by pointers in
**	    QEF_AHD structures.
**	29-dec-03 (inkdo01)
**	    DSH is now parameter, "function" replaces "reset".
**	5-feb-04 (inkdo01)
**	    Add support for partitioned tables.
**	12-mar-04 (inkdo01)
**	    Fix to handle bigtids on byte-swapped machines.
**	19-mar-04 (inkdo01)
**	    Fix for bigtids and rules.
**	12-may-04 (inkdo01)
**	    Call qeq_part_open unconditionally - it'll determine whether
**	    partition cbs are already prepared.
**	8-Jul-2004 (schka24)
**	    Still some tid byte-ordering confusion on x86, make tid handling
**	    more portable.
**	26-aug-04 (inkdo01)
**	    Add global base array support for update buffer.
**	24-Feb-05 (hweho01)
**	    The copying of tid needs to be handled differently if   
**          TID_SWAP is defined, so the tid value can be preserved. 
**          Star #13864021.
**	28-Feb-2005 (schka24)
**	    Rework the above fix, it turns out that the underlying problem
**	    was the 4byte-tidp flag not getting set.  Now that it's set
**	    properly, obey it here.  Also, do partition opens against the
**	    cursor query, not the RUP -- it's the one with the valid list..
**	18-Jul-2005 (schka24)
**	    Well, I fixed by-tid updates, but not true in-place updates!
**	    Use new ahd_ruporig machinery to get at the current partition
**	    number for in-place updating.
**	13-Dec-2005 (kschendel)
**	    Can count on qen-ade-cx now.
**	16-Jan-2006 (kschendel)
**	    Access qen-status thru xaddrs.
**	20-june-06 (dougi)
**	    Add support for BEFORE triggers.
**	1-Nov-2006 (kschendel)
**	    Some fixes to BEFORE triggers, make sure things are set up.
**	7-mar-2007 (dougi)
**	    Slight change to address the DMR_CB (broken by BEFORE changes).
**	8-Sep-2008 (kibro01) b120693
**	    Remove unused action parameter from qeq_part_open
**	09-Sep-2009 (thaju02) B122374
**	    If BEFORE trigger has been executed, do not use ahd_upd_colmap.
**	    ahd_upd_colmap may not reflect cols updated by the rule/proc.
**	15-Jan-2010 (jonj)
**	    SIR 121619 MVCC: If E_DM0029_ROW_UPDATE_CONFLICT returned,
**	    invalidate the QP and retry.
**	1-Jul-2010 (kschendel) b124004
**	    Minor changes for RUP from scrollable keyset cursors;  the
**	    fetched row is always in dsh-qef-output.
*/
DB_STATUS
qea_rupdate(
QEF_AHD		    *act,
QEF_RCB		    *qef_rcb,
QEE_DSH		    *dsh,
QEE_DSH		    *assoc_dsh,
i4		    function,
i4		    state )
{
    i4		err;
    DB_STATUS		status	= E_DB_OK;
    QEF_CB		*qef_cb = dsh->dsh_qefcb;
    ADF_CB		*adfcb = dsh->dsh_adf_cb;
    DMR_CB		*dmr_cb, *pdmr_cb;
    QEN_ADF		*qen_adf;
    ADE_EXCB		*ade_excb;
    PTR			*assoc_cbs = assoc_dsh->dsh_cbs;
    PTR			output, save_addr;
    char		*tidinput;  /* location of tid */
    DB_TID8		oldbigtid, newbigtid;
    u_i2		oldpartno = 0;
    u_i2		newpartno = 0;
    i4			odmr_cb_ix;	/* CB number of DMR_CB */
    i4			orig_node;
    
    status = E_DB_OK;
    
    for (;;)
    {
	/* A cursor update affects only a single row. If we are called back  */
	/* after rules processing simply return. */
	if (state == DSH_CT_CONTINUE)
	    break;

	/* Address the DMR_CB used to access the row.  The odmr_cb_ix is in
	** the associated (cursor) QP context.  We'll adjust for partitioning
	** a bit later.
	*/
	odmr_cb_ix = act->qhd_obj.qhd_qep.ahd_odmr_cb;
	dmr_cb = (DMR_CB*) assoc_cbs[odmr_cb_ix];
	if (status == DSH_CT_CONTINUE3)
	{
	    /* Resuming from a BEFORE trigger, reset variables */
	    MEcopy(dsh->dsh_row[act->qhd_obj.qhd_qep.u1.s1.ahd_a_tid],
			sizeof(DB_TID8), (PTR) &newbigtid);
	    MEcopy(dsh->dsh_row[act->qhd_obj.qhd_qep.u1.s1.ahd_b_tid],
			sizeof(DB_TID8), (PTR) &oldbigtid);
	    oldpartno = oldbigtid.tid.tid_partno;
	    newpartno = newbigtid.tid.tid_partno;
	    output = dsh->dsh_row[act->qhd_obj.qhd_qep.u1.s1.ahd_a_row];
	    if (act->qhd_obj.qhd_qep.ahd_part_def != NULL)
		dmr_cb = (DMR_CB *) assoc_cbs[odmr_cb_ix + oldpartno + 1];
	}
	else
	{
	    /* Normal path */
	    dsh->dsh_qef_remnull = 0;
	    dsh->dsh_qef_rowcount = 0;

	    /* Use fetch row for holding update row if need be */
	    output = assoc_dsh->dsh_row[assoc_dsh->dsh_qp_ptr->qp_fetch_ahd->qhd_obj.qhd_qep.ahd_ruprow];

	    /* make sure we have a positioned record */
	    if (assoc_dsh->dsh_positioned == FALSE)
	    {
		/* no record could be valid in this action's updatable control block.
		** Nor do we know what we will be looking at when we access the
		** update control block index number
		*/
		dsh->dsh_error.err_code = E_QE0021_NO_ROW;
		status = E_DB_ERROR;
		break;
	    }

	    /* check that this query plan has update privilege */
	    if ((assoc_dsh->dsh_qp_ptr->qp_status & QEQP_UPDATE) == 0)
	    {
		/* no permission */
		dsh->dsh_error.err_code = E_QE0009_NO_PERMISSION;
		status = E_DB_ERROR;
		break;
    	    }

	    if (qef_cb->qef_c1_distrib & DB_3_DDB_SESS)	/* distributed? */
	    {
		/* DDB processing */

		status = qeq_c5_replace(qef_rcb, dsh);
		if (status == E_DB_OK)
		    dsh->dsh_qef_rowcount = 1;
		else
		    dsh->dsh_qef_rowcount = 0;
		return(status);
	    }

	    /* LDB processing */

	    /* process the qualification expression */
	    qen_adf     = act->qhd_obj.qhd_qep.ahd_constant;
	    if (qen_adf != NULL)
	    {
		ade_excb = (ADE_EXCB*) dsh->dsh_cbs[qen_adf->qen_pos];
		if (dsh->dsh_qp_ptr->qp_status & QEQP_GLOBAL_BASEARRAY)
		    dsh->dsh_row[qen_adf->qen_uoutput] = output;
		else ade_excb->excb_bases[ADE_ZBASE + qen_adf->qen_uoutput] = output;
		status = qen_execute_cx(dsh, ade_excb);
		if (status != E_DB_OK)
		    break;

		/* handle condition where qualification failed. */
		if (ade_excb->excb_value != ADE_TRUE)
		{
		    dsh->dsh_qef_targcount = 1;
		    dsh->dsh_qef_rowcount = 0;
		    break;
		}
	    }

	    /* REPLACE THE TUPLE
	    ** if the cursor is positioned on the base table (ahd_tidoffset is
	    ** -1), replace the tuple at the current position.  Otherwise the
	    ** cursor must have been positioned via a secondary index.  Get
	    ** the tid, re-fetch the original row by tid, and replace the
	    ** base table tuple by the tid.
	    */

	    if (act->qhd_obj.qhd_qep.ahd_tidoffset == -1)
	    {
		/* If partitioned, dig the current partition number out of
		** the node status for the orig (or kjoin/tjoin) node that
		** fetched the row in the first place.  OPC has kindly put
		** the node number of same into ahd_ruporig.
		*/
		if (act->qhd_obj.qhd_qep.ahd_part_def != NULL)
		{
		    orig_node = act->qhd_obj.qhd_qep.ahd_ruporig;
		    if (orig_node == -1)
		    {
			TRdisplay("%@ qea_rupd: missing ahd_ruporig\n");
			dsh->dsh_error.err_code = E_QE0002_INTERNAL_ERROR;
			status = E_DB_ERROR;
			break;
		    }
		    oldpartno = assoc_dsh->dsh_xaddrs[orig_node]->
						qex_status->node_ppart_num;
		    dmr_cb = (DMR_CB *) assoc_cbs[odmr_cb_ix + oldpartno + 1];
		}
		dmr_cb->dmr_flags_mask = DMR_CURRENT_POS;
	    }
	    else
	    {
		/* set the tid */
		tidinput  = 
		    (char *) assoc_dsh->dsh_row[act->qhd_obj.qhd_qep.ahd_tidrow]
				 + act->qhd_obj.qhd_qep.ahd_tidoffset;

		if (act->qhd_obj.qhd_qep.ahd_qepflag & AHD_4BYTE_TIDP)
		{
		    I4ASSIGN_MACRO(*tidinput, oldbigtid.tid_i4.tid );
		    oldbigtid.tid_i4.tpf = 0;
		}
		else
		{
		    I8ASSIGN_MACRO(*tidinput, oldbigtid);
		}
		oldpartno = oldbigtid.tid.tid_partno;
		newpartno = oldpartno;
	
		/* Check for partitioning and set up DMR_CB. */
		if (act->qhd_obj.qhd_qep.ahd_part_def)
		{
		    /* Open against "get" action.  The RUP action dmtix and
		    ** flags are the same as the cursor's, thanks to OPC.
		    */
		    status = qeq_part_open(qef_rcb, assoc_dsh, NULL, 0, 
			odmr_cb_ix,
			act->qhd_obj.qhd_qep.ahd_dmtix, oldpartno);
			
		    if (status != E_DB_OK)
		    {
			dsh->dsh_error.err_code = assoc_dsh->dsh_error.err_code;
			return(status);
		    }
		    pdmr_cb = (DMR_CB *)assoc_cbs[odmr_cb_ix + oldpartno+1];

		    STRUCT_ASSIGN_MACRO(dmr_cb->dmr_data, pdmr_cb->dmr_data);
		    dmr_cb = pdmr_cb;
		}
		dmr_cb->dmr_tid = oldbigtid.tid_i4.tid;
		dmr_cb->dmr_flags_mask = DMR_BY_TID;
	
		/* get the tuple to be updated. */
		save_addr = dmr_cb->dmr_data.data_address;
		dmr_cb->dmr_data.data_address = output;
		status = dmf_call(DMR_GET, dmr_cb);
		dmr_cb->dmr_data.data_address = save_addr;
		if (status != E_DB_OK)
		{
		    dsh->dsh_error.err_code = dmr_cb->error.err_code;
		    return (status);
		}
	    }

	    /* If we have rules, save a copy of the row before updating */
	    if (act->qhd_obj.qhd_qep.ahd_after_act != NULL ||
		act->qhd_obj.qhd_qep.ahd_before_act != NULL)
	    {
		MEcopy(output, act->qhd_obj.qhd_qep.ahd_repsize,
		    dsh->dsh_row[act->qhd_obj.qhd_qep.u1.s1.ahd_b_row]);
		oldbigtid.tid_i4.tpf = 0;
		oldbigtid.tid_i4.tid = dmr_cb->dmr_tid;
		oldbigtid.tid.tid_partno = oldpartno;
	    }

	    /* process the update expression */
	    qen_adf     = act->qhd_obj.qhd_qep.ahd_current;
	    ade_excb    = (ADE_EXCB*) dsh->dsh_cbs[qen_adf->qen_pos];	
	    if (dsh->dsh_qp_ptr->qp_status & QEQP_GLOBAL_BASEARRAY)
		dsh->dsh_row[qen_adf->qen_uoutput] = output;
	    else ade_excb->excb_bases[ADE_ZBASE+qen_adf->qen_uoutput] = output;

	    status = qen_execute_cx(dsh, ade_excb);
	    if (status != E_DB_OK)
		break;

	    /* Check for partitioning and see if we changed target partition. */
	    if (act->qhd_obj.qhd_qep.ahd_part_def && 
		(act->qhd_obj.qhd_qep.ahd_qepflag & AHD_PCOLS_UPDATE))
	    {
		status = adt_whichpart_no(adfcb,
			act->qhd_obj.qhd_qep.ahd_part_def, 
			output, &newpartno);
		if (status != E_DB_OK)
		    return(status);
	    }
	    /* Process BEFORE triggers (if any). */
	    if (act->qhd_obj.qhd_qep.ahd_before_act != NULL)
	    {
		/*
		** Place the TID in a known location so it can be used
		** as a parameter to the procedure fired by the rule.
		*/
		newbigtid.tid_i4.tpf = 0;
		newbigtid.tid_i4.tid = dmr_cb->dmr_tid;
		newbigtid.tid.tid_partno = newpartno;
		MEcopy ((PTR)&newbigtid, sizeof(DB_TID8),
			dsh->dsh_row[act->qhd_obj.qhd_qep.u1.s1.ahd_a_tid]);   
		MEcopy ((PTR)&oldbigtid, sizeof(DB_TID8),
			dsh->dsh_row[act->qhd_obj.qhd_qep.u1.s1.ahd_b_tid]);   

		MEcopy(output, act->qhd_obj.qhd_qep.ahd_repsize,
			dsh->dsh_row[act->qhd_obj.qhd_qep.u1.s1.ahd_a_row]);
		dsh->dsh_ctx_act[dsh->dsh_depth_act].dsh_ct_ptr = act;
		dsh->dsh_ctx_act[dsh->dsh_depth_act].dsh_ct_status =
			DSH_CT_CONTINUE3;
		dsh->dsh_depth_act++;
		dsh->dsh_act_ptr = act->qhd_obj.qhd_qep.ahd_before_act;
		dsh->dsh_error.err_code = E_QE0120_RULE_ACTION_LIST;
		status = E_DB_ERROR;
		break;
	    }
	}    /* end of !DSH_CT_CONTINUE3 */

	state = DSH_CT_INITIAL;			/* signal resumption after
						** BEFORE trigger */

	if (act->qhd_obj.qhd_qep.ahd_qepflag & AHD_PCOLS_UPDATE &&
		oldpartno != newpartno)
	{
	    /* Partition has changed for row in partitioned table.
	    ** Delete from 1st partition and insert into next.
	    ** We have to hope that DMF can keep it all straight.
	    */
	    status = dmf_call(DMR_DELETE, dmr_cb);
	    if (status != E_DB_OK)
	    {
		if (dmr_cb->error.err_code == E_DM0055_NONEXT)
		    dsh->dsh_error.err_code = 4599;
		else
		    dsh->dsh_error.err_code = dmr_cb->error.err_code;
		break;
	    }

	    /* Get output partition DMR_CB, then do DMR_PUT.
	    ** Don't change the fetching DSH's current dmr-cb in case
	    ** we're running a true in-place cursor.
	    */
	    status = qeq_part_open(qef_rcb, assoc_dsh, NULL, 0, 
		odmr_cb_ix,
		act->qhd_obj.qhd_qep.ahd_dmtix, newpartno);
			
	    if (status != E_DB_OK)
	    {
		dsh->dsh_error.err_code = assoc_dsh->dsh_error.err_code;
		return(status);
	    }
	    dmr_cb = (DMR_CB *)assoc_cbs[odmr_cb_ix + newpartno+1];

	    dsh->dsh_qef_targcount = 1;
	    /* Final preparation of new partition DMR_CB. */
	    dmr_cb->dmr_flags_mask = 0;
	    dmr_cb->dmr_val_logkey = 0;
	    dmr_cb->dmr_data.data_address = output;
	    dmr_cb->dmr_data.data_in_size  =
				act->qhd_obj.qhd_qep.ahd_repsize;
	    if (act->qhd_obj.qhd_qep.ahd_duphandle != QEF_SKIP_DUP)
		dmr_cb->dmr_flags_mask |= DMR_DUP_ROLLBACK;
	    status = dmf_call(DMR_PUT, dmr_cb);

	}
	else
	{
	    dsh->dsh_qef_targcount = 1;
	    if ((act->qhd_obj.qhd_qep.ahd_upd_colmap) && 
		(act->qhd_obj.qhd_qep.ahd_before_act == NULL))
		dmr_cb->dmr_attset = 
			(char *)act->qhd_obj.qhd_qep.ahd_upd_colmap;
	    else
		dmr_cb->dmr_attset = (char *)0;

	    if (act->qhd_obj.qhd_qep.ahd_duphandle != QEF_SKIP_DUP)
		dmr_cb->dmr_flags_mask |= DMR_DUP_ROLLBACK;
	    status = dmf_call(DMR_REPLACE, dmr_cb);
	}
	    
	if (status == E_DB_OK || 
		((dmr_cb->error.err_code == E_DM0046_DUPLICATE_RECORD ||
		  dmr_cb->error.err_code == E_DM0045_DUPLICATE_KEY    ||
		  dmr_cb->error.err_code == E_DM0048_SIDUPLICATE_KEY) &&
		 act->qhd_obj.qhd_qep.ahd_duphandle == QEF_SKIP_DUP))
	{
	    if (status == E_DB_OK)
	    {
	    	dsh->dsh_qef_rowcount = 1;
		/* Look for rules to apply */
		if (act->qhd_obj.qhd_qep.ahd_after_act != NULL)
		{
		    /*
		    ** Place the TID in a known location so it can be used
		    ** as a parameter to the procedure fired by the rule.
		    */
		    newbigtid.tid_i4.tpf = 0;
		    newbigtid.tid_i4.tid = dmr_cb->dmr_tid;
		    newbigtid.tid.tid_partno = newpartno;
		    MEcopy ((PTR)&newbigtid, sizeof(DB_TID8),
			dsh->dsh_row[act->qhd_obj.qhd_qep.u1.s1.ahd_a_tid]);   
		    MEcopy ((PTR)&oldbigtid, sizeof(DB_TID8),
			dsh->dsh_row[act->qhd_obj.qhd_qep.u1.s1.ahd_b_tid]);   

		    MEcopy(output, act->qhd_obj.qhd_qep.ahd_repsize,
			dsh->dsh_row[act->qhd_obj.qhd_qep.u1.s1.ahd_a_row]);
		    dsh->dsh_ctx_act[dsh->dsh_depth_act].dsh_ct_ptr = act;
		    dsh->dsh_ctx_act[dsh->dsh_depth_act].dsh_ct_status =
			DSH_CT_CONTINUE;
		    dsh->dsh_depth_act++;
		    dsh->dsh_act_ptr = act->qhd_obj.qhd_qep.ahd_after_act;
		    dsh->dsh_error.err_code = E_QE0120_RULE_ACTION_LIST;
		    status = E_DB_ERROR;
		    break;
		}
	    }
	    else
	    {
		dsh->dsh_qef_rowcount = 0;
		status = E_DB_OK;
	    }	
	    break;	    
	}
	
	if (dmr_cb->error.err_code == E_DM0055_NONEXT)
	    dsh->dsh_error.err_code = 4599;
	else
	if ( dmr_cb->error.err_code == E_DM0029_ROW_UPDATE_CONFLICT )
	{
	    dsh->dsh_qp_status |= DSH_QP_OBSOLETE;
	    dsh->dsh_error.err_code = E_QE0023_INVALID_QUERY;
	    status = E_DB_WARN;
	}
	else
	    dsh->dsh_error.err_code = dmr_cb->error.err_code;
	break;
    }

    return (status);
}
Esempio n. 25
0
/*{
** Name: psq_cbreturn	- Clear call and session CB after processing.
**
** Description:
**	This routine is a common routine that clears up the call (psq_cb) and
**	session CB (sess_cb) after processing a query.  The routine
**	psq_parseqry still does its own work as it handles various errors
**	associated with textual queries.
**
** Inputs:
**      psq_cb				Pointer to call CB.
**	sess_cb				Pointer to the session control block
**
** Outputs:
**      psq_cb			
**		.psq_result		Result query tree.
**	Returns:
**	    DB_STATUS
**	Exceptions:
**	    None
**
** Side Effects:
**	    None
**
** History:
**	21-apr-89 (neil)
**	    Extracted this from psq_parseqry to allow it to be called from
**	    other routines as well.
**	15-jun-92 (barbara)
**	    Sybil merge.  Pass in sess control block to pst_clrrng.
**	25-may-1993 (rog)
**	    Moved clean-up/exit code here from psq_parseqry() above, and added
**	    status argument so that we know whether to execute the good exit
**	    code or the bad exit code.
**	10-aug-93 (andre)
**	    fixed cause of a compiler warning
**	27-aug-93 (andre)
**		(part of fix for bug 54348)
**	    moved code responsible for destroying a dbproc QEP into a separate 
**	    function (psq_destr_dbp_qep()) which will be called from 
**	    psq_cbreturn() and from psq_recreate() if an error occurs AFTER the
**	    dbproc QEP QSF object has been created
**	16-mar-94 (andre)
**	    use psf_retry() to determine whether we are going to retry parsing 
**	    this query and, therefore, whether we should destroy any QSF objects
**	    created during the just completed attempt 
**	28-jan-2004 (schka24)
**	    Close partition def memory if open.
**	15-Mar-2006 (kschendel)
**	    Close function-arg stream if open.
**	28-nov-2007 (dougi)
**	    Different logic for PSQ_REPDYN (for cached dynamic queries).
*/
DB_STATUS
psq_cbreturn(
	PSQ_CB     *psq_cb,
	PSS_SESBLK *sess_cb,
	DB_STATUS   ret_val)
{
    DB_STATUS		status;
    i4		err_code;
    QSF_RCB		qsf_rb;

    qsf_rb.qsf_type = QSFRB_CB;
    qsf_rb.qsf_ascii_id = QSFRB_ASCII_ID;
    qsf_rb.qsf_length = sizeof(qsf_rb);
    qsf_rb.qsf_owner = (PTR)DB_PSF_ID;
    qsf_rb.qsf_sid = sess_cb->pss_sessid;

    /* Tasks that are common to both a normal return and an error return. */

    do	/* Something to break out of */
    {
	/* Clear any cached stack blocks as we're going to
	** trash the memory stream in here anyway. */
	sess_cb->pss_stk_freelist = NULL;

	/* Other stuff that shouldn't be left dangling */
	sess_cb->pss_yyvars = NULL;

	/*
	** Clear out the user's range table.
	*/
	status = pst_clrrng(sess_cb, &sess_cb->pss_usrrange,
			    &psq_cb->psq_error);
	if (status == E_DB_FATAL)
	    ret_val = status;

	/*
	** Clear out the auxliary range table.
	*/
	status = pst_clrrng(sess_cb, &sess_cb->pss_auxrng, &psq_cb->psq_error);
	if (status == E_DB_FATAL)
	    ret_val = status;

	/*
	** If the statement has emitted query text, close the stream.
	*/
	if (sess_cb->pss_tchain != (PTR) NULL)
	{
	    status = psq_tclose(sess_cb->pss_tchain, &psq_cb->psq_error);
	    if (status == E_DB_FATAL)
		ret_val = status;

	    sess_cb->pss_tchain = (PTR) NULL;
	}

	if (sess_cb->pss_tchain2 != (PTR) NULL)
	{
	    status = psq_tclose(sess_cb->pss_tchain2, &psq_cb->psq_error);
	    if (status == E_DB_FATAL)
		ret_val = status;

	    sess_cb->pss_tchain2 = (PTR) NULL;
	}

	/* Close partition definition working memory stream if in use */
	if (sess_cb->pss_ses_flag & PSS_PARTDEF_STREAM_OPEN)
	{
	    status = ulm_closestream(&sess_cb->pss_partdef_stream);
	    /* Toss any error */
	    sess_cb->pss_ses_flag &= ~PSS_PARTDEF_STREAM_OPEN;
	}

	/* Close nested-function-call arg list stack if it was needed */
	if (sess_cb->pss_funarg_stream != NULL)
	{
	    ULM_RCB ulm;

	    ulm.ulm_facility = DB_PSF_ID;
	    ulm.ulm_poolid = Psf_srvblk->psf_poolid;
	    ulm.ulm_streamid_p = &sess_cb->pss_funarg_stream;
	    ulm.ulm_memleft = &sess_cb->pss_memleft;
	    status = ulm_closestream(&ulm);
	    /* Ignore error */
	    sess_cb->pss_funarg_stream = NULL;
	}

    } while (0);

    for (; ret_val == E_DB_OK; )	/* Something to break out of */
    {
	/*
	** This is the path we take for a successful exit.
	** If we have a problem here, we break out of this loop and
	** fall through to the failure exit code.
	*/

	/*
	** Set the QSF id of the return object and unlock it, if any.
	*/
	if (sess_cb->pss_ostream.psf_mstream.qso_handle != (PTR) NULL)
	{
	    qsf_rb.qsf_obj_id.qso_handle =
		sess_cb->pss_ostream.psf_mstream.qso_handle;
	    qsf_rb.qsf_lk_id = sess_cb->pss_ostream.psf_mlock;

	    if (psq_cb->psq_mode == PSQ_REPDYN)
	    {
		/* If cached dynamic qp already exists, destroy parse
		** tree object. */
		if (ret_val = qsf_call(QSO_DESTROY, &qsf_rb))
		{
		    (VOID) psf_error(E_PS0A09_CANTDESTROY,
			qsf_rb.qsf_error.err_code, PSF_INTERR, &err_code,
			&psq_cb->psq_error, 0);

		    /* break out to the failure code. */
		    break;
		}
	    }
	    else
	    {
		/* If not cached dynamic, copy object ID and unlock
		** parse tree. */
		STRUCT_ASSIGN_MACRO(sess_cb->pss_ostream.psf_mstream,
				psq_cb->psq_result);
		if (ret_val = qsf_call(QSO_UNLOCK, &qsf_rb))
		{
		    (VOID) psf_error(E_PS0B05_CANT_UNLOCK,
			qsf_rb.qsf_error.err_code, PSF_INTERR, &err_code,
			&psq_cb->psq_error, 0);

		    /* break out to the failure code. */
		    break;
		}
	    }
	    sess_cb->pss_ostream.psf_mlock = 0;
	}

	/*
	** Unlock the text stream if it was used.
	** this is unlocked after the text stream is created.
	** (Don't know why this was taken out.)
	*/
#ifdef NO
	if (sess_cb->pss_tstream.psf_mstream.qso_handle != (PTR) NULL)
	{
	    qsf_rb.qsf_obj_id.qso_handle =
		sess_cb->pss_tstream.psf_mstream.qso_handle;
	    qsf_rb.qsf_lk_id = sess_cb->pss_tstream.psf_mlock;
	    if (ret_val = qsf_call(QSO_UNLOCK, &qsf_rb))
	    {
		(VOID) psf_error(E_PS0B05_CANT_UNLOCK,
				 qsf_rb.qsf_error.err_code, PSF_INTERR,
				 &err_code, &psq_cb->psq_error, 0);

		/* break out to the failure code. */
		break;
	    }
	    sess_cb->pss_tstream.psf_mlock = 0;
	}
#endif
	/* Unlock the control block stream if it was used */
	if (sess_cb->pss_cbstream.psf_mstream.qso_handle != (PTR) NULL)
	{
	    qsf_rb.qsf_obj_id.qso_handle =
		sess_cb->pss_cbstream.psf_mstream.qso_handle;
	    qsf_rb.qsf_lk_id = sess_cb->pss_cbstream.psf_mlock;
	    if (ret_val = qsf_call(QSO_UNLOCK, &qsf_rb))
	    {
		(VOID) psf_error(E_PS0B05_CANT_UNLOCK,
				 qsf_rb.qsf_error.err_code, PSF_INTERR,
				 &err_code, &psq_cb->psq_error, 0);

		/* break out to the failure code. */
		break;
	    }
	    sess_cb->pss_cbstream.psf_mlock = 0;
	}

	/*
	** We need to deallocate memory if the same query is to be tried
	** again. This is supposed to fix The 'drop table, nonexistent_table'
	** memory leak problem.
	*/
	if (psf_retry(sess_cb, psq_cb, ret_val))
	{
	    if (sess_cb->pss_ostream.psf_mstream.qso_handle != (PTR) NULL)
	    {
		(VOID) psf_mclose(sess_cb, &sess_cb->pss_ostream, &psq_cb->psq_error);
		sess_cb->pss_ostream.psf_mstream.qso_handle = (PTR) NULL;
	    }

	    if (sess_cb->pss_tstream.psf_mstream.qso_handle != (PTR) NULL)
	    {
		(VOID) psf_mclose(sess_cb, &sess_cb->pss_tstream, &psq_cb->psq_error);
		sess_cb->pss_tstream.psf_mstream.qso_handle = (PTR) NULL;
	    }

	    if (sess_cb->pss_cbstream.psf_mstream.qso_handle != (PTR) NULL)
	    {
		(VOID) psf_mclose(sess_cb, &sess_cb->pss_cbstream, &psq_cb->psq_error);
		sess_cb->pss_cbstream.psf_mstream.qso_handle = (PTR) NULL;
	    }
	}

	/* end with no output streams */
	sess_cb->pss_ostream.psf_mstream.qso_handle = (PTR) NULL;
	sess_cb->pss_tstream.psf_mstream.qso_handle = (PTR) NULL;
	sess_cb->pss_cbstream.psf_mstream.qso_handle = (PTR) NULL;

	if (ret_val == E_DB_OK)
	{
	    /*
	    ** this IF statement is here to keep acc from complaining - we would
	    ** never reach this point unless ret_val was E_DB_OK
	    */
	    return (ret_val);
	}
    }

    /* This is the failure exit code. */

    /*
    ** On an error, the yacc error handling function will call psf_error.
    ** All that's necessary here is to return a status indicating that
    ** an error has occurred.  If an output object has been allocated,
    ** and the error caused the statement to fail, deallocate the object
    ** before returning.  Same for miscellaneous objects, like control
    ** blocks and query text.
    */
    if (ret_val == E_DB_ERROR || ret_val == E_DB_FATAL ||
	ret_val == E_DB_SEVERE)
    {
	/* 
	** In case of CREATE PROCEDURE statement we also need to 
	** destroy the QEP object in QSF if it was created.
	*/
	if (sess_cb->pss_ostream.psf_mstream.qso_handle != (PTR) NULL &&
	    psq_cb->psq_mode == PSQ_CREDBP
	   )
	{
	    DB_STATUS	stat;

	    stat = 
		psq_destr_dbp_qep(sess_cb, 
		    sess_cb->pss_ostream.psf_mstream.qso_handle, 
		    &psq_cb->psq_error);
	    if (stat > ret_val)
		ret_val = stat;
        }

	if (sess_cb->pss_ostream.psf_mstream.qso_handle != (PTR) NULL)
	{
	    (VOID) psf_mclose(sess_cb, &sess_cb->pss_ostream, &psq_cb->psq_error);
	    sess_cb->pss_ostream.psf_mstream.qso_handle = (PTR) NULL;
	}

	if (sess_cb->pss_tstream.psf_mstream.qso_handle != (PTR) NULL)
	{
	    (VOID) psf_mclose(sess_cb, &sess_cb->pss_tstream, &psq_cb->psq_error);
	    sess_cb->pss_tstream.psf_mstream.qso_handle = (PTR) NULL;
	}

	if (sess_cb->pss_cbstream.psf_mstream.qso_handle != (PTR) NULL)
	{
	    (VOID) psf_mclose(sess_cb, &sess_cb->pss_cbstream, &psq_cb->psq_error);
	    sess_cb->pss_cbstream.psf_mstream.qso_handle = (PTR) NULL;
	}
    }

    /*
    ** If the statement was a "define cursor" or a "define repeat cursor",
    ** we have to deallocate the cursor control block, if it was allocated.
    */
    if (sess_cb->pss_cstream != (PTR) NULL)
    {
	status = psq_delcursor(sess_cb->pss_crsr, &sess_cb->pss_curstab,
	    &sess_cb->pss_memleft, &psq_cb->psq_error);
	if (status == E_DB_FATAL)
	    ret_val = status;
    }

    return(ret_val);
}
Esempio n. 26
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;
}
Esempio n. 27
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 */
Esempio n. 28
0
/*{
** Name: DI_slave_write -  Request a slave to writes page(s) to a file on disk.
**
** Description:
**	This routine was created to make DIwrite more readable once
**	error checking had been added. See DIwrite for comments.
**
** Inputs:
**      f                    Pointer to the DI file
**                           context needed to do I/O.
**	diop		     Pointer to dilru file context.
**      buf                  Pointer to page(s) to write.
**      page                 Value indicating page(s) to write.
**	num_of_pages	     number of pages to write
**      
** Outputs:
**      err_code             Pointer to a variable used
**                           to return operating system 
**                           errors.
**    Returns:
**          OK
**	    other errors.
**    Exceptions:
**        none
**
** Side Effects:
**        none
**
** History:
**    30-nov-1992 (rmuth)
**	    Created.
**      10-oct-1993 (mikem)
**          bug #47624
**          Bug 47624 resulted in CSsuspend()'s from the DI system being woken
**          up early.  Mainline DI would then procede while the slave would
**          actually be processing the requested asynchronous action.  Various
**          bad things could happen after this depending on timing: (mainline
**          DI would change the slave control block before slave read it,
**          mainline DI would call DIlru_release() and ignore it failing which
**          would cause the control block to never be freed eventually leading
**          to the server hanging when it ran out of slave control blocks, ...
**
**          Fixes were made to scf to hopefully eliminate the unwanted
**          CSresume()'s.  In addition defensive code has been added to DI
**          to catch cases of returning from CSresume while the slave is
**          operating, and to check for errors from DIlru_release().  Before
**          causing a slave to take action the master will set the slave
**          control block status to DI_INPROGRESS, the slave in turn will not
**          change this status until it has completed the operation.
**
**          The off by one error was caused by the CSsuspend called by 
**	    DI_slave_send() returning early in the case of a DIwrite() of one 
**	    page.  The old write loop would increment disl->pre_seek before the
**	    slave had actually read the control block so the slave would write 
**	    the data from page N to the N+1 location in the file.  The 
**	    DI_INPROGRESS flag should stop this, and at least in the one page 
**	    write case we no longer increment disl->pre_seek.
**	23-aug-1993 (bryanp)
**	    If segment isn't yet mapped, map it!
**	01-oct-1998 (somsa01)
**	    Return DI_NODISKSPACE when we are out of disk space.
*/
static STATUS
DI_slave_write(
    DI_IO	*f,
    DI_OP	*diop,
    char        *buf,
    i4	page,
    i4	num_of_pages,
    CL_ERR_DESC *err_code)
{
    register DI_SLAVE_CB	*disl;
    ME_SEG_INFO			*seginfo;
    bool			direct_write;
    STATUS			big_status = OK, small_status = OK;
    STATUS			intern_status = OK, status;

    /* unix variables */
    int		bytes_to_write;

    do
    {
        disl = diop->di_evcb;
	bytes_to_write = (f->io_bytes_per_page * (num_of_pages));

	/*
	** Determine whether we're writing from shared memory, and set
	** up the segment ID and offset correctly.
	*/
	seginfo = ME_find_seg( buf, (char *)buf + bytes_to_write,
			       &ME_segpool);

	if (seginfo != 0 && (seginfo->flags & ME_SLAVEMAPPED_MASK) == 0)
	{
	    status = DI_lru_slmapmem(seginfo, &intern_status, &small_status);
	    if (status)
		break;
	}

        if (seginfo != 0 && (seginfo->flags & ME_SLAVEMAPPED_MASK) != 0)
	{
	    direct_write = TRUE;
	    MEcopy( (PTR)seginfo->key, sizeof(disl->seg_key),
	            (PTR)disl->seg_key);

	    disl->seg_offset = (char *)buf - (char *)seginfo->addr;
	}
	else
	{
	    direct_write = FALSE;
	    seginfo = ME_find_seg(disl->buf, disl->buf, &ME_segpool);
	    if (seginfo)
	    {
	        MEcopy( (PTR)seginfo->key, sizeof(disl->seg_key),
			(PTR)disl->seg_key);

	        disl->seg_offset= (char *)disl->buf - (char *)seginfo->addr;
	    }
	    else
	    {
	        small_status = DI_BADWRITE;
	    	break;
	    }
	}

	/* Send file properties to slave */
	FPROP_COPY(f->io_fprop,disl->io_fprop);

	disl->pre_seek = 
	    (OFFSET_TYPE)(f->io_bytes_per_page) * (OFFSET_TYPE)(page);
	disl->file_op = DI_SL_WRITE;

	/*
	** Write the data
	*/
	do 
	{
	    if (direct_write)
		disl->length = bytes_to_write;
	    else
	    {
		disl->length = min(bytes_to_write, Cs_srv_block.cs_size_io_buf);
		MEcopy((PTR)buf, disl->length, (PTR)disl->buf);
	    }

	    DI_slave_send( disl->dest_slave_no, diop,
		           &big_status, &small_status, &intern_status);

	    if (( big_status != OK ) || (small_status != OK ))
		break;

	    if ((small_status = disl->status) != OK )
	    {
		STRUCT_ASSIGN_MACRO(disl->errcode, *err_code);
	    }

	    if ((small_status != OK) || (disl->length == 0))
	    {
		switch( err_code->errnum )
		{
		case EFBIG:
		    small_status = DI_BADEXTEND;
		    break;
		case ENOSPC:
		    small_status = DI_NODISKSPACE;
		    break;
#ifdef EDQUOT
		case EDQUOT:
		    small_status = DI_EXCEED_LIMIT;
		    break;
#endif
		default:
		    small_status = DI_BADWRITE;
		    break;
		}

		break;
	    }

	    bytes_to_write -= disl->length;
	    buf += disl->length;
	    if (bytes_to_write > 0)
		disl->pre_seek += (OFFSET_TYPE)disl->length;

	} while ( bytes_to_write > 0);

    } while (FALSE);


    if (big_status != OK )
	small_status = big_status;

    if (small_status != OK )
        DIlru_set_di_error( &small_status, err_code, intern_status,
			    DI_GENERAL_ERR);

    return( small_status );
}
Esempio n. 29
0
static  i4
ad0_clmatch(
ADULcstate	*pat,	    /* the string holding the pattern matching char */
u_char		*endpat,    /* end of the pattern string */
ADULcstate	*str,	    /* the other string */
u_char		*endstr,    /* end of the string */
bool		bignore)    /* If TRUE, ignore blanks and null chars */
{
    i4			oldc;
    i4			found;
    i4			bfound;
    i4			ret_val = -1;
    auto ADULcstate	sst, pst;

    oldc = 0;

    adulnext(pat);

    /* Look for an empty range, if found, just ignore it */
    while (adulptr(pat) < endpat)
    {
	if (adultrans(pat)/COL_MULTI == DB_PAT_RBRAC)
	{
	    /* empty range, ignore it */
	    adulnext(pat);
	    return (ad0_3clexc_pm(pat, endpat, str, endstr, FALSE, bignore));
	}
	else
	{
	    if (bignore && (adulspace(pat)  || adultrans(pat) == 0))
		adulnext(pat);
	    else
		break;
	}
    }


    /* find a non-blank, non-null char in s, if ignoring these */
    while (adulptr(str) < endstr)
    {
	if (bignore && (adulspace(str)  || adultrans(str) == 0))
	{
	    adulnext(str);
	    continue;
	}

	/* search for a match on 'c' */
	found = 0;	/* assume failure */
	bfound = 0;	/* assume failure */

	while (adulptr(pat) < endpat)
	{
	    switch(adultrans(pat)/COL_MULTI)
	    {
	      case DB_PAT_RBRAC:
		{
		    adulnext(pat);
		    if (bfound)
		    {   /*
			** Since we found a blank or null char in the pattern
			** range, and blanks and null chars are being ignored,
			** try this first to see if the two are equal by
			** ignoring the range altogether.
			*/
			STRUCT_ASSIGN_MACRO(*pat, pst);
			STRUCT_ASSIGN_MACRO(*str, sst);
			ret_val = ad0_3clexc_pm(&pst, endpat,
						&sst, endstr, FALSE, bignore);
		    }

		    if (ret_val != 0  && found)
		    {
			adulnext(str);
			ret_val = ad0_3clexc_pm(pat, endpat,
						str, endstr, FALSE, bignore);
		    }
		    return (ret_val);
		}

	      case AD_DASH_CHAR:
		if (oldc == 0 || (adulnext(pat), adulptr(pat) >= endpat))
		    return (-1);    /* not found ... really an error */
	    
		if (oldc - adultrans(str) <= 0 && adulcmp(pat, str) >= 0)
		    found++;
		break;

	      default:
		oldc = adultrans(pat);

		if (bignore && (adulspace(pat) || oldc == 0))
		    bfound++;

		if (adultrans(str) == oldc)
		    found++;
	    }
	    adulnext(pat);
	}
	return (-1);    /* no match ... this should actually be an error,
			** because if we reach here, we would have an LBRAC
			** without an associated RBRAC.
			*/
    }
    return (1);
}
Esempio n. 30
0
static  i4
ad0_cpmatch(
ADULcstate      *pat,       /* the string holding the pattern matching char */
u_char	    	*endpat,    /* pointer to end of pattern char string */
ADULcstate	*str,       /* the string to be checked */
u_char	    	*endstr,    /* pointer to end of string */
bool		bignore)    /* if TRUE, we ignore blanks and null chars */
{
    ADULcstate	    psave;
    ADULcstate	    ssave;
    u_i4	    c;
    u_i4	    d;

    adulnext(pat);

    /*
    ** Skip over blanks and null chars if requested -- This fixes a
    ** bug where "a* " would not match "aaa".  The extra space after
    ** the '*' is often put in by EQUEL programs.
    */
    while (    adulptr(pat) < endpat
	    && bignore
	    && (adulspace(pat)  ||  (c = adultrans(pat)) == 0)
	  )
    {
        adulnext(pat);
    }

    if (adulptr(pat) >= endpat)
        return  (0);    /* a match if no more chars in p */

    /*
    ** If the next character in "pat" is not another
    ** pattern matching character, then scan until
    ** first matching char and continue comparison.
    */
    c = adultrans(pat)/COL_MULTI;
    if (c != DB_PAT_ANY && c != DB_PAT_LBRAC && c != DB_PAT_ONE)
    {
        while (adulptr(str) < endstr)
        {
            d = adultrans(str)/COL_MULTI;
            if (    adulcmp(pat, str) == 0
		||  d == DB_PAT_ANY
		||  d == DB_PAT_LBRAC
		||  d == DB_PAT_ONE
	       )
            {
		STRUCT_ASSIGN_MACRO(*pat, psave);
		STRUCT_ASSIGN_MACRO(*str, ssave);
                if (ad0_3clexc_pm(&psave, endpat, &ssave, endstr,
				  FALSE, bignore) == 0)
                    return (0);
            }
            adulnext(str);
        }
    }
    else
    {
        while (adulptr(str) < endstr)
	{
	    STRUCT_ASSIGN_MACRO(*pat, psave);
	    STRUCT_ASSIGN_MACRO(*str, ssave);
            if (ad0_3clexc_pm(&psave, endpat, &ssave, endstr,
			      FALSE, bignore) == 0)
                return (0); /* match */
	    _VOID_ adultrans(str);
	    adulnext(str);
	}
    }
    return (-1);    /* no match */
}