II_EXTERN II_VOID II_FAR II_EXPORT IIapi_autocommit( IIAPI_AUTOPARM II_FAR *autoParm ) { IIAPI_TRANHNDL *tranHndl; IIAPI_CONNHNDL *connHndl; IIAPI_TRACE( IIAPI_TR_TRACE )("IIapi_autocommit: set autocommit state\n"); /* ** Validate Input parameters */ if ( ! autoParm ) { IIAPI_TRACE( IIAPI_TR_ERROR ) ( "IIapi_autocommit: null autocommit parameters\n" ); return; } autoParm->ac_genParm.gp_completed = FALSE; autoParm->ac_genParm.gp_status = IIAPI_ST_SUCCESS; autoParm->ac_genParm.gp_errorHandle = NULL; connHndl = (IIAPI_CONNHNDL *)autoParm->ac_connHandle; tranHndl = (IIAPI_TRANHNDL *)autoParm->ac_tranHandle; /* ** Make sure API is initialized */ if ( ! IIapi_initialized() ) { IIAPI_TRACE( IIAPI_TR_ERROR ) ( "IIapi_autocommit: API is not initialized\n" ); IIapi_appCallback( &autoParm->ac_genParm, NULL, IIAPI_ST_NOT_INITIALIZED ); return; } if ( ! connHndl && ! tranHndl ) { IIAPI_TRACE( IIAPI_TR_ERROR ) ( "IIapi_autocommit: no handle provided\n" ); IIapi_appCallback( &autoParm->ac_genParm, NULL, IIAPI_ST_INVALID_HANDLE ); return; } if ( connHndl && (! IIapi_isConnHndl( connHndl ) || IIAPI_STALE_HANDLE( connHndl )) ) { IIAPI_TRACE( IIAPI_TR_ERROR ) ( "IIapi_autocommit: invalid connection handle\n" ); IIapi_appCallback( &autoParm->ac_genParm, NULL, IIAPI_ST_INVALID_HANDLE ); return; } if ( tranHndl && (! IIapi_isTranHndl( tranHndl ) || IIAPI_STALE_HANDLE( tranHndl )) ) { IIAPI_TRACE( IIAPI_TR_ERROR ) ( "IIapi_autocommit: invalid transaction handle\n" ); IIapi_appCallback( &autoParm->ac_genParm, NULL, IIAPI_ST_INVALID_HANDLE ); return; } IIAPI_TRACE( IIAPI_TR_INFO ) ( "IIapi_autocommit: connHndl = %p, tranHndl = %p\n", autoParm->ac_connHandle, autoParm->ac_tranHandle ); if ( connHndl ) IIapi_clearAllErrors( (IIAPI_HNDL *)connHndl ); if ( tranHndl ) IIapi_clearAllErrors( (IIAPI_HNDL *)tranHndl ); if ( ! tranHndl && ! IIapi_isQueEmpty( &connHndl->ch_tranHndlList ) ) { /* ** Application is attempting to enable autocommit mode ** with an active transaction. */ IIAPI_TRACE( IIAPI_TR_ERROR ) ( "IIapi_autocommit: can't enable autocommit in a transaction\n" ); if ( ! IIapi_localError( (IIAPI_HNDL *)connHndl, E_AP0003_ACTIVE_TRANSACTIONS, II_SS25000_INV_XACT_STATE, IIAPI_ST_FAILURE ) ) IIapi_appCallback( &autoParm->ac_genParm, NULL, IIAPI_ST_OUT_OF_MEMORY ); else IIapi_appCallback( &autoParm->ac_genParm, (IIAPI_HNDL *)connHndl, IIAPI_ST_FAILURE ); return; } if ( tranHndl && ! IIapi_isQueEmpty( &tranHndl->th_stmtHndlList ) ) { /* ** Application is attempting to disable autocommit mode ** with active statements. */ IIAPI_TRACE( IIAPI_TR_ERROR ) ("IIapi_autocommit: can't disable autocommit with active statements\n"); if ( ! IIapi_localError( (IIAPI_HNDL *)tranHndl, E_AP0004_ACTIVE_QUERIES, II_SS25000_INV_XACT_STATE, IIAPI_ST_FAILURE ) ) IIapi_appCallback( &autoParm->ac_genParm, NULL, IIAPI_ST_OUT_OF_MEMORY ); else IIapi_appCallback( &autoParm->ac_genParm, (IIAPI_HNDL *)tranHndl, IIAPI_ST_FAILURE ); return; } if ( ! tranHndl ) { /* ** Enable autocommit mode. Create a transaction handle ** and return it to the application. */ if ( ! ( tranHndl = IIapi_createTranHndl( NULL, connHndl ) ) ) { IIAPI_TRACE( IIAPI_TR_ERROR ) ( "IIapi_autocommit: createTranHndl failed\n" ); IIapi_appCallback( &autoParm->ac_genParm, NULL, IIAPI_ST_OUT_OF_MEMORY ); return; } autoParm->ac_tranHandle = (II_PTR)tranHndl; } else { /* ** Disable autocommit mode. The transaction handle ** will be deleted, so clear the output parameter. */ autoParm->ac_tranHandle = NULL; } IIapi_uiDispatch( IIAPI_EV_AUTO_FUNC, (IIAPI_HNDL *)tranHndl, (II_PTR)autoParm ); return; }
II_EXTERN II_BOOL IIapi_termAPI( IIAPI_ENVHNDL *envHndl ) { IIAPI_ENVHNDL *defEnvHndl; II_BOOL last_term = FALSE; if ( ! IIapi_static ) return( TRUE ); defEnvHndl = IIapi_defaultEnvHndl(); if ( envHndl ) { /* ** Free the environment handle. */ MUp_semaphore( &IIapi_static->api_semaphore ); QUremove( (QUEUE *)envHndl ); MUv_semaphore( &IIapi_static->api_semaphore ); IIapi_deleteEnvHndl( envHndl ); } else { /* ** Decrement the usage counter in ** the default environment handle. */ MUp_semaphore( &defEnvHndl->en_semaphore ); defEnvHndl->en_initCount = max( 0, defEnvHndl->en_initCount - 1 ); MUv_semaphore( &defEnvHndl->en_semaphore ); } /* ** Shutdown API when all version 1 initializers have terminated ** and there are no active version 2 environments. */ if ( ! defEnvHndl->en_initCount && IIapi_isQueEmpty( &IIapi_static->api_env_q ) ) { QUEUE *q; IIAPI_TRACE( IIAPI_TR_TRACE ) ( "IIapi_termAPI: shutting down API completely.\n" ); /* ** Free the default environment. */ IIapi_deleteEnvHndl( (IIAPI_ENVHNDL *)IIapi_static->api_env_default ); IIapi_static->api_env_default = NULL; /* ** Shutdown sub-systems. */ IIapi_termGCA(); IIapi_termADF(); IIAPI_TRACE( IIAPI_TR_INFO )( "IIapi_termAPI: API shutdown.\n" ); IIAPI_TERMTRACE(); /* ** Free the remaining global resources. */ if (IIapi_static->api_ucode_ctbl) MEfree (IIapi_static->api_ucode_ctbl); if (IIapi_static->api_ucode_cvtbl) MEfree (IIapi_static->api_ucode_cvtbl); MEtls_destroy( &IIapi_static->api_thread, MEfree ); MUr_semaphore( &IIapi_static->api_semaphore ); MEfree( (PTR)IIapi_static ); IIapi_static = NULL; last_term = TRUE; } return( last_term ); }
II_EXTERN II_VOID II_FAR II_EXPORT IIapi_batch( IIAPI_BATCHPARM II_FAR *batchParm ) { IIAPI_CONNHNDL *connHndl; IIAPI_TRANHNDL *tranHndl; IIAPI_STMTHNDL *stmtHndl; IIAPI_HNDL *handle; IIAPI_TRACE( IIAPI_TR_TRACE )( "IIapi_batch: adding a batch query\n" ); /* ** Validate Input parameters */ if ( ! batchParm ) { IIAPI_TRACE( IIAPI_TR_ERROR ) ( "IIapi_batch: null batch parameters\n" ); return; } batchParm->ba_genParm.gp_completed = FALSE; batchParm->ba_genParm.gp_status = IIAPI_ST_SUCCESS; batchParm->ba_genParm.gp_errorHandle = NULL; connHndl = (IIAPI_CONNHNDL *)batchParm->ba_connHandle; handle = (IIAPI_HNDL *)batchParm->ba_tranHandle; stmtHndl = (IIAPI_STMTHNDL *)batchParm->ba_stmtHandle; /* ** Make sure API is initialized */ if ( ! IIapi_initialized() ) { IIAPI_TRACE( IIAPI_TR_ERROR ) ( "IIapi_batch: API is not initialized\n" ); IIapi_appCallback( &batchParm->ba_genParm, NULL, IIAPI_ST_NOT_INITIALIZED ); return; } /* ** Validate connection handle. */ if ( ! IIapi_isConnHndl( connHndl ) || IIAPI_STALE_HANDLE( connHndl ) ) { IIAPI_TRACE( IIAPI_TR_ERROR ) ( "IIapi_batch: invalid connHndl %p\n", connHndl ); IIapi_appCallback( &batchParm->ba_genParm, NULL, IIAPI_ST_INVALID_HANDLE ); return; } /* ** Validate transaction handle. */ if ( handle && ! IIapi_isTranName( (IIAPI_TRANNAME *)handle ) && (! IIapi_isTranHndl( (IIAPI_TRANHNDL *)handle ) || IIAPI_STALE_HANDLE( handle )) ) { IIAPI_TRACE( IIAPI_TR_ERROR ) ( "IIapi_batch: invalid tranHndl %p\n", handle ); IIapi_appCallback( &batchParm->ba_genParm, NULL, IIAPI_ST_INVALID_HANDLE ); return; } /* ** Validate statement handle. */ if ( stmtHndl ) { if ( ! IIapi_isStmtHndl( (IIAPI_STMTHNDL *)stmtHndl ) || IIAPI_STALE_HANDLE( stmtHndl ) ) { IIAPI_TRACE( IIAPI_TR_ERROR ) ( "IIapi_batch: invalid stmtHndl %p\n", stmtHndl ); IIapi_appCallback( &batchParm->ba_genParm, NULL, IIAPI_ST_INVALID_HANDLE ); return; } if ( ! handle || IIapi_isTranName( (IIAPI_TRANNAME *)handle) ) { IIAPI_TRACE( IIAPI_TR_ERROR ) ( "IIapi_batch: transaction handle required\n" ); IIapi_appCallback( &batchParm->ba_genParm, NULL, IIAPI_ST_INVALID_HANDLE ); return; } if ( handle != (IIAPI_HNDL *)stmtHndl->sh_tranHndl ) { IIAPI_TRACE( IIAPI_TR_ERROR ) ( "IIapi_batch: wrong tranHndl %p for stmtHndl %p\n", handle, stmtHndl ); IIapi_appCallback( &batchParm->ba_genParm, NULL, IIAPI_ST_INVALID_HANDLE ); return; } if ( connHndl != IIapi_getConnHndl( (IIAPI_HNDL *)stmtHndl ) ) { IIAPI_TRACE( IIAPI_TR_ERROR ) ( "IIapi_batch: wrong connHndl %p for stmtHndl %p\n", connHndl, stmtHndl ); IIapi_appCallback( &batchParm->ba_genParm, NULL, IIAPI_ST_INVALID_HANDLE ); return; } } IIAPI_TRACE( IIAPI_TR_INFO ) ( "IIapi_batch: connHndl = %p, tranHndl = %p, stmtHndl = %p, queryType = %d\n", batchParm->ba_connHandle, batchParm->ba_tranHandle, batchParm->ba_stmtHandle, batchParm->ba_queryType ); IIAPI_TRACE( IIAPI_TR_INFO ) ( "IIapi_batch: queryText = %s\n", batchParm->ba_queryText ? batchParm->ba_queryText : "<NULL>" ); IIapi_clearAllErrors( stmtHndl ? (IIAPI_HNDL *)stmtHndl : ( (handle && IIapi_isTranHndl( (IIAPI_TRANHNDL *)handle )) ? handle : (IIAPI_HNDL *)connHndl ) ); /* ** Check that batch processing is supported on the connection. */ if ( connHndl->ch_partnerProtocol < GCA_PROTOCOL_LEVEL_68 ) { IIAPI_TRACE( IIAPI_TR_ERROR ) ( "IIapi_batch: batch not supported at protocol level %d\n", connHndl->ch_partnerProtocol ); if ( ! IIapi_localError( (IIAPI_HNDL *)connHndl, E_AP001F_BATCH_UNSUPPORTED, II_SS50008_UNSUPPORTED_STMT, IIAPI_ST_FAILURE ) ) IIapi_appCallback( &batchParm->ba_genParm, NULL, IIAPI_ST_OUT_OF_MEMORY ); else IIapi_appCallback( &batchParm->ba_genParm, (IIAPI_HNDL *)connHndl, IIAPI_ST_FAILURE ); return; } /* ** Check restrictions on query type and associated info. */ if ( connHndl->ch_type != IIAPI_SMT_SQL || (batchParm->ba_queryType != IIAPI_QT_QUERY && batchParm->ba_queryType != IIAPI_QT_EXEC && batchParm->ba_queryType != IIAPI_QT_EXEC_PROCEDURE) ) { IIAPI_TRACE( IIAPI_TR_ERROR ) ( "IIapi_batch: invalid query type %d for connection type %d\n", batchParm->ba_queryType, connHndl->ch_type ); if ( ! IIapi_localError( (IIAPI_HNDL *)connHndl, E_AP0011_INVALID_PARAM_VALUE, II_SS50008_UNSUPPORTED_STMT, IIAPI_ST_FAILURE ) ) IIapi_appCallback( &batchParm->ba_genParm, NULL, IIAPI_ST_OUT_OF_MEMORY ); else IIapi_appCallback( &batchParm->ba_genParm, (IIAPI_HNDL *)connHndl, IIAPI_ST_FAILURE ); return; } if ( batchParm->ba_queryType != IIAPI_QT_EXEC_PROCEDURE && ! batchParm->ba_queryText ) { IIAPI_TRACE( IIAPI_TR_ERROR ) ( "IIapi_batch: query requires query text\n" ); if ( ! IIapi_localError( (IIAPI_HNDL *)connHndl, E_AP0011_INVALID_PARAM_VALUE, II_SS5000R_RUN_TIME_LOGICAL_ERROR, IIAPI_ST_FAILURE ) ) IIapi_appCallback( &batchParm->ba_genParm, NULL, IIAPI_ST_OUT_OF_MEMORY ); else IIapi_appCallback( &batchParm->ba_genParm, (IIAPI_HNDL *)connHndl, IIAPI_ST_FAILURE ); return; } if ( batchParm->ba_queryType == IIAPI_QT_EXEC_PROCEDURE && ! batchParm->ba_parameters ) { IIAPI_TRACE( IIAPI_TR_ERROR ) ( "IIapi_batch: query requires parameters, none indicated\n" ); if ( ! IIapi_localError( (IIAPI_HNDL *)connHndl, E_AP0011_INVALID_PARAM_VALUE, II_SS5000R_RUN_TIME_LOGICAL_ERROR, IIAPI_ST_FAILURE ) ) IIapi_appCallback( &batchParm->ba_genParm, NULL, IIAPI_ST_OUT_OF_MEMORY ); else IIapi_appCallback( &batchParm->ba_genParm, (IIAPI_HNDL *)connHndl, IIAPI_ST_FAILURE ); return; } /* ** Allocate a transaction handle if one was not provided. */ if ( ! handle || IIapi_isTranName( (IIAPI_TRANNAME *)handle ) ) { /* ** Check to see if there is an active transaction. */ if ( ! IIapi_isQueEmpty( (QUEUE *)&connHndl->ch_tranHndlList ) ) { IIAPI_TRACE( IIAPI_TR_ERROR ) ("IIapi_batch: connection has active transaction.\n"); if ( ! IIapi_localError( (IIAPI_HNDL *)connHndl, E_AP0003_ACTIVE_TRANSACTIONS, II_SS25000_INV_XACT_STATE, IIAPI_ST_FAILURE ) ) IIapi_appCallback( &batchParm->ba_genParm, NULL, IIAPI_ST_OUT_OF_MEMORY ); else IIapi_appCallback( &batchParm->ba_genParm, (IIAPI_HNDL *)connHndl, IIAPI_ST_FAILURE ); return; } if ( ! ( tranHndl = IIapi_createTranHndl( (IIAPI_TRANNAME *)batchParm->ba_tranHandle, (IIAPI_CONNHNDL *)batchParm->ba_connHandle ) ) ) { IIAPI_TRACE( IIAPI_TR_ERROR ) ( "IIapi_batch: createTranHndl failed\n" ); IIapi_appCallback( &batchParm->ba_genParm, NULL, IIAPI_ST_OUT_OF_MEMORY ); return; } } else { /* ** Use existing transaction handle. */ tranHndl = (IIAPI_TRANHNDL *)handle; IIapi_clearAllErrors( (IIAPI_HNDL *)tranHndl ); } /* ** Allocate a new statement handle or initialize existing handle. */ if ( stmtHndl ) initStmtHndl( stmtHndl ); else if ( ! (stmtHndl = IIapi_createStmtHndl( connHndl, tranHndl )) ) { IIAPI_TRACE( IIAPI_TR_ERROR ) ( "IIapi_batch: createStmtHndl failed\n" ); IIapi_appCallback( &batchParm->ba_genParm, NULL, IIAPI_ST_OUT_OF_MEMORY ); goto freeTranHandle; } /* ** Update statement handle with batch query information. */ if ( batchParm->ba_queryText && ! (stmtHndl->sh_queryText = STalloc( batchParm->ba_queryText )) ) { IIAPI_TRACE( IIAPI_TR_FATAL ) ( "IIapi_batch: can't alloc query text\n" ); IIapi_appCallback( &batchParm->ba_genParm, NULL, IIAPI_ST_OUT_OF_MEMORY ); goto freeStmtHandle; } stmtHndl->sh_queryType = batchParm->ba_queryType; if ( batchParm->ba_parameters ) stmtHndl->sh_flags |= IIAPI_SH_PARAMETERS; /* ** The current set of external batch/query flags ** are not applicable to batch processing, but ** we pass them along anyway. */ stmtHndl->sh_flags |= batchParm->ba_flags & IIAPI_QF_ALL_FLAGS; batchParm->ba_stmtHandle = (II_PTR)stmtHndl; batchParm->ba_tranHandle = (II_PTR)tranHndl; IIapi_uiDispatch( IIAPI_EV_BATCH_FUNC, (IIAPI_HNDL *)stmtHndl, (II_PTR)batchParm ); return; freeStmtHandle: /* ** If the statement handle is not the input handle, ** then we allocated a new handle above and we must ** now delete it. */ if ( stmtHndl != (IIAPI_STMTHNDL *)batchParm->ba_stmtHandle ) IIapi_deleteStmtHndl( stmtHndl ); freeTranHandle: /* ** If the transaction handle is not the input handle, ** then we allocated a new handle above and we must ** now delete it. */ if ( tranHndl != (IIAPI_TRANHNDL *)batchParm->ba_tranHandle ) IIapi_deleteTranHndl( tranHndl ); return; }