secgateway/Platform/user/database/database.c

731 lines
22 KiB
C
Raw Blame History

This file contains invisible Unicode characters

This file contains invisible Unicode characters that are indistinguishable to humans but may be processed differently by a computer. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

#include <stdlib.h>
#include <stdio.h>
#include <sql.h>
#include <sqlext.h>
#include <stdarg.h>
#include "database.h"
#include "cjson/cJSON.h"
/* 保存列信息的数据结构 */
typedef struct column_info
{
char name[30];
SQLSMALLINT nameLength;
SQLSMALLINT dateType;
SQLULEN columnSize;
SQLSMALLINT decimalDigits;
SQLSMALLINT nullable;
}COLUMN_INFO_T;
/*********************************************************************************
  * Description  
* 打印异常信息
  * Input:  
* hEnv - 环境变量
* hDbc - 连接句柄
* hStmt - 新分配的数据结构的句柄缓冲区的指针
  * Output:
* 
  * Return:
* 无
  * Others:
* 无
**********************************************************************************/
static void DumpODBCLog(SQLHENV hEnv, SQLHDBC hDbc, SQLHSTMT hStmt)
{
SQLTCHAR szError[501];
SQLTCHAR szSqlState[10];
SQLINTEGER nNativeError;
SQLSMALLINT nErrorMsg;
if (hStmt != NULL)
{
while ( SQLError( hEnv, hDbc, hStmt, szSqlState, &nNativeError, szError, 500, &nErrorMsg ) == SQL_SUCCESS )
{
printf( "%s\n", szError);
}
}
if (hDbc != NULL)
{
while ( SQLError( hEnv, hDbc, 0, szSqlState, &nNativeError, szError, 500, &nErrorMsg ) == SQL_SUCCESS )
{
printf( "%s\n", szError);
}
}
if (hEnv != NULL)
{
while ( SQLError( hEnv, 0, 0, szSqlState, &nNativeError, szError, 500, &nErrorMsg ) == SQL_SUCCESS )
{
printf( "%s\n", szError);
}
}
return;
}
/*********************************************************************************
  * Description  
* 连接数据库操作
  * Input:  
* module_id - 模块ID每个模块需要向数据库模块设置模块ID用于打印、统计使用
  * Output:
* 
  * Return:
* 数据库句柄
* NULL - 连接数据库失败
* 非NULL - 连接数据库成功
  * Others:
* 无
**********************************************************************************/
void * connect_database (int module_id)
{
SQLHENV henv = NULL;
SQLHDBC hdbc = NULL;
SQLRETURN ret;
SQLAllocHandle( SQL_HANDLE_ENV, SQL_NULL_HANDLE, &henv);
SQLSetEnvAttr( henv, SQL_ATTR_ODBC_VERSION, (SQLPOINTER)SQL_OV_ODBC3, 0 );
SQLAllocHandle( SQL_HANDLE_DBC, henv, &hdbc );
SQLSetConnectAttr( hdbc, SQL_ATTR_ODBC_CURSORS, (SQLPOINTER)SQL_CUR_USE_ODBC, 0 );
ret = SQLConnect( hdbc, "meng", SQL_NTS, "", SQL_NTS, "", SQL_NTS );
if (ret != SQL_SUCCESS)
{
return NULL;
}
return hdbc;
}
/*********************************************************************************
  * Description  
* 释放数据库连接
  * Input:  
* module_id - 模块ID每个模块需要向数据库模块设置模块ID用于打印、统计使用
  * db_handle - 数据库句柄
* Output:
* 
  * Return:
* DB_RET_PARAM_NULL - 入参指针为NULL
* DB_RET_ERR - 释放失败
* DB_RET_OK - 释放成功
  * Others:
* 无
**********************************************************************************/
int disconnect_database (int module_id, void * db_handle)
{
SQLRETURN ret;
if (NULL == db_handle)
{
return DB_RET_PARAM_NULL;
}
SQLDisconnect(db_handle);
ret = SQLFreeHandle(SQL_HANDLE_DBC, db_handle);
if (ret != SQL_SUCCESS)
{
return DB_RET_ERR;
}
return DB_RET_OK;
}
/*********************************************************************************
  * Description  
* 创建数据库表
  * Input:  
* module_id - 模块ID每个模块需要向数据库模块设置模块ID用于打印、统计使用
  * db_handle - 数据库句柄
* table_name - 创建的表名
* sql_str - 创建表的SQL语句
* Output:
* 
  * Return:
* DB_RET_PARAM_NULL - 入参指针为NULL
* DB_RET_ERR - 释放失败
* DB_RET_OK - 释放成功
  * Others:
* 无
**********************************************************************************/
int create_database_table(int module_id, void * db_handle, char * table_name, char * sql_str)
{
SQLRETURN ret;
SQLHSTMT hstmt;
if ((NULL == db_handle) || (NULL == table_name) || (NULL == sql_str))
{
return DB_RET_PARAM_NULL;
}
ret = SQLAllocHandle( SQL_HANDLE_STMT, db_handle, &hstmt);
if ((SQL_INVALID_HANDLE == ret) || (SQL_ERROR == ret))
{
return DB_RET_ERR;
}
ret = SQLExecDirect(hstmt, sql_str, SQL_NTS);
SQLCloseCursor(hstmt);
SQLFreeStmt(hstmt, SQL_DROP);
if (ret != SQL_SUCCESS)
{
return DB_RET_ERR;
}
return DB_RET_OK;
}
/*********************************************************************************
  * Description  
* 对据库表执行插入、删除、更新操作
  * Input:  
* module_id - 模块ID每个模块需要向数据库模块设置模块ID用于打印、统计使用
  * db_handle - 数据库句柄
* op_type - 操作类型 DB_OP_INSERT插入数据 DB_OP_DEL删除数据 DB_OP_UPDATE更新数据
* table_name - 创建的表名
* sql_str - 创建表的SQL语句
* param_num - 扩展参数组合数量填写0表示没有需要防止SQL注入问题需要使用扩展参数组合
* Output:
* 
  * Return:
* DB_RET_PARAM_NULL - 入参指针为NULL
* DB_RET_PARAM_ERR - 入参错误
* DB_RET_ERR - 操作失败
* DB_RET_OK - 操作成功
  * Others:
* 无
**********************************************************************************/
int update_database(int module_id, void * db_handle, int op_type, char * table_name, char * sql_str, int param_num, ...)
{
SQLRETURN ret;
SQLHSTMT hstmt;
SQLUSMALLINT RowStatusArray[DB_ROWS];
if ((NULL == db_handle) || (NULL == table_name) || (NULL == sql_str))
{
return DB_RET_PARAM_NULL;
}
if ((op_type != DB_OP_INSERT) && (op_type != DB_OP_DEL) && (op_type != DB_OP_UPDATE))
{
return DB_RET_PARAM_ERR;
}
SQLAllocHandle(SQL_HANDLE_STMT, db_handle, &hstmt);
if ((SQL_INVALID_HANDLE == ret) || (SQL_ERROR == ret))
{
return DB_RET_ERR;
}
SQLSetStmtAttr(hstmt, SQL_ATTR_CONCURRENCY, (SQLPOINTER)SQL_CONCUR_VALUES, 0);
SQLSetStmtAttr(hstmt, SQL_ATTR_CURSOR_TYPE, (SQLPOINTER)SQL_CURSOR_STATIC, 0);
SQLSetStmtAttr(hstmt, SQL_ATTR_ROW_ARRAY_SIZE, (SQLPOINTER)DB_COLUMN, 20 );
SQLSetStmtAttr(hstmt, SQL_ATTR_ROW_STATUS_PTR, RowStatusArray, 0);
SQLSetCursorName(hstmt, "ORDERCURSOR", SQL_NTS );
/* 是否存在扩展参数,会采用不同的处理流程 */
if (0 == param_num)
{
ret = SQLExecDirect(hstmt, sql_str, SQL_NTS);
}
else
{
int i;
int type;
int len;
SQLLEN ind_name = SQL_NTS;
long long int_temp;
va_list ap;
double double_temp;
SQLPrepare(hstmt, sql_str, SQL_NTS);
va_start(ap, param_num);
/* 执行参数绑定操作 */
for (i = 1; i <= param_num; i++)
{
type = va_arg(ap, int);
len = va_arg(ap, int);
if (DB_DATA_INT_TYPE == type)
{
int_temp = va_arg(ap, long long);
ret = SQLBindParameter(hstmt, i, SQL_PARAM_INPUT, SQL_C_UBIGINT, SQL_C_UBIGINT, len, 0, &int_temp, len, &ind_name);
}
else if (DB_DATA_STRING_TYPE == type)
{
ret = SQLBindParameter(hstmt, i, SQL_PARAM_INPUT, SQL_C_CHAR, SQL_CHAR , len, 0, va_arg(ap, char *), len, &ind_name);
}
else if (DB_DATA_FLOAT_TYPE == type)
{
double_temp = va_arg(ap, double);
ret = SQLBindParameter(hstmt, i, SQL_PARAM_INPUT, SQL_C_DOUBLE, SQL_DOUBLE, len, 0, &double_temp, len, &ind_name);
}
else
{
/* 当前只支持以上三种类型,如果不是则打印报错 */
printf("\n type error : %d", type);
}
}
va_end(ap);
ret = SQLExecute(hstmt);
}
SQLCloseCursor(hstmt);
SQLFreeStmt(hstmt, SQL_DROP);
if (ret != SQL_SUCCESS)
{
return DB_RET_ERR;
}
return DB_RET_OK;
}
/*********************************************************************************
  * Description  
* 根据指定信息查找数据库
  * Input:  
* module_id - 模块ID每个模块需要向数据库模块设置模块ID用于打印、统计使用
  * db_handle - 数据库句柄
* table_name - 创建的表名
* sql_str - 创建表的SQL语句
* begin_num - 从第几条查询结果开始返回
* need_num - 应用需要返回的结果条数, 如果need_num = 0表示返回所有数据
* param_num - 扩展参数组合数量填写0表示没有需要防止SQL注入问题需要使用扩展参数组合
* Output:
*  return_num - 实际返回的结果条数
  * Return:
* NULL - 操作失败
* 非NULL - 返回CJSON格式的查询结果
  * Others:
* 无
**********************************************************************************/
void * select_datebase_by_number(int module_id, void * db_handle, char * table_name, char * sql_str, int begin_num, int need_num, int * return_num, int param_num, ...)
{
SQLRETURN ret;
SQLHSTMT hstmt;
SQLUSMALLINT RowStatusArray[DB_ROWS];
SQLSMALLINT nameLength = 0;
SQLSMALLINT dateType = 0;
SQLULEN columnSize = 0;
SQLSMALLINT decimalDigits = 0;
SQLSMALLINT nullable = 0;
SQLRETURN retcode = 0;
int i = 0;
int j = 0;
COLUMN_INFO_T db_column_info[20];
int column_nmuber = 0;
SQLCHAR value[DB_ROWS][DB_COLUMN][DB_ROWS_MAX_LEN];
int ret_num = 0;
SQLUINTEGER FetchOrientation;
SQLLEN cbValue[DB_ROWS][DB_ROWS_MAX_LEN];
cJSON *json = NULL;
char *json_data = NULL;
cJSON *array = NULL;
cJSON * obj = NULL;
if ((NULL == db_handle) || (NULL == table_name) || (NULL == sql_str))
{
return NULL;
}
if ((begin_num <= 0) || (need_num < 0))
{
return NULL;
}
ret = SQLAllocHandle(SQL_HANDLE_STMT, db_handle, &hstmt);
if ((SQL_INVALID_HANDLE == ret) || (SQL_ERROR == ret))
{
return NULL;
}
SQLSetStmtAttr( hstmt, SQL_ATTR_CONCURRENCY, (SQLPOINTER)SQL_CONCUR_VALUES, 0 );
SQLSetStmtAttr( hstmt, SQL_ATTR_CURSOR_TYPE, (SQLPOINTER)SQL_CURSOR_STATIC, 0 );
SQLSetStmtAttr( hstmt, SQL_ATTR_ROW_ARRAY_SIZE, (SQLPOINTER)DB_COLUMN, 20 );
SQLSetStmtAttr( hstmt, SQL_ATTR_ROW_STATUS_PTR, RowStatusArray, 0 );
SQLSetCursorName( hstmt, "ORDERCURSOR", SQL_NTS );
SQLPrepare( hstmt, sql_str, SQL_NTS );
column_nmuber = 1;
/* 解析查询结果中包含的列信息 */
do
{
retcode = SQLDescribeCol(hstmt, column_nmuber, db_column_info[column_nmuber].name, sizeof(db_column_info[column_nmuber].name), &db_column_info[column_nmuber].nameLength,
&db_column_info[column_nmuber].dateType, &db_column_info[column_nmuber].columnSize,
&db_column_info[column_nmuber].decimalDigits, &db_column_info[column_nmuber].nullable);
if (retcode != SQL_SUCCESS)
{
column_nmuber--;
break;
}
column_nmuber++;
}while(1);
/* 如果列为0返回查询结果 */
if (0 == column_nmuber)
{
SQLCloseCursor(hstmt);
SQLFreeStmt(hstmt, SQL_DROP);
return NULL;
}
*return_num = 0;
/* 是否存在扩展参数,会采用不同的处理流程 */
if (0 == param_num)
{
ret = SQLExecDirect(hstmt, sql_str, SQL_NTS);
}
else
{
int i;
int type;
int len;
SQLLEN ind_name = SQL_NTS;
long long int_temp;
va_list ap;
double double_temp;
SQLPrepare(hstmt, sql_str, SQL_NTS);
va_start(ap, param_num);
for (i = 1; i <= param_num; i++)
{
type = va_arg(ap, int);
len = va_arg(ap, int);
if (DB_DATA_INT_TYPE == type)
{
int_temp = va_arg(ap, long long);
ret = SQLBindParameter(hstmt, i, SQL_PARAM_INPUT, SQL_C_UBIGINT, SQL_C_UBIGINT, len, 0, &int_temp, len, &ind_name);
}
else if (DB_DATA_STRING_TYPE == type)
{
ret = SQLBindParameter(hstmt, i, SQL_PARAM_INPUT, SQL_C_CHAR, SQL_CHAR , len, 0, va_arg(ap, char*), len, &ind_name);
}
else if (DB_DATA_FLOAT_TYPE == type)
{
double_temp = va_arg(ap, double);
ret = SQLBindParameter(hstmt, i, SQL_PARAM_INPUT, SQL_C_DOUBLE, SQL_DOUBLE, len, 0, &double_temp, len, &ind_name);
}
else
{
/* 当前只支持以上三种类型,如果不是则打印报错 */
printf("\n type error : %d", type);
}
}
va_end(ap);
ret = SQLExecute(hstmt);
}
if (ret != SQL_SUCCESS)
{
SQLCloseCursor(hstmt);
SQLFreeStmt(hstmt, SQL_DROP);
return NULL;
}
json = cJSON_CreateObject();
if (NULL == json)
{
SQLCloseCursor(hstmt);
SQLFreeStmt(hstmt, SQL_DROP);
return NULL;
}
/* 将应用程序数据缓冲区绑定到结果集中的列 */
for (i = 1; i <= column_nmuber; i++)
{
if (SQL_BIGINT == db_column_info[i].dateType)
{
SQLBindCol(hstmt, i, SQL_C_UBIGINT, value[i][0], DB_ROWS_MAX_LEN, cbValue[i]);
}
else if (SQL_CHAR == db_column_info[i].dateType)
{
SQLBindCol(hstmt, i, db_column_info[i].dateType, value[i][0], DB_ROWS_MAX_LEN, cbValue[i]);
}
else if (SQL_DOUBLE == db_column_info[i].dateType)
{
SQLBindCol(hstmt, i, db_column_info[i].dateType, value[i][0], 0, cbValue[i]);
}
else
{
/* 不支持的类型 */
}
}
cJSON_AddItemToObject(json, "data", array = cJSON_CreateArray());
/* 查询结果 */
FetchOrientation = SQL_FETCH_RELATIVE;
/* need_num为0表示一次返回所有找到的信息 */
if (0 == need_num)
{
while(1)
{
ret = SQLFetchScroll(hstmt, FetchOrientation, begin_num);
FetchOrientation = SQL_FETCH_NEXT;
/* 查找失败,表示已经返回所有找到的信息 */
if (ret != SQL_SUCCESS)
{
break;
}
ret_num++;
cJSON_AddItemToArray(array, obj = cJSON_CreateObject());
for (j = 1; j <= column_nmuber; j++)
{
if (SQL_BIGINT == db_column_info[j].dateType)
{
cJSON_AddNumberToObject(obj, db_column_info[j].name, *((long long *)&(value[j][0])));
}
else if (SQL_CHAR == db_column_info[j].dateType)
{
cJSON_AddStringToObject(obj, db_column_info[j].name , value[j][0]);
}
else if (SQL_DOUBLE == db_column_info[j].dateType)
{
cJSON_AddNumberToObject(obj, db_column_info[j].name , *((double *)&(value[j][0])));
}
else
{
/* 不支持类型,后续增加统计和打印 */
}
}
}
}
else
{
for (i = 1; i <= need_num; i++)
{
ret = SQLFetchScroll(hstmt, FetchOrientation, begin_num);
FetchOrientation = SQL_FETCH_NEXT;
/* 查找失败,表示已经返回所有找到的信息 */
if (ret != SQL_SUCCESS)
{
break;
}
ret_num++;
cJSON_AddItemToArray(array, obj = cJSON_CreateObject());
for (j = 1; j <= column_nmuber; j++)
{
if (SQL_BIGINT == db_column_info[j].dateType)
{
cJSON_AddNumberToObject(obj, db_column_info[j].name, *((long long *)&(value[j][0])));
}
else if (SQL_CHAR == db_column_info[j].dateType)
{
cJSON_AddStringToObject(obj, db_column_info[j].name , value[j][0]);
}
else if (SQL_DOUBLE == db_column_info[j].dateType)
{
cJSON_AddNumberToObject(obj, db_column_info[j].name , *((double *)&(value[j][0])));
}
else
{
/* 不支持类型,后续增加统计和打印 */
}
}
}
}
SQLCloseCursor(hstmt);
SQLFreeStmt(hstmt, SQL_DROP);
*return_num = ret_num;
if (ret_num != 0)
{
json_data = cJSON_Print(json);
}
cJSON_Delete(json);
return json_data;
}
/*********************************************************************************
  * Description  
* 释放查询接口申请的内存
  * Input:  
* module_id - 模块ID每个模块需要向数据库模块设置模块ID用于打印、统计使用
* table_name - 创建的表名
* memory_ptr - 待释放内存指针
* Output:
* 
  * Return:
* DB_RET_PARAM_NULL - 入参指针为NULL
* DB_RET_ERR - 操作失败
* DB_RET_OK - 操作成功
  * Others:
* 无
**********************************************************************************/
int free_database_memory(int module_id, char * table_name, void * memory_ptr)
{
if ((NULL == table_name) && (NULL == memory_ptr))
{
return DB_RET_PARAM_NULL;
}
free(memory_ptr);
return DB_RET_OK;
}
/*********************************************************************************
  * Description  
* 返回根据指定信息查找数据库的结果的条目数
  * Input:  
* module_id - 模块ID每个模块需要向数据库模块设置模块ID用于打印、统计使用
  * db_handle - 数据库句柄
* table_name - 创建的表名
* sql_str - 创建表的SQL语句
* param_num - 扩展参数组合数量填写0表示没有需要防止SQL注入问题需要使用扩展参数组合
* Output:
*  ret_num - 实际返回的结果条数
  * Return:
* DB_RET_PARAM_NULL - 入参指针为NULL
* DB_RET_ERR - 操作失败
* DB_RET_OK - 操作成功
  * Others:
* 无
**********************************************************************************/
int get_select_datebase_number(int module_id, void * db_handle, char * table_name, char * sql_str, int * ret_num, int param_num, ...)
{
SQLRETURN ret;
SQLHSTMT hstmt;
SQLUSMALLINT RowStatusArray[DB_ROWS];
SQLSMALLINT nameLength = 0;
SQLSMALLINT dateType = 0;
SQLULEN columnSize = 0;
SQLSMALLINT decimalDigits = 0;
SQLSMALLINT nullable = 0;
SQLRETURN retcode = 0;
int i = 0;
int j = 0;
COLUMN_INFO_T db_column_info[20];
int column_nmuber = 0;
SQLCHAR value[DB_ROWS][DB_COLUMN][DB_ROWS_MAX_LEN];
int returnNum = 0;
SQLUINTEGER FetchOrientation;
SQLLEN cbValue[DB_ROWS_MAX_LEN][DB_ROWS];
SQLLEN count;
if ((NULL == db_handle) || (NULL == table_name) || (NULL == sql_str))
{
return DB_RET_PARAM_NULL;
}
ret = SQLAllocHandle( SQL_HANDLE_STMT, db_handle, &hstmt);
if ((SQL_INVALID_HANDLE == ret) || (SQL_ERROR == ret))
{
return DB_RET_ERR;
}
*ret_num = 0;
SQLSetStmtAttr( hstmt, SQL_ATTR_CONCURRENCY, (SQLPOINTER)SQL_CONCUR_VALUES, 0 );
SQLSetStmtAttr( hstmt, SQL_ATTR_CURSOR_TYPE, (SQLPOINTER)SQL_CURSOR_STATIC, 0 );
SQLSetStmtAttr( hstmt, SQL_ATTR_ROW_ARRAY_SIZE, (SQLPOINTER)DB_COLUMN, 20 );
SQLSetStmtAttr( hstmt, SQL_ATTR_ROW_STATUS_PTR, RowStatusArray, 0 );
SQLSetCursorName( hstmt, "ORDERCURSOR", SQL_NTS );
SQLPrepare( hstmt, sql_str, SQL_NTS );
if (0 == param_num)
{
ret = SQLExecDirect(hstmt, sql_str, SQL_NTS);
}
else
{
int i;
int type;
int len;
SQLLEN ind_name = SQL_NTS;
long long int_temp;
va_list ap;
double double_temp;
SQLPrepare(hstmt, sql_str, SQL_NTS);
va_start(ap, param_num);
for (i = 1; i <= param_num; i++)
{
type = va_arg(ap, int);
len = va_arg(ap, int);
if (DB_DATA_INT_TYPE == type)
{
int_temp = va_arg(ap, long long);
ret = SQLBindParameter(hstmt, i, SQL_PARAM_INPUT, SQL_C_UBIGINT, SQL_C_UBIGINT, len, 0, &int_temp, len, &ind_name);
}
else if (DB_DATA_STRING_TYPE == type)
{
ret = SQLBindParameter(hstmt, i, SQL_PARAM_INPUT, SQL_C_CHAR, SQL_CHAR , len, 0, va_arg(ap, char*), len, &ind_name);
}
else if (DB_DATA_FLOAT_TYPE == type)
{
double_temp = va_arg(ap, double);
ret = SQLBindParameter(hstmt, i, SQL_PARAM_INPUT, SQL_C_DOUBLE, SQL_DOUBLE, len, 0, &double_temp, len, &ind_name);
}
else
{
}
}
va_end(ap);
ret = SQLExecute(hstmt);
}
if (ret != SQL_SUCCESS)
{
SQLCloseCursor(hstmt);
SQLFreeStmt(hstmt, SQL_DROP);
return DB_RET_ERR;
}
SQLRowCount( hstmt, &count);
*ret_num = count;
SQLCloseCursor(hstmt);
SQLFreeStmt(hstmt, SQL_DROP);
return DB_RET_OK;
}