secgateway/Platform/user/database/database.c

650 lines
19 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 <stdio.h>
#include <sql.h>
#include <sqlext.h>
#include <stdarg.h>
#include "database.h"
#include "cjson/cJSON.h"
#define DB_ROWS 20
#define DB_COLUMN 1
#define DB_STATUS_LEN 6
#define DB_ROWS_MAX_LEN 50
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 );
DumpODBCLog(NULL, hdbc, NULL);
if (ret != SQL_SUCCESS && ret != SQL_SUCCESS_WITH_INFO)
{
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_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_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)
{
DumpODBCLog(NULL, db_handle, hstmt);
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 - 应用需要返回的结果条数
* 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 = cJSON_CreateObject();
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;
}
/* 是否存在扩展参数,会采用不同的处理流程 */
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 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;
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++)
{
printf("\n db_column_info[j].dateType: %d j : %d", db_column_info[j].dateType, 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);
}
return json_data;
}
/*********************************************************************************
  * 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;
}
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
{
}
}
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;
}