* This file is part of the oGRAC project.
* Copyright (c) 2026 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.
* -------------------------------------------------------------------------
*
* connection.c
*
*
* IDENTIFICATION
* src/driver/ogodbc/connection.c
*/
#include "connection.h"
#include "cm_error.h"
static SQLRETURN handle_conn_error(HDBC *phdbc,
environment_class *env,
connection_class *conn,
char *msg)
{
*phdbc = SQL_NULL_HDBC;
env->error_msg = msg;
env->err_sign = ENV_ERROR;
free(conn);
conn = NULL;
return SQL_ERROR;
}
static void init_conn_info(connection_class *conn, environment_class *environment)
{
conn->error_msg = NULL;
conn->environment = environment;
conn->err_sign = 0;
conn->error_code = 0;
conn->flag = 1;
}
SQLRETURN ograc_AllocConnect(SQLHENV henv, SQLHDBC *phdbc)
{
ogconn_conn_t ogconn;
environment_class *environment = (environment_class *)henv;
connection_class *conn = NULL;
conn = (connection_class *)malloc(sizeof(connection_class));
status_t status;
if (henv == NULL || phdbc == NULL) {
return SQL_INVALID_HANDLE;
}
if (!conn) {
*phdbc = SQL_NULL_HDBC;
environment->error_msg = "Couldn't allocate memory for connection object.";
environment->err_sign = ENV_ERROR;
return SQL_ERROR;
}
status = ogconn_alloc_conn(&ogconn);
if (status != OG_SUCCESS) {
char *msg = "alloc connection handle error.";
return handle_conn_error(phdbc, environment, conn, msg);
}
if (memset_s(&conn->connInfo, sizeof(ConnInfo), 0, sizeof(ConnInfo)) != 0) {
char *msg = "clean up database info failed.";
ogconn_free_conn(ogconn);
return handle_conn_error(phdbc, environment, conn, msg);
}
int is_autocommit = AUTO_COMMIT;
status = ogconn_set_conn_attr(ogconn, OGCONN_ATTR_AUTO_COMMIT, &is_autocommit, sizeof(int));
if (status != OG_SUCCESS) {
char *msg = "set autoCommit attribute failed.";
ogconn_free_conn(ogconn);
return handle_conn_error(phdbc, environment, conn, msg);
}
init_conn_info(conn, environment);
conn->ogconn = ogconn;
*phdbc = conn;
return SQL_SUCCESS;
}
static SQLRETURN set_conn_info(connection_class *conn, const SQLCHAR *name,
SQLSMALLINT nameLength, char *buf, size_t size)
{
errno_t code;
uint32 len = 0;
if (name != NULL && name[0] != '\0') {
len = (nameLength == SQL_NTS) ? (uint32)strlen((const char *)name) : nameLength;
if (len >= size) {
conn->err_sign = 1;
conn->error_msg = "value is too long, create connection failed.";
return SQL_ERROR;
}
code = memcpy_s(buf, len, name, len);
if (code != 0) {
conn->err_sign = 1;
conn->error_msg = "secure C lib has throw an error.";
return SQL_ERROR;
}
buf[len] = '\0';
}
return SQL_SUCCESS;
}
SQLRETURN ograc_connect(SQLHDBC ConnectionHandle,
const SQLCHAR *ServerName, SQLSMALLINT NameLength1,
const SQLCHAR *UserName, SQLSMALLINT NameLength2,
const SQLCHAR *Authentication, SQLSMALLINT NameLength3)
{
connection_class *conn = (connection_class *)ConnectionHandle;
ConnInfo *info = NULL;
SQLRETURN retcode;
if (ServerName == NULL) {
conn->err_sign = 1;
conn->error_msg = "The ServerName is NULL";
return SQL_ERROR;
}
info = &conn->connInfo;
if (memset_s(info, sizeof(ConnInfo), 0, sizeof(ConnInfo)) != 0) {
conn->err_sign = 1;
conn->error_msg = "secure C lib has throw an error.";
return SQL_ERROR;
}
retcode = set_conn_info(conn, ServerName, NameLength1, info->dsn, sizeof(info->dsn));
if (retcode != SQL_SUCCESS) {
return retcode;
}
if (init_odbc_dsn(conn, info) != SQL_SUCCESS) {
return SQL_ERROR;
}
retcode = set_conn_info(conn, UserName, NameLength2, info->username, sizeof(info->username));
if (retcode != SQL_SUCCESS) {
return retcode;
}
retcode = set_conn_info(conn, Authentication, NameLength3, info->password, sizeof(info->password));
if (retcode != SQL_SUCCESS) {
return retcode;
}
retcode = og_db_connect(conn, info);
if (NULL != info->password) {
memset_s(info->password, sizeof(info->password), 0, sizeof(info->password));
}
if (NULL != info->sslpassword) {
memset_s(info->sslpassword, sizeof(info->sslpassword), 0, sizeof(info->sslpassword));
}
return retcode;
}
static SQLRETURN clean_up_info(connection_class *conn, size_t len)
{
if (memset_s(&conn->connInfo, len, 0, len) != 0) {
conn->err_sign = 1;
conn->error_msg = "secure C lib has throw an error.";
return SQL_ERROR;
}
return SQL_SUCCESS;
}
SQLRETURN ograc_disconnect(connection_class *conn)
{
ogconn_conn_t pconn;
if (!conn) {
conn->err_sign = 1;
conn->error_msg = "Connection handle is invalid";
return SQL_INVALID_HANDLE;
}
pconn = conn->ogconn;
ogconn_disconnect(pconn);
conn->flag = 1;
return clean_up_info(conn, sizeof(ConnInfo));
}
static column_param *get_col_param(statement *stmt, uint32 index, SQLPOINTER TargetValue)
{
uint32 p = 0;
column_param *col_param_temp = NULL;
column_param *col_param = NULL;
status_t status;
while (p < stmt->param.count) {
col_param_temp = (column_param *)cm_list_get(&stmt->param, p);
if (col_param_temp->ptr == index) {
return col_param_temp;
}
p++;
}
if (TargetValue != NULL) {
status = cm_list_new(&stmt->param, (void **)&col_param);
if (status != OGCONN_ERROR && col_param != NULL) {
col_param->ptr = index;
}
}
return col_param;
}
SQLRETURN ograc_bind_col(statement *stmt,
SQLUSMALLINT colIndex,
SQLSMALLINT ctype,
PTR dataPtr,
SQLLEN dataSize,
SQLLEN *buffPtr)
{
column_param *col_param = NULL;
uint32 index = colIndex - 1;
uint32 ptr = 0;
SQLLEN cal_len = 0;
col_param = get_col_param(stmt, index, dataPtr);
if (col_param != NULL) {
if (dataPtr != NULL) {
col_param->sql_type = ctype;
col_param->value = dataPtr;
col_param->size = buffPtr;
cal_len = cal_len_of_sql_type(ctype);
if (cal_len == 0) {
col_param->col_len = dataSize;
} else {
col_param->col_len = cal_len;
}
ptr = colIndex - 1;
} else {
col_param->sql_type = SQL_C_CHAR;
col_param->value = NULL;
*(col_param->size) = 0;
col_param->col_len = 0;
ptr = col_param->ptr;
}
col_param->generate_result.result_size = 0;
col_param->generate_result.sql_type = SQL_C_DEFAULT;
col_param->generate_result.is_str = OG_FALSE;
col_param->generate_result.is_col = OG_TRUE;
col_param->generate_result.ptr = ptr;
col_param->generate_result.is_recieved = OG_FALSE;
col_param->generate_result.og_type = OGCONN_TYPE_UNKNOWN;
}
return SQL_SUCCESS;
}