Oracle C++ Call Interface
Oracle C++ Call Interface
Sr. Product
Manager
Oracle Corporation
Oracle C++ Call
Interface
A New API for High-
Performance Internet
Applications
Agenda
Survey
Customer Requirements
Meeting the Needs
Realizing the Benefits
Summary
Q&A
Agenda
Survey
Customer Requirements
Meeting the Needs
Realizing the Benefits
Summary
Q&A
Customer Requirements
Comprehensive Support
– Oracle Relational and Object-Relational
access
High performance and Scalable API
– Reduce round-trip access, minimize data
copying, caching, connection pooling, etc.
High Productivity
– Simple: hiding complexity
– Easy: familiar constructs
Agenda
Survey
Customer Requirements
Meeting the Needs
Realizing the Benefits
Summary
Q&A
Meeting the Needs
Comprehensive Support (OCI)
– Oracle Relational and Object-Relational
access
High performance and Scalable API (OCI)
– Reduce round-trip access, minimize data
copying, cacheing, connection pooling, etc.
High Productivity (C++/Java)
– Simple: hiding complexity
– Easy: familiar constructs
Oracle C++ Call Interface
Built on top of OCI
– Comprehensive Support
Oracle Relational and Object-Relational
access
– High performance and scalable API
Reduce round-trip access, minimize data
copying, cacheing, connection pooling, etc.
C++ API modeled after JDBC
– High Productivity (C++)
Simple: encapsulation
Easy: JDBC-like constructs
OCCI Functionalities
Associative Relational Access
– Basics
– Advanced Techniques
Objects Access
– Navigational
– Associative
Metadata Access
Agenda
Survey
Customer Requirements
Meeting the Needs
– Associative Relational Access
– Objects Access
– Metadata Access
Realizing the Benefits
Summary
Q&A
Using OCCI
setup and connection
executing SQL statements
using objects
– Navigational Interface
– Associative (SQL) Interface
OCCI Factory Hierarchy
Env
Create
Create
ConnPool Conn
Create
getMD
Create
getMD
Stmt MetaData
getResultSet
ResultSet
Environment Class
Allows multiple class instances
Manages memory and other resources
for OCCI objects
An Environment instance maps to an OCI
environment handle
Create/Terminate
Environment
Create an instance by calling the static method
Environment::createEnvironment(Mode mode=DEFAULT, ...)
– DEFAULT mode is neither thread-safe nor object
– Other parameters allow custom memory
management functions
Free an instance and its resources with the
static
Environment::terminateEnvironment (Environment *env)
Connection *conn;
Environment *env = Environment::createEnvironment();
conn = env->createConnection(“scott”, “tiger”);
…
env->terminateConnection(conn);
Environment::terminateEnvironment(env);
Executing SQL DML
Statement
public int executeUpdate(const string
&sql="");
Executes a non-query statement
– INSERT, UPDATE, DELETE, CREATE/ALTER,
etc.), or a stored procedure
– Returns the row count for INSERT, UPDATE,
DELETE
– Returns 0 for statements that return
nothing
executeUpdate() Example
Creating a Table
Statement *stmt = conn->createStatement();
stmt->executeUpdate(“
CREATE TABLE basket (
fruit VARCHAR2(20), quantity NUMBER)”);
SQL DML statement
stmt->executeUpdate(
“ INSERT INTO basket values (‘MANGO’, 3)”);
Executing Prepared
Statement
SQL DML statement with IN bind
variables
stmt->setSQL(“
INSERT INTO basket VALUES(:1, :2)”);
stmt->executeUpdate();
Executing Callable
Statements
Calling procedures stored on the database
server
int quantity;
stmt->setSQL("BEGIN countFruit(:1, :2); END:");
// specify the first (IN) parameter of procedure
stmt->setString(1, "Apples");
// specify the type and size of the second (OUT)
parameter
stmt->registerOutParam(2, Type::OCCIINT,
sizeof(quantity));
stmt->executeUpdate();
// get the value of the second (OUT) parameter
quantity = stmt->getInt(2);
Streamed Reads and
Writes
The OCCI supports streamed parameters for
prepared and callable statements
– Read/write binary or character data
– Writeable stream corresponds to IN bind
variable
– Readable stream corresponds to OUT bind
variable
– Bi-directional stream corresponds to IN/OUT
bind variable
An Example
char buffer[4096];
ResultSet *rs = stmt->executeQuery
("SELECT blobCol FROM tab1 WHERE col1 = 11");
ResultSet *rs = stmt->getResultSet ();
while (rs->next ()) {
unsigned int length = 0;
unsigned int size = 500;
Stream *stream = rs->getCharacterStream (2, 4000);
while (stream->status () == Stream::READY_FOR_READ)
{
length += stream->readBuffer (buffer +length,
size);
}
cout << "Read " << length << " bytes into the buffer"
<< endl;
}
Executing SQL Queries
public ResultSet * executeQuery(const string &sql="
")
Execute a SQL Select statement
– Should not be called for a non-query
statement
– Does not allow streamed parameters
Returns an ResultSet that contains the
data produced by the query
Executing SQL Queries
ResultSet *rs = stmt->executeQuery(
“SELECT quantity FROM basket
WHERE fruit = ‘ORANGE’ “);
– UNPREPARED
– PREPARED
– RESULT_SET_AVAILABLE
– UPDATE_COUNT_AVAILABLE
– NEEDS_STREAM_DATA
– STREAM_DATA_AVAILABLE
Committing a Transaction
All SQL DML statements are executed in
the context of a transaction
– Changes become permanent by
committing the transaction
– Undo changes by performing a rollback
– SQL COMMIT and ROLLBACK can be
executed with executeUpdate method
– Connection::commit() and
Connection::rollback() methods can also be
used
Connection Pooling
Problem
– Mid-tier mult-threaded applications need
multiple connections to the database
– Opening and closing connection each time
is very expensive
– Opening all the necessary connections
before hand is wasteful
Solution
– Maintain a pool of connections
– Allocate/release a connection for execution
– Connection Pool is dynamically
configurable
Connection Pooling
ConnectionPool* createConnectionPool(
const string &poolUserName, const string &poolPassword,
const string &connectString ="", unsigned int minConn =0,
unsigned int maxConn =1, unsigned int incrConn =1);
ADDRESS *addr;
addr = new (conn, “ADDRESS_TAB”)
ADDRESS(“CA”, “94002”);
Fetching an Object
Reference
Object Reference
– logical pointer to an object instance
– Ref<T>
Ref<T>::operator ->
– overloaded
– pins the object instance during the first
time
Client-side Object Cache
load
Pin
Network
Modifying an Object
void ADDRESS::setState(string new_state) {
state = new_state;
}
addr_ref->setState(“PA”);
Connection::commit
– commit the transaction
– flush all the dirty objects
Complex Object Retrieval
(COR)
Object-oriented application has a set of
graph- or tree-structured objects
COR prefetches multiple objects in one
network round trip to improve performance
– The desired root object is explicitly fetched
– The depth level is the minimum number of
references to be traversed from the root to an
object
– Constrained by available memory in the object
cache
Invoking COR
COR is invoked by setting attributes of
Ref<T> before de-referencing
– prefetch attributes of the specified type
name up to the the specified depth
Ref<T>::setPrefetch(const string &typeName,
unsigned int depth);
– prefetch all the attribute types up to the
specified depth
Ref<T>::setPrefetch(unsigned int depth);
Type Inheritance
Oracle9i provides SQL-99 standard
support of type inheritance
– Polymorphic method dispatch
– Polymorphic object substitutibility
OTT for Type Inheritance
Generates classes from inheritance
hierarchy
while (rs->next())
{
ADDRESS *addr_val = rs->getObject(1);
cout << “state : “ << addr_val->getState();
}
Insert a new object using
SQL
// create a transient instance
ADDRESS *addr_val = new ADDRESS(“NV”, “23567”);
stmt->execute();
Example :- (OTT code)
class PERSON : public PObject {
protected :
string name;
vector<Ref<ADDRESS> > addr_list;
…
}
void RegisterMappings(Environment *env) {
Map *map = env->getMap();
map->put(“SCOTT.ADDRESS”,
ADDRESS::readSQL, ADDRESS::writeSQL);
map->put(“SCOTT.PERSON”,
PERSON::readSQL, PERSON::writeSQL);
}
Example :- (user class
def. )
// ADDRESS, PERSON : OTT generated classes
class MyAddress : public ADDRESS {
public:
MyAddress(string state_i, string zip_i);
void displayInfo();
}
class MyPerson : public PERSON {
public:
MyPerson(string name, Ref<MyAddress>& addr);
void move(const Ref<MyAddress>& new_addr);
void displayInfo();
}
Example (user class
methods)
void MyAddress::displayInfo() {
cout << "STATE is" << state << endl;
cout << "ZIP is" << zip << endl;
}
void MyPerson::displayInfo() {
cout << "NAME is" << name << endl;
cout << "Address List: " << endl;
for (int i = 0; i < addr_list.size(); i++)
// operator [] on vector, operator -> on vector
element, REF
addr_list[i]->displayInfo();
}
Example (contd.)
void MyPerson::move(const Ref<MyAddress>&
new_addr)
{
addr_list.push_back(new_addr);
this->mark_modified(); // mark the object as dirty
}
Example (contd.)
int main() {
Environment *env =
Environment::createEnvironment();
Connection *conn = env->createConnection("scott",
"tiger");
/* Call the OTT generated function to register the
mappings */
RegisterMappings(env);
conn->closeStatement(stmt);
env->terminateConnection(conn);
Environment::terminateEnvironment(env);
return 0;
}
Agenda
Survey
Customer Requirements
Meeting the Needs
– Associative Relational Access
– Objects Access
– Metadata Access
Realizing the Benefits
Summary
Q&A
Metadata
MetaData type_md;