Exemplo n.º 1
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);
}
Exemplo n.º 2
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 */
Exemplo n.º 3
0
DB_STATUS
psy_asequence(
	PSY_CB	   *psy_cb,
	PSS_SESBLK *sess_cb)
{
    RDF_CB		rdf_cb;
    RDR_RB		*rdf_rb = &rdf_cb.rdf_rb;
    DB_IISEQUENCE	*newseqp;
    DB_STATUS		status;

    newseqp = &psy_cb->psy_tuple.psy_sequence;	/* update values */

    /* 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_REPLACE;
    rdf_rb->rdr_qrytuple    = (PTR)newseqp;		/* modified iisequence tuple */

    /* Update existing 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_asequence */
Exemplo n.º 4
0
/*{
** Name: psy_kuser - Destroy user
**
**  INTERNAL PSF call format: status = psy_kuser(&psy_cb, sess_cb);
**
** Description:
**	This procedure deletes a user.  If the
**	user does not exist, the statement is aborted.
**	If the user does exist, the associated
**	iiuser tuple is deleted.
**	This procedure is called for SQL language only.
**
** Inputs:
**      psy_cb
**	    .psy_usrq			user list
**	sess_cb				Pointer to session control block
**					(Can be NULL)
**
** Outputs:
**      psy_cb
**	    .psy_error			Filled in if error happens
**	Returns:
**	    E_DB_OK			Function completed normally.
**	    E_DB_INFO			Function completed with warning(s).
**	    E_DB_WARN			One ore more roles were rejected.
**	    E_DB_ERROR			Function failed; non-catastrophic error
**	Exceptions:
**	    none
**
** Side Effects:
**	    Removed tuples from iiuser.
**
** History:
**	04-sep-89 (ralph)
**          written
**	12-mar-90 (andre)
**	    set rdr_2types_mask to 0.
**      22-may-90 (teg)
**          init rdr_instr to RDF_NO_INSTR
*/
DB_STATUS
psy_kuser(
	PSY_CB             *psy_cb,
	PSS_SESBLK	   *sess_cb)
{
    DB_STATUS		status, stat;
    RDF_CB		rdf_cb;
    register RDR_RB	*rdf_rb = &rdf_cb.rdf_rb;
    DU_USER		ustuple;
    register DU_USER	*ustup = &ustuple;
    PSY_USR		*psy_usr;

    /* This code is called for SQL only */

    /*
    ** Fill in the part of RDF request block that will be constant.
    */
    pst_rdfcb_init(&rdf_cb, sess_cb);
    rdf_rb->rdr_update_op   = RDR_DELETE;
    rdf_rb->rdr_status	    = DB_SQL;
    rdf_rb->rdr_types_mask  = RDR_USER;
    rdf_rb->rdr_qrytuple    = (PTR) ustup;
    rdf_rb->rdr_qtuple_count = 1;

    ustup->du_gid	= 0;
    ustup->du_mid	= 0;
    ustup->du_status 	= 0;
    ustup->du_flagsmask	= 0;


    MEfill(sizeof(ustup->du_group),
	   (u_char)' ',
	   (PTR)&ustup->du_group);

    status = E_DB_OK;

    for (psy_usr  = (PSY_USR *)  psy_cb->psy_usrq.q_next;
	 psy_usr != (PSY_USR *) &psy_cb->psy_usrq;
	 psy_usr  = (PSY_USR *)  psy_usr->queue.q_next
	)
    {
	/* STRUCT_ASSIGN_MACRO(psy_usr->psy_usrnm,
			       ustup->du_name); */
	MEcopy((PTR)&psy_usr->psy_usrnm,
	       sizeof(ustup->du_name),
	       (PTR)&ustup->du_name);

	stat = rdf_call(RDF_UPDATE, (PTR)&rdf_cb);
	status = (stat > status) ? stat : status;

	if (DB_FAILURE_MACRO(stat))
	    break;
    }

    if (DB_FAILURE_MACRO(status))
	(VOID) psf_rdf_error(RDF_UPDATE, &rdf_cb.rdf_error, 
			     &psy_cb->psy_error);

    return    (status);
} 
Exemplo n.º 5
0
/*{
** Name: psy_kgroup - Destroy group
**
**  INTERNAL PSF call format: status = psy_kgroup(&psy_cb, sess_cb);
**
** Description:
**	This procedure deletes group identifiers.  No members can be
**	in the group to be deleted.  If members exist in a group,
**	the group is not deleted.
**	This procedure is called for SQL language only.
**
** Inputs:
**      psy_cb
**	    .psy_tblq			head of group  queue
**	sess_cb				Pointer to session control block
**					(Can be NULL)
**
** Outputs:
**      psy_cb
**	    .psy_error			Filled in if error happens
**	Returns:
**	    E_DB_OK			Function completed normally.
**	    E_DB_INFO			Function completed with message(s).
**	    E_DB_WARN			One or more groups were rejected.
**	    E_DB_ERROR			Function failed; non-catastrophic error
**	Exceptions:
**	    none
**
** Side Effects:
**	    Removed tuples from iiusergroup.
**
** History:
**	13-mar-89 (ralph)
**          written
**	20-may-89 (ralph)
**	    Allow multiple groups to be specified.
**	12-mar-90 (andre)
**	    set rdr_2types_mask to 0.
**      22-may-90 (teg)
**          init rdr_instr to RDF_NO_INSTR
*/
DB_STATUS
psy_kgroup(
	PSY_CB             *psy_cb,
	PSS_SESBLK	   *sess_cb)
{
    DB_STATUS		status, stat;
    RDF_CB		rdf_cb;
    register RDR_RB	*rdf_rb = &rdf_cb.rdf_rb;
    DB_USERGROUP	ugtuple;
    register DB_USERGROUP *ugtup = &ugtuple;
    PSY_TBL		*psy_tbl;
    PSY_USR		*psy_usr;

    /* This code is called for SQL only */

    /*
    ** Fill in the part of RDF request block that will be constant.
    */
    pst_rdfcb_init(&rdf_cb, sess_cb);
    rdf_rb->rdr_update_op   = RDR_DELETE;
    rdf_rb->rdr_status	    = DB_SQL;
    rdf_rb->rdr_types_mask  = RDR_GROUP;
    rdf_rb->rdr_qrytuple    = (PTR) ugtup;
    rdf_rb->rdr_qtuple_count = 1;

    MEfill(sizeof(DB_OWN_NAME), (u_char)' ', (PTR)&ugtup->dbug_member);
    MEfill(sizeof(ugtup->dbug_reserve),
	   (u_char)' ',
	   (PTR)ugtup->dbug_reserve);

    status = E_DB_OK;

    for (psy_tbl  = (PSY_TBL *)  psy_cb->psy_tblq.q_next;
	 psy_tbl != (PSY_TBL *) &psy_cb->psy_tblq;
	 psy_tbl  = (PSY_TBL *)  psy_tbl->queue.q_next
	)
    {
	/* STRUCT_ASSIGN_MACRO(psy_tbl->psy_tabnm,
			       ugtup->dbug_group); */
	MEcopy((PTR)&psy_tbl->psy_tabnm,
	       sizeof(ugtup->dbug_group),
	       (PTR)&ugtup->dbug_group);

	stat = rdf_call(RDF_UPDATE, (PTR) &rdf_cb);
	status = (stat > status) ? stat : status;

	if (DB_FAILURE_MACRO(stat))
	    break;
    }

    if (DB_FAILURE_MACRO(status))
	(VOID) psf_rdf_error(RDF_UPDATE, &rdf_cb.rdf_error, 
			     &psy_cb->psy_error);

    return    (status);
}
Exemplo n.º 6
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);
}
Exemplo n.º 7
0
DB_STATUS
psy_dsequence(
	PSY_CB             *psy_cb,
	PSS_SESBLK	   *sess_cb)
{
    RDF_CB              rdf_cb;
    RDR_RB		*rdf_rb = &rdf_cb.rdf_rb;
    DB_STATUS		status;

    /* Fill in the RDF request block */

    /* first zero it out and fill in common elements */
    pst_rdfcb_init(&rdf_cb, sess_cb);
	
    rdf_rb->rdr_2types_mask  = RDR2_SEQUENCE;		/*Sequence delettion */
    rdf_rb->rdr_update_op   = RDR_DELETE;
    rdf_rb->rdr_qrytuple    = (PTR)&psy_cb->psy_tuple.psy_sequence; /* sequence tup */

    status = rdf_call(RDF_UPDATE, (PTR) &rdf_cb);	/* Destroy sequence */
    if (status != E_DB_OK)
	_VOID_ psf_rdf_error(RDF_UPDATE, &rdf_cb.rdf_error, &psy_cb->psy_error);
    return (status);
} /* psy_dsequence */
Exemplo n.º 8
0
/*{
** Name: opv_tproc	- Load RDF defs for table procedure range table entry
**
** Description:
**      This function allocates and formats simulated RDF structures for
**	a table procedure, including result column descriptors that are
**	used to resolve "column" references to the procedure.
**
** Inputs:
**	sess_cb				Pointer to session control block
**      rngtable                        Pointer to the user range table
**	scope				scope that range variable belongs in
**					-1 means don't care.
**	corrname			Correlation name of table procedure
**	dbp				Ptr to PSF procedure descriptor
**	rngvar				Place to put pointer to new range
**					variable
**	root				Ptr to RESDOM list of parameter specs
**	err_blk				Place to put error information
**
** Outputs:
**      rngvar                          Set to point to the range variable
**	err_blk				Filled in if an error happens
**	Returns:
**	    E_DB_OK			Success
**	    E_DB_ERROR			Non-catastrophic failure
**	    E_DB_FATAL			Catastrophic failure
**	Exceptions:
**	    none
**
** Side Effects:
**	    Can allocate memory
**
** History:
**	17-april-2008 (dougi)
**	    Written for table procedures(semi-cloned from pst_stproc).
**	15-dec-2008 (dougi) BUG 121381
**	    Fix computation of result column offsets.
*/
DB_STATUS
opv_tproc(
	OPS_STATE	*global,
	OPV_IGVARS	gvar,
	OPV_GRV		*grvp,
	PST_RNGENTRY	*rngentry)

{
    DMT_ATT_ENTRY	**attarray, *attrp;
    DMT_ATT_ENTRY	**parmarray, **rescarray;
    DMT_TBL_ENTRY	*tblptr;
    RDR_INFO		*rdrinfop;
    QEF_DATA		*qp;
    RDF_CB		*rdf_cb;
    RDR_RB		*rdf_rb;
    DB_PROCEDURE	*dbp;
    DB_DBP_NAME		proc_name;
    DB_OWN_NAME		proc_owner;
    i4			parameterCount, rescolCount, resrowWidth;
    u_i4		created;

    i4			i, j, totlen, offset;
    DB_STATUS           status;
    i4		err_code;


    /* First retrieve iiprocedure row using id from range table entry. */
    rdf_cb = &global->ops_rangetab.opv_rdfcb;
    rdf_rb = &rdf_cb->rdf_rb;

    STRUCT_ASSIGN_MACRO(rngentry->pst_rngvar, rdf_rb->rdr_tabid);
    rdf_rb->rdr_types_mask  = RDR_PROCEDURE;
    rdf_rb->rdr_2types_mask = 0;
    rdf_rb->rdr_instr       = RDF_NO_INSTR;

    /*
    ** need to set rdf_info_blk to NULL for otherwise RDF assumes that we
    ** already have the info_block
    */
    rdf_cb->rdf_info_blk = (RDR_INFO *) NULL;

    status = rdf_call(RDF_GETINFO, rdf_cb);
    if (DB_FAILURE_MACRO(status))
    {
	(VOID) opx_verror(status, E_OP0004_RDF_GETDESC,
                                rdf_cb->rdf_error.err_code);
    }
    dbp = rdf_cb->rdf_info_blk->rdr_dbp;

    /* Before proceeding - assure this is the same proc that we think it is. */
    if (rngentry->pst_timestamp.db_tab_high_time != dbp->db_created)
    {
	/* If not, bounce back to SCF to re-parse query. */
	opx_vrecover(E_DB_ERROR, E_OP008F_RDF_MISMATCH, 
					rdf_cb->rdf_error.err_code);
    }

    /* Save procedure stuff for later. */
    parameterCount = dbp->db_parameterCount;
    rescolCount = dbp->db_rescolCount;
    resrowWidth = dbp->db_resrowWidth;
    created = dbp->db_created;
    STRUCT_ASSIGN_MACRO(dbp->db_dbpname, proc_name);
    STRUCT_ASSIGN_MACRO(dbp->db_owner, proc_owner);

    /* Allocate attr descriptors and address from ptr arrays. */
    i = dbp->db_parameterCount + dbp->db_rescolCount;

    attarray = (DMT_ATT_ENTRY **) opu_memory(global, (sizeof(PTR) +
		sizeof(DMT_ATT_ENTRY)) * i + sizeof(PTR));
				/* 1 extra ptr because array is 1-origin */

    /* Set up attr pointer arrays for both parms and result columns. */
    for (j = 1, attrp = (DMT_ATT_ENTRY *)&attarray[i+1],
	attarray[0] = (DMT_ATT_ENTRY *)NULL; j <= i; j++, attrp = &attrp[1])
    {
	attarray[j] = attrp;
	MEfill(sizeof(DMT_ATT_ENTRY), (u_char)0, (char *)attrp);
    }

    rescarray = attarray;
    parmarray = &attarray[rescolCount+1];

    /* Load iiprocedure_parameter rows for both parms and result cols. */
    rdf_rb->rdr_types_mask     = 0;
    rdf_rb->rdr_2types_mask    = RDR2_PROCEDURE_PARAMETERS;
    rdf_rb->rdr_instr          = RDF_NO_INSTR;

    rdf_rb->rdr_update_op      = RDR_OPEN;
    rdf_rb->rdr_qrymod_id      = 0;	/* get all tuples */
    rdf_rb->rdr_qtuple_count   = 20;	/* get 20 at a time */
    rdf_cb->rdf_error.err_code = 0;

    /*
    ** must set rdr_rec_access_id since otherwise RDF will barf when we
    ** try to RDR_OPEN
    */
    rdf_rb->rdr_rec_access_id  = NULL;

    while (rdf_cb->rdf_error.err_code == 0)
    {
	status = rdf_call(RDF_READTUPLES, rdf_cb);
	rdf_rb->rdr_update_op = RDR_GETNEXT;

	/* Must not use DB_FAILURE_MACRO because E_RD0011 returns
	** E_DB_WARN that would be missed.
	*/
	if (status != E_DB_OK)
	{
	    switch(rdf_cb->rdf_error.err_code)
	    {
		case E_RD0011_NO_MORE_ROWS:
		    status = E_DB_OK;
		    break;

		case E_RD0013_NO_TUPLE_FOUND:
		    status = E_DB_OK;
		    continue;

		default:
		    opx_error(E_OP0013_READ_TUPLES);
		    break;
	    }	    /* switch */
	}	/* if status != E_DB_OK */

	/* For each dbproc parameter tuple */
	for (qp = rdf_cb->rdf_info_blk->rdr_pptuples->qrym_data, j = 0;
	    j < rdf_cb->rdf_info_blk->rdr_pptuples->qrym_cnt;
	    qp = qp->dt_next, j++)
	{
	    DB_PROCEDURE_PARAMETER *param_tup =
		(DB_PROCEDURE_PARAMETER *) qp->dt_data;
	    if (i-- == 0)
	    {
		opx_error(E_OP0013_READ_TUPLES);
	    }
	    if (param_tup->dbpp_flags & DBPP_RESULT_COL)
	    {
		attrp = rescarray[param_tup->dbpp_number];
		attrp->att_number = param_tup->dbpp_number;
	    }
	    else 
	    {
		attrp = parmarray[param_tup->dbpp_number-1];
		attrp->att_flags = DMT_F_TPROCPARM;
		attrp->att_number = param_tup->dbpp_number +
					dbp->db_rescolCount;
	    }

	    STRUCT_ASSIGN_MACRO(param_tup->dbpp_name, attrp->att_name);
	    attrp->att_type = param_tup->dbpp_datatype;
	    attrp->att_width = param_tup->dbpp_length;
	    attrp->att_prec = param_tup->dbpp_precision;
	    attrp->att_offset = param_tup->dbpp_offset;
	}
    }

    /* Reset result column offsets to remove effect of parms. */
    offset = rescarray[1]->att_offset;
    for (j = 1; j <= rescolCount; j++)
	rescarray[j]->att_offset -= offset;

    if (rdf_rb->rdr_rec_access_id != NULL)
    {
	rdf_rb->rdr_update_op = RDR_CLOSE;
	status = rdf_call(RDF_READTUPLES, rdf_cb);
	if (DB_FAILURE_MACRO(status))
	{
	    opx_error(E_OP0013_READ_TUPLES);
	}
    }

    /* now unfix the dbproc description */
    rdf_rb->rdr_types_mask  = RDR_PROCEDURE | RDR_BY_NAME;
    rdf_rb->rdr_2types_mask = 0;
    rdf_rb->rdr_instr       = RDF_NO_INSTR;

    status = rdf_call(RDF_UNFIX, rdf_cb);
    if (DB_FAILURE_MACRO(status))
    {
	opx_error(E_OP008D_RDF_UNFIX);
    }

    /* Allocate table descriptor. */
    tblptr = (DMT_TBL_ENTRY *) opu_memory(global, sizeof(DMT_TBL_ENTRY));

    /* Allocate RDR_INFO block. */
    rdrinfop = (RDR_INFO *) opu_memory(global, sizeof(RDR_INFO)+sizeof(PTR));

    /* Now format them all. */

    MEfill(sizeof(DMT_TBL_ENTRY), (u_char) 0, tblptr);
    MEcopy((char *)&proc_name.db_dbp_name, sizeof(DB_DBP_NAME), 
				(char *)&tblptr->tbl_name.db_tab_name);
    STRUCT_ASSIGN_MACRO(proc_owner, tblptr->tbl_owner);
    MEfill(sizeof(DB_LOC_NAME), (u_char)' ', (char *)&tblptr->tbl_location);
    tblptr->tbl_attr_count = rescolCount + parameterCount;
    tblptr->tbl_width = resrowWidth;
    tblptr->tbl_date_modified.db_tab_high_time = created;
    tblptr->tbl_storage_type = DB_TPROC_STORE;
    /* Load cost parameters (if there). */
    tblptr->tbl_record_count = (dbp->db_estRows) ? dbp->db_estRows : DBP_ROWEST;
    tblptr->tbl_page_count = (dbp->db_estCost) ? dbp->db_estCost : DBP_DIOEST;
    tblptr->tbl_pgsize = 2048;

    /* All the other DMT_TBL_ENTRY fields are being left 0 until 
    ** something happens that suggests other values. */

    /* Finally fill in the RDR_INFO structure. */
    MEfill(sizeof(RDR_INFO), (u_char) 0, rdrinfop);
    rdrinfop->rdr_rel = tblptr;
    rdrinfop->rdr_attr = rescarray;
    rdrinfop->rdr_no_attr = tblptr->tbl_attr_count;
    rdrinfop->rdr_dbp = dbp;
    grvp->opv_relation = rdrinfop;

    BTset((i4)gvar, (char *)&global->ops_rangetab.opv_mrdf); /* indicate
						** that RDF info is fixed */
    grvp->opv_gmask |= OPV_TPROC;
    global->ops_gmask |= OPS_TPROCS;		/* show query has table procs */

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

    *ret_flags = 0;

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

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

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

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

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

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

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

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

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

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

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


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

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

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

    /* Initialize the QSF control block */
    qsf_rb->qsf_type = QSFRB_CB;
    qsf_rb->qsf_ascii_id = QSFRB_ASCII_ID;
    qsf_rb->qsf_length = sizeof(QSF_RCB);
    qsf_rb->qsf_owner = (PTR)DB_PSF_ID;
    qsf_rb->qsf_sid = sess_cb->pss_sessid;
    qsf_rb->qsf_obj_id.qso_type = QSO_QTEXT_OBJ;
    qsf_rb->qsf_obj_id.qso_lname = 0;

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

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

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

	goto cleanup2;
    }

    /* Object is locked exclusively now. */

    pinfo = rdf_cb->rdf_rb.rdr_procedure;

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

    status = qsf_call(QSO_PALLOC, qsf_rb);

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

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

	goto cleanup1;
    }

    qdesc = (PSQ_QDESC *) qsf_rb->qsf_piece;

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

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

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

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

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

    status = qsf_call(QSO_SETROOT, qsf_rb);

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

    status = qsf_call(QSO_UNLOCK, qsf_rb);

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

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

    return (status);

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

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

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

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

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

    return (status);
}
Exemplo n.º 10
0
/*{
** Name: psy_kproc - Drop a database procedure definition from
**		     the system catalogs.
**
** Description:
**
** Inputs:
**
** Outputs:

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

    /* Invalidate procedure object from RDF cache */
    pst_rdfcb_init(&rdf_cb, sess_cb);
    (VOID) MEcopy((PTR)&psy_cb->psy_tabname[0], sizeof(DB_DBP_NAME),
	(PTR)&rdf_rb->rdr_name.rdr_prcname);
    STRUCT_ASSIGN_MACRO(sess_cb->pss_user, rdf_rb->rdr_owner);
    rdf_rb->rdr_types_mask = RDR_PROCEDURE;
    status = rdf_call(RDF_INVALIDATE, (PTR) &rdf_cb);
    if (DB_FAILURE_MACRO(status))
    {
	(VOID) psf_rdf_error(RDF_INVALIDATE, &rdf_cb.rdf_error,
			&psy_cb->psy_error);
    }

exit:
    return (status);
}
Exemplo n.º 11
0
/*{
** Name: psy_cproc - Create a database procedure definition in
**		     the system catalogs.
**
** Description:
**
** Inputs:
**
** Outputs:
**	Exceptions:
**	    none
**
** Side Effects:
**	    Modifies system catalogs.
**
** History:
**      27-apr-88 (stec)
**	    Created.
**	23-aug-88 (stec)
**	    Added comments, initialize new fields in DB_PROCEDURE.
**	26-apr-89 (andre)
**	    For internal procedures, set db_mask[0] to DB_IPROC.
**	12-mar-90 (andre)
**	    set rdr_2types_mask to 0.
**      22-may-90 (teg)
**          init rdr_instr to RDF_NO_INSTR
**	12-jun-90 (andre)
**	    when trying to destroy a dbproc QEP, use "private" alias, which is
**	    always defined as opposed to the "public" alias which would not be
**	    defined if the dbproc is not grantable.
**	04-mar-92 (andre)
**	    set DB_ACTIVE_DBP in db_mask[0] to indicate that the dbproc is not
**	    abandoned.  If the dbproc is grantable, set DB_DBPGRANT_OK in
**	    db_mask[0].
**	18-may-92 (andre)
**	    call psy_dbp_status() to verify that the new dbproc is not abandoned
**	    and trust psy_dbp_status() to determine whether the dbproc is
**	    grantable or just active.
**	19-may-92 (andre)
**	    in pslsgram.yi, pss_dependencies_stream was opened to collect info
**	    about objects/privileges on which the new dbproc depends;
**	    this stream must be closed before leaving this function since the
**	    dependence information will be of no use once we return
**	01-jun-92 (andre)
**	    pass information about objects/privileges on which the new database
**	    procedure depends to QEF.
**	26-jun-92 (andre)
**	    enter information about the dbproc into IIPROCEDURE and the list of
**	    objects and privileges on which it depends into IIDBDEPENDS and
**	    IIPRIV respectively before calling psy_dbp_status() to determine
**	    whether it is active.  This is necessary since otherwise it would be
**	    impossible to create mutually recursive database procedures (if P1
**	    calls P2 and we are trying to create P2 calling P1, psy_dbp_status()
**	    will report that P1 is dormant and prevent us from creating P2)
**
**	    Since we won't know whether the dbproc is active and/or grantable
**	    until psy_dbp_status() is done, we will set only DB_DBP_INDEP_LIST
**	    bit in IIPROCEDURE.dbp_mask1 here, unless the independent
**	    object/privilege list is empty, in which case there is no reason to
**	    call psy_dbp_status(), so we will set DB_DBPGRANT_OK and
**	    DB_ACTIVE_DBP bits in IIPROCEDURE.dbp_mask1.
**
**	    If the independent object/privilege list is not empty and the
**	    procedure is not dormant, psy_dbp_status() will set appropriate bits
**	    (DB_DBPGRANT_OK and/or DB_ACTIVE_DBP) in IIPROCEDURE.dbp_mask1 once
**	    it has determined whether the dbproc is active or grantable
**	09-sep-92 (andre)
**	    psy_dbp_status() no longer accepts or returns an indicator of
**	    whether cache had to be flushed in psy_dbp_priv_check()
**	07-nov-92 (andre)
**	    we will no longer create private aliases for dbproc QPs
**	22-feb-93 (rblumer)
**	    initialize new RDF proc_param variables for both normal and
**	    set-input procedures; reverse order of MEcopy and I4assign in
**	    QP cleanup code so that qsf id gets set up correctly.
**	13-apr-93 (andre)
**	    if creating a system-generated procedure, independent
**	    object/privilege list will be empty - QEF will insert IIDBDEPENDS
**	    tuple recording dependence of the dbproc on a constraint (for
**	    constraint-enforcing dbprocs) or view (for CHECK OPTION-enforcing
**	    dbprocs.)  Here we will set bits indicating that there will be
**	    independent object list and that the dbproc is active but not
**	    grantable (we don't want the user to grant privileges on
**	    system-generated dbprocs)
**	01-sep-93 (andre)
**	    in the course of parsing a dbproc definition, we will try to 
**	    determine id of a base table on which the dbproc depends; here we
**	    will copy it into proctuple.dbPdbp_ubt_id to ensure that it gets 
**	    inserted into IIPROCEDURE
**	22-oct-93 (rblumer)
**	    normal procedures will now have their parameters inserted into the
**	    catalogs (previously just set-input procedures did); changed
**	    initialization of db_parameterCount, rdr_proc_param_cnt and
**	    rdr_proc_params to work for both types of procedures.
**	30-apr-94 (andre)
**	    fix for bug 61087:
**	    proctuple.db_mask[0] was being set before proctuple was MEfill'd 
**	    with NULLCHAR; moved the line initializing proctuple.db_mask[0] 
**	    below call to MEfill() 
**	16-jun-94 (andre)
**	    Bug #64395
**	    it is dangerous to cast a (char *) into a (DB_CURSOR_ID *) and then
**	    dereference the resulting pointer because the chat ptr may not be 
**	    pointing at memory not aligned on an appopriate boundary.  Instead,
**	    we will allocate a DB_CURSOR_ID structure on the stack, initialize 
**	    it and MEcopy() it into the char array
**	19-june-06 (dougi)
**	    Add DBP_DATA_CHANGE flag for BEFORE trigger validation.
**	28-march-2008 (dougi)
**	    Changes to support table procedures and named result row elements.
**	4-feb-2009 (dougi)
**	    Tidy up computation of table procedure result row length.
**	30-mar-2009 (toumi01) b121871
**	    Rewrite and simplify the computation of table procedure input
**	    and output parameter count and width (fixes a logic error that
**	    caused the result width to be decremented by the width of the
**	    first result parameter when there were no input parameters).
*/
DB_STATUS
psy_cproc(
	PSY_CB	   *psy_cb,
	PSS_SESBLK *sess_cb)
{
    RDF_CB		rdf_cb;
    register RDR_RB	*rdf_rb = &rdf_cb.rdf_rb;
    i4			textlen;
    QSF_RCB		qsf_rb;
    DB_PROCEDURE	proctuple;
    DB_STATUS		status, stat;
    i4		err_code;
    PSY_TBL		dbp_descr;
    i4			dbp_mask[2];
    bool		empty_indep_list, rowproc;

    /* If this is a recreate case, and this code gets called
    ** just return since there is no work to be done, not even
    ** recovery of resources.
    */
    if (sess_cb->pss_dbp_flags & PSS_RECREATE)
	return(E_DB_OK);

    /* determine if the new dbproc depends on any object or privileges */
    if (   sess_cb->pss_indep_objs.psq_objs
	|| sess_cb->pss_indep_objs.psq_objprivs
	|| sess_cb->pss_indep_objs.psq_colprivs
       )
    {
	empty_indep_list = FALSE;
    }
    else
    {
	empty_indep_list = TRUE;
    }

    /*
    ** Initialize the header of the QSF control block
    ** NOTE: it is important that we init qsf_rb before calling
    **       psy_dbp_status() - if the dbproc cannot be created, code under
    **	     exit: will expect the control block set up for deleting the query
    **	     text QSF object and the query plan QSF 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(psy_cb->psy_qrytext, qsf_rb.qsf_obj_id);

    /* Retrieve info about the procedure text object */
    status = qsf_call(QSO_INFO, &qsf_rb);

    if (DB_FAILURE_MACRO(status))
    {
	goto exit;
    }

    /* Get the text length. */
    MEcopy((PTR) qsf_rb.qsf_root, sizeof(i4), (PTR) &textlen);

    /* Initialize the II_PROCEDURE tuple. */
    MEfill(sizeof(proctuple), NULLCHAR, (PTR) &proctuple);

    (VOID) MEcopy((PTR)&psy_cb->psy_tabname[0], sizeof(DB_DBP_NAME),   
	(PTR)&proctuple.db_dbpname);

    /* Current user is the owner. */
    STRUCT_ASSIGN_MACRO(sess_cb->pss_user, proctuple.db_owner);

    proctuple.db_txtlen = textlen;

    TMnow((SYSTIME *) &proctuple.db_txtid);

    /*
    ** if the independent object/privilege list is non-empty, we will set
    ** DB_DBP_INDEP_LIST bit and leave it to psy_dbp_status() to set the
    ** remaining bits, if appropriate; otherwise we will set DB_DBPGRANT_OK and
    ** DB_ACTIVE_DBP bits and avoid calling psy_dbp_status()
    **
    ** if creating a system-generated dbproc, mark the dbproc ACTIVE and
    ** indicate that there is independent object list (there is not one at this
    ** point, but QEF will insert IIDBDEPENDS tuple recording dependence of the
    ** dbproc on a constraint (for constraint-enforcing dbprocs) or view (for
    ** CHECK OPTION-enforcingdbprocs.)
    */
    
    /* If working on internal dbproc, set DB_IPROC in db_mask[0] */
    if (sess_cb->pss_dbp_flags & PSS_IPROC)
	proctuple.db_mask[0] |= DB_IPROC;

    if (sess_cb->pss_dbp_flags & PSS_SYSTEM_GENERATED)
	proctuple.db_mask[0] |=
	    DBP_SYSTEM_GENERATED | DB_ACTIVE_DBP | DB_DBP_INDEP_LIST;
    else if (empty_indep_list)
	proctuple.db_mask[0] |= DB_DBPGRANT_OK | DB_ACTIVE_DBP;
    else
	proctuple.db_mask[0] |= DB_DBP_INDEP_LIST;

    if (sess_cb->pss_dbp_flags & PSS_SET_INPUT_PARAM)
	proctuple.db_mask[0] |= DBP_SETINPUT;

    if (sess_cb->pss_dbp_flags & PSS_NOT_DROPPABLE)
	proctuple.db_mask[0] |= DBP_NOT_DROPPABLE;

    if (sess_cb->pss_dbp_flags & PSS_SUPPORTS_CONS)
	proctuple.db_mask[0] |= DBP_CONS;

    if (sess_cb->pss_dbp_flags & PSS_DATA_CHANGE)
	proctuple.db_mask[0] |= DBP_DATA_CHANGE;

    if (sess_cb->pss_dbp_flags & PSS_OUT_PARMS)
	proctuple.db_mask[0] |= DBP_OUT_PARMS;

    if (sess_cb->pss_dbp_flags & PSS_TX_STMT)
	proctuple.db_mask[0] |= DBP_TX_STMT;

    if (sess_cb->pss_dbp_flags & PSS_ROW_PROC)
    {
	rowproc = TRUE;
	proctuple.db_mask[0] |= DBP_ROW_PROC;
    }
    else rowproc = FALSE;

    proctuple.db_mask[1] = 0;

    /*
    ** if we were able to determine id of a base table on which this dbproc will
    ** depend, copy it into proctuple
    */
    proctuple.db_dbp_ubt_id.db_tab_base  = sess_cb->pss_dbp_ubt_id.db_tab_base;
    proctuple.db_dbp_ubt_id.db_tab_index = sess_cb->pss_dbp_ubt_id.db_tab_index;

    /* db_procid to be filled in by RDF or QEF */

    proctuple.db_parameterCount = 0;
    proctuple.db_recordWidth    = 0;
    proctuple.db_rescolCount = 0;
    proctuple.db_resrowWidth    = 0;

    if (sess_cb->pss_procparmlist != (QEF_DATA *) NULL)
    {
	DB_PROCEDURE_PARAMETER	*param_tuple;
	QEF_DATA		*listptr;

	/* compute count and total width of input and result parameters */
	for (listptr = sess_cb->pss_procparmlist;
	     listptr != (QEF_DATA *) NULL;
	     listptr = listptr->dt_next)
	{
	    param_tuple = (DB_PROCEDURE_PARAMETER *)listptr->dt_data;
	    if (param_tuple->dbpp_flags & DBPP_RESULT_COL)
	    {
		proctuple.db_rescolCount++;
		proctuple.db_resrowWidth = param_tuple->dbpp_offset 
			+ param_tuple->dbpp_length;
	    }
	    else
	    {
		proctuple.db_parameterCount++;
		proctuple.db_recordWidth = param_tuple->dbpp_offset 
			+ param_tuple->dbpp_length;
	    }
	}
	if (proctuple.db_rescolCount > 0)
	    proctuple.db_resrowWidth -= proctuple.db_recordWidth;
    }

    /* Initialize the RDF request block. */
    pst_rdfcb_init(&rdf_cb, sess_cb);
    (VOID) MEcopy((PTR)&psy_cb->psy_tabname[0], sizeof(DB_DBP_NAME),
	(PTR)&rdf_rb->rdr_name.rdr_prcname);
    STRUCT_ASSIGN_MACRO(sess_cb->pss_user, rdf_rb->rdr_owner);
    rdf_rb->rdr_types_mask = RDR_PROCEDURE;
    rdf_rb->rdr_update_op = RDR_APPEND;
    rdf_rb->rdr_qrytuple = (PTR) &proctuple; 
    rdf_rb->rdr_l_querytext = textlen;
    rdf_rb->rdr_querytext = ((char *) qsf_rb.qsf_root) + sizeof(i4);

    /*
    ** pass information about objects/privileges on which the new database
    ** procedure depends to QEF
    */
    sess_cb->pss_indep_objs.psq_grantee = &sess_cb->pss_user;
    rdf_rb->rdr_indep = (PTR) &sess_cb->pss_indep_objs;

    /* fill in the description of the procedure's parameters
    ** (which RDF/QEF will store into iiprocedure_parameter);
    */
    rdf_rb->rdr_proc_param_cnt = proctuple.db_parameterCount
					+ proctuple.db_rescolCount;
    rdf_rb->rdr_proc_params    = sess_cb->pss_procparmlist;

    /* Create a new procedure in the system catalogs */
    status = rdf_call(RDF_UPDATE, (PTR) &rdf_cb);

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

	goto exit;
    }

    /*
    ** if the independent object/privilege list is non-empty, verify that the
    ** dbproc we are about to create is not abandoned; strictly speaking, as
    ** long as the independent object list is empty, we are guaranteed that the
    ** dbproc is not abandoned (user posesses required privileges), but we will
    ** take an extra step and try to determine whether it is grantable
    */
    if (!empty_indep_list)
    {
	MEcopy((PTR) psy_cb->psy_tabname, sizeof(DB_DBP_NAME),
	    (PTR) &dbp_descr.psy_tabnm);
	dbp_descr.psy_tabid.db_tab_base = proctuple.db_procid.db_tab_base;
	dbp_descr.psy_tabid.db_tab_index = proctuple.db_procid.db_tab_index;
	
	status = psy_dbp_status(&dbp_descr, sess_cb, (PSF_QUEUE *) NULL,
	    (i4) PSQ_CREDBP, dbp_mask, &psy_cb->psy_error);
	if (DB_FAILURE_MACRO(status))
	{
	    goto exit;
	}
    }


exit:

    /*
    ** close the memory stream which was used to allocate descriptors of
    ** objects/privileges on which the new dbproc depends
    */
    stat = psf_mclose(sess_cb, sess_cb->pss_dependencies_stream, &psy_cb->psy_error);
    if (DB_FAILURE_MACRO(stat) && stat > status)
	status = stat;

    /*
    ** ensure that no one tries to use the stream that is no longer valid
    */
    sess_cb->pss_dependencies_stream = (PSF_MSTREAM *) NULL;

    /* Get a lock on the query text from QSF */
    qsf_rb.qsf_lk_state = QSO_EXLOCK;

    stat = qsf_call(QSO_LOCK, &qsf_rb);

    if (DB_FAILURE_MACRO(stat))
    {
	(VOID) psf_error(E_PS0A08_CANTLOCK, qsf_rb.qsf_error.err_code,
	    PSF_INTERR, &err_code, &psy_cb->psy_error, 0);
	if (stat > status)
	    status = stat;
    }
    else
    {
	/* Now destroy the query text */
	stat = qsf_call(QSO_DESTROY, &qsf_rb);

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


    /* Destroy the procedure QP in QSF if things went wrong. */
    if (DB_FAILURE_MACRO(status))
    {
	PSS_DBPALIAS	dbpid;
	DB_CURSOR_ID	dbp_curs_id;

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

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

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

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

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

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

	if (DB_FAILURE_MACRO(stat))
	{
	    if (qsf_rb.qsf_error.err_code != E_QS0019_UNKNOWN_OBJ)
	    {
		(VOID) psf_error(E_PS037A_QSF_TRANS_ERR,
		    qsf_rb.qsf_error.err_code, PSF_INTERR,
		    &err_code, &psy_cb->psy_error, 0);
		if (stat > status)
		    status = stat;
		goto exit1;
	    }
	    else
	    {
		/* QP disappeared, which is alright. */
		goto exit1;
	    }
	}

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

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

exit1:
    return (status);
}
Exemplo n.º 12
0
Arquivo: dmcend.c Projeto: akdh/Ingres
/*
** History:
**	26-jul-1993 (bryanp)
**	    Fixed error handling in release_cb following dmxe_pass_abort call.
**	01-Oct-2004 (jenjo02)
**	    With Factotum threads, scb_oq_next will be empty
**	    but xcb_odcb_ptr will be correct when calling
**	    dmxe_pass_abort().
**	6-Jul-2006 (kschendel)
**	    Pass the db id to RDF in the right place.
**	16-Nov-2009 (kschendel) SIR 122890
**	    Update destroy-temp call parameters.
**	15-Jan-2010 (jonj)
**	    SIR 121619 MVCC: Deallocate lctx, jctx if allocated.
**	14-Apr-2010 (kschendel) SIR 123485
**	    Force a BLOB query-end during cleanup.
*/
static DB_STATUS
release_cb(
DMC_CB		*dmc,
DML_SCB		*scb)
{
    DML_XCB		*xcb;
    DMP_DCB		*dcb;
    DMP_RCB		*rcb;
    i4		error,local_error;
    CL_ERR_DESC		clerror;
    DB_STATUS		status;
    DML_ODCB		*odcb;
    DML_SPCB		*spcb;
    DML_XCCB            *xccb;
    DB_TAB_ID		tbl_id;

    CLRDBERR(&dmc->error);

    while (scb->scb_x_next != (DML_XCB *) &scb->scb_x_next)
    {
	/*  Get next XCB. */

	xcb = (DML_XCB *) scb->scb_x_next;
	odcb = (DML_ODCB *) xcb->xcb_odcb_ptr;

	/* Remove blob Locator context */
	if (scb->scb_lloc_cxt)
	    dm0m_deallocate((DM_OBJECT **)&scb->scb_lloc_cxt);

	/* Close off any in-flight DMPE stuff */
	status = dmpe_query_end(TRUE, TRUE, &dmc->error);
	if ( status != E_DB_OK )
	{
	    SETDBERR(&dmc->error, 0, E_DM0106_ERROR_ENDING_SESSION);
	    return (E_DB_FATAL);
	}

	/* Remove blob PCB's */
	while (xcb->xcb_pcb_list != NULL)
	    dmpe_deallocate(xcb->xcb_pcb_list);

	/*  Close all open tables and destroy all open temporary tables. */

	while (xcb->xcb_rq_next != (DMP_RCB*) &xcb->xcb_rq_next)
	{
	    /*	Get next RCB. */

	    rcb = (DMP_RCB *)((char *)xcb->xcb_rq_next -
		(char *)&(((DMP_RCB*)0)->rcb_xq_next));

	    /*	Remove from the XCB. */

	    rcb->rcb_xq_next->rcb_q_prev = rcb->rcb_xq_prev;
	    rcb->rcb_xq_prev->rcb_q_next = rcb->rcb_xq_next;

	    /*	Remember DCB and table id of a temporary. */

	    dcb = 0;
	    if (rcb->rcb_tcb_ptr->tcb_temporary == TCB_TEMPORARY)
	    {
		dcb = rcb->rcb_tcb_ptr->tcb_dcb_ptr;
		tbl_id = rcb->rcb_tcb_ptr->tcb_rel.reltid;
	    }

	    /*	Deallocate the RCB. */

	    status = dm2t_close(rcb, (i4)0, &dmc->error);
	    if (status != E_DB_OK)
	    {
		if ((dmc->error.err_code != E_DM004B_LOCK_QUOTA_EXCEEDED) &&
		    (dmc->error.err_code != E_DM0042_DEADLOCK) &&
		    (dmc->error.err_code != E_DM004D_LOCK_TIMER_EXPIRED) &&
		    (dmc->error.err_code != E_DM004A_INTERNAL_ERROR))
		{
		    uleFormat( &dmc->error, 0, NULL, ULE_LOG , NULL, 
			(char * )NULL, 0L, (i4 *)NULL, 
			&local_error, 0);
		    SETDBERR(&dmc->error, 0, E_DM0106_ERROR_ENDING_SESSION);
		}
		return (E_DB_FATAL);
	    }

	    /*	Now destroy the TCB if it's a temporary. */
	    /*  I can't be bothered to change this code to run off of the
	    **  xccb list, so can't use dmt-destroy-temp. (schka24)
	    **  I may regret this if it turns out that factotum can get
	    **  here -- could end up deleting session temp...
	    */

	    if (dcb)
	    {
		RDF_CB rdfcb;

		/* RDF doesn't use its end-session call, and anyway
		** we know the table ID and it doesn't.   Toss the
		** table out of RDF so that it's not clogging up the
		** RDF-works.  This also ensures that nobody will accidently
		** find the table by ID in RDF if the ID is reused.
		** (Unlikely, but possible.)
		** Zero in rdr_fcb says don't send invalidate dbevents
		** to other servers.  Zero in the rdfcb rdf_info_blk says
		** we don't have anything fixed.
		*/

		MEfill(sizeof(RDF_CB), 0, &rdfcb);
		STRUCT_ASSIGN_MACRO(tbl_id, rdfcb.rdf_rb.rdr_tabid);
		rdfcb.rdf_rb.rdr_session_id = scb->scb_sid;
		rdfcb.rdf_rb.rdr_unique_dbid = dcb->dcb_id;
		rdfcb.rdf_rb.rdr_db_id = (PTR) odcb;
		/* Ignore error on this call */
		(void) rdf_call(RDF_INVALIDATE, &rdfcb);

		/*
		**  Another RCB, yet to be deleted, could still be referencing
		**  the TCB.  Handle the associated error from destroy as normal
		**  in this case.
		*/

		status = dm2t_destroy_temp_tcb(scb->scb_lock_list, 
			    dcb, &tbl_id, &dmc->error);

		if (status != E_DB_OK &&
		    dmc->error.err_code != E_DM005D_TABLE_ACCESS_CONFLICT)
		{
		    uleFormat( &dmc->error, 0, NULL, ULE_LOG , NULL, 
			(char * )NULL, 0L, (i4 *)NULL, 
			&local_error, 0);
		    SETDBERR(&dmc->error, 0, E_DM0106_ERROR_ENDING_SESSION);
		    return (E_DB_FATAL);
		}
	    }
	}
	/* One more time after table closes, guarantees BQCB's deleted */
	status = dmpe_query_end(TRUE, FALSE, &dmc->error);
	if ( status != E_DB_OK )
	{
	    SETDBERR(&dmc->error, 0, E_DM0106_ERROR_ENDING_SESSION);
	    return (E_DB_FATAL);
	}

	/*  Remove SPCBs. */

	while (xcb->xcb_sq_next != (DML_SPCB*) &xcb->xcb_sq_next)
	{
	    /*	Get next SPCB. */

	    spcb = xcb->xcb_sq_next;

	    /*	Remove SPCB from XCB queue. */

	    spcb->spcb_q_next->spcb_q_prev = spcb->spcb_q_prev;
	    spcb->spcb_q_prev->spcb_q_next = spcb->spcb_q_next;

	    /*	Deallocate the SPCB. */

	    dm0m_deallocate((DM_OBJECT **)&spcb);
	}

	/*  Remove XCCBs. */

	while (xcb->xcb_cq_next != (DML_XCCB*)&xcb->xcb_cq_next)
	{
	    /* Get pend XCCB */

	    xccb = xcb->xcb_cq_next;

	    /*	Remove from queue. */

	    xccb->xccb_q_next->xccb_q_prev = xccb->xccb_q_prev;
	    xccb->xccb_q_prev->xccb_q_next = xccb->xccb_q_next;

	    /*	Deallocate. */

	    dm0m_deallocate((DM_OBJECT **)&xccb);
	}

	/* Deallocate lctx, jctx if allocated */
	if ( xcb->xcb_lctx_ptr )
	    dm0m_deallocate(&xcb->xcb_lctx_ptr);
	if ( xcb->xcb_jctx_ptr )
	{
	    /* Close any open jnl file, deallocate jctx */
	    status = dm0j_close(&xcb->xcb_jctx_ptr, &dmc->error);
	    if ( status )
	    {
		SETDBERR(&dmc->error, 0, E_DM0106_ERROR_ENDING_SESSION);
		return (E_DB_FATAL);
	    }
	}

	/*
	** Since we are deallocating a session which has an open transaction,
	** we signal the RCP to abort the transaction for us before deallocating
	** its context.
	**
	** Call dmxe to flush any required pages from the Buffer Manager and
	** to make the abort request to the RCP.
	**
	** The LG context will be freed up by the RCP when the abort is
	** complete.
	**
	** Reference the DB opened on the XCB, not SCB; if this
	** is a Factotum thread, scb_oq_next will be empty,
	** but xcb_odcb_ptr will be valid.
	** Likewise, use xcb_lk_id rather than scb_lock_list.
	*/

	/* XXXX log error message about why pass abort is called */
	status = dmxe_pass_abort(xcb->xcb_log_id, xcb->xcb_lk_id, 
		    &xcb->xcb_tran_id, odcb->odcb_dcb_ptr->dcb_id, &dmc->error);
	if (status)
	{
	    /* XXXX May want to dmd_check here */
	    uleFormat(&dmc->error, 0, NULL, ULE_LOG, NULL, NULL, 0, NULL, &error, 0);
	    SETDBERR(&dmc->error, 0, E_DM0106_ERROR_ENDING_SESSION);
	    return (E_DB_FATAL);
	}

	/*  Remove XCB from SCB queue. */

	xcb->xcb_q_next->xcb_q_prev = xcb->xcb_q_prev;
	xcb->xcb_q_prev->xcb_q_next = xcb->xcb_q_next;
	scb->scb_x_ref_count--;

	dm0m_deallocate((DM_OBJECT **)&xcb);
    }

    /* Close all the opened database of the session. */

    while (scb->scb_oq_next != (DML_ODCB *) &scb->scb_oq_next)
    {
	/*  Get next ODCB. */

	odcb = (DML_ODCB *) scb->scb_oq_next;

	status = dm2d_close_db(odcb->odcb_dcb_ptr, scb->scb_lock_list, 
				DM2D_NLG | DM2D_NLK_SESS, &dmc->error);
	if (status != E_DB_OK)
	{
	    if (dmc->error.err_code > E_DM_INTERNAL)
	    {
		uleFormat( &dmc->error, 0, NULL, ULE_LOG , NULL, 
		    (char * )NULL, 0L, (i4 *)NULL, &local_error, 0);
		SETDBERR(&dmc->error, 0, E_DM0106_ERROR_ENDING_SESSION);
	    }
	    return (E_DB_FATAL);
	}

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

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

    /* No integrity numbers means destroy all integrities. */
    if (psy_cb->psy_numnms == 0)
    {
        /* Zero integrity number means destroy all integs. */
        rdf_rb->rdr_qrymod_id = 0;
        status = rdf_call(RDF_UPDATE, (PTR) &rdf_cb);
        if (DB_FAILURE_MACRO(status))
        {
            if (rdf_cb.rdf_error.err_code == E_RD0002_UNKNOWN_TBL)
            {
                (VOID) psf_error(E_PS0903_TAB_NOTFOUND, 0L, PSF_USERERR,
                                 &err_code, &psy_cb->psy_error, 1,
                                 psf_trmwhite(sizeof(psy_cb->psy_tabname[0]),
                                              (char *) &psy_cb->psy_tabname[0]),
                                 &psy_cb->psy_tabname[0]);
            }
            else
            {
                (VOID) psf_rdf_error(RDF_UPDATE, &rdf_cb.rdf_error,
                                     &psy_cb->psy_error);
            }
            return (status);
        }

        /* Invalidate table info from RDF cache */

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

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

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

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

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

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

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

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

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

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

                return (status);
            }

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

    return    (status);
}
Exemplo n.º 15
0
/*{
** Name: psy_aprofile - Alter profile
**
** Description:
**	This procedure alters an iiprofile tuple.  If the
**	user does not exist, the statement is aborted.
**	If the user does exist, the associated
**	iiprofile tuple is replaced.
**	This procedure is called for SQL language only.
**
** Inputs:
**      psy_cb
**	    .psy_usrq			user list
**	sess_cb				Pointer to session control block
**					(Can be NULL)
**
** Outputs:
**      psy_cb
**	    .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_SEVERE			Function failed; catastrophic error
**	Exceptions:
**	    none
**
** Side Effects:
**	    Replaces tuples in iiuser.
**
** History:
**	27-aug-93 (robf)
**          Written
*/
static DB_STATUS
psy_aprofile(
	PSY_CB             *psy_cb,
	PSS_SESBLK	   *sess_cb)
{
    DB_STATUS		status, stat;
    RDF_CB		rdf_cb;
    i4		err_code;
    register RDR_RB	*rdf_rb = &rdf_cb.rdf_rb;
    struct
    {
	DU_PROFILE	    protuple;
	DU_PROFILE	    protuple2;
    }			usparam;
    register DU_PROFILE	*protup  = &usparam.protuple;
    register DU_PROFILE	*protup2 = &usparam.protuple2;
    PSY_USR		*psy_usr;
    SCF_CB              scf_cb;
    SCF_CB              scf_cb2;
    DB_DATA_VALUE	db_data;
    DB_DATE	        dateval;

    FUNC_EXTERN DB_STATUS rdf_call();
    FUNC_EXTERN DB_STATUS scf_call();

    /* This code is called for SQL only */

    /*
    ** Fill in the part of RDF request block that will be constant.
    */
    pst_rdfcb_init(&rdf_cb, sess_cb);
    rdf_rb->rdr_update_op   = RDR_REPLACE;
    rdf_rb->rdr_status	    = DB_SQL;
    rdf_rb->rdr_2types_mask = RDR2_PROFILE;
    rdf_rb->rdr_qrytuple    = (PTR) protup;
    rdf_rb->rdr_qtuple_count = 1;

    protup->du_flagsmask  = 0;

    if(psy_cb->psy_usflag& PSY_USRDEFPRIV)
    {
	protup->du_defpriv = psy_cb->psy_usdefprivs;
	protup->du_flagsmask|= DU_UDEFPRIV;
	/* Add default=all indicator */
	if(psy_cb->psy_usflag & PSY_USRDEFALL)
		protup->du_flagsmask|=DU_UDEFALL;

	/* if user has specified nodefault_privileges we
	** store this flag to negotiate the final status
	** of default privileges.
	*/
	if (psy_cb->psy_usflag & PSY_UNODEFPRIV)
  	  protup->du_flagsmask|= DU_UNODEFPRIV;
    }
    else
	protup->du_defpriv = 0;

    /*
    ** Expiration date, may be empty
    */
    if(psy_cb->psy_usflag& PSY_USREXPDATE)
    {
	/*
	** Date already formatted earlier
	*/
	MECOPY_CONST_MACRO((PTR)&psy_cb->psy_date, sizeof(DB_DATE), 
			(PTR)&protup->du_expdate);
	protup->du_flagsmask|= DU_UEXPDATE;
    }
    else
    {
	/*
	** Initialize to the empty date
	*/
	db_data.db_datatype  = DB_DTE_TYPE;
	db_data.db_prec	 = 0;
	db_data.db_length    = DB_DTE_LEN;
	db_data.db_data	 = (PTR)&protup->du_expdate;
	status = adc_getempty(sess_cb->pss_adfcb, &db_data);
	if(status)
		return status;
    }
    /*
    ** Check if adding, deleting, or setting privileges
    */
    protup->du_status = (i4) psy_cb->psy_usprivs;
    if (psy_cb->psy_usflag & PSY_USRAPRIVS)
	protup->du_flagsmask |=  DU_UAPRIV;
    else if (psy_cb->psy_usflag & PSY_USRDPRIVS)
	protup->du_flagsmask |=  DU_UDPRIV;
    else if (psy_cb->psy_usflag & PSY_USRPRIVS)
	protup->du_flagsmask |=  DU_UPRIV;
    else
	protup->du_status = 0;
    /*
    ** Check if updating security audit options
    */
    if (psy_cb->psy_usflag & PSY_USRSECAUDIT)
    {
	if(psy_cb->psy_ussecaudit & PSY_USAU_ALL_EVENTS)
		protup->du_flagsmask |= DU_UALLEVENTS;
	else
		protup->du_flagsmask |= DU_UDEFEVENTS;
	if (psy_cb->psy_ussecaudit & PSY_USAU_QRYTEXT)
		protup->du_flagsmask |= DU_UQRYTEXT;
	else
		protup->du_flagsmask |= DU_UNOQRYTEXT;
    }

    if (psy_cb->psy_usflag & PSY_USRDEFGRP)
    {
	MEcopy((PTR)&psy_cb->psy_usgroup,
	       sizeof(protup->du_group),
	       (PTR)&protup->du_group);
	protup->du_flagsmask|= DU_UGROUP;
    }
    else
    {
	MEfill(sizeof(protup->du_group),
	       (u_char)' ',
	       (PTR)&protup->du_group);
    }



    status = E_DB_OK;

    for (psy_usr  = (PSY_USR *)  psy_cb->psy_usrq.q_next;
	 psy_usr != (PSY_USR *) &psy_cb->psy_usrq;
	 psy_usr  = (PSY_USR *)  psy_usr->queue.q_next
	)
    {
	/* STRUCT_ASSIGN_MACRO(psy_usr->psy_usrnm,
			       protup->du_name); */
	MEcopy((PTR)&psy_usr->psy_usrnm,
	       sizeof(protup->du_name),
	       (PTR)&protup->du_name);

	stat = rdf_call(RDF_UPDATE, (PTR)&rdf_cb);
	status = (stat > status) ? stat : status;

	if (DB_FAILURE_MACRO(stat))
	    break;
    }

    if (DB_FAILURE_MACRO(status))
	(VOID) psf_rdf_error(RDF_UPDATE, &rdf_cb.rdf_error, 
	    &psy_cb->psy_error);

    return    (status);
} 
Exemplo n.º 16
0
/*{
** Name: psy_auser - Alter user
**
**  INTERNAL PSF call format: status = psy_auser(&psy_cb, sess_cb);
**
** Description:
**	This procedure alters an iiuser tuple.  If the
**	user does not exist, the statement is aborted.
**	If the user does exist, the associated
**	iiuser tuple is replaced.
**	This procedure is called for SQL language only.
**
** Inputs:
**      psy_cb
**	    .psy_usrq			user list
**	sess_cb				Pointer to session control block
**					(Can be NULL)
**
** Outputs:
**      psy_cb
**	    .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_SEVERE			Function failed; catastrophic error
**	Exceptions:
**	    none
**
** Side Effects:
**	    Replaces tuples in iiuser.
**
** History:
**	04-sep-89 (ralph)
**          written
**      16-jan-90 (ralph)
**          add support for user passwords
**	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)
**	    add support for oldpassword (as in ALTER USER OLDPASSWORD = '******')
**	12-apr-95 (forky01)
**	    Apply default privs when only privs specified to allow backward
**	    compatibility to fix Secure 2.0 code.
**	28-jul-2003 (gupsh01)
**	    Added check for case when noprivileges have been added and
**	    nodefault_privileges is not specified, with a profile in alter
**	    user statement. 
*/
DB_STATUS
psy_auser(
	PSY_CB             *psy_cb,
	PSS_SESBLK	   *sess_cb)
{
    DB_STATUS		status, stat;
    RDF_CB		rdf_cb;
    i4		err_code;
    register RDR_RB	*rdf_rb = &rdf_cb.rdf_rb;
    struct
    {
	DU_USER	    ustuple;
	DU_USER	    ustuple2;
    }			usparam;
    register DU_USER	*ustup  = &usparam.ustuple;
    register DU_USER	*ustup2 = &usparam.ustuple2;
    PSY_USR		*psy_usr;
    bool                encrypt;
    bool                encrypt2;
    SCF_CB              scf_cb;
    SCF_CB              scf_cb2;
    DB_DATA_VALUE	db_data;
    DB_DATE	        dateval;

    /* This code is called for SQL only */

    /*
    ** Fill in the part of RDF request block that will be constant.
    */
    pst_rdfcb_init(&rdf_cb, sess_cb);
    rdf_rb->rdr_update_op   = RDR_REPLACE;
    rdf_rb->rdr_status	    = DB_SQL;
    rdf_rb->rdr_types_mask  = RDR_USER;
    rdf_rb->rdr_qrytuple    = (PTR) ustup;
    rdf_rb->rdr_qtuple_count = 1;

    ustup->du_gid	= 0;
    ustup->du_mid	= 0;
    ustup->du_flagsmask  = 0;

    /* User profile */
    if(psy_cb->psy_usflag& PSY_USRPROFILE)
    {
	    MECOPY_CONST_MACRO((PTR)&psy_cb->psy_usprofile, 
		sizeof(psy_cb->psy_usprofile), 
	    	(PTR)&ustup->du_profile);
	   
	    ustup->du_flagsmask|= DU_UHASPROFILE;
    }
    else
    {
	MEfill(sizeof(ustup->du_profile),
	       (u_char)' ',
	       (PTR)&ustup->du_profile);
    }

    if ((psy_cb->psy_usflag& PSY_USRPROFILE) &&
	(psy_cb->psy_usflag& PSY_USRPRIVS) &&
	(psy_cb->psy_usflag& PSY_UNOPRIVS) &&
        !(psy_cb->psy_usflag & PSY_UNODEFPRIV))
    {
  	/* If alter user has PSY_UNOPRIVS specified and
  	** we have provided a profile for this user
  	** but we have not set the nodefault_privileges
  	** specified, We should return an error. profile
  	** may have default_privileges, which will be
  	** inherited by the user with noprivileges.
  	*/
  	  err_code = E_US1968_6504_UNOPRIV_WDEFAULT;
  	  (VOID) psf_error( E_US1968_6504_UNOPRIV_WDEFAULT, 0L,
  	     PSF_USERERR, &err_code, &psy_cb->psy_error, 0);
  	  status = E_DB_ERROR;

	  return(status);
    }

    if(psy_cb->psy_usflag& PSY_USRDEFPRIV)
    {
	ustup->du_defpriv = psy_cb->psy_usdefprivs;
	ustup->du_flagsmask|= DU_UDEFPRIV;
	/* Add default=all indicator */
	if(psy_cb->psy_usflag & PSY_USRDEFALL)
		ustup->du_flagsmask|=DU_UDEFALL;

	/* set value of nodefault_privileges flag */
	if (psy_cb->psy_usflag & PSY_UNODEFPRIV)
	  ustup->du_flagsmask|= DU_UNODEFPRIV;
    }
    else
    {
	/*
	** If no default specified use all privileges
	*/
	if (psy_cb->psy_usflag & PSY_USRPRIVS)
		ustup->du_defpriv = (i4)psy_cb->psy_usprivs;
	else
		ustup->du_defpriv = 0;
    }

    /*
    ** Expiration date, may be empty
    */
    if(psy_cb->psy_usflag& PSY_USREXPDATE)
    {
	/*
	** Date already formatted earlier
	*/
	MECOPY_CONST_MACRO((PTR)&psy_cb->psy_date, sizeof(DB_DATE), 
			(PTR)&ustup->du_expdate);
	ustup->du_flagsmask|= DU_UEXPDATE;
    }
    else
    {
	/*
	** Initialize to the empty date
	*/
	db_data.db_datatype  = DB_DTE_TYPE;
	db_data.db_prec	 = 0;
	db_data.db_length    = DB_DTE_LEN;
	db_data.db_data	 = (PTR)&ustup->du_expdate;
	status = adc_getempty(sess_cb->pss_adfcb, &db_data);
	if(status)
		return status;
    }
    /*
    ** Check if adding, deleting, or setting privileges
    */
    ustup->du_status = (i4) psy_cb->psy_usprivs;

	
    if (psy_cb->psy_usflag & PSY_USRAPRIVS)
	ustup->du_flagsmask |=  DU_UAPRIV;
    else if (psy_cb->psy_usflag & PSY_USRDPRIVS)
	ustup->du_flagsmask |=  DU_UDPRIV;
    else if (psy_cb->psy_usflag & PSY_USRPRIVS)
	ustup->du_flagsmask |=  DU_UPRIV;
    else
	ustup->du_status = 0;
    /*
    ** Check if updating security audit options
    */
    if (psy_cb->psy_usflag & PSY_USRSECAUDIT)
    {
	if(psy_cb->psy_ussecaudit & PSY_USAU_ALL_EVENTS)
		ustup->du_flagsmask |= DU_UALLEVENTS;
	else
		ustup->du_flagsmask |= DU_UDEFEVENTS;
	if (psy_cb->psy_ussecaudit & PSY_USAU_QRYTEXT)
		ustup->du_flagsmask |= DU_UQRYTEXT;
	else
		ustup->du_flagsmask |= DU_UNOQRYTEXT;
    }

    if (psy_cb->psy_usflag & PSY_USRDEFGRP)
    {
	MEcopy((PTR)&psy_cb->psy_usgroup,
	       sizeof(ustup->du_group),
	       (PTR)&ustup->du_group);
	ustup->du_flagsmask|= DU_UGROUP;
    }
    else
    {
	MEfill(sizeof(ustup->du_group),
	       (u_char)' ',
	       (PTR)&ustup->du_group);
    }

    encrypt = (STskipblank((char *)&psy_cb->psy_apass,
                           (i4)sizeof(psy_cb->psy_apass))
                            != NULL);
    if (encrypt)
    {
        scf_cb.scf_length       = sizeof (SCF_CB);
        scf_cb.scf_type		= SCF_CB_TYPE;
        scf_cb.scf_facility     = DB_PSF_ID;
        scf_cb.scf_session      = sess_cb->pss_sessid;
        scf_cb.scf_nbr_union.scf_xpasskey =
            (PTR)&ustup->du_name;
        scf_cb.scf_ptr_union.scf_xpassword =
            (PTR)&ustup->du_pass;
        scf_cb.scf_len_union.scf_xpwdlen =
             sizeof(ustup->du_pass);
    }
    else
        STRUCT_ASSIGN_MACRO(psy_cb->psy_apass, ustup->du_pass);

    if (psy_cb->psy_usflag & PSY_USRPASS)
    {
	ustup->du_flagsmask|= DU_UPASS;
        if (psy_cb->psy_usflag & PSY_USREXTPASS)
	     ustup->du_flagsmask |= DU_UEXTPASS;
    }
    else
    {
	MEfill(sizeof(ustup->du_pass),
	       (u_char)' ',
	       (PTR)&ustup->du_pass);
    }

    encrypt2 = (STskipblank((char *)&psy_cb->psy_bpass,
                           (i4)sizeof(psy_cb->psy_bpass))
                            != NULL);
    if (encrypt2)
    {
        scf_cb2.scf_length      = sizeof (SCF_CB);
        scf_cb2.scf_type	= SCF_CB_TYPE;
        scf_cb2.scf_facility    = DB_PSF_ID;
        scf_cb2.scf_session     = sess_cb->pss_sessid;
        scf_cb2.scf_nbr_union.scf_xpasskey =
            (PTR)&ustup->du_name;
        scf_cb2.scf_ptr_union.scf_xpassword =
            (PTR)&ustup2->du_pass;
        scf_cb2.scf_len_union.scf_xpwdlen =
             sizeof(ustup2->du_pass);
    }
    else
        STRUCT_ASSIGN_MACRO(psy_cb->psy_bpass, ustup2->du_pass);

    if (psy_cb->psy_usflag & PSY_USROLDPASS)
	ustup->du_flagsmask|= DU_UOLDPASS;
    else
    {
	MEfill(sizeof(ustup2->du_pass),
	       (u_char)' ',
	       (PTR)&ustup2->du_pass);
    }

    status = E_DB_OK;

    for (psy_usr  = (PSY_USR *)  psy_cb->psy_usrq.q_next;
	 psy_usr != (PSY_USR *) &psy_cb->psy_usrq;
	 psy_usr  = (PSY_USR *)  psy_usr->queue.q_next
	)
    {
	/* STRUCT_ASSIGN_MACRO(psy_usr->psy_usrnm,
			       ustup->du_name); */
	MEcopy((PTR)&psy_usr->psy_usrnm,
	       sizeof(ustup->du_name),
	       (PTR)&ustup->du_name);

	/* Encrypt the password if nonblank and not already hex value */

        if (encrypt)
        {
            STRUCT_ASSIGN_MACRO(psy_cb->psy_apass, ustup->du_pass);
	    if(!(psy_cb->psy_usflag & PSY_HEXPASS))
	    {
		status = scf_call(SCU_XENCODE, &scf_cb);
		if (status != E_DB_OK)
		{
		    err_code = scf_cb.scf_error.err_code;
		    (VOID) psf_error(E_PS0D43_XENCODE_ERROR, 0L,
			PSF_INTERR, &err_code, &psy_cb->psy_error, 0);
		    status = (status > E_DB_SEVERE) ? status : E_DB_SEVERE;
		    return(status);
		}
            }
        }

        if (encrypt2)
        {
            STRUCT_ASSIGN_MACRO(psy_cb->psy_bpass, ustup2->du_pass);
            status = scf_call(SCU_XENCODE, &scf_cb2);
            if (status != E_DB_OK)
            {
                err_code = scf_cb2.scf_error.err_code;
                (VOID) psf_error(E_PS0D43_XENCODE_ERROR, 0L,
                                PSF_INTERR, &err_code, &psy_cb->psy_error, 0);
                status = (status > E_DB_SEVERE) ? status : E_DB_SEVERE;
                return(status);
            }
        }

	stat = rdf_call(RDF_UPDATE, (PTR) &rdf_cb);
	status = (stat > status) ? stat : status;

	if (DB_FAILURE_MACRO(stat))
	    break;
    }

    if (DB_FAILURE_MACRO(status))
	(VOID) psf_rdf_error(RDF_UPDATE, &rdf_cb.rdf_error, 
	    &psy_cb->psy_error);

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

    finalstatus = E_DB_OK;
    error.err_code = 0;

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

    if (DB_FAILURE_MACRO(finalstatus))
    {
	if (report)
	    opx_verror( finalstatus, E_OP0084_DEALLOCATION, error.err_code); /* report
					    ** error and generate an exception */
	else
	    opx_rverror(global->ops_cb->ops_callercb, finalstatus,
		E_OP0084_DEALLOCATION, error.err_code);
					    /* report error only but do not generate an
					    ** exception */
    }
}
Exemplo n.º 18
0
/*{
** Name: psy_reregister	    - REREGISTER a STAR object.
**
**  INTERNAL PSF call format: status = psy_reregister(&psy_cb, &sess_cb);
**
**  EXTERNAL call format:     status = psy_call(PSY_REREGISTER, &psy_cb,
**						&sess_cb);
**
** Description:
**      The psy_reregister function will call QEF to REREGISTER a STAR object.
**	QED_DDL_INFO block has been already prepared, so there is very little to
**	do here.
**
** Inputs:
**      psy_cb
**          .psy_dmucb 			ptr to QED_DDL_INFO
**	sess_cb				Pointer to session control block
**					(Can be NULL)
**
** Outputs:
**      psy_cb
**	    .psy_error			Filled in if error happens
**		.err_code		    What the error was
**		    E_PS0000_OK			Success
**		    E_PS0001_USER_ERROR		User made a mistake
**		    E_PS0002_INTERNAL_ERROR	Internal inconsistency in PSF
**		    E_PS0003_INTERRUPTED	User interrupt
**		    E_PS0005_USER_MUST_ABORT	User must abort xact
**		    E_PS0008_RETRY		Query should be retried.
**	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:
**	    STAR object will be dropped and recreated with the SAME object id.
**	    RDF cache entry for this object will be destroyed.
** History:
**      04-apr-89 (andre)    
**          written
**	15-jun-92 (barbara)
**	    All psy functions called from psy_call pass the same parameters.
**	    Add session control block to fit in with this scheme.
**	03-aug-92 (barbara)
**	    Invalidate registered object from RDF cache.
**	07-dec-92 (andre)
**	    address of psy_dmucb (which is overloaded with the address of a
**	    QED_DDL_INFO) will be stored in QEU_CB.qeu_ddl_info instead
**	    of overloading qeu_qso.
**	10-aug-93 (andre)
**	    fixed the cause of a compiler warning
*/
DB_STATUS
psy_reregister(
	PSY_CB          *psy_cb,
	PSS_SESBLK	*sess_cb,
	QEU_CB		*qeu_cb)
{
    char		*ddb_obj_name;
    i4		err_code;
    RDF_CB		rdf_cb;
    RDR_RB		*rdf_rb = &rdf_cb.rdf_rb;
    DB_STATUS		status;

    qeu_cb->qeu_d_cb = (PTR) NULL;

    qeu_cb->qeu_ddl_info = psy_cb->psy_dmucb;

    qeu_cb->qeu_d_op = QED_RLINK;

    status = qef_call(QEU_DBU, ( PTR ) qeu_cb);

    if (DB_FAILURE_MACRO(status))
    {
	switch (qeu_cb->error.err_code)
	{
	    /* object unknown */
	    case E_QE0031_NONEXISTENT_TABLE:		
	    {
		ddb_obj_name =
			((QED_DDL_INFO *) psy_cb->psy_dmucb)->qed_d1_obj_name;
			
		(VOID) psf_error(E_PS0903_TAB_NOTFOUND, 0L,
		    PSF_USERERR, &err_code, &psy_cb->psy_error,1,
		   psf_trmwhite(sizeof(DD_OBJ_NAME), ddb_obj_name),
			 ddb_obj_name);
		break;
	    }
	    /* interrupt */
	    case E_QE0022_QUERY_ABORTED:
	    {
		(VOID) psf_error(E_PS0003_INTERRUPTED,
		    0L, PSF_USERERR,
		    &err_code, &psy_cb->psy_error,0);
		break;
	    }
	    /* should be retried */
	    case E_QE0023_INVALID_QUERY:
	    {
		psy_cb->psy_error.err_code = E_PS0008_RETRY;
		break;
	    }
	    /* user has some other locks on the object */
	    case E_QE0051_TABLE_ACCESS_CONFLICT:
	    {
		(VOID) psf_error(E_PS0D21_QEF_ERROR, 0L,
		    PSF_USERERR, &err_code, &psy_cb->psy_error,0);
		break;
	    }
	    /* resource related */
	    case E_QE000D_NO_MEMORY_LEFT:
	    case E_QE000E_ACTIVE_COUNT_EXCEEDED:
	    case E_QE000F_OUT_OF_OTHER_RESOURCES:
	    case E_QE001E_NO_MEM:
	    {
		(VOID) psf_error(E_PS0D23_QEF_ERROR,
		    qeu_cb->error.err_code, PSF_USERERR,
		    &err_code, &psy_cb->psy_error,0);
		break;
	    }
	    /* lock timer */
	    case E_QE0035_LOCK_RESOURCE_BUSY:
	    case E_QE0036_LOCK_TIMER_EXPIRED:
	    {
		(VOID) psf_error(4702L,
		    qeu_cb->error.err_code, PSF_USERERR,
		    &err_code, &psy_cb->psy_error,0);
		break;
	    }
	    /* resource quota */
	    case E_QE0052_RESOURCE_QUOTA_EXCEED:
	    case E_QE0067_DB_OPEN_QUOTA_EXCEEDED:
	    case E_QE0068_DB_QUOTA_EXCEEDED:
	    case E_QE006B_SESSION_QUOTA_EXCEEDED:
	    {
		(VOID) psf_error(4707L,
		    qeu_cb->error.err_code, PSF_USERERR,
		    &err_code, &psy_cb->psy_error,0);
		break;
	    }
	    /* log full */
	    case E_QE0024_TRANSACTION_ABORTED:
	    {
		(VOID) psf_error(4706L,
		    qeu_cb->error.err_code, PSF_USERERR,
		    &err_code, &psy_cb->psy_error,0);
		break;
	    }
	    /* deadlock */
	    case E_QE002A_DEADLOCK:
	    {
		(VOID) psf_error(4700L,
		    qeu_cb->error.err_code, PSF_USERERR,
		    &err_code, &psy_cb->psy_error,0);
		break;
	    }
	    /* lock quota */
	    case E_QE0034_LOCK_QUOTA_EXCEEDED:
	    {
		(VOID) psf_error(4705L,
		    qeu_cb->error.err_code, PSF_USERERR,
		    &err_code, &psy_cb->psy_error,0);
		break;
	    }
	    /* inconsistent database */
	    case E_QE0099_DB_INCONSISTENT:
	    {
		(VOID) psf_error(38L,
		    qeu_cb->error.err_code, PSF_USERERR,
		    &err_code, &psy_cb->psy_error,0);
		break;
	    }
	    case E_QE0025_USER_ERROR:
	    {
	      psy_cb->psy_error.err_code = E_PS0001_USER_ERROR;
	      break;
	    }
	    default:
	    {
		(VOID) psf_error(E_PS0D20_QEF_ERROR,
		    qeu_cb->error.err_code,
		    PSF_INTERR, &err_code, &psy_cb->psy_error,0);
	    }
	}

	return (status);
    }

    /* Invalidate registered object from RDF cache */
    {
	QED_DDL_INFO	*ddl_info = (QED_DDL_INFO *)psy_cb->psy_dmucb;

	pst_rdfcb_init(&rdf_cb, sess_cb);
	STRUCT_ASSIGN_MACRO(ddl_info->qed_d7_obj_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);
}
Exemplo n.º 19
0
/*{
** Name: psy_kpermit	- Destroy one or more permits on a database object
**			  (a table or a procedure or an event).
**
**  INTERNAL PSF call format: status = psy_kpermit(&psy_cb, &sess_cb);
**
**  EXTERNAL call format:     status = psy_call(PSY_KPERMIT, &psy_cb, &sess_cb);
**
** Description:
**      The psy_kpermit function removes the definition of one or more permits 
**      on a table, a procedure, or an event from all system relations
**	(protect, tree, and iiqrytext).
**	Optionally, one can tell this function to destroy all of the permits
**	on a given table, procedure or event.
**
**	Dropping all permits on a table is similar enough to dropping those on
**	a procedure, so we will handle them together.  On the other hand, when
**	permit numbers are specified, processing is somewhat differen, e.g.
**	we (at least for now) disallow dropping 0 and 1 on a dbproc.
**	Events follow exactly the same model as procedures.
** Inputs:
**      psy_cb
**          .psy_tables[0]              Id of table for which to destroy
**					permit(s)
**          .psy_numbs[]                Id numbers of the permits to destroy
**					(20 maximum)
**          .psy_numnms                 Number of permit numbers given.  Zero
**					means to destroy all of the permits on
**					the given table.
**	    .psy_tabname[0]		Name of the table for which to destroy
**					permit(s)
**	    .psy_grant			PSY_PDROP if dropping permits on
**					dbproc(s);
**					PSY_TDROP if dropping permits on
**					table(s).
**					PSY_SDROP if dropping security alarms.
**					PSY_EVDROP if dropping permits on
**					event(s).
**	sess_cb				Pointer to session control block.
**
** Outputs:
**	psy_cb
**	    .psy_error			Filled in if an error happens
**		.err_code		    What the error was
**		    E_PS0000_OK			Success
**		    E_PS0001_USER_ERROR		User made a mistake
**		    E_PS0002_INTERNAL_ERROR	Internal inconsistency in PSF
**	Returns:
**	    E_DB_OK			Function completed normally.
**	    E_DB_WARN			Function completed with warning(s)
**	    E_DB_ERROR			Function failed; non-catastrophic error
**	    E_DB_FATAL			Function failed; catastrophic error
**	Exceptions:
**	    none
**
** Side Effects:
**	    Deletes query tree representing predicate of permit from tree
**	    relation, query text of permit definition from iiqrytext relation,
**	    does a dmf alter table on the base table to indicate that there
**	    are no more permissions on it should that happen to be the case.
**	    
** History:
**	02-oct-85 (jeff)
**          written
**	05-aug-88 (andre)
**	    modified for DROPping permits on dbprocs.
**	03-oct-88 (andre)
**	    Modify call to pst_rgent to pass 0 as a query mode since it is
**	    clearly not PSQ_DESTROY.
**	04-oct-88 (andre)
**	    Make sure that the highest status received is reported to caller
**	02-nov-89 (neil)
**	    Alerters: Changes for dropping permits on events.
**	16-jan-90 (ralph)
**	    Add integrity check for DROP PERMIT/SECURITY_ALARM:
**	    don't allow drop permit to drop a security alarm;
**	    don't allow drop security_alarm to drop a permit.
**	    Initialise status to E_DB_OK.
**	12-mar-90 (andre)
**	    set rdr_2types_mask to 0.
**      22-may-90 (teg)
**          init rdr_instr to RDF_NO_INSTR
**	04-feb-91 (neil)
**	    Fix 2 error cases:
**	    1. If pst_rgent returns E_PS0903_TAB_NOTFOUND then return this
**	       error to the user.  Can happen through Dynamic SQL where you
**	       drop the table before you exec the statement that drops grant.
**	    2. Allow E_RD0025_USER_ERROR from RDF_UPDATE and continue.
**	29-aug-91 (andre)
**	    Do not call RDF to destroy permits if the object is a QUEL view
**	    owned by the DBA.
**
**	    Until now we could safely assume that if a view is non-grantable and
**	    there are permits defined on it, then the view is a QUEL view owned
**	    by the DBA and the only permit defined on it is an access permit.
**	    With advent of GRANT WGO, there may be permits defined on views
**	    marked as non-grantable (since "grantable" means that the view is
**	    defined on top of the objects owned by its owner so that its owner
**	    can always grant access to the view) and grantable QUEL views will
**	    be marked as such (this way if a user creates an SQL view on top of
**	    his grantable QUEL view we are guaranteed that the new view is also
**	    grantable).  By not trying to destroy permits on QUEL views owned by
**	    the DBA we will ensure that a user cannot destroy an access permit
**	    which gets created for QUEL views owned by the DBA.
**	16-jun-92 (barbara)
**	    Change interface to pst_rgent.
**	22-jul-92 (andre)
**	    permits 0 and 1 will no longer hold special meaning for tables; in
**	    the past they meant ALL/RETRIEVE TO ALL, but with introduction of
**	    grantable privileges, they will no longer be created.  Whether
**	    permit numbers 0 and 1 will become available for regular permits
**	    needs to be decided, but one thing is for sure, psy_kpermit() will
**	    not need to know about it.
**
**	    If user is destroying all permits or security_alarms, set
**	    RDR_DROP_ALL over rdr_types_mask
**	27-jul-92 (andre)
**	    we may be told that we may not drop a permit or all permits because
**	    it would render some permit or object abandoned
**	03-aug-92 (barbara)
**	    Invalidate base table info from RDF cache.
**	07-aug-92 (teresa)
**	    RDF_INVALID must be called to invalidate the base object from RDF's
**	    relation cache as well as to remove any permit trees from RDF's
**	    qtree cache.
**	08-nov-92 (andre)
**	    having dropped ALL permits on PROCEDURE, remember to set
**	    RDR_PROCEDURE in rdf_inv_cb.rdf_rb.rdr_types_mask before calling
**	    RDF_INVALIDATE
**	26-apr-93 (markg)
**	    Fixed bug which caused AV when attempting to drop a 
**	    security_alarm. The problem was caused by incorrectly
**	    referencing a NULL pointer when initializing a local variable. 
**	10-aug-93 (andre)
**	    fixed cause of compiler warning
**	13-sep-93 (andre)
**	    PSF will no longer be in business of altering timestamps of tables
**	    (or underlying base tables of views) on which permit(s) or 
** 	    security_alarm(s) have been dropped - responsibility for this has 
** 	    been assumed by QEF
*/
DB_STATUS
psy_kpermit(
	PSY_CB             *psy_cb,
	PSS_SESBLK	   *sess_cb)
{
    RDF_CB              rdf_cb;
    RDF_CB              rdf_inv_cb;
    register RDR_RB	*rdf_rb = &rdf_cb.rdf_rb;
    DB_STATUS		status = E_DB_OK;
    i4		err_code;
    i4		msgid;
    register i4	i;
    PSS_RNGTAB		*rngvar;

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

    rdf_rb->rdr_update_op = RDR_DELETE;

    if (psy_cb->psy_grant == PSY_TDROP)		/* dropping perm on a table */
    {
	/* get range table entry for this table */
	status = pst_rgent(sess_cb, &sess_cb->pss_auxrng, -1, "", PST_SHWID,
	    (DB_TAB_NAME*) NULL, (DB_TAB_OWN*) NULL, &psy_cb->psy_tables[0],
	    TRUE, &rngvar, (i4) 0, &psy_cb->psy_error);
	if (DB_FAILURE_MACRO(status))
	{
	    if (psy_cb->psy_error.err_code == E_PS0903_TAB_NOTFOUND)
	    {
		(VOID) psf_error(E_PS0903_TAB_NOTFOUND, 0L, PSF_USERERR,
		    &err_code, &psy_cb->psy_error, 1,
		    psf_trmwhite(sizeof(psy_cb->psy_tabname[0]),
			(char *) &psy_cb->psy_tabname[0]),
		    &psy_cb->psy_tabname[0]);
	    }
	    return (status);
	}
	rdf_rb->rdr_types_mask = RDR_PROTECT;
    }
    else if (psy_cb->psy_grant == PSY_SDROP)	/* dropping security alarm  */
    {
	rdf_rb->rdr_types_mask = RDR_SECALM;
    }
    else if (psy_cb->psy_grant == PSY_PDROP)    /* dropping perm on a dbproc */
    {
	DB_DBP_NAME	*dbpname = (DB_DBP_NAME *) psy_cb->psy_tabname;

	/* save dbproc name and owner for RDF */

	STRUCT_ASSIGN_MACRO(*dbpname, rdf_rb->rdr_name.rdr_prcname); 
	STRUCT_ASSIGN_MACRO(sess_cb->pss_user, rdf_rb->rdr_owner);
	
	rdf_rb->rdr_types_mask = RDR_PROTECT | RDR_PROCEDURE;
	rdf_inv_cb.rdf_rb.rdr_types_mask |= RDR_PROCEDURE;
    }
    else if (psy_cb->psy_grant == PSY_EVDROP)	    /* dropping perm on event */
    {
	DB_EVENT_NAME		*evname = (DB_EVENT_NAME *)psy_cb->psy_tabname;

	/* Save event name and owner for RDF */
	STRUCT_ASSIGN_MACRO(*evname, rdf_rb->rdr_name.rdr_evname); 
	STRUCT_ASSIGN_MACRO(sess_cb->pss_user, rdf_rb->rdr_owner);
	rdf_rb->rdr_types_mask = RDR_PROTECT | RDR_EVENT;
    }

    /* Zero permit numbers means destroy all permits */
    
    if (psy_cb->psy_numnms == 0)
    {
	/*								
	** Note that this block handles destroying all permits on
	** a dbproc, event or a table or all security_alarms on a table
	*/

	/*
	** check if user may drop permits (access permits get special
	** treatment).  If not, we are done.
	*/
	if (psy_cb->psy_grant == PSY_TDROP)
	{
	    /*
	    ** if this is a QUEL view owned by the DBA, avoid calling RDF since
	    ** we need to rpevent a user from destroying access permit which is
	    ** created on such views.
	    */
	    if (   rngvar->pss_tabdesc->tbl_status_mask & DMT_VIEW
		&& !MEcmp((PTR) &sess_cb->pss_dba, (PTR) &rngvar->pss_ownname,
			sizeof(DB_OWN_NAME))
	       )
	    {
		/* check if this is a QUEL view */
		i4	    issql = 0;

		status = psy_sqlview(rngvar, sess_cb, &psy_cb->psy_error,
		    &issql);
		if (DB_FAILURE_MACRO(status))
		{
		    return(status);
		}

		if (!issql)
		{
		    return(E_DB_OK);
		}
	    }
	}
	
	/* tell RDF that we are dropping ALL permits or security_alarms */
	rdf_rb->rdr_types_mask |= RDR_DROP_ALL;

	status = rdf_call(RDF_UPDATE, (PTR) &rdf_cb);
	if (DB_FAILURE_MACRO(status))
	{
	    switch (rdf_cb.rdf_error.err_code)
	    {
		case E_RD0002_UNKNOWN_TBL:  
		{
		    (VOID) psf_error(E_PS0903_TAB_NOTFOUND, 0L, PSF_USERERR,
			&err_code, &psy_cb->psy_error, 1,
			psf_trmwhite(sizeof(psy_cb->psy_tabname[0]),
			    (char *) &psy_cb->psy_tabname[0]),
			&psy_cb->psy_tabname[0]);
		    break;
		}
		case E_RD0201_PROC_NOT_FOUND:
		{
		    (VOID) psf_error(E_PS0905_DBP_NOTFOUND, 0L, PSF_USERERR,
		        &err_code, &psy_cb->psy_error, 1,
		        psf_trmwhite(sizeof(psy_cb->psy_tabname[0]),
			    (char *) &psy_cb->psy_tabname[0]),
		        &psy_cb->psy_tabname[0]);
		    break;
		}
		case E_RD0210_ABANDONED_OBJECTS:
		{
		    char	*obj_type;
		    i4		type_len;

		    switch (psy_cb->psy_grant)
		    {
			case PSY_TDROP:
			    obj_type = "table";
			    type_len = sizeof("table") - 1;
			    break;
			case PSY_PDROP:
			    obj_type = "database procedure";
			    type_len = sizeof("database procedure") - 1;
			    break;
			case PSY_EVDROP:
			    obj_type = "dbevent";
			    type_len = sizeof("dbevent") - 1;
			    break;
			default:
			    obj_type = "UNKNOWN OBJECT TYPE";
			    type_len = sizeof("UNKNOWN OBJECT TYPE") - 1;
			    break;
		    }
		    
		    (VOID) psf_error(E_PS0564_ALLPROT_ABANDONED_OBJ, 0L,
			PSF_USERERR, &err_code, &psy_cb->psy_error, 2,
			type_len, obj_type,
			psf_trmwhite(sizeof(psy_cb->psy_tabname[0]),
			    (char *) psy_cb->psy_tabname),
			psy_cb->psy_tabname);
		    break;
		}
		default: 
		{
		    /* Event errors are handled in QEF */
		    (VOID) psf_rdf_error(RDF_UPDATE, &rdf_cb.rdf_error,
					 &psy_cb->psy_error);
		}
	    }

	    return (status);
	}
	/*
	** Invalidate base object's infoblk from RDF cache; rdr_tabid
	** already contains base table id; Call RDF to invalidate the
	** base object. Then call again to invalidate any permit trees,
	** set rdr_2_types mask for tree.
	*/
	status = rdf_call(RDF_INVALIDATE, (PTR) &rdf_inv_cb); /* drop infoblk */
	if (DB_FAILURE_MACRO(status))
	{
	    (VOID) psf_rdf_error(RDF_INVALIDATE, &rdf_inv_cb.rdf_error,
				&psy_cb->psy_error);
	    return(status);
	}
	rdf_inv_cb.rdf_rb.rdr_2types_mask |= RDR2_CLASS; /* drop permit trees */
	status = rdf_call(RDF_INVALIDATE, (PTR) &rdf_inv_cb);
	if (DB_FAILURE_MACRO(status))
	{
	    (VOID) psf_rdf_error(RDF_INVALIDATE, &rdf_inv_cb.rdf_error,
				&psy_cb->psy_error);
	    return(status);
	}
    }
    else if (psy_cb->psy_grant == PSY_PDROP || psy_cb->psy_grant == PSY_EVDROP)
    {
	DB_STATUS   stat;
	
	/* Run through permit numbers, destroying each one */
	for (i = 0; i < psy_cb->psy_numnms; i++)
	{
	    rdf_rb->rdr_qrymod_id = psy_cb->psy_numbs[i];

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

	    /* remember the error to report later */
	    status = (status > stat) ? status : stat;

	    if (DB_FAILURE_MACRO(status))
	    {
		switch (rdf_cb.rdf_error.err_code)
		{
		    case E_RD0201_PROC_NOT_FOUND:
		    {
			(VOID) psf_error(E_PS0905_DBP_NOTFOUND, 0L,
			    PSF_USERERR, &err_code, &psy_cb->psy_error, 1,
			    psf_trmwhite(sizeof(psy_cb->psy_tabname[0]),
			 	(char *) &psy_cb->psy_tabname[0]),
			    &psy_cb->psy_tabname[0]);
			break;
		    }
		    case E_RD0210_ABANDONED_OBJECTS:
		    {
			char	*obj_type;
			i4	type_len;

			if (psy_cb->psy_grant == PSY_PDROP)
			{
			    obj_type = "database procedure";
			    type_len = sizeof("database procedure") - 1;
			}
			else
			{
			    obj_type = "dbevent";
			    type_len = sizeof("dbevent") - 1;
			}

			(VOID) psf_error(E_PS0565_PROT_ABANDONED_OBJ, 0L,
			    PSF_USERERR, &err_code, &psy_cb->psy_error, 3,
			    sizeof(psy_cb->psy_numbs[i]), psy_cb->psy_numbs + i,
			    type_len, obj_type,
			    psf_trmwhite(sizeof(psy_cb->psy_tabname[0]),
				(char *) psy_cb->psy_tabname),
			    psy_cb->psy_tabname);
			break;
		    }
		    case E_RD0013_NO_TUPLE_FOUND:
		    {
			(VOID) psf_error((i4) 5204, 0L, PSF_USERERR,
					 &err_code, &psy_cb->psy_error, 1,
					 sizeof (rdf_rb->rdr_qrymod_id),
					 &rdf_rb->rdr_qrymod_id);
			continue;
		    }

		    case E_RD0025_USER_ERROR:
			/*
			** Warning already handled - may be repeated when
			** we try some more updates (if this is a multi-
			** permit drop).
			*/
			if (psy_cb->psy_grant == PSY_EVDROP)
			{
			    status = E_DB_OK;
			    continue;
			}
			/* else fall through */
		    
		    default:
		    {
			/* Event-specific errors are reported through QEF */
			(VOID) psf_rdf_error(RDF_UPDATE, &rdf_cb.rdf_error,
					     &psy_cb->psy_error);
			break;
		    }
		}

		return (status);
	    }

	    /*
	    ** Invalidate base object's infoblk from RDF cache: rdr_tabid
	    ** already contains base table id; rdr_sequence contains
	    ** permit number; set rdr_2_types mask.
	    */
	    rdf_inv_cb.rdf_rb.rdr_sequence = psy_cb->psy_numbs[i];
	    rdf_inv_cb.rdf_rb.rdr_2types_mask |= RDR2_ALIAS;
	    status = rdf_call(RDF_INVALIDATE, (PTR) &rdf_inv_cb);
	    if (DB_FAILURE_MACRO(status))
	    {
		(VOID) psf_rdf_error(RDF_INVALIDATE, &rdf_inv_cb.rdf_error,
				    &psy_cb->psy_error);
		return(status);
	    }
	}
	/* 
	** invalidate the relation cache entry that the permit was defined on 
	*/
	rdf_inv_cb.rdf_rb.rdr_2types_mask &= ~RDR2_ALIAS;
	status = rdf_call(RDF_INVALIDATE, (PTR) &rdf_inv_cb);
	if (DB_FAILURE_MACRO(status))
	{
	    (VOID) psf_rdf_error(RDF_INVALIDATE, &rdf_inv_cb.rdf_error,
				&psy_cb->psy_error);
	    return(status);
	}
    }
    else	    /* drop permit or security alarm on a table */
    {
	DB_STATUS   stat;
	bool	    cant_drop_perms = FALSE;

	if (psy_cb->psy_grant == PSY_TDROP)
	{
	    i4	mask = rngvar->pss_tabdesc->tbl_status_mask;
	    /*
	    ** if this is a QUEL view owned by the DBA, avoid calling RDF since
	    ** we need to rpevent a user from destroying access permit which is
	    ** created on such views.  Instead, we will act as if the tuple was
	    ** not found by QEF (without actually calling it.)
	    */
	    if (   mask & DMT_VIEW
		&& !MEcmp((PTR) &sess_cb->pss_dba, (PTR) &rngvar->pss_ownname,
			sizeof(DB_OWN_NAME))
	       )
	    {
		/* check if this is a QUEL view */
		i4	    issql = 0;

		status = psy_sqlview(rngvar, sess_cb, &psy_cb->psy_error,
		    &issql);
		if (DB_FAILURE_MACRO(status))
		{
		    return(status);
		}

		if (!issql)
		{
		    cant_drop_perms = TRUE;
		    
		    /* errors will be reported later */
		    status = E_DB_ERROR;
		}
	    }
	}

	/* Run through permit or security_alarm numbers, destroying each one */
	for (i = 0; i < psy_cb->psy_numnms; i++)
	{
	    if (cant_drop_perms)
	    {
		(VOID) psf_error(5204L, 0L, PSF_USERERR,
		    &err_code, &psy_cb->psy_error, 1,
		    sizeof (psy_cb->psy_numbs[i]), (PTR) &psy_cb->psy_numbs[i]);
		continue;
	    }
	    else
	    {
		rdf_rb->rdr_qrymod_id = psy_cb->psy_numbs[i];
	    }

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

	    /* remember the error to report later */
	    status = (status > stat) ? status : stat;
	    
	    if (DB_FAILURE_MACRO(stat))
	    {
		switch (rdf_cb.rdf_error.err_code)
		{
		    case E_RD0002_UNKNOWN_TBL:
		    {
			(VOID) psf_error(E_PS0903_TAB_NOTFOUND, 0L,
			    PSF_USERERR, &err_code, &psy_cb->psy_error, 1,
			    psf_trmwhite(sizeof(psy_cb->psy_tabname[0]),
			        (char *) &psy_cb->psy_tabname[0]),
			    &psy_cb->psy_tabname[0]);
			break;
		    }

		    case E_RD0210_ABANDONED_OBJECTS:
		    {
			(VOID) psf_error(E_PS0565_PROT_ABANDONED_OBJ, 0L,
			    PSF_USERERR, &err_code, &psy_cb->psy_error, 3,
			    sizeof(psy_cb->psy_numbs[i]), psy_cb->psy_numbs + i,
			    sizeof("table") - 1, "table",
			    psf_trmwhite(sizeof(psy_cb->psy_tabname[0]),
				(char *) psy_cb->psy_tabname),
			    psy_cb->psy_tabname);
			break;
		    }
		    case E_RD0013_NO_TUPLE_FOUND:
		    {
			if (psy_cb->psy_grant == PSY_SDROP)
			    msgid = (i4)5213;
			else
			    msgid = (i4)5204;
			(VOID) psf_error(msgid, 0L, PSF_USERERR,
					 &err_code, &psy_cb->psy_error, 1,
					 sizeof (rdf_rb->rdr_qrymod_id),
					 &rdf_rb->rdr_qrymod_id);
			continue;
		    }

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

		return (status);
	    }

	    /*
	    ** Invalidate base object's infoblk from RDF cache: rdr_tabid
	    ** already contains base table id; rdr_sequence contains
	    ** permit number (if not drop security alarm); set rdr_2_types mask.
	    */
	    if (psy_cb->psy_grant == PSY_SDROP)
	    {
		rdf_inv_cb.rdf_rb.rdr_2types_mask |= RDR2_KILLTREES;
	    }
	    else
	    {
		rdf_inv_cb.rdf_rb.rdr_2types_mask |= RDR2_ALIAS;
		rdf_inv_cb.rdf_rb.rdr_types_mask = RDR_PROTECT;
	    }
	    status = rdf_call(RDF_INVALIDATE, (PTR) &rdf_inv_cb);
	    if (DB_FAILURE_MACRO(status))
	    {
		(VOID) psf_rdf_error(RDF_INVALIDATE, &rdf_inv_cb.rdf_error,
				    &psy_cb->psy_error);
		return(status);
	    }
	}

	/* now invalidate the base object that the permit was defined on */
	rdf_inv_cb.rdf_rb.rdr_2types_mask &= ~(RDR2_ALIAS | RDR2_KILLTREES);
	status = rdf_call(RDF_INVALIDATE, (PTR) &rdf_inv_cb);
	if (DB_FAILURE_MACRO(status))
	{
	    (VOID) psf_rdf_error(RDF_INVALIDATE, &rdf_inv_cb.rdf_error,
				&psy_cb->psy_error);
	    return(status);
	}
    }

    return    (status);
} 
Exemplo n.º 20
0
DB_STATUS
psy_calarm(
	PSY_CB	   *psy_cb,
	PSS_SESBLK *sess_cb)
{
    RDF_CB		rdf_cb;
    RDR_RB		*rdf_rb = &rdf_cb.rdf_rb;
    i4			textlen;		/* Length of query text */
    QSF_RCB		qsf_rb;
    DB_STATUS		status, loc_status;
    i4		err_code;
    DB_SECALARM		*alarm= &psy_cb->psy_tuple.psy_alarm;

    /* Fill in QSF request to lock text */
    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;

    /* Initialize RDF_CB */
    pst_rdfcb_init(&rdf_cb, sess_cb);
    rdf_rb->rdr_types_mask  = RDR_SECALM;	/* Alarm definition */
    rdf_rb->rdr_update_op   = RDR_APPEND;
    rdf_rb->rdr_qrytuple    = (PTR)&psy_cb->psy_tuple.psy_alarm; /* Alarm tuple */

    /*
    ** Get the query text from QSF.  QSF has stored the text 
    ** as a {nat, string} pair - maybe not be aligned.
    */
    STRUCT_ASSIGN_MACRO(psy_cb->psy_qrytext, qsf_rb.qsf_obj_id);
    status = qsf_call(QSO_INFO, &qsf_rb);
    if (status != E_DB_OK)
    {
	psf_error(E_PS0D19_QSF_INFO, qsf_rb.qsf_error.err_code,
		  PSF_INTERR, &err_code, &psy_cb->psy_error, 0);
	goto cleanup;
    }
    MEcopy((PTR)qsf_rb.qsf_root, sizeof(i4), (PTR)&textlen);
    rdf_rb->rdr_l_querytext	= textlen;
    rdf_rb->rdr_querytext	= ((char *)qsf_rb.qsf_root) + sizeof(i4);
    rdf_rb->rdr_tabid.db_tab_base=alarm->dba_objid.db_tab_base;

    /*
    ** Check type of alarm, and handle accordingly.
    ** Main difference is where/how subjects are handled:
    ** - Named alarms have a single subject, which has already been 
    **   resolved in psl. Alarms to public are handled here also
    ** - Anonymous alarms (old style) may have multiple subjects. These
    **   operate much like permits, and are split into several alarms, one
    **   for each subject.
    */
    if(STskipblank((char*)&alarm->dba_alarmname,
		sizeof(alarm->dba_alarmname)) ==NULL &&
	    (alarm->dba_subjtype==DBGR_USER ||
	     alarm->dba_subjtype==DBGR_APLID ||
	     alarm->dba_subjtype==DBGR_GROUP)
	)
    {
        PSY_USR		*psy_usr;
	u_char		*subj_name;
	i4		subj_name_len;
        u_char          delim_subj_name[DB_MAX_DELIMID];
	/*
	** Anonymous alarms.
	** We loop over each subject, updating the query text for
	** each subject and creating the alarm.
	*/
	psy_usr = (PSY_USR *) psy_cb->psy_usrq.q_next;
	do 
	{
	    subj_name = (u_char *) &psy_usr->psy_usrnm;
	    subj_name_len = 
		(i4) psf_trmwhite(sizeof(psy_usr->psy_usrnm), 
		    (char *) subj_name);
	    if (~psy_usr->psy_usr_flags & PSY_REGID_USRSPEC)
	    {
		status = psl_norm_id_2_delim_id(&subj_name, 
		    &subj_name_len, delim_subj_name, 
		    &psy_cb->psy_error);
		if (DB_FAILURE_MACRO(status))
			return status;
	    }
	    if (subj_name_len < DB_MAX_DELIMID)
		subj_name[ subj_name_len ] = EOS;
	    STmove((char*)subj_name, ' ', DB_MAX_DELIMID,
		  rdf_rb->rdr_querytext + psy_cb->psy_noncol_grantee_off);

            STmove((char*)subj_name, ' ', sizeof(alarm->dba_subjname),
		(char*)&alarm->dba_subjname);
			
	    /* Reset alarm name in case filled in by RDF/QEF */
	    MEfill(sizeof(alarm->dba_alarmname), ' ',
		    (PTR)&alarm->dba_alarmname);


	    /* Create a new alarm in iisecalarm */
	    status = rdf_call(RDF_UPDATE, (PTR) &rdf_cb);
	    if (status != E_DB_OK)
	    {
		if (   rdf_cb.rdf_error.err_code == E_RD0002_UNKNOWN_TBL)
		{
		    psf_error(E_PS0903_TAB_NOTFOUND, 0L, PSF_USERERR, &err_code,
			  &psy_cb->psy_error, 1, 
			  psf_trmwhite(sizeof(psy_cb->psy_tabname[0]),
				   (char *) &psy_cb->psy_tabname[0]),
			  &psy_cb->psy_tabname[0]);
		}
		else
		{
		    _VOID_ psf_rdf_error(RDF_UPDATE, &rdf_cb.rdf_error,
				 &psy_cb->psy_error);
	        }
		goto cleanup;
	    } /* If RDF error */

	    /* Next subject */
	    psy_usr = (PSY_USR *) psy_usr->queue.q_next;
        } while (psy_usr != (PSY_USR *) &psy_cb->psy_usrq);
    }
    else
    {
	/* Named alarms */
	/* Create a new alarm in iisecalarm */
	status = rdf_call(RDF_UPDATE, (PTR) &rdf_cb);
	if (status != E_DB_OK)
	{
	    if (   rdf_cb.rdf_error.err_code == E_RD0002_UNKNOWN_TBL)
	    {
		psf_error(E_PS0903_TAB_NOTFOUND, 0L, PSF_USERERR, &err_code,
			  &psy_cb->psy_error, 1, 
			  psf_trmwhite(sizeof(psy_cb->psy_tabname[0]),
				   (char *) &psy_cb->psy_tabname[0]),
			  &psy_cb->psy_tabname[0]);
	    }
	    else
	    {
		_VOID_ psf_rdf_error(RDF_UPDATE, &rdf_cb.rdf_error,
				 &psy_cb->psy_error);
	    }
	    goto cleanup;
	} /* If RDF error */
    }

cleanup:
    qsf_rb.qsf_lk_state	= QSO_EXLOCK;

    /* Destroy query text - lock it first */
    STRUCT_ASSIGN_MACRO(psy_cb->psy_qrytext, qsf_rb.qsf_obj_id);
    loc_status = qsf_call(QSO_LOCK, &qsf_rb);
    if (loc_status != E_DB_OK)
    {
	psf_error(E_PS0D18_QSF_LOCK, qsf_rb.qsf_error.err_code,
		  PSF_INTERR, &err_code, &psy_cb->psy_error, 0);
	if (loc_status > status)
	    status = loc_status;
    }
    loc_status = qsf_call(QSO_DESTROY, &qsf_rb);
    if (loc_status != E_DB_OK)
    {
	psf_error(E_PS0D1A_QSF_DESTROY, qsf_rb.qsf_error.err_code,
		  PSF_INTERR, &err_code, &psy_cb->psy_error, 0);
	if (loc_status > status)
	    status = loc_status;
    }

    /* Invalidate tableinfo from RDF cache if table object */
    if(psy_cb->psy_gtype==DBOB_TABLE)
    {
        pst_rdfcb_init(&rdf_cb, sess_cb);
        STRUCT_ASSIGN_MACRO(alarm->dba_objid, rdf_rb->rdr_tabid);
        loc_status = rdf_call(RDF_INVALIDATE, (PTR) &rdf_cb);
        if (DB_FAILURE_MACRO(loc_status))
        {
	    (VOID) psf_rdf_error(RDF_INVALIDATE, &rdf_cb.rdf_error,
				&psy_cb->psy_error);
	    if (loc_status > status)
	        status = loc_status;
	}
    }
    return (status);
} /* psy_calarm */
Exemplo n.º 21
0
/*{
** Name: psy_drop_synonym - Drop an IISYNONYM tuple.
**
** Description:
**	Call RDF_UPDATE to delete a tuple from IISYNONYM.
** Inputs:
**	psy_cb		PSY control block.
**	sess_cb		PSF session control block.
** Outputs:
**	Exceptions:
**	    none
** Returns:
**	E_DB_OK			synonym tuple has been deleted 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 table infoblk from RDF's cache.
**	10-aug-93 (andre)
**	    fixed causes of compiler warnings
**	13-sep-93 (andre)
**	    QEF will assume responsibility for altering timestamps of tables
**	    (or underlying tables of views) synonym(s) on which have been 
**	    dropped.  We will supply QEF with the id of the object on which 
**	    the synonym was defined
**	22-oct-93 (andre)
**	    In the unlikely event that RDF's cache entry for the synonym named 
**	    in the DROP SYNONYM statement is stale and the synonym no longer 
**	    exists, RDF will return E_RD014A_NONEXISTENT_SYNONYM which we will 
**	    translate into 2753L
*/
DB_STATUS
psy_drop_synonym(
	PSY_CB	   *psy_cb,
	PSS_SESBLK *sess_cb)
{
    RDF_CB		rdf_cb;
    RDF_CB		rdf_inv_cb;
    DB_IISYNONYM	syn_tuple;
    register RDR_RB	*rdf_rb = &rdf_cb.rdf_rb;
    DB_STATUS		status;
    register i4	syn_count;
    i4		err_code;


    /* Initialize the RDF request block. */
    pst_rdfcb_init(&rdf_cb, sess_cb);
    pst_rdfcb_init(&rdf_inv_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_DELETE;
    rdf_rb->rdr_qrytuple = (PTR) &syn_tuple;
    rdf_rb->rdr_tabid.db_tab_base = DM_B_SYNONYM_TAB_ID;
    rdf_rb->rdr_tabid.db_tab_index = DM_I_SYNONYM_TAB_ID;

    MEmove(sizeof(DB_OWN_NAME), (char *)&sess_cb->pss_user, ' ',
           sizeof(DB_SYNOWN), (char *)&syn_tuple.db_synowner);

    for (syn_count = 0; syn_count < psy_cb->psy_numtabs; syn_count++)
    {
	/* store synonym name in the tuple */
	MEmove(sizeof(DB_TAB_NAME), (char *)(psy_cb->psy_tabname + syn_count),
	       ' ', sizeof(DB_SYNNAME), (char *)&syn_tuple.db_synname);
	
	syn_tuple.db_syntab_id.db_tab_base = 
	    psy_cb->psy_tables[syn_count].db_tab_base;
	
	syn_tuple.db_syntab_id.db_tab_index = 
	    psy_cb->psy_tables[syn_count].db_tab_index;

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

	if (DB_FAILURE_MACRO(status))
	{
	    if (rdf_cb.rdf_error.err_code == E_RD0144_DROP_SYNONYM)
	    {
		(VOID) psf_error(E_PS0456_DROP_SYN_ERROR, 0L, PSF_USERERR,
		    &err_code, &psy_cb->psy_error, 1,
		    psf_trmwhite(sizeof(DB_SYNNAME), 
			(char *) &syn_tuple.db_synname),
		    &syn_tuple.db_synname);
	    }
	    else if (rdf_cb.rdf_error.err_code == E_RD014A_NONEXISTENT_SYNONYM)
	    {
		/* 
		** looks like RDF cache entry was stale - tell user that 
		** synonym did not exist and proceed on to the next entry
		*/
		status = E_DB_OK;

		(VOID) psf_error(2753L, 0L, PSF_USERERR, &err_code,
		    &psy_cb->psy_error, 2,
		    sizeof("DROP SYNONYM") - 1, "DROP SYNONYM",
		    psf_trmwhite(sizeof(DB_SYNNAME), 
			(char *) &syn_tuple.db_synname),
		    &syn_tuple.db_synname);
		
		continue;
	    }
	    else
	    {
		(VOID) psf_rdf_error(RDF_UPDATE, &rdf_cb.rdf_error,
		    &psy_cb->psy_error);
	    }
	    break;
	}


	STRUCT_ASSIGN_MACRO(psy_cb->psy_tables[syn_count],
			    rdf_inv_cb.rdf_rb.rdr_tabid);
				
	status = rdf_call(RDF_INVALIDATE, (PTR) &rdf_inv_cb);

	if (DB_FAILURE_MACRO(status))
	{
	    (VOID) psf_rdf_error(RDF_INVALIDATE, &rdf_inv_cb.rdf_error,
				&psy_cb->psy_error);
	    break;
	}
    }

    return (status);
}
Exemplo n.º 22
0
/*{
** Name: opv_parser	- init global range table element given parser varno
**
** Description:
**      This routine will initialize the global range table element in OPF
**      corresponding to the PSF range table element.
**
** Inputs:
**      global                          ptr to global range table
**      gvar                            element in parser range table
**                                      which is referenced in query
**
** Outputs:
**      global->ops_rangetab.opv_base[gvar] initialize corresponding element
**                                      in optimizer range table
**	Returns:
**	    VOID
**	Exceptions:
**	    none
**
** Side Effects:
**	    none
**
** History:
**	2-jul-86 (seputis)
**          initial creation
**	6-nov-88 (seputis)
**          change RDF invalidation to include all indexes on base relation
**          since this is only notification that OPF gets that its' time
**          stamp is out of date
**      25-sep-89 (seputis)
**          - made addition to timestamp check, to refresh if this is a
**          multi-variable query and the tuple count is zero
**	9-nov-89 (seputis)
**          - added OPA_NOVID initialization for b8160, and corrected
**	    sep 25 fix for timestamps
**	12-jan-90 (seputis)
**	    - detect table ID's which are the same for different range vars
**	26-feb-91 (seputis)
**	    - add improved diagnostics for b35862
**      31-dec-91 (seputis)
**          - flush cache entry if tuple count is zero and more than one
**          range table entry, since aggregate queries and flattened queries
**          are not getting handled.
**	12-feb-93 (jhahn)
**	    Added support for statement level rules. (FIPS)
**	12-apr-93 (ed)
**	    - fix bug 50673, relax range variable check for larger OPF table
**      7-dec-93 (ed)
**          b56139 - add OPZ_TIDHISTO to mark tid attributes which
**          need histograms,... needed since target list is traversed
**          earlier than before
**      16-feb-95 (inkdo01)
**          b66907 - check for explicit refs to inconsistent tabs/idxes
**      23-feb-95 (wolf) 
**          Recent addition of MEcopy call should have been accompanied by
**	    an include of me.h
**      10-aug-98 (stial01)
**          opv_parser() Remove code to invalidate indexes. The invalidate
**          table that follows will do the job. Invalidate indexes by table id
**          can get E_OP008E_RDF_INVALIDATE, E_RD0045_ULH_ACCESS
**	31-oct-1998 (nanpr01)
**	    Reset the rdfcb->infoblk ptr before checking the error code.
**	18-june-99 (inkdo01)
**	    Init opv_ttmodel for temp table model histogram feature.
**	19-Jan-2000 (thaju02)
**	    relation descriptor may be out of date and contain a stale 
**	    secondary index count, use rdfcb->rdf_info_block->rdr_no_index 
**	    which reflects the number of index entries in the rdr_indx 
**	    array. (b100060)
**	17-Jan-2004 (schka24)
**	    Rename RDR_BLD_KEY to RDR_BLD_PHYS.
**	3-Sep-2005 (schka24)
**	    Remove if-0'ed out section that included a ref to a member
**	    that is going away (opv_ghist).
**	17-Nov-2005 (schka24)
**	    Don't propagate RDF invalidates that we cause.  Our RDF cache
**	    is out of date but that's not other servers' problem.
**	14-Mar-2007 (kschendel) SIR 122513
**	    Light "partitioned" flag if partitioned table seen.
**	18-april-2008 (dougi)
**	    Add support for table procedures.
**	8-Jul-2010 (wanfr01) b123949
**	    If rdf_gdesc failed with an error, don't use the column 
**	    information - it may not be fully initialized.
*/
bool
opv_parser(
	OPS_STATE          *global,
	OPV_IGVARS	   gvar,
	OPS_SQTYPE         sqtype,
	bool		   rdfinfo,
	bool               psf_table,
	bool               abort)
{
    OPV_GRT             *gbase;	    /* ptr to base of global range table */

# ifdef E_OP0387_VARNO
    if ((gvar < 0) || ((gvar >= PST_NUMVARS) && (gvar >= OPV_MAXVAR)))
	opx_error(E_OP0387_VARNO ); /* range var out of range - 
                                    ** consistency check */
# endif

    gbase = global->ops_rangetab.opv_base; /* get base of global range table
                                    ** ptr to array of ptrs */
    if ( !gbase->opv_grv[gvar] )
    {
	/* if global range variable element has not been allocated */
	OPV_GRV             *grvp;	    /* ptr to new range var element */
	
        if (global->ops_rangetab.opv_gv <= gvar)
            global->ops_rangetab.opv_gv = gvar+1; /* update the largest range
                                            ** table element assigned so far
                                            */
        grvp = (OPV_GRV *) opu_memory(global, sizeof( OPV_GRV ) ); /* save
                                            ** and allocate ptr to global
                                            ** var */
	/* Explicitly zero out the grv entry */
	MEfill(sizeof(*grvp), (u_char)0, (PTR)grvp);
	grvp->opv_qrt = gvar;		    /* save index to
                                            ** parser range table element */
        grvp->opv_created = sqtype;         /* save global range table type */
	grvp->opv_gvid = OPA_NOVID;	    /* if this base table was implicitly
					    ** referenced then the view id of the
					    ** explicitly reference view will be
					    ** saved */
        grvp->opv_siteid = OPD_NOSITE;      /* initialize distributed site location */
	grvp->opv_same = OPV_NOGVAR;	    /* used to map tables with similiar
					    ** IDs */
	grvp->opv_compare = OPV_NOGVAR;	    /* used to map tables with similiar
					    ** IDs */
	grvp->opv_ttmodel = NULL;	    /* RDR_INFO ptr for temp table model
					    ** histograms */
	gbase->opv_grv[gvar] = grvp;	    /* place into table */

        /* get RDF information about the table */
        if (rdfinfo)
        {
	    RDF_CB             *rdfcb;	    /* ptr to RDF control block which
                                            ** has proper db_id and sessionid
                                            ** info */
	    PST_RNGENTRY       *rngentry;   /* ptr to parse tree range entry */
	    DB_STATUS          status;      /* RDF return status */

	    i4	       ituple;

            rdfcb = &global->ops_rangetab.opv_rdfcb;
	    if (psf_table)
	    {
		/* Snag table procedures and handle them elsewhere. */
		if ((rngentry = global->ops_qheader->pst_rangetab[gvar])
						->pst_rgtype == PST_TPROC)
		{
		    if (opv_tproc(global, gvar, grvp, rngentry) == E_DB_OK)
			return(FALSE);
		    else return(TRUE);
		}

		STRUCT_ASSIGN_MACRO(global->ops_qheader->pst_rangetab[gvar]->
		    pst_rngvar, rdfcb->rdf_rb.rdr_tabid); /* need 
						** table id from parser's table */
#if 0
                if ((BTnext((i4)-1, (char *)&rangep->pst_outer_rel,
                    (i4)BITS_IN(rangep->pst_outer_rel)) >= 0)
                    ||
                    (BTnext((i4)-1, (char *)&rangep->pst_inner_rel,
                    (i4)BITS_IN(rangep->pst_outer_rel)) >= 0)
                    )
                    grvp->opv_gmask |= OPV_GOJVAR; /* mark whether this
                                            ** variable is within the scope of an
                                            ** outer join */
/* OPV_GOJVAR is not reliably set since the subquery bitmap should be tested 
** also for an aggregate temp, multi-to-one mappings may exist for global range
** variables
*/
#endif
		if (global->ops_qheader->pst_rangetab[gvar]->
		    pst_rgtype == PST_SETINPUT)
		    grvp->opv_gmask |= OPV_SETINPUT; /* is this the set input
						    ** parameter for a procedure
						    */
		rdfcb->rdf_rb.rdr_types_mask = RDR_RELATION | RDR_INDEXES |
		    RDR_ATTRIBUTES | RDR_BLD_PHYS; /* get relation info 
						** - The optimizer uses attribute
						** info in query tree directly 
						** but it is needed to be requested
						** since the RDF uses attr info to
						** build RDR_BLK_KEY info.  The
						** attribute info does not need to
						** requested if RDF is changed.
						** - ask for indexes so that
						** invalidating the cache can also
						** invalidate any indexes in the
						** cache
						*/
/* When we're ready to enable column comparison stats, uncomment the
   following statement. **
		rdfcb->rdf_rb.rdr_2types_mask = RDR2_COLCOMPARE; /* column 
						** comparison stats, too */
		
	    }
	    rdfcb->rdf_info_blk = NULL;     /* get new ptr to info
                                            ** associated with global var */
            status = rdf_call( RDF_GETDESC, (PTR)rdfcb);
	    grvp->opv_relation = rdfcb->rdf_info_blk; /* save ptr to
                                            ** new info block */
	    if ((status != E_RD0000_OK)
		&&
		(rdfcb->rdf_error.err_code != E_RD026A_OBJ_INDEXCOUNT) /* this
					    ** is a check for distributed
					    ** index information, which could
					    ** be inconsistent but should not
					    ** cause the query to be aborted
					    ** it will cause indexes to be
					    ** avoided */
		)
	    {
		gbase->opv_grv[gvar] = NULL;
		if (abort)
		    opx_verror( status, E_OP0004_RDF_GETDESC,
			rdfcb->rdf_error.err_code);
		else
		{
		    return (TRUE);	/* indicate failure to get RDF
				    ** descriptor */
		}
	    }
            BTset( (i4)gvar, (char *)&global->ops_rangetab.opv_mrdf); /* indicate
                                            ** that RDF information is fixed */

	    /* Check table and all associated indexes to see if there is a
	    ** statement level index associated with this variable
	    */
	    if (grvp->opv_relation->rdr_rel->tbl_2_status_mask
		& DMT_STATEMENT_LEVEL_UNIQUE)
		grvp->opv_gmask |= OPV_STATEMENT_LEVEL_UNIQUE;
	    for( ituple = grvp->opv_relation->rdr_no_index;
		ituple-- ;)
	    {
		if (grvp->opv_relation->rdr_indx[ituple]->idx_status
		    & DMT_I_STATEMENT_LEVEL_UNIQUE)
		    grvp->opv_gmask |= OPV_STATEMENT_LEVEL_UNIQUE;
	    }
	    if (psf_table)
	    {	/* check if timestamp matches and invalidate RDF cache
                ** date of last modify do not match, this is only done
		** for tables passed by PSF, the other tables should
		** be dependent on the PSF time stamp */
		DB_TAB_TIMESTAMP	*timeptr; /* ptr to last modify
                                            ** date that RDF has cached */
		DB_TAB_TIMESTAMP	*psftimeptr; /* ptr to last modify
					    ** date which parser used for the
                                            ** table */
		psftimeptr = &global->ops_qheader->pst_rangetab[gvar]->
		    pst_timestamp;
		timeptr = &grvp->opv_relation->rdr_rel->tbl_date_modified;
                if (timeptr->db_tab_high_time != psftimeptr->db_tab_high_time
                    ||
                    timeptr->db_tab_low_time != psftimeptr->db_tab_low_time
                    ||
                    (
                        !grvp->opv_relation->rdr_rel->tbl_record_count
                        &&
                        (global->ops_qheader->pst_rngvar_count
                            > 1)
		     )			    /* special zero tuple count
                                            ** case check to see if tuple count
                                            ** is way off, i.e. a table create
                                            ** followed by a number of appends
                                            ** will cause a 0 tuple count, check
					    ** for more than one variable since
					    ** refresh is only useful when joins occur
					    */
                    )
		{
		    PTR save_fcb = rdfcb->rdf_rb.rdr_fcb;

		    /* Don't propagate this invalidate to other DBMS servers.
		    ** There's no reason to think that they are as out of
		    ** date as we are.  (plus this might be a session temp
		    ** which is strictly local!)
		    */

		    rdfcb->rdf_rb.rdr_fcb = NULL;
		    status = rdf_call( RDF_INVALIDATE, (PTR)rdfcb);
		    rdfcb->rdf_rb.rdr_fcb = save_fcb;
# ifdef E_OP008E_RDF_INVALIDATE
		    if (status != E_RD0000_OK)
			opx_verror( E_DB_ERROR, E_OP008E_RDF_INVALIDATE,
			    rdfcb->rdf_error.err_code);
# endif
		    status = rdf_call( RDF_GETDESC, (PTR)rdfcb);
		    grvp->opv_relation = rdfcb->rdf_info_blk; /* save ptr to
					    ** new info block */
		    if (status != E_RD0000_OK)
		    {
			gbase->opv_grv[gvar] = NULL;
			opx_verror( E_DB_ERROR, E_OP0004_RDF_GETDESC,
			    rdfcb->rdf_error.err_code);
		    }
		    timeptr = &grvp->opv_relation->rdr_rel->tbl_date_modified;
		    if (timeptr->db_tab_high_time != psftimeptr->db_tab_high_time
			||
			timeptr->db_tab_low_time != psftimeptr->db_tab_low_time
			)
			opx_vrecover( E_DB_ERROR, E_OP008F_RDF_MISMATCH,
			    rdfcb->rdf_error.err_code); /* PSF timestamp is
					    ** still out of date, so tell
                                            ** SCF to reparse the query */
		}
		{   /* search thru existing tables to discover if any
		    ** tables have the same table ID */
		    OPV_IGVARS	    gvno;
		    DB_TAB_ID	    *tabidp;
		    OPV_IGVARS	    target_vno;

		    tabidp = &global->ops_qheader->pst_rangetab[gvar]->pst_rngvar;
		    target_vno = OPV_NOGVAR;

		    for (gvno = 0; gvno < OPV_MAXVAR; gvno++)
		    {
			OPV_GRV	    *grv1p;
			grv1p = gbase->opv_grv[gvno];
			if (grv1p && grv1p->opv_relation)
			{
			    DB_TAB_ID   *gtabidp;

			    if (gvno == gvar)
				continue;
			    gtabidp = &grv1p->opv_relation->rdr_rel->tbl_id;
			    if ((tabidp->db_tab_base == gtabidp->db_tab_base)
				&&
				(tabidp->db_tab_index == gtabidp->db_tab_index)
				)
			    {	/* found 2 table ID's which are identical */
				global->ops_gmask |= OPS_IDSAME;
				if (target_vno == OPV_NOGVAR)
				{   /* map all table id's vars to the lowest
				    ** global range number of the group */
				    if (gvno > gvar)
					target_vno = gvar;
				    else
					target_vno = gvno;
				}
				grv1p->opv_same = target_vno;
				grvp->opv_same = target_vno;
				if (target_vno != gvar)
				    break;
			    }
			}
		    }
		}
	    }
	    if (global->ops_cb->ops_smask & OPS_MDISTRIBUTED)
		opd_addsite(global, grvp); /* add site information if a
					** distributed thread */
	    /* Check for partitioned table, turns on additional
	    ** analysis after enumeration.
	    */
	    if (grvp->opv_relation != NULL
	      && grvp->opv_relation->rdr_parts != NULL)
		global->ops_gmask |= OPS_PARTITION;
            if (grvp->opv_relation && grvp->opv_relation->rdr_rel->
                   tbl_2_status_mask & DMT_INCONSIST)
                                        /* check for inconsistent table
                                        ** (due to partial back/recov) */
            {
               OPT_NAME     tabname;
               i2           i;
               
               MEcopy(&grvp->opv_relation->rdr_rel->tbl_name, 
                         sizeof(grvp->opv_relation->rdr_rel->tbl_name),
                         &tabname);           /* table name is msg token */
               for (i = sizeof(grvp->opv_relation->rdr_rel->tbl_name);
                      i > 1 && tabname.buf[i-1] == ' '; i--);
               tabname.buf[i] = 0;            /* lop blanks off name */
	       opx_1perror(E_OP009A_INCONSISTENT_TAB,(PTR)&tabname);    
            }
        }
	else
	    grvp->opv_relation = NULL;          /* set to NULL if not used */
    }
    return(FALSE);
}
Exemplo n.º 23
0
/*{
** Name: psy_dbpriv - GRANT/REVOKE database privileges
**
**  INTERNAL PSF call format: status = psy_dbpriv(&psy_cb, sess_cb);
**  EXTERNAL     call format: status = psy_call (PSY_DBPRIV,&psy_cb, sess_cb);
**
** Description:
**	This procedure is sued to grant and revoke database privileges.
**	A template iidbpriv tuple is built and shipped to RDF.
**	Eventually, the tuple is added/merged into iidbpriv.
**	This procedure is called for SQL language only.
**
** Inputs:
**      psy_cb
**	    .psy_usrq			list of grantees
**	    .psy_tblq			list of objects
**	    .psy_gtype			grantee type
**	    .psy_grant			statement type (GRANT or REVOKE)
**	    .psy_fl_dbpriv		control flags
**	    .psy_qdio_limit		query I/O  limit
**	    .psy_qrow_limit		query row  limit
**	    .psy_qcpu_limit		query CPU  limit
**	    .psy_qpage_limit		query page limit
**	    .psy_qcost_limit		query cost limit
**	    .psy_idle_limit		idle time  limit
**	    .psy_connect_limit		connect time  limit
**	    .psy_priority_limit		priority   limit
**	sess_cb				Pointer to session control block
**					(Can be NULL)
**
** Outputs:
**      psy_cb
**	    .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_SEVERE			Function failed; catastrophic error
**	Exceptions:
**	    none
**
** Side Effects:
**	    None.
**
** History:
**	10-apr-89 (ralph)
**          written
**	06-jun-89 (ralph)
**	    corrected unix portability problems
**	24-jun-89 (ralph)
**	    corrected internal error message
**	06-sep-89 (ralph)
**	    added support for GRANT/REVOKE ON ALL DATABASES
**	    removed DBGR_DEFAULT
**	12-mar-90 (andre)
**	    set rdr_2types_mask to 0.
**      22-may-90 (teg)
**          init rdr_instr to RDF_NO_INSTR
**	19-jul-92 (andre)
**	    changes were made to enable a user to specify privileges to PUBLIC
**	    along with one or more user authorization identifiers
**	10-aug-93 (andre)
**	    fixed cause of a compiler warning
*/
DB_STATUS
psy_dbpriv(
	PSY_CB             *psy_cb,
	PSS_SESBLK	   *sess_cb)
{
    DB_STATUS		status = E_DB_OK;
    DB_STATUS		stat;
    i4		err_code;
    RDF_CB		rdf_cb;
    register RDR_RB	*rdf_rb = &rdf_cb.rdf_rb;
    DB_PRIVILEGES	dbprtuple;
    register DB_PRIVILEGES *dbprtup = &dbprtuple;
    PSY_USR		*psy_usr;
    PSY_TBL		*psy_tbl;
    bool		grant_to_public;
    bool		leave_loop = TRUE;
    
    /* This code is called for SQL only */

    do
    {
	/* Fill in the RDF request block */

	pst_rdfcb_init(&rdf_cb, sess_cb);
	if (psy_cb->psy_grant == PSY_DGRANT)
	    rdf_rb->rdr_update_op   = RDR_APPEND;
	else if (psy_cb->psy_grant == PSY_DREVOKE)
	    rdf_rb->rdr_update_op   = RDR_DELETE;
	else
	{
	    /* Invalid operation specified in psy_grant */
	    err_code = E_PS0D45_INVALID_GRANT_OP;
	    (VOID) psf_error(E_PS0D45_INVALID_GRANT_OP, 0L,
			     PSF_INTERR, &err_code, &psy_cb->psy_error, 0);
	    status   = E_DB_ERROR;
	    break;
	}
	rdf_rb->rdr_status	    = DB_SQL;
	rdf_rb->rdr_types_mask  = RDR_DBPRIV;
	rdf_rb->rdr_qrytuple    = (PTR) dbprtup;
	rdf_rb->rdr_qtuple_count = 1;

	/* Initialize the template iidbpriv tuple */

	dbprtup->dbpr_gtype	  = psy_cb->psy_gtype;
	dbprtup->dbpr_control	  = psy_cb->psy_ctl_dbpriv;
	dbprtup->dbpr_dbflags	  = 0;
	dbprtup->dbpr_flags	  = psy_cb->psy_fl_dbpriv;
	dbprtup->dbpr_qrow_limit  = psy_cb->psy_qrow_limit;
	dbprtup->dbpr_qdio_limit  = psy_cb->psy_qdio_limit;
	dbprtup->dbpr_qcpu_limit  = psy_cb->psy_qcpu_limit;
	dbprtup->dbpr_qpage_limit = psy_cb->psy_qpage_limit;
	dbprtup->dbpr_qcost_limit = psy_cb->psy_qcost_limit;
	dbprtup->dbpr_connect_time_limit = psy_cb->psy_connect_limit;
	dbprtup->dbpr_idle_time_limit    = psy_cb->psy_idle_limit;
	dbprtup->dbpr_priority_limit     = psy_cb->psy_priority_limit;

	MEfill(sizeof(dbprtup->dbpr_database), (u_char) ' ',
	    (PTR) &dbprtup->dbpr_database);

	MEfill(sizeof(dbprtup->dbpr_reserve), (u_char) ' ',
	    (PTR) dbprtup->dbpr_reserve);

	/* Point to first database object, if any */

	psy_tbl = (PSY_TBL *)psy_cb->psy_tblq.q_next;

	/* No database objects means GRANT/REVOKE ON ALL DATABASES */

	if (psy_tbl == (PSY_TBL *) &psy_cb->psy_tblq)
	    dbprtup->dbpr_dbflags |= DBPR_ALLDBS;

	/*
	** Pass the template tuples to RDF for each database/grantee.
	** RDF/QEF will return E_DB_INFO if a database/grantee is rejected,
	** or E_DB_WARN is a database is rejected.  Anything worse than
	** E_DB_WARN is a fatal error.
	*/

	/* Process each database/grantee */
	for (;;)
	{
	    /*
	    ** Copy in database name if one was provided.
	    ** None will be provided if ON ALL DATABASES was specified.
	    */
	    if (psy_tbl != (PSY_TBL *) &psy_cb->psy_tblq)
		MEcopy((PTR)&psy_tbl->psy_tabnm,
		       sizeof(dbprtup->dbpr_database),
		       (PTR)&dbprtup->dbpr_database);

	    grant_to_public = (psy_cb->psy_flags & PSY_PUBLIC) != 0;
	    psy_usr = (PSY_USR *)  psy_cb->psy_usrq.q_next;

	    do
	    {
		if (grant_to_public)
		{
		    /*
		    ** user specified TO/FROM PUBLIC, possibly along with other
		    ** user auth ids; we will process TO/FROM PUBLIC first
		    */
		    dbprtup->dbpr_gtype = DBGR_PUBLIC;
		    
		    MEmove(sizeof("public") - 1, (PTR) "public", ' ',
			sizeof(dbprtup->dbpr_gname),
			(PTR) &dbprtup->dbpr_gname);
		}
		else
		{
		    STRUCT_ASSIGN_MACRO(psy_usr->psy_usrnm,
			dbprtup->dbpr_gname);
		}
		
		stat = rdf_call(RDF_UPDATE, (PTR) &rdf_cb);
		status = (stat > status) ? stat : status;
		if (stat > E_DB_INFO)
		    break;

		if (grant_to_public)
		{
		    dbprtup->dbpr_gtype = psy_cb->psy_gtype;

		    /*
		    ** remember that we have processed GRANT TO PUBLIC on this
		    ** database or on the installation
		    */
		    grant_to_public = FALSE;
		}
		else
		{
		    psy_usr = (PSY_USR *) psy_usr->queue.q_next;
		}

	    } while (psy_usr != (PSY_USR *) &psy_cb->psy_usrq);

	    /* Break out if failure */
	    if (DB_FAILURE_MACRO(status))
		break;

	    /* Point to next database object */
	    psy_tbl = (PSY_TBL *)  psy_tbl->queue.q_next;

	    /* Break out if no more objects */
	    if (psy_tbl == (PSY_TBL *) &psy_cb->psy_tblq)
		break;
	}

	/* We are done */

	/* leave_loop has already been set to TRUE */
    } while (!leave_loop);

    if (DB_FAILURE_MACRO(status))
	(VOID) psf_rdf_error(RDF_UPDATE, &rdf_cb.rdf_error, 
			     &psy_cb->psy_error);

    return    (status);
}
Exemplo n.º 24
0
/*{
** Name: psy_kuser - Destroy profile
**
** Description:
**	This procedure deletes a profile.  If the
**	profile does not exist, the statement is aborted.
**	If the user does exist, the associated
**	iiprofile tuple is deleted.
**	This procedure is called for SQL language only.
**
** Inputs:
**      psy_cb
**	    .psy_usrq			user list
**	sess_cb				Pointer to session control block
**					(Can be NULL)
**
** Outputs:
**      psy_cb
**	    .psy_error			Filled in if error happens
**	Returns:
**	    E_DB_OK			Function completed normally.
**	    E_DB_INFO			Function completed with warning(s).
**	    E_DB_WARN			One ore more roles were rejected.
**	    E_DB_ERROR			Function failed; non-catastrophic error
**	Exceptions:
**	    none
**
** Side Effects:
**	    Removed tuples from iiuser.
**
** History:
**	27-aug-93 (robf)
**          written
*/
static DB_STATUS
psy_kprofile(
	PSY_CB             *psy_cb,
	PSS_SESBLK	   *sess_cb)
{
    DB_STATUS		status, stat;
    RDF_CB		rdf_cb;
    register RDR_RB	*rdf_rb = &rdf_cb.rdf_rb;
    DU_PROFILE		protuple;
    register DU_PROFILE	*protup = &protuple;
    PSY_USR		*psy_usr;

    FUNC_EXTERN DB_STATUS rdf_call();

    /* This code is called for SQL only */

    /*
    ** Fill in the part of RDF request block that will be constant.
    */
    pst_rdfcb_init(&rdf_cb, sess_cb);
    rdf_rb->rdr_update_op   = RDR_DELETE;
    rdf_rb->rdr_status	    = DB_SQL;
    rdf_rb->rdr_2types_mask = RDR2_PROFILE;
    rdf_rb->rdr_qrytuple    = (PTR) protup;
    rdf_rb->rdr_qtuple_count = 1;

    protup->du_status 	= 0;
    protup->du_flagsmask	= 0;
    /*
    ** Pass on RESTRICT/CASCADE processsing. RESTRICT is the default,
    */
    if (psy_cb->psy_usflag & PSY_USRCASCADE)
	protup->du_flagsmask|= DU_UCASCADE;


    MEfill(sizeof(protup->du_group),
	   (u_char)' ',
	   (PTR)&protup->du_group);

    status = E_DB_OK;

    for (psy_usr  = (PSY_USR *)  psy_cb->psy_usrq.q_next;
	 psy_usr != (PSY_USR *) &psy_cb->psy_usrq;
	 psy_usr  = (PSY_USR *)  psy_usr->queue.q_next
	)
    {
	/* STRUCT_ASSIGN_MACRO(psy_usr->psy_usrnm,
			       protup->du_name); */
	MEcopy((PTR)&psy_usr->psy_usrnm,
	       sizeof(protup->du_name),
	       (PTR)&protup->du_name);

	stat = rdf_call(RDF_UPDATE, (PTR) &rdf_cb);
	status = (stat > status) ? stat : status;

	if (DB_FAILURE_MACRO(stat))
	    break;
    }

    if (DB_FAILURE_MACRO(status))
	(VOID) psf_rdf_error(RDF_UPDATE, &rdf_cb.rdf_error, 
			     &psy_cb->psy_error);

    return    (status);
} 
Exemplo n.º 25
0
/*{
** Name: psy_integ	- Apply integrity constraints
**
** Description:
**      This function applies integrity constraints.  It gets the constraints
**	from RDF and puts them in the query where appropriate.
**
** Inputs:
**      mstream                         QSF memory stream to allocate from
**	root				Root of query tree to constrain
**	rngtab				Pointer to the range table
**	resvar				Pointer to the result range variable
**	qmode				Query mode of user's query
**	sess_cb				session control block
**	result				Place to put pointer to constrained tree
**	err_blk				Filled in if an error happens
**
** Outputs:
**      root                            Integrity constraints may be appended
**	result				Filled in with pointer to constrained
**					tree
**	err_blk				Filled in if an error happened
**	Returns:
**	    E_DB_OK			Success
**	    E_DB_ERROR			Failure
**	Exceptions:
**	    none
**
** Side Effects:
**	    Allocates memory
**
** History:
**	19-jun-86 (jeff)
**          Adapted from integrity.c in 4.0.
**      02-sep-86 (seputis)
**          changes for new RDF interface
**          fixed bug for no integrity case
**	04-dec-86 (daved)
**	    process define and replace cursor. Use copy of saved qual for
**	    replace cursor.
**	03-dec-87 (stec)
**	    Change psy_apql interface.
**	11-may-88 (stec)
**	    Make changes for db procs.
**	06-feb-89 (ralph)
**	    Modified to use DB_COL_WORDS*2 as extent of dset array
**	23-Feb-89 (andre)
**	    Changed the way the tree consisting of qualifications obtained from
**	    the integrity trees is constructed and merged with the
**	    qualifications found in the original tree.
**	18-may-89 (neil)
**	    Use session memory for cursors with integrities (bug fix).
**	12-mar-90 (andre)
**	    set rdr_2types_mask to 0.
**      22-may-90 (teg)
**          init rdr_instr to RDF_NO_INSTR
**	04-sep-90 (andre)
**	    fixed bug 32976: for OPEN CURSOR (qmode==PSQ_DEFCURS) we need to
**			     compare attribute number(s) found in the integrity
**			     tuple with attribute number found in the VAR
**			     node(s) found in the portion of the target list
**			     which was built to represent the FOR UPDATE list
**			     (such node(s) are right children of RESDOM nodes
**			     with pst_rsupdt set to TRUE; note that for
**			     RESDOM nodes built to represent the real target
**			     list of SELECT, this field is set to FALSE.)
**	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
**	05-dec-92 (rblumer)
**	    ignore FIPS constraints during INGRES integrity processing
**	10-jan-93 (andre)
**	    after calling rdf_call() for IIINTEGRITY tuples, compare status to
**	    E_DB_OK instead of using DB_FAILURE_MACRO() since if there are fewer
**	    than 20 rows, rdf_call() sets err_code to E_RD0011 and status to
**	    E_DB_WARN
**	10-Feb-93 (Teresa)
**	    Changed RDF_GETINFO to RDF_READTUPLES for new RDF I/F
**	23-May-1997 (shero03)
**	    Save the rdr_info_blk after an UNFIX
**	22-Jul-2004 (schka24)
**	    Delete old ifdef'ed out normalization call
**	28-nov-2007 (dougi)
**	    Add PSQ_REPDYN to PSQ_DEFCURS test (cached dynamic).
*/
DB_STATUS
psy_integ(
	PSF_MSTREAM	*mstream,
	PST_QNODE	*root,
	PSS_USRRANGE	*rngtab,
	PSS_RNGTAB	*resvar,
	i4		qmode,
	PSS_SESBLK	*sess_cb,
	PST_QNODE	**result,
	DB_ERROR	*err_blk)
{
    register PST_QNODE	*r;
    PSC_CURBLK		*curblk = sess_cb->pss_crsr;
    CS_SID		sessid  = sess_cb->pss_sessid;
    PTR			db_id   = sess_cb->pss_dbid;
    i2			dset[DB_COL_WORDS*2];
    i2			doms;
    i2			*domset;
    bool		subset;
    PST_QNODE		*p;
    register i4	i;
    PST_QNODE		*iqual;
    PST_QNODE		**tmp1;
    DB_INTEGRITY	*inttup;
    i4		err_code;
    PST_QTREE		*qtree;
    PST_PROCEDURE	*pnode;
    DB_STATUS		status = E_DB_OK;
    i4			found;
    RDF_CB		rdf_cb;
    QEF_DATA		*qp;
    RDF_CB		rdf_tree_cb;
    PSS_DUPRB		dup_rb;
    i4			tupcount;
    i4			map[PST_NUMVARS];   /* Map for reassigning varnos */

    r = root;

    /* Initialize fields in dup_rb */
    dup_rb.pss_op_mask = 0;
    dup_rb.pss_num_joins = PST_NOJOIN;
    dup_rb.pss_tree_info = (i4 *) NULL;
    dup_rb.pss_mstream = mstream;
    dup_rb.pss_err_blk = err_blk;

    if (qmode == PSQ_REPCURS)
    {
	if (!curblk->psc_integ)
	{
	    *result = r;
	    return (E_DB_OK);
	}
	/*
	** On a replace cursor, get the query tree that was stored in the
	** cursor control block.
	*/
	/* copy the qual fragment so we can change below. */
	dup_rb.pss_tree = curblk->psc_integ;
	dup_rb.pss_dup  = &iqual;
	status = pst_treedup(sess_cb, &dup_rb);
	
	if (DB_FAILURE_MACRO(status))
	{
	    return (status);
	}
    }
    else
    {
	/*
	**  Check to see if we should apply the integrity
	**  algorithm.
	**
	**  This means checking to insure that we have an update
	**  and seeing if any integrity constraints apply.
	*/
	if 
	(
	    resvar == 0 || 
	    (resvar->pss_tabdesc->tbl_status_mask & DMT_INTEGRITIES) == 0
	)
	{
	    *result = r;
	    return (E_DB_OK);
	}
	/*
	**  Create a set of the domains updated in this query.
	*/

	for (i = 0; i < DB_COL_WORDS*2; i++)
	    dset[i] = 0;

	for (p = r->pst_left, doms = 0;
	    p != (PST_QNODE *) NULL && p->pst_sym.pst_type != PST_TREE;
	    p = p->pst_left)
	{
	    if (p->pst_sym.pst_type != PST_RESDOM)
	    {
		psf_error(E_PS0D0C_NOT_RESDOM, 0L, PSF_INTERR, &err_code,
		    err_blk, 0);
		return (E_DB_SEVERE);
	    }

	    /*
	    ** if we are defining a cursor, RESDOM numbers are meaningless as
	    ** at best they reflect position of an attribute in the target list
	    ** of a subselect or, at worst, they are set to 1 for all columns
	    ** mentioned in the FOR UPDATE LIST.  We really are interested only
	    ** in the VAR nodes which are children of RESDOM nodes built to
	    ** repersent columns appearing in the FOR UPDATE list, so we will
	    ** skip over RESDOM nodes which represent a true subselect
	    ** (i.e. pst_rsupdt == FALSE)
	    */
	    if (qmode == PSQ_DEFCURS)
	    {
		if (p->pst_sym.pst_value.pst_s_rsdm.pst_rsupdt)
		{
		    PST_QNODE	    *r_child = p->pst_right;

		    /*
		    ** this RESDOM was built to represent the column in the FOR
		    ** UPDATE list
		    */

		    /*
		    ** make sure the right child is a VAR node; otherwise flag
		    ** an error
		    */
		    if (r_child == (PST_QNODE *) NULL ||
		        r_child->pst_sym.pst_type != PST_VAR)
		    {
			psf_error(E_PS0C04_BAD_TREE, 0L, PSF_INTERR, &err_code,
			    err_blk, 0);
			return (E_DB_SEVERE);
		    }
		    
		    BTset((i4) r_child->
				 pst_sym.pst_value.pst_s_var.pst_atno.db_att_id,
			  (char *) dset);
		    ++doms;
		}
	    }
	    else
	    {
		BTset((i4) p->pst_sym.pst_value.pst_s_rsdm.pst_rsno,
		    (char *) dset);
		++doms;
	    }
	}

	/*
	** Note if we are appending a subset of the relation's domains.
	** If we are, we'll need to be extra careful to avoid violating
	** constraints on those attributes not being explicitly appended:
	*/
	subset = ((doms < resvar->pss_tabdesc->tbl_attr_count)
	    && (qmode == PSQ_APPEND));

	
	/*
	**  Scan integrity catalog for possible tuples.  If found,
	**  include them in the integrity qualification.
	*/

	iqual = (PST_QNODE *) NULL;

        /* Set up constant part of rdf query tree control block */
	pst_rdfcb_init(&rdf_tree_cb, sess_cb);
        STRUCT_ASSIGN_MACRO(resvar->pss_tabid, rdf_tree_cb.rdf_rb.rdr_tabid);
        rdf_tree_cb.rdf_rb.rdr_types_mask = RDR_INTEGRITIES | RDR_QTREE;
	rdf_tree_cb.rdf_rb.rdr_qtuple_count = 1;  
		/* Get 1 integ tree at a time */
	rdf_tree_cb.rdf_info_blk = resvar->pss_rdrinfo;

	/* Get all integrity tuples */
	pst_rdfcb_init(&rdf_cb, sess_cb);
	STRUCT_ASSIGN_MACRO(resvar->pss_tabid, rdf_cb.rdf_rb.rdr_tabid);
	rdf_cb.rdf_rb.rdr_types_mask = RDR_INTEGRITIES;
	rdf_cb.rdf_rb.rdr_update_op = RDR_OPEN;
	rdf_cb.rdf_rb.rdr_rec_access_id = NULL;
	rdf_cb.rdf_rb.rdr_qtuple_count = 20;  /* Get 20 integrities at a time */
	rdf_cb.rdf_info_blk = resvar->pss_rdrinfo;
	/* For each group of 20 integrities */
	while (rdf_cb.rdf_error.err_code == 0)
	{
	  status = rdf_call(RDF_READTUPLES, (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
          */
	  if (rdf_cb.rdf_info_blk != resvar->pss_rdrinfo)
	  {
	    resvar->pss_rdrinfo =
		rdf_tree_cb.rdf_info_blk = rdf_cb.rdf_info_blk;
	  }
	  
	  /*
	  ** Must not use DB_FAILURE_MACRO because E_RD0011 returns E_DB_WARN
	  ** that would be missed.
	  */
	  if (status != E_DB_OK)
	  {
	    if (   rdf_cb.rdf_error.err_code == E_RD0011_NO_MORE_ROWS
		|| rdf_cb.rdf_error.err_code == E_RD0013_NO_TUPLE_FOUND)
	    {
		status = E_DB_OK;
		if (rdf_cb.rdf_error.err_code == E_RD0013_NO_TUPLE_FOUND)
		    continue;
	    }
	    else if (rdf_cb.rdf_error.err_code == E_RD0002_UNKNOWN_TBL)
	    {
		(VOID) psf_error(2117L, 0L, PSF_USERERR,
		    &err_code, err_blk, 1,
		    psf_trmwhite(sizeof(DB_TAB_NAME), 
			(char *) &resvar->pss_tabname),
		    &resvar->pss_tabname);
		status = E_DB_ERROR;
		goto exit;
	    }
	    else
	    {
		(VOID) psf_rdf_error(RDF_READTUPLES, &rdf_cb.rdf_error, err_blk);
		goto exit;
	    }
	  }

	  rdf_cb.rdf_rb.rdr_update_op = RDR_GETNEXT;
    
	  /* FOR EACH INTEGRITY */
	  for 
	  (
	    qp = rdf_cb.rdf_info_blk->rdr_ituples->qrym_data,
	    tupcount = 0;
	    tupcount < rdf_cb.rdf_info_blk->rdr_ituples->qrym_cnt;
	    qp = qp->dt_next,
	    tupcount++
	  )
	  {
	    inttup = (DB_INTEGRITY*) qp->dt_data;

	    /*
	    ** Ignore FIPS constraints (i.e. SQL92 constraints)
	    ** (they are implemented via rules instead)
	    */
	    if (inttup->dbi_consflags != 0)
	    {
		continue;
	    }

	    /* check for some domain set overlap */

	    domset = (i2*) inttup->dbi_columns.db_domset;

	    for (i = 0; i < DB_COL_WORDS*2; i++)
	    {
		if ((dset[i] & domset[i]) != 0)
		    break;
	    }

	    /*
	    ** Check for appends where defaults don't satisfy integrity.
	    */

	    if ((i >= DB_COL_WORDS*2) && !subset)
	    {
		continue;
	    }

	    /* Get integrity tree and make qtree point to it */
	STRUCT_ASSIGN_MACRO(inttup->dbi_tree, rdf_tree_cb.rdf_rb.rdr_tree_id);
	    rdf_tree_cb.rdf_rb.rdr_qrymod_id = inttup->dbi_number;
	    rdf_tree_cb.rdf_rb.rdr_update_op = 0;
	    rdf_tree_cb.rdf_rb.rdr_rec_access_id = NULL;
	    rdf_tree_cb.rdf_info_blk = resvar->pss_rdrinfo;
	    rdf_tree_cb.rdf_rb.rdr_integrity = NULL;
	    STRUCT_ASSIGN_MACRO(inttup->dbi_tabid,
				rdf_tree_cb.rdf_rb.rdr_tabid);
	    rdf_tree_cb.rdf_rb.rdr_sequence = inttup->dbi_number;

	    status = rdf_call(RDF_GETINFO, (PTR) &rdf_tree_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
	    */
	    if (rdf_tree_cb.rdf_info_blk != resvar->pss_rdrinfo)
	    {
		resvar->pss_rdrinfo =
		    rdf_cb.rdf_info_blk = rdf_tree_cb.rdf_info_blk;
	    }

	    if (DB_FAILURE_MACRO(status))
	    {
		if (rdf_tree_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(DB_TAB_NAME), 
			    (char *) &resvar->pss_tabname),
			&resvar->pss_tabname);
		}
		else
		{
		    (VOID) psf_rdf_error(RDF_GETINFO, &rdf_tree_cb.rdf_error,
			err_blk);
		}
		goto exit;
	    }
	    pnode   = 
	    (PST_PROCEDURE *) rdf_tree_cb.rdf_rb.rdr_integrity->qry_root_node;
	    qtree = pnode->pst_stmts->pst_specific.pst_tree;
		
	    /* trim off (null) target list */
	    p = qtree->pst_qtree->pst_right;
	    /* use a copy of the qtree because the qtree is in RDF memory */
	    dup_rb.pss_tree = qtree->pst_qtree->pst_right;
	    dup_rb.pss_dup  = &p;
	    status = pst_treedup(sess_cb, &dup_rb);

	    {	/* unfix the query tree no matter what the above status is */
		DB_STATUS	temp_status;

		temp_status = rdf_call(RDF_UNFIX, (PTR) &rdf_tree_cb);
	        resvar->pss_rdrinfo = 
			rdf_cb.rdf_info_blk = rdf_tree_cb.rdf_info_blk;
		if (DB_FAILURE_MACRO(temp_status))
		{
		    (VOID) psf_rdf_error(RDF_UNFIX, &rdf_tree_cb.rdf_error,
			err_blk);
		    status = temp_status;
		}
	    }
	    if (DB_FAILURE_MACRO(status))
		goto exit;		/* close integrity file */

	    /*
	    ** Make the result variable for the integrity the same as the result
	    ** variable for the user query.  
	    ** I AM NOT SURE THE FOLLOWING COMMENT APPLIES SO I AM MERGING
	    ** THE RANGE VAR FOR APPENDS.
	    ** This is not done for append because
	    ** append doesn't have a result range variable.
	    */
	    for (i = 0; i < PST_NUMVARS; i++)
		map[i] = i;
	    i = inttup->dbi_resvar;

	    map[i] = resvar->pss_rgno;
	    status = psy_mapvars(p, map, err_blk);
	    if (DB_FAILURE_MACRO(status))
		goto exit;

	    /* add to integrity qual */

	    if (iqual == NULL)
	    {
		status = pst_node(sess_cb, mstream, p, (PST_QNODE *) NULL,
		    PST_AND, (PTR) NULL, sizeof(PST_OP_NODE), DB_NODT, (i2) 0,
		    (i4) 0, (DB_ANYTYPE *) NULL, &iqual, err_blk, (i4) 0);

		if (DB_FAILURE_MACRO(status))
		    goto exit;		/* close integrity file */

		/*
		** Note that tmp1 will contain address of the pst_right ptr
		** of the bottom AND node in the tree constructed from the
		** qualifications found in the integrities
		*/

		tmp1 = &iqual->pst_right;
	    }
	    else
	    {
		PST_QNODE	*newnode;
		
		status = pst_node(sess_cb, mstream, p, iqual, PST_AND,
		    (PTR) NULL, sizeof(PST_OP_NODE), DB_NODT, (i2) 0, (i4) 0,
		    (DB_ANYTYPE *) NULL, &newnode, err_blk, (i4) 0);

		if (DB_FAILURE_MACRO(status))
		    goto exit;		/* close integrity file */

		iqual = newnode;
	    }
	  }
	}
	if (rdf_cb.rdf_rb.rdr_rec_access_id != NULL)
	{
	    DB_STATUS	temp_status;
	    /* unfix integrity tuples */
	    rdf_cb.rdf_rb.rdr_update_op = RDR_CLOSE;
	    temp_status = rdf_call(RDF_READTUPLES, (PTR) &rdf_cb);
	    resvar->pss_rdrinfo =
		rdf_tree_cb.rdf_info_blk = rdf_cb.rdf_info_blk;
	    if (DB_FAILURE_MACRO(temp_status))
	    {
		(VOID) psf_rdf_error(RDF_READTUPLES, &rdf_cb.rdf_error, err_blk);
		status = temp_status;
	    }
	}
    }

    if (qmode == PSQ_DEFCURS || qmode == PSQ_REPDYN)
    {
        /*
        ** On a "define cursor", keep a copy of the integrity qualification
        ** for later use.
        */
        if (iqual == NULL)
        {
	    curblk->psc_integ = (PST_QNODE *) NULL;
        }
        else
        {
	    status = pst_trdup(curblk->psc_stream, iqual,
		&curblk->psc_integ, &sess_cb->pss_memleft, err_blk);
	    if (DB_FAILURE_MACRO(status))
	    {
		return (status);
	    }
	}
    }
    else
    {   
	/*
	**  Clean up the integrity qualification so that it will merge
	**  nicely into the tree, and then append it to the user's
	**  qualification.
	*/

	if (iqual != NULL)
	{
	    /* replace VAR nodes by corresponding user afcn from user's
	    ** query. For example, if the integ says r.a > 1 and the user's
	    ** query says resdom 4 = 4 + 3, the integ is modified to 4 + 3 > 1.
	    **
	    ** The following paragraph refers to the case where an integrity
	    ** refers to a variable not updated in the target list.
	    **
	    ** If there is no resdom for r.a, if the user didn't specify r.a
	    ** in the target list of the query, and the query is an append,
	    ** r.a > 1 is replaced with 'default val for col a' > 1. If the
	    ** query is a replace statement, we do nothing because r.a will
	    ** be retrieved but is not in the targ list. We will be verifying
	    ** what we know should already hold (ie the integrity constraint).
	    ** If we have replace cursor, we wan't to replace r.a with a value
	    ** so a retrieve can be avoided on the replace command. We can't
	    ** have col a = 5 where r.a > 1. We do, however, have the value r.a
	    ** in the row to be updated. QEF has this value. We replace r.a with
	    ** a curval node that refers to the value r.a.
	    */

	    /* will pass dup_rb, but first null out pss_tree and pss_dup */
	    dup_rb.pss_tree = (PST_QNODE *) NULL;
	    dup_rb.pss_dup  = (PST_QNODE **) NULL;
	    
	    status = psy_subsvars(sess_cb, &iqual, resvar, r->pst_left, qmode,
		(PST_QNODE *) NULL, resvar, (i4) 0, qmode,
		&curblk->psc_blkid, &found, &dup_rb);

	    if (DB_FAILURE_MACRO(status))
	    {
		return (status);
	    }

	    /*
	    ** for REPLACE CURSOR, we need to traverse down the pst_right's
	    ** until we encounter NULL in place of which we will append the
	    ** qualification from the ROOT
	    ** Note that iqual is guaranteed to be an AND node with BOP for a
	    ** left child and either AND or NULL for the right child.
	    */

	    if (qmode == PSQ_REPCURS)
	    {
		for (tmp1 = &iqual->pst_right; (*tmp1) != (PST_QNODE *) NULL;
		     tmp1 = &(*tmp1)->pst_right)
		;
	    }
	    
	    /*
	    ** append qualification from the tree to the integrities and
	    ** make the result the new qualification for the tree
	    */
	    (*tmp1) = r->pst_right;
	    r->pst_right = iqual; 
	}
    }

exit:
    if ((qmode != PSQ_REPCURS)
	&&
	(rdf_cb.rdf_rb.rdr_rec_access_id != NULL))
    {
	DB_STATUS	temp_status;
	/* unfix integrity tuples */
	rdf_cb.rdf_rb.rdr_update_op = RDR_CLOSE;
	temp_status = rdf_call(RDF_READTUPLES, (PTR) &rdf_cb);
	resvar->pss_rdrinfo =
	    rdf_tree_cb.rdf_info_blk = rdf_cb.rdf_info_blk;
	if (DB_FAILURE_MACRO(temp_status))
	{
	    (VOID) psf_rdf_error(RDF_READTUPLES, &rdf_cb.rdf_error, err_blk);
	    status = temp_status;
	}
    }
    if (status == E_DB_OK)
    {
	*result = r;
    }
    return (status);
}
Exemplo n.º 26
0
/*{
** Name: psy_gsequence	- Get description of a sequence from RDF.
**
** Description:
** 	This routine calls RDF to return the iisequence tuple for a sequence,
**	then moves certain columns into the PSS_SEQINFO structure for its caller.
**	It is used by psl to verify the existence of a sequence referenced in 
**	a sequence operation (next/current value) and return definition information.
**
** Inputs:
**	sess_cb				Pointer to session control block.
**	    .pss_user			User/owner of the event.
**	seq_own				Sequence owner (from syntax).
**	seq_name			Sequence name (from syntax).
**	seq_mask			flag field
**	    PSS_USRSEQ	    search for sequence owned by the current user
**	    PSS_DBASEQ	    search for sequence owned by the DBA
**				    (must not be set unless 
**				    (seq_mask & PSS_USRSEQ))
**	    PSS_INGSEQ	    search for sequence owned by $ingres
**                                  (must not be set unless
**                                  (seq_mask & PSS_USRSEQ))
**	    PSS_SEQ_BY_OWNER	    search for sequence owned by the specified 
**				    owner
**	    PSS_SEQ_BY_ID	    search for sequence by id
**		NOTE:		    PSS_USRSEQ <==> !PSS_SEQ_BY_OWNER
**				    PSS_SEQ_BY_ID ==> !PSS_SEQ_BY_OWNER
**				    PSS_SEQ_BY_ID ==> !PSS_USRSEQ
**	privs				Pointer to privilege bit map (if we're to
**					check privileges on this sequence) or NULL.
**	qmode				Query mode (for errors).
**	grant_all			Flag indicating GRANT ALL accompanied request.
**
** Outputs:
**	seq_info			Pointer to sequence information block
**	    .pss_seqname		Sequence name.
**	    .pss_owner			Sequence owner.
**	    .pss_seqid			Internal sequence ID.
**	    .pss_dt			Sequence value datatype.
**	    .pss_length			Sequence value length.
**	    .pss_secid			Sequence security ID.
**      err_blk
**	    .err_code			Filled in if an error happens:
**		E_US1914_SEQ_NOT_FOUND	  Cannot find sequence definition.
**		Generally, the error codes returned by RDF and QEU
**		qrymod processing routines are passed back to the caller
**		except where they are user errors (eg, sequence doesn't exist).
**
**	Returns:
**	    E_DB_OK, E_DB_WARN, E_DB_ERROR, E_DB_FATAL
**	Exceptions:
**	    none
**
** Side Effects:
**	none
**
** History:
**	18-mar-02 (inkdo01)
**	    Cloned from psy_gevent for sequence support.
**	21-feb-03 (inkdo01)
**	    Add seq_mask to control iisequence retrieval.
**	24-apr-03 (inkdo01)
**	    Reset IISEQUENCE ptr for secondary calls to RDF.
**	24-apr-03 (inkdo01)
**	    Fix "not found" message for "drop sequence".
**      09-Mar-2010 (coomi01) b123351
**          Block users from dropping dba sequences.
**      29-Apr-2010 (coomi01) b123638
**          Backout the above change, then put in a test
**          to prevent delete dba's sequence by non dba.  
**          This allows non-dba to find sequence for 
**          updating.
**	15-Oct-2010 (kschendel) SIR 124544
**	    Update psl-command-string call.
*/
DB_STATUS
psy_gsequence(
	PSS_SESBLK      *sess_cb,
	DB_OWN_NAME	*seq_own,
	DB_NAME		*seq_name,
	i4		seq_mask,
	PSS_SEQINFO	*seq_info,
	DB_IISEQUENCE	*seqp,
	i4		*ret_flags,
	i4		*privs,
	i4		qmode,
	i4		grant_all,
	DB_ERROR	*err_blk)
{
    DB_STATUS		status;
    RDF_CB		rdf_seq;	/* RDF for sequence */
    DB_IISEQUENCE	seqtuple;	/* sequence tuple to retrieve into */
    i4		err_code;
    bool	leave_loop = TRUE;

    *ret_flags = 0;

    /* First retrieve sequence tuple from RDF */
    if (seqp == NULL)
	seqp = &seqtuple;

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

    /* init relevant elements */
    {
	rdf_seq.rdf_rb.rdr_types_mask = RDR_BY_NAME;
	rdf_seq.rdf_rb.rdr_2types_mask = RDR2_SEQUENCE;
	MEmove(sizeof(DB_NAME), (PTR) seq_name, ' ',
	    sizeof(DB_NAME), (PTR) &rdf_seq.rdf_rb.rdr_name.rdr_seqname);
	STRUCT_ASSIGN_MACRO((*seq_own), rdf_seq.rdf_rb.rdr_owner);
    }
    
    rdf_seq.rdf_rb.rdr_update_op = RDR_OPEN;
    rdf_seq.rdf_rb.rdr_qtuple_count = 1;
    rdf_seq.rdf_rb.rdr_qrytuple = (PTR) seqp;

    do     		/* something to break out of */
    {
	status = rdf_call(RDF_GETINFO, (PTR) &rdf_seq);

	/*
	** if caller specified sequence owner name, or
	**    the sequence was found, or
	**    an error other than "sequence not found" was encountered,
	**  bail out
	*/
	if (   seq_mask & PSS_SEQ_BY_OWNER
	    || status == E_DB_OK
	    || rdf_seq.rdf_error.err_code != E_RD0013_NO_TUPLE_FOUND
	   )
	    break;

	/*
	** if sequence was not found, and
	**    - caller requested that DBA's sequences be considered, and
	**    - user is not the DBA,
	**    - check we are not attempting to destroy the sequence.
	** check if the sequence is owned by the DBA
	*/
	if ((qmode != PSQ_DSEQUENCE) &&
	       seq_mask & PSS_DBASEQ
	    && MEcmp((PTR) &sess_cb->pss_dba.db_tab_own, 
		   (PTR) &sess_cb->pss_user, sizeof(DB_OWN_NAME))
	   )
	{
	    STRUCT_ASSIGN_MACRO(sess_cb->pss_dba.db_tab_own,
				rdf_seq.rdf_rb.rdr_owner);
	    rdf_seq.rdf_rb.rdr_qtuple_count = 1;
	    rdf_seq.rdf_rb.rdr_qrytuple = (PTR) &seqtuple;
	    status = rdf_call(RDF_GETINFO, (PTR) &rdf_seq);
	    if (status == E_DB_OK)
		STRUCT_ASSIGN_MACRO(seqtuple, *seqp);
	}

	/*
	** if still not found, and
	**   - caller requested that sequences owned by $ingres be considered, and
	**   - user is not $ingres and
	**   - DBA is not $ingres,
	** check if the sequence is owned by $ingres
	*/
	if (   status != E_DB_OK
	    && rdf_seq.rdf_error.err_code == E_RD0013_NO_TUPLE_FOUND
	    && seq_mask & PSS_INGSEQ
	   )
	{
	    if (   MEcmp((PTR) &sess_cb->pss_user,
			 (PTR) sess_cb->pss_cat_owner,
			 sizeof(DB_OWN_NAME)) 
		&& MEcmp((PTR) &sess_cb->pss_dba.db_tab_own,
			 (PTR) sess_cb->pss_cat_owner,
			 sizeof(DB_OWN_NAME))
	       )
	    {
		STRUCT_ASSIGN_MACRO((*sess_cb->pss_cat_owner),
				    rdf_seq.rdf_rb.rdr_owner);
		rdf_seq.rdf_rb.rdr_qtuple_count = 1;
		rdf_seq.rdf_rb.rdr_qrytuple = (PTR) &seqtuple;
		status = rdf_call(RDF_GETINFO, (PTR) &rdf_seq);
		if (status == E_DB_OK)
		    STRUCT_ASSIGN_MACRO(seqtuple, *seqp);
	    }
	}

	/* leave_loop has already been set to TRUE */
    } while (!leave_loop);

    if (status != E_DB_OK)
    {
	if (rdf_seq.rdf_error.err_code == E_RD0013_NO_TUPLE_FOUND)
	{
	    if (qmode == PSQ_ASEQUENCE || qmode == PSQ_DSEQUENCE)
	    {
		_VOID_ psf_error(6419L, 0L,
		    PSF_USERERR, &err_code, err_blk, 1,
		    psf_trmwhite(sizeof(*seq_name), 
		    (PTR)seq_name), (PTR)seq_name);
	    }
	    else /* must be DML currval/nextval request */
	    {
		char        qry[PSL_MAX_COMM_STRING];
		i4     qry_len;

		psl_command_string(qmode, sess_cb, qry, &qry_len);
		_VOID_ psf_error(6420L, 0L,
		    PSF_USERERR, &err_code, err_blk, 2,
		    qry_len, qry,
		    psf_trmwhite(sizeof(*seq_name), (char *) seq_name),
		    (PTR) seq_name);
	    }
	    if (sess_cb->pss_dbp_flags & PSS_DBPROC)
		sess_cb->pss_dbp_flags |= PSS_MISSING_OBJ;

	    *ret_flags |= PSS_MISSING_SEQUENCE;
	    status = E_DB_OK;
	}
	else /* some other error */
	{
	    _VOID_ psf_rdf_error(RDF_GETINFO, &rdf_seq.rdf_error, err_blk);
	}

	return (status);
    } /* If RDF did not return the sequence tuple */

    STRUCT_ASSIGN_MACRO(rdf_seq.rdf_rb.rdr_owner, (*seq_own));
					/* copy back successful owner */

    if (seq_info != NULL)
    {
	/* fill in a sequence descriptor */
	STRUCT_ASSIGN_MACRO(seqp->dbs_name, seq_info->pss_seqname);
	STRUCT_ASSIGN_MACRO(seqp->dbs_owner, seq_info->pss_seqown);
	STRUCT_ASSIGN_MACRO(seqp->dbs_uniqueid, seq_info->pss_seqid);
	seq_info->pss_dt = seqp->dbs_type;
	seq_info->pss_length = seqp->dbs_length;
	seq_info->pss_prec = seqp->dbs_prec;
    }

    /*
    ** if we are parsing a dbproc and the sequence which we have just looked up
    ** is owned by the dbproc's owner, we will add the sequence to the dbproc's
    ** independent object list unless it has already been added.
    ** Note that only sequences owned by the current user will be included into
    ** the list of independent objects.
    **
    ** NOTE: we do not build independent object list for system-generated
    **	     dbprocs
    */
    if (   sess_cb->pss_dbp_flags & PSS_DBPROC
	&& ~sess_cb->pss_dbp_flags & PSS_SYSTEM_GENERATED
        && !MEcmp((PTR) &sess_cb->pss_user, (PTR) &seqp->dbs_owner,
		  sizeof(sess_cb->pss_user))
       )
    {
	status = pst_add_1indepobj(sess_cb, &seqp->dbs_uniqueid,
	    PSQ_OBJTYPE_IS_SEQUENCE, (DB_DBP_NAME *) NULL,
	    &sess_cb->pss_indep_objs.psq_objs, sess_cb->pss_dependencies_stream,
	    err_blk);

	if (DB_FAILURE_MACRO(status))
	{
	    return(status);
	}
    }
		  
    if (privs && *privs)
    {
	i4	    privs_to_find = *privs;

	status = psy_seqperm(&rdf_seq, &privs_to_find, sess_cb, seq_info, qmode,
	    grant_all, err_blk);
	if (DB_FAILURE_MACRO(status))
	{
	    return (status);
	}
	else if (privs_to_find)
	{
	    if (grant_all && *privs != privs_to_find)
	    {
		/*
		** if we are processing GRANT ALL and psy_seqperm() has
		** determined that the user may grant some but not all
		** privileges on the sequence, reset the privilege map
		** accordingly
		*/
		*privs &= ~(privs_to_find & ~((i4) DB_GRANT_OPTION));
	    }
	    else
	    {
		*ret_flags |= PSS_INSUF_SEQ_PRIVS;
		return(E_DB_OK);
	    }
	} /* If no permission */
    }

    return(E_DB_OK);

}
Exemplo n.º 27
0
/*{
** Name: psy_seqperm	- Check if the user/group/role has sequence permission.
**
** Description:
**	This routine retrieves all protection tuples applicable to a given
**	sequence until it establishes that the user posesses all privileges
**	specified in *privs (SUCCESS) or until there are no more left (FAILURE).
**	(The only privilege defined on sequences is NEXT - like SELECT)
**
**	The routine assumes that if the current user is the same as the sequence
**	owner, then no 	privileges need be checked.
**	
** Inputs:
**	rdf_cb				RDF CB that was used to extract the
**					original sequence.  Note that the RDF
**					operation type masks will be modified
**					in this routine
**					(rdr_types_mask will be set to
**					RDR_PROTECT|RDR2_SEQUENCE)
**	privs				ptr to a map of privileges to verify
**	    DB_NEXT			user must posess NEXT on sequence
**	    DB_GRANT_OPTION		privilege(s) must be grantable
**	sess_cb				Session CB with various values plus:
**	    .pss_user			User name.
**	    .pss_group			Group name.
**	    .pss_aplid			Application/role name.
**      seq_info			sequence descriptor
**	qmode				mode of the query
**	grant_all			TRUE if processing GRANT ALL;
**					FALSE otherwise
**
** Outputs:
**	privs				if non-zero, indicates which privileges
**					the user does not posess
**	err_blk.err_code		Filled in if an error happened:
**					  errors from RDF & other PSF utilities
**	Returns:
**	    E_DB_OK			Success
**	    E_DB_ERROR			Failure
**	Exceptions:
**	    none
**	
** Side Effects:
**	1. Via RDF will also access iiprotect.
**
** History:
**	3-may-02 (inkdo01)
**	    Written for sequence support (cloned from psy_evperm).
**	24-apr-03 (inkdo01)
**	    Corrected "missing privilege" message.
*/
DB_STATUS
psy_seqperm(
	RDF_CB		*rdf_cb,
	i4		*privs,
	PSS_SESBLK      *sess_cb,
	PSS_SEQINFO	*seq_info,
	i4		qmode,
	i4		grant_all,
	DB_ERROR	*err_blk)
{
    RDR_RB	    	*rdf_rb = &rdf_cb->rdf_rb;	/* RDR request block */
#define	PSY_RDF_SEQ	5
    DB_PROTECTION	seqprots[PSY_RDF_SEQ];	/* Set of returned tuples */
    DB_PROTECTION   	*protup;	/* Single tuple within set */
    i4		     	tupcount;	/* Number of tuples in scan */
    DB_STATUS	     	status;
    i4			save_privs = *privs, privs_wgo = (i4) 0;
    PSQ_OBJPRIV         *seqpriv_element = (PSQ_OBJPRIV *) NULL;

				/* 
				** will be used to remember whether the 
				** <auth id> attempting to grant privilege(s)
				** him/herself possesses any privilege on the 
				** object; 
				** will start off pessimistic, but may be reset 
				** to TRUE if we find at least one permit 
				** granting ANY privilege to <auth id> 
				** attempting to grant the privilege or to 
				** PUBLIC
				*/
    bool		cant_access = TRUE;

    status = E_DB_OK;

    if (!MEcmp((PTR) &sess_cb->pss_user,
	    (PTR) &seq_info->pss_seqown, sizeof(sess_cb->pss_user))
       )
    {
	/* owner of the sequence posesses all privileges on it */
	*privs = (i4) 0;
    }

    if (!*privs)
    {
	/* no privileges to check or the sequence is owned by the current user */
	return(E_DB_OK);
    }

    /*
    ** rdr_rec_access_id must be set before we try to scan a privilege list
    ** since under some circumstances we may skip all the way to saw_the_perms:
    ** and seqperm_exit, and code under seqperm_exit: relies on rdr_rec_access_id
    ** being set to NULL as indication that the tuple stream has not been opened
    */
    rdf_rb->rdr_rec_access_id  = NULL;    

    /*
    ** if processing CREATE PROCEDURE, before scanning IIPROTECT to check if the
    ** user has the required privileges on the sequence, check if some of the
    ** privileges have already been checked.
    */
    if (sess_cb->pss_dbp_flags & PSS_DBPROC)
    {
	bool			missing;

	status = psy_check_objprivs(sess_cb, privs, &seqpriv_element,
	    &sess_cb->pss_indep_objs.psq_objprivs, &missing,
	    &seq_info->pss_seqid, sess_cb->pss_dependencies_stream,
	    PSQ_OBJTYPE_IS_SEQUENCE, err_blk);
	if (DB_FAILURE_MACRO(status))
	{
	    return(status);
	}
	else if (missing)
	{
	    if (sess_cb->pss_dbp_flags & PSS_DBPGRANT_OK)
	    {
		/* dbproc is clearly ungrantable now */
		sess_cb->pss_dbp_flags &= ~PSS_DBPGRANT_OK;
	    }

	    if (sess_cb->pss_dbp_flags & PSS_0DBPGRANT_CHECK)
	    {
		/*
		** if we determine that a user lacks some privilege(s) by
		** scanning IIPROTECT, code under saw_the_perms expects
		** priv to contain a map of privileges which could not be
		** satisfied;
		** if parsing a dbproc to determine its grantability, required
		** privileges must be all grantable (so we OR DB_GRANT_OPTION
		** into *privs);
		** strictly speaking, it is unnecessary to OR DB_GRANT_OPTION
		** into *privs, but I prefer to ensure that saw_the_perms: code
		** does not have to figure out whether or not IIPROTECT was
		** scanned
		*/
		*privs |= DB_GRANT_OPTION;
	    }

	    goto saw_the_perms;
	}
	else if (!*privs)
	{
	    /*
	    ** we were able to determine that the user posesses required
	    ** privilege(s) based on information contained in independent
	    ** privilege lists
	    */
	    return(E_DB_OK);
	}
    }

    /*
    ** if we are parsing a dbproc to determine if its owner can grant permit on
    ** it, we definitely want all of the privileges WGO;
    ** when processing GRANT, caller is expected to set DB_GRANT_OPTION in
    ** *privs
    */

    if (sess_cb->pss_dbp_flags & PSS_DBPROC)
    {
	if (sess_cb->pss_dbp_flags & PSS_0DBPGRANT_CHECK)
	{
	    /*
	    ** if parsing a dbproc to determine if it is grantable, user must be
	    ** able to grant required privileges
	    */
	    *privs |= DB_GRANT_OPTION;
	}
	else if (sess_cb->pss_dbp_flags & PSS_DBPGRANT_OK)
	{
	    /*
	    ** if we are processing a definition of a dbproc which appears to be
	    ** grantable so far, we will check for existence of all required
	    ** privileges WGO to ensure that it is, indeed, grantable.
	    */
	    privs_wgo = *privs;
	}
    }
    
    /*
    ** Some RDF fields are already set in calling routine.  Permit tuples are
    ** extracted by unique "dummy" table id.  In the case of sequences there
    ** cannot be any caching of permissions (as there are no timestamps) so we
    ** pass in an iiprotect result tuple set (seqprots).
    */
    STRUCT_ASSIGN_MACRO(seq_info->pss_seqid, rdf_rb->rdr_tabid);
    rdf_rb->rdr_types_mask     = RDR_PROTECT;
    rdf_rb->rdr_2types_mask    = RDR2_SEQUENCE; 
    rdf_rb->rdr_instr          = RDF_NO_INSTR;
    rdf_rb->rdr_update_op      = RDR_OPEN;
    rdf_rb->rdr_qrymod_id      = 0;		/* Get all protect tuples */
    rdf_cb->rdf_error.err_code = 0;

    /* For each group of permits */
    while (rdf_cb->rdf_error.err_code == 0 && (*privs || privs_wgo))
    {
	/* Get a set at a time */
	rdf_rb->rdr_qtuple_count = PSY_RDF_SEQ;
	rdf_rb->rdr_qrytuple     = (PTR) seqprots;  /* Result block for tuples */
	status = rdf_call(RDF_READTUPLES, (PTR) rdf_cb);
	rdf_rb->rdr_update_op = RDR_GETNEXT;
	if (status != E_DB_OK)
	{
	    switch(rdf_cb->rdf_error.err_code)
	    {
	      case E_RD0011_NO_MORE_ROWS:
		status = E_DB_OK;
		break;
	      case E_RD0013_NO_TUPLE_FOUND:
		status = E_DB_OK;
		continue;			/* Will stop outer loop */
	      default:
		_VOID_ psf_rdf_error(RDF_READTUPLES, &rdf_cb->rdf_error, err_blk);
		goto seqperm_exit;
	    } /* End switch error */
	} /* If error */

	/* For each permit tuple */
	for (tupcount = 0, protup = seqprots;
	     tupcount < rdf_rb->rdr_qtuple_count;
	     tupcount++, protup++)
	{
	    bool	applies;
	    i4		privs_found;

	    /* check if the permit applies to this session */
	    status = psy_grantee_ok(sess_cb, protup, &applies, err_blk);
	    if (DB_FAILURE_MACRO(status))
	    {
		goto seqperm_exit;
	    }
	    else if (!applies)
	    {
		continue;
	    }

	    /*
	    ** remember that the <auth id> attempting to grant a privilege 
	    ** possesses some privilege on the sequence
	    */
	    if (qmode == PSQ_GRANT && cant_access)
	        cant_access = FALSE;

	    /*
	    ** if some of the required privileges have not been satisfied yet,
	    ** we will check for privileges in *privs; otherwise we will check
	    ** for privileges in (privs_wgo|DB_GRANT_OPTION)
	    */
	    privs_found = prochk((*privs) ? *privs
					  : (privs_wgo | DB_GRANT_OPTION),
		(i4 *) NULL, protup, sess_cb);

	    if (!privs_found)
		continue;

	    /* mark the operations as having been handled */
	    *privs &= ~privs_found;

	    /*
	    ** if the newly found privileges are WGO and we are looking for
	    ** all/some of them WGO, update the map of privileges WGO being
	    ** sought
	    */
	    if (protup->dbp_popset & DB_GRANT_OPTION && privs_found & privs_wgo)
	    {
		privs_wgo &= ~privs_found;
	    }

	    /*
	    ** check if all required privileges have been satisfied;
	    ** note that DB_GRANT_OPTION bit does not get turned off when we
	    ** find a tuple matching the required privileges since when we
	    ** process GRANT ON SEQUENCE, more than one privilege may be required
	    */
	    if (*privs && !(*privs & ~DB_GRANT_OPTION))
	    {
		*privs = (i4) 0;
	    }

	    if (!*privs && !privs_wgo)
	    {
		/*
		** all the required privileges have been satisfied and the
		** required privileges WGO (if any) have been satisfied as
		** well -  we don't need to examine any more tuples
		*/
		break;
	    }
	} /* For all tuples */
    } /* While there are RDF tuples */

saw_the_perms:
    if (   sess_cb->pss_dbp_flags & PSS_DBPGRANT_OK
	&& (privs_wgo || *privs & DB_GRANT_OPTION))
    {
	/*
	** we are processing a dbproc definition; until now the dbproc appeared
	** to be grantable, but the user lacks the required privileges WGO on
	** this sequence - mark the dbproc as non-grantable
	*/
	sess_cb->pss_dbp_flags &= ~PSS_DBPGRANT_OK;
    }

    /*
    ** if processing a dbproc, we will record the privileges which the current
    ** user posesses if
    **	    - user posesses all the required privileges or
    **	    - we were parsing the dbproc to determine if it is grantable (in
    **	      which case the current dbproc will be marked as ungrantable, but
    **	      the privilege information may come in handy when processing the
    **	      next dbproc mentioned in the same GRANT statement.)
    **
    ** NOTE: we do not build independent privilege list for system-generated
    **	     dbprocs
    */
    if (   sess_cb->pss_dbp_flags & PSS_DBPROC
	&& ~sess_cb->pss_dbp_flags & PSS_SYSTEM_GENERATED
	&& (!*privs || sess_cb->pss_dbp_flags & PSS_0DBPGRANT_CHECK))
    {
	if (save_privs & ~*privs)
	{
	    if (seqpriv_element)
	    {
		seqpriv_element->psq_privmap |= (save_privs & ~*privs);
	    }
	    else
	    {
		/* create a new descriptor */

		status = psy_insert_objpriv(sess_cb, &seq_info->pss_seqid,
		    PSQ_OBJTYPE_IS_SEQUENCE, save_privs & ~*privs,
		    sess_cb->pss_dependencies_stream,
		    &sess_cb->pss_indep_objs.psq_objprivs, err_blk);

		if (DB_FAILURE_MACRO(status))
		    goto seqperm_exit;
	    }
	}
    }

    if (*privs)
    {
	char                buf[60];  /* buffer for missing privilege string */
	i4		    err_code;

	psy_prvmap_to_str((qmode == PSQ_GRANT) ? *privs & ~DB_GRANT_OPTION
					       : *privs,
	    buf, sess_cb->pss_lang);

	if (sess_cb->pss_dbp_flags & PSS_DBPROC)
	    sess_cb->pss_dbp_flags |= PSS_MISSING_PRIV;
	    
	if (qmode == PSQ_GRANT)
	{
	    if (cant_access)
	    {
		_VOID_ psf_error(E_US088F_2191_INACCESSIBLE_EVENT, 0L, 
		    PSF_USERERR, &err_code, err_blk, 3,
		    sizeof("GRANT") - 1, "GRANT",
		    psf_trmwhite(sizeof(DB_OWN_NAME), 
			(char *) &seq_info->pss_seqown), 
		    &seq_info->pss_seqown,
		    psf_trmwhite(sizeof(DB_NAME),
			(char *) &seq_info->pss_seqname),
		    &seq_info->pss_seqname);
	    }
	    else if (!grant_all)
	    {
		/* privileges were specified explicitly */
		_VOID_ psf_error(E_PS0551_INSUF_PRIV_GRANT_OBJ, 0L, PSF_USERERR,
		    &err_code, err_blk, 3,
		    STlength(buf), buf,
		    psf_trmwhite(sizeof(DB_NAME), 
			(char *) &seq_info->pss_seqname),
		    &seq_info->pss_seqname,
		    psf_trmwhite(sizeof(DB_OWN_NAME), 
			(char *) &seq_info->pss_seqown),
		    &seq_info->pss_seqown);
	    }
	    else if (save_privs == *privs)
	    {
		/* user entered GRANT ALL [PRIVILEGES] */
		_VOID_ psf_error(E_PS0563_NOPRIV_ON_GRANT_EV, 0L, PSF_USERERR,
		    &err_code, err_blk, 2,
		    psf_trmwhite(sizeof(DB_NAME), 
			(char *) &seq_info->pss_seqname),
		    &seq_info->pss_seqname,
		    psf_trmwhite(sizeof(DB_OWN_NAME), 
			(char *) &seq_info->pss_seqown),
		    &seq_info->pss_seqown);
	    }
	}
	else if (   sess_cb->pss_dbp_flags & PSS_DBPROC
		 && sess_cb->pss_dbp_flags & PSS_0DBPGRANT_CHECK)
	{
	    /*
	    ** if we were processing a dbproc definition to determine if it
	    ** is grantable, record those of required privileges which the
	    ** current user does not posess
	    */

	    _VOID_ psf_error(E_PS0557_DBPGRANT_LACK_EVPRIV, 0L, PSF_USERERR,
		&err_code, err_blk, 4,
		psf_trmwhite(sizeof(DB_NAME), (char *) &seq_info->pss_seqname),
		&seq_info->pss_seqname,
		psf_trmwhite(sizeof(DB_OWN_NAME), 
		    (char *) &seq_info->pss_seqown),
		&seq_info->pss_seqown,
		psf_trmwhite(sizeof(DB_DBP_NAME), 
		    (char *) sess_cb->pss_dbpgrant_name),
		sess_cb->pss_dbpgrant_name,
		STlength(buf), buf);

	    status = psy_insert_objpriv(sess_cb, &seq_info->pss_seqid,
		PSQ_OBJTYPE_IS_SEQUENCE | PSQ_MISSING_PRIVILEGE,
		save_privs & *privs, sess_cb->pss_dependencies_stream,
		&sess_cb->pss_indep_objs.psq_objprivs, err_blk);
	}
	else
	{
	    char	*op;

	    op = "NEXT VALUE";	/* only one possible */

	    _VOID_ psf_error(E_PS0D3D_MISSING_SEQUENCE_PRIV, 0L, PSF_USERERR,
		&err_code, err_blk, 4, 
		STlength(op), op, 
		STlength(buf), buf,
		psf_trmwhite(sizeof(DB_NAME), 
		    (char *) &seq_info->pss_seqname),
		&seq_info->pss_seqname,
		psf_trmwhite(sizeof(DB_OWN_NAME), 
		    (char *) &seq_info->pss_seqown),
		&seq_info->pss_seqown);
	}
    }
	    
seqperm_exit:
    /* Close iiprotect system catalog */
    if (rdf_rb->rdr_rec_access_id != NULL)
    {
	DB_STATUS	stat;

	rdf_rb->rdr_update_op = RDR_CLOSE;
	stat = rdf_call(RDF_READTUPLES, (PTR) rdf_cb);
	if (DB_FAILURE_MACRO(stat))
	{
	    _VOID_ psf_rdf_error(RDF_READTUPLES, &rdf_cb->rdf_error, err_blk);

	    if (stat > status)
	    {
		status = stat;	
	    }
	}
    }
    /*
    ** If user does not have privs we need to audit that they failed to perform
    ** the action on the event.
    */
    if ( *privs && Psf_srvblk->psf_capabilities & PSF_C_C2SECURE )
    {
	i4		msg_id;
	i4		accessmask = SXF_A_FAIL;

	/* determin action */
	switch (qmode)
	{
	    default: 
		accessmask |= SXF_A_RAISE;
		msg_id = I_SX2704_RAISE_DBEVENT;
		break;
	}
/*	stat = psy_secaudit(FALSE, sess_cb, 
		ev_info->pss_alert_name.dba_alert.db_name, 
		&ev_info->pss_alert_name.dba_owner,
		sizeof(ev_info->pss_alert_name.dba_alert.db_name),
		SXF_E_EVENT, msg_id, accessmask, 
		(PTR)&ev_info->pss_evsecid,
		DB_SECID_TYPE,
		&e_error);
	if (stat > status)
	    status = stat;  */
    }
    return(status);
} /* psy_seqperm */
Exemplo n.º 28
0
DB_STATUS
psy_kalarm(
	PSY_CB             *psy_cb,
	PSS_SESBLK	   *sess_cb)
{
    RDF_CB              rdf_cb;
    RDR_RB		*rdf_rb = &rdf_cb.rdf_rb;
    RDF_CB              rdf_inv_cb;
    DB_STATUS		status;
    DB_SECALARM		*atuple= &psy_cb->psy_tuple.psy_alarm;
    i4			i;
    PSY_OBJ		*psy_obj;
    bool		loop=FALSE;


    /* Fill in the RDF request blocks */
    pst_rdfcb_init(&rdf_cb, sess_cb);
    rdf_rb->rdr_types_mask  = RDR_SECALM;	/* Alarm deletion */
    rdf_rb->rdr_update_op   = RDR_DELETE;
    rdf_rb->rdr_qrytuple    = (PTR)atuple;/* Alarm tuple */

    pst_rdfcb_init(&rdf_inv_cb, sess_cb);
    rdf_inv_cb.rdf_rb.rdr_types_mask |= RDR_SECALM;

    do
    {
	/*
	** Loop through each alarm in turn deleting them.
	** User may have specified alarms by name or by number, or by all
	*/
	if (psy_cb->psy_numnms == 0 && 
	    (PSY_OBJ*)psy_cb->psy_objq.q_next ==  (PSY_OBJ*)&psy_cb->psy_objq)
	{
	    /*
	    ** Drop all alarms on the indicated object
	    */
	    rdf_rb->rdr_types_mask  |= RDR_DROP_ALL;	
	    STmove(ERx("all alarms"),' ',
			sizeof(atuple->dba_alarmname),
			(char*)&atuple->dba_alarmname);
	    status = rdf_call(RDF_UPDATE, (PTR) &rdf_cb);	/* Destroy alarm */
	    if (status != E_DB_OK)
	    {
	        _VOID_ psf_rdf_error(RDF_UPDATE, &rdf_cb.rdf_error, 
			&psy_cb->psy_error);
	    }
	}
	if(psy_cb->psy_numnms)
	{
	    /*
	    ** Dropping alarms by number, so walk through all numbers dropping.
	    */
	    for (i=0;i <psy_cb->psy_numnms; i++)
	    {
		char tmpstr[64];
		CVla((i4)psy_cb->psy_numbs[i],tmpstr);
		STmove(tmpstr,' ', 
			sizeof(atuple->dba_alarmname),
			(char*)&atuple->dba_alarmname);
	     	atuple->dba_alarmno=psy_cb->psy_numbs[i];
	     	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);
		     break;
	        }
	    }
	}
	if((PSY_OBJ*)psy_cb->psy_objq.q_next!= (PSY_OBJ*)&psy_cb->psy_objq)
	{
	    /*
	    ** Dropping alarms by name, so walk through all names dropping
	    */
	    for (psy_obj  = (PSY_OBJ *)  psy_cb->psy_objq.q_next;
	      psy_obj != (PSY_OBJ *) &psy_cb->psy_objq;
	      psy_obj  = (PSY_OBJ *)  psy_obj->queue.q_next
	    )
	    {
	     	MEcopy((PTR)&psy_obj->psy_objnm,
		    sizeof(atuple->dba_alarmname), (PTR)&atuple->dba_alarmname);
	     	atuple->dba_alarmno=0;
	     	status = rdf_call(RDF_UPDATE, (PTR) &rdf_cb);/* Destroy alarm */
	     	if (status != E_DB_OK)
	     	{
		    _VOID_ psf_rdf_error(RDF_UPDATE, &rdf_cb.rdf_error, 
			&psy_cb->psy_error);
		    break;
	         }
	    }
	}
    }
    while(loop);

    if(status==E_DB_OK && atuple->dba_objtype==DBOB_TABLE)
    {
	/*
	** Invalidate table infoblk from RDF cache.
	*/
	STRUCT_ASSIGN_MACRO(atuple->dba_objid, rdf_inv_cb.rdf_rb.rdr_tabid);
	status = rdf_call(RDF_INVALIDATE, (PTR) &rdf_inv_cb); /* drop infoblk */
	if (DB_FAILURE_MACRO(status))
	{
	    (VOID) psf_rdf_error(RDF_INVALIDATE, &rdf_inv_cb.rdf_error,
				&psy_cb->psy_error);
	    return(status);
	}
    }
    return (status);
} /* psy_kalarm */