#include #include #include #include #include #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; }