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