Example #1
0
/*{
** Name: OPU_GSMEMORY_CLOSE	- Get memory from the stack ULM memory stream
**
** Description:
**      This routine allocates memory from the ULM memory stream that is used 
**      for the stack style memory usage.
[@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.
**	size -
**	    size of the piece of memory to allocate.
**
** Outputs:
**
**	Returns:
**	    The address of the allocated memory.
**	Exceptions:
**	    none
**
** Side Effects:
**	    none
**
** History:
**      19-July-87 (eric)
**          written
**      21-feb-91 (seputis)
**          make non-zero initialization of memory an xDEBUG feature
**      16-sep-93 (smc)
**          Moved <cs.h> for CS_SID.
**	11-oct-2006 (hayke02)
**	    Send E_OP0002_NOMEMORY to errlog.log. This change fixes bug 116309.
[@history_line@]...
[@history_template@]...
*/
PTR
opu_Gsmemory_get(
	OPS_STATE   *global,
	i4	    size)
{
    DB_STATUS      ulmstatus;		    /* return status from ULM */

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

    /* store the size to be allocate */
    global->ops_mstate.ops_ulmrcb.ulm_psize = size;

    if ( (ulmstatus = ulm_palloc( &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
    }	
#ifdef xDEBUG
    MEfill( size, (u_char)127, (PTR)global->ops_mstate.ops_ulmrcb.ulm_pptr); /*FIXME
                                            ** remove this initialization after
                                            ** test for uninitialized memory
                                            ** is not required any more */
#endif
    /* return the allocated memory */
    return( global->ops_mstate.ops_ulmrcb.ulm_pptr );
}
Example #2
0
/*{
** Name: psq_tinsert 	- Add a piece of query text to a chain in front
**			  of some piece.
**
** Description:
**      This function inserts a piece of query text to an existing chain.
**	New text is added in front of the existing piece specified by the
**	caller .
**	A need for the routine arises from the fact that the owner names need
**	to qualify database object names in case of database procedures.
**	Another use for the function is when synonym_name has to be
**	replaced with owner.actual_table_name in the text stored for views,
**	integrities, and permits.
**	These names become known when the scanner has already 'seen' the
**	object name (and therefore has already added it to the text chain).
**
** Inputs:
**      header                          Pointer to chain header
**	piece				Pointer to piece of text
**	size				Size of piece
**	result				Place to put pointer to new piece
**	oldpiece			Piece in front of which the new piece
**					will be inserted (should not be NULL).
**	err_blk				Filled in if an error happens
**
** Outputs:
**      result                          Filled in with pointer to chain element
**	err_blk				Filled in if an error happens
**	Returns:
**	    E_DB_OK			Success
**	    E_DB_ERROR			Non-catastrophic failure
**	    E_DB_FATAL			Catastrophic failure
**	Exceptions:
**	    none
**
** Side Effects:
**	    Allocates memory
**
** History:
**      02-jun-88 (stec)
**          written
**	04-jun-90 (andre)
**	    renamed from psq_tb1add() to psq_tinsert();
**	    changed the description to describe use of this function in
**	    conjunction with synonyms.
*/
DB_STATUS
psq_tinsert(
	PTR                header,
	u_char		   *piece,
	i4		   size,
	PTR		   *result,
	PTR		   oldpiece,
	DB_ERROR	   *err_blk)
{
    PSQ_THEAD           *hp = (PSQ_THEAD *) header;
    PSQ_TEXT		*tp, *op = (PSQ_TEXT *) oldpiece;
    i4		err_code;
    DB_STATUS		status;

    if (op == (PSQ_TEXT *) NULL)
    {
	/* Should not be reached */
	return (E_DB_ERROR);
    }

    /* Allocate enough space for PSQ_TEXT structure containing piece */
    hp->psq_tmem.ulm_psize = size + sizeof(PSQ_TEXT) - 1;
    status = ulm_palloc(&hp->psq_tmem);
    if (DB_FAILURE_MACRO(status))
    {
	if (hp->psq_tmem.ulm_error.err_code == E_UL0005_NOMEM)
	{
	    psf_error(E_PS0F02_MEMORY_FULL, 0L, PSF_CALLERR, 
		&err_code, err_blk, 0);
	}
	else
	    (VOID) psf_error(E_PS0371_ALLOC_TEXT_CHAIN,
		hp->psq_tmem.ulm_error.err_code, PSF_INTERR, &err_code,err_blk, 0);
	return (status);
    }
    *result = hp->psq_tmem.ulm_pptr;
    tp	    = (PSQ_TEXT*) *result;

    /* Fill in text piece */
    MEcopy((char *) piece, size, (char *) tp->psq_tval);
    tp->psq_psize = size;

    /* Hook it up to the chain */
    if (tp->psq_prev = op->psq_prev)
	tp->psq_prev->psq_next = tp;
    tp->psq_next = op;
    op->psq_prev = tp;

    if (hp->psq_first == op)
	hp->psq_first = tp;

    /* Add in the length to the total for the chain */
    hp->psq_tsize += size;

    return (E_DB_OK);
}
Example #3
0
/*{
** Name: psq_tadd	- Add a piece of query text to a chain
**
** Description:
**      This function adds a piece of query text to an existing chain.
**
** Inputs:
**      header                          Pointer to chain header
**	piece				Pointer to piece of text
**	size				Size of piece
**	result				Place to put pointer to new piece
**	err_blk				Filled in if an error happens
**
** Outputs:
**      result                          Filled in with pointer to chain element
**	err_blk				Filled in if an error happens
**	Returns:
**	    E_DB_OK			Success
**	    E_DB_ERROR			Non-catastrophic failure
**	    E_DB_FATAL			Catastrophic failure
**	Exceptions:
**	    none
**
** Side Effects:
**	    Allocates memory
**
** History:
**      18-jul-86 (jeff)
**          written
*/
DB_STATUS
psq_tadd(
	PTR                header,
	u_char		   *piece,
	i4		   size,
	PTR		   *result,
	DB_ERROR	   *err_blk)
{
    PSQ_THEAD           *hp = (PSQ_THEAD *) header;
    PSQ_TEXT		*tp;
    i4		err_code;
    DB_STATUS		status;

    /* Allocate enough space for PSQ_TEXT structure containing piece */
    hp->psq_tmem.ulm_psize = size + sizeof(PSQ_TEXT) - 1;
    status = ulm_palloc(&hp->psq_tmem);
    if (status != E_DB_OK)
    {
	if (hp->psq_tmem.ulm_error.err_code == E_UL0005_NOMEM)
	{
	    psf_error(E_PS0F02_MEMORY_FULL, 0L, PSF_CALLERR, 
		&err_code, err_blk, 0);
	}
	else
	    (VOID) psf_error(E_PS0371_ALLOC_TEXT_CHAIN,
		hp->psq_tmem.ulm_error.err_code, PSF_INTERR, &err_code,err_blk, 0);
	return (status);
    }
    *result = hp->psq_tmem.ulm_pptr;
    tp	    = (PSQ_TEXT*) *result;

    /* Fill in text piece */
    MEcopy((char *) piece, size, (char *) tp->psq_tval);
    tp->psq_psize = size;

    /* Hook it up to the chain */
    tp->psq_next = (PSQ_TEXT *) NULL;
    if (hp->psq_last != (PSQ_TEXT *) NULL)
    {
	hp->psq_last->psq_next = tp;
	tp->psq_prev = hp->psq_last;
    }
    else
    {
	tp->psq_prev = NULL;
    }
    hp->psq_last = tp;
    if (hp->psq_first == (PSQ_TEXT *) NULL)
	hp->psq_first = tp;

    /* Add in the length to the total for the chain */
    hp->psq_tsize += size;

    return (E_DB_OK);
}
Example #4
0
/*{
** Name: psf_symall	Allocates memory for a symbol block.
**
** Description:
**      Symbol blocks are used mainly by scanners to pass additional data
**	to parsers. They also hold emmitted text. This routine allocates
**	a new block and takes care of initializing appropriate fields in the
**	session control block.
**
** Inputs:
**      pss_cb				session control block pointer.
**	psq_cb				query control block.
**	size				amount of memory to be allocated.
**
** Outputs:
**	pss_cb				session control block with
**					appropriate fields initialized.
**	psq_cb				query control block with psq_error
**					field initialized, if error.
**	Returns:
**	    E_DB_OK
**	    status			return by ULM
**
**	Exceptions:
**	    none
**
** Side Effects:
**	    Allocates memory.
**
** History:
**	25-nov-87 (stec)
**          written
**	31-jan-97 (pchang)
**	    psf_symall(), when allocating memory for a symbol table block,
**	    failed to take into account the space needed for the next block
**	    pointer 'pss_sbnext' which later caused memory overrun in the data
**	    area 'pss_symdata'.  In some cases, the corruption is neutralized
**	    when the user of the violated adjacent memory space overlays it
**	    with new data.  Whereas, if the violated memory space is occupied
**	    by a less volatile entity such as a pointer for a linked list,
**	    what follows could be a random SEGV.  (B75105?)
*/
DB_STATUS
psf_symall(
	PSS_SESBLK  *pss_cb,
	PSQ_CB	    *psq_cb,
	i4	    size)
{
    DB_STATUS	status = E_DB_OK;
    ULM_RCB	ulm_rcb;
    i4	err_code;

    /* If no more blocks, allocate another */
    if (pss_cb->pss_symblk->pss_sbnext==(PSS_SYMBLK *) NULL)
    {
	/* If out of room, allocate some more */
	ulm_rcb.ulm_facility = DB_PSF_ID;
	ulm_rcb.ulm_streamid_p = &pss_cb->pss_symstr;
	ulm_rcb.ulm_psize = size + sizeof(PTR);    /* add space for fwd ptr */
	ulm_rcb.ulm_memleft = &pss_cb->pss_memleft;
	status = ulm_palloc(&ulm_rcb);

	if (DB_FAILURE_MACRO(status))
	{
	    if (ulm_rcb.ulm_error.err_code == E_UL0005_NOMEM)
	    {
		psf_error(E_PS0F02_MEMORY_FULL, 0L, PSF_CALLERR,
		    &err_code, &psq_cb->psq_error, 0);
	    }
	    else
	    {
		psf_error(2704L, 0L, PSF_USERERR,
		    &err_code, &psq_cb->psq_error, 0);
	    }
	    return (status);
	}
	pss_cb->pss_symblk->pss_sbnext = (PSS_SYMBLK*) ulm_rcb.ulm_pptr;
	pss_cb->pss_symblk->pss_sbnext->pss_sbnext = NULL;
    }

    /* Set current block and next character pointer */
    pss_cb->pss_symblk = pss_cb->pss_symblk->pss_sbnext;
    pss_cb->pss_symnext = pss_cb->pss_symblk->pss_symdata;

    return (E_DB_OK);
}
Example #5
0
/*{
** Name: psf_umalloc	- Allocate memory from ULM.
**
** Description:
**      General purpose interface into allocating from ULM for the current
**	session.
**
** Inputs:
**      sess_cb				Session control block pointer.
**	mstream				ULM stream id.
**	msize				Size of memory.
**
** Outputs:
**	sess_cb				Session control block:
**		.pss_memleft		Memory left in current session.
**	mresult				Pointer to result object.
**	err_blk.err_code		Error returned
**		E_PS0F02_MEMORY_FULL	No more memory for session
**		E_PS0A02_BADALLOC	Some other ULM error
**
**	Returns:
**	    status			return by ULM
**	    E_DB_FATAL			If memory corrupted.
**
**	Exceptions:
**	    none
**
** Side Effects:
**	    Allocates memory.
**
** History:
**	19-apr-89 (neil)
**          Written
*/
DB_STATUS
psf_umalloc(
	PSS_SESBLK  	*sess_cb,
	PTR		mstream,
	i4	    	msize,
	PTR		*mresult,
	DB_ERROR	*err_blk)
{
    DB_STATUS	status;
    ULM_RCB	ulm_rcb;
    i4	err_code;

    ulm_rcb.ulm_facility = DB_PSF_ID;
    ulm_rcb.ulm_streamid_p = &mstream;
    ulm_rcb.ulm_psize = msize;
    ulm_rcb.ulm_memleft = &sess_cb->pss_memleft;
    status = ulm_palloc(&ulm_rcb);

    if (status != 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,
			     err_blk, 0);
	}
	else
	{
	    _VOID_ psf_error(E_PS0A02_BADALLOC, 0L, PSF_INTERR, &err_code,
			     err_blk, 0);
	}
	if (ulm_rcb.ulm_error.err_code == E_UL0004_CORRUPT)
	    status = E_DB_FATAL;
	*mresult = NULL;
    }
    else
    {
	*mresult = ulm_rcb.ulm_pptr;
    }
    return (status);
} /* psf_umalloc */
Example #6
0
/*{
** Name: opu_memory	- get joinop memory
**
** Description:
**      This routine will allocate the requested size of memory from the 
**      joinop memory stream.  Memory in this stream is not deallocated 
**      until the optimization has completed.  The allocated memory will
**      be aligned for any datatype.
**
** Inputs:
**      global                          ptr to global state variable
**      size                            size of memory block requested.
**
** Outputs:
**	Returns:
**	    PTR to aligned memory of "size" bytes
**	Exceptions:
**	    none
**
** Side Effects:
**	    none
**
** History:
**	16-jun-86 (seputis)
**          initial creation
**	4-mar-91 (seputis)
**	    make initialization of memory an xDEBUG feature
**	11-oct-2006 (hayke02)
**	    Send E_OP0002_NOMEMORY to errlog.log. This change fixes bug 116309.
**	5-oct-2007 (dougi)
**	    Accumulate memory acquisition stats.
*/
PTR
opu_memory(
	OPS_STATE          *global,
	i4                size)
{
    DB_STATUS      ulmstatus;		    /* return status from ULM */

    global->ops_mstate.ops_countalloc++;
    if (size >= 2048)
	global->ops_mstate.ops_count2kalloc++;
    global->ops_mstate.ops_totalloc += size;

    global->ops_mstate.ops_ulmrcb.ulm_streamid_p = &global->ops_mstate.ops_streamid; /* allocate memory
					    ** from the global stream */
    global->ops_mstate.ops_ulmrcb.ulm_psize = size;    /* size of request */
    ulmstatus = ulm_palloc( &global->ops_mstate.ops_ulmrcb );
    if (DB_FAILURE_MACRO(ulmstatus))
    {
	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
    }	
#ifdef xDEBUG
    MEfill( size, (u_char)247, (PTR)global->ops_mstate.ops_ulmrcb.ulm_pptr); /*FIXME
                                            ** remove this initialization after
                                            ** test for uninitialized memory
                                            ** is not required any more */
#endif
    return( global->ops_mstate.ops_ulmrcb.ulm_pptr );  /* return the allocated
					    ** memory */
}
Example #7
0
/*
** Name: sxapo_bgn_ses - register a session with the auditing system
**
** Description:
**	This routine is called at session startup time to initialize the
**	audit specific data structures associated with a session. It should
**	be called only once for each session.
**
**	The only session specific data structure need for the operating system
**	audit log version of auditing is the record identifier that keeps
**	count of the number of records written since the last flush for this
**	session.
**
** Inputs:
**	scb		SXF session control block
**
** Outputs:
**	err_code	Error code returned to the caller
**
** Returns:
**	DB_STATUS
**
** History:
**	1-dec-93 (stephenb)
**	    Initial creation.
**
*/
DB_STATUS
sxapo_bgn_ses (
    SXF_SCB	*scb,
    i4	*err_code)
{
    ULM_RCB		ulm_rcb;
    DB_STATUS		status;
    i4		local_err;

    *err_code = E_SX0000_OK;

    ulm_rcb.ulm_facility = DB_SXF_ID;
    ulm_rcb.ulm_streamid_p = &scb->sxf_scb_mem;
    ulm_rcb.ulm_psize = sizeof (SXAPO_RECID);
    ulm_rcb.ulm_memleft = &Sxf_svcb->sxf_pool_sz;
    status = ulm_palloc(&ulm_rcb);
    if (status != E_DB_OK)
    {
	if (ulm_rcb.ulm_error.err_code == E_UL0005_NOMEM)
	    *err_code = E_SX106B_MEMORY_ERROR;
	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);
    }
    else
	scb->sxf_sxap_scb = ulm_rcb.ulm_pptr;
    /* handle errors */
    if (*err_code != E_SX0000_OK)
    {
	_VOID_ ule_format(*err_code, NULL, ULE_LOG, NULL, NULL,
		0L, NULL, &local_err, 0);
	*err_code = E_SX101D_SXAP_BGN_SESSION;
	status = E_DB_ERROR;
    }

    return(status);
}
Example #8
0
/*
** Name: sxapo_startup - startup the low level auditing system
**
** Description:
**
**	This routine initializes the operating system audit log version of
**	the SXAP auditing system. It should
**	be called once at SXF startup time. Its purpose is to allocate
**	and initialize the resources needed for the running of the low level
**	auditing system. 
**
**	This routine also initializes the vector used to access all other 
**	SXAP routines, all these routines must be called using this vector.
**
** Inputs:
**	None.
**
** Outputs:
**	rscb			RSCB for the current write audit file.
**	err_code		Error code returned to the caller.
**
** Returns:
**	DB_STATUS
**
** History:
**	2-dec-93 (stephenb)
**	    first written.
**	4-jan-94 (stephenb)
**	    Add sxapo_alter entry point to the sxap vector.
*/
DB_STATUS
sxapo_startup(
    SXF_RSCB	*rscb,
    i4 	*err_code)
{
    DB_STATUS	    status = E_DB_OK;
    i4	    local_err;
    SXAPO_RSCB	    *rs;
    ULM_RCB	    ulm_rcb;
    SXAP_VECTOR	    *v;
    bool	    file_open = FALSE;

    *err_code = E_SX0000_OK;

    for (;;)
    {
	/* Build the SXAP main control block */
	ulm_rcb.ulm_facility = DB_SXF_ID;
	ulm_rcb.ulm_streamid_p = &Sxf_svcb->sxf_svcb_mem;
	ulm_rcb.ulm_psize = sizeof (SXAPO_CB);
	ulm_rcb.ulm_memleft = &Sxf_svcb->sxf_pool_sz;
	status = ulm_palloc(&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);
	    break;
	}
	Sxapo_cb = (SXAPO_CB *) ulm_rcb.ulm_pptr;
	Sxapo_cb->sxapo_curr_rscb = NULL;


	/* Build and initialize the SXAP call vector */
	ulm_rcb.ulm_psize = sizeof (SXAP_VECTOR);
	status = ulm_palloc(&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;
	}
	Sxap_vector = (SXAP_VECTOR *) ulm_rcb.ulm_pptr;

	v = Sxap_vector;
	v->sxap_init = sxapo_startup;
	v->sxap_term = sxapo_shutdown;
	v->sxap_begin = sxapo_bgn_ses;
	v->sxap_end = sxapo_end_ses;
	v->sxap_open = sxapo_open;
	v->sxap_close = sxapo_close;
	v->sxap_pos = sxapo_position;
	v->sxap_read = sxapo_read;
	v->sxap_write = sxapo_write;
	v->sxap_flush = sxapo_flush;
	v->sxap_show = sxapo_show;
	v->sxap_alter = sxapo_alter;


	/* Initialize the audit file configuration data */
	status = sxapo_init_cnf(&local_err);
	if (status != E_DB_OK)
	{
	    *err_code = local_err;
	    _VOID_ ule_format(*err_code, NULL, ULE_LOG, 
		NULL, NULL, 0L, NULL, &local_err, 0);
	    break;
	}

	/* 
	** Open the audit file for writing.
	*/
	status = sxapo_open( NULL, SXF_WRITE, rscb, NULL, NULL, &local_err);
	if (status != E_DB_OK)
	{
	    *err_code = local_err;
	     _VOID_ ule_format(*err_code, NULL, ULE_LOG, 
			NULL, NULL, 0L, NULL, &local_err, 0);
	    break;
	}
	file_open = TRUE;
	rs = (SXAPO_RSCB *) rscb->sxf_sxap;
	Sxapo_cb->sxapo_curr_rscb = rs;

	Sxapo_cb->sxapo_status |= SXAPO_ACTIVE;
	break;
    }

    /* Cleanup after any errors */
    if (*err_code != E_SX0000_OK)
    {
	if (file_open)
	    _VOID_ sxapo_close(rscb, &local_err);


	*err_code = E_SX101A_SXAP_STARTUP;

	/*
	** Errors during startup of the auditing system are 
	** considered to be severe errors.
	*/
	status = E_DB_SEVERE;
    }
 
    return (status);
}
Example #9
0
/*{
** Name: PSQ_TCNVT	- convert db_data_value to text form
**
** Description:
**      This routine takes any user supplied db_data_value and converts
**  it to the value's textual representation.  This is required for the
**  iiqrytext catalog.  It is assumed that all datavalues can be written
**  into a character representation. 
**
** Inputs:
**	sess_cb				session control block
**	    .pss_adfcb			adf session control block for output
**					arguments.
**      header                          Pointer to chain header
**	dbval				db_data_value
**	result				Place to put pointer to new piece
**	err_blk				Filled in if an error happens
**
** Outputs:
**      result                          Filled in with pointer to chain element
**	err_blk				Filled in if an error happens
**	Returns:
**	    E_DB_OK			Success
**	    E_DB_ERROR			Non-catastrophic failure
**	    E_DB_FATAL			Catastrophic failure
**	Exceptions:
**	    none
**
** Side Effects:
**	    Allocates memory
**
** History:
**      29-jun-87 (daved)
**          written
**	28-jan-91 (andre)
**	    fix bug 35446: size of a new piece should include quotes, if they
**	    were added.
**	18-nov-91 (rog)
**	    Fixed bug 40869, et alia: the above fix missed adding the quotes
**	    to the total size and not just the piece size.
**	23-Sep-2009 (kiria01) b122578
**	    Initialise the ADF_FN_BLK .adf_fi_desc and adf_dv_n members.
**	19-Aug-2010 (kschendel) b124282
**	    Make sure fi-desc is always set to something.
*/
DB_STATUS
psq_tcnvt(
	PSS_SESBLK	   *sess_cb,
	PTR                header,
	DB_DATA_VALUE	   *dbval,
	PTR		   *result,
	DB_ERROR	   *err_blk)
{
    PSQ_THEAD           *hp;
    PSQ_TEXT		*tp;
    i4		err_code;
    DB_STATUS		status;
    ADF_CB		*adf_cb;
    ADF_FN_BLK		adffn;
    i4			dv_size;
    i4			count;
    char		*cptr;
    char		*quote_char;
    DB_TEXT_STRING      *string;
    ADI_DT_NAME		dt_fname;
    ADI_DT_NAME		dt_tname;
    char		f4_style;
    char		f8_style;
    i4			f4_width;
    i4			f8_width;
    i4			f4_prec;
    i4			f8_prec;
    i4			totype;
    i4			is_string;

    hp	    = (PSQ_THEAD *) header;
    adf_cb  = (ADF_CB *) sess_cb->pss_adfcb;
    status  = E_DB_OK;
    totype  = (DB_DT_ID) DB_LTXT_TYPE;

    adffn.adf_r_dv.db_datatype = totype;
    if (dbval->db_datatype == totype)
	dv_size = dbval->db_length;
    else
	dv_size = 0;

    /* JRBCMT -- PSF is not allowed to know this!!  First of all, date is   */
    /* missing from the list below and decimal will soon need to be on it.  */
    /* But also, we need to fix this code so that it doesn't make	    */
    /* assumptions about what types exist.  I think the proper approach is  */
    /* to quote all non-intrinsic types, but this should be investigated.   */

    /* are we dealing with a string type (incoming). */
    if (abs(dbval->db_datatype) == DB_INT_TYPE ||
        abs(dbval->db_datatype) == DB_FLT_TYPE ||
	abs(dbval->db_datatype) == DB_MNY_TYPE ||
	abs(dbval->db_datatype) == DB_BOO_TYPE)
    {
	is_string = FALSE;
	quote_char = (char *) NULL;
    }
    else
    {
	is_string = TRUE;
	quote_char = (sess_cb->pss_lang == DB_SQL) ? "\'" : "\"";
    }
    

    /* set the floating point conversion display */
    f4_style = adf_cb->adf_outarg.ad_f4style;
    f8_style = adf_cb->adf_outarg.ad_f8style;
    f4_width = adf_cb->adf_outarg.ad_f4width;
    f8_width = adf_cb->adf_outarg.ad_f8width;
    f4_prec  = adf_cb->adf_outarg.ad_f4prec;
    f8_prec  = adf_cb->adf_outarg.ad_f8prec;

    adf_cb->adf_outarg.ad_f4style = 'n';
    adf_cb->adf_outarg.ad_f8style = 'n';
    adf_cb->adf_outarg.ad_f4width = 20;
    adf_cb->adf_outarg.ad_f8width = 20;
    adf_cb->adf_outarg.ad_f4prec  = 10;
    adf_cb->adf_outarg.ad_f8prec  = 10;

    /* get the function instance id for this conversion */
    status = adi_ficoerce(adf_cb, dbval->db_datatype, totype, &adffn.adf_fi_id);
    if (status != E_DB_OK)
    {
	goto exit;
    }         

    /* determine the result size. */
    status = adi_fidesc(adf_cb, adffn.adf_fi_id, &adffn.adf_fi_desc);
    if (status != E_DB_OK)
    {
	goto exit;
    }
    if (!dv_size)
    {
	/* Now lets fill in the datatype length info and allocate space for the 
	** data.
	*/
	status = adi_0calclen(adf_cb, &adffn.adf_fi_desc->adi_lenspec, 1, &dbval, 
		&adffn.adf_r_dv);
	dv_size = adffn.adf_r_dv.db_length;

	if (status != E_DB_OK)
	{
	     goto exit;
	}
    }
    /* if string, add room for quotes */
    if (is_string)
	dv_size += 2 * CMbytecnt(quote_char);

    /* Allocate enough space for PSQ_TEXT structure containing piece */
    hp->psq_tmem.ulm_psize = dv_size + sizeof(PSQ_TEXT) - 1;
    status = ulm_palloc(&hp->psq_tmem);
    if (status != E_DB_OK)
    {
	if (hp->psq_tmem.ulm_error.err_code == E_UL0005_NOMEM)
	{
	    psf_error(E_PS0F02_MEMORY_FULL, 0L, PSF_CALLERR, 
		&err_code, err_blk, 0);
	}
	else
	    (VOID) psf_error(E_PS0371_ALLOC_TEXT_CHAIN,
		hp->psq_tmem.ulm_error.err_code, PSF_INTERR,
		&err_code, err_blk, 0);
	return (status);
    }
    *result = hp->psq_tmem.ulm_pptr;
    tp	    = (PSQ_TEXT*) *result;

    string	  = (DB_TEXT_STRING*) tp->psq_tval;
    /* Fill in text piece */
    adffn.adf_r_dv.db_length	= dv_size;
    adffn.adf_r_dv.db_data	= (PTR) string;
    adffn.adf_dv_n		= 1;
    STRUCT_ASSIGN_MACRO(*dbval, adffn.adf_1_dv);
    adffn.adf_pat_flags		= AD_PAT_DOESNT_APPLY;
    if ((status = adf_func(adf_cb, &adffn)) != E_DB_OK)
    {
	goto exit;
    }
    /* CAUTION: entering tricky code.
    ** string is a variable containing a text datatype. We want to convert
    ** to a C datatype.  We also want to add quote characters if the datatype
    ** was a string type.  We grab the count from the string variable first.
    ** we can then use the 2 byte count for character data.
    */
    count = string->db_t_count;
    cptr = (char *)  string;
    if (is_string)
    {
	/*
	** for strings, copy the opening quote (" or ', depending on language)
	*/ 
	CMcpychar(quote_char, cptr);
	cptr += CMbytecnt(quote_char);
    }
    MEcopy((PTR) string->db_t_text, count, (PTR) cptr);
    cptr += count;
    if (is_string)
    {
	/*
	** for strings, copy the closing quote (" or ', depending on language)
	*/ 
	CMcpychar(quote_char, cptr);
    }

    /* if storing a string, do not forget to account for quotes (bug 35446) */
    tp->psq_psize = (is_string) ? count + 2 * CMbytecnt(quote_char) : count;

    /* Hook it up to the chain */
    tp->psq_next = (PSQ_TEXT *) NULL;
    if (hp->psq_last != (PSQ_TEXT *) NULL)
    {
	hp->psq_last->psq_next = tp;
	tp->psq_prev = hp->psq_last;
    }
    else
    {
	tp->psq_prev = NULL;
    }
    hp->psq_last = tp;
    if (hp->psq_first == (PSQ_TEXT *) NULL)
	hp->psq_first = tp;

    /* Add in the length to the total for the chain */
    hp->psq_tsize += tp->psq_psize;

exit:
    /* set the floating point conversion display */
    adf_cb->adf_outarg.ad_f4style = f4_style;
    adf_cb->adf_outarg.ad_f8style = f8_style;
    adf_cb->adf_outarg.ad_f4width = f4_width;
    adf_cb->adf_outarg.ad_f8width = f8_width;
    adf_cb->adf_outarg.ad_f4prec  = f4_prec;
    adf_cb->adf_outarg.ad_f8prec  = f8_prec;

    if (status != E_DB_OK)
    {
	(VOID) adi_tyname(adf_cb, dbval->db_datatype, &dt_fname);
	(VOID) adi_tyname(adf_cb, totype, &dt_tname);
	(VOID) psf_error(2911L, 0L, PSF_USERERR,
	    &err_code, err_blk, 3, sizeof (sess_cb->pss_lineno),
	    &sess_cb->pss_lineno, 
	    psf_trmwhite(sizeof(dt_fname), (char *) &dt_fname), &dt_fname, 
	    psf_trmwhite(sizeof (dt_tname), (char *) &dt_tname), &dt_tname);
        return (E_DB_ERROR);    
    }
    return (status);
}
Example #10
0
/*{
** Name: psq_tsubs	- Substitute one piece of text for another
**
** Description:
**      This function substitutes one piece of query text for another in the
**	given text chain.  It will try to re-use the current piece before
**	allocating another.
**
** Inputs:
**      header                          Pointer to header
**	piece				Piece we want to substitute for
**	newtext				Pointer to new piece of text
**	size				Size of new piece
**	newpiece			Place to put pointer to new piece
**	err_blk				Filled in if an error happens
**
** Outputs:
**      newpiece                        Filled in with pointer to new piece
**	err_blk				Filled in if an error happened
**	Returns:
**	    E_DB_OK			Success
**	    E_DB_ERROR			Non-catastrophic error
**	    E_DB_FATAL			Catastrophic error
**	Exceptions:
**	    none
**
** Side Effects:
**	    Can allocate memory
**
** History:
**      18-jul-86 (jeff)
**          written
*/
DB_STATUS
psq_tsubs(
	PTR                header,
	PTR		   piece,
	u_char		   *newtext,
	i4		   size,
	PTR		   *newpiece,
	DB_ERROR	   *err_blk)
{
    PSQ_THEAD           *hp = (PSQ_THEAD *) header;
    PSQ_TEXT		*tp = (PSQ_TEXT *) piece;
    PSQ_TEXT		*np;
    DB_STATUS		status;
    i4		err_code;
    i4			oldsize;

    /* Remember the size of the original piece */
    oldsize = tp->psq_psize;

    /* If there isn't enough room in the current piece, allocate another one */
    if (tp->psq_psize < size)
    {
	/* Allocate enough for PSQ_TEXT struct with size bytes of text */
	hp->psq_tmem.ulm_psize = size + sizeof(PSQ_TEXT) - 1;
	status = ulm_palloc(&hp->psq_tmem);
	if (status != E_DB_OK)
	{
	    if (hp->psq_tmem.ulm_error.err_code == E_UL0005_NOMEM)
	    {
		psf_error(E_PS0F02_MEMORY_FULL, 0L, PSF_CALLERR, 
		    &err_code, err_blk, 0);
	    }
	    else
		(VOID) psf_error(E_PS0371_ALLOC_TEXT_CHAIN,
		    hp->psq_tmem.ulm_error.err_code,
		    PSF_INTERR,&err_code, err_blk, 0);
	    return (status);
	}
	np = (PSQ_TEXT*) hp->psq_tmem.ulm_pptr;

	/* Hook up the new piece into the chain */
	if (np->psq_prev = tp->psq_prev)
	{
	    np->psq_prev->psq_next = np;
	}
	
	if (np->psq_next = tp->psq_next)
	{
	    np->psq_next->psq_prev = np;
	}

	if (hp->psq_first == tp)
	    hp->psq_first = np;
	if (hp->psq_last == tp)
	    hp->psq_last = np;
	tp = np;
    }

    /* Copy the new text into the piece and set the size */
    MEcopy((char *) newtext, size, (char *) tp->psq_tval);
    tp->psq_psize = size;

    /* Adjust the total size of the chain */
    hp->psq_tsize -= oldsize - size;

    /* Give the caller a pointer to the new piece */
    *newpiece = (PTR) tp;

    return (E_DB_OK);    
}
Example #11
0
/*{
** Name: psq_rptqry_text - add a piece of text to the text chain for a repeat
**			   query
**
** Description: Add a piece of text to the text chain for a repeat query.  It is
**		imperative that text of all repeat queries be stored in a
**		uniform fashion so that comparing two stored query texts would
**		serve as a reliable indicator of their sameness.  Each piece
**		will be preceeded with a blank except for a PERIOD.  Neither the
**		piece consisting of PERIOD nor the following piece will be
**		preceeded with a blank.
**
** Inputs:
**      header                          Pointer to chain header
**	piece				Pointer to piece of text
**	size				Size of piece
**	result				Place to put pointer to new piece
**	err_blk				Filled in if an error happens
**
** Outputs:
**      result                          Filled in with pointer to chain element
**	err_blk				Filled in if an error happens
**	Returns:
**	    E_DB_OK			Success
**	    E_DB_ERROR			Non-catastrophic failure
**	    E_DB_FATAL			Catastrophic failure
**	Exceptions:
**	    none
**
** Side Effects:
**	    Allocates memory
**
** History:
**      24-jan-90 (andre)
**          Plagiarized from psq_tadd().
**	28-jan-91 (andre)
**	    Do not insert a space if a piece is immediately following a piece
**	    consisting of a $.
*/
DB_STATUS
psq_rptqry_text(
	PTR                header,
	u_char		   *piece,
	i4		   size,
	PTR		   *result,
	DB_ERROR	   *err_blk)
{
    PSQ_THEAD           *hp = (PSQ_THEAD *) header;
    PSQ_TEXT		*tp;
    i4		err_code;
    bool		leading_blank;
    char		*txt;
    DB_STATUS		status;

    /*
    ** Allocate enough space for PSQ_TEXT structure containing piece:
    ** all pieces will be preceeded with a blank with the following exceptions:
    **	- piece consisting of PERIOD will not be preceeeded with a blank;
    **	- piece which immediately follows a piece consisting of PERIOD;
    **	- piece starting with a "white" character will not be preceeded with a
    **	  blank;
    **	- piece which immediately follows a piece consisting of $ (preceeded by
    **	  a blank which was inserted by this function)
    */

    if (   size == CMbytecnt(".") && !CMcmpcase(piece, ".")
	|| CMwhite(piece))
    {
	/*
	** piece consists of a period or starts with a "white" character - no
	** leading blanks will be added
	*/
	leading_blank = FALSE;
    }
    else if (   hp->psq_last != (PSQ_TEXT *) NULL
	     && ((   hp->psq_last->psq_psize == CMbytecnt(".")
		  && !CMcmpcase(hp->psq_last->psq_tval, ".")
		 )
		 ||
		 (   hp->psq_last->psq_psize == CMbytecnt(" ") + CMbytecnt("$")
		  && !CMcmpcase(hp->psq_last->psq_tval, " ")
		  && !CMcmpcase((hp->psq_last->psq_tval + CMbytecnt(" ")), "$")
		 )
	        )
	    )
    {
	/*
	** previous piece consists of a period or of a $ preceeded by a blank
	** inserted by this function - no leading blanks will be added
	*/
	leading_blank = FALSE;
    }
    else
    {
	/* insert a blank before the piece */
	leading_blank = TRUE;
    }

    hp->psq_tmem.ulm_psize = (leading_blank)
	? size + sizeof(PSQ_TEXT) - 1 + CMbytecnt(" ")
	: size + sizeof(PSQ_TEXT) - 1;

    if ((status = ulm_palloc(&hp->psq_tmem)) != E_DB_OK)
    {
	if (hp->psq_tmem.ulm_error.err_code == E_UL0005_NOMEM)
	{
	    (VOID) psf_error(E_PS0F02_MEMORY_FULL, 0L, PSF_CALLERR, 
		&err_code, err_blk, 0);
	}
	else
	{
	    (VOID) psf_error(E_PS0371_ALLOC_TEXT_CHAIN,
		hp->psq_tmem.ulm_error.err_code, PSF_INTERR, &err_code, err_blk,
		0);
	}

	return (status);
    }

    *result = hp->psq_tmem.ulm_pptr;
    tp	    = (PSQ_TEXT*) *result;

    /* Fill in text piece */
    txt = (char *) tp->psq_tval;

    /* insert a leading blank if necessary */
    if (leading_blank)
    {
	CMcpychar(" ", txt);
	txt += CMbytecnt(" ");
    }
	
    MEcopy((char *) piece, size, txt);
    tp->psq_psize = (leading_blank) ? size + CMbytecnt(" ") : size;

    /* Hook it up to the chain */
    tp->psq_next = (PSQ_TEXT *) NULL;
    if (hp->psq_last != (PSQ_TEXT *) NULL)
    {
	hp->psq_last->psq_next = tp;
	tp->psq_prev = hp->psq_last;
    }
    else
    {
	tp->psq_prev = NULL;
    }
    hp->psq_last = tp;
    if (hp->psq_first == (PSQ_TEXT *) NULL)
	hp->psq_first = tp;

    /* Add in the length to the total for the chain */
    hp->psq_tsize += tp->psq_psize;

    return (E_DB_OK);
}
Example #12
0
/*{
** Name: gwi_map_idx_rel    -	create a tuple entry in the iigwX_relation
**				table for this gateway secondary index
**
** Description:
**	This function creates a tuple in the extended relation catalog for this
**	gateway secondary index.  The tuple is identical to that for its base
**	table, except that it has a non-zero xreltidx field.
**
** Inputs:
**	gw_rcb->		gateway request control block
**	    gwr_tab_id		table id for this secondary index
**	dmt_cb			DMF table request control block, passed in from
**				parent routine to avoid re-allocating
**	dmr_cb			DMF record request control block passed in from
**				parent routine to avoid re-allocating
**	ulm_rcb			memory request control block, passed in from
**				parent routine as it is in the same stream, we
**				want to deallocate all related memory from there
**
** Output:
**	gw_rcb->
**		error.err_code	One of the following error numbers.
**				E_GW0600_NO_MEM
**
**      Returns:
**          E_DB_OK             Function completed normally. 
**          E_DB_ERROR          Function completed abnormally with 
**                              error.err_code.
** History:
**	24-sep-90 (linda)
**	    Created.
**	07-oct-92 (robf)
**	    If we can't find the base tuple, don't try to save an (incorrect)
**	    index tuple.
**	    Look up the base tuple, not index tuple, from relation (the
**	    index tuple doesn't exist yet, so we wouldn't expect to find it)
**	    If opening the iigwXX_relation catalog fails, break rather
**	    than trying to access an unopened table.
**	    Save errors on return so higher level knows what happened.
**	    (symptom was spurious ULEFORMAT errors on error #0)
**      8-oct-92 (daveb)
**          prototyped.  Cast db_id arg to gwu_copen.  It's a PTR.
**          removed dead var gwx.
*/
static
DB_STATUS
gwi_map_idx_rel( GW_RCB *gw_rcb,
                DMT_CB  *dmt,
                DMR_CB  *dmr,
                ULM_RCB *ulm_rcb )
{
    GW_SESSION	    *session = (GW_SESSION *)gw_rcb->gwr_session_id;
    DB_TAB_ID	    base_tab_id;
    DB_TAB_ID	    *tab_id;
    i4	    gw_id = gw_rcb->gwr_gw_id;
    i4		    xrel_sz = Gwf_facility->gwf_gw_info[gw_id].gwf_xrel_sz;
    DB_STATUS	    status = E_DB_OK;
    DB_STATUS	    ret_code=E_DB_OK;
    DMR_ATTR_ENTRY  attkey[2];
    DMR_ATTR_ENTRY  *attkey_ptr[2];
    DB_ERROR	    err;

    for (;;)	/* just to break out of on error... */
    {
        /*
        ** First create the iigwXX_relation row buffer
        */
        ulm_rcb->ulm_psize = xrel_sz;

        if ((status = ulm_palloc(ulm_rcb)) != E_DB_OK)
        {
            gwf_error(ulm_rcb->ulm_error.err_code, GWF_INTERR, 0);
            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_GW021D_GWU_MAP_IDX_REL_ERROR;
            break;
        }

	dmr->dmr_data.data_in_size = xrel_sz;
	dmr->dmr_data.data_address = ulm_rcb->ulm_pptr;
     
	/*
	** NOTE we are looking for the base table entry.
	*/
	STRUCT_ASSIGN_MACRO(gw_rcb->gwr_tab_id, base_tab_id);
	base_tab_id.db_tab_index = 0;


	/* position to get if this is a DMT_A_READ */
	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[1].attr_value = (char*) &base_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;


	/* get extended relation catalog info - iigwX_relation */
	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_xrel_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_GW021D_GWU_MAP_IDX_REL_ERROR;
		    break;
	    }
	    break;
	}

	dmr->dmr_flags_mask = DMR_NEXT;
	tab_id = (DB_TAB_ID *)dmr->dmr_data.data_address;
	STRUCT_ASSIGN_MACRO(base_tab_id, *tab_id);
	dmr->dmr_char_array.data_address = 0;

	/* search for the right tuple */
	do
	{
	    status = (*Dmf_cptr)(DMR_GET, dmr);
	} while (status == E_DB_OK
	     &&
	     MEcmp((PTR)dmr->dmr_data.data_address,
		   (PTR)&base_tab_id,
		   sizeof(DB_TAB_ID)));

	if (status != E_DB_OK)	/* cannot get table info */
	{
	    switch (dmt->error.err_code)
	    {
		case    E_DM0042_DEADLOCK:
		    err.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,
			    (i4)4, (PTR)&gw_rcb->gwr_tab_id.db_tab_base,
			    (i4)4, (PTR)&gw_rcb->gwr_tab_id.db_tab_index);
		    gw_rcb->gwr_error.err_code = E_GW021D_GWU_MAP_IDX_REL_ERROR;
		    break;
	    }
	}
	/*
	**	Only save the index tuple if we found base tuple
	*/
	if (status == E_DB_OK)
	{
		/*
		** Now that we've found the tuple for the base table, 
		** update it to be that of the index.  This code assumes that 
		** the tab_id fields are the first fields in the extended 
		** relation catalog.
		*/
		tab_id = (DB_TAB_ID *)dmr->dmr_data.data_address;
		STRUCT_ASSIGN_MACRO(gw_rcb->gwr_tab_id, *tab_id);

		/* put the iigwX_relation tuple */
		/*
		** Initialize the DMR control block with the information 
		** required for an insert.
		*/
		dmr->type = DMR_RECORD_CB;
		dmr->length = sizeof(*dmr);
		dmr->dmr_data.data_in_size = xrel_sz;

		if ((status = (*Dmf_cptr)(DMR_PUT, dmr)) != E_DB_OK)
		{
		    switch (dmt->error.err_code)
		    {
			case    E_DM0042_DEADLOCK:
			    err.err_code = E_GW0327_DMF_DEADLOCK;
			    break;

			default:
			    /***note need args here to specify which catalog***/
			    gwf_error(dmr->error.err_code, GWF_INTERR, 0);
			    gwf_error(E_GW0320_DMR_PUT_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);
			    gwf_error(E_GW0623_XCAT_PUT_FAILED, GWF_INTERR, 0);
			    gw_rcb->gwr_error.err_code = E_GW021D_GWU_MAP_IDX_REL_ERROR;
			    break;
		    }
		}
	}
	/*
	**	Preserve previous status in case of earlier error and
	**	OK close loosing error status.
	*/
	ret_code=status;

	if ((status = (*Dmf_cptr)(DMT_CLOSE, dmt)) != E_DB_OK)
	{
	    switch (dmt->error.err_code)
	    {
		case    E_DM0042_DEADLOCK:
		    err.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_GW021D_GWU_MAP_IDX_REL_ERROR;
		    break;
	    }
	}
	/*
	**	Restore any failure from before
	*/
	if (status==E_DB_OK)
		status=ret_code;

	break;
    }
    return(status);
}
Example #13
0
/*{
** 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);
}
Example #14
0
/*
** 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);
}
Example #15
0
/*{
** Name: gwi_map_idx_att    -	create tuple entries in the iigwX_attribute
**				table for this gateway secondary index
**
** Description:
**	This function creates tuples in the extended attribute catalog for this
**	gateway secondary index.  The tuples are those defined for the index,
**	plus a tidp column.
**
**	In order to create the tuple entries, the following steps are performed:
**
**	(1) select all rows from iiattribute for this index, and save them.
**	(2) For each row saved:
**	    (a)	if it's 'tidp', drop down to (3).
**	    (b)	select the row from iiattribute for the base table which has
**		the same name and save its attid; we will use this to get
**		extended attribute info.
**	    (c)	now select the appropriate row from iigwX_attribute.
**	    (d)	update the xrelidx and xattid fields -- xrelidx is non-zero for
**		this index, xattid is that for the index not the base table.
**	    (e)	append the row.
**	(3) finished with "real" attributes.  Check that we found 1 or more
**	    other attributes -- else error.  Now create the row for the tidp
**	    domain and append it.  Use integer gw datatype, length 4, offset 0;
**	    we don't really use this attribute and it doesn't exist in the
**	    gateway record.  Need to have a gateway-specific static definition
**	    for this row.
**
** Inputs:
**	gw_rcb->		gateway request control block
**	    gwr_tab_id		table id for this secondary index
**	ulm_rcb			memory request control block, passed in from
**				parent routine as it is in the same stream, we
**				want to deallocate all related memory from there
**
** Output:
**	gw_rcb->
**		error.err_code	One of the following error numbers.
**				E_GW0600_NO_MEM
**
**      Returns:
**          E_DB_OK             Function completed normally. 
**          E_DB_ERROR          Function completed abnormally with 
**                              error.err_code.
** History:
**	24-sep-90 (linda)
**	    Created.
**	07-oct-92 (robf)
**	    If open of iiattribute fails, don't try to continue processing.
**      8-oct-92 (daveb)
**          cast an assignment.
**      8-oct-92 (daveb)
**          prototyped.  Cast db_id arg to gwu_copen; it's a PTR.
**	30-May-2006 (jenjo02)
**	    Max attributes in an index is now DB_MAXIXATTS, not DB_MAXKEYS.
*/
static
DB_STATUS
gwi_map_idx_att(GW_RCB  *gw_rcb,
                ULM_RCB *ulm_rcb )
{
    GW_SESSION	    *session = (GW_SESSION *)gw_rcb->gwr_session_id;
    DMT_CB	    dmt;
    DMR_CB	    dmr;
    char	    *dmp_atts[DB_MAXIXATTS+1];
    GW_DMP_ATTR	    *dmp_att1;
    GW_DMP_ATTR	    *dmp_att2;
    GW_DMP_ATTR	    iiatt_buf;
    DB_TAB_ID	    base_tab_id;
    DB_TAB_ID	    *tab_id;
    i4		    i;
    i4		    j;
    i2		    *attid_ptr;
    DMR_ATTR_ENTRY  attkey[2];
    DMR_ATTR_ENTRY  *attkey_ptr[2];
    i4	    gw_id = gw_rcb->gwr_gw_id;
    i4		    xatt_sz = Gwf_facility->gwf_gw_info[gw_id].gwf_xatt_sz;
    char	    stage_buf[DB_MAXTUP];
    char	    *xatt_rows[DB_MAXIXATTS+1];
    DB_STATUS	    status = E_DB_OK;

    /*
    ** Set up the base table id for later use.
    */
    STRUCT_ASSIGN_MACRO(gw_rcb->gwr_tab_id, base_tab_id);
    base_tab_id.db_tab_index = 0;

    for (;;)	/* just to break out of on error... */
    {
	/*
	** First set up dmt and open iiattribute table.
	*/
	dmt.type = DMT_TABLE_CB;
	dmt.length = sizeof(DMT_CB);
	dmt.dmt_id.db_tab_base = 3;    /* tab_id for iiattribute */
	dmt.dmt_id.db_tab_index = 0;   /* "    "	"   "	"   " */
/**
*** gwr_gw_sequence == 0, which causes dmt_open to fail.  For now set it to 1.
***	dmt.dmt_sequence = gw_rcb->gwr_gw_sequence;
**/
	dmt.dmt_sequence = 1;
	dmt.dmt_db_id = (PTR)gw_rcb->gwr_database_id;
	dmt.dmt_tran_id = gw_rcb->gwr_xact_id;
	dmt.dmt_flags_mask = 0;
	dmt.dmt_access_mode = DMT_A_READ;
	dmt.dmt_lock_mode = DMT_IS;
	dmt.dmt_update_mode = DMT_U_DEFERRED;
	dmt.dmt_char_array.data_address = NULL;
	dmt.dmt_char_array.data_in_size = 0;

	if ((status = (*Dmf_cptr)(DMT_OPEN, &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_GW0324_DMT_OPEN_ERROR, GWF_INTERR, 2,
				    (i4)4, (PTR)&dmt.dmt_id.db_tab_base,
				    (i4)4, (PTR)&dmt.dmt_id.db_tab_index);
		    gw_rcb->gwr_error.err_code = E_GW021E_GWU_MAP_IDX_ATT_ERROR;
		    break;
	    }
	    break;
	}

	/* position to get if this is a DMT_A_READ */
	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;
	if ((status = (*Dmf_cptr)(DMR_POSITION, &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_GW0323_DMR_POSITION_ERROR, GWF_INTERR, 2,
				    (i4)4, (PTR)&dmt.dmt_id.db_tab_base,
				    (i4)4, (PTR)&dmt.dmt_id.db_tab_index);
		    gw_rcb->gwr_error.err_code = E_GW0213_GWU_COPEN_ERROR;
		    break;
	    }
	}

	/*
	** We'll allocate room for a GW_DMP_ATTR struct plus an extra 2
	** bytes for the column's base table attid, which we'll use to get
	** the right row from iigwX_attribute.
	*/
	ulm_rcb->ulm_psize = sizeof(GW_DMP_ATTR) + 2;

	dmr.dmr_data.data_in_size = sizeof(GW_DMP_ATTR) + 2;
	dmr.dmr_flags_mask = DMR_NEXT;
	dmr.dmr_data.data_address = &stage_buf[0];
	dmr.dmr_char_array.data_address = 0;

	for (i=0; i < gw_rcb->gwr_column_cnt; i++)
	{
	    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)
	    {
		if ((status = ulm_palloc(ulm_rcb)) != E_DB_OK)
		{
		    gwf_error(ulm_rcb->ulm_error.err_code, GWF_INTERR, 0);
		    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
		    {
			switch (dmt.error.err_code)
			{
			    case    E_DM0042_DEADLOCK:
				gw_rcb->gwr_error.err_code =
					    E_GW0327_DMF_DEADLOCK;
				break;

			    default:
				gw_rcb->gwr_error.err_code =
					E_GW021E_GWU_MAP_IDX_ATT_ERROR;
				break;
			}
		    }
		    break;
		}
		MEcopy((PTR)&stage_buf[0], sizeof(GW_DMP_ATTR)+2,
		       ulm_rcb->ulm_pptr);
		dmp_atts[i] = (char *)ulm_rcb->ulm_pptr;
		continue;   /* get next attribute for the index */
	    }
	    else if (dmr.error.err_code == E_DM0055_NONEXT)
	    {
/***FIXME*** -- at this point we've allocated an extra buffer?  look at -- ***/
		status = E_DB_OK;
		dmr.error.err_code = E_DB_OK;
		break;	    /* no more attributes for this index */
	    }
	    else
	    {
		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_GW0323_DMR_POSITION_ERROR,
					 GWF_INTERR, 2, (i4)4,
					 (PTR)&dmt.dmt_id.db_tab_base,
					 (i4)4,
					 (PTR)&dmt.dmt_id.db_tab_index);
			gw_rcb->gwr_error.err_code =
				    E_GW021E_GWU_MAP_IDX_ATT_ERROR;
			break;
		}
	    }

	    break;
	}

	if (status != E_DB_OK)
	    break;  /* error already reported. */

	/*
	** Now we get the base table rows from iiattribute, so we can store the
	** attid from the base to get the proper base table row from
	** iigwX_attribute.
	*/
	attkey[0].attr_value = (char *)&base_tab_id.db_tab_base;
	attkey[1].attr_value = (char *)&base_tab_id.db_tab_index;

	if ((status = (*Dmf_cptr)(DMR_POSITION, &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_GW0323_DMR_POSITION_ERROR, GWF_INTERR, 2,
				    (i4)4, (PTR)&dmt.dmt_id.db_tab_base,
				    (i4)4, (PTR)&dmt.dmt_id.db_tab_index);
		    gw_rcb->gwr_error.err_code = E_GW021E_GWU_MAP_IDX_ATT_ERROR;
		    break;
	    }
	    break;
	}

	/*
	** We don't know how many columns are in the base table; just need to
	** find matches for those in the index table.  The tidp column will be
	** handled separately.  Only need one buffer here, we store base table
	** attid with previously-allocated rows for index table.
	*/

	dmr.dmr_data.data_in_size = sizeof(GW_DMP_ATTR);
	dmr.dmr_data.data_address = (PTR)&iiatt_buf;
	dmr.dmr_char_array.data_address = 0;

	i = 0;	/* keep a count of matches found */

	for (;;)    /* this gives us a place to continue to. */
	{
	    do
	    {
		status = (*Dmf_cptr)(DMR_GET, &dmr);
	    }
	    while ((status == E_DB_OK) &&
		   (MEcmp((PTR)dmr.dmr_data.data_address,
			  (PTR)&base_tab_id,
			  sizeof(DB_TAB_ID)))
		  );

	    if (status == E_DB_OK)
	    {
		dmp_att1 = (GW_DMP_ATTR *)dmr.dmr_data.data_address;
		for (j=0; j < gw_rcb->gwr_column_cnt; j++)
		{
		    dmp_att2 = (GW_DMP_ATTR *)dmp_atts[j];
		    if
		    (!MEcmp((PTR)&dmp_att1->attname, (PTR)&dmp_att2->attname,
			    sizeof(DB_ATT_NAME)))
		    {
			attid_ptr =
			    (i2 *)(dmp_atts[j] + sizeof(GW_DMP_ATTR));
			*attid_ptr = dmp_att1->attid;
			i++;
			break;	/* out of inner loop */
		    }
		}
	    }
	    else if (dmr.error.err_code == E_DM0055_NONEXT)
	    {
		status = E_DB_OK;
		dmr.error.err_code = E_DB_OK;
		break;	    /* no more attributes for this index */
	    }
	    else
	    {
		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_GW0323_DMR_POSITION_ERROR,
					 GWF_INTERR, 2, (i4)4,
					 (PTR)&dmt.dmt_id.db_tab_base,
					 (i4)4,
					 (PTR)&dmt.dmt_id.db_tab_index);
			gw_rcb->gwr_error.err_code =
				    E_GW021E_GWU_MAP_IDX_ATT_ERROR;
			break;
		}
		break;
	    }

	    if (i == gw_rcb->gwr_column_cnt - 1)
		break;	/* we've found all the matching rows */
	}

	/* Always close iiattribute table. */
	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:
		    gwf_error(dmt.error.err_code, GWF_INTERR, 0);
		    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);
		    gwf_error(E_GW062C_XREL_CLOSE_FAILED, GWF_INTERR, 0);
		    gw_rcb->gwr_error.err_code = E_GW021E_GWU_MAP_IDX_ATT_ERROR;
		    break;
	    }
	    break;
	}

	if (status != E_DB_OK)	/* whether from previous code, or close */
	    break;  /* error already reported */

	/*
	** We should have found matches for all but one index column (tidp).
	*/
	if (i != gw_rcb->gwr_column_cnt - 1)
	{
/***generate error here***/
	    gw_rcb->gwr_error.err_code = E_GW021E_GWU_MAP_IDX_ATT_ERROR;
	    break;
	}


	/* position on base table id */
	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];


	/* now we get the rows from the extended attribute 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_xatt_tab_name,
		DMT_A_WRITE, TRUE, &gw_rcb->gwr_error)) 
	    != 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(gw_rcb->gwr_error.err_code, GWF_INTERR, 0);
		    gw_rcb->gwr_error.err_code = E_GW021E_GWU_MAP_IDX_ATT_ERROR;
		    break;
	    }
	}

	/*
	** Set up staging area for tuples returned from extended attribute
	** catalog.  We'll allocate space when we find a match, so we can
	** insert them later.
	*/
	dmr.dmr_flags_mask = DMR_NEXT;
	dmr.dmr_data.data_in_size = xatt_sz;
	dmr.dmr_data.data_address = (PTR)&stage_buf[0];
	dmr.dmr_char_array.data_address = 0;

	/*
	** Size to be allocated is one extended attribute row.
	*/
	ulm_rcb->ulm_psize = xatt_sz;

	i = 0;

	/* search for the right tuples */
	for (;;)
	{
	    do
	    {
		status = (*Dmf_cptr)(DMR_GET, &dmr);
	    } while (status == E_DB_OK
		 &&
		 MEcmp((PTR)dmr.dmr_data.data_address,
		       (PTR)&base_tab_id,
		       sizeof(DB_TAB_ID)));

	    if (status == E_DB_OK)
	    {

		/*
		** When we find a tuple from iigwX_attribute which matches one
		** of the index tuples, update the values to represent the
		** index and then store the tuple.  NOTE that we assume that
		** tab_id and attid fields are the first fields in the extended
		** catalog.  We can't know the internal structure of extended
		** attribute catalogs for particular gateways beyond the 1st
		** three cols.
		*/

		dmp_att1 = (GW_DMP_ATTR *)dmr.dmr_data.data_address;

		for (j=0; j < gw_rcb->gwr_column_cnt - 1; j++)
		{
		    if (dmp_att1->attid ==
			*(i2 *)(dmp_atts[j] + sizeof(GW_DMP_ATTR)))
		    {
			if ((status = ulm_palloc(ulm_rcb)) != E_DB_OK)
			{
			    gwf_error(ulm_rcb->ulm_error.err_code, GWF_INTERR,
				      0);
			    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_GW021E_GWU_MAP_IDX_ATT_ERROR;
			    break;
			}

			dmp_att1->attid = i + 1;
			xatt_rows[i] = ulm_rcb->ulm_pptr;
			MEcopy(dmr.dmr_data.data_address,
			       xatt_sz, xatt_rows[i]);
			tab_id = (DB_TAB_ID *)xatt_rows[i];
			STRUCT_ASSIGN_MACRO(gw_rcb->gwr_tab_id, *tab_id);
			i++;
			break;
		    }
		}
		if (i == gw_rcb->gwr_column_cnt - 1)
		    break;
	    }
	    else	/* cannot get table info */
	    {
		if (dmr.error.err_code == E_DM0055_NONEXT)
		{
		    status = E_DB_OK;
		    dmr.error.err_code = E_DB_OK;
		    break;	    /* no more attributes for this index */
		}
		else
		{
		    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, (i4)4,
					(PTR)&gw_rcb->gwr_tab_id.db_tab_base,
					(i4)4,
					(PTR)&gw_rcb->gwr_tab_id.db_tab_index);
			    gw_rcb->gwr_error.err_code =
					E_GW021E_GWU_MAP_IDX_ATT_ERROR;
			    break;
		    }
		    break;
		}
	    }

	    continue;   /* get next attribute for the base */
	}

	/*
	** Okay, now construct the row for tidp.  Reuse stage_buf for this.
	*/
	MEcopy(Gwf_facility->gwf_gw_info[gw_id].gwf_xatt_tidp, xatt_sz,
	       (PTR)&stage_buf[0]);
	tab_id = (DB_TAB_ID *)&stage_buf[0];
	STRUCT_ASSIGN_MACRO(gw_rcb->gwr_tab_id, *tab_id);
	attid_ptr = (i2 *)(&stage_buf[0] + sizeof(DB_TAB_ID));
	*attid_ptr = i + 1;
	xatt_rows[i] = &stage_buf[0];

	/*
	** Finally, put the iigwX_attribute tuples for the gateway secondary
	** index.
	*/

	dmr.dmr_data.data_in_size = xatt_sz;

	for (j=0; j<=i; j++)
	{
	    dmr.dmr_data.data_address = (PTR)xatt_rows[j];

	    if ((status = (*Dmf_cptr)(DMR_PUT, &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:
			/***note need args here to specify which catalog***/
			gwf_error(dmr.error.err_code, GWF_INTERR, 0);
			gwf_error(E_GW0320_DMR_PUT_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);
			gwf_error(E_GW0623_XCAT_PUT_FAILED, GWF_INTERR, 0);
			gw_rcb->gwr_error.err_code =
					E_GW021E_GWU_MAP_IDX_ATT_ERROR;
			break;
		}
		break;
	    }
	}

	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_GW021E_GWU_MAP_IDX_ATT_ERROR;
		    break;
	    }
	    break;
	}

	/* if we get here everything's OK... */
	break;
    }

    return(status);
}