You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

156 lines
3.8 KiB

// OracleDB.cpp
#include "OracleDB.h"
#include <cstring>
#include <cstdlib>
#include <cstdio>
#include <string>
#include <vector>
OracleDB::OracleDB() : conn(nullptr), stmt(nullptr), isConnected(false) {}
OracleDB::~OracleDB() {
disconnect();
}
bool OracleDB::connect(const char* user, const char* pwd, const char* host) {
if (isConnected) return true;
// 创建连接
conn = OCI_ConnectionCreate(host, user, pwd, OCI_SESSION_DEFAULT);
if (!conn) {
printf("连接数据库失败: %s\n", OCI_GetLastError() ? OCI_ErrorGetString(OCI_GetLastError()) : "Unknown error");
return false;
}
stmt = OCI_StatementCreate(conn);
if (!stmt) {
printf("创建语句对象失败\n");
OCI_ConnectionFree(conn);
conn = nullptr;
return false;
}
isConnected = true;
printf("数据库连接成功\n");
return true;
}
void OracleDB::disconnect() {
if (stmt) {
OCI_StatementFree(stmt);
stmt = nullptr;
}
if (conn) {
OCI_ConnectionFree(conn);
conn = nullptr;
}
isConnected = false;
}
int OracleDB::executeQuery(
const char* sql,
int* outputColumn,
int* outputRow,
char**** outputValue
) {
// 初始化输出参数
*outputColumn = 0;
*outputRow = 0;
*outputValue = nullptr;
printf("初始化输出参数完成\n");
if (!isConnected || !stmt) {
printf("数据库未连接或语句对象无效\n");
return -1;
}
printf("检查数据库连接成功\n");
if (!OCI_ExecuteStmt(stmt, sql)) {
printf("SQL执行失败: %s\n", OCI_ErrorGetString(OCI_GetLastError()));
return -1;
}
printf("SQL语句执行成功\n");
OCI_Resultset* rs = OCI_GetResultset(stmt);
if (!rs) {
printf("无法获取结果集\n");
return -1;
}
printf("获取结果集成功\n");
int colCount = (int)OCI_GetColumnCount(rs);
printf("列数: %d\n", colCount);
// 使用 vector 临时存储所有数据
std::vector<std::vector<std::string>> tempData;
int rowCount = 0;
while (OCI_FetchNext(rs)) {
std::vector<std::string> row;
for (int j = 0; j < colCount; j++) {
const char* val = OCI_GetString(rs, j + 1);
if (val) {
row.push_back(std::string(val));
}
else {
row.push_back("NULL");
}
}
tempData.push_back(row);
rowCount++;
}
printf("遍历结果集完成,行数: %d\n", rowCount);
// 分配 outputValue
char*** result = (char***)calloc(rowCount, sizeof(char**));
if (!result) {
printf("内存分配失败\n");
return -1;
}
printf("为结果分配内存完成\n");
for (int i = 0; i < rowCount; i++) {
result[i] = (char**)calloc(colCount, sizeof(char*));
if (!result[i]) {
// 清理已分配内存
for (int j = 0; j < i; j++) {
for (int k = 0; k < colCount; k++) {
free(result[j][k]);
}
free(result[j]);
}
free(result);
printf("内存分配失败\n");
return -1;
}
printf("为第 %d 行分配内存完成\n", i + 1);
for (int j = 0; j < colCount; j++) {
const std::string& val = tempData[i][j];
result[i][j] = (char*)malloc(val.length() + 1);
if (result[i][j]) {
strcpy(result[i][j], val.c_str());
printf("复制第 %d 行第 %d 列的数据: %s\n", i + 1, j + 1, result[i][j]);
}
else {
result[i][j] = nullptr;
printf("内存分配失败,设置第 %d 行第 %d 列为空指针\n", i + 1, j + 1);
}
}
}
// 设置输出参数
*outputColumn = colCount;
*outputRow = rowCount;
*outputValue = result;
printf("executeQuery 成功返回\n");
return 0; // 成功
}