ORAC++© is a shared C++ class library developed for Oracle8i (Release 2) on
Linux (Red Hat 8.0).
It serves as an C++ interface to Oracle OCI package.
To use ORAC++, programs have to be compiled using standard GNU
C++ compiler and linked with ORAC++ library and Oracle client
shared library (created at Oracle build time).
This document describes basic features of ORAC++. For more
detailed description, please see the following documents (in Word
format): ORAC++ User Documentation, ORAC++ Programming Examples
and ORAC++ Additional Features.
ORAC++ provide a quick and easy way to write programs to
select, insert, update and delete records
from a table. It also works with joins, views, stored
procedures, functions and packages. ORAC++
can be regarded as an excellent tool for writing quick reports,
with its formatting capabilities.
Being closely connected to Oracle-specific SQL and SQL*Plus makes
it extremely easy for Oracle developer to write small ( by number
of code lines ) and efficient C++ programs.
All Oracle basic data types are supported including CLOB and
BLOB. ORAC++ makes also use of SQL set operators like union,
intersect, minus and outer-joins. To
improve SQL performance Oracle hints can also be
used.
A full reusability of created objects allows to minimize effort
needed to write even most complicated programs. Integrated
error checking allows programmer to identify any
problems without writing additional lines of code. ORAC++ library
also supports multithreaded processing.
To illustrate, how easy is to write program with ORAC++ let's
take a look at the following example of a SQL statement:
select prod_id, prod_desc, prod_price
from products
where prod_id = 100001;
Below is a full listing of corresponding C++ program using
ORAC++:
#include <orac_lib.h>
int main()
{
Connect c;
try {
Database d
= c.OpenDatabase("scott", "tiger");
Table tb =
d.GetTable("products");
Select sel(tb);
sel
<< tb["prod_id"]
// select
prod_id,
<< tb["prod_desc"]
// prod_desc,
<< tb["prod_price"];
// prod_price from products
sel
>> tb["prod_id"] == 100001;
// where prod_id
= 100001
while
(sel.Row()) {
sel << prod_id << prod_name
<< prod_price;
cout << prod_id << prod_name
<< prod_price << endl;
}
d.Close();
}
catch (OException&
e) {
cout
<< e << endl;
}
catch (...) {
cout
<< "Error ..." << endl;
}
return 0;
}
Let's assume now, that we want to write C++ program which
corresponds to a SQL statement:
select * from products
where prod_id = 100001;
Listing of the C++ program using default (Line) output is shown
below (code within try block):
Database
d = c.OpenDatabase("scott", "tiger");
Table t
= d.GetTable("products");
Select s(t);
// select
* from products
s >> t["prod_id"] ==
100001;
// where prod_id = 100001
while (s.Row())
cout
<< s;
// display Line
(default) formatted Select
The program (when run against test data) will produce output:
PROD_ID PROD_DESC
PROD_PRICE
PROD_TYPE
100001 BOOKSHELF
108.5
3
If we call AsRecord() function:
s.AsRecord()
while (s.Row())
cout
<< s;
all data will be displayed in the following way:
PROD_ID : 100001
PROD_DESC : BOOKSHELF
PROD_PRICE : 108.5
PROD_TYPE : 3
Data from the fetched row can be also loaded directly into output
variables:
Select s(t);
//
select * from products
s >> t["prod_id"] ==
100001;
// where prod_id = 100001
while (s.Row())
{
s
<< id << desc;
// load in a table columns
order
cout
<< "ID = " << id << endl;
cout
<< "DESC = " << desc << endl;
}
Let's consider now a SQL join statement:
select products.prod_desc,
products.prod_price,
orders.ord_id,
orders.ord_date,
orders.ord_qty,
product_types.type_desc
from products, orders, product_types
where products.prod_id =
orders.prod_id
and product_types.type_id =
products.prod_type
and products.prod_desc = BREAD
and orders.ord_qty = 20;
A corresponding C++ program using ORAC++ will look as follows
(code within try block is shown only):
Database d
= c.OpenDatabase("scott", "tiger");
Table tb
= d.GetTable("products");
Table tc
= d.GetTable("orders");
Table td
= d.GetTable("product_types");
Select sel(tb);
// create join of three tables
sel += tc;
sel += td;
sel <<
tb["prod_desc"] << tb["prod_price"]
<< tc["ord_id"] <<
tc["ord_date"]
<< tc["ord_qty"] <<
td["type_desc"];
sel >> tb["prod_id"]
== tc["prod_id"];
sel >> and_ >>
td["type_id"] == tb["prod_type"];
sel >> and_ >>
tb["prod_desc"] == "BREAD";
sel >> and_ >>
tc["ord_qty"] == 20;
sel.AsRecord();
// use
Record display
while(sel.Row())
cout
<< sel;
The program (using test data) will create output:
PROD_DESC : BREAD
PROD_PRICE : 1.35
ORD_ID : 20003214
ORD_DATE : 13-MAR-00
ORD_QTY : 20
TYPE_DESC : FOOD
Above program examples demontstrated use of Select class.
It is worth noting, that is possible to use formats on selected
and query columns. The format must be entered after column name
using convention : column('format') if numeric/date or
column('size') if varchar2.
tb["prod_id('000999')"]
//
column type number(n)
tb["prod_price('$99999.99')"]
// column type number(n,p)
tc["ord_date('DD/MM/YY
HH24:MI:SS')"]
// column type date
tb["prod_desc('15')"]
// set column size to 15
All Oracle defined formats are supported. Sometimes there is a
need to use a sub-queries within a program.
Example below, demonstrates use of SQL sub-query in a C++ program
using ORAC++ (only code within try block shown):
Database
d = c.OpenDatabase("scott", "tiger");
Table tb
= d.GetTable("product_types");
Table tc
= d.GetTable("products");
Select sel(tb);
sel << tb["type_id"]
<< tb["type_desc"];
Select sel1(tc);
sel1 << tc["prod_id"]
<< tc["prod_desc"] <<
tc["prod_type"];
sel1 >>
tc["prod_type"] == ":";
// (1) placeholder here
while(sel.Row()) {
sel
<< type_id << desc;
cout
<< " (outer)--- " << type_id <<
":" << desc << endl;
sel1
>> type_id;
// (2) substitute it by
type_id
while
(sel1.Row()) {
sel1 << id << name <<
proc_type;
cout << "
(inner)--- " << id << ":"
<< name <<
":" << proc_type << endl;
}
}
ORAC++ allow to simplify writing programs to insert, update
and delete records from the table. To insert rows
into the table all we have to write is (try block shown only)
Database
d = c.OpenDatabase("scott", "tiger");
Table t
= d.GetTable("products");
Insert ins(t);
ins << t["prod_id"]
<< t["prod_desc"] <<
t["prod_type"];
ins >> 100010 >> "TV
STAND" >> 2;
cout << ins.Row()
<< " rows inserted" << endl;
Array insert is also supported. Lets assume that we want to
insert an array of 10 records.
A corresponding program code is shown below:
#define ARR 10
int prod_id[ARR];
char *prod_desc[ARR];
int prod_type[ARR];
after populating arrays of data, following lines have to be
added:
ins << t["prod_id"]
<< t["prod_desc"] <<
t["prod_type"];
ins >> prod_id >>
prod_desc >> prod_type;
ins.Array(ARR);
cout << ins.Row()
<< " rows inserted" << endl;
number of rows inserted will be equal to ARR (upon successful
insertion).
A following program code shows that table update is
also very easy task when using ORAC++ ( only code within try
block is shown ):
Database
d = c.OpenDatabase("scott", "tiger");
Table t
= d.GetTable("products");
Update upd(t);
upd << t["prod_desc"]
<< t["prod_type"];
// updated columns
upd >> "PRINTER
STAND" >> 2;
// updated data
upd >> t["prod_id"]
== 100100;
// where prod_id = 100100
cout << upd.Row()
<< " rows updated" << endl;
The same simplicity exists in case of deleting records from
a table:
Database
d = c.OpenDatabase("scott", "tiger");
Table t
= d.GetTable("products");
Delete del(t);
// delete from products
del >>
t["prod_id"] == 100001;
// where prod_id = 100001
cout << del.Row()
<< " rows deleted" << endl;
Stored procedures and functions can also be easily accessed and
executed using ORAC++. Lets take look at the following Oracle
stored procedure:
create or replace procedure
p_get_prod_name (
p_id in number,
p_name out varchar2)
is
cursor c(pid in number) is
select prod_desc
from products
where prod_id = pid;
begin
open c(p_id);
fetch c into p_name;
if c%notfound then
p_name := not found;
end if;
close c;
end;
To access this stored procedure from C++ program using
ORAC++ we have to write just a few lines of code (only code
within try block is shown):
int id = 100001;
char *name = new char[30];
Connect
c;
Database d
= c.OpenDatabase("scott", "tiger");
Procedure p =
d.GetProcedure("p_get_prod_name");
p >> id >> name;
// load all
input/output arguments
p.Execute();
p << id << name;
// reload all variables
cout << "product id
:" << id << endl;
cout << "product desc
:" << name << endl;
Class Sql allows to process any user entered SQL statement.
Program below, shows how Sql class can be used to process select
and update statements. (only code within try block is shown).
int prod_id;
double price;
TStr id_str(10),
name_str(30), price_str(10);
Connect
c;
Database
d = c.OpenDatabase("scott", "tiger");
Sql st = d.GetSql("select * from
products where prod_id = :1");
st << id_str << name_str
<< price_str; // fetch into strings
st >> 100001; // bind data
while (st.Execute())
{
st << id_str
<< name_str << price_str;
cout << id_str
<< ":" << name_str << ":"
<< price_str << endl;
}
st = "update products"; // reload Sql object with new statement
st += "set prod_desc = :1";
st += "where prod_id = :2";
st >> "updated
description" >> 100001;
st.Execute();
st = "select * from
products"; // reload Sql object again
st << prod_id << name_str
<< price; // fetch into proper data
types
while (st.Execute())
{
st << prod_id
<< name_str << price;
cout << prod_id
<< ":" << name_str << ":"
<< price << endl;
}
In this brief document only basic features of ORAC++ library of
classes were presented.
For detailed description of all features and more programming
examples please refer to the following documents: ORAC++ User
Documentation, ORAC++ Programming Examples and
ORAC++ Additional Features.