Esempio n. 1
0
static void
crsr_close_sm( PTR arg )
{
    GCD_PCB	*pcb = (GCD_PCB *)arg;
    GCD_CCB	*ccb = pcb->ccb;
    GCD_SCB	*scb = pcb->scb;

  top:

    if ( GCD_global.gcd_trace_level >= 4 )
	TRdisplay( "%4d    GCD Close: %s\n", 
		    ccb->id, gcu_lookup( closeMap, ccb->sequence ) );

    switch( ccb->sequence++ )
    {
    case CLOSE_CURSOR :
	pcb->scb = NULL;
	gcd_push_callback( pcb, crsr_close_sm );
	gcd_del_stmt( pcb, scb );
	return;

    case CLOSE_XACT : 
	pcb->result.flags |= PCB_RSLT_CLOSED;

	if ( ccb->cib->flags & (GCD_CONN_ABORT | GCD_LOGIC_ERR) )  
	    break;	/* Handled below */

	gcd_push_callback( pcb, crsr_close_sm );

	if ( ccb->cib->flags & GCD_XACT_ABORT )
	    gcd_xact_abort( pcb );
	else
	    gcd_xact_check( pcb, GCD_XQOP_CURSOR_CLOSE );
	return;
    
    case CLOSE_DONE :
	gcd_send_done( ccb, &pcb->rcb, pcb );
	gcd_del_pcb( pcb );

	if ( ccb->cib->flags & GCD_CONN_ABORT )
	    gcd_sess_abort( ccb, FAIL );
	else  if ( ccb->cib->flags & GCD_LOGIC_ERR )
	    gcd_sess_abort( ccb, E_GC4809_INTERNAL_ERROR );
	else
	    gcd_msg_pause( ccb, TRUE );
	return;

    default :
	if ( GCD_global.gcd_trace_level >= 1 )
	    TRdisplay( "%4d    GCD invalid close sequence: %d\n", 
			ccb->id, --ccb->sequence );
	gcd_del_pcb( pcb );
	gcd_sess_abort( ccb, E_GC480A_PROTOCOL_ERROR );
	return;
    }

    goto top;
}
Esempio n. 2
0
bool
gcd_api_relXID( GCD_CCB *ccb )
{
    IIAPI_RELXIDPARM	parm;

    parm.rl_tranIdHandle = ccb->xact.distXID;
    ccb->xact.distXID = NULL;
    IIapi_releaseXID( &parm );

    if ( API_ERROR( parm.rl_status )  &&  GCD_global.gcd_trace_level >= 1 )
	TRdisplay( "%4d    GCD IIapi_releaseXID() status: %s\n", ccb->id, 
		   gcu_lookup( apiMap, parm.rl_status ) );

    return( API_ERROR( parm.rl_status ) ? FALSE : TRUE );
}
Esempio n. 3
0
bool
gcd_api_regXID( GCD_CCB *ccb, IIAPI_TRAN_ID *tranID )
{
    IIAPI_REGXIDPARM	parm;
    bool		success = FALSE;

    MEcopy( (PTR)tranID, sizeof( *tranID ), (PTR)&parm.rg_tranID );
    IIapi_registerXID( &parm );

    if ( ! API_ERROR( parm.rg_status ) )
    {
	ccb->xact.distXID = parm.rg_tranIdHandle;
	success = TRUE;
    }  
    else  if ( GCD_global.gcd_trace_level >= 1 )
    {
	TRdisplay( "%4d    GCD IIapi_registerXID() status: %s\n", ccb->id, 
		   gcu_lookup( apiMap, parm.rg_status ) );
    }

    return( success );
}
Esempio n. 4
0
static void
crsr_fetch_sm( PTR arg )
{
    GCD_PCB	*pcb = (GCD_PCB *)arg;
    GCD_CCB	*ccb = pcb->ccb;
    GCD_SCB	*scb = pcb->scb;

  top:

    if ( GCD_global.gcd_trace_level >= 4 )
	TRdisplay( "%4d    GCD Fetch: %s\n", 
		    ccb->id, gcu_lookup( fetchMap, ccb->sequence ) );

    switch( ccb->sequence++ )
    {
    case FETCH_INIT :
	/*
	** Validate current fetch state.
	*/
	if ( scb->column.cur_col != 0  ||  scb->column.more_segments )
	{
	    if ( GCD_global.gcd_trace_level >= 1 )
		TRdisplay("%4d    GCD previous fetch not complete: (%d,%d)\n",
			  ccb->id, scb->column.cur_col, scb->column.max_cols);
	    gcd_del_pcb( pcb );
	    gcd_sess_abort( ccb, E_GC480A_PROTOCOL_ERROR );
	    return;
	}

	/*
	** Allocate row/column buffers, if needed.
	** Note: for BYREF procedure parameters we
	** force at least two rows even though only
	** one is expected.  This allows detection
	** of end-of-data during row processing so
	** that the statement can be easily closed.
	*/
	if ( scb->flags & GCD_STMT_BYREF )  pcb->data.data.max_row = 2;

	if ( pcb->data.data.max_row > scb->column.max_rows  && 
	     ! gcd_alloc_qdata( &scb->column, pcb->data.data.max_row ) )
	{
	    gcd_del_pcb( pcb );
	    gcd_sess_abort( ccb, E_GC4808_NO_MEMORY );
	    return;
	}

	/*
	** Skip column set-up if only positioning.
	*/
	if ( ! pcb->data.data.max_row )  ccb->sequence = FETCH_POS;
        break;

    case FETCH_COLS :
    {
	IIAPI_DESCRIPTOR	*desc = (IIAPI_DESCRIPTOR *)scb->column.desc;
	u_i2			column;

	/*
	** If there is a BLOB column in the data set,
	** only fetch upto and including the BLOB (for
	** the first segment).  Additional segments will 
	** be fetched individually.  Remaining columns 
	** will be fetched once the BLOB is done.
	*/
	for( 
	     column = scb->column.cur_col; 
	     column < scb->column.max_cols; 
	     column++ 
	   )
	    if ( desc[ column ].ds_dataType == IIAPI_LVCH_TYPE  ||
		 desc[ column ].ds_dataType == IIAPI_LNVCH_TYPE ||
		 desc[ column ].ds_dataType == IIAPI_LBYTE_TYPE )
	    {
		/* Include BLOB and stop */
		column++;
		pcb->data.data.max_row = 1; 	/* BLOBs force single row */
		break;
	    }

	/*
	** Only one row allowed if partial row.  Preceding loop 
	** checked last column, need to check first column.
	*/
	if ( scb->column.cur_col )  pcb->data.data.max_row = 1;
	scb->column.col_cnt = column - scb->column.cur_col;
	pcb->data.data.col_cnt = scb->column.col_cnt;
	pcb->data.data.data = 
	    &((IIAPI_DATAVALUE *)scb->column.data)[ scb->column.cur_col ];

	/*
	** Skip positioning if doing simple NEXT.
	*/
	if ( pcb->data.data.reference == MSG_POS_CURRENT  &&
	     pcb->data.data.offset == 1 )
	    ccb->sequence = FETCH_FETCH;
	break;
    }

    case FETCH_POS :
	/*
	** Skip row processing if no rows are requested.
	*/
	if ( ! pcb->data.data.max_row )  ccb->sequence = FETCH_QINFO;
	gcd_push_callback( pcb, crsr_fetch_sm );
	gcd_api_position( pcb );
	return;

    case FETCH_FETCH :
	/*
	** Subsequent fetch (if any) will be simple NEXT.
	*/
	pcb->data.data.reference = MSG_POS_CURRENT;
	pcb->data.data.offset = 1;

	gcd_push_callback( pcb, crsr_fetch_sm );

	if ( ccb->msg.flags & GCD_MSG_XOFF )
	{
	    if ( GCD_global.gcd_trace_level >= 4 )
		TRdisplay( "%4d    GCD fetch pending OB XON\n", ccb->id );
	    ccb->msg.xoff_pcb = (PTR)pcb;
	    return;
	}

	gcd_api_getCol( pcb );
	return;

    case FETCH_ROWS :
	/*
	** Send row/column data to client.  
	**
	** Fetching continues if partial row received.
	** End-of-data if didn't receive all requested rows.
	** Non-cursor queries remain active (except at EOD).
	*/
	if ( pcb->api_error )
	    ccb->sequence = FETCH_CLEAR;
	else  if ( ! crsr_rows( ccb, scb, pcb ) )
	    ccb->sequence = FETCH_COLS;			/* partial row */
	else  if ( pcb->data.data.row_cnt < pcb->data.data.max_row )
	{
	    /*
	    ** For scrollable, sensitive cursor, several reasons
	    ** exist for receiving fewer than expected rows.  EOD
	    ** is never returned for a scrollable cursors.  The
	    ** DBMS returns the EOD indication for forward-only
	    ** cursors.  For all others, EOD must be generated.
	    */
	    if ( ! (scb->flags & GCD_STMT_CURSOR) )  
		pcb->result.flags |= PCB_RSLT_EOD;	/* end-of-data */
	}
	else  if ( ! (scb->flags & GCD_STMT_CURSOR) )  
	    ccb->sequence = FETCH_DONE;			/* keep active */
	break;

    case FETCH_QINFO : 
	gcd_push_callback( pcb, crsr_fetch_sm );
	gcd_api_gqi( pcb );
	return;

    case FETCH_CLEAR :
	ccb->api.stmt = NULL;	/* Statement is now dormant. */
	if ( pcb->api_error )  ccb->sequence = FETCH_CHECK;
	break;

    case FETCH_DONE :
	/*
	** Close statement if end-of-data and 
	** AUTO_CLOSE has been requested.
	*/
	if ( pcb->result.flags & PCB_RSLT_EOD  &&
	     scb->flags & GCD_STMT_AUTO_CLOSE )
	{
	    if ( GCD_global.gcd_trace_level >= 4 )
		TRdisplay( "%4d    GCD closing statement at EOD\n", ccb->id );
	    ccb->sequence = CLOSE_CURSOR;
	    crsr_close_sm( (PTR)pcb );
	    return;
	}

	/*
	** Continue fetching rows if requested
	** and not end-of-data.
	*/
	if ( scb->flags & GCD_STMT_FETCH_ALL  &&
	     ! (pcb->result.flags & PCB_RSLT_EOD) )
	{
	    if ( GCD_global.gcd_trace_level >= 4 )
		TRdisplay( "%4d    GCD fetch next block of rows\n", ccb->id );
	    ccb->sequence = FETCH_COLS;
	    ccb->api.stmt = scb->handle;	/* May have cleared above */
	}
	break;

    case FETCH_CHECK :
	if ( ccb->cib->flags & (GCD_CONN_ABORT | GCD_LOGIC_ERR) )  
	    break;	/* Handled below */

	if ( ccb->cib->flags & GCD_XACT_ABORT )
	{
	    gcd_push_callback( pcb, crsr_fetch_sm );
	    gcd_xact_abort( pcb );
	    return;
	}
	break;

    case FETCH_EXIT :
	gcd_send_done( ccb, &pcb->rcb, pcb );
	gcd_del_pcb( pcb );

	if ( ccb->cib->flags & GCD_CONN_ABORT )
	    gcd_sess_abort( ccb, FAIL );
	else  if ( ccb->cib->flags & GCD_LOGIC_ERR )
	    gcd_sess_abort( ccb, E_GC4809_INTERNAL_ERROR );
	else
	    gcd_msg_pause( ccb, TRUE );
	return;

    default :
	if ( GCD_global.gcd_trace_level >= 1 )
	    TRdisplay( "%4d    GCD invalid fetch sequence: %d\n", 
			ccb->id, --ccb->sequence );
	gcd_del_pcb( pcb );
	gcd_sess_abort( ccb, E_GC480A_PROTOCOL_ERROR );
	return;
    }

    goto top;
}
Esempio n. 5
0
void
gcd_msg_cursor( GCD_CCB *ccb )
{
    DAM_ML_CUR	cursor;
    STMT_ID	stmt_id;
    GCD_SCB	*scb;
    GCD_PCB	*pcb;
    STATUS	status;
    u_i2	pos_anchor = MSG_POS_CURRENT;	/* Default to NEXT */
    i4		pos_offset = 1;
    u_i4	pre_fetch = 1;
    bool	incomplete = FALSE;
    bool	got_id = FALSE;

    if ( ! gcd_get_i2( ccb, (u_i1 *)&cursor.cursor_op ) )
    {
	if ( GCD_global.gcd_trace_level >= 1 )
	    TRdisplay( "%4d    GCD no cursor op specified\n", ccb->id );
	gcd_sess_abort( ccb, E_GC480A_PROTOCOL_ERROR );
	return;
    }

    if ( GCD_global.gcd_trace_level >= 3 )
	TRdisplay( "%4d    GCD Cursor operation: %s\n", 
		   ccb->id, gcu_lookup( curMap, cursor.cursor_op ) );

    if ( ! (pcb = gcd_new_pcb( ccb ))  ||
         ! (pcb->rcb = gcd_new_rcb( ccb, -1 )) )
    {
	if ( pcb )  gcd_del_pcb( pcb );
	gcd_sess_abort( ccb, E_GC4808_NO_MEMORY );
	return;
    }

    while( ccb->msg.msg_len )
    {
	DAM_ML_PM	cp;
	u_i1		u_i1_val;
	u_i2		u_i2_val;
	u_i4		u_i4_val;

	incomplete = TRUE;
	if ( ! gcd_get_i2( ccb, (u_i1 *)&cp.param_id ) )  break;
	if ( ! gcd_get_i2( ccb, (u_i1 *)&cp.val_len ) )  break;

	switch( cp.param_id )
	{
	case MSG_CUR_STMT_ID :
	    if ( cp.val_len != (CV_N_I4_SZ * 2)  ||
	         ! gcd_get_i4( ccb, (u_i1 *)&stmt_id.id_high )  ||
		 ! gcd_get_i4( ccb, (u_i1 *)&stmt_id.id_low ) )
		break;

	    incomplete = FALSE;
	    got_id = TRUE;
	    break;
	
	case MSG_CUR_PRE_FETCH :
	    switch( cp.val_len )
	    {
	    case 1 : 
		if ( gcd_get_i1( ccb, (u_i1 *)&u_i1_val ) )
		{
		    pre_fetch = max( pre_fetch, u_i1_val );
		    incomplete = FALSE;
		}
		break;

	    case 2 :
		if ( gcd_get_i2( ccb, (u_i1 *)&u_i2_val ) )
		{
		    pre_fetch = max( pre_fetch, u_i2_val );
		    incomplete = FALSE;
		}
		break;

	    case 4 :
		if ( gcd_get_i4( ccb, (u_i1 *)&u_i4_val ) )
		{
		    pre_fetch = max( pre_fetch, u_i4_val );
		    incomplete = FALSE;
		}
		break;
	    }
	    break;

	case MSG_CUR_POS_ANCHOR :
	    switch( cp.val_len )
	    {
	    case 1 : 
		if ( gcd_get_i1( ccb, (u_i1 *)&u_i1_val ) )
		{
		    pos_anchor = (u_i2)u_i1_val;
		    incomplete = FALSE;
		}
		break;

	    case 2 :
		if ( gcd_get_i2( ccb, (u_i1 *)&u_i2_val ) )
		{
		    pos_anchor = (u_i2)u_i2_val;
		    incomplete = FALSE;
		}
		break;

	    case 4 :
		if ( gcd_get_i4( ccb, (u_i1 *)&u_i4_val ) )
		{
		    pos_anchor = (u_i2)u_i2_val;
		    incomplete = FALSE;
		}
		break;
	    }
	    break;

	case MSG_CUR_POS_OFFSET :
	    if ( cp.val_len != CV_N_I4_SZ  ||
		 ! gcd_get_i4( ccb, (u_i1 *)&pos_offset ) )
		break;

	    incomplete = FALSE;
	    break;
	
	default :
	    if ( GCD_global.gcd_trace_level >= 3 )
		TRdisplay( "%4d    GCD     unkown parameter ID %d\n",
			   ccb->id, cp.param_id );
	    break;
	}

	if ( incomplete )  break;
    }

    if ( incomplete )
    {
	if ( GCD_global.gcd_trace_level >= 1 )
	    TRdisplay( "%4d    GCD unable to read all cursor parameters %d\n",
		       ccb->id );
	status = E_GC480A_PROTOCOL_ERROR;
    }
    else  if ( ! got_id )
    {
	if ( GCD_global.gcd_trace_level >= 1 )
	    TRdisplay( "%4d    GCD no cursor ID for cursor message\n", 
			ccb->id );
	status = E_GC480A_PROTOCOL_ERROR;
    }
    else
	status = OK;

    if ( status != OK )
    {
	gcd_del_pcb( pcb );
	gcd_sess_abort( ccb, status );
	return;
    }

    if ( ! (scb = gcd_find_stmt( ccb, &stmt_id )) )
    {
	if ( GCD_global.gcd_trace_level >= 1 )
	    TRdisplay( "%4d    GCD no active statement for cursor ID\n", 
			ccb->id );
	gcd_sess_error( ccb, &pcb->rcb, E_GC4811_NO_STMT );
	gcd_send_done( ccb, &pcb->rcb, pcb );
	gcd_del_pcb( pcb );
	gcd_msg_pause( ccb, TRUE );
	return;
    }

    switch( cursor.cursor_op )
    {
    case MSG_CUR_CLOSE :
	ccb->sequence = CLOSE_CURSOR;
	pcb->scb = scb;
	crsr_close_sm( (PTR)pcb );
	break;
    
    case MSG_CUR_FETCH :
	ccb->sequence = FETCH_INIT;
	ccb->api.stmt = scb->handle;		/* Activate statement */
	pcb->scb = scb;
	pcb->data.data.reference = pos_anchor;
	pcb->data.data.offset = pos_offset;
	pcb->data.data.max_row = pre_fetch;

	crsr_fetch_sm( (PTR)pcb );
	break;

    default :
	if ( GCD_global.gcd_trace_level >= 1 )
	    TRdisplay( "%4d    GCD invalid cursor op: %d\n", 
			ccb->id, cursor.cursor_op );
	gcd_del_pcb( pcb );
	gcd_sess_abort( ccb, E_GC480A_PROTOCOL_ERROR );
    }

    return;
}
Esempio n. 6
0
static STATUS
gcd_api_status( char *func_name, IIAPI_GENPARM *genParm, 
		 GCD_CCB *ccb, GCD_RCB **rcb_ptr )
{
    IIAPI_STATUS	api_status = genParm->gp_status;
    bool		api_error = API_ERROR( genParm->gp_status );
    bool		dbms_error = FALSE;
    STATUS		status = OK;

    if ( (api_error  &&  GCD_global.gcd_trace_level >= 1)  ||
	 GCD_global.gcd_trace_level >= 2 )
	TRdisplay( "%4d    GCD %s status: %s\n", ccb->id, func_name, 
		   gcu_lookup( apiMap, genParm->gp_status ) );

    if ( genParm->gp_errorHandle )
    {
	IIAPI_GETEINFOPARM	get;

	get.ge_errorHandle = genParm->gp_errorHandle;
	IIapi_getErrorInfo( &get );

	while( get.ge_status == IIAPI_ST_SUCCESS )
	{
	    u_i2 msg_len = get.ge_message ? (u_i2)STlength(get.ge_message) : 0;

	    switch( get.ge_type )
	    {
	    case IIAPI_GE_ERROR   : 
		switch( get.ge_errorCode )
		{
		case E_AP0001_CONNECTION_ABORTED :
		    ccb->cib->flags |= GCD_CONN_ABORT;
		    break;

		case E_AP0002_TRANSACTION_ABORTED : 
		    ccb->cib->flags |= GCD_XACT_ABORT;
		    break;

		case E_AP0003_ACTIVE_TRANSACTIONS : 
		case E_AP0004_ACTIVE_QUERIES : 
		case E_AP0006_INVALID_SEQUENCE : 
		    ccb->cib->flags |= GCD_LOGIC_ERR;
		    break;
		}

		if ( ! dbms_error )
		{
		    status = get.ge_errorCode;
		    dbms_error = TRUE;
		}

		if ( GCD_global.gcd_trace_level >= 2 )
		    TRdisplay( "%4d    GCD Error 0x%x '%s'\n", ccb->id, 
			       get.ge_errorCode, get.ge_SQLSTATE );
		if ( GCD_global.gcd_trace_level >= 3  &&  get.ge_message )
		    TRdisplay( "%4d    GCD     %s\n", ccb->id, get.ge_message );

		if ( rcb_ptr )
		    gcd_send_error( ccb, rcb_ptr, MSG_ET_ERR, get.ge_errorCode,
				    get.ge_SQLSTATE, msg_len, get.ge_message );
		break;


	    case IIAPI_GE_XAERR :
		if ( GCD_global.gcd_trace_level >= 2 )
		    TRdisplay( "%4d    GCD XA Error %d\n", ccb->id, 
			       get.ge_errorCode );

		if ( ! dbms_error )
		{
		    status = FAIL;
		    dbms_error = TRUE;
		}

		if ( rcb_ptr )
		    gcd_send_error( ccb, rcb_ptr, MSG_ET_XA, get.ge_errorCode,
				    get.ge_SQLSTATE, msg_len, get.ge_message );
	        break;

	    case IIAPI_GE_WARNING : 
		if ( GCD_global.gcd_trace_level >= 2 )
		    TRdisplay( "%4d    GCD Warning 0x%x '%s'\n", 
		    	       ccb->id, get.ge_errorCode, get.ge_SQLSTATE );
		if ( GCD_global.gcd_trace_level >= 3  &&  get.ge_message )
		    TRdisplay( "%4d    GCD     %s\n", ccb->id, get.ge_message );

		if ( rcb_ptr )
		    gcd_send_error( ccb, rcb_ptr, MSG_ET_WRN, get.ge_errorCode,
				    get.ge_SQLSTATE, msg_len, get.ge_message );
		break;

	    default :
		if ( GCD_global.gcd_trace_level >= 2 )
		    TRdisplay( "%4d    GCD User Message 0x%x\n", 
		    	       ccb->id, get.ge_errorCode );
		if ( GCD_global.gcd_trace_level >= 3  &&  get.ge_message )
		    TRdisplay( "%4d    GCD     %s\n", ccb->id, get.ge_message );

		if ( rcb_ptr )
		    gcd_send_error( ccb, rcb_ptr, MSG_ET_MSG, get.ge_errorCode,
				    get.ge_SQLSTATE, msg_len, get.ge_message );
		break;
	    }

	    IIapi_getErrorInfo( &get );
	}
    }

    if ( dbms_error  &&  ! status )  
	status = E_GC4809_INTERNAL_ERROR;
    else  if ( api_error  &&  ! dbms_error )
    {
	status = (api_status == IIAPI_ST_OUT_OF_MEMORY)
		 ? E_GC4808_NO_MEMORY : E_GC4809_INTERNAL_ERROR;
	if ( rcb_ptr )  gcd_sess_error( ccb, rcb_ptr, status );
    }

    return( status );
}
Esempio n. 7
0
STATUS
gcd_api_init( u_i2 api_ver, PTR *env )
{
    IIAPI_INITPARM	init;
    IIAPI_SETENVPRMPARM	set;
    bool		done;
    STATUS		status = OK;

    init.in_timeout = -1;
    init.in_version = api_ver;

    IIapi_initialize( &init );

    if ( init.in_status != IIAPI_ST_SUCCESS  &&
	 GCD_global.gcd_trace_level >= 1 )
	TRdisplay( "%4d    GCD Error initializing API: %s\n", 
		   -1, gcu_lookup( apiMap, init.in_status ) );

    switch( init.in_status )
    {
    case IIAPI_ST_SUCCESS :
	*env = init.in_envHandle;
	break;
    
    case IIAPI_ST_OUT_OF_MEMORY :
	status = E_GC4808_NO_MEMORY;
	break;
    
    default :
	status = E_GC4809_INTERNAL_ERROR;
	break;
    }

    for( done = (status != OK); ! done; done = TRUE )
    {
	II_LONG	value;

	set.se_envHandle = *env;
	set.se_paramID = IIAPI_EP_TRACE_FUNC;
	set.se_paramValue = (II_PTR)gcd_api_trace;

	IIapi_setEnvParam( &set );
	if ( (status = set.se_status) != OK )  break;

	if( api_ver >= IIAPI_VERSION_6 )
	{
	    set.se_paramID = IIAPI_EP_DATE_ALIAS;
	    set.se_paramValue = IIAPI_EPV_INGDATE;

	    IIapi_setEnvParam( &set );
	    if ( (status = set.se_status) != OK )  break;
	}

	set.se_paramID = IIAPI_EP_DATE_FORMAT;
	value = IIAPI_EPV_DFRMT_FINNISH;
	set.se_paramValue = (II_PTR)&value;

	IIapi_setEnvParam( &set );
	if ( (status = set.se_status) != OK )  break;

	set.se_paramID = IIAPI_EP_TIMEZONE;
	set.se_paramValue = "gmt";

	IIapi_setEnvParam( &set );
	if ( (status = set.se_status) != OK )  break;

	set.se_paramID = IIAPI_EP_MAX_SEGMENT_LEN;
	value = 8192;
	set.se_paramValue = (II_PTR)&value;

	IIapi_setEnvParam( &set );
	if ( (status = set.se_status) != OK )  break;
   
	set.se_paramID = IIAPI_EP_DECIMAL_CHAR;
	set.se_paramValue  = ".";

	IIapi_setEnvParam( &set );
	if ( (status = set.se_status) != OK )  break;

	set.se_paramID = IIAPI_EP_MONEY_SIGN ;
	set.se_paramValue  = "$";

	IIapi_setEnvParam( &set );
	if ( (status = set.se_status) != OK )  break;

	set.se_paramID = IIAPI_EP_MONEY_LORT ;
	value = IIAPI_EPV_MONEY_LEAD_SIGN;
	set.se_paramValue  =  (II_PTR)&value;

	IIapi_setEnvParam( &set );
	if ( (status = set.se_status) != OK )  break;

	set.se_paramID = IIAPI_EP_MONEY_PRECISION ;
	value = 2;
	set.se_paramValue  =  (II_PTR)&value;

	IIapi_setEnvParam( &set );
	if ( (status = set.se_status) != OK )  break;
    }

    if ( status != OK )
	gcu_erlog( 0, GCD_global.language, status, NULL, 0, NULL );

    return( status );
}
Esempio n. 8
0
void
jdbc_xact_check( JDBC_PCB *pcb, u_i1 xqop )
{
    JDBC_CCB	*ccb = pcb->ccb;

    if ( JDBC_global.trace_level >= 4 )
	TRdisplay( "%4d    JDBC %s %s %s\n", ccb->id, 
		   ccb->cib->autocommit ? "Autocommit" :
		       (ccb->xact.xacm_multi ? "Multi-cursor" : "Transaction"),
		   ccb->cib->tran ? "active" : "inactive",
		   ccb->cib->autocommit ? 
		       gcu_lookup( modeMap, ccb->xact.auto_mode ) : "" );
    /*
    ** Non-autocommit transactions are handled entirely
    ** through the DBMS, so there is nothing to do if
    ** autocommit is disabled (watch out for multi-cursor
    ** simulated autocommit mode which temporarily disables
    ** autocommit).
    */
    if ( ! ccb->cib->autocommit  &&  ! ccb->xact.xacm_multi )
    {
	jdbc_pop_callback( pcb );
	return;
    }

    switch( ccb->xact.auto_mode )
    {
    case JDBC_XACM_DBMS :
	/*
	** Autocommit is being handled by the DBMS, but
	** autocommit may not yet have been enabled.
	** Start autocommit transaction if not yet started
	** (jdbc_api_autocommit() will make callback when
	** completed).  Otherwise, nothing to do.
	*/
	if ( ! ccb->cib->tran )
	    jdbc_api_autocommit( pcb, TRUE );
	else
	    jdbc_pop_callback( pcb );
	break;
    
    case JDBC_XACM_SINGLE :
	/*
	** Autocommit is being handled by the DBMS and
	** only a single cursor is permitted to be open.
	** An open cursor will be closed if an open 
	** cursor or non-cursor request is made to avoid 
	** an error when sending the request to the DBMS.
	**
	** The autocommit enable optimization is also
	** done for this mode, so turn on autocommit if
	** not enabled.
	*/
	if ( ! ccb->cib->tran )
	    jdbc_api_autocommit( pcb, TRUE );
	else  switch( xqop )
	{
	case JDBC_XQOP_NON_CURSOR :
	case JDBC_XQOP_CURSOR_OPEN :
	    jdbc_purge_stmt( pcb );
	    break;

	case JDBC_XQOP_CURSOR_UPDATE :
	case JDBC_XQOP_CURSOR_CLOSE :
	default : 
	    jdbc_pop_callback( pcb );
	    break;
	}
	break;

    case JDBC_XACM_MULTI :
	/*
	** Autocommit handled by DBMS only when cursors are
	** not open.  A normal transaction is used while
	** cursors are open and commited once all cursors
	** are closed.
	*/
	switch( xqop )
	{
	case JDBC_XQOP_NON_CURSOR :
	case JDBC_XQOP_CURSOR_UPDATE :
	    /*
	    ** Turn on autocommit if not enabled.
	    */
	    if ( ccb->cib->autocommit  &&  ! ccb->cib->tran )
		jdbc_api_autocommit( pcb, TRUE );
	    else
		jdbc_pop_callback( pcb );
	    break;

	case JDBC_XQOP_CURSOR_OPEN :
	    /*
	    ** Turn off autocommit to prepare for a normal 
	    ** transaction activated by the cursor open.
	    */
	    if ( ccb->xact.xacm_multi )
		jdbc_pop_callback( pcb );
	    else
	    {
		ccb->cib->autocommit = FALSE;
		ccb->xact.xacm_multi = TRUE;

		if ( ccb->cib->tran )
		    jdbc_api_autocommit( pcb, FALSE );
		else
		    jdbc_pop_callback( pcb );
	    }
	    break;

	case JDBC_XQOP_CURSOR_CLOSE :
	    /*
	    ** If no cursors are open, commit the
	    ** normal transaction activated by the
	    ** open cursor request and return our
	    ** state to autocommit.
	    **
	    ** We should not reach this point if
	    ** autocommit is actually enabled
	    ** (should be simulated autocommit),
	    ** but handle this condition just to
	    ** be safe.
	    */
	    if ( ccb->cib->autocommit )
	    {
		if ( ccb->cib->tran )
		    jdbc_pop_callback( pcb );
		else
		    jdbc_api_autocommit( pcb, TRUE );
	    }
	    else  if ( jdbc_active_stmt( ccb ) )
		jdbc_pop_callback( pcb );
	    else
	    {
		ccb->xact.xacm_multi = FALSE;
		ccb->cib->autocommit = TRUE;

		if ( ccb->cib->tran )
		    jdbc_api_commit( pcb );
		else
		    jdbc_pop_callback( pcb );
	    }
	    break;

	default : 
	    /*
	    ** Should not happen.
	    */
	    jdbc_pop_callback( pcb );
	    break;
	}
	break;

    default :
	if ( JDBC_global.trace_level >= 1 )
	    TRdisplay( "%4d    JDBC invalid xact autocommit mode: %d\n",
		       ccb->id, ccb->xact.auto_mode );
	jdbc_pop_callback( pcb );
	break;
    }

    return;
}
Esempio n. 9
0
static void
msg_xact_sm( PTR arg )
{
    JDBC_PCB	*pcb = (JDBC_PCB *)arg;
    JDBC_CCB	*ccb = pcb->ccb;

    /*
    ** If not yet allocated, allocate the RCB.
    */
    if ( ! pcb->rcb  &&  ! (pcb->rcb = jdbc_new_rcb( ccb )) )
    {
	jdbc_del_pcb( pcb );
	jdbc_gcc_abort( ccb, E_JD0108_NO_MEMORY );
	return;
    }

  top:

    if ( JDBC_global.trace_level >= 4 )
	TRdisplay( "%4d    JDBC xact process seq %s\n",
		   ccb->id, gcu_lookup( xactSeqMap, ccb->sequence ) );

    switch( ccb->sequence++ )
    {
    case XACT_COMMIT :				/* Commit */
	ccb->sequence = XACT_NEW_ID;
	jdbc_push_callback( pcb, msg_xact_sm );
	jdbc_api_commit( pcb );
	return;

    case XACT_ROLLBACK :			/* Rollback */
	ccb->sequence = XACT_NEW_ID;
	jdbc_push_callback( pcb, msg_xact_sm );
	jdbc_api_rollback( pcb );
	return;
    
    case XACT_AC_ON :  				/* Enable autocommit */
	/*
	** We don't actually turn on autocommit here,
	** rather we just flag autocommit requested 
	** (see jdbc_xact_check()).
	**
	** We need to commit the existing standard
	** transaction (which requires a new ID).
	*/
	ccb->cib->autocommit = TRUE;
	ccb->sequence = XACT_NEW_ID;
	jdbc_push_callback( pcb, msg_xact_sm );
	jdbc_api_commit( pcb );
	return;

    case XACT_AC_OFF : 				/* Disable autocommit */
	ccb->cib->autocommit = FALSE;
	ccb->sequence = XACT_DONE;
	jdbc_push_callback( pcb, msg_xact_sm );
	jdbc_api_autocommit( pcb, FALSE );	
	return;

    case XACT_BEGIN :				/* Begin Distributed */
	/*
	** Register the distributed transaction ID.
	*/
	if ( ! jdbc_api_regXID( pcb->ccb, &pcb->data.tran.distXID ) )
	{
	    jdbc_sess_error( ccb, &pcb->rcb, E_JD0116_XACT_REG_XID );
	    ccb->sequence = XACT_DONE;
	    break;
	}

	/*
	** Issue a query to associate DBMS transaction with 
	** the XID.  This also has the effect of translating 
	** the OpenAPI Transaction Name Handle into an OpenAPI
	** Transaction Handle for the distributed transaction.
	*/
	ccb->cib->tran = ccb->xact.distXID;
	pcb->data.query.type = IIAPI_QT_QUERY;
	pcb->data.query.params = FALSE;
	pcb->data.query.text = ccb->qry.qtxt;

	ccb->sequence = XACT_GQI;
	jdbc_push_callback( pcb, msg_xact_sm );
	jdbc_api_query( pcb );
	return;

    case XACT_PREPARE :				/* Prepare (2PC) */
	ccb->sequence = XACT_DONE;
	jdbc_push_callback( pcb, msg_xact_sm );
	jdbc_api_prepare( pcb );
	return;

    case XACT_GQI :				/* Get query info */
	if ( pcb->api_error )
	{
	    /*
	    ** The distributed XID is placed in the transaction 
	    ** handle to start a distributed transaction.  A real
	    ** real transaction handle should be returned.  If
	    ** not, clear the transaction handle.
	    */ 
	    if ( ccb->cib->tran == ccb->xact.distXID ) ccb->cib->tran = NULL;
	    ccb->sequence = XACT_CANCEL;
	    break;
	}

	ccb->sequence = XACT_CLOSE;
	jdbc_push_callback( pcb, msg_xact_sm );
	jdbc_api_gqi( pcb );
	return;

    case XACT_NEW_ID :				/* New Transaction ID */
	ccb->sequence = XACT_DONE;
	ccb->xact.tran_id++;
	ccb->stmt.stmt_id = 0;
	break;

    case XACT_CANCEL :				/* Cancel query */
	jdbc_flush_msg( ccb );
	jdbc_push_callback( pcb, msg_xact_sm );
	jdbc_api_cancel( pcb );
	return;

    case XACT_CLOSE :				/* Close query */
	jdbc_push_callback( pcb, msg_xact_sm );
	jdbc_api_close( pcb, NULL );
	return;
	
    case XACT_DONE :				/* Processing completed */
	jdbc_send_done( ccb, &pcb->rcb, pcb );
	jdbc_del_pcb( pcb );
	jdbc_msg_pause( ccb, TRUE );
	return;

    default :
	if ( JDBC_global.trace_level >= 1 )
	    TRdisplay( "%4d    JDBC invalid xact processing sequence: %d\n",
		       ccb->id, --ccb->sequence );
	jdbc_del_pcb( pcb );
	jdbc_gcc_abort( ccb, E_JD0109_INTERNAL_ERROR);
	return;
    }

    goto top;
}
Esempio n. 10
0
void
jdbc_msg_xact( JDBC_CCB *ccb )
{
    JDBC_PCB		*pcb;
    IIAPI_II_TRAN_ID	iid;
    IIAPI_XA_TRAN_ID	xid;
    u_i2		*p_req = p_req_xa;
    u_i2		req_id, p_rec = 0;
    bool		done = FALSE;
    bool		incomplete = FALSE;

    if ( ! jdbc_get_i2( ccb, (u_i1 *)&req_id ) )
    {
	if ( JDBC_global.trace_level >= 1 )
	    TRdisplay( "%4d    JDBC invalid XACT message format\n", 
			ccb->id );
	jdbc_gcc_abort( ccb, E_JD010A_PROTOCOL_ERROR );
	return;
    }

    if ( JDBC_global.trace_level >= 3 )
	TRdisplay( "%4d    JDBC Transaction request: %s\n", 
		   ccb->id, gcu_lookup( xactMap, req_id ) );

    if ( JDBC_global.trace_level >= 4 )
	TRdisplay( "%4d    JDBC %s %s %s\n", ccb->id, 
		   ccb->cib->autocommit ? "Autocommit" :
		       (ccb->xact.xacm_multi ? "Multi-cursor" : "Transaction"),
		   ccb->cib->tran ? "active" : "inactive",
		   ccb->cib->autocommit ? 
		       gcu_lookup( modeMap, ccb->xact.auto_mode ) : "" );

    MEfill( sizeof( xid ), 0, (PTR)&xid );

    /*
    ** Read the request parameters.
    */
    while( ccb->msg.msg_len )
    {
	JDBC_MSG_PM xp;

	incomplete = TRUE;
	if ( ! jdbc_get_i2( ccb, (u_i1 *)&xp.param_id ) )  break;
	if ( ! jdbc_get_i2( ccb, (u_i1 *)&xp.val_len ) )  break;

	switch( xp.param_id )
	{
	case JDBC_XP_II_XID :
	    if ( xp.val_len != (CV_N_I4_SZ * 2)  ||
		 ! jdbc_get_i4( ccb, (u_i1 *)&iid.it_lowTran )  ||
		 ! jdbc_get_i4( ccb, (u_i1 *)&iid.it_highTran ) )
		break;

	    p_rec |= XP_II_XID;
	    incomplete = FALSE;
	    p_req = p_req_ing;
	    break;

	case JDBC_XP_XA_FRMT :
	    if ( xp.val_len != CV_N_I4_SZ  ||
		 ! jdbc_get_i4( ccb, (u_i1 *)&xid.xt_formatID ) )
		break;

	    p_rec |= XP_FRMT;
	    incomplete = FALSE;
	    break;

	case JDBC_XP_XA_GTID :
	    if ( xid.xt_bqualLength  &&  xp.val_len <= IIAPI_XA_MAXGTRIDSIZE )
	    {
		/* BQUAL follows GTRID in data array */
		int i;

		for( i = xid.xt_bqualLength - 1; i >= 0; i-- )
		    xid.xt_data[ xp.val_len + i ] = xid.xt_data[ i ];
	    }

	    if ( xp.val_len > IIAPI_XA_MAXGTRIDSIZE  ||
		 ! jdbc_get_bytes( ccb, xp.val_len, (u_i1 *)&xid.xt_data[0] ) )
		break;
	    
	    xid.xt_gtridLength  = xp.val_len;
	    p_rec |= XP_GTID;
	    incomplete = FALSE;
	    break;

	case JDBC_XP_XA_BQUAL :
	    if ( xp.val_len > IIAPI_XA_MAXBQUALSIZE  ||
		 ! jdbc_get_bytes( ccb, xp.val_len, 
				   (u_i1 *)&xid.xt_data[xid.xt_gtridLength] ) )
		break;
	    
	    xid.xt_bqualLength = xp.val_len;
	    p_rec |= XP_BQUAL;
	    incomplete = FALSE;
	    break;

	default :
	    if ( JDBC_global.trace_level >= 1 )
		TRdisplay( "%4d    JDBC     unkown parameter ID %d\n",
			   ccb->id, xp.param_id );
	    break;
	}

	if ( incomplete )  break;
    }

    if ( incomplete  ||  
	 (p_rec & p_req[ req_id ]) != p_req[ req_id ]  ||
	 (p_rec & ~(p_req[ req_id ] | p_opt[ req_id ])) )
    {
	if ( JDBC_global.trace_level >= 1 )
	    if ( incomplete )
		TRdisplay( "%4d    JDBC unable to read all request params %d\n",
			   ccb->id );
	    else
		TRdisplay( "%4d    JDBC invalid or missing request params %d\n",
			   ccb->id );
	jdbc_gcc_abort( ccb, E_JD010A_PROTOCOL_ERROR );
	return;
    }

    /*
    ** Don't allocate the RCB at this time so that there
    ** is no client error message produced when purging
    ** statements.
    */
    if ( ! (pcb = jdbc_new_pcb( ccb, FALSE )) )
    {
	jdbc_gcc_abort( ccb, E_JD0108_NO_MEMORY );
	return;
    }

    switch( req_id )
    {
    case JDBC_XACT_COMMIT :
	if ( 
	     ccb->cib->autocommit  ||  	/* Autocommit enabled */
	     ccb->xact.xacm_multi  ||	/* Simulated autocommit */
	     ! ccb->cib->tran 		/* No active transaction */
	   )  
	    done = TRUE;
	else
	    ccb->sequence = XACT_COMMIT;
	break;
    
    case JDBC_XACT_ROLLBACK :
	if ( 
	     ccb->cib->autocommit  ||	/* Autocommit enabled */
	     ccb->xact.xacm_multi  ||	/* Simulated autocommit */
	     ! ccb->cib->tran 		/* No active transaction */
	   )
	    done = TRUE;
	else
	    ccb->sequence = XACT_ROLLBACK;
	break;
    
    case JDBC_XACT_AC_ENABLE :
	if ( ccb->cib->autocommit  ||  ccb->xact.xacm_multi )
	    done = TRUE;	/* Already enabled */
	else  if ( ! ccb->cib->tran )
	{
	    /*
	    ** We don't actually turn on autocommit here,
	    ** rather we just flag autocommit requested 
	    ** (see jdbc_xact_check()).
	    */
	    ccb->cib->autocommit = TRUE;
	    done = TRUE;
	}
	else  if ( ccb->xact.distXID )
	{
	    jdbc_sess_error( ccb, &pcb->rcb, E_JD0110_XACT_AC_STATE );
	    done = TRUE;
	}
	else
	{
	    /*
	    ** A standard transaction is active: close all 
	    ** active statements and commit the transaction.
	    */
	    ccb->sequence = XACT_AC_ON;
	}
	break;
    
    case JDBC_XACT_AC_DISABLE :
	if ( ! ccb->cib->tran )
	{
	    ccb->cib->autocommit = FALSE;
	    ccb->xact.xacm_multi = FALSE;
	    done = TRUE;
	}
	else  if ( ccb->cib->autocommit )
	    ccb->sequence = XACT_AC_OFF;	/* Disable autocommit */
	else  if ( ccb->xact.distXID )
	{
	    jdbc_sess_error( ccb, &pcb->rcb, E_JD0110_XACT_AC_STATE );
	    done = TRUE;
	}
	else
	{
	    /*
	    ** There is a standard transaction active.
	    ** (possibly for autocommit simulation).
	    ** Commit the transaction (and disable
	    ** autocommit simulation).
	    */
	    ccb->xact.xacm_multi = FALSE;
	    ccb->sequence = XACT_COMMIT;
	}
	break;
    
    case JDBC_XACT_BEGIN :
	if ( ccb->cib->tran  ||  ccb->xact.distXID  ||
	     ccb->cib->autocommit  ||  ccb->xact.xacm_multi )
	{
	    jdbc_sess_error( ccb, &pcb->rcb, E_JD0114_XACT_BEGIN_STATE );
	    done = TRUE;
	}
	else
	{
	    char xid_str[ 512 ];

	    ccb->sequence = XACT_BEGIN;

	    if ( p_req == p_req_ing )
	    {
		pcb->data.tran.distXID.ti_type = IIAPI_TI_IIXID;
		STcopy( JDBC_XID_NAME, xid_str );
		STcopy( xid_str, 
		    pcb->data.tran.distXID.ti_value.iiXID.ii_tranName );
		pcb->data.tran.distXID.ti_value.iiXID.ii_tranID.it_highTran =
		    iid.it_highTran;
		pcb->data.tran.distXID.ti_value.iiXID.ii_tranID.it_lowTran =
		    iid.it_lowTran;

		if ( ! jdbc_expand_qtxt( ccb, STlength( beginII ) + 
					      STlength( xid_str ), FALSE ) )
		{
		    jdbc_del_pcb( pcb );
		    jdbc_gcc_abort( ccb, E_JD0108_NO_MEMORY );
		    return;
		}

		STprintf( ccb->qry.qtxt, beginII, xid_str );
	    }
	    else
	    {
		pcb->data.tran.distXID.ti_type = IIAPI_TI_XAXID;
		pcb->data.tran.distXID.ti_value.xaXID.xa_branchSeqnum = 
		    JDBC_XID_SEQNUM;
		pcb->data.tran.distXID.ti_value.xaXID.xa_branchFlag = 
		    JDBC_XID_FLAGS;

		MEcopy( (PTR)&xid, sizeof( xid ),
			(PTR)&pcb->data.tran.distXID.ti_value.xaXID.xa_tranID );
		formatXID( &pcb->data.tran.distXID.ti_value.xaXID, xid_str );

		if ( ! jdbc_expand_qtxt( ccb, STlength( beginXA ) + 
					      STlength( xid_str ), FALSE ) )
		{
		    jdbc_del_pcb( pcb );
		    jdbc_gcc_abort( ccb, E_JD0108_NO_MEMORY );
		    return;
		}

		STprintf( ccb->qry.qtxt, beginXA, xid_str );
	    }
	}
	break;

    case JDBC_XACT_PREPARE :
	if ( ! ccb->cib->tran  ||  ! ccb->xact.distXID )
	{
	    jdbc_sess_error( ccb, &pcb->rcb, E_JD0115_XACT_PREP_STATE );
	    done = TRUE;
	}
	else
	    ccb->sequence = XACT_PREPARE;
	break;

    default :
	if ( JDBC_global.trace_level >= 1 )
	    TRdisplay( "%4d    JDBC invalid XACT operation: %d\n", 
			ccb->id, req_id );
	jdbc_del_pcb( pcb );
	jdbc_gcc_abort( ccb, E_JD010A_PROTOCOL_ERROR );
	return;
    }

    if ( done )
    {
	jdbc_send_done( ccb, &pcb->rcb, NULL );
	jdbc_del_pcb( pcb );
	jdbc_msg_pause( ccb, TRUE );
    }
    else
    {
	/*
	** Before changing the transaction state,
	** make sure all statements have been closed.
	*/
	jdbc_push_callback( pcb, msg_xact_sm );
	jdbc_purge_stmt( pcb );
    }

    return;
}