/*
* Class:     org_trafodion_jdbc_t2_T2Driver
* Method:    setCharsetEncodingOverride
* Signature: (I)Ljava/lang/String;
* Note: This function is a generic implementation to allow setting the
*       char set override encoding for the given charset (currently only the ISO88591
*       column is allowed to be overriden)
*/
JNIEXPORT void JNICALL Java_org_trafodion_jdbc_t2_T2Driver_setCharsetEncodingOverride(JNIEnv *jenv, jclass jcls,
																					jint charset, jstring encodingOverride)
{
	FUNCTION_ENTRY("Java_org_trafodion_jdbc_t2_T2Driver_setCharsetEncodingOverride",
		("charset=%ld, encodingOverride=%s",charset, DebugJString(jenv,encodingOverride)));

	//Added for connect/disconnect impro.
		 if (srvrGlobal == NULL)
		 MEMORY_ALLOC_PERM(srvrGlobal,SRVR_GLOBAL_Def)

	for (int idx=0; idx<gJNICache.totalCharsets; idx++)
		if (charset == gJNICache.charsetInfo[idx].charset)
		{
			const char *nEncodingOverride = JNI_GetStringUTFChars(jenv,encodingOverride, NULL);
			if (strcmp(nEncodingOverride,defaultEncodingOption) == 0)
			{
				gJNICache.charsetInfo[idx].useDefaultEncoding = TRUE;
			}
			else
			{
				gJNICache.charsetInfo[idx].useDefaultEncoding = FALSE;
			}
			JNI_ReleaseStringUTFChars(jenv,encodingOverride, nEncodingOverride);
		}
		FUNCTION_RETURN_VOID((NULL));
}
/*
* Class:     org_trafodion_jdbc_t2_T2Driver
* Method:    checkLibraryVersion
* Signature: (Ljava/lang/String;)V
*/
JNIEXPORT void JNICALL Java_org_trafodion_jdbc_t2_T2Driver_checkLibraryVersion(JNIEnv *jenv, jclass jcls,
																			 jstring javaVproc)
{


#ifdef NSK_PLATFORM	// Linux port - ToDo txn related
		int cliret = client_initialization();//by venu for TSLX
		if (cliret != 1)//client init return 1 on success
		{

				DEBUG_OUT(DEBUG_LEVEL_TXN,("TSLX initialization failed %d", cliret));

		}
		DEBUG_OUT(DEBUG_LEVEL_TXN,("TSLX Initialization done"));
#endif

	//Added for R3.0 Transaction issue sol. 10-100430-9906


	FUNCTION_ENTRY("Java_org_trafodion_jdbc_t2_T2Driver_checkLibraryVersion",("javaVproc=%s",
		DebugJString(jenv,javaVproc)));

	// Set the TMLIB cleanup 
	setTM_enable_cleanup();

#ifdef NSK_PLATFORM		// Linux port
  	short status = tmfInit();

  	DEBUG_OUT(DEBUG_LEVEL_TXN,("tmfInit() returned %d", status));

  	if (status != 0)
  	{
  		throwTransactionException(jenv, status);
  		FUNCTION_RETURN_VOID(("status(%d) is non-zero",status));
	}
#endif

//End





	if (javaVproc && !driverVersionChecked)
	{
		const char *java_vproc_str = JNI_GetStringUTFChars(jenv,javaVproc, NULL);
		if (java_vproc_str)
		{
			if (strcmp(java_vproc_str,driverVproc)!=0)
			{
				printf("JDBC Library Version Error - Jar: %s Jni: %s\n",
					java_vproc_str,driverVproc);
				abort();
			}
			JNI_ReleaseStringUTFChars(jenv,javaVproc, java_vproc_str);
			driverVersionChecked = true;
		}
	}
	FUNCTION_RETURN_VOID((NULL));
}
JNIEXPORT jobject JNICALL Java_org_trafodion_jdbc_t2_SQLMXDatabaseMetaData_getSchemas
  (JNIEnv *jenv, jobject jobj, jstring server, jlong dialogueId, jint txid, 
  jboolean autoCommit, jint txnMode, jstring schemaPattern)
{
	FUNCTION_ENTRY("Java_org_trafodion_jdbc_t2_SQLMXDatabaseMetaData_getSchemas",("server=%s, dialogueId=0x%08x, txid=0x%08x, autoCommit=%s, txnMode=%ld, schemaPattern=%s",
		DebugJString(jenv,server),
		dialogueId,
		txid,
        DebugBoolStr(autoCommit),
		txnMode,
		DebugJString(jenv,schemaPattern)));

	jobject rc = getSQLCatalogsInfo(jenv, jobj, server, dialogueId,  txid, autoCommit, txnMode, 
		SQL_API_SQLTABLES_JDBC, NULL, schemaPattern,
		NULL, NULL, NULL, 0, 0, 0, 0, 0, 0, 1, NULL, NULL, NULL);
	
	FUNCTION_RETURN_PTR(rc, (NULL));
}
JNIEXPORT void JNICALL Java_org_trafodion_jdbc_t2_SQLMXStatement_closeUsingLabel
(JNIEnv *jenv, jclass jclass, jstring server, jlong dialogueId,
 jstring stmtLabel, jboolean dropStmt)
{
    FUNCTION_ENTRY("Java_org_trafodion_jdbc_t2_SQLMXStatement_closeUsingLabel",("... stmtLabel=%s, dialogueId=0x%08x, dropStmt=%s",
                   DebugJString(jenv,stmtLabel),
                   dialogueId,
                   DebugBoolStr(dropStmt)));

    ExceptionStruct				exception_;
    long						rowsAffected;
    ERROR_DESC_LIST_def			sqlWarning;
    ERROR_DESC_def				*error_desc_def;
    const char					*nStmtLabel;

    if (stmtLabel)
        nStmtLabel = JNI_GetStringUTFChars(jenv,stmtLabel, NULL);
    else
    {
        throwSQLException(jenv, INVALID_STMT_LABEL_ERROR, NULL, "HY000");
        FUNCTION_RETURN_VOID(("stmtLabel is NULL"));
    }

    odbc_SQLSvc_CloseUsingLabel_sme_(NULL, NULL, &exception_,
                                     dialogueId,
                                     (char *)nStmtLabel,
                                     (dropStmt ? SQL_DROP : SQL_CLOSE),
                                     &rowsAffected,
                                     &sqlWarning);

    if (stmtLabel)
        JNI_ReleaseStringUTFChars(jenv,stmtLabel, nStmtLabel);
    // Ignore setting warning since the input is jclass and not jobject
    switch (exception_.exception_nr)
    {
    case CEE_SUCCESS:
        break;
    case odbc_SQLSvc_Close_SQLError_exn_:
        break;
    case odbc_SQLSvc_Close_ParamError_exn_:
        throwSQLException(jenv, PROGRAMMING_ERROR, exception_.u.ParamError.ParamDesc, "HY000");
        break;
    case odbc_SQLSvc_Close_InvalidConnection_exn_:
    case odbc_SQLSvc_Close_TransactionError_exn_:
    default:
        // TFDS - This exceptions should not happen
        throwSQLException(jenv, PROGRAMMING_ERROR, NULL, "HY000", exception_.exception_nr);
        break;
    }
    FUNCTION_RETURN_VOID((NULL));
}
/*
* Class:     org_trafodion_jdbc_t2_T2Driver
* Method:    setDefaultEncoding
* Signature: (Ljava/lang/String;)V
*/
JNIEXPORT void JNICALL Java_org_trafodion_jdbc_t2_T2Driver_setDefaultEncoding(JNIEnv *jenv, jclass jcls,
																			jstring encoding)
{
	FUNCTION_ENTRY("Java_org_trafodion_jdbc_t2_T2Driver_setDefaultEncoding",("encoding=%s",
		DebugJString(jenv,encoding)));
	gJNICache.defaultCharset = SQLCHARSETCODE_UNKNOWN;
	if (encoding)
	{
		const char *encoding_str = JNI_GetStringUTFChars(jenv,encoding, NULL);
		if (encoding_str)
		{
			gJNICache.defaultCharset = getCharset(encoding_str);
			JNI_ReleaseStringUTFChars(jenv,encoding, encoding_str);
		}
	}
	FUNCTION_RETURN_VOID((NULL));
}
JNIEXPORT jboolean JNICALL Java_org_trafodion_jdbc_t2_SQLMXResultSet_fetchN
  (JNIEnv *jenv, jobject jobj, jstring server, jlong dialogueId, jint txid, jint txnMode,
		jlong stmtId, 
		jint maxRowCnt, jint queryTimeout, jint holdability)
{
	FUNCTION_ENTRY("Java_org_trafodion_jdbc_t2_SQLMXResultSet_fetchN",("server=%s, dialogueId=0x%08x, txid=0x%08x, txnMode=%ld, stmtId=0x%08x, maxRowCnt=%ld, queryTimeout=%ld, holdability=%ld",
		DebugJString(jenv,server),
		dialogueId,
		txid,
		txnMode,
		stmtId,
		maxRowCnt,
		queryTimeout,
		holdability));

	ExceptionStruct			exception_;
	SQLValueList_def		outputValueList;
	long					rowsAffected;
	BOOL					retCode = FALSE;
	ERROR_DESC_LIST_def		sqlWarning;
	jint					currentTxid = txid;
	jint					externalTxid = 0;
	const char				*nStmtLabel;
	
	SRVR_STMT_HDL	*pSrvrStmt;
	long			sqlcode;
	short			txn_status;

	if ((pSrvrStmt = getSrvrStmt(dialogueId, stmtId, &sqlcode)) == NULL)
	{
		throwSQLException(jenv, INVALID_HANDLE_ERROR, NULL, "HY000", sqlcode);
		FUNCTION_RETURN_NUMERIC(false,("getSrvrStmt() returned NULL"));
	}

	if ((txn_status = beginTxnControl(jenv, currentTxid, externalTxid, txnMode, holdability)) != 0)
	{
		jenv->CallVoidMethod(jobj, gJNICache.setCurrentTxidRSMethodId, currentTxid);
		throwTransactionException(jenv, txn_status);
		FUNCTION_RETURN_NUMERIC(false,("beginTxnControl() failed"));
	}

	odbc_SQLSvc_FetchN_sme_(NULL, NULL, &exception_,
			dialogueId, stmtId, maxRowCnt, FALSE, queryTimeout, &rowsAffected, &outputValueList,
			&sqlWarning);

	if ((txn_status = endTxnControl(jenv, currentTxid, 0, FALSE, 
		(exception_.exception_nr == odbc_SQLSvc_FetchN_SQLNoDataFound_exn_ ? CEE_SUCCESS : 
			exception_.exception_nr), TRUE, txnMode, externalTxid)) != 0)
	{
		jenv->CallVoidMethod(jobj, gJNICache.setCurrentTxidRSMethodId, currentTxid);
		throwTransactionException(jenv, txn_status);
		FUNCTION_RETURN_NUMERIC(false,("endTxnControl() Failed"));
	}
	switch (exception_.exception_nr)
	{
	case CEE_SUCCESS:
		if (sqlWarning._length != 0)
			setSQLWarning(jenv, jobj, &sqlWarning);

		setFetchOutputs(jenv, jobj, pSrvrStmt, &outputValueList, rowsAffected, 
			rowsAffected < maxRowCnt ? TRUE : FALSE, TRUE, currentTxid);

		retCode = TRUE;
		break;
	case odbc_SQLSvc_FetchN_SQLNoDataFound_exn_:
		jenv->CallVoidMethod(jobj, gJNICache.setCurrentTxidRSMethodId, currentTxid);
		break;
	case odbc_SQLSvc_FetchN_SQLQueryCancelled_exn_:
		jenv->CallVoidMethod(jobj, gJNICache.setCurrentTxidRSMethodId, currentTxid);
		throwSQLException(jenv, QUERY_CANCELLED_ERROR, NULL, "HY008", 
			exception_.u.SQLQueryCancelled.sqlcode);
		break;
	case odbc_SQLSvc_FetchN_SQLError_exn_:
		jenv->CallVoidMethod(jobj, gJNICache.setCurrentTxidRSMethodId, currentTxid);
		throwSQLException(jenv, &exception_.u.SQLError);
		break;
	case odbc_SQLSvc_FetchN_ParamError_exn_:
		jenv->CallVoidMethod(jobj, gJNICache.setCurrentTxidRSMethodId, currentTxid);
		throwSQLException(jenv, PROGRAMMING_ERROR, exception_.u.ParamError.ParamDesc, "HY000");
		break;
	case odbc_SQLSvc_FetchN_SQLInvalidHandle_exn_:
		jenv->CallVoidMethod(jobj, gJNICache.setCurrentTxidRSMethodId, currentTxid);
		throwSQLException(jenv, INVALID_HANDLE_ERROR, NULL, "HY000", exception_.u.SQLInvalidHandle.sqlcode);
		break;
	case odbc_SQLSvc_FetchN_SQLStillExecuting_exn_:
	case odbc_SQLSvc_FetchN_InvalidConnection_exn_:
	case odbc_SQLSvc_FetchN_TransactionError_exn_:
	default:
// TFDS
		jenv->CallVoidMethod(jobj, gJNICache.setCurrentTxidRSMethodId, currentTxid);
		throwSQLException(jenv, PROGRAMMING_ERROR, NULL, "HY000", exception_.exception_nr);
		break;
	}
	FUNCTION_RETURN_NUMERIC(retCode,(DebugBoolStr(retCode)));
}
JNIEXPORT void JNICALL Java_org_trafodion_jdbc_t2_SQLMXResultSet_close
  (JNIEnv *jenv, jobject jobj, jstring server, jlong dialogueId, jint txid, jboolean autoCommit, jint txnMode,
	jlong stmtId, jboolean dropStmt)
{
	FUNCTION_ENTRY("Java_org_trafodion_jdbc_t2_SQLMXResultSet_close",("server=%s, dialogueId=0x%08x, txid=0x%08x, autoCommit=%s, txnMode=%ld, stmtId=0x%08x, dropStmt=%s",
		DebugJString(jenv,server),
		dialogueId,
		txid,
		DebugBoolStr(autoCommit),
		txnMode,
        	stmtId,
		DebugBoolStr(dropStmt)));

	jint						currentTxid = txid;
	jint						externalTxid = 0;
	jboolean					selectStmt = FALSE;
	ExceptionStruct				exception_;
	long						rowsAffected;
	ERROR_DESC_LIST_def			sqlWarning;
	short						txn_status;
	
	ERROR_DESC_def				*error_desc_def;
	// Don't bother resuming the transaction, if it is already zero. Try and close the cursor
	if (currentTxid != 0)
	{
		if ((txn_status = beginTxnControl(jenv, currentTxid, externalTxid, txnMode, CLOSE_CURSORS_AT_COMMIT)) != 0 )
		{
			jenv->CallVoidMethod(jobj, gJNICache.setCurrentTxidRSMethodId, currentTxid);
			throwTransactionException(jenv, txn_status);
			FUNCTION_RETURN_VOID(("beginTxnControl() failed"));
		}
	}
	
	odbc_SQLSvc_Close_sme_(NULL, NULL, &exception_,
					dialogueId,
					stmtId,
					(dropStmt ? SQL_DROP : SQL_CLOSE),
					&rowsAffected,
					&sqlWarning);
	
	if (currentTxid != 0)
	{
		if ((txn_status = endTxnControl(jenv, currentTxid, 0, autoCommit, 0, selectStmt, txnMode, externalTxid)) != 0)
		{
			jenv->CallVoidMethod(jobj, gJNICache.setCurrentTxidRSMethodId, currentTxid);
			throwTransactionException(jenv, txn_status);
			FUNCTION_RETURN_VOID(("endTxnControl() failed"));
		}
		jenv->CallVoidMethod(jobj, gJNICache.setCurrentTxidRSMethodId, currentTxid);
	}	
	
	switch (exception_.exception_nr)
	{
	case CEE_SUCCESS:
		// Not updating rowsAffected, since it is not useful in JDBC
		if (sqlWarning._length != 0)
			setSQLWarning(jenv, jobj, &sqlWarning);
		selectStmt = FALSE;
		break;
	case odbc_SQLSvc_Close_SQLError_exn_:
		error_desc_def =((ERROR_DESC_LIST_def *)(&exception_.u.SQLError.errorList))->_buffer;
		if (error_desc_def->sqlcode == -8811)		// Close a non-existant cursor and hence don't end 
													// the transaction by treating it like Select stmt
			selectStmt = TRUE;	
		// sql Error in case of close could be treated as SQLWarning
		setSQLWarning(jenv, jobj, &exception_.u.SQLError.errorList);
		break;
	case odbc_SQLSvc_Close_ParamError_exn_:
		throwSQLException(jenv, PROGRAMMING_ERROR, exception_.u.ParamError.ParamDesc, "HY000");
		break;
	case odbc_SQLSvc_Close_InvalidConnection_exn_:
	case odbc_SQLSvc_Close_TransactionError_exn_:
	default:
	// TFDS - This exceptions should not happen
		throwSQLException(jenv, PROGRAMMING_ERROR, NULL, "HY000", exception_.exception_nr);
		break;
	}
	FUNCTION_RETURN_VOID((NULL));
}
// MFC - added two parameters to set the MFC on/off and the directory
JNIEXPORT void JNICALL Java_org_trafodion_jdbc_t2_T2Driver_SQLMXInitialize(JNIEnv *jenv, jclass cls,
																		 jstring language, jint nowaitOn, jstring moduleCaching, jstring compiledModuleLocation)
{
	FUNCTION_ENTRY("Java_org_trafodion_jdbc_t2_T2Driver_SQLMXInitialize",("language=%s, nowaitOn=%ld",
		DebugJString(jenv,language),
		nowaitOn));
	const char 					*nLanguage;
	//	static GlobalInformation	*globalInfo = new GlobalInformation();
	//MFC
	const char					*nModuleCaching;
	const char					*nCompiledModuleLocation;

/*
	// Seaquest related - Linux port
	int argc = 0;
	char *argv[] = {"AAA"};
	//argv[0] = NULL;
	// Initialize seabed
	int	sbResult;
	char buffer[FILENAME_MAX] = {0};
	bzero(buffer, sizeof(buffer));
	
	sbResult = file_init_attach(&argc, &argv, true, buffer);
	if(sbResult != XZFIL_ERR_OK){
		abort();
	}
	sbResult = file_mon_process_startup(true);
	if(sbResult != XZFIL_ERR_OK){
		abort();
	}
	msg_mon_enable_mon_messages(true);
	// End Seaquest related
*/

	if (!driverVersionChecked)
	{
		printf("JDBC Library Version Error - Jar: Unknown Jni: %s\n",
			driverVproc);
		abort();
	}

	GlobalInformation::setSQLMX_Version();

	if (srvrGlobal == NULL)
		MEMORY_ALLOC_PERM(srvrGlobal,SRVR_GLOBAL_Def)
	else
	{
		if (srvrGlobal->boolFlgforInitialization == 1)
			FUNCTION_RETURN_VOID(("Already Initialized"));
	}


	if (! cacheJNIObjects(jenv))
		FUNCTION_RETURN_VOID(("cacheJNIObjects() failed"));

#ifdef NSK_PLATFORM		// Linux port
	if (language)
	{
		nLanguage = JNI_GetStringUTFChars(jenv,language, NULL);
		if (strcmp(nLanguage, "ja") == 0)
		{
			srvrGlobal->clientLCID = MAKELCID(MAKELANGID(LANG_JAPANESE, SUBLANG_DEFAULT), SORT_DEFAULT);
			srvrGlobal->clientErrorLCID = srvrGlobal->clientLCID;
		}
		else
			if (strcmp(nLanguage, "en") == 0)
			{
				srvrGlobal->clientLCID = MAKELCID(MAKELANGID(LANG_ENGLISH, SUBLANG_DEFAULT), SORT_DEFAULT);
				srvrGlobal->clientErrorLCID = srvrGlobal->clientLCID;
			}
			else
			{
				srvrGlobal->clientLCID = LANG_NEUTRAL;
				srvrGlobal->clientErrorLCID = LANG_NEUTRAL;
			}
			JNI_ReleaseStringUTFChars(jenv,language, nLanguage);
	}
	else
	{
		srvrGlobal->clientLCID = LANG_NEUTRAL;
		srvrGlobal->clientErrorLCID = LANG_NEUTRAL;
	}
#endif

	srvrGlobal->dialogueId = 0;			// DialogueId is set to zero now

	// Linux port - Nowait support is set to OFF for now.
	// nowaitOn = 0;	// Should come command line or JDBC properties
	
	switch (nowaitOn)
	{
	case 0:
		srvrGlobal->nowaitOn = 0;
		break;
	case 1:
		srvrGlobal->nowaitOn = 1;
		break;
	case 2:
		srvrGlobal->nowaitOn = 2;
		break;
	default:
		srvrGlobal->nowaitOn = 0;
		break;
	}

#ifdef NSK_PLATFORM		// Linux port
	// setup MP system catalog name
	if (envGetSystemCatalogName (&srvrGlobal->NskSystemCatalogName[0]) != TRUE)
	{
		throwSQLException(jenv, SYSTEM_CATALOG_ERROR, NULL, "HY000", 0);
		FUNCTION_RETURN_VOID(("envGetSystemCatalogName() failed"));
	}

	// setup MX system catalog name
	if (envGetMXSystemCatalogName (&srvrGlobal->SystemCatalog[0]) != TRUE)
	{
		throwSQLException(jenv, SYSTEM_CATALOG_ERROR, NULL, "HY000", 0);
		FUNCTION_RETURN_VOID(("envGetMXSystemCatalogName() failed"));
	}
#endif

	// MFC - set the srvrGlobal variables w.r.t the properties - start

	srvrGlobal->moduleCaching=0;
	if (moduleCaching)
	{
		nModuleCaching = JNI_GetStringUTFChars(jenv,moduleCaching, NULL);
		if (strcmp(nModuleCaching,"ON") == 0)
			srvrGlobal->moduleCaching=1;

		//Soln. No.: 10-110927-9875 - fix memory leak
		JNI_ReleaseStringUTFChars(jenv,moduleCaching, nModuleCaching);
	}


	if (srvrGlobal->moduleCaching == 1)
	{
		memset(srvrGlobal->CurrentCatalog, '\0', 129);
		memset(srvrGlobal->CurrentSchema, '\0', 129);
		memset(srvrGlobal->compiledModuleLocation, '\0', 100);
		if (compiledModuleLocation == NULL)
		{
			strcpy(srvrGlobal->compiledModuleLocation,"/usr/tandem/sqlmx/USERMODULES");
		}
		else
		{
			nCompiledModuleLocation = JNI_GetStringUTFChars(jenv,compiledModuleLocation, NULL);
			strcpy(srvrGlobal->compiledModuleLocation,nCompiledModuleLocation);

			//Soln. No.: 10-110927-9875 - fix memory leak
			JNI_ReleaseStringUTFChars(jenv,compiledModuleLocation, nCompiledModuleLocation);

			if(srvrGlobal->compiledModuleLocation[0] != '/')
			{
				printf("The directory provided for option \"compiledmodulelocation\" must be an absolute path.\n");
				abort();
			}
			int nDirExists = access(srvrGlobal->compiledModuleLocation, F_OK);
			if(nDirExists != 0)
			{
				printf("The directory provided for option \"compiledmodulelocation\" does not exist.\n");
				abort();
			}
			nDirExists = access(srvrGlobal->compiledModuleLocation, W_OK);
			if(nDirExists != 0)
			{
				printf("The directory provided for option \"compiledmodulelocation\" does not have \"write\" permission.\n");
				abort();
			}
			if(srvrGlobal->compiledModuleLocation[strlen(srvrGlobal->compiledModuleLocation)-1] == '/')
			{
				srvrGlobal->compiledModuleLocation[strlen(srvrGlobal->compiledModuleLocation)-1] = '\0';
			}
		}
	}
	srvrGlobal->boolFlgforInitialization = 1;
	// MFC set the srvrGlobal variables w.r.t the properties - end
	FUNCTION_RETURN_VOID((NULL));
}
JNIEXPORT void JNICALL Java_org_trafodion_jdbc_t2_SQLMXStatement_executeDirect
(JNIEnv *jenv, jobject jobj, jstring server, jlong dialogueId, jint txid, jboolean autoCommit, jint txnMode,
 jstring stmtLabel, jstring cursorName, jstring sql, jboolean isSelect, jint queryTimeout,
 jint holdability, jobject resultSet, jlong currentStmtId)
{
    FUNCTION_ENTRY_LEVEL(DEBUG_LEVEL_STMT,"Java_org_trafodion_jdbc_t2_SQLMXStatement_executeDirect",
                         ("... dialogueId=0x%08x, txid=%ld, autoCommit=%s, stmtLabel=%s, cursorName=%s, sql=%s, txnMode=%ld, isSelect=%s, holdability=%ld, resultSet=0x%08x",
                          dialogueId,
                          txid,
                          DebugBoolStr(autoCommit),
                          DebugJString(jenv,stmtLabel),
                          DebugJString(jenv,cursorName),
                          DebugJString(jenv,sql),
                          txnMode,
                          DebugBoolStr(isSelect),
                          holdability,
                          resultSet));

    ExceptionStruct				exception_;
    long					estimatedCost;
    long					rowsAffected;
    ERROR_DESC_LIST_def			sqlWarning;
    SQLItemDescList_def			outputDesc;
    jint						currentTxid = txid;
    jint						externalTxid = 0;
    long						stmtId;

    const char		*nSql;
    const char		*nStmtLabel;
    const char		*nCursorName;
    jbyteArray		sqlByteArray;
    jboolean		isCopy;
    jsize			len;
    SQLValue_def	sqlString;
    short			txn_status;

    sqlString.dataCharset = 0;
    sqlString.dataInd = 0;
    sqlString.dataType = SQLTYPECODE_VARCHAR;

    if (sql)
    {
        if ((sqlByteArray = (jbyteArray)jenv->CallObjectMethod(sql, gJNICache.getBytesMethodId))
                == NULL)
        {
            throwSQLException(jenv, INVALID_SQL_STRING_ERROR, NULL, "HY090");
            FUNCTION_RETURN_VOID(("getBytesMethod returned NULL"));
        }
        if ((nSql = (const char *)JNI_GetByteArrayElements(jenv,sqlByteArray, &isCopy)) == NULL)
        {
            throwSQLException(jenv, INVALID_SQL_STRING_ERROR, NULL, "HY090");
            FUNCTION_RETURN_VOID(("GetByteArrayElements returned NULL"));
        }
        len = JNI_GetArrayLength(jenv,sqlByteArray);
        sqlString.dataValue._buffer = (unsigned char *)nSql;
        sqlString.dataValue._length = len;
        DEBUG_OUT(DEBUG_LEVEL_CLI,("sqlString = '%s', length =%ld", nSql, len));
        MEMORY_DUMP(DEBUG_LEVEL_CLI, nSql, len);
    }
    else
    {
        throwSQLException(jenv, INVALID_SQL_STRING_ERROR, NULL, "HY090");
        FUNCTION_RETURN_VOID(("sql is NULL"));
    }

    if (stmtLabel)
        nStmtLabel = JNI_GetStringUTFChars(jenv,stmtLabel, NULL);
    else
    {
        throwSQLException(jenv, INVALID_STMT_LABEL_ERROR, NULL, "HY000");
        FUNCTION_RETURN_VOID(("stmtLabel is NULL"));
    }

    if (cursorName)
        nCursorName = JNI_GetStringUTFChars(jenv,cursorName, NULL);
    else
        nCursorName = NULL;

    if ((txn_status = beginTxnControl(jenv, currentTxid, externalTxid, txnMode, -1) != 0))
    {
        jenv->CallVoidMethod(jobj, gJNICache.setCurrentTxidStmtMethodId, currentTxid);
        throwTransactionException(jenv, txn_status);
        FUNCTION_RETURN_VOID(("beginTxnControl() failed"));
    }

    exception_.u.SQLError.errorList._buffer = NULL;
    odbc_SQLSvc_ExecDirect_sme_(NULL, NULL,
                                &exception_,
                                dialogueId,
                                nStmtLabel,
                                (char *)nCursorName,
                                "",					// StmtExplainName
                                EXTERNAL_STMT,
                                (isSelect ? TYPE_SELECT : TYPE_UNKNOWN),
                                &sqlString,
                                holdability,
                                queryTimeout,
                                (long) resultSet,
                                &estimatedCost,
                                &outputDesc,
                                &rowsAffected,
                                &sqlWarning,
                                &stmtId,
                                currentStmtId);

    if (sql)
        JNI_ReleaseByteArrayElements(jenv,sqlByteArray, (jbyte *)nSql, JNI_ABORT);
    if (stmtLabel)
        JNI_ReleaseStringUTFChars(jenv,stmtLabel, nStmtLabel);
    if (cursorName)
        JNI_ReleaseStringUTFChars(jenv,cursorName, nCursorName);

    if ((txn_status = endTxnControl(jenv, currentTxid, txid, autoCommit,
                                    exception_.exception_nr, isSelect, txnMode, externalTxid)) != 0)
    {
        jenv->CallVoidMethod(jobj, gJNICache.setCurrentTxidStmtMethodId, currentTxid);
        throwTransactionException(jenv, txn_status);
        FUNCTION_RETURN_VOID(("endTxnControl() Failed"));
    }

    switch (exception_.exception_nr)
    {
    case CEE_SUCCESS:
        if (sqlWarning._length != 0)
            setSQLWarning(jenv, jobj, &sqlWarning);
        setExecuteDirectOutputs(jenv, jobj, &outputDesc, rowsAffected, currentTxid, stmtId);
        break;
    case odbc_SQLSvc_ExecDirect_ParamError_exn_:
        jenv->CallVoidMethod(jobj, gJNICache.setCurrentStmtIdMethodId, stmtId);
        jenv->CallVoidMethod(jobj, gJNICache.setCurrentTxidStmtMethodId, currentTxid);
        throwSQLException(jenv, PROGRAMMING_ERROR, exception_.u.ParamError.ParamDesc, "HY000");
        break;
    case odbc_SQLSvc_ExecDirect_SQLError_exn_:
        jenv->CallVoidMethod(jobj, gJNICache.setCurrentStmtIdMethodId, stmtId);
        jenv->CallVoidMethod(jobj, gJNICache.setCurrentTxidStmtMethodId, currentTxid);
        throwSQLException(jenv, &exception_.u.SQLError);
        break;
    case odbc_SQLSvc_ExecDirect_SQLQueryCancelled_exn_:
        jenv->CallVoidMethod(jobj, gJNICache.setCurrentStmtIdMethodId, stmtId);
        jenv->CallVoidMethod(jobj, gJNICache.setCurrentTxidStmtMethodId, currentTxid);
        throwSQLException(jenv, QUERY_CANCELLED_ERROR, NULL, "HY008",
                          exception_.u.SQLQueryCancelled.sqlcode);
        break;
    case odbc_SQLSvc_ExecDirect_SQLInvalidHandle_exn_:
        jenv->CallVoidMethod(jobj, gJNICache.setCurrentStmtIdMethodId, stmtId);
        jenv->CallVoidMethod(jobj, gJNICache.setCurrentTxidStmtMethodId, currentTxid);
        throwSQLException(jenv, INVALID_HANDLE_ERROR, NULL, "HY000", exception_.u.SQLInvalidHandle.sqlcode);
        break;
    case odbc_SQLSvc_ExecDirect_SQLStillExecuting_exn_:
    case odbc_SQLSvc_ExecDirect_InvalidConnection_exn_:
    case odbc_SQLSvc_ExecDirect_TransactionError_exn_:
    default:
// TFDS - These error should not happen
        jenv->CallVoidMethod(jobj, gJNICache.setCurrentStmtIdMethodId, stmtId);
        jenv->CallVoidMethod(jobj, gJNICache.setCurrentTxidStmtMethodId, currentTxid);
        throwSQLException(jenv, PROGRAMMING_ERROR, NULL, "HY000", exception_.exception_nr);
        break;
    }
    FUNCTION_RETURN_VOID((NULL));
}
/* RFE: Batch update improvements
 * executeBatch() now contains an additional argument: contBatchOnError
 */
JNIEXPORT void JNICALL Java_org_trafodion_jdbc_t2_SQLMXStatement_executeBatch
(JNIEnv *jenv, jobject jobj, jstring server, jlong dialogueId, jint txid, jboolean autoCommit, jint txnMode,
 jstring stmtLabel, jstring cursorName, jobjectArray sqlCommands, jboolean isSelect, jint queryTimeout, jboolean contBatchOnError, jlong currentStmtId)
{
    FUNCTION_ENTRY("Java_org_trafodion_jdbc_t2_SQLMXStatement_executeBatch",
                   ("... dialogueId=0x%08x, txid=%ld, autoCommit=%s, stmtLabel=%s, cursorName=%s,txnMode=%ld, isSelect=%s,contBatchOnError=%s ...",
                    dialogueId,
                    txid,
                    DebugBoolStr(autoCommit),
                    DebugJString(jenv,stmtLabel),
                    DebugJString(jenv,cursorName),
                    txnMode,
                    DebugBoolStr(isSelect),
                    DebugBoolStr(contBatchOnError)));

    ExceptionStruct				exception_;
    long						estimatedCost;
    long						rowsAffected;
    ERROR_DESC_LIST_def			sqlWarning;
    SQLItemDescList_def			outputDesc;
    jint						currentTxid = txid;
    jint						externalTxid = 0;
    jsize						noOfCommands;
    jstring						sql;
    jint						i;

    const char		*nSql;
    const char		*nStmtLabel;
    const char		*nCursorName = NULL;
    jbyteArray		sqlByteArray;
    jboolean		isCopy;
    long			stmtId;
    jsize			len;
    SQLValue_def	sqlString;
    short			txn_status;
    // RFE: Batch update improvements
    jthrowable		queuedException = NULL;
    jthrowable		exceptionHead = NULL;
    bool			isSuspended = false;

    exception_.exception_nr = CEE_SUCCESS;

    if (stmtLabel)
        nStmtLabel = JNI_GetStringUTFChars(jenv,stmtLabel, NULL);
    else
    {
        throwSQLException(jenv, INVALID_STMT_LABEL_ERROR, NULL, "HY000");
        FUNCTION_RETURN_VOID(("stmtLabel is NULL"));
    }

    if (cursorName) nCursorName = JNI_GetStringUTFChars(jenv,cursorName, NULL);

    if ((txn_status = beginTxnControl(jenv, currentTxid, externalTxid, txnMode, -1) != 0))
    {
        jenv->CallVoidMethod(jobj, gJNICache.setCurrentTxidStmtMethodId, currentTxid);
        throwTransactionException(jenv, txn_status);
        FUNCTION_RETURN_VOID(("beginTxnControl() failed"));
    }

    sqlString.dataCharset = 0;
    sqlString.dataInd = 0;
    sqlString.dataType = SQLTYPECODE_VARCHAR;

    noOfCommands = JNI_GetArrayLength(jenv,sqlCommands);

    for (i = 0; i < noOfCommands ; i++)
    {
        /* RFE: Batch update improvements
         * Resume the transaction if it was earlier suspended, by checking the
         * variable isSuspended. This is reset to false after the transaction is resumed.
         */
        if(isSuspended)
        {
            if ((txn_status = beginTxnControl(jenv, currentTxid, externalTxid, txnMode, -1) != 0))
            {
                jenv->CallVoidMethod(jobj, gJNICache.setCurrentTxidStmtMethodId, currentTxid);
                throwTransactionException(jenv, txn_status);
                FUNCTION_RETURN_VOID(("beginTxnControl() failed"));
            }
            isSuspended = false;
        }
        sql = (jstring) JNI_GetObjectArrayElement(jenv,sqlCommands, i);
        if (sql)
        {
            if ((sqlByteArray = (jbyteArray)jenv->CallObjectMethod(sql, gJNICache.getBytesMethodId))
                    == NULL)
            {
                throwSQLException(jenv, INVALID_SQL_STRING_ERROR, NULL, "HY090");
                FUNCTION_RETURN_VOID(("getBytesMethod() returned NULL"));
            }
            if ((nSql = (const char *)JNI_GetByteArrayElements(jenv,sqlByteArray, &isCopy)) == NULL)
            {
                throwSQLException(jenv, INVALID_SQL_STRING_ERROR, NULL, "HY090");
                FUNCTION_RETURN_VOID(("GetByteArrayElements() returned NULL"));
            }
            len = JNI_GetArrayLength(jenv,sqlByteArray);
            sqlString.dataValue._buffer = (unsigned char *)nSql;
            sqlString.dataValue._length = len;
        }
        else
        {
            throwSQLException(jenv, INVALID_SQL_STRING_ERROR, NULL, "HY090");
            FUNCTION_RETURN_VOID(("sql is NULL"));
        }

        odbc_SQLSvc_ExecDirect_sme_(NULL, NULL,
                                    &exception_,
                                    dialogueId,
                                    nStmtLabel,
                                    (char *)nCursorName,
                                    "",					// StmtExplainName
                                    EXTERNAL_STMT,
                                    (isSelect ? TYPE_SELECT : TYPE_UNKNOWN),
                                    &sqlString,
                                    CLOSE_CURSORS_AT_COMMIT,
                                    queryTimeout,
                                    NULL,
                                    &estimatedCost,
                                    &outputDesc,
                                    &rowsAffected,
                                    &sqlWarning,
                                    &stmtId
                                    ,currentStmtId);

        if (sql)
            JNI_ReleaseByteArrayElements(jenv,sqlByteArray, (jbyte *)nSql, JNI_ABORT);

        /* RFE: Batch update improvements
         * Perform pre-function exit processing only if contBatchOnError is not set to true
         */
        if (exception_.exception_nr != CEE_SUCCESS)
        {
            //RFE: Batch update improvements
            if(!contBatchOnError)
            {
                if (stmtLabel)
                    JNI_ReleaseStringUTFChars(jenv,stmtLabel, nStmtLabel);
                if (cursorName)
                    JNI_ReleaseStringUTFChars(jenv,cursorName, nCursorName);
            }

            // Commit the transaction so all good statements are processed.
            txn_status = endTxnControl(jenv, currentTxid, txid, autoCommit,
                                       CEE_SUCCESS, isSelect, txnMode, externalTxid);
            jenv->CallVoidMethod(jobj, gJNICache.setCurrentTxidStmtMethodId, currentTxid);
            if (txn_status != 0)
            {
                throwTransactionException(jenv, txn_status);
                DEBUG_OUT(DEBUG_LEVEL_ENTRY|DEBUG_LEVEL_TXN,("endTxnControl() Failed after ExecDirect failure"));
            }
            //RFE: Batch update improvements
            if(contBatchOnError)
                isSuspended = true;

        }

        switch (exception_.exception_nr)
        {
        case CEE_SUCCESS:
            if (sqlWarning._length != 0)
                setSQLWarning(jenv, jobj, &sqlWarning);
            jenv->CallVoidMethod(jobj, gJNICache.execDirectBatchOutputsMethodId, i, rowsAffected,
                                 currentTxid);
            break;
        case odbc_SQLSvc_ExecDirect_ParamError_exn_:
            jenv->CallVoidMethod(jobj, gJNICache.setCurrentStmtIdMethodId, stmtId);
            throwSQLException(jenv, PROGRAMMING_ERROR, exception_.u.ParamError.ParamDesc, "HY000");
            break;
        case odbc_SQLSvc_ExecDirect_SQLError_exn_:
            jenv->CallVoidMethod(jobj, gJNICache.setCurrentStmtIdMethodId, stmtId);
            throwSQLException(jenv, &exception_.u.SQLError);
            break;
        case odbc_SQLSvc_ExecDirect_SQLQueryCancelled_exn_:
            jenv->CallVoidMethod(jobj, gJNICache.setCurrentStmtIdMethodId, stmtId);
            throwSQLException(jenv, QUERY_CANCELLED_ERROR, NULL, "HY008",
                              exception_.u.SQLQueryCancelled.sqlcode);
            break;
        case odbc_SQLSvc_ExecDirect_SQLInvalidHandle_exn_:
            jenv->CallVoidMethod(jobj, gJNICache.setCurrentStmtIdMethodId, stmtId);
            throwSQLException(jenv, INVALID_HANDLE_ERROR, NULL, "HY000", exception_.u.SQLInvalidHandle.sqlcode);
            break;
        case odbc_SQLSvc_ExecDirect_SQLStillExecuting_exn_:
        case odbc_SQLSvc_ExecDirect_InvalidConnection_exn_:
        case odbc_SQLSvc_ExecDirect_TransactionError_exn_:
        default:
            // TFDS - These error should not happen
            jenv->CallVoidMethod(jobj, gJNICache.setCurrentStmtIdMethodId, stmtId);
            throwSQLException(jenv, PROGRAMMING_ERROR, NULL, "HY000", exception_.exception_nr);
            break;
        }
        /* RFE: Batch update improvements
         * Return to caller on error and if contBatchOnError is not true.
         */
        if (exception_.exception_nr != CEE_SUCCESS && !contBatchOnError)
            FUNCTION_RETURN_VOID(("exception_.exception_nr(%ld) is not CEE_SUCCESS",exception_.exception_nr));

        /* RFE: Batch update improvements
         * Queue up the exceptions.
         */
        if(jenv->ExceptionOccurred())
        {
            queuedException = jenv->ExceptionOccurred();
            if(exceptionHead)
                jenv->CallVoidMethod(exceptionHead, gJNICache.setNextExceptionMethodId,
                                     queuedException);
            else
                exceptionHead = queuedException;
        }

    }//end of for

    if (stmtLabel)
        JNI_ReleaseStringUTFChars(jenv,stmtLabel, nStmtLabel);

    if (cursorName)
        JNI_ReleaseStringUTFChars(jenv,cursorName, nCursorName);

    /* RFE: Batch update improvements
     * If contBatchOnError is true, CEE_SUCCESS is always passed instead of
     * exception_.exception_nr, so that endTxnControl suspends the transaction.
     */
    txn_status = endTxnControl(jenv, currentTxid, txid, autoCommit,
                               (contBatchOnError ? CEE_SUCCESS:exception_.exception_nr), isSelect, txnMode, externalTxid);
    jenv->CallVoidMethod(jobj, gJNICache.setCurrentTxidStmtMethodId, currentTxid);
    if (txn_status != 0)
    {
        throwTransactionException(jenv, txn_status);
        FUNCTION_RETURN_VOID(("endTxnControl() failed"));
    }
    /* RFE: Batch update improvements
     * Throw the queued exception if any */
    if(exceptionHead)
        jenv->Throw(exceptionHead);
    FUNCTION_RETURN_VOID((NULL));
}
//venu changed dialogueId and stmtId from int to long for 64 bit
JNIEXPORT void JNICALL Java_org_trafodion_jdbc_t2_SQLMXStatement_executeRS
(JNIEnv *jenv, jobject jobj, jstring server, jlong dialogueId, jint txid, jboolean autoCommit, jint txnMode,
 jstring stmtLabel, jstring RSstmtLabel,  jboolean isSelect, jlong stmtId, jint ResultSetIndex, jobject resultSet)
{
    FUNCTION_ENTRY_LEVEL(DEBUG_LEVEL_STMT, "Java_org_trafodion_jdbc_t2_SQLMXStatement_executeRS",
                         ("...dialogueId=0x%08x, txid=0x%08x, stmtLabel=%s, RSstmtLabel=%s, isSelect=%s, stmtId=0x%08x, ResultSetIndex=%ld, resultSet=0x%08x",
                          dialogueId,
                          txid,
                          DebugJString(jenv,stmtLabel),
                          DebugJString(jenv,RSstmtLabel),
                          DebugBoolStr(isSelect),
                          stmtId,
                          ResultSetIndex,
                          resultSet));

    ExceptionStruct				exception_;
    ERROR_DESC_LIST_def			sqlWarning;
    SQLItemDescList_def			outputDesc;
    jint						currentTxid = txid;
    jint						externalTxid = 0;
    long						RSstmtId;
    const char					*nStmtLabel;
    const char					*nRSStmtLabel;
    jboolean					isCopy;
    short						txn_status;

    if (stmtLabel)
        nStmtLabel = JNI_GetStringUTFChars(jenv,stmtLabel, NULL);
    else
    {
        throwSQLException(jenv, INVALID_STMT_LABEL_ERROR, NULL, "HY000");
        FUNCTION_RETURN_VOID(("stmtLabel is NULL"));
    }
    if (RSstmtLabel)
        nRSStmtLabel = JNI_GetStringUTFChars(jenv,RSstmtLabel, NULL);
    else
    {
        throwSQLException(jenv, INVALID_STMT_LABEL_ERROR, NULL, "HY000");
        FUNCTION_RETURN_VOID(("RSstmtLabel is NULL"));
    }

    if ((txn_status = beginTxnControl(jenv, currentTxid, externalTxid, txnMode, -1) != 0))
    {
        jenv->CallVoidMethod(jobj, gJNICache.setCurrentTxidStmtMethodId, currentTxid);
        throwTransactionException(jenv, txn_status);
        FUNCTION_RETURN_VOID(("beginTxnControl() failed"));
    }

    jdbc_SQLSvc_ExecSPJRS_sme_(NULL, NULL,
                               &exception_,
                               dialogueId,
                               nStmtLabel,
                               nRSStmtLabel,
                               EXTERNAL_STMT,
                               (isSelect ? TYPE_SELECT : TYPE_UNKNOWN),
                               (long) resultSet,
                               ResultSetIndex,
                               &outputDesc,
                               &sqlWarning,
                               &RSstmtId,
                               stmtId);

    if (stmtLabel)
        JNI_ReleaseStringUTFChars(jenv, stmtLabel, nStmtLabel);

    if (RSstmtLabel)
        JNI_ReleaseStringUTFChars(jenv, RSstmtLabel, nRSStmtLabel);

    if ((txn_status = endTxnControl(jenv, currentTxid, txid, autoCommit,
                                    exception_.exception_nr, isSelect, txnMode, externalTxid)) != 0)
    {
        jenv->CallVoidMethod(jobj, gJNICache.setCurrentTxidStmtMethodId, currentTxid);
        throwTransactionException(jenv, txn_status);
        FUNCTION_RETURN_VOID(("endTxnControl() Failed"));
    }

    switch (exception_.exception_nr)
    {
    case CEE_SUCCESS:
        if (sqlWarning._length != 0)
            setSQLWarning(jenv, jobj, &sqlWarning);
        setExecuteRSOutputs(jenv, jobj, &outputDesc, currentTxid, RSstmtId, ResultSetIndex);
        break;
    case jdbc_SQLSvc_ExecSPJRS_ParamError_exn_:
        jenv->CallVoidMethod(jobj, gJNICache.setCurrentTxidStmtMethodId, currentTxid);
        throwSQLException(jenv, PROGRAMMING_ERROR, exception_.u.ParamError.ParamDesc, "HY000");
        break;
    case jdbc_SQLSvc_ExecSPJRS_SQLError_exn_:
        jenv->CallVoidMethod(jobj, gJNICache.setCurrentTxidStmtMethodId, currentTxid);
        throwSQLException(jenv, &exception_.u.SQLError);
        break;
    case jdbc_SQLSvc_ExecSPJRS_SQLQueryCancelled_exn_:
        jenv->CallVoidMethod(jobj, gJNICache.setCurrentTxidStmtMethodId, currentTxid);
        throwSQLException(jenv, QUERY_CANCELLED_ERROR, NULL, "HY008", exception_.u.SQLQueryCancelled.sqlcode);
        break;
    case jdbc_SQLSvc_ExecSPJRS_SQLInvalidHandle_exn_:
        jenv->CallVoidMethod(jobj, gJNICache.setCurrentTxidStmtMethodId, currentTxid);
        throwSQLException(jenv, INVALID_HANDLE_ERROR, NULL, "HY000", exception_.u.SQLInvalidHandle.sqlcode);
        break;
    case jdbc_SQLSvc_ExecSPJRS_SQLStillExecuting_exn_:
    case jdbc_SQLSvc_ExecSPJRS_InvalidConnection_exn_:
    case jdbc_SQLSvc_ExecSPJRS_TransactionError_exn_:
    default:
        jenv->CallVoidMethod(jobj, gJNICache.setCurrentTxidStmtMethodId, currentTxid);
        throwSQLException(jenv, PROGRAMMING_ERROR, NULL, "HY000", exception_.exception_nr);
        break;
    }
    FUNCTION_RETURN_VOID((NULL));
}