コード例 #1
0
/*
** Name: sxapo_close - close an audit trail
**
** Description:
**	This routine closes an audit trail that has previously been opened
**	by a call to sxap_open.
**
** 	Overview of algorithm:-
**
**	Call SAclose.
**	close the memory stream ascociated with this audit trail.
**
** Inputs:
**	sxf_rscb		The SXF_RSCB structure associated with this
**				audit trail
**
** Outputs:
**	err_code		Error code returned to the caller.
**
** Returns:
**	DB_STATUS
**
** History:
**	6-jan-94 (stephenb)
**	    Initial creation.
**	11-feb-94 (stephenb)
**	    Update SA call to current spec.
*/
sxapo_close(
    SXF_RSCB	*rscb,
    i4	*err_code)
{
    SXAPO_RSCB		*sxapo_rscb = (SXAPO_RSCB *)rscb->sxf_sxap;
    STATUS		cl_stat;
    CL_ERR_DESC		cl_err;
    DB_STATUS		status;
    ULM_RCB		ulm_rcb;
    i4		local_err;

    *err_code = E_SX0000_OK;
    for(;;)
    {
        if (!sxapo_rscb)
        {
            *err_code = E_SX0004_BAD_PARAMETER;
            _VOID_ ule_format(*err_code, NULL, ULE_LOG, NULL, NULL,
                              0L, NULL, &local_err, 0);
            break;
        }
        /*
        ** incriment stats counter
        */
        Sxf_svcb->sxf_stats->close_count++;

        cl_stat = SAclose(&sxapo_rscb->sxapo_desc, &cl_err);
        if (cl_stat != OK)
        {
            *err_code = E_SX1018_FILE_ACCESS_ERROR;
            _VOID_ ule_format(*err_code, &cl_err, ULE_LOG, NULL, NULL,
                              0L, NULL, &local_err, 0);
        }
        /*
        ** Close memory stream
        */
        ulm_rcb.ulm_facility = DB_SXF_ID;
        ulm_rcb.ulm_streamid_p = &sxapo_rscb->rs_memory;
        ulm_rcb.ulm_memleft = &Sxf_svcb->sxf_pool_sz;
        status = ulm_closestream(&ulm_rcb);
        if (status != E_DB_OK)
        {
            *err_code = E_SX106B_MEMORY_ERROR;
            _VOID_ ule_format(ulm_rcb.ulm_error.err_code, NULL, ULE_LOG,
                              NULL, NULL, 0L, NULL, &local_err, 0);
            _VOID_ ule_format(*err_code, NULL, ULE_LOG, NULL, NULL,
                              0L, NULL, &local_err, 0);
        }
        /* ULM has nullified rs_memory */
        rscb->sxf_sxap = NULL;
        break;
    }
    if (*err_code != E_SX0000_OK)
    {
        *err_code = E_SX1026_SXAP_CLOSE;
        status = E_DB_ERROR;
    }
    return (status);
}
コード例 #2
0
ファイル: sxcend.c プロジェクト: saqibjamil/Ingres
/*
** Name: SXC_DESTROY_SCB - destroy a SXF session control block
**
** Description:
**	This routine frees all the resourses associated with a session control
**	block (SXF_SCB).
**
**	Overview of algorithm:-
**
**	Release the SCB's lock list.
**	Close the SCB's memory stream.
**
** Inputs:
**	scb		pointer to session control block to be destroyed
**
** Outputs:
**	err_code	
**
** Returns:
**	DB_STATUS
** History:
**	25-sept-92 (markg)
**	    Initial creation.
**	26-oct-1992 (markg)
**	    Updated error handling.
**      10-mar-1993 (markg)
**          Fixed problem where errors returned from ulm were not getting
**          handled correctly.
**	10-may-1993 (robf)
**	    Added handling for database cb in session.
*/
DB_STATUS
sxc_destroy_scb(
    SXF_SCB	*scb,
    i4	*err_code)
{
    DB_STATUS		status = E_DB_OK;
    i4		local_err;
    CL_ERR_DESC		cl_err;
    ULM_RCB		ulm_rcb;

    *err_code = E_SX0000_OK;

    for (;;)
    {
	if (LKrelease(LK_ALL, scb->sxf_lock_list, 
		NULL, NULL, NULL, &cl_err) != OK)
	{
	    *err_code = E_SX1008_BAD_LOCK_RELEASE;
	    _VOID_ ule_format(*err_code, &cl_err,
		ULE_LOG, NULL, NULL, 0L, NULL, &local_err, 0);
	}
	/*
	** Release database cb 
	*/
	sxc_freedbcb(scb, scb->sxf_db_info);

	ulm_rcb.ulm_facility = DB_SXF_ID;
	ulm_rcb.ulm_streamid_p = &scb->sxf_scb_mem;
	ulm_rcb.ulm_memleft = &Sxf_svcb->sxf_pool_sz;
	status = ulm_closestream(&ulm_rcb);
	if (status != E_DB_OK)
	{
	    *err_code = E_SX106B_MEMORY_ERROR;
	    _VOID_ ule_format(ulm_rcb.ulm_error.err_code, NULL,
		ULE_LOG, NULL, NULL, 0L, NULL, &local_err, 0);
	    _VOID_ ule_format(*err_code, NULL,
		ULE_LOG, NULL, NULL, 0L, NULL, &local_err, 0);
	}
	/* ULM has nullified sxf_scb_mem */

	break;
    }

    /* Handle any errors */
    if (*err_code != E_SX0000_OK)
    {
	if (*err_code > E_SXF_INTERNAL)
	    *err_code = E_SX1007_BAD_SCB_DESTROY;

	if (status == E_DB_OK)
	    status = E_DB_ERROR;	
    }

    return (status);
}
コード例 #3
0
ファイル: tpdsvpt.c プロジェクト: saqibjamil/Ingres
DB_STATUS
tpd_s2_clear_all_sps(
	TPR_CB	*v_tpr_p)
{
    DB_STATUS	status = E_DB_OK;
    TPD_SS_CB	*sscb_p = (TPD_SS_CB *) v_tpr_p->tpr_session;
    TPD_DX_CB	*dxcb_p = & sscb_p->tss_dx_cb;
    TPD_LX_CB	*lxcb_p = (TPD_LX_CB *) NULL;
    TPD_LM_CB	*lxlm_p = & dxcb_p->tdx_22_lx_ulmcb;
    TPD_LM_CB	*splm_p = & dxcb_p->tdx_23_sp_ulmcb;
    ULM_RCB	ulm;


    /* 1.  MUST reinitialize every LDB's savepoint count */

    lxcb_p = (TPD_LX_CB *) lxlm_p->tlm_3_frst_ptr;  /* first LX CB in list */
    while (lxcb_p != (TPD_LX_CB *) NULL)
    {
	lxcb_p->tlx_sp_cnt = 0;
	lxcb_p = lxcb_p->tlx_22_next_p;	/* advance to next LX CB */
    }

    if (splm_p->tlm_1_streamid == (PTR) NULL)
	return(E_DB_OK);    /* session has no outstanding savepoints */

    /* 2.  MUST close the memory stream opend for savepoints */

    ulm.ulm_facility = DB_QEF_ID;   /* borrow QEF's id */
    ulm.ulm_streamid_p = &splm_p->tlm_1_streamid;	/* use before nulling */
    ulm.ulm_memleft = & Tpf_svcb_p->tsv_7_ulm_memleft.ts4_2_i4;

    splm_p->tlm_2_cnt = 0;
    splm_p->tlm_3_frst_ptr = 
        splm_p->tlm_4_last_ptr = (PTR) NULL;

    status = ulm_closestream(& ulm);
    if (status != E_DB_OK)
    {
	return( tpd_u1_error(E_TP0017_ULM_CLOSE_FAILED, v_tpr_p) );
    }
    /* ULM has nullified tlm_1_streamid */
    return(E_DB_OK);
}
コード例 #4
0
/*{
** Name: psq_tclose	- Close the memory stream for a text chain
**
** Description:
**      This function closes the memory stream for a text chain, deallocating
**	the memory.
**
** Inputs:
**      header                          Pointer to header of text chain
**	err_blk				Filled in if an error happens
**
** Outputs:
**      err_blk                         Filled in if an error happened
**	Returns:
**	    E_DB_OK			Success
**	    E_DB_ERROR			Non-catastrophic failure
**	    E_DB_FATAL			Catastrophic failure
**	Exceptions:
**	    none
**
** Side Effects:
**	    Deallocates memory
**
** History:
**      18-jul-86 (jeff)
**          written
*/
DB_STATUS
psq_tclose(
	PTR		   header,
	DB_ERROR           *err_blk)
{
    DB_STATUS           status;
    ULM_RCB		ulm_rcb;
    i4		err_code;

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

    return (E_DB_OK);
}
コード例 #5
0
/*{
** Name: OPU_CSMEMORY_CLOSE	- Close the stack ULM memory stream
**
** Description:
**      This routine closes the ULM memory stream that was used 
**      for the stack style memory allocation and deallocation. 
[@comment_line@]...
**
** Inputs:
**	global -
**	    State info for the current query.
**	global->ops_mstate.ops_ulmrcb -
**	    The ULM control block.
**	global->ops_mstate.ops_sstreamid -
**	    The stream id.
**
** Outputs:
**
**	Returns:
**	    Nothing
**	Exceptions:
**	    none
**
** Side Effects:
**	    none
**
** History:
**      19-July-87 (eric)
**          written
**	11-oct-2006 (hayke02)
**	    Send E_OP0002_NOMEMORY to errlog.log. This change fixes bug 116309.
[@history_template@]...
*/
VOID
opu_Csmemory_close(
	OPS_STATE   *global)
{
    DB_STATUS      ulmstatus;		    /* return status from ULM */

    /* store the stream id */
    global->ops_mstate.ops_ulmrcb.ulm_streamid_p = &global->ops_mstate.ops_sstreamid;
    /* ULM will nullify ops_sstreamid */

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

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

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

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

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

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

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

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

	    sess_cb->pss_tchain = (PTR) NULL;
	}

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

	    sess_cb->pss_tchain2 = (PTR) NULL;
	}

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

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

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

    } while (0);

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

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

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

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

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

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

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

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

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

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

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

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

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

    /* This is the failure exit code. */

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

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

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

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

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

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

    return(ret_val);
}
コード例 #7
0
/*
** Name: sxapo_open - open an audit trail
**
** Description:
**	This routine is used to open an audit trail that can, in theory, be used
**	for either reading or writing audit records, although reading of
**	operating system audit records is not currently supported. SXF supports
**	the ability to have a maximum of one audit trail open for writing at
**	a time. This routine
**	returns an access identifier (actually a pointer to a SXAPO_RSCB
**	structure) that must be specified for all other operations requested
**	on this trail. if no filename is specified the current audit trail
**	will be opened.
**
** 	Overview of algorithm:-
**
**	Validate the parameters passed to the routine.
**	Open a memory stream and allocate and build a SXAPO_RSCB.
**	If filename is NULL get the name of the current audit trail.
**	Call the SAopen routine to perform the physical open call.
**
**
** Inputs:
**	filename		Name of the audit trail to open, if this is NULL
**				the current audit trail will be opened.
**	mode			either SXF_READ of SXF_WRITE (must currently
**				be SXF_WRITE).
**	sxf_rscb		the SXF_RSCB for the audit trail
**
** Outputs:
**	sxf_rscb		Access identifier for audit file.
**	err_code		Error code returned to the caller.
**
** Returns:
**	DB_STATUS
**
** History:
**	6-jan-94 (stephenb)
**	    Initial Creation.
**	7-feb-94 (stephenb)
**	    log error E_SX002E_OSAUDIT_NO_READ since we don't do it anywhere
**	    else yet.
**	11-feb-94 (stephenb)
**	    Update SA call to current spec.
*/
DB_STATUS
sxapo_open(
    PTR			filename,
    i4			mode,
    SXF_RSCB		*sxf_rscb,
    i4		*filesize,
    PTR			sptr,
    i4		*err_code)
{
    ULM_RCB		ulm_rcb;
    DB_STATUS		status = E_DB_OK;
    i4		local_err;
    bool		stream_open = FALSE;
    SXAPO_RSCB		*sxapo_rscb;
    STATUS		cl_stat;
    CL_ERR_DESC		cl_err;

    *err_code = E_SX0000_OK;
    for (;;)
    {
        /* validate parameters, write is currently the only valid mode */
        if (sxf_rscb == NULL)
        {
            *err_code = E_SX0004_BAD_PARAMETER;
            break;
        }
        else if (mode != SXF_WRITE)
        {
            *err_code = E_SX002E_OSAUDIT_NO_READ;
            /*
            ** Log this here since we don't yet do it anywhere else.
            */
            _VOID_ ule_format(*err_code, NULL, ULE_LOG, NULL, NULL, 0L,
                              NULL, &local_err, 0);
            break;
        }
        /*
        ** Open a memory stream and allocate some memory for the SXAPO_RSCB
        */
        ulm_rcb.ulm_facility = DB_SXF_ID;
        ulm_rcb.ulm_poolid = Sxf_svcb->sxf_pool_id;
        ulm_rcb.ulm_blocksize = 0;
        ulm_rcb.ulm_memleft = &Sxf_svcb->sxf_pool_sz;
        ulm_rcb.ulm_streamid_p = &ulm_rcb.ulm_streamid;
        /* No other allocations on this stream - make it private */
        /* Open stream and allocate SXAPO_RSCB with one call */
        ulm_rcb.ulm_flags = ULM_PRIVATE_STREAM | ULM_OPEN_AND_PALLOC;
        ulm_rcb.ulm_psize = sizeof (SXAPO_RSCB);
        status = ulm_openstream(&ulm_rcb);
        if (status != E_DB_OK)
        {
            if(ulm_rcb.ulm_error.err_code == E_UL0005_NOMEM)
                *err_code = E_SX1002_NO_MEMORY;
            else
                *err_code = E_SX106B_MEMORY_ERROR;
            _VOID_ ule_format(ulm_rcb.ulm_error.err_code, NULL, ULE_LOG,
                              NULL, NULL, 0L, NULL, &local_err, 0);
            _VOID_ ule_format(*err_code, NULL, ULE_LOG,
                              NULL, NULL, 0L, NULL, &local_err, 0);
            break;
        }
        stream_open = TRUE;

        sxf_rscb->sxf_sxap = ulm_rcb.ulm_pptr;
        sxapo_rscb = (SXAPO_RSCB *) sxf_rscb->sxf_sxap;
        sxapo_rscb->rs_memory = ulm_rcb.ulm_streamid;
        /*
        ** Filename should not be supplied for OS audit trail writes
        */
        if (filename)
        {
            *err_code = E_SX101E_INVALID_FILENAME;
            break;
        }
        else
        {
            /*
            ** Auditing must be enabled to use "current" file
            */
            if (Sxapo_cb->sxapo_status & SXAPO_STOPAUDIT)
            {
                _VOID_ ule_format(E_SX10A7_NO_CURRENT_FILE, NULL, ULE_LOG,
                                  NULL, NULL, 0L, NULL, &local_err, 0);
                *err_code = E_SX0015_FILE_NOT_FOUND;
                break;
            }
        }
        /*
        ** Open the audit trail with SAopen
        */
        cl_stat = SAopen(NULL, SA_WRITE,
                         &sxapo_rscb->sxapo_desc, &cl_err);
        if (cl_stat != OK)
        {
            *err_code = E_SX1018_FILE_ACCESS_ERROR;
            _VOID_ ule_format(*err_code, &cl_err, ULE_LOG, NULL, NULL,
                              0L, NULL, &local_err, 0);
            break;
        }
        break;
    }
    /*
    ** Handle any errors
    */
    if (*err_code != E_SX0000_OK)
    {
        if (stream_open)
            _VOID_ ulm_closestream(&ulm_rcb);
        if (*err_code > E_SXF_INTERNAL)
        {
            _VOID_ ule_format(E_SX10B6_OSAUDIT_OPEN_FAILED, NULL, ULE_LOG,
                              NULL, NULL, 0L, NULL, &local_err, 0);
            *err_code = E_SX1023_SXAP_OPEN;
        }
        if (status == E_DB_OK)
            status = E_DB_ERROR;
    }
    else
    {
        /*
        ** Incriment stats counter
        */
        Sxf_svcb->sxf_stats->open_write++;
    }

    return (status);
}
コード例 #8
0
DB_STATUS
qet_t9_ok_w_ldbs(
QEE_DSH		*i_dsh_p,
QEF_RCB		*v_qer_p,
bool		*o1_ok_p)
{
    DB_STATUS	    status_0 = E_DB_OK,
		    status_t = E_DB_OK,
		    status_u = E_DB_OK;		
    DB_ERROR	    ulm_err,
		    tpf_err;
    QES_DDB_SES	    *dds_p = & v_qer_p->qef_cb->qef_c2_ddb_ses;
    TPR_CB	    tpr_cb,
		    *tpr_p = & tpr_cb;
    QEF_QP_CB	    *qp_p = i_dsh_p->dsh_qp_ptr;
    QEF_AHD	    *act_p = qp_p->qp_ahd;
    QEQ_D1_QRY	    *subqry_p;
    ULM_RCB	    ulm;
    i4		    w_ldbcnt;
    TPR_W_LDB	    *wldb1_p = (TPR_W_LDB *) NULL,
		    *wldb2_p = (TPR_W_LDB *) NULL;


    *o1_ok_p = TRUE;	/* assume */

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

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

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

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

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

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

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

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

		w_ldbcnt++;

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

		    wldb2_p = (TPR_W_LDB *) ulm.ulm_pptr;

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

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

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

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

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

dismantle_9:

    /* must always close stream */

    status_0 = ulm_closestream(&ulm);

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

	    if (ret_val != QEU_F_RETURN)
	    {
		continue;
	    }

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

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

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

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

    if (mem_opened)
    {
	/* don't try to close a stream unless it was opened */
	ulm_closestream(&ulm);
    }
    
    return (status);
}
コード例 #12
0
/*{
** Name: psq_bgn_session	- Begin a parser session.
**
**  INTERNAL PSF call format: status = psq_bgn_session(&psq_cb, &sess_cb);
**
**  EXTERNAL call format: status = psq_call(PSQ_BGN_SESSION, &psq_cb, &sess_cb);
**
** Description:
**      The psq_bgn_session function begins a parser session.  It should be
**	called each time a new user connects to a server.  There may be 
**      many parser sessions per database server.  There should be one parser 
**      session for each invocation of the database system that is connected 
**      to the server.  When starting a parser session, one has to tell it
**	what query language to use, and other session parameters.
**
** Inputs:
**      psq_cb
**          .psq_qlang                  The query language to use.
**          .psq_decimal
**		.psf_decspec		TRUE indicates that the decimal marker
**					has been specified.  FALSE means use the
**					default (a ".").
**		.psf_decimal		The character to use as a decimal marker
**					(if specified).
**	    .psq_distrib		Indicator for whether distributed
**					statements and constructs should be
**					accepted.
**	    .psq_sessid			Session id 
**	    .psq_server			address of server control block
**	    .psq_adf_cb			Pointer to session's ADF_CB
**	    .psq_dbid			Database id for this session.
**	    .psq_user			User name of 
**	    .psq_dba			User name of dba
**	    .psq_group			Group id of session
**	    .psq_aplid			Application id of session
**	    .psq_flag			bitmask containing the following flags:
**	      .psq_catupd		  TRUE means catalogs updateable
**	      .psq_warnings		  Set to TRUE if user wishes to see
**					  warnings on unsupported commands
**	    .psq_idxstruct		Structure for creating new indexes
**					(e.g. DB_ISAM_STORE)
**	    .psq_udbid			Unique database id for this session.
**	    .psq_ustat	 		User status flags from SCS_ICS
**	    .psq_dbxlate		Case translation semantics for the db
**	sess_cb				Pointer to session control block
**					(Can be NULL)
**
** Outputs:
**      psq_cb
**          .psq_error                  Error information
**		.err_code		    What error occurred
**		    E_PS0000_OK			Success
**		    E_PS0001_INTERNAL_ERROR	    Internal PSF problem
**		    E_PS0201_BAD_QLANG		    Bad query language specifier
**		    E_PS0203_NO_DECIMAL		    No decimal marker specified
**		    E_PS0204_BAD_DISTRIB	    Bad distributed
**						    specification
**		    E_PS0205_SRV_NOT_INIT	    Server not initialized
**		    E_PS0206_TOO_MANY_SESS	    Too many sessions at one
**						    time
**	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			Session is to be aborted
**	    E_DB_FATAL			Function failed; catastrophic error
**	Exceptions:
**	    none
**
** Side Effects:
**	    Causes memory to be allocated.
**	    Increments the session count in the server control block.
**
** History:
**	01-oct-85 (jeff)
**          written
**	28-jul-86 (jeff)
**	    Added initialization of pss_catupd and pss_idxstruct
**      26-aug-86 (seputis)
**          Removed definition of yaccstream
**	13-apr-87 (puree)
**	    Initialize prototype list for dynamic SQL.
**	24-apr-87 (stec)
**	    init pss_project.
**	11-may-87 (stec)
**	    store psq_udbid to pss_dbid.
**	04-sep-87 (stec)
**	    Added critical region code where needed.
**	02-oct-87 (stec)
**	    Added pss_journaling initialization.
**	13-jun-88 (stec)
**	    Added initialization of pss_ruset for DB procs.
**	08-mar-89 (andre)
**	    Copy dba_drop_all from PSQ_CB to PSS_SESBLK.
**	15-mar-89 (ralph)
**	    GRANT Enhancements, Phase 1:
**	    Copy psq_aplid to pss_aplid;
**	    Copy psq_group to pss_group.
**	16-mar-89 (neil)
**	    Initialized rule field.
**	27-jul-89 (jrb)
**	    Copy numeric literals flag into session cb.
**	27-oct-89 (ralph)
**	    Copy user status flags to session control block.
**	11-oct-89 (ralph)
**	    Initialize pss_rgset and pss_raset.
**	28-dec-89 (andre)
**	    Copy fips_mode from PSQ_CB to PSS_SESBLK.
**	13-feb-90 (andre)
**	    set scf_stype to SCU_EXCLUSIVE before calling scu_swait.
**	12-sep-90 (sandyh)
**	    Added support for session memory value calculated from psf
**	    memory startup parameter.
**	15-nov-90 (andre)
**	    check the return status after calling SCF to acquire or to release a
**	    semaphore.
**	    If an error occurred when trying to acquire the semaphore, return
**	    E_DB_SEVERE to abort the session.
**	    If an error occurred when trying to release the semaphore, return
**	    E_DB_FATAL to bring down the server.
**	17-may-91 (andre)
**	    store DBA name into sess_cb->pss_dbaname and NULL-terminate.
**	08-nov-91 (rblumer)
**          merged from 6.4:  25-jul-91 (andre)
**		if (psq_cb->psq_flag & PSQ_STRIP_NL_IN_STRCONST), set bit
**		PSS_STRIP_NL_IN_STRCONST in sess_cb->pss_ses_flag.  this will
**		indicate that we are connected to an older FE, so the scanners
**		will continue to strip NLs inside quoted strings;
**		this is required to fix bug 38098
**	14-jan-92 (barbara)
**	    Included ddb.h for Star.  Updated to check for distributed
**	    specification.
**	26-feb-92 (andre)
**	    if PSQ_REPAIR_SYSCAT is set in psq_cb->psq_flag, set
**	    PSS_REPAIR_SYSCAT in sess_cb->pss_ses_flags
**	30-mar-1992 (bryanp)
**	    Fill in pss_sess_owner with a session-unique owner name for use
**	    by temporary tables which are owned by this session.
**	02-jun-92 (andre)
**	    initialize pss_dependencies_stream to NULL to avloid use of illegal
**	    address throughout the parser.
**	24-nov-92 (ralph)
**	    CREATE SCHEMA:
**	    Initialize pss_prvgoval
**	22-dec-92 (rblumer)
**	    initialize pointer for statement-level rule list.
**	14-jan-93 (andre)
**	    remember whether we are running UPGRADEDB - this will enable us to
**	    decide whether IIDEVICES can be dropped - which is needed by
**	    UPGRADEDB
**	15-mar-93 (ralph)
**	    DELIM_IDENT: initialize pss_dbxlate to zero
**	08-apr-93 (andre)
**	    names of rule list headers in sess_cb have changed (and their
**	    number has doubled)
**	26-mar-93 (ralph)
**	    DELIM_IDENT: Must initialize pss_dbxlate from psq_cb.psq_dbxlate
**	    and pss_cat_owner from psq_cat_owner.
**	10-aug-93 (andre)
**	    fixed cause of a compiler warning
**	08-sep-93 (swm)
**	    Changed sizeof(DB_SESSID) to sizeof(CS_SID) to reflect recent CL
**	    interface revision.
**	20-sep-93 (rogerk)
**	    Changed default table create semantics to be WITH JOURNALING.
**	    Initialized the pss_ses_flag setting to include PSS_JOURNALING
**	    which mimics the user requesting "set journaling" to indicate that
**	    tables created should be journaled.
**	08-oct-93 (rblumer)
**	    increased values allowed in pss_trace vector, using PSS_TVALS.
**	18-oct-93 (rogerk)
**	    Added support for journal default override.  Check psf server
**	    control block flag for PSF_NO_JNL_DEFAULT override before setting
**	    the session parse flag to assume journaling on table creates.
**	15-nov-93 (andre)
**	    add code to initialize a newly added sess_cb->pss_flattening_flags
**	01-nov-93 (anitap)
**	    if PSQ_INGRES_PRIV is set in psq_cb->psq_flag, set
**	    PSS_INGRES_PRIV in sess_cb->pss_ses_flags.
**	17-dec-93 (rblumer)
**	    "FIPS mode" no longer exists.  It was replaced some time ago by
**	    several feature-specific flags (e.g. flatten_nosingleton and
**	    direct_cursor_mode).  So I removed all FIPS_MODE flags.
**	02-jan-94 (andre)
**	    if starting a local session, call DMF to determine whether the 
**	    database to which we are connected is being journaled and record 
**	    that information by setting (or not setting) PSS_JOURNALED_DB bit 
**	    in pss_ses_flags
**	 7-jan-94 (swm)
**	    Bug #58635
**	    Added PTR cast for pss_owner which has changed type to PTR.
**	17-mar-94 (robf)
**          Add support for PSQ_SELECT_ALL flag
**	13-Feb-1995 (canor01)
**	    initialize the pss_audit field in the session control block
**	09-Oct-1998 (jenjo02)
**	    Removed SCF semaphore functions, inlining the CS calls instead.
**	23-mar-1999 (thaju02)
**	    Modified '$Sess' to use #define DB_SESS_TEMP_OWNER. (B94067)
**      01-Dec-2000 (hanal04) Bug 100680 INGSRV 1123
**          If PSQ_RULE_UPD_PREFETCH is set turn on PSS_RULE_UPD_PREFETCH
**          in the session control block to signify that we should use
**          the prefetch stategy required to ensure consitent behaviour in
**          updating rules fired by updates.
**	10-Jan-2001 (jenjo02)
**	    Remove callback to SCF to get session id and ADF_CB;
**	    *ADF_CB now supplied by scsinit in PSQ_CB.
**	30-Jan-2004 (schka24)
**	    Get rid of a type-cast warning on adf cb.
**	3-Feb-2005 (schka24)
**	    Num-literals renamed to parser-compat, fix here.
**	15-june-06 (dougi)
**	    Add support for "before" triggers.
**	30-aug-06 (thaju02)
**	    If PSQ_RULE_DEL_PREFETCH is set turn on PSS_RULE_DEL_PREFETCH
**          in the session control block, for prefetch strategy to 
**          be applied for deletes. (B116355)
**	26-Oct-2009 (kiria01) SIR 121883
**	    Scalar sub-query support: Added copy of
**	    psq_flag.PSQ_NOCHK_SINGLETON_CARD to session flag
**	    for defaulting SET CARDINALITY_CHECK
**      November 2009 (stephenb)
**          Batch execution; initilization of new fields.
**      29-apr-2010 (stephenb)
**          Init batch_copy_optim.
**	04-may-2010 (miket) SIR 122403
**	    Init new sess_cb->pss_stmt_flags2.
**	19-May-2010 (kiria01) b123766
**	    Get cardinality check default from server block not psq_cb
**	21-Jul-2010 (kschendel) SIR 124104
**	    Initialize default compression from facility cb.
**	14-Oct-2010 (kschendel) SIR 124544
**	    Initialize default result structure from facility cb.
**	19-Nov-2010 (kiria01) SIR 124690
**	    Add support for setting installation wide collation defaults.
*/
DB_STATUS
psq_bgn_session(
	register PSQ_CB     *psq_cb,
	register PSS_SESBLK *sess_cb)
{
    i4		    err_code;
    i4			    i;
    DB_STATUS		    status = E_DB_OK;
    STATUS		    sem_status;
    i4		    sem_errno;
    bool		    leave_loop = TRUE;
    ULM_RCB		    ulm_rcb;

    /*
    ** No error to begin with.
    */
    psq_cb->psq_error.err_code = E_PS0000_OK;

    /*
    ** Do as much validity checking as possible before allocating any memory.
    ** That way, there won't be any cleaning up to do for the majority of
    ** errors.
    */

    /*
    ** Check for server initialized. This code could be placed within
    ** critical region, but this is not necessary, since this is a flag
    ** test.
    */
    if (!Psf_srvblk->psf_srvinit)
    {
	(VOID) psf_error(E_PS0205_SRV_NOT_INIT, 0L, PSF_CALLERR, &err_code,
	    &psq_cb->psq_error, 0);
	return (E_DB_ERROR);
    }

    /*
    ** Check for valid language spec.
    */
    if (psq_cb->psq_qlang != DB_QUEL && psq_cb->psq_qlang != DB_SQL)
    {
	(VOID) psf_error(E_PS0201_BAD_QLANG, 0L, PSF_CALLERR, &err_code,
	    &psq_cb->psq_error, 0);
	return (E_DB_ERROR);
    }
	
    /*
    ** Check whether language is allowed in this server.  This will be useful
    ** when we have configurable servers, where some query languages can be
    ** used and some can't. This code could be placed within a critical region
    ** but it is not necessary, since this is a flag test only.
    */
    if ((psq_cb->psq_qlang & Psf_srvblk->psf_lang_allowed) == 0)
    {
	(VOID) psf_error(E_PS0202_QLANG_NOT_ALLOWED, 0L, PSF_CALLERR, &err_code,
	    &psq_cb->psq_error, 0);
	return (E_DB_ERROR);
    }

    /*
    ** Make sure that the decimal character is actually specified.
    */
    if (!psq_cb->psq_decimal.db_decspec)
    {
	(VOID) psf_error(E_PS0203_NO_DECIMAL, 0L, PSF_CALLERR, &err_code,
	    &psq_cb->psq_error, 0);
	return (E_DB_ERROR);
    }

     /* Check distributed specification
    **
    ** a=local_server, b=distrib_server, c=distrib_session
    **
    **   a,b
    **
    **     00  01  11  10
    **    -----------------
    ** c  |   |   |   |   |
    **  0 | 1 | 1 | 0 | 0 |
    **    |   |   |   |   |
    **    -----------------  ==> ERROR
    **    |   |   |   |   |
    **  1 | 1 | 0 | 0 | 1 |
    **    |   |   |   |   |
    **    -----------------
    */
    if (   !(psq_cb->psq_distrib & (DB_1_LOCAL_SVR | DB_3_DDB_SESS))
	|| ((~psq_cb->psq_distrib & DB_2_DISTRIB_SVR)
	    && (psq_cb->psq_distrib & DB_3_DDB_SESS))
	)
    {
	psf_error(E_PS0204_BAD_DISTRIB, 0L, PSF_CALLERR, &err_code,
	    &psq_cb->psq_error,0);
	return (E_DB_ERROR);
    }

    /*
    ** Check for too many sessions in server at one time.
    ** This code must be executed as a critical region.
    */

    do		    /* something to break out of */
    {
	/* get the semaphore */
	if (sem_status = CSp_semaphore(1, &Psf_srvblk->psf_sem)) /* exclusive */
	{
	    status = E_DB_SEVERE;	/* abort the session */
	    sem_errno = E_PS020A_BGNSES_GETSEM_FAILURE;
	    break;
	}

	if (Psf_srvblk->psf_nmsess >= Psf_srvblk->psf_mxsess)
	{
	    (VOID) psf_error(E_PS0208_TOO_MANY_SESS, 0L, PSF_CALLERR, &err_code,
		&psq_cb->psq_error, 0);
	    status = E_DB_ERROR;
	    break;
	}

	/* Increment the session count */
	Psf_srvblk->psf_nmsess++;
	sess_cb->pss_psessid = ++Psf_srvblk->psf_sess_num;

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

    /* if semaphore has been successfully acquired, try to release it */
    if (sem_status == OK)
    {
	if (sem_status = CSv_semaphore(&Psf_srvblk->psf_sem))
	{
	    status = E_DB_FATAL;	/* bring down the server */
	    sem_errno = E_PS020B_BGNSES_RELSEM_FAILURE;
	}
    }

    /*
    ** if an error was encountered while trying to get or to release a
    ** semaphore, report it here
    */
    if (sem_status != OK)
    {
	(VOID) psf_error(sem_errno, sem_status, PSF_INTERR,
	    &err_code, &psq_cb->psq_error, 0);
    }

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

    /*
    ** Initialize the case translation semantics stuff
    */
    sess_cb->pss_dbxlate = psq_cb->psq_dbxlate;
    sess_cb->pss_cat_owner = psq_cb->psq_cat_owner;

    /*
    ** Copy the user name and dba name to the session control block.
    */
    STRUCT_ASSIGN_MACRO(psq_cb->psq_user.db_tab_own, sess_cb->pss_user);
    STRUCT_ASSIGN_MACRO(psq_cb->psq_dba, sess_cb->pss_dba);
    STRUCT_ASSIGN_MACRO(psq_cb->psq_group, sess_cb->pss_group);
    STRUCT_ASSIGN_MACRO(psq_cb->psq_aplid, sess_cb->pss_aplid);

    /* copy DBA name into sess_cb->pss_dbaname and NULL-terminate */
    {
	u_i2			dba_name_len;

	dba_name_len = (u_i2) psf_trmwhite((u_i4) sizeof(sess_cb->pss_dba),
			    (char *) &sess_cb->pss_dba);
	MEcopy((PTR) &sess_cb->pss_dba, dba_name_len,
	       (PTR) sess_cb->pss_dbaname);

	sess_cb->pss_dbaname[dba_name_len] = EOS;
    }

    /*
    ** Build a DB_OWN_NAME which contains a session-unique owner name. This
    ** owner name will be used for temporary tables which are owned by this
    ** session.
    */
    {
	char	    temp_sess_id[10];

	STmove(DB_SESS_TEMP_OWNER, ' ', sizeof(sess_cb->pss_sess_owner),
		(char *)&sess_cb->pss_sess_owner);
	/*
	** We can't convert directly into the sess_owner field because CVlx
	** null-terminates the result, and we don't want the trailing null
	*/
	CVlx(sess_cb->pss_psessid, temp_sess_id);
	MEcopy(temp_sess_id, 8, &sess_cb->pss_sess_owner.db_own_name[5]);
    }

    /*
    ** Start with per-user quota of memory.  Note that user may have overridden
    ** the default value at server startup in which case we will use calculated
    ** amount (pool/sessions); otherwise, default amount will be used.
    */
    sess_cb->pss_memleft = (Psf_srvblk->psf_sess_mem) ? Psf_srvblk->psf_sess_mem
						      : PSF_SESMEM;

    /*
    ** Initialize the user range table.
    */
    if (pst_rginit(&sess_cb->pss_usrrange) != E_DB_OK)
    {
	return (E_DB_FATAL);
    }
	
    /*
    ** Initialize the auxiliary range table.
    */
    if (pst_rginit(&sess_cb->pss_auxrng) != E_DB_OK)
    {
	return (E_DB_FATAL);
    }

    /*
    ** Open a memory stream for the symbol table.  The symbol table is
    ** composed of a list of blocks.
    ** Allocate the symbol table at the same time.
    */
    ulm_rcb.ulm_facility = DB_PSF_ID;
    ulm_rcb.ulm_poolid = Psf_srvblk->psf_poolid;
    ulm_rcb.ulm_blocksize = sizeof(PSS_SYMBLK);
    ulm_rcb.ulm_memleft = &sess_cb->pss_memleft;
    /* Set pointer to stream handle for ULM */
    ulm_rcb.ulm_streamid_p = &sess_cb->pss_symstr;
    /* Open a private, thread-safe stream */
    ulm_rcb.ulm_flags = ULM_PRIVATE_STREAM | ULM_OPEN_AND_PALLOC;
    ulm_rcb.ulm_psize = sizeof(PSS_SYMBLK);
    if (ulm_openstream(&ulm_rcb) != E_DB_OK)
    {
	if (ulm_rcb.ulm_error.err_code == E_UL0005_NOMEM)
	{
	    (VOID) psf_error(E_PS0F02_MEMORY_FULL, 0L, PSF_CALLERR, 
		&err_code, &psq_cb->psq_error, 0);
	}
	else
	{
	    (VOID) psf_error(E_PS0A02_BADALLOC, ulm_rcb.ulm_error.err_code,
		PSF_INTERR, &err_code, &psq_cb->psq_error, 0);
	}

	return((ulm_rcb.ulm_error.err_code == E_UL0004_CORRUPT) ? E_DB_FATAL
								: E_DB_ERROR);
    }

    sess_cb->pss_symtab = (PSS_SYMBLK*) ulm_rcb.ulm_pptr;
    sess_cb->pss_symtab->pss_sbnext = (PSS_SYMBLK *) NULL;

    /*
    ** Allocate the YACC_CB.  
    */

    if ((status = psl_yalloc(sess_cb->pss_symstr, 
	&sess_cb->pss_memleft,
	(PTR *) &sess_cb->pss_yacc, &psq_cb->psq_error)) != E_DB_OK)
    {
	/*
	** If the allocation failed, remember to close the streams, so the
	** memory associated with it will be freed.
	*/
	(VOID) ulm_closestream(&ulm_rcb);
	return (status);
    }
	
    /*
    ** Fill in the control block header.
    */
    sess_cb->pss_next = (PSS_SESBLK *) NULL;
    sess_cb->pss_prev = (PSS_SESBLK *) NULL;
    sess_cb->pss_length = sizeof(PSS_SESBLK);
    sess_cb->pss_type = PSS_SBID;
    sess_cb->pss_owner = (PTR)DB_PSF_ID;
    sess_cb->pss_ascii_id = PSSSES_ID;

    /*
    ** Initialize the session control block.
    */
    /* Save the session id */
    sess_cb->pss_sessid	    = psq_cb->psq_sessid;

    /* Set pointer to session's ADF_CB */
    sess_cb->pss_adfcb	    = (ADF_CB *) psq_cb->psq_adfcb;

    /* No cursors yet */
    sess_cb->pss_numcursors = 0;

    /* Language has already been validated */
    sess_cb->pss_lang = psq_cb->psq_qlang;

    /* Decimal spec has already been validated */
    sess_cb->pss_decimal = psq_cb->psq_decimal.db_decimal;

    /* Distributed spec has already been validated */
    sess_cb->pss_distrib = psq_cb->psq_distrib;

    /* Save the database id */
    sess_cb->pss_dbid = psq_cb->psq_dbid;

    /* Save the unique database id */
    sess_cb->pss_udbid = psq_cb->psq_udbid;

    /* Initialize QSF_RCB for use by psfmem.c functions */
    sess_cb->pss_qsf_rcb.qsf_type = QSFRB_CB;
    sess_cb->pss_qsf_rcb.qsf_ascii_id = QSFRB_ASCII_ID;
    sess_cb->pss_qsf_rcb.qsf_length = sizeof(sess_cb->pss_qsf_rcb);
    sess_cb->pss_qsf_rcb.qsf_owner = (PTR)DB_PSF_ID;
    sess_cb->pss_qsf_rcb.qsf_sid = sess_cb->pss_sessid;

    /*
    **	so session reset all bit flags
    */
    sess_cb->pss_stmt_flags = sess_cb->pss_stmt_flags2 =
	sess_cb->pss_dbp_flags = sess_cb->pss_ses_flag = 0L;
    sess_cb->pss_flattening_flags = 0;

    /*
    ** Default table create semantics are to assume journaling unless
    ** the PSF_NO_JNL_DEFAULT override is set.
    */
    if ((Psf_srvblk->psf_flags & PSF_NO_JNL_DEFAULT) == 0)
	sess_cb->pss_ses_flag |= PSS_JOURNALING;

	    /* catalog update flag */
    if (psq_cb->psq_flag & PSQ_CATUPD)
	sess_cb->pss_ses_flag |= PSS_CATUPD;

	    /* warnings on unsupported commands */
    if (psq_cb->psq_flag & PSQ_WARNINGS)
	sess_cb->pss_ses_flag |= PSS_WARNINGS;

	/* INDICATE if the DBA may DROP everyone's tables */
    if (psq_cb->psq_flag & PSQ_DBA_DROP_ALL)
	sess_cb->pss_ses_flag |= PSS_DBA_DROP_ALL;

	/* INDICATE if the session may SELECT everyone's tables */
    if (psq_cb->psq_flag & PSQ_SELECT_ALL)
	sess_cb->pss_ses_flag |= PSS_SELECT_ALL;

	/*
	** indicate that the session is allowed to INSERT/DELETE/UPDATE an index
	** which is a catalog (but not an extended catalog
	*/
    if (psq_cb->psq_flag & PSQ_REPAIR_SYSCAT)
	sess_cb->pss_ses_flag |= PSS_REPAIR_SYSCAT;

	/* 
	** indicate that the session allows $ingres to drop/add constraint on
	** tables owned by other users
	*/
    if (psq_cb->psq_flag & PSQ_INGRES_PRIV)
	sess_cb->pss_ses_flag |= PSS_INGRES_PRIV;	

    if (psq_cb->psq_flag & PSQ_ROW_SEC_KEY)
	sess_cb->pss_ses_flag |= PSS_ROW_SEC_KEY;

    /* See if passwords, roles allowed */
    if (psq_cb->psq_flag & PSQ_PASSWORD_NONE)
	sess_cb->pss_ses_flag |= PSS_PASSWORD_NONE;

    if (psq_cb->psq_flag & PSQ_ROLE_NONE)
	sess_cb->pss_ses_flag |= PSS_ROLE_NONE;

    if (psq_cb->psq_flag & PSQ_ROLE_NEED_PW)
	sess_cb->pss_ses_flag |= PSS_ROLE_NEED_PW;

	/* remember whether we are running UPGRADEDB */
    if (psq_cb->psq_flag & PSQ_RUNNING_UPGRADEDB)
	sess_cb->pss_ses_flag |= PSS_RUNNING_UPGRADEDB;

    /* Pick up serverwide default for card check */
    if (Psf_srvblk->psf_flags & PSF_NOCHK_SINGLETON_CARD)
	sess_cb->pss_ses_flag |= PSS_NOCHK_SINGLETON_CARD;

        /* Initialize pss_project. */
    sess_cb->pss_ses_flag |= PSS_PROJECT;	/* pss_project = TRUE */
    
    /* init last statement */
    sess_cb->pss_last_sname[0] = EOS;
    /* batch optimization switch starts undefined */
    sess_cb->batch_copy_optim = PSS_BATCH_OPTIM_UNDEF;

    /* 
    ** if starting a local session, determine whether the database is being 
    ** journaled
    */
    if (~psq_cb->psq_distrib & DB_3_DDB_SESS)
    {
        DMC_CB		    dmc_cb, *dmc = &dmc_cb;
        DMC_CHAR_ENTRY	    dmc_char;

	MEfill(sizeof(dmc_cb), (u_char) 0, (PTR) dmc);

        dmc->type = DMC_CONTROL_CB;
        dmc->length = sizeof(*dmc);
        dmc->dmc_op_type = DMC_DATABASE_OP;
	dmc->dmc_session_id = (PTR) sess_cb->pss_sessid;
        dmc->dmc_flags_mask = DMC_JOURNAL;
        dmc->dmc_char_array.data_address= (PTR) &dmc_char;
	dmc->dmc_char_array.data_out_size = sizeof(dmc_char);
	dmc->dmc_db_id = (char *) sess_cb->pss_dbid;
	
	status = dmf_call(DMC_SHOW, (PTR) dmc);
	if (DB_FAILURE_MACRO(status))
	{
	    (VOID) psf_error(E_PS020E_CANT_GET_DB_JOUR_STATUS, 
		dmc->error.err_code, PSF_INTERR, &err_code, 
		&psq_cb->psq_error, 0);
	    return(status);
	}

	if (dmc_char.char_value == DMC_C_ON)
	{
	    sess_cb->pss_ses_flag |= PSS_JOURNALED_DB;
	}
    }

    /* Save the storage structure for indexes */
    sess_cb->pss_idxstruct = psq_cb->psq_idxstruct;

    /* Make session copy of parser compatability settings */
    sess_cb->pss_parser_compat = psq_cb->psq_parser_compat;

    /* remember if NLs inside string constants need to be stripped */
    if (psq_cb->psq_flag & PSQ_STRIP_NL_IN_STRCONST)
	sess_cb->pss_ses_flag |= PSS_STRIP_NL_IN_STRCONST;

    /* no rule tree yet */
    sess_cb->pss_row_lvl_usr_rules  =
    sess_cb->pss_row_lvl_sys_rules  =
    sess_cb->pss_stmt_lvl_usr_rules =
    sess_cb->pss_stmt_lvl_sys_rules =
    sess_cb->pss_row_lvl_usr_before_rules  =
    sess_cb->pss_row_lvl_sys_before_rules  =
    sess_cb->pss_stmt_lvl_usr_before_rules =
    sess_cb->pss_stmt_lvl_sys_before_rules = (PST_STATEMENT *) NULL;

    if (psq_cb->psq_flag & PSQ_RULE_DEL_PREFETCH)
	sess_cb->pss_ses_flag |= PSS_RULE_DEL_PREFETCH;

    if(psq_cb->psq_flag2 & PSQ_RULE_UPD_PREFETCH)
        sess_cb->pss_ses_flag |= PSS_RULE_UPD_PREFETCH;

    /* copy user status flags to session control block */
    sess_cb->pss_ustat = psq_cb->psq_ustat;

    /*
    ** Initialize lots of pointer to NULL because nothing is happening yet.
    */
    sess_cb->pss_qbuf = sess_cb->pss_nxtchar = sess_cb->pss_prvtok =
	sess_cb->pss_bgnstmt = sess_cb->pss_endbuf =
	sess_cb->pss_prvgoval = (u_char *) NULL;

    /* initialize pss_audit */
    sess_cb->pss_audit = NULL;

    for (i = 0; i < PSS_CURTABSIZE; i++)
    {
	sess_cb->pss_curstab.pss_curque[i] = (PSC_CURBLK *) NULL;
    }

    /* initialize prototype list for dynamic SQL */
    sess_cb->pss_proto = (PST_PROTO *) NULL;

    /*
    ** pss_dependencies_stream, when not NULL, is expected to point at a valid
    ** stream descriptor.  After closing the stream we always reset
    ** pss_dependencies_stream to NULL, but in some cases we may end up checking
    ** pss_dependencies_stream before ever opening (and closing it).  As a
    ** result, you may end up using invalid address as a stream pointer.
    ** Initializing it here to NULL will ensure that it is non-NULL iff it
    ** points at a valid open stream descriptor.
    */
    sess_cb->pss_dependencies_stream = (PSF_MSTREAM *) NULL;

    /* No trace flags set */
    /* expect lint message */
    ult_init_macro(&sess_cb->pss_trace, PSS_TBITS, PSS_TVALS, PSS_TVAO);

    /* Cursor id set to 0, no cursors open yet */
    sess_cb->pss_crsid = 0;

    sess_cb->pss_create_compression = Psf_srvblk->psf_create_compression;

    /* SCF can pass a client requested result_structure, but if it
    ** doesn't, init from server default.
    */
    if (psq_cb->psq_result_struct != 0)
    {
	sess_cb->pss_result_struct = psq_cb->psq_result_struct;
	sess_cb->pss_result_compression = psq_cb->psq_result_compression;
    }
    else
    {
	sess_cb->pss_result_struct = Psf_srvblk->psf_result_struct;
	sess_cb->pss_result_compression = Psf_srvblk->psf_result_compression;
    }

    if (psq_cb->psq_def_coll > DB_NOCOLLATION)
	sess_cb->pss_def_coll = psq_cb->psq_def_coll;
    else
	sess_cb->pss_def_coll = Psf_srvblk->psf_def_coll;
    if (psq_cb->psq_def_unicode_coll > DB_NOCOLLATION)
	sess_cb->pss_def_unicode_coll = psq_cb->psq_def_unicode_coll;
    else
	sess_cb->pss_def_unicode_coll = Psf_srvblk->psf_def_unicode_coll;

    return (E_DB_OK);
}
コード例 #13
0
ファイル: gwfidx.c プロジェクト: fosslc/Ingres
/*{
** Name: gwi_remove - remove a gateway index
**
** Description:
**	This function removes extended gateway index catalog information.  A
**	DMF external interface is used to update, namely delete, the extended
**	gateway index catalog, iigwX_index. This request must be made before
**	gateway index removal can be considered complete.
**
**	The GWF tcb cache for the base table is discarded since it is no longer
**	current.
**
** Inputs:
**	gw_rcb->		gateway request control block
**		session_id	an established session id
**		dmu->
**		  dmu_db_id	database id
**		  dmu_tran_id	transaction id
**		  dmu_tbl_id	base table id
**		  dmu_idx_id	INGRES index id
**		gw_id		gateway id, derived from DBMS type
**
** Output:
**	gw_rcb->
**		error.err_code	One of the following error numbers.
**                              E_GW0600_NO_MEM
**				E_GW0400_BAD_GWID
**				E_GW0006_XIDX_OPEN_FAILED
**      Returns:
**          E_DB_OK             Function completed normally. 
**          E_DB_ERROR          Function completed abnormally with 
**                              error.err_code.
** History:
**      28-Apr-1989 (alexh)
**          Created.
**	2-apr-90 (bryanp)
**	    If this gateway has no extended system catalogs, nothing to do.
**	09-apr-90 (linda)
**	    Added error handling, single return point.
**	18-apr-90 (bryanp)
**	    Return E_GW0600_NO_MEM when out of ULM memory.
**	28-mar-91 (linda)
**	    Fixed 2 problems:  (a) error on tuple delete from dmf was logged
**	    but did not cause this routine to return a bad status; (b) call to
**	    DMR_DELETE required DMR_CURRENT_POS in flags mask.
**      7-oct-92 (daveb)
**          prototyped.  Cast arg to gwu_copen (db_id is PTR).
*/
DB_STATUS
gwi_remove(GW_RCB *gw_rcb)
{
    GW_SESSION	    *session = (GW_SESSION *)gw_rcb->gwr_session_id;
    DMT_CB	    dmt;
    DMR_CB	    dmr;
    ULM_RCB	    ulm_rcb;
    DM_DATA	    xidx_buff;
    i4	    gw_id = gw_rcb->gwr_gw_id;
    i4		    xidx_sz = Gwf_facility->gwf_gw_info[gw_id].gwf_xidx_sz;
    DMR_ATTR_ENTRY  attkey[2];
    DMR_ATTR_ENTRY  *attkey_ptr[2];
    DB_TAB_ID	    sav_idx_id;
    DB_ERROR	    err;
    DB_STATUS	    status;
    DB_STATUS	    sav_status;

    for (;;)
    {
	if ((gw_id <= 0) || (gw_id >= GW_GW_COUNT) ||
	    (Gwf_facility->gwf_gw_info[gw_id].gwf_gw_exist == 0))
	{
	    (VOID) gwf_error(E_GW0400_BAD_GWID, (i4)0, GWF_INTERR, 1,
			     sizeof(gw_rcb->gwr_gw_id), &gw_rcb->gwr_gw_id);
	    gw_rcb->gwr_error.err_code = E_GW0208_GWI_REGISTER_ERROR;
	    status = E_DB_ERROR;
	    break;
	}

	if (xidx_sz == 0)
	{
	    status = E_DB_OK;
	    break;
	}

	/* copy ulm_rcb */
	STRUCT_ASSIGN_MACRO(session->gws_ulm_rcb, ulm_rcb);
	xidx_buff.data_in_size = xidx_sz;
	ulm_rcb.ulm_blocksize = xidx_buff.data_in_size;

	/* allocate a iigwX_index buffer from a temporary  memory stream */
	if ((status = ulm_openstream(&ulm_rcb)) != E_DB_OK)
	{
	    (VOID) gwf_error(ulm_rcb.ulm_error.err_code, GWF_INTERR, 0);
	    (VOID) gwf_error(E_GW0312_ULM_OPENSTREAM_ERROR, GWF_INTERR, 3,
			     sizeof(*ulm_rcb.ulm_memleft),
			     ulm_rcb.ulm_memleft,
			     sizeof(ulm_rcb.ulm_sizepool),
			     &ulm_rcb.ulm_sizepool,
			     sizeof(ulm_rcb.ulm_blocksize),
			     &ulm_rcb.ulm_blocksize);
	    if (ulm_rcb.ulm_error.err_code == E_UL0005_NOMEM)
		gw_rcb->gwr_error.err_code = E_GW0600_NO_MEM;
	    else
		gw_rcb->gwr_error.err_code = E_GW0209_GWI_REMOVE_ERROR;
	    break;
	}

	ulm_rcb.ulm_psize = ulm_rcb.ulm_blocksize;
	if ((status = ulm_palloc(&ulm_rcb)) != E_DB_OK)
	{
	    (VOID) gwf_error(ulm_rcb.ulm_error.err_code, GWF_INTERR, 0);
	    (VOID) gwf_error(E_GW0314_ULM_PALLOC_ERROR, GWF_INTERR, 4,
			     sizeof(*ulm_rcb.ulm_memleft),
			     ulm_rcb.ulm_memleft,
			     sizeof(ulm_rcb.ulm_sizepool),
			     &ulm_rcb.ulm_sizepool,
			     sizeof(ulm_rcb.ulm_blocksize),
			     &ulm_rcb.ulm_blocksize,
			     sizeof(ulm_rcb.ulm_psize),
			     &ulm_rcb.ulm_psize);
	    if (ulm_rcb.ulm_error.err_code == E_UL0005_NOMEM)
		gw_rcb->gwr_error.err_code = E_GW0600_NO_MEM;
	    else
		gw_rcb->gwr_error.err_code = E_GW0209_GWI_REMOVE_ERROR;

	    if ((status = ulm_closestream(&ulm_rcb)) != E_DB_OK)
	    {
		(VOID) gwf_error(ulm_rcb.ulm_error.err_code, GWF_INTERR, 0);
		(VOID) gwf_error(E_GW0313_ULM_CLOSESTREAM_ERROR, GWF_INTERR, 1,
				 sizeof(*ulm_rcb.ulm_memleft),
				 ulm_rcb.ulm_memleft);
	    }
	    status = E_DB_ERROR;    /* reset after closestream call */
	    break;
	}

	xidx_buff.data_address = ulm_rcb.ulm_pptr;

	/* initialize dmt_sequence */
	dmt.dmt_sequence = gw_rcb->gwr_gw_sequence;

	/* set up position for iigwXX_index catalog*/
	attkey[0].attr_number = 1;
	attkey[0].attr_operator = DMR_OP_EQ;
	attkey[0].attr_value = (char *)&gw_rcb->gwr_tab_id.db_tab_base;
	attkey[1].attr_number = 2;
	attkey[1].attr_operator = DMR_OP_EQ;
	attkey[1].attr_value = (char *)&gw_rcb->gwr_tab_id.db_tab_index;

	attkey_ptr[0] = &attkey[0];
	attkey_ptr[1] = &attkey[1];

	dmr.type = DMR_RECORD_CB;
	dmr.length = sizeof(DMR_CB);
	dmr.dmr_flags_mask = 0;
	dmr.dmr_position_type = DMR_QUAL;
	dmr.dmr_attr_desc.ptr_in_count = 2;
	dmr.dmr_attr_desc.ptr_size = sizeof(DMR_ATTR_ENTRY);
	dmr.dmr_attr_desc.ptr_address = (PTR)&attkey_ptr[0];
	dmr.dmr_access_id = dmt.dmt_record_access_id;
	dmr.dmr_q_fcn = NULL;

	/* open the iigwX_index catalog */
	if ((status = gwu_copen(&dmt, &dmr, session->gws_scf_session_id, 
		(PTR)gw_rcb->gwr_database_id, gw_id, gw_rcb->gwr_xact_id,
		&gw_rcb->gwr_tab_id,
		&session->gws_gw_info[gw_id].gws_xidx_tab_name,
		DMT_A_WRITE, TRUE, &err)) != E_DB_OK)
	{
	    switch (dmt.error.err_code)
	    {
		case    E_DM0042_DEADLOCK:
		    gw_rcb->gwr_error.err_code = E_GW0327_DMF_DEADLOCK;
		    break;

		default:
		    (VOID) gwf_error(err.err_code, GWF_INTERR, 0);
		    gw_rcb->gwr_error.err_code = E_GW0209_GWI_REMOVE_ERROR;
		    break;
	    }

	    if ((status = ulm_closestream(&ulm_rcb)) != E_DB_OK)
	    {
		(VOID) gwf_error(ulm_rcb.ulm_error.err_code, GWF_INTERR, 0);
		(VOID) gwf_error(E_GW0313_ULM_CLOSESTREAM_ERROR, GWF_INTERR, 1,
				 sizeof(*ulm_rcb.ulm_memleft),
				 ulm_rcb.ulm_memleft);
		gw_rcb->gwr_error.err_code = E_GW0209_GWI_REMOVE_ERROR;
	    }
	    break;
	}

	dmr.dmr_flags_mask = DMR_NEXT;
	STRUCT_ASSIGN_MACRO(xidx_buff, dmr.dmr_data);
	dmr.dmr_char_array.data_address = 0;

	/*
	**	Delete the index entry with index and base table id
	*/
	do
	{
	    status = (*Dmf_cptr)(DMR_GET, &dmr);
	}
	while (status == E_DB_OK &&
		MEcmp((PTR)dmr.dmr_data.data_address,
		      (PTR)&gw_rcb->gwr_tab_id,
		      sizeof(DB_TAB_ID))
		);

	if (status == E_DB_OK)
	{
	    dmr.dmr_flags_mask |= DMR_CURRENT_POS;
	    if ((status = (*Dmf_cptr)(DMR_DELETE, &dmr)) != E_DB_OK)
	    {
		switch (dmt.error.err_code)
		{
		    case    E_DM0042_DEADLOCK:
			gw_rcb->gwr_error.err_code = E_GW0327_DMF_DEADLOCK;
			break;

		    default:
			(VOID) gwf_error(dmr.error.err_code, GWF_INTERR, 0);
			(VOID) gwf_error(E_GW0322_DMR_DELETE_ERROR, GWF_INTERR,
				     2, sizeof(gw_rcb->gwr_tab_id.db_tab_base),
				     &gw_rcb->gwr_tab_id.db_tab_base,
				     sizeof(gw_rcb->gwr_tab_id.db_tab_index),
				     &gw_rcb->gwr_tab_id.db_tab_index);
			gw_rcb->gwr_error.err_code = E_GW0209_GWI_REMOVE_ERROR;
			break;
		}
		if (dmt.error.err_code == E_DM0042_DEADLOCK)
			break;
		/* (Else no break; we still want to close index catalog.) */
	    }
	}
	else	/* status != E_DB_OK */
	{
	    switch (dmt.error.err_code)
	    {
		case    E_DM0042_DEADLOCK:
		    gw_rcb->gwr_error.err_code = E_GW0327_DMF_DEADLOCK;
		    break;

		default:
		    (VOID) gwf_error(dmr.error.err_code, GWF_INTERR, 0);
		    (VOID) gwf_error(E_GW0321_DMR_GET_ERROR, GWF_INTERR, 2,
				     sizeof(gw_rcb->gwr_tab_id.db_tab_base),
				     &gw_rcb->gwr_tab_id.db_tab_base,
				     sizeof(gw_rcb->gwr_tab_id.db_tab_index),
				     &gw_rcb->gwr_tab_id.db_tab_index);
		    gw_rcb->gwr_error.err_code = E_GW0209_GWI_REMOVE_ERROR;
		    break;
	    }
	    if (dmt.error.err_code == E_DM0042_DEADLOCK)
		    break;
	    /* (Else no break; we still want to close index catalog.) */
	}

	sav_status = status;	/* in case of non-deadlock error above */

	if ((status = (*Dmf_cptr)(DMT_CLOSE, &dmt)) != E_DB_OK)
	{
	    switch (dmt.error.err_code)
	    {
		case    E_DM0042_DEADLOCK:
		    gw_rcb->gwr_error.err_code = E_GW0327_DMF_DEADLOCK;
		    break;

		default:
		    (VOID) gwf_error(dmt.error.err_code, GWF_INTERR, 0);
		    (VOID) gwf_error(E_GW0325_DMT_CLOSE_ERROR, GWF_INTERR, 2,
				     sizeof(dmt.dmt_id.db_tab_base),
				     &dmt.dmt_id.db_tab_base,
				     sizeof(dmt.dmt_id.db_tab_index),
				     &dmt.dmt_id.db_tab_index);
		    gw_rcb->gwr_error.err_code = E_GW0209_GWI_REMOVE_ERROR;
		    break;
	    }
	}

	/* 
	**  delete tcb from GWF cache since its index info cannot be current.
	*/
	/*
	** First save index's tab_id, set base to 0 for call.
	*/
	_VOID_ MEcopy((PTR)&gw_rcb->gwr_tab_id, sizeof(DB_TAB_ID),
		      (PTR)&sav_idx_id);
	gw_rcb->gwr_tab_id.db_tab_index = 0;

	if ((status = gwu_deltcb(gw_rcb, GWU_TCB_OPTIONAL, &err)) != E_DB_OK)
	{
	    (VOID) gwf_error(err.err_code, GWF_INTERR, 0);
	    gw_rcb->gwr_error.err_code = E_GW0209_GWI_REMOVE_ERROR;
	    _VOID_ MEcopy((PTR)&sav_idx_id, sizeof(DB_TAB_ID),
			  (PTR)&gw_rcb->gwr_tab_id);
	    break;
	}
	_VOID_ MEcopy((PTR)&sav_idx_id, sizeof(DB_TAB_ID),
		      (PTR)&gw_rcb->gwr_tab_id);

	if ((status = ulm_closestream(&ulm_rcb)) != E_DB_OK)
	{
	    (VOID) gwf_error(ulm_rcb.ulm_error.err_code, GWF_INTERR, 0);
	    (VOID) gwf_error(E_GW0313_ULM_CLOSESTREAM_ERROR, GWF_INTERR, 1,
			     sizeof(ulm_rcb.ulm_error.err_code),
			     &ulm_rcb.ulm_error.err_code);
	    gw_rcb->gwr_error.err_code = E_GW0209_GWI_REMOVE_ERROR;
	    break;
	}

	/*
	** If we get here, things went okay after the tuple delete.  Recheck
	** status from that call.
	*/
	if (sav_status == E_DB_OK)
	{
	    gw_rcb->gwr_error.err_code = E_DB_OK;
	}
	else
	{
	    status = sav_status;
	    gw_rcb->gwr_error.err_code = E_GW0209_GWI_REMOVE_ERROR;
	}
	break;
    }

    return(status);
}
コード例 #14
0
ファイル: gwfidx.c プロジェクト: fosslc/Ingres
/*
** Name: gwi_register - register a gateway index
**
** Description:
**	This function registers extended gateway  index catalog information.  A
**	DMF external interface is used to update, namely put, the extended
**	gateway catalog,  iigwX_index.  This request  must be made before
**	gateway index registration can be considered complete.
**
**	The GWF tcb cache for the base table is discarded since it is no longer
**	current.
**
** Inputs:
**	gw_rcb->		gateway request control block
**		session_id	an established session id
**		dmu->
**		  dmu_db_id	database id
**		  dmu_tran_id	transaction id
**		  dmu_tbl_id	base table id
**		  dmu_idx_id	INGRES index id
**		gw_id		gateway id, derived from DBMS type
**		in_vdata2	source of the gateway index.
**
** Output:
**	gw_rcb->
**		error.err_code	One of the following error numbers.
**                              E_GW0600_NO_MEM
**				E_GW0400_BAD_GWID
**				E_GW0208_GWI_REGISTER_ERROR
**				E_GW0006_XIDX_OPEN_FAILED
**      Returns:
**          E_DB_OK             Function completed normally. 
**          E_DB_ERROR          Function completed abnormally with 
**                              error.err_code.
** History:
**      28-Apr-1989 (alexh)
**          Created.
**	2-apr-90 (bryanp)
**	    If gateway has no extended system catalog, nothing to do.
**	09-apr-90 (linda)
**	    Add error handling and single return point.
**	18-apr-90 (bryanp)
**	    Return E_GW0600_NO_MEM when out of ULM memory.
**	1-jul-91 (rickh)
**	    If the gateway exit returns an error, don't clobber the status
**	    word when we close the stream!  Also, if the exit has already
**	    reported the problem, spare us the uninformative yet alarming
**	    error-babble of higher facilities.
**	7-oct-92 (robf)
**	    Still create Xrelation & Xattribute entries even if no Xindex
**	    table - a gateway may need rel/attr entires but not the
**	    index one
**      7-oct-92 (daveb)
**          Hand the exit the session pointer, in case it wants to add
**          an exit-private SCB.  Prototyped.  Removed dead vars xrel_sz
**          and sav_idx_id.  Cast db_id arg to gwu_copen; it's a PTR.
**	17-nov-92 (robf)
**	    Changed calls to gwf_display() to use array rather than
**	    arg list.
*/
DB_STATUS
gwi_register(GW_RCB *gw_rcb)
{
    GWX_RCB	gwx;
    ULM_RCB	ulm_rcb;
    GW_SESSION	*session = (GW_SESSION *)gw_rcb->gwr_session_id;
    DMT_CB	dmt;
    DMR_CB	dmr;
    i4     gw_id = gw_rcb->gwr_gw_id;
    i4          xidx_sz = Gwf_facility->gwf_gw_info[gw_id].gwf_xidx_sz;
    DB_STATUS	status;
    DB_STATUS	ulm_status;
    DB_ERROR	err;
    char	trbuf[GWF_MAX_MSGLEN + 1]; /* last char for `\n' */

    if(GWF_MAIN_MACRO(12))
    {
	gwf_display(gwf_scctalk, 0, trbuf, sizeof(trbuf) - 1,
	    "GWI_REGISTER: REGISTER INDEX entry\n");
    }
    for (;;)
    {
	if ((gw_id <= 0) || (gw_id >= GW_GW_COUNT) ||
	    (Gwf_facility->gwf_gw_info[gw_id].gwf_gw_exist == 0))
	{
	    (VOID) gwf_error(E_GW0400_BAD_GWID, (i4)0, GWF_INTERR, 1,
			     sizeof(gw_id), &gw_id);
	    gw_rcb->gwr_error.err_code = E_GW0208_GWI_REGISTER_ERROR;
	    status = E_DB_ERROR;
	    break;
	}
	/*
	** Allocate a memory stream for the life of this operation.  Used as
	** storage for temporary structures.  Note that it is allocated from
	** the session's GWF memory stream.
	*/
	STRUCT_ASSIGN_MACRO(session->gws_ulm_rcb, ulm_rcb);
	ulm_rcb.ulm_blocksize = xidx_sz;
	if ((status = ulm_openstream(&ulm_rcb)) != E_DB_OK)
	{
		(VOID) gwf_error(ulm_rcb.ulm_error.err_code, GWF_INTERR, 0);
		(VOID) gwf_error(E_GW0312_ULM_OPENSTREAM_ERROR, GWF_INTERR, 3,
			 sizeof(*ulm_rcb.ulm_memleft),
			 ulm_rcb.ulm_memleft,
			 sizeof(ulm_rcb.ulm_sizepool),
			 &ulm_rcb.ulm_sizepool,
			 sizeof(ulm_rcb.ulm_blocksize),
			 &ulm_rcb.ulm_blocksize);
		if (ulm_rcb.ulm_error.err_code == E_UL0005_NOMEM)
			gw_rcb->gwr_error.err_code = E_GW0600_NO_MEM;
		else
			gw_rcb->gwr_error.err_code = E_GW0208_GWI_REGISTER_ERROR;
		break;
	}
	/*
	**	Only process extended index info if this gateway has an
	**	extended index catalog
	*/
	if (Gwf_facility->gwf_gw_info[gw_id].gwf_xidx_sz > 0)
	{

	    gwx.xrcb_tab_id = &gw_rcb->gwr_tab_id;
/*	    STRUCT_ASSIGN_MACRO(gw_rcb->gwr_tab_id, gwx.xrcb_tab_id);    */
	    gwx.xrcb_gw_id = gw_id;
	    STRUCT_ASSIGN_MACRO(gw_rcb->gwr_in_vdata2, gwx.xrcb_var_data2);


	    /* allocate iigwX_index tuple buffer */
	    gwx.xrcb_var_data1.data_in_size =
	        ulm_rcb.ulm_psize = ulm_rcb.ulm_blocksize; 
	    if ((status = ulm_palloc(&ulm_rcb)) != E_DB_OK)
	    {
	        (VOID) gwf_error(ulm_rcb.ulm_error.err_code, GWF_INTERR, 0);
	        (VOID) gwf_error(E_GW0314_ULM_PALLOC_ERROR, GWF_INTERR, 4,
	    		     sizeof(*ulm_rcb.ulm_memleft),
	    		     ulm_rcb.ulm_memleft,
	    		     sizeof(ulm_rcb.ulm_sizepool),
	    		     &ulm_rcb.ulm_sizepool,
	    		     sizeof(ulm_rcb.ulm_blocksize),
	    		     &ulm_rcb.ulm_blocksize,
	    		     sizeof(ulm_rcb.ulm_psize),
	    		     &ulm_rcb.ulm_psize);
	        if (ulm_rcb.ulm_error.err_code == E_UL0005_NOMEM)
	    	gw_rcb->gwr_error.err_code = E_GW0600_NO_MEM;
	        else
	    	gw_rcb->gwr_error.err_code = E_GW0208_GWI_REGISTER_ERROR;
	        break;
	    }
	    gwx.xrcb_var_data1.data_address = ulm_rcb.ulm_pptr;

	    /* request exit format */
	    if ((status =
	    	(*Gwf_facility->gwf_gw_info[gw_id].gwf_gw_exits	[GWX_VIDXF])
	    	    (&gwx)) !=  E_DB_OK)
	    {
	        if ( gwx.xrcb_error.err_code == E_GW050E_ALREADY_REPORTED )
	        {
			gw_rcb->gwr_error.err_code = E_GW050E_ALREADY_REPORTED;
	        }
	        else
	        {
			(VOID) gwf_error(gwx.xrcb_error.err_code, GWF_INTERR, 0);
			gw_rcb->gwr_error.err_code = E_GW0208_GWI_REGISTER_ERROR;
	        }

	        if ((ulm_status = ulm_closestream(&ulm_rcb)) != E_DB_OK)
	        {
			(VOID) gwf_error(ulm_rcb.ulm_error.err_code, GWF_INTERR, 0);
			(VOID) gwf_error(E_GW0313_ULM_CLOSESTREAM_ERROR, GWF_INTERR, 1,
					 sizeof(*ulm_rcb.ulm_memleft),
					 ulm_rcb.ulm_memleft);
			break;
	        }

	        break;
	    }
	    else
	    {
	        /* initialize dmt_sequence */
	        dmt.dmt_sequence = gw_rcb->gwr_gw_sequence;

	        /* request DMF to append tuples */
	        status = gwu_copen(&dmt, &dmr, session->gws_scf_session_id, 
	            (PTR) gw_rcb->gwr_database_id, gw_id, gw_rcb->gwr_xact_id,
	            &gw_rcb->gwr_tab_id,
		    &session->gws_gw_info[gw_id].gws_xidx_tab_name,
	            DMT_A_WRITE, FALSE, &err);

	        /* put the iigwX_index tuple */
	        if ( status == E_DB_OK)
	        {
	    	STRUCT_ASSIGN_MACRO(gwx.xrcb_var_data1, dmr.dmr_data);
	    	if ((status = (*Dmf_cptr)(DMR_PUT, &dmr)) == E_DB_OK)
	    	{
	    	    status = (*Dmf_cptr)(DMT_CLOSE, &dmt);
	    	    if (status != E_DB_OK)
	    	    {
	    		/* Handle error from close */
	    		(VOID) gwf_error(dmt.error.err_code, GWF_INTERR, 0);
	    		gw_rcb->gwr_error.err_code =
	    			    E_GW0208_GWI_REGISTER_ERROR;
	    		break;
	    	    }
	    	}
	    	else
	    	{
	    	    /* Handle error from put */
	    	    switch (dmt.error.err_code)
	    	    {
	    		case    E_DM0042_DEADLOCK:
	    		    gw_rcb->gwr_error.err_code = E_GW0327_DMF_DEADLOCK;
	    		    break;

	    		default:
	    		    (VOID) gwf_error(dmt.error.err_code, GWF_INTERR, 0);
	    		    gw_rcb->gwr_error.err_code =
	    				E_GW0208_GWI_REGISTER_ERROR;
	    		    break;
	    	    }
	    	    break;
	    	}
	        }
	        else
	        {
			/* Handle error from gwu_copen() */
			(VOID) gwf_error(err.err_code, GWF_INTERR, 0);
			gw_rcb->gwr_error.err_code = E_GW0208_GWI_REGISTER_ERROR;
			break;
	        }

	        /* 
	        **	delete tcb from GWF cache since its index info cannot be
	        **	current.
	        **
	        **** Not clear that we care about this. We probably can't remove
	        **** an index if it is being used and it is only referenced in its
	        **** own tcb.
	        */
#if 0
	        /*
	        ** Save the index's table id, set db_tab_index to 0 for the call.
	        */
	        _VOID_ MEcopy((PTR)&gw_rcb->gwr_tab_id, sizeof(DB_TAB_ID),
	    		  (PTR)&sav_idx_id);
	        gw_rcb->gwr_tab_id.db_tab_index = 0;

	        if ((status = gwu_deltcb(gw_rcb, GWU_TCB_OPTIONAL, &err))
	    	    != E_DB_OK)
	        {
			(VOID) gwf_error(err.err_code, GWF_INTERR, 0);
			gw_rcb->gwr_error.err_code = E_GW0208_GWI_REGISTER_ERROR;
			_VOID_ MEcopy((PTR)&sav_idx_id, sizeof(DB_TAB_ID),
	    		      (PTR)&gw_rcb->gwr_tab_id);
			break;
	        }
	        _VOID_ MEcopy((PTR)&sav_idx_id, sizeof(DB_TAB_ID),
	    		  (PTR)&gw_rcb->gwr_tab_id);
#endif	    /* 0 */
	    }
	} /* End if Xindex processing */

	/*
	** Append a tuple to iigwX_relation catalog for this index.
	*/
	if ((status = gwi_map_idx_rel(gw_rcb, &dmt, &dmr, &ulm_rcb)) != E_DB_OK)
	{
	    _VOID_ gwf_error(gw_rcb->gwr_error.err_code, GWF_INTERR, 0);
	    gw_rcb->gwr_error.err_code = E_GW0208_GWI_REGISTER_ERROR;
	    break;
	}

	/*
	** Now append iigwX_attribute tuples.
	*/

	if ((status = gwi_map_idx_att(gw_rcb, &ulm_rcb)) != E_DB_OK)
	{
	    _VOID_ gwf_error(gw_rcb->gwr_error.err_code, GWF_INTERR, 0);
	    gw_rcb->gwr_error.err_code = E_GW0208_GWI_REGISTER_ERROR;
	    break;
	}

	/* close the temporary stream */
	if ((status = ulm_closestream(&ulm_rcb)) != E_DB_OK)
	{
	    (VOID) gwf_error(ulm_rcb.ulm_error.err_code, GWF_INTERR, 0);
	    (VOID) gwf_error(E_GW0313_ULM_CLOSESTREAM_ERROR, GWF_INTERR, 1,
			     sizeof(*ulm_rcb.ulm_memleft),
			     ulm_rcb.ulm_memleft);
	    gw_rcb->gwr_error.err_code = E_GW0208_GWI_REGISTER_ERROR;
	    break;
	}

	/* If we get here everything is okay. */
	break;
    }

    if (status == E_DB_OK)
	gw_rcb->gwr_error.err_code = E_DB_OK;

    return(status);
}