* This file is part of the oGRAC project.
* Copyright (c) 2024 Huawei Technologies Co.,Ltd.
*
* oGRAC 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.
* -------------------------------------------------------------------------
*
* ogconn_common.h
*
*
* IDENTIFICATION
* src/driver/ogconn/ogconn_common.h
*
* -------------------------------------------------------------------------
*/
#ifndef __CTCONN_COMMON_H__
#define __CTCONN_COMMON_H__
#include "cm_defs.h"
#include "cm_list.h"
#include "ogconn.h"
#include "cm_thread.h"
#include "cs_packet.h"
#include "cs_pipe.h"
#include "cs_protocol.h"
#include "cm_nls.h"
#ifdef __cplusplus
extern "C" {
#endif
typedef enum en_cli_stmt_status {
CLI_STMT_IDLE = 1,
CLI_STMT_PREPARED = 2,
CLI_STMT_EXECUTED = 3,
CLI_STMT_FETCHING = 4,
#ifdef OG_RAC_ING
CLI_STMT_PRE_PARAMS = 5,
#endif
CLI_STMT_DESCRIBLE = 6
} cli_stmt_status_t;
typedef enum en_cli_db_role {
ROLE_PRIMARY = 0,
ROLE_PHYSICAL_STANDBY = 1,
ROLE_CASCADED_PHYSICAL_STANDBY = 2,
} cli_db_role_t;
#ifdef DB_DEBUG_VERSION
#define OG_SQL_TYPE_CREATE_USER 40
#else
#define OG_SQL_TYPE_CREATE_USER 39
#endif
#define OGCONN_IS_DATABASE_DATATYPE(type) \
(CM_IS_DATABASE_DATATYPE((type) + OG_TYPE_BASE) || (type) == OGCONN_TYPE_NATIVE_DATE)
#define OGCONN_IS_STRING_TYPE(type) ((type) == OGCONN_TYPE_CHAR || (type) == OGCONN_TYPE_VARCHAR || (type) == OGCONN_TYPE_STRING)
#define OGCONN_IS_BINARY_TYPE(type) ((type) == OGCONN_TYPE_BINARY || (type) == OGCONN_TYPE_VARBINARY)
#define OGCONN_IS_LOB_TYPE(type) ((type) == OGCONN_TYPE_CLOB || (type) == OGCONN_TYPE_BLOB || (type) == OGCONN_TYPE_IMAGE)
#define OGCONN_IS_DATE_TYPE(type) \
((type) == OGCONN_TYPE_DATE || (type) == OGCONN_TYPE_TIMESTAMP || (type) == OGCONN_TYPE_TIMESTAMP_TZ || \
(type) == OGCONN_TYPE_TIMESTAMP_TZ_FAKE)
#define OGCONN_IS_NUMBER_TYPE(type) \
((type) == OGCONN_TYPE_NUMBER || (type) == OGCONN_TYPE_DECIMAL || (type) == OGCONN_TYPE_INTEGER || \
(type) == OGCONN_TYPE_BIGINT || (type) == OGCONN_TYPE_REAL || (type) == OGCONN_TYPE_BOOLEAN || \
(type) == OGCONN_TYPE_UINT32 || (type) == OGCONN_TYPE_NUMBER2)
#define OGCONN_IS_TYPE_NEED_EXTRA(type) \
((type) == OGCONN_TYPE_NUMBER || (type) == OGCONN_TYPE_DECIMAL || (type) == OGCONN_TYPE_NUMBER2 || \
(type) == OGCONN_TYPE_CHAR || (type) == OGCONN_TYPE_VARCHAR || (type) == OGCONN_TYPE_STRING || \
(type) == OGCONN_TYPE_BINARY || (type) == OGCONN_TYPE_VARBINARY || (type) == OGCONN_TYPE_RAW)
#define OGCONN_CHECK_FETCH_STATUS(stmt) \
do { \
if ((stmt)->status == CLI_STMT_DESCRIBLE) { \
CLT_THROW_ERROR((stmt)->conn, ERR_CLT_OUT_OF_API_SEQUENCE, "can not fetch data in describling mode"); \
return OG_ERROR; \
} \
} while (0)
#define CLT_LOB_INLINE(lob) ((lob) != NULL && (lob)->type == OG_LOB_FROM_KERNEL && (!(lob)->is_outline))
#define MAX_SET_NLS_SQL 2048
#define CLT_DATE_BINARY_SIZE 7
#define CLT_CHARSET_NAME_SIZE 5
typedef struct st_clt_lob_head {
uint32 size;
uint32 type;
uint32 is_outline : 1;
uint32 node_id : 9;
uint32 unused : 22;
} clt_lob_head_t;
typedef struct st_clt_cache_lob {
clt_lob_head_t lob_head;
uint32 fetched_times;
uint32 column_id;
uint32 offset;
} clt_cache_lob_t;
#define OGCONN_INLINE_LOB_ENCODE_LEN (uint32)(sizeof(clt_cache_lob_t))
typedef struct st_clt_server_info {
uint32 locator_size;
uint16 server_charset;
int16 server_dbtimezone;
uint32 server_max_pack_size;
cli_db_role_t db_role;
} clt_server_info_t;
typedef struct st_clt_options {
int32 connect_timeout;
int32 socket_timeout;
int32 l_onoff;
int32 l_linger;
uint32 port;
uint32 client_flag;
ogconn_ssl_mode_t ssl_mode;
char *host;
char *user;
char *ssl_key;
char *ssl_cert;
char *ssl_ca;
SENSI_INFO char *ssl_keypwd;
char *ssl_crl;
char *ssl_cipher;
char *server_path;
char *client_path;
int16 app_kind;
uint8 reserverd[2];
} clt_options_t;
typedef struct st_clt_packet {
cs_packet_t pack;
uint32 id;
bool8 used;
uint8 reserved[3];
} clt_packet_t;
typedef struct st_clt_serveroutput {
list_t output_data;
uint32 output_count;
uint32 pos;
} clt_serveroutput_t;
typedef struct st_clt_resultset {
list_t stmt_ids;
list_t ids;
uint32 pos;
} clt_resultset_t;
typedef struct st_clt_batch_errs_t {
uint32 allowed_count;
uint32 actual_count;
list_t err_list;
uint32 pos;
} clt_batch_errs_t;
typedef struct st_cli_buf_ctrl {
char data[2 * OG_MAX_PACKET_SIZE];
uint32 size;
uint32 offset;
} cli_buf_ctrl_t;
typedef struct st_clt_stmt {
struct st_clt_conn *conn;
uint16 id;
uint16 stmt_id;
clt_packet_t *cache_pack;
cli_stmt_status_t status;
list_t columns;
uint32 column_count;
list_t params;
uint32 param_count;
list_t outparams;
uint32 outparam_count;
uint32 paramset_size;
uint32 fetch_size;
uint32 prefetch_rows;
uint32 prefetch_buf;
uint32 affected_rows;
uint16 return_rows;
uint16 stmt_type;
uint16 sql_type;
bool8 more_rows;
bool8 eof;
uint8 fetch_mode;
uint8 reserved1[1];
uint32 fetched_times;
uint32 fetched_rows;
uint32 fetch_pos;
uint16 row_index;
*/
uint8 reserved2[2];
clt_serveroutput_t serveroutput;
clt_resultset_t resultset;
clt_batch_errs_t batch_errs;
cli_buf_ctrl_t *ctrl;
char *ori_row;
#ifdef OG_RAC_ING
uint64 gts_scn;
uint32 offset;
uint32 max_batch_buf_size;
uint32 paramset_len_offset;
char *batch_bnd_ptr;
char *batch_curr_ptr;
bool8 can_read_ack;
uint32 shard_dml_id;
uint64 scn;
bool8 is_log_slowsql;
cs_prepare_req_t *req;
#endif
} clt_stmt_t;
typedef struct st_clt_query {
clt_stmt_t *query_stmt;
list_t ids;
uint32 pos;
} clt_query_t;
typedef struct st_clt_conn {
spinlock_t parallel_lock;
uint32 sid;
uint32 serial;
int64 last_insert_id;
uint16 ready : 1;
uint16 in_process : 1;
uint16 auto_commit : 1;
uint16 exit_commit : 1;
uint16 serveroutput : 1;
uint16 interactive_clt : 1;
uint16 auto_commit_xa_backup : 1;
uint16 remote_as_sysdba : 1;
uint16 ogsql_in_altpwd : 1;
uint16 has_auth : 1;
uint8 shd_rw_split;
uint8 autotrace;
source_location_t loc;
int32 error_code;
char message[OG_MESSAGE_BUFFER_SIZE];
cs_packet_t pack;
list_t pack_list;
cs_pipe_t pipe;
ptlist_t stmts;
clt_query_t query;
clt_options_t options;
uint32 server_capabilities;
uint32 client_flag;
uint32 server_version;
uchar *ssl_connector;
uint32 call_version;
uint32 serial_number_send;
nlsparams_t nls_params;
ogconn_xact_status_t xact_status;
uint32 num_width;
uint16 local_charset;
int16 local_sessiontz;
cs_shd_node_type_t node_type;
transcode_func_t send_trans_func;
transcode_func_t recv_trans_func;
clt_server_info_t server_info;
uint8 flag_with_ts;
char curr_schema[OG_NAME_BUFFER_SIZE];
void *node;
alter_set_info_t alter_set_info;
} clt_conn_t;
#define CLT_CONN(conn) ((clt_conn_t *)(conn))
static inline void clt_set_error(clt_conn_t *conn, const char *file, uint32 line, int32 code, const char *format, ...)
{
va_list args;
conn->error_code = code;
conn->loc.line = 0;
conn->loc.column = 0;
va_start(args, format);
PRTS_RETVOID_IFERR(vsnprintf_s(conn->message, OG_MESSAGE_BUFFER_SIZE, OG_MESSAGE_BUFFER_SIZE - 1, format, args));
va_end(args);
}
#define CLT_SET_ERROR(conn, err_no, format, ...) \
{ \
clt_set_error(conn, (char *)__FILE__, (uint32)__LINE__, err_no, format, ##__VA_ARGS__); \
}
#define CLT_THROW_ERROR(conn, err_no, ...) \
{ \
clt_set_error(conn, (char *)__FILE__, (uint32)__LINE__, err_no, g_error_desc[err_no], ##__VA_ARGS__); \
}
#define CLT_SET_LOCAL_ERROR(conn, ret) \
do { \
status_t _status_ = (ret); \
if (SECUREC_UNLIKELY(_status_ != OG_SUCCESS)) { \
clt_copy_local_error(conn); \
return _status_; \
} \
} while (0)
#define OGCONN_CHECK_OBJECT_NULL_GS(obj_ptr, obj_name) \
{ \
if (SECUREC_UNLIKELY((obj_ptr) == NULL)) { \
OG_THROW_ERROR(ERR_CLT_OBJECT_IS_NULL, (obj_name)); \
return OG_ERROR; \
} \
}
#define OGCONN_CHECK_OBJECT_NULL_CLT(conn, obj_ptr, obj_name) \
{ \
if (SECUREC_UNLIKELY((obj_ptr) == NULL)) { \
CLT_THROW_ERROR(conn, ERR_CLT_OBJECT_IS_NULL, (obj_name)); \
return OG_ERROR; \
} \
}
#define CS_SERIAL_NUMBER_INC(conn, req) \
do { \
(conn)->serial_number_send++; \
(req)->head->serial_number = (conn)->serial_number_send; \
} while (0)
typedef struct st_clt_column_desc {
uint16 size;
uint8 precision;
int8 scale;
uint16 datatype;
bool8 nullable;
bool8 auto_increment;
bool8 is_character;
bool8 is_array;
bool8 is_jsonb;
bool8 is_rowid_type;
uint16 name_len;
char name[OG_NAME_BUFFER_SIZE];
} clt_column_desc_t;
typedef struct st_clt_inline_lob {
text_t cache_buf;
uint32 used_pos;
} clt_inline_lob_t;
struct st_clt_column;
typedef status_t (*copy_col_2_buf_t)(clt_stmt_t *stmt, struct st_clt_column *column);
typedef struct st_clt_column {
char *ptr;
struct {
char *bnd_ptr;
uint16 *ind_ptr;
copy_col_2_buf_t cp_func;
};
uint16 id;
uint16 size;
struct {
uint16 bnd_size;
uint8 bnd_type;
};
clt_column_desc_t def;
clt_inline_lob_t inline_lob;
} clt_column_t;
typedef struct st_clt_output_item {
text_t output;
uint32 cache_len;
} clt_output_item_t;
typedef struct st_clt_param {
char name[OG_NAME_BUFFER_SIZE];
uint8 direction;
uint8 bnd_type;
bool8 is_W_CType;
uint8 reserved;
uint32 bnd_size;
char *bnd_ptr;
uint16 *ind_ptr;
char *curr_ptr;
char *lob_ptr;
uint32 lob_ptr_size;
} clt_param_t;
typedef struct st_clt_outparam_desc {
char name[OG_NAME_BUFFER_SIZE];
uint16 size;
uint8 direction;
uint8 datatype;
} clt_outparam_desc_t;
typedef struct st_clt_outparam {
clt_outparam_desc_t def;
uint32 size;
char *ptr;
clt_stmt_t *sub_stmt;
} clt_outparam_t;
typedef struct st_clt_rs_stmt {
uint16 stmt_id;
uint8 fetch_mode;
uint8 reserved;
} clt_rs_stmt_t;
typedef struct st_clt_batch_err {
uint32 line;
int32 err_code;
char err_message[OG_MESSAGE_BUFFER_SIZE];
} clt_batch_error_t;
typedef struct __ctconn_stmt *ogconn_stmt_t;
int ogconn_transcode_ucs2(ogconn_stmt_t pstmt, const void *src, uint32 *src_len, void *dst, uint32 dst_len, bool32
*eof);
int ogconn_encrypt_password(char *orig_pswd, unsigned int orig_len, char *rand_local_key, char *rand_factor_key,
char *cipher, unsigned int *cipher_len);
int ogconn_decrypt_password(char *pswd, unsigned int len, char *rand_local_key, char *rand_factor_key, char *cipher,
unsigned int cipher_len);
int ogconn_set_charset(ogconn_stmt_t pstmt, uint16 charset_id);
void clt_free_pack(clt_conn_t *conn, clt_packet_t *clt_pack);
void clt_copy_local_error(clt_conn_t *conn);
status_t clt_receive_serveroutput(clt_stmt_t *stmt, cs_packet_t *ack);
status_t clt_reset_stmt_transcode_buf(clt_stmt_t *stmt);
status_t clt_alloc_pack(clt_conn_t *conn, clt_packet_t **clt_pack);
status_t ogconn_write_sql(clt_stmt_t *stmt, const char *sql, uint32 total_size, uint32 *curr_size, cs_packet_t
*req_pack);
status_t clt_set_conn_transcode_func(clt_conn_t *conn);
status_t clt_get_execute_ack(clt_stmt_t *stmt);
status_t clt_get_prepare_ack(clt_stmt_t *stmt, cs_packet_t *pack, const text_t *sql);
status_t clt_remote_call(clt_conn_t *conn, cs_packet_t *req, cs_packet_t *ack);
status_t clt_desc_column_by_id(clt_stmt_t *stmt, uint32 id, ogconn_column_desc_t *desc);
status_t clt_get_column_by_id(clt_stmt_t *stmt, uint32 id, void **data, uint32 *size, bool32 *is_null);
status_t clt_try_process_feedback(clt_stmt_t *stmt, cs_packet_t *ack);
status_t clt_verify_lob(clt_stmt_t *stmt, uint32 pos, clt_param_t **param);
status_t clt_transcode_column(clt_stmt_t *stmt, char **data, uint32 *size, transcode_func_t transcode_func);
status_t clt_try_get_batch_error(clt_stmt_t *stmt, cs_execute_ack_t *exec_ack, uint32 line_offset);
status_t cs_put_alter_set(cs_packet_t *req_pack, clt_stmt_t *stmt);
status_t clt_read_ack(clt_conn_t *conn, cs_packet_t *ack);
status_t clt_async_get_ack(clt_conn_t *conn, cs_packet_t *ack);
status_t clt_extend_param_list(clt_stmt_t *stmt, uint32 count);
static inline status_t clt_lock_conn(clt_conn_t *conn)
{
if (conn->in_process) {
CLT_THROW_ERROR(conn, ERR_CLT_PARALLEL_LOCK, conn->sid, cm_get_current_thread_id());
return OG_ERROR;
}
cm_spin_lock(&(conn->parallel_lock), NULL);
if (conn->in_process) {
CLT_THROW_ERROR(conn, ERR_CLT_PARALLEL_LOCK, conn->sid, cm_get_current_thread_id());
cm_spin_unlock(&(conn->parallel_lock));
return OG_ERROR;
}
conn->in_process = OG_TRUE;
cm_spin_unlock(&(conn->parallel_lock));
return OG_SUCCESS;
}
static inline void clt_unlock_conn(clt_conn_t *conn)
{
cm_spin_lock(&(conn->parallel_lock), NULL);
conn->in_process = OG_FALSE;
cm_spin_unlock(&(conn->parallel_lock));
}
static inline void clt_reset_error(clt_conn_t *conn)
{
conn->error_code = ERR_ERRNO_BASE;
conn->message[0] = '\0';
cm_reset_error();
}
static inline void clt_reset_lob(ogconn_lob_t *lob)
{
if (lob == NULL) {
return;
}
lob->size = 0;
lob->type = OG_LOB_FROM_VMPOOL;
lob->entry_vmid = OG_INVALID_ID32;
lob->last_vmid = OG_INVALID_ID32;
}
static inline void clt_reset_batch_lob(ogconn_lob_t *lob, uint32 paramset_size)
{
uint32 i;
if (lob == NULL) {
return;
}
for (i = 0; i < paramset_size; i++) {
clt_reset_lob(&lob[i]);
}
}
static inline status_t clt_strndup(const void *data, uint32 len, char **res)
{
char *dupstr = NULL;
if (data == NULL || len == 0 || len == OG_MAX_UINT32) {
*res = NULL;
return OG_SUCCESS;
}
dupstr = (char *)malloc(len + 1);
if (dupstr == NULL) {
OG_THROW_ERROR(ERR_MALLOC_BYTES_MEMORY, len + 1);
return OG_ERROR;
}
if (memcpy_s(dupstr, len, data, len) != EOK) {
CM_FREE_PTR(dupstr);
OG_THROW_ERROR(ERR_MALLOC_BYTES_MEMORY, len + 1);
return OG_ERROR;
}
dupstr[len] = '\0';
*res = dupstr;
return OG_SUCCESS;
}
static inline char *clt_strdup(const char *s)
{
char *result = NULL;
if (s == NULL) {
return NULL;
}
if (clt_strndup((const void *)s, (uint32)strlen(s), &result) != OG_SUCCESS) {
return NULL;
}
return result;
}
static inline void clt_session_nlsparam_geter(clt_stmt_t *stmt, nlsparam_id_t id, text_t *text)
{
const clt_conn_t *conn = stmt->conn;
conn->nls_params.param_geter(&conn->nls_params, id, text);
}
static inline uint32 clt_prefetch_rows(clt_stmt_t *stmt)
{
return (stmt->fetch_size > OG_INIT_PREFETCH_ROWS && stmt->fetch_size > stmt->prefetch_rows) ? stmt->fetch_size :
stmt->prefetch_rows;
}
status_t clt_get_error_message(clt_conn_t *conn, cs_packet_t *pack, char *err_msg);
#ifdef __cplusplus
}
#endif
#endif