Accessing stored procedures in Oracle from C++

Requirements for this howto:

  1. Oracle 10 R2 or Oracle XE database
  2. scott/tiger account enabled
  3. stdlibc++5 installed
  4. ORACLE_HOME defined in environment

First you need to create the PL/SQL package implementing our small calculator.
To do this download this SQL script and run the following command: sqlplus /nolog @[path/]demo.sql

demo.sql

connect scott/tiger@xe;

create or replace package calculator AS
  function ad (a in NUMBER, b in NUMBER) RETURN NUMBER;
  function sub (a in NUMBER, b in NUMBER) RETURN NUMBER;
  function mul (a in NUMBER, b in NUMBER) RETURN NUMBER;
  function div (a in NUMBER, b in NUMBER) RETURN NUMBER;
end;
/

create or replace package BODY calculator AS

    function ad (a in NUMBER, b in NUMBER) RETURN NUMBER is
    begin
        return a + b;
    end;
      
    function sub (a in NUMBER, b in NUMBER) RETURN NUMBER is
    begin
        return a - b;
    end;        

    function mul (a in NUMBER, b in NUMBER) RETURN NUMBER is
    begin
        return a * b;
    end;

    function div (a in NUMBER, b in NUMBER) RETURN NUMBER is
    begin
        return a / b;
    end;

end calculator;
/
quit;

The next step is to download the C++ source and the Makefile.
To compile the code enter this command: make

Makefile

all: demo.cc
	g++ -D_LARGEFILE64_SOURCE -D_FILE_OFFSET_BITS=64 -g -I${ORACLE_HOME}/rdbms/public
-I${ORACLE_HOME}/rdbms/demo -L${ORACLE_HOME}/lib -lclntsh -locci /usr/lib/libstdc++.so.5 -o demo demo.cc clean: rm -f demo demo.o

C++ source

#include <cstring>
#include <cstdlib>
#include <iostream>
#include <sstream>
#include <stdexcept>
#include <occi.h>

using namespace oracle::occi;
using namespace std;

class Calculator {
    public:
        Calculator(string uid, string pwd, string db);
        double add(double a, double b);
        double sub(double a, double b);
        double mul(double a, double b);
        double div(double a, double b);
        ~Calculator();
    private:
        Environment*    env;
        Connection*     con;

};

Calculator::Calculator(string uid, string pwd, string db) {
    this->env = Environment::createEnvironment (Environment::DEFAULT);
    this->con = env->createConnection (uid, pwd, db);
}

double Calculator::add(double a, double b) {
    Statement* stmt;
    ResultSet* rset;
    char sql[100];

    sprintf(sql, "select calculator.ad(%2.2f,%2.2f) from dual", a, b);
    stmt = this->con->createStatement(sql);
    rset = stmt->executeQuery();

    while (rset->next()) {
        cout << "Result: " << rset->getDouble(1) << endl;
    }
    stmt->closeResultSet(rset);
    this->con->terminateStatement(stmt);
}

double Calculator::sub(double a, double b) {
    Statement* stmt;
    ResultSet* rset;
    char sql[100];

    sprintf(sql, "select calculator.sub(%2.2f,%2.2f) from dual", a, b);
    stmt = this->con->createStatement(sql);
    rset = stmt->executeQuery();

    while (rset->next()) {
        cout << "Result: " << rset->getDouble(1) << endl;
    }
    stmt->closeResultSet(rset);
    this->con->terminateStatement(stmt);
}

double Calculator::mul(double a, double b) {
    Statement* stmt;
    ResultSet* rset;
    char sql[100];

    sprintf(sql, "select calculator.mul(%2.2f,%2.2f) from dual", a, b);
    stmt = this->con->createStatement(sql);
    rset = stmt->executeQuery();

    while (rset->next()) {
        cout << "Result: " << rset->getDouble(1) << endl;
    }
    stmt->closeResultSet(rset);
    this->con->terminateStatement(stmt);
}

double Calculator::div(double a, double b) {
    Statement* stmt;
    ResultSet* rset;
    char sql[100];

    sprintf(sql, "select calculator.div(%2.2f,%2.2f) from dual", a, b);
    stmt = this->con->createStatement(sql);
    rset = stmt->executeQuery();

    while (rset->next()) {
        cout << "Result: " << rset->getDouble(1) << endl;
    }
    stmt->closeResultSet(rset);
    this->con->terminateStatement(stmt);
}

Calculator::~Calculator() {
    if (this->env) {
        if (this->con)
            this->env->terminateConnection(this->con);
        Environment::terminateEnvironment(this->env);
    }
}

int main(int argc, char* argv[]) {
    double x, y;
    string function;

    if (argc != 4) {
        cout << "Usage: " << argv[0] << " <uid> <pwd> <db>" << endl;
        return EXIT_FAILURE;
    }
    try {
        Calculator* calc = new Calculator(argv[1], argv[2], argv[3]);
        while(true) {
            cout << "Enter operation [add, sub, mul, div, STOP]: ";
            cin >> function;
            if (function == "STOP")
                break;
            cout << "Enter two floating-point values: ";
            cin >> x;
            cin >> y;
            if (function == "add")
                calc->add(x,y);
            else if (function == "sub")
                calc->sub(x,y);
            else if (function == "mul")
                calc->mul(x,y);
            else if (function == "div")
                calc->div(x,y);
            else
                cout << function << 
                    ": not in [add, sub, mul, div, STOP]" << endl;
        }
    }
    catch (SQLException& ex) {
        cerr << ex.getMessage();
        return EXIT_FAILURE;
    }
    catch (...) {
        cerr << "Unhandled exception occured" << endl;
        return EXIT_FAILURE;
    }
    return EXIT_SUCCESS;
}