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.

582 lines
16 KiB

This file contains ambiguous Unicode characters!

This file contains ambiguous Unicode characters that may be confused with others in your current locale. If your use case is intentional and legitimate, you can safely ignore this warning. Use the Escape button to highlight these characters.

#include <iostream>
#include <occi.h>
using namespace oracle::occi;
using namespace std;
class occidml
{
private:
public:
Environment* env;
oracle::occi::Connection* conn;
Statement* stmt;
occidml (string user, string passwd, string db)
{
#ifdef _WIN32
_putenv("NLS_LANG=AMERICAN_AMERICA.ZHS16GBK");
#else
setenv("NLS_LANG", "SIMPLIFIED CHINESE_CHINA.ZHS16GBK", 1);
#endif
printf("0-\n");
env = Environment::createEnvironment (Environment::DEFAULT);
printf("1-\n");
conn = env->createConnection (user, passwd, db);
printf("2-\n");
}
~occidml ()
{
printf("3-\n");
env->terminateConnection (conn);
printf("4-\n");
Environment::terminateEnvironment (env);
printf("5-\n");
}
string safeGetString(ResultSet* rset, int colIndex) {
try {
if (rset->isNull(colIndex)) {
return "NULL";
}
Bytes bytes = rset->getBytes(colIndex);
if (bytes.length() <= 0) {
return "";
}
// ¸´ÖÆ×Ö½Ú
unsigned char* buf = new unsigned char[bytes.length()];
bytes.getBytes(buf, bytes.length());
string result(reinterpret_cast<char*>(buf), bytes.length());
delete[] buf;
return result;
}
catch (...) {
return "ERROR";
}
}
/**
* Insertion of a row with dynamic binding, PreparedStatement functionality.
*/
void insertBind (int c1, string c2)
{
string sqlStmt = "INSERT INTO author_tab VALUES (:x, :y)";
stmt=conn->createStatement (sqlStmt);
try{
stmt->setInt (1, c1);
stmt->setString (2, c2);
stmt->executeUpdate ();
cout << "insert - Success" << endl;
}catch(SQLException ex)
{
cout<<"Exception thrown for insertBind"<<endl;
cout<<"Error number: "<< ex.getErrorCode() << endl;
cout<<ex.getMessage() << endl;
}
conn->terminateStatement (stmt);
}
/**
* Inserting a row into the table.
*/
void insertRow ()
{
string sqlStmt = "INSERT INTO author_tab VALUES (111, 'ASHOK')";
stmt = conn->createStatement (sqlStmt);
try{
stmt->executeUpdate ();
cout << "insert - Success" << endl;
}catch(SQLException ex)
{
cout<<"Exception thrown for insertRow"<<endl;
cout<<"Error number: "<< ex.getErrorCode() << endl;
cout<<ex.getMessage() << endl;
}
conn->terminateStatement (stmt);
}
/**
* updating a row
*/
void updateRow (int c1, string c2)
{
string sqlStmt =
"UPDATE author_tab SET author_name = :x WHERE author_id = :y";
stmt = conn->createStatement (sqlStmt);
try{
stmt->setString (1, c2);
stmt->setInt (2, c1);
stmt->executeUpdate ();
cout << "update - Success" << endl;
}catch(SQLException ex)
{
cout<<"Exception thrown for updateRow"<<endl;
cout<<"Error number: "<< ex.getErrorCode() << endl;
cout<<ex.getMessage() << endl;
}
conn->terminateStatement (stmt);
}
/**
* deletion of a row
*/
void deleteRow (int c1, string c2)
{
string sqlStmt =
"DELETE FROM author_tab WHERE author_id= :x AND author_name = :y";
stmt = conn->createStatement (sqlStmt);
try{
stmt->setInt (1, c1);
stmt->setString (2, c2);
stmt->executeUpdate ();
cout << "delete - Success" << endl;
}catch(SQLException ex)
{
cout<<"Exception thrown for deleteRow"<<endl;
cout<<"Error number: "<< ex.getErrorCode() << endl;
cout<<ex.getMessage() << endl;
}
conn->terminateStatement (stmt);
}
/**
* displaying all the rows in the table
*/
void displayAllRows ()
{
string sqlStmt = "SELECT author_id, author_name FROM author_tab \
order by author_id";
stmt = conn->createStatement (sqlStmt);
ResultSet *rset = stmt->executeQuery ();
try{
while (rset->next ())
{
cout << "author_id: " << rset->getInt (1) << " author_name: "
<< rset->getString (2) << endl;
}
}catch(SQLException ex)
{
cout<<"Exception thrown for displayAllRows"<<endl;
cout<<"Error number: "<< ex.getErrorCode() << endl;
cout<<ex.getMessage() << endl;
}
stmt->closeResultSet (rset);
conn->terminateStatement (stmt);
}
/**
* Inserting a row into elements table.
* Demonstrating the usage of BFloat and BDouble datatypes
*/
void insertElement (string elm_name, float mvol=0.0, double awt=0.0)
{
BFloat mol_vol;
BDouble at_wt;
if (!(mvol))
mol_vol.isNull = TRUE;
else
mol_vol.value = mvol;
if (!(awt))
at_wt.isNull = TRUE;
else
at_wt.value = awt;
string sqlStmt = "INSERT INTO elements VALUES (:v1, :v2, :v3)";
stmt = conn->createStatement (sqlStmt);
try{
stmt->setString(1, elm_name);
stmt->setBFloat(2, mol_vol);
stmt->setBDouble(3, at_wt);
stmt->executeUpdate ();
cout << "insertElement - Success" << endl;
}catch(SQLException ex)
{
cout<<"Exception thrown for insertElement"<<endl;
cout<<"Error number: "<< ex.getErrorCode() << endl;
cout<<ex.getMessage() << endl;
}
conn->terminateStatement (stmt);
}
/**
* displaying rows from element table
*/
void displayElements ()
{
string sqlStmt =
"SELECT element_name, molar_volume, atomic_weight FROM elements \
order by element_name";
stmt = conn->createStatement (sqlStmt);
ResultSet *rset = stmt->executeQuery ();
try{
cout.precision(7);
while (rset->next ())
{
string elem_name = rset->getString(1);
BFloat mol_vol = rset->getBFloat(2);
BDouble at_wt = rset->getBDouble(3);
cout << "Element Name: " << elem_name << endl;
if ( mol_vol.isNull )
cout << "Molar Volume is NULL" << endl;
else
cout << "Molar Volume: " << mol_vol.value << " cm3 mol-1" << endl;
if ( at_wt.isNull )
cout << "Atomic Weight is NULL" << endl;
else
cout << "Atomic Weight: " << at_wt.value << " g/mole" << endl;
}
}catch(SQLException ex)
{
cout<<"Exception thrown for displayElements"<<endl;
cout<<"Error number: "<< ex.getErrorCode() << endl;
cout<<ex.getMessage() << endl;
}
stmt->closeResultSet (rset);
conn->terminateStatement (stmt);
}
/**
* ·â×° OCCI executeQuery Ϊ C ·ç¸ñ½Ó¿Ú
*
* @param conn OCCI Êý¾Ý¿âÁ¬½Ó
* @param sql SQL ²éѯÓï¾ä
* @param outputColumn Êä³ö£ºÁÐÊý£¨Í¨¹ýÖ¸Õë·µ»Ø£©
* @param outputValueCount Êä³ö£º×ÜÊý¾ÝÏîÊýÁ¿£¨ÐÐÊý ¡Á ÁÐÊý£©
* @param outputValue Êä³ö£º¶þάÊý×é char[row][col]£¬Ðèµ÷ÓÃÕßÊÍ·Å
* @return 0=³É¹¦, -1=ʧ°Ü
*/
int executeQuery(
oracle::occi::Connection* conn,
const char* sql,
int* outputColumn,
int* outputValueCount,
char**** outputValue)
{
printf("DEBUG: Entering executeQuery function\n");
fflush(stdout);
// ³õʼ»¯Êä³ö²ÎÊý
*outputColumn = 0;
printf("DEBUG: Initialized outputColumn = 0\n");
fflush(stdout);
*outputValueCount = 0;
printf("DEBUG: Initialized outputValueCount = 0\n");
fflush(stdout);
*outputValue = nullptr;
printf("DEBUG: Set outputValue to nullptr\n");
fflush(stdout);
Statement* stmt = nullptr;
ResultSet* rset = nullptr;
vector<vector<string>> resultData;
try {
printf("DEBUG: Entering try block\n");
fflush(stdout);
printf("DEBUG: sql====%s\n", sql);
fflush(stdout);
// ´´½¨Óï¾ä
stmt = conn->createStatement(sql);
printf("DEBUG: Created statement from connection\n");
fflush(stdout);
// Ö´Ðвéѯ
rset = stmt->executeQuery();
printf("DEBUG: Executed query and got ResultSet\n");
fflush(stdout);
// ¡¾¹Ø¼üÐÞ¸´¡¿Ïȵ÷Óà next() ÔÙ»ñȡԪÊý¾Ý£¬·ÀÖ¹±ÀÀ£
bool hasData = rset->next();
printf("DEBUG: First rset->next() called for initialization, hasData = %s\n", hasData ? "true" : "false");
fflush(stdout);
// »ñÈ¡ÁÐÔªÊý¾Ý£¨±ØÐëÔÚ next() Ö®ºóµ÷ÓòŰ²È«£©
auto metaData = rset->getColumnListMetaData();
unsigned int numCols = 0;
if (!metaData.empty()) {
numCols = static_cast<unsigned int>(metaData.size());
printf("DEBUG: Got number of columns = %u\n", numCols);
fflush(stdout);
}
else {
printf("ERROR: Metadata is empty after next(), unable to get column count.\n");
fflush(stdout);
stmt->closeResultSet(rset);
conn->terminateStatement(stmt);
return -1;
}
fflush(stdout);
// Èç¹ûÓÐÊý¾Ý£¬±£´æµÚÒ»ÐÐ
if (hasData) {
vector<string> firstRow;
for (unsigned int i = 1; i <= numCols; ++i) {
printf("DEBUG: Processing column %u of first row\n", i);
fflush(stdout);
try {
//string val = rset->getString(i);
//printf("DEBUG: Retrieved value for column %u: '%s'\n", i, val.c_str());
//fflush(stdout);
//firstRow.push_back(val);
string val = safeGetString(rset, i);
printf("DEBUG: Retrieved value for column %u: '%s'\n", i, val.c_str());
firstRow.push_back(val);
printf("1111111111111111111111111\n");
}
catch (SQLException&) {
printf("DEBUG: Exception getting column %u, using 'NULL'\n", i);
fflush(stdout);
firstRow.push_back("NULL");
}
catch (exception& e) {
printf("exception=========%u\n", i);
printf("Exception caught on column %u: %s\n", i, e.what());
fflush(stdout);
}
}
printf("22222222222222222222\n");
resultData.push_back(firstRow);
printf("DEBUG: First row saved to resultData\n");
fflush(stdout);
}
// ¼ÌÐø¶ÁȡʣÓàÐÐ
unsigned int rowCount = static_cast<unsigned int>(resultData.size());
printf("DEBUG: Starting to fetch remaining rows\n");
fflush(stdout);
while (rset->next()) {
printf("DEBUG: Fetching next row\n");
fflush(stdout);
vector<string> row;
for (unsigned int i = 1; i <= numCols; ++i) {
try {
string val = safeGetString(rset,i);
row.push_back(val);
printf("DEBUG: Retrieved value for row %u, col %u: '%s'\n", rowCount, i, val.c_str());
fflush(stdout);
}
catch (SQLException&) {
row.push_back("NULL");
printf("DEBUG: NULL value at row %u, col %u\n", rowCount, i);
fflush(stdout);
}
}
resultData.push_back(row);
++rowCount;
printf("DEBUG: Completed row %u\n", rowCount);
fflush(stdout);
}
printf("DEBUG: Finished fetching all rows, total count = %u\n", rowCount);
fflush(stdout);
// ÉèÖÃÊä³ö²ÎÊý
*outputColumn = static_cast<int>(numCols);
*outputValueCount = static_cast<int>(rowCount);
printf("DEBUG: Set outputColumn = %d, outputValueCount = %d\n", *outputColumn, *outputValueCount);
fflush(stdout);
// ·ÖÅäÊä³öÄڴ棺char*** -> char**[] -> char*[] -> char[]
char*** rows = nullptr;
if (rowCount > 0) {
rows = new char** [rowCount]; // ÿÐÐÊÇÒ»¸ö char**
printf("DEBUG: Allocated %u row pointers\n", rowCount);
fflush(stdout);
for (unsigned int i = 0; i < rowCount; ++i) {
char** cols = new char* [numCols];
printf("DEBUG: Allocated %u column pointers for row %u\n", numCols, i);
fflush(stdout);
for (unsigned int j = 0; j < numCols; ++j) {
const string& s = resultData[i][j];
cols[j] = new char[s.length() + 1];
strcpy(cols[j], s.c_str());
printf("DEBUG: Copied '%s' to outputValue[%u][%u]\n", s.c_str(), i, j);
fflush(stdout);
}
rows[i] = cols;
}
}
else {
rows = nullptr; // ¿Õ½á¹û¼¯
}
*outputValue = rows;
printf("DEBUG: Assigned result to *outputValue\n");
fflush(stdout);
// ÇåÀí OCCI ×ÊÔ´
stmt->closeResultSet(rset);
printf("DEBUG: Closed ResultSet\n");
fflush(stdout);
conn->terminateStatement(stmt);
printf("DEBUG: Terminated Statement\n");
fflush(stdout);
printf("DEBUG: Query executed successfully, returning 0\n");
fflush(stdout);
return 0; // ³É¹¦
}
catch (SQLException& e) {
printf("DEBUG: SQLException caught\n");
fflush(stdout);
cerr << "SQL Error: " << e.getMessage() << endl;
cerr << "SQL: " << sql << endl;
// ÇåÀí×ÊÔ´
if (rset && stmt) {
try { stmt->closeResultSet(rset); }
catch (...) {}
}
if (stmt) {
try { conn->terminateStatement(stmt); }
catch (...) {}
}
printf("DEBUG: Returning -1 due to SQL error\n");
fflush(stdout);
return -1;
}
catch (bad_alloc& e) {
printf("DEBUG: bad_alloc exception caught: %s\n", e.what());
fflush(stdout);
cerr << "Memory allocation failed!" << endl;
// ÇåÀí×ÊÔ´
if (rset && stmt) {
try { stmt->closeResultSet(rset); }
catch (...) {}
}
if (stmt) {
try { conn->terminateStatement(stmt); }
catch (...) {}
}
printf("DEBUG: Returning -2 due to memory allocation failure\n");
fflush(stdout);
return -2;
}
catch (...) {
printf("DEBUG: Unknown exception caught\n");
fflush(stdout);
if (rset && stmt) {
try { stmt->closeResultSet(rset); }
catch (...) {}
}
if (stmt) {
try { conn->terminateStatement(stmt); }
catch (...) {}
}
printf("DEBUG: Returning -1 due to unknown error\n");
fflush(stdout);
return -1;
}
}
}; // end of class occidml
//int main (void)
//{
// string user = "scott";
// string passwd = "tiger";
// string db = "";
// try{
// cout << "occidml - Exhibiting simple insert, delete & update operations"
// << endl;
// occidml *demo = new occidml (user, passwd, db);
// cout << "Displaying all records before any operation" << endl;
// demo->displayAllRows ();
//
// cout << "Inserting a record into the table author_tab "
// << endl;
// demo->insertRow ();
//
// cout << "Displaying the records after insert " << endl;
// demo->displayAllRows ();
//
// cout << "Inserting a records into the table author_tab using dynamic bind"
// << endl;
// demo->insertBind (222, "ANAND");
//
// cout << "Displaying the records after insert using dynamic bind" << endl;
// demo->displayAllRows ();
//
// cout << "deleting a row with author_id as 222 from author_tab table" << endl;
// demo->deleteRow (222, "ANAND");
//
// cout << "updating a row with author_id as 444 from author_tab table" << endl;
// demo->updateRow (444, "ADAM");
//
// cout << "displaying all rows after all the operations" << endl;
// demo->displayAllRows ();
//
// cout << "inserting radio active element properties" << endl;
// demo->insertElement ("Uranium", 12.572, 238.0289 );
// demo->insertElement ("Plutonium", 12.12, 244.0642 );
// demo->insertElement ("Curium", 18.17, 247.0703 );
// demo->insertElement ("Thorium");
// demo->insertElement ("Radium", 41.337, 226.0254);
//
// cout << "displaying all radio active element properties" << endl;
// demo->displayElements ();
//
// delete (demo);
// }
// catch (SQLException ex){
// cout << ex.getMessage() << endl;
// }
// cout << "occidml - done" << endl;
//}