add org.opengauss jni Fully dense state adapter
This commit is contained in:
@ -28,7 +28,8 @@ driver_error.cpp \
|
||||
jni_string_convertor.cpp \
|
||||
jni_util.cpp \
|
||||
jni_logger.cpp \
|
||||
org_postgresql_jdbc_ClientLogicImpl.cpp
|
||||
org_postgresql_jdbc_ClientLogicImpl.cpp\
|
||||
org_opengauss_jdbc_ClientLogicImpl.cpp
|
||||
|
||||
OBJS = $(CPP_SRCS:.cpp=.o)
|
||||
|
||||
|
@ -0,0 +1,792 @@
|
||||
/*
|
||||
* Copyright (c) 2020 Huawei Technologies Co.,Ltd.
|
||||
*
|
||||
* openGauss is licensed under Mulan PSL v2.
|
||||
* You can use this software according to the terms and conditions of the Mulan PSL v2.
|
||||
* You may obtain a copy of Mulan PSL v2 at:
|
||||
*
|
||||
* http://license.coscl.org.cn/MulanPSL2
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND,
|
||||
* EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT,
|
||||
* MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE.
|
||||
* See the Mulan PSL v2 for more details.
|
||||
* -------------------------------------------------------------------------
|
||||
*
|
||||
* org_opengauss_jdbc_ClientLogicImpl.cpp
|
||||
*
|
||||
* IDENTIFICATION
|
||||
* src/common/interfaces/libpq/jdbc/client_logic_jni/org_opengauss_jdbc_ClientLogicImpl.cpp
|
||||
*
|
||||
* -------------------------------------------------------------------------
|
||||
*/
|
||||
|
||||
#include "client_logic_jni.h"
|
||||
#include "org_opengauss_jdbc_ClientLogicImpl.h"
|
||||
#ifndef ENABLE_LITE_MODE
|
||||
#include <jni.h>
|
||||
#endif
|
||||
#include <stdio.h>
|
||||
#include "libpq-fe.h"
|
||||
#include "jni_logger.h"
|
||||
#include "jni_string_convertor.h"
|
||||
#include "jni_util.h"
|
||||
#include "jni_logger.h"
|
||||
#include "client_logic_data_fetcher/data_fetcher_manager.h"
|
||||
|
||||
#define DELETE_ARRAY(ptr) \
|
||||
if (ptr != NULL) { \
|
||||
delete[] ptr; \
|
||||
ptr = NULL; \
|
||||
}
|
||||
|
||||
static bool adjust_param_valid(const char *adjusted_param_value, const char* param_value)
|
||||
{
|
||||
return adjusted_param_value && param_value &&
|
||||
strcmp(adjusted_param_value, param_value) != 0;
|
||||
}
|
||||
|
||||
static bool check_pre_param_valid(JNIEnv *env, jstring statement_name_java, jobjectArray parameters_java)
|
||||
{
|
||||
if (env == NULL || statement_name_java == NULL || parameters_java == NULL) {
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
/*
|
||||
* Placeholder for few usefull methods in JNI pluming
|
||||
*/
|
||||
struct JniResult {
|
||||
JniResult(JNIEnv *env, int array_length) : m_env(env), m_array_length(array_length) {}
|
||||
/* *
|
||||
* Initializes the array to return
|
||||
* @return false on any failure or true on success
|
||||
*/
|
||||
bool init()
|
||||
{
|
||||
if (m_env == NULL) {
|
||||
return false; /* Should never happen */
|
||||
}
|
||||
object_class = m_env->FindClass("java/lang/Object");
|
||||
if (object_class == NULL) {
|
||||
return false; /* Should never happen */
|
||||
}
|
||||
array = m_env->NewObjectArray(m_array_length, object_class, NULL);
|
||||
if (array == NULL) {
|
||||
return false; /* Should never happen */
|
||||
}
|
||||
return true;
|
||||
}
|
||||
/* *
|
||||
* Set the array to return error
|
||||
* @param status
|
||||
*/
|
||||
void set_error_return(DriverError *status) const
|
||||
{
|
||||
if (status == NULL) {
|
||||
return;
|
||||
}
|
||||
set_error(m_env, object_class, array, status->get_error_code(),
|
||||
status->get_error_message() ? status->get_error_message() : "");
|
||||
}
|
||||
/* *
|
||||
* sets to return OK success
|
||||
*/
|
||||
void set_no_error_retrun() const
|
||||
{
|
||||
set_no_error(m_env, object_class, array);
|
||||
}
|
||||
/*
|
||||
* Convert java string to utf8 char * using JNIStringConvertor and handles errors if any
|
||||
* @param string_convertor string converter pointer
|
||||
* @param java_str the java string to convert
|
||||
* @param status
|
||||
* @param failure_message message to put in log for failures
|
||||
* @return true for success and false for failures
|
||||
*/
|
||||
bool convert_string(JNIStringConvertor *string_convertor, jstring java_str, DriverError *status,
|
||||
const char *failure_message) const
|
||||
{
|
||||
if (string_convertor == NULL || java_str == NULL || status == NULL) {
|
||||
return false;
|
||||
}
|
||||
string_convertor->convert(m_env, java_str);
|
||||
if (string_convertor->c_str == NULL) {
|
||||
status->set_error(JNI_SYSTEM_ERROR_CODES::STRING_CREATION_FAILED);
|
||||
set_error_return(status);
|
||||
JNI_LOG_ERROR("string conversion failed :%s", failure_message ? failure_message : "");
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
bool from_handle(long handle, ClientLogicJNI **client_logic, DriverError *status, const char *failure_message) const
|
||||
{
|
||||
if (!ClientLogicJNI::from_handle(handle, client_logic, status) || *client_logic == NULL) {
|
||||
JNI_LOG_ERROR("From handle failed: %ld, on: %s", (long)handle, failure_message ? failure_message : "");
|
||||
set_error_return(status);
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
JNIEnv *m_env;
|
||||
int m_array_length;
|
||||
jobjectArray array = NULL;
|
||||
jclass object_class = NULL;
|
||||
};
|
||||
|
||||
/* *
|
||||
* Links the client logic object with its libpq conn to the Java PgConnection Instance
|
||||
* @param env pointer to JVM
|
||||
* @param jdbc_cl_impl pointer back to the Java client logic impl instance
|
||||
* @return java array
|
||||
* [0][0] - int status code - zero for success
|
||||
* [0][1] - string status description
|
||||
* [1] - long - instance handle to be re-used in future calls by the same connection
|
||||
*/
|
||||
JNIEXPORT jobjectArray JNICALL JDBC_FUNC_NAME(linkClientLogicImpl)(JNIEnv *env,
|
||||
jobject jdbc_cl_impl, jstring database_name_java)
|
||||
{
|
||||
JniResult result(env, 2);
|
||||
if (!result.init()) {
|
||||
return result.array; /* Should never happen */
|
||||
}
|
||||
if (env == NULL || jdbc_cl_impl == NULL) {
|
||||
return result.array; /* Should never happen */
|
||||
}
|
||||
DriverError status(0, "");
|
||||
|
||||
// Link the client logic object
|
||||
ClientLogicJNI *client_logic_jni = NULL;
|
||||
client_logic_jni = new (std::nothrow) ClientLogicJNI();
|
||||
if (client_logic_jni == NULL) {
|
||||
status.set_error(UNEXPECTED_ERROR);
|
||||
JNI_LOG_ERROR("linkClientLogicImpl failed");
|
||||
} else {
|
||||
DriverError status(0, "");
|
||||
|
||||
JNIStringConvertor database_name;
|
||||
database_name.convert(env, database_name_java);
|
||||
if (!client_logic_jni->link_client_logic(env, jdbc_cl_impl, database_name.c_str, &status)) {
|
||||
delete client_logic_jni;
|
||||
client_logic_jni = NULL;
|
||||
result.set_error_return(&status);
|
||||
} else {
|
||||
// Successful Connection
|
||||
result.set_no_error_retrun();
|
||||
jlong handle = (jlong)(intptr_t)client_logic_jni;
|
||||
place_jlong_in_target_array(env, handle, 1, result.array);
|
||||
}
|
||||
}
|
||||
return result.array;
|
||||
}
|
||||
|
||||
JNIEXPORT jobjectArray JNICALL JDBC_FUNC_NAME(setKmsInfoImpl)(JNIEnv *env, jobject,
|
||||
jlong handle, jstring key_java, jstring value_java)
|
||||
{
|
||||
JNIStringConvertor key;
|
||||
JNIStringConvertor value;
|
||||
|
||||
JniResult result(env, 1);
|
||||
if (!result.init()) {
|
||||
return result.array; /* Should never happen */
|
||||
}
|
||||
DriverError status(0, "");
|
||||
ClientLogicJNI *client_logic_jni = NULL;
|
||||
if (!result.from_handle((long)handle, &client_logic_jni, &status, "setKmsInfoImpl")) {
|
||||
return result.array;
|
||||
}
|
||||
|
||||
if (!result.convert_string(&key, key_java, &status, "setKmsInfo dump kms info")) {
|
||||
return result.array;
|
||||
}
|
||||
if (!result.convert_string(&value, value_java, &status, "setKmsInfo dump kms info")) {
|
||||
return result.array;
|
||||
}
|
||||
|
||||
if (client_logic_jni->set_kms_info(key.c_str, value.c_str)) {
|
||||
result.set_no_error_retrun();
|
||||
} else {
|
||||
status.set_error(INVALID_INPUT_PARAMETER, "set kms info error");
|
||||
result.set_error_return(&status);
|
||||
}
|
||||
|
||||
return result.array;
|
||||
}
|
||||
|
||||
/*
|
||||
* Runs the pre query, to replace client logic field values with binary format before sending the query to the database
|
||||
* server
|
||||
* @param env pointer to jvm
|
||||
* @param
|
||||
* @param handle pointer to ClientLogicJNI instance
|
||||
* @param original_query_java the query with potentially client logic values in user format
|
||||
* @return java array
|
||||
* [0][0] - int status code - zero for success
|
||||
* [0][1] - string status description
|
||||
* [1] - String - The modified query
|
||||
*/
|
||||
JNIEXPORT jobjectArray JNICALL JDBC_FUNC_NAME(runQueryPreProcessImpl)(JNIEnv *env,
|
||||
jobject jdbc_cl_impl, jlong handle, jstring original_query_java)
|
||||
{
|
||||
JniResult result(env, 2);
|
||||
if (!result.init()) {
|
||||
return result.array; /* Should never happen */
|
||||
}
|
||||
if (env == NULL || original_query_java == NULL) {
|
||||
return result.array; /* Should never happen */
|
||||
}
|
||||
DriverError status(0, "");
|
||||
ClientLogicJNI *client_logic = NULL;
|
||||
if (!result.from_handle((long)handle, &client_logic, &status, "runQueryPreProcess")) {
|
||||
JNI_LOG_ERROR("no handle? %s", env->GetStringUTFChars(original_query_java, NULL));
|
||||
return result.array;
|
||||
}
|
||||
JNIStringConvertor original_query;
|
||||
|
||||
original_query.convert(env, original_query_java);
|
||||
if (original_query.c_str == NULL) {
|
||||
status.set_error(JNI_SYSTEM_ERROR_CODES::STRING_CREATION_FAILED);
|
||||
result.set_error_return(&status);
|
||||
JNI_LOG_ERROR(JDBC_FUNC_STR "runQueryPreProcessImpl error code:%d text:'%s'",
|
||||
status.get_error_code(), status.get_error_message() ? status.get_error_message() : "");
|
||||
return result.array;
|
||||
}
|
||||
const char *original_query_dup = client_logic->get_new_query(original_query.c_str);
|
||||
if (original_query_dup == NULL) {
|
||||
status.set_error(JNI_SYSTEM_ERROR_CODES::STRING_CREATION_FAILED);
|
||||
result.set_error_return(&status);
|
||||
JNI_LOG_ERROR(JDBC_FUNC_STR "runQueryPreProcessImpl error code:%d text:'%s'",
|
||||
status.get_error_code(), status.get_error_message() ? status.get_error_message() : "");
|
||||
result.set_error_return(&status);
|
||||
return result.array;
|
||||
}
|
||||
client_logic->set_jni_env_and_cl_impl(env, jdbc_cl_impl);
|
||||
if (!client_logic->run_pre_query(original_query_dup, &status)) {
|
||||
JNI_LOG_ERROR(
|
||||
JDBC_FUNC_STR "runQueryPreProcessImpl failed: %ld, error code: %d error: '%s'",
|
||||
(long)handle, status.get_error_code(), status.get_error_message() ? status.get_error_message() : "");
|
||||
result.set_error_return(&status);
|
||||
return result.array;
|
||||
}
|
||||
result.set_no_error_retrun();
|
||||
place_string_in_array(env, client_logic->get_pre_query_result(), 1, result.array);
|
||||
client_logic->clean_stmnt();
|
||||
return result.array;
|
||||
}
|
||||
|
||||
/*
|
||||
* Runs post process on the backend, to free the client logic state machine when a query is done
|
||||
* @param env pointer to jvm
|
||||
* @param
|
||||
* @param handle pointer to ClientLogicJNI instance
|
||||
* @param statament_name_java when issued for prepared statement contains the statement name, otherwise an empty string
|
||||
* @return java array
|
||||
* [0][0] - int status code - zero for success
|
||||
* [0][1] - string status description
|
||||
*/
|
||||
JNIEXPORT jobjectArray JNICALL JDBC_FUNC_NAME(runQueryPostProcessImpl)(JNIEnv *env,
|
||||
jobject jdbc_cl_impl, jlong handle)
|
||||
{
|
||||
JniResult result(env, 1);
|
||||
if (!result.init()) {
|
||||
return result.array; /* Should never happen */
|
||||
}
|
||||
DriverError status(0, "");
|
||||
ClientLogicJNI *client_logic = NULL;
|
||||
if (!result.from_handle((long)handle, &client_logic, &status, "runQueryPostProcess")) {
|
||||
return result.array;
|
||||
}
|
||||
client_logic->set_jni_env_and_cl_impl(env, jdbc_cl_impl);
|
||||
if (JNI_TRUE == env->IsSameObject(jdbc_cl_impl, NULL)) {
|
||||
fprintf(stderr, "Client encryption run_post_query failed jobject %p was invalid\n", jdbc_cl_impl);
|
||||
}
|
||||
if (!client_logic->run_post_query("", &status)) {
|
||||
JNI_LOG_ERROR("run_post_query failed: %ld, error code: %d error: '%s'", (long)handle, status.get_error_code(),
|
||||
status.get_error_message() ? status.get_error_message() : "");
|
||||
result.set_error_return(&status);
|
||||
return result.array;
|
||||
}
|
||||
result.set_no_error_retrun();
|
||||
return result.array;
|
||||
}
|
||||
|
||||
/*
|
||||
* Replace client logic field value with user input - used when receiving data in a resultset
|
||||
* @param env pointer to jvm
|
||||
* @param
|
||||
* @param handle pointer to ClientLogicJNI instance
|
||||
* @param data_to_process_java the data in binary format (hexa)
|
||||
* @param data_type the oid (modid) of the original field type
|
||||
* @return java array with the format below:
|
||||
* [0][0] - int status code - zero for success
|
||||
* [0][1] - string status description
|
||||
* [1] - String - The data in user format
|
||||
*/
|
||||
JNIEXPORT jobjectArray JNICALL JDBC_FUNC_NAME(runClientLogicImpl)(JNIEnv *env,
|
||||
jobject jdbc_cl_impl, jlong handle, jstring data_to_process_java, jint data_type)
|
||||
{
|
||||
JniResult result(env, 2);
|
||||
if (!result.init()) {
|
||||
return result.array; /* Should never happen */
|
||||
}
|
||||
|
||||
if (env == NULL || data_to_process_java == NULL) {
|
||||
return result.array;
|
||||
}
|
||||
DriverError status(0, "");
|
||||
JNIStringConvertor data_to_process;
|
||||
if (!result.convert_string(&data_to_process, data_to_process_java, &status, "runClientLogicImpl")) {
|
||||
return result.array;
|
||||
}
|
||||
|
||||
ClientLogicJNI *client_logic = NULL;
|
||||
if (!result.from_handle((long)handle, &client_logic, &status, "runClientLogicImpl")) {
|
||||
return result.array;
|
||||
}
|
||||
client_logic->set_jni_env_and_cl_impl(env, jdbc_cl_impl);
|
||||
unsigned char *proccessed_data = NULL;
|
||||
size_t length_output;
|
||||
if (!client_logic->deprocess_value(data_to_process.c_str, data_type, &proccessed_data, length_output, &status)) {
|
||||
libpq_free(proccessed_data);
|
||||
JNI_LOG_ERROR(JDBC_FUNC_STR "runClientLogicImpl failed:error code: %d error: '%s'",
|
||||
status.get_error_code(), status.get_error_message() ? status.get_error_message() : "");
|
||||
result.set_error_return(&status);
|
||||
return result.array;
|
||||
}
|
||||
result.set_no_error_retrun();
|
||||
place_ustring_in_array(env, proccessed_data, 1, result.array);
|
||||
libpq_free(proccessed_data);
|
||||
return result.array;
|
||||
}
|
||||
|
||||
/**
|
||||
* check if a type is holding a record type and then need to pass its values to process_record_data
|
||||
* In Java this is done once for every field in the resultset and
|
||||
* then we call process_record_data only for the fields that we need to
|
||||
* @param env pointer to jvm
|
||||
* @param
|
||||
* @param handle pointer to ClientLogicJNI instance
|
||||
* @param column_name_java the name of the column in the resultset
|
||||
* @param oid the oid of the field type
|
||||
* @return java array with the format below:
|
||||
* [0][0] - int status code - zero for success
|
||||
* [0][1] - string status description
|
||||
* [0...n] - array of ints with actual oids that the field contain
|
||||
*/
|
||||
JNIEXPORT jobjectArray JNICALL JDBC_FUNC_NAME(getRecordIDsImpl)(JNIEnv *env, jobject,
|
||||
jlong handle, jstring column_name_java, jint oid)
|
||||
{
|
||||
DriverError status(0, "");
|
||||
JniResult result(env, 2);
|
||||
if (!result.init()) {
|
||||
return result.array; /* Should never happen */
|
||||
}
|
||||
|
||||
if (env == NULL || column_name_java == NULL) {
|
||||
return result.array;
|
||||
}
|
||||
JNIStringConvertor column_type_name;
|
||||
if (!result.convert_string(&column_type_name, column_name_java, &status, "getRecordIDsImpl")) {
|
||||
return result.array;
|
||||
}
|
||||
|
||||
ClientLogicJNI *client_logic = NULL;
|
||||
if (!result.from_handle((long)handle, &client_logic, &status, "getRecordIDsImpl")) {
|
||||
return result.array;
|
||||
}
|
||||
result.set_no_error_retrun();
|
||||
size_t number_of_oids = client_logic->get_record_data_oid_length(oid, column_type_name.c_str);
|
||||
if (number_of_oids > 0) {
|
||||
const int *oids = client_logic->get_record_data_oids(oid, column_type_name.c_str);
|
||||
place_ints_in_target_array(env, oids, number_of_oids, 1, result.array);
|
||||
}
|
||||
return result.array;
|
||||
}
|
||||
|
||||
/**
|
||||
* gets a record in client logic format and returns it in user format
|
||||
* @param env pointer to jvm
|
||||
* @param
|
||||
* @param handle pointer to ClientLogicJNI instance
|
||||
* @param data_to_process_java the data in client logic format
|
||||
* @param original_oids_java the result returned from getRecordIDsImpl method for this field
|
||||
* @return java array with the format below:
|
||||
* [0][0] - int status code - zero for success
|
||||
* [0][1] - string status description
|
||||
* [1] - int 0 not client logic 1 - is client logic
|
||||
* [2] - String - The data in user format
|
||||
*/
|
||||
JNIEXPORT jobjectArray JNICALL JDBC_FUNC_NAME(runClientLogic4RecordImpl)(JNIEnv *env, jobject,
|
||||
jlong handle, jstring data_to_process_java, jintArray original_oids_java)
|
||||
{
|
||||
JniResult result(env, ARRAY_SIZE + 1);
|
||||
if (!result.init()) {
|
||||
return result.array; /* Should never happen */
|
||||
}
|
||||
if (env == NULL || data_to_process_java == NULL || original_oids_java == NULL) {
|
||||
return result.array;
|
||||
}
|
||||
DriverError status(0, "");
|
||||
JNIStringConvertor data_to_process;
|
||||
if (!result.convert_string(&data_to_process, data_to_process_java, &status, "runClientLogic4RecordImpl")) {
|
||||
return result.array;
|
||||
}
|
||||
ClientLogicJNI *client_logic = NULL;
|
||||
if (!result.from_handle((long)handle, &client_logic, &status, "runClientLogic4RecordImpl")) {
|
||||
return result.array;
|
||||
}
|
||||
bool is_client_logic = false;
|
||||
unsigned char *proccessed_data = NULL;
|
||||
size_t length_output;
|
||||
size_t number_of_oids = env->GetArrayLength(original_oids_java);
|
||||
if (number_of_oids > 0) {
|
||||
/* Gauss wil not allow more than 250 fields with client logic */
|
||||
static const size_t MAXMIMUM_NUMBER_OF_CL_FIELDS_IN_TABLE = 250;
|
||||
Assert(number_of_oids < MAXMIMUM_NUMBER_OF_CL_FIELDS_IN_TABLE);
|
||||
int original_oids[MAXMIMUM_NUMBER_OF_CL_FIELDS_IN_TABLE] = {0};
|
||||
jint *oids_java = env->GetIntArrayElements(original_oids_java, 0);
|
||||
for (size_t index = 0; index < number_of_oids; ++index) {
|
||||
original_oids[index] = oids_java[index];
|
||||
}
|
||||
if (!client_logic->process_record_data(data_to_process.c_str, original_oids, number_of_oids,
|
||||
&proccessed_data, &is_client_logic, length_output, &status)) {
|
||||
libpq_free(proccessed_data);
|
||||
JNI_LOG_ERROR(
|
||||
JDBC_FUNC_STR "runClientLogic4RecordImpl failed:error code: %d error: '%s'",
|
||||
status.get_error_code(), status.get_error_message() ? status.get_error_message() : "");
|
||||
result.set_error_return(&status);
|
||||
return result.array;
|
||||
}
|
||||
result.set_no_error_retrun();
|
||||
}
|
||||
if (is_client_logic) {
|
||||
place_int_in_target_array(env, 1, 1, result.array);
|
||||
} else {
|
||||
place_int_in_target_array(env, 0, 1, result.array);
|
||||
}
|
||||
if (proccessed_data != NULL) {
|
||||
place_ustring_in_array(env, proccessed_data, 2, result.array);
|
||||
libpq_free(proccessed_data);
|
||||
}
|
||||
return result.array;
|
||||
}
|
||||
|
||||
/*
|
||||
* Run prepare statement
|
||||
* @param env pointer to jvm
|
||||
* @param
|
||||
* @param handle pointer to ClientLogicJNI instance
|
||||
* @param query_java
|
||||
* @param statement_name
|
||||
* @param parameter_count
|
||||
* @return Object in the following format:
|
||||
* [0][0][0] - error code - 0 for none
|
||||
* [0][1] - error text - if none, empty string
|
||||
* [1] - modified query
|
||||
*/
|
||||
JNIEXPORT jobjectArray JNICALL JDBC_FUNC_NAME(prepareQueryImpl)(JNIEnv *env,
|
||||
jobject jdbc_cl_impl, jlong handle, jstring query_java, jstring statement_name_java, jint parameter_count)
|
||||
{
|
||||
JniResult result(env, 2);
|
||||
if (!result.init()) {
|
||||
return result.array;
|
||||
}
|
||||
if (env == NULL || statement_name_java == NULL || query_java == NULL) {
|
||||
return result.array;
|
||||
}
|
||||
DriverError status(0, "");
|
||||
ClientLogicJNI *client_logic = NULL;
|
||||
if (!result.from_handle((long)handle, &client_logic, &status, "prepareQuery")) {
|
||||
return result.array;
|
||||
}
|
||||
JNIStringConvertor original_query;
|
||||
|
||||
original_query.convert(env, query_java);
|
||||
if (original_query.c_str == NULL) {
|
||||
status.set_error(JNI_SYSTEM_ERROR_CODES::STRING_CREATION_FAILED);
|
||||
result.set_error_return(&status);
|
||||
JNI_LOG_ERROR("prepareQuery failed getting the query string error code:%d text:'%s'", status.get_error_code(),
|
||||
status.get_error_message() ? status.get_error_message() : "");
|
||||
return result.array;
|
||||
}
|
||||
JNIStringConvertor statement_name;
|
||||
if (!result.convert_string(&statement_name, statement_name_java, &status, "prepareQuery")) {
|
||||
return result.array;
|
||||
}
|
||||
client_logic->set_jni_env_and_cl_impl(env, jdbc_cl_impl);
|
||||
if (!client_logic->preare_statement(original_query.c_str, statement_name.c_str, parameter_count, &status)) {
|
||||
JNI_LOG_ERROR("preare_statement call failed: %ld, error code: %d error: '%s'", (long)handle,
|
||||
status.get_error_code(), status.get_error_message() ? status.get_error_message() : "");
|
||||
result.set_error_return(&status);
|
||||
return result.array;
|
||||
}
|
||||
if (client_logic->get_statement_data() == NULL) {
|
||||
status.set_error(STATEMENT_DATA_EMPTY);
|
||||
JNI_LOG_ERROR("preare_statement get_statement_data call failed: %ld, error code: %d error: '%s'", (long)handle,
|
||||
status.get_error_code(), status.get_error_message() ? status.get_error_message() : "");
|
||||
result.set_error_return(&status);
|
||||
return result.array;
|
||||
}
|
||||
result.set_no_error_retrun();
|
||||
place_string_in_array(env, client_logic->get_statement_data()->params.adjusted_query, 1, result.array);
|
||||
return result.array;
|
||||
}
|
||||
|
||||
/*
|
||||
* Replaces parameters in prepare statement values before sending to execution
|
||||
* @param[in] env JVM environment
|
||||
* @param[in]
|
||||
* @param[in] handle pointer to ClientLogicJNI instance
|
||||
* @param[in] statement_name_java statement name
|
||||
* @param[in] parameters_java list of parameters in form of Java array of strings
|
||||
* @param[in] parameter_count number of parameters
|
||||
* @return Object in the following format:
|
||||
* [0][0] - error code - 0 for none
|
||||
* [0][1][0] - error text - if none, empty string
|
||||
* [1][0 ... parameter_count - 1] - array with the parameters value, if the parameter is not being replace a NULL apears
|
||||
* otherwise the replaced value
|
||||
* [2][0 ... parameter_count - 1] - array with the parameters' type-oids,
|
||||
* if the parameter is being replaced, otherwise 0
|
||||
*/
|
||||
JNIEXPORT jobjectArray JNICALL JDBC_FUNC_NAME(replaceStatementParamsImpl)(JNIEnv *env,
|
||||
jobject jdbc_cl_impl, jlong handle, jstring statement_name_java, jobjectArray parameters_java)
|
||||
{
|
||||
JniResult result(env, 3);
|
||||
if (!result.init()) {
|
||||
return result.array;
|
||||
}
|
||||
if (!check_pre_param_valid(env, statement_name_java, parameters_java)) {
|
||||
return result.array;
|
||||
}
|
||||
|
||||
DriverError status(0, "");
|
||||
JNIStringConvertor statement_name;
|
||||
if (!result.convert_string(&statement_name, statement_name_java, &status,
|
||||
"replaceStatementParams statement_name_java")) {
|
||||
return result.array;
|
||||
}
|
||||
ClientLogicJNI *client_logic = NULL;
|
||||
if (!result.from_handle((long)handle, &client_logic, &status, "replaceStatementParams")) {
|
||||
return result.array;
|
||||
}
|
||||
int parameter_count = env->GetArrayLength(parameters_java);
|
||||
|
||||
bool convert_failure = false;
|
||||
const char **param_values = NULL;
|
||||
param_values = new (std::nothrow) const char *[(size_t)parameter_count];
|
||||
if (param_values == NULL) {
|
||||
status.set_error(JNI_SYSTEM_ERROR_CODES::UNEXPECTED_ERROR);
|
||||
result.set_error_return(&status);
|
||||
JNI_LOG_ERROR("out of memory");
|
||||
return result.array;
|
||||
}
|
||||
JNIStringConvertor *string_convertors = NULL;
|
||||
string_convertors = new (std::nothrow) JNIStringConvertor[(size_t)parameter_count];
|
||||
if (string_convertors == NULL) {
|
||||
delete[] param_values;
|
||||
status.set_error(JNI_SYSTEM_ERROR_CODES::UNEXPECTED_ERROR);
|
||||
result.set_error_return(&status);
|
||||
JNI_LOG_ERROR("out of memory");
|
||||
return result.array;
|
||||
}
|
||||
for (int i = 0; i < parameter_count && !convert_failure; ++i) {
|
||||
jstring value = (jstring)env->GetObjectArrayElement(parameters_java, i);
|
||||
string_convertors[i].convert(env, value);
|
||||
if (string_convertors[i].c_str == NULL) {
|
||||
status.set_error(JNI_SYSTEM_ERROR_CODES::STRING_CREATION_FAILED);
|
||||
result.set_error_return(&status);
|
||||
JNI_LOG_ERROR("replaceStatementParams failed getting the parameter at index %d", i);
|
||||
convert_failure = true;
|
||||
} else {
|
||||
param_values[i] = string_convertors[i].c_str;
|
||||
}
|
||||
}
|
||||
if (convert_failure) {
|
||||
delete[] param_values;
|
||||
delete[] string_convertors;
|
||||
return result.array;
|
||||
}
|
||||
client_logic->set_jni_env_and_cl_impl(env, jdbc_cl_impl);
|
||||
if (!client_logic->replace_statement_params(statement_name.c_str, param_values, parameter_count, &status)) {
|
||||
JNI_LOG_ERROR("replace_statement_params failed: %ld, error code: %d error: '%s'", (long)handle,
|
||||
status.get_error_code(), status.get_error_message() ? status.get_error_message() : "");
|
||||
result.set_error_return(&status);
|
||||
delete[] param_values;
|
||||
delete[] string_convertors;
|
||||
return result.array;
|
||||
}
|
||||
|
||||
// After parameters values replaces, place the new values on the target array
|
||||
jobjectArray parameters_array = env->NewObjectArray(parameter_count, result.object_class, NULL);
|
||||
const StatementData *stmnt_data = client_logic->get_statement_data();
|
||||
|
||||
int *parameters_types_array = NULL;
|
||||
if (stmnt_data->params.adjusted_paramTypes != NULL) {
|
||||
// set adjusted types array to return to JNI
|
||||
parameters_types_array = new (std::nothrow) int[(size_t)parameter_count];
|
||||
if (parameters_types_array == NULL) {
|
||||
delete[] param_values;
|
||||
delete[] string_convertors;
|
||||
status.set_error(JNI_SYSTEM_ERROR_CODES::UNEXPECTED_ERROR);
|
||||
result.set_error_return(&status);
|
||||
JNI_LOG_ERROR("new failed");
|
||||
return result.array;
|
||||
}
|
||||
}
|
||||
|
||||
for (int i = 0; i < parameter_count && !convert_failure; ++i) {
|
||||
/*
|
||||
* rawValue in INSERT could be NULL or empty string,
|
||||
* we have recgonize it in preare_statement routine and make adjusted_param_values[idx]
|
||||
* to the NULL value directly, therefore ignore it here just like the normal empty value.
|
||||
*/
|
||||
if (adjust_param_valid(stmnt_data->params.adjusted_param_values[i], param_values[i])) {
|
||||
place_string_in_array(env, stmnt_data->params.adjusted_param_values[i], i, parameters_array);
|
||||
}
|
||||
/* return type oid for jdbc side distinguish the enc param */
|
||||
if (parameters_types_array != NULL) {
|
||||
parameters_types_array[i] = (int)stmnt_data->params.adjusted_paramTypes[i];
|
||||
}
|
||||
}
|
||||
|
||||
/* [1][...] arryay object */
|
||||
env->SetObjectArrayElement(result.array, 1, parameters_array);
|
||||
/* [2][...] arryay object */
|
||||
place_ints_in_target_array(env, parameters_types_array, parameter_count, 2, result.array);
|
||||
delete[] param_values;
|
||||
delete[] string_convertors;
|
||||
client_logic->clean_stmnt();
|
||||
DELETE_ARRAY(parameters_types_array);
|
||||
result.set_no_error_retrun();
|
||||
return result.array;
|
||||
}
|
||||
|
||||
/*
|
||||
* replace client logic values in error message coming from the server
|
||||
* For example, when inserting a duplicate unique value,
|
||||
* it will change the client logic value of \x... back to the user input
|
||||
* @param env java environment
|
||||
* @param
|
||||
* @param handle client logic instance handle
|
||||
* @param original_message_java the message received from the server and need to be converted
|
||||
* @return Object in the following format:
|
||||
* [0][0] - error code - 0 for none
|
||||
* [0][1][0] - error text - if none, empty string
|
||||
* [1] - converted message - if empty then the message has not changed
|
||||
*/
|
||||
JNIEXPORT jobjectArray JNICALL JDBC_FUNC_NAME(replaceErrorMessageImpl)(JNIEnv *env,
|
||||
jobject jdbc_cl_impl, jlong handle, jstring original_message_java)
|
||||
{
|
||||
JniResult result(env, 2);
|
||||
if (!result.init()) {
|
||||
return result.array;
|
||||
}
|
||||
if (env == NULL || original_message_java == NULL) {
|
||||
return result.array;
|
||||
}
|
||||
DriverError status(0, "");
|
||||
// Find the client logic instance:
|
||||
ClientLogicJNI *client_logic = NULL;
|
||||
if (!result.from_handle((long)handle, &client_logic, &status, "replaceErrorMessage")) {
|
||||
return result.array;
|
||||
}
|
||||
JNIStringConvertor original_message;
|
||||
if (!result.convert_string(&original_message, original_message_java, &status, "replaceErrorMessage")) {
|
||||
return result.array;
|
||||
}
|
||||
client_logic->set_jni_env_and_cl_impl(env, jdbc_cl_impl);
|
||||
char *converted_message = NULL;
|
||||
bool retval = client_logic->replace_message(original_message.c_str, &converted_message, &status);
|
||||
if (!retval) {
|
||||
// returning false due to an error
|
||||
if (converted_message != NULL) {
|
||||
free(converted_message);
|
||||
converted_message = NULL;
|
||||
}
|
||||
if (status.get_error_code() != 0) {
|
||||
JNI_LOG_ERROR("replaceErrorMessage failed: %ld, error code: %d error: '%s'", (long)handle,
|
||||
status.get_error_code(), status.get_error_message() ? status.get_error_message() : "");
|
||||
result.set_error_return(&status);
|
||||
return result.array;
|
||||
}
|
||||
// returning false may be due to not finding anything to replace and then the string is empty
|
||||
result.set_no_error_retrun();
|
||||
place_string_in_array(env, "", 1, result.array);
|
||||
return result.array;
|
||||
}
|
||||
|
||||
result.set_no_error_retrun();
|
||||
if (converted_message == NULL) {
|
||||
/* Should not happen, but just in case */
|
||||
place_string_in_array(env, "", 1, result.array);
|
||||
} else {
|
||||
place_string_in_array(env, converted_message, 1, result.array);
|
||||
free(converted_message);
|
||||
converted_message = NULL;
|
||||
}
|
||||
return result.array;
|
||||
}
|
||||
/**
|
||||
* reloads the client logic cache
|
||||
* @param env java environment
|
||||
* @param jdbc_cl_impl pointer back to the Java client logic impl instance
|
||||
* @param handle client logic instance handle
|
||||
*/
|
||||
JNIEXPORT void JNICALL JDBC_FUNC_NAME(reloadCacheImpl) (JNIEnv *env,
|
||||
jobject jdbc_cl_impl, jlong handle)
|
||||
{
|
||||
ClientLogicJNI *client_logic = NULL;
|
||||
DriverError status(0, "");
|
||||
if (!ClientLogicJNI::from_handle(handle, &client_logic, &status) || client_logic == NULL) {
|
||||
JNI_LOG_DEBUG("reloadCacheImpl failed: %ld, error code: %d error: '%s'", (long)handle, status.get_error_code(),
|
||||
status.get_error_message() ? status.get_error_message() : "");
|
||||
return;
|
||||
}
|
||||
client_logic->set_jni_env_and_cl_impl(env, jdbc_cl_impl);
|
||||
client_logic->reload_cache();
|
||||
}
|
||||
|
||||
/**
|
||||
* reloads the client logic cache ONLY if the server timestamp is later than the client timestamp
|
||||
* @param env java environment
|
||||
* @param jdbc_cl_impl pointer back to the Java client logic impl instance
|
||||
* @param handle client logic instance handle
|
||||
*/
|
||||
JNIEXPORT void JNICALL JDBC_FUNC_NAME(reloadCacheIfNeededImpl) (JNIEnv *env,
|
||||
jobject jdbc_cl_impl, jlong handle){
|
||||
ClientLogicJNI *client_logic = NULL;
|
||||
DriverError status(0, "");
|
||||
if (!ClientLogicJNI::from_handle(handle, &client_logic, &status) || client_logic == NULL){
|
||||
JNI_LOG_DEBUG("reloadCacheIfNeededImpl failed: %ld, error code: %d error: '%s'",
|
||||
(long)handle, status.get_error_code(),
|
||||
status.get_error_message() ? status.get_error_message() : "");
|
||||
return;
|
||||
}
|
||||
client_logic->set_jni_env_and_cl_impl(env, jdbc_cl_impl);
|
||||
client_logic->reload_cache_if_needed();
|
||||
}
|
||||
|
||||
/*
|
||||
* Class: org_postgresql_jdbc_ClientLogicImpl
|
||||
* Method: destroy
|
||||
* Signature: (J)V
|
||||
*/
|
||||
JNIEXPORT void JNICALL JDBC_FUNC_NAME(destroy)(JNIEnv *env, jobject, jlong handle)
|
||||
{
|
||||
JNI_LOG_DEBUG("About to destroy handle: %ld", (long)handle);
|
||||
ClientLogicJNI *client_logic = NULL;
|
||||
DriverError status(0, "");
|
||||
if (!ClientLogicJNI::from_handle(handle, &client_logic, &status) || client_logic == NULL) {
|
||||
JNI_LOG_DEBUG("Destroy failed: %ld, error code: %d error: '%s'", (long)handle, status.get_error_code(),
|
||||
status.get_error_message() ? status.get_error_message() : "");
|
||||
return;
|
||||
} else {
|
||||
delete client_logic;
|
||||
client_logic = NULL;
|
||||
JNI_LOG_DEBUG("Handle destroyed: %ld", (long)handle);
|
||||
}
|
||||
return;
|
||||
}
|
@ -0,0 +1,148 @@
|
||||
/*
|
||||
* Copyright (c) 2020 Huawei Technologies Co.,Ltd.
|
||||
*
|
||||
* openGauss is licensed under Mulan PSL v2.
|
||||
* You can use this software according to the terms and conditions of the Mulan PSL v2.
|
||||
* You may obtain a copy of Mulan PSL v2 at:
|
||||
*
|
||||
* http://license.coscl.org.cn/MulanPSL2
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND,
|
||||
* EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT,
|
||||
* MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE.
|
||||
* See the Mulan PSL v2 for more details.
|
||||
* -------------------------------------------------------------------------
|
||||
*
|
||||
* org_opengauss_jdbc_ClientLogicImpl.h
|
||||
*
|
||||
* IDENTIFICATION
|
||||
* src/common/interfaces/libpq/jdbc/client_logic_jni/org_opengauss_jdbc_ClientLogicImpl.h
|
||||
*
|
||||
* -------------------------------------------------------------------------
|
||||
*/
|
||||
|
||||
#ifndef _Included_org_opengauss_jdbc_ClientLogicImpl
|
||||
#define _Included_org_opengauss_jdbc_ClientLogicImpl
|
||||
|
||||
/* DO NOT EDIT THIS FILE - it is machine generated */
|
||||
#ifndef ENABLE_LITE_MODE
|
||||
#include <jni.h>
|
||||
#endif
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
#define JDBC_FUNC_REPLACE(pkg, name) Java_##pkg##jdbc_ClientLogicImpl_##name
|
||||
#define JDBC_FUNC_NAME(name) JDBC_FUNC_REPLACE(org_opengauss_, name)
|
||||
#define JDBC_FUNC_STR "Java_org_opengauss_jdbc_ClientLogicImpl_"
|
||||
|
||||
/*
|
||||
* Class: org_postgresql_jdbc_ClientLogicImpl
|
||||
* Method: linkClientLogicImpl
|
||||
* Signature: ()[Ljava/lang/Object;
|
||||
*/
|
||||
JNIEXPORT jobjectArray JNICALL JDBC_FUNC_NAME(linkClientLogicImpl)
|
||||
(JNIEnv *, jobject, jstring);
|
||||
|
||||
JNIEXPORT jobjectArray JNICALL JDBC_FUNC_NAME(setKmsInfoImpl)(JNIEnv *env, jobject,
|
||||
jlong, jstring, jstring);
|
||||
|
||||
/*
|
||||
* Class: org_postgresql_jdbc_ClientLogicImpl
|
||||
* Method: runQueryPreProcessImpl
|
||||
* Signature: (JLjava/lang/String;)[Ljava/lang/Object;
|
||||
*/
|
||||
JNIEXPORT jobjectArray JNICALL JDBC_FUNC_NAME(runQueryPreProcessImpl)(JNIEnv *, jobject, jlong,
|
||||
jstring);
|
||||
|
||||
/*
|
||||
* Class: org_postgresql_jdbc_ClientLogicImpl
|
||||
* Method: runQueryPostProcessImpl
|
||||
* Signature: (JLjava/lang/String;)[Ljava/lang/Object;
|
||||
*/
|
||||
JNIEXPORT jobjectArray JNICALL JDBC_FUNC_NAME(runQueryPostProcessImpl)(JNIEnv *, jobject,
|
||||
jlong);
|
||||
|
||||
/*
|
||||
* Class: org_postgresql_jdbc_ClientLogicImpl
|
||||
* Method: runClientLogicImpl
|
||||
* Signature: (JLjava/lang/String;I)[Ljava/lang/Object;
|
||||
*/
|
||||
JNIEXPORT jobjectArray JNICALL JDBC_FUNC_NAME(runClientLogicImpl)(JNIEnv *, jobject, jlong,
|
||||
jstring, jint);
|
||||
|
||||
/*
|
||||
* Class: org_postgresql_jdbc_ClientLogicImpl
|
||||
* Method: getRecordIDsImpl
|
||||
* Signature: (JLjava/lang/String;I)[Ljava/lang/Object;
|
||||
*/
|
||||
JNIEXPORT jobjectArray JNICALL JDBC_FUNC_NAME(getRecordIDsImpl)(JNIEnv *, jobject, jlong,
|
||||
jstring, jint);
|
||||
|
||||
/*
|
||||
* Class: org_postgresql_jdbc_ClientLogicImpl
|
||||
* Method: runClientLogic4RecordImpl
|
||||
* Signature: (JLjava/lang/String;[I)[Ljava/lang/Object;
|
||||
*/
|
||||
JNIEXPORT jobjectArray JNICALL JDBC_FUNC_NAME(runClientLogic4RecordImpl)(JNIEnv *, jobject,
|
||||
jlong, jstring, jintArray);
|
||||
|
||||
/*
|
||||
* Class: org_postgresql_jdbc_ClientLogicImpl
|
||||
* Method: prepareQueryImpl
|
||||
* Signature: (JLjava/lang/String;Ljava/lang/String;I)[Ljava/lang/Object;
|
||||
*/
|
||||
JNIEXPORT jobjectArray JNICALL JDBC_FUNC_NAME(prepareQueryImpl)(JNIEnv *, jobject, jlong,
|
||||
jstring, jstring, jint);
|
||||
|
||||
/*
|
||||
* Class: org_postgresql_jdbc_ClientLogicImpl
|
||||
* Method: replaceStatementParamsImpl
|
||||
* Signature: (JLjava/lang/String;[Ljava/lang/String;)[Ljava/lang/Object;
|
||||
*/
|
||||
JNIEXPORT jobjectArray JNICALL JDBC_FUNC_NAME(replaceStatementParamsImpl)(JNIEnv *, jobject,
|
||||
jlong, jstring, jobjectArray);
|
||||
|
||||
/*
|
||||
* Class: org_postgresql_jdbc_ClientLogicImpl
|
||||
* Method: replaceErrorMessageImpl
|
||||
* Signature: (JLjava/lang/String;)[Ljava/lang/Object;
|
||||
*/
|
||||
JNIEXPORT jobjectArray JNICALL JDBC_FUNC_NAME(replaceErrorMessageImpl)(JNIEnv *, jobject,
|
||||
jlong, jstring);
|
||||
|
||||
/*
|
||||
* Class: Java_org_postgresql_jdbc_ClientLogicImpl_reloadCacheIfNeededImpl
|
||||
* Method: reloadCache
|
||||
* Signature: (J)V
|
||||
*/
|
||||
JNIEXPORT void JNICALL JDBC_FUNC_NAME(reloadCacheIfNeededImpl) (JNIEnv *, jobject, jlong);
|
||||
|
||||
/*
|
||||
* Class: org_postgresql_jdbc_ClientLogicImpl
|
||||
* Method: reloadCache
|
||||
* Signature: (J)V
|
||||
*/
|
||||
JNIEXPORT void JNICALL JDBC_FUNC_NAME(reloadCacheImpl)
|
||||
(JNIEnv *, jobject, jlong);
|
||||
|
||||
/*
|
||||
* Class: Java_org_postgresql_jdbc_ClientLogicImpl_reloadCacheIfNeededImpl
|
||||
* Method: reloadCache
|
||||
* Signature: (J)V
|
||||
*/
|
||||
|
||||
JNIEXPORT void JNICALL JDBC_FUNC_NAME(reloadCacheIfNeededImpl)
|
||||
(JNIEnv *, jobject, jlong);
|
||||
|
||||
/*
|
||||
* Class: org_postgresql_jdbc_ClientLogicImpl
|
||||
* Method: destroy
|
||||
* Signature: (J)V
|
||||
*/
|
||||
JNIEXPORT void JNICALL JDBC_FUNC_NAME(destroy)(JNIEnv *, jobject, jlong);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
#endif
|
Reference in New Issue
Block a user