OTL support v16
Oracle Template Library (OTL) is a C++ library for database access. It consists of a single header file. To know more about OTL, see the Oracle, Odbc and DB2-CLI Template Library Programmer's Guide.
OTL certification
The EDB OCL Connector, version 13.1.4.2, is certified with OTL 4.0. To use OTL-supported data types and for other OTL-specific behavior, define the OTL environment variable (the value isn't important) on the shell before running an OTL-based app. For example, you can export OTL=TRUE
for conditional execution of scenarios that are related to OTL.
EDB OCL Connector is certified with the following OTL features:
- Connect, disconnect, commit, and roll back using
otl_connect
. - Constant SQL statements using the static function
otl_cursor::direct_exec
. (A SQL statement is constant if it doesn't have any bind variables.) It includes most DDL statements likeCREATE TABLE
andCREATE PROCEDURE/FUNCTION
. - SQL statements with bind variable using
otl_stream class
. It includes most DML statements likeSELECT
,UPDATE
,DELETE
,INSERT
, andPROCEDURE/FUNCTION
calls. - Date/Time data types using
otl_datetime
. - Raw/Long Raw data types using
otl_long_string
. - Ref cursors using
otl_refcur_stream
.
Connect and log in
This example initializes OCL and connects to a database using a tnsnames.ora
-based connection string:
otl_connect db; otl_connect::otl_initialize(); db.rlogon("enterprisedb/edb@EDBX"); if(db.connected) cout<<"Connected to Database"<<endl;
CREATE TABLE, INSERT, and SELECT
This example uses otl_cursor::direct_exec
to create a table and then insert a row in the table. You can then use otl_stream
to retrieve the inserted row.
char* createstmt = "create table testtable(c1 VARCHAR2(15), c2 DATE)"; char* insertstmt = "insert into testtable values('test_data123', " "TO_DATE('2005-12-31 23:59:59','YYYY-MM-DD HH24:MI:SS'))"; char* selectstmt = "select c1, c2 from testtable"; otl_cursor::direct_exec(db, createstmt); // create table db.commit(); otl_cursor::direct_exec(db, insertstmt); // Insert data. char strData[100]; otl_datetime dtData; otl_stream otlCur(50, sqlstmnt, db); while (!otlCur.eof()) { otlCur >> strData >> dtData; cout << "Retrieved Value: " << data << endl; cout << "Retrieved Value: " << data.month << "/" << data.day << "/" << data.year << " " << data.hour << ":" << data.minute << ":" << data.second << endl; }
UPDATE
This example uses bind parameters in an UPDATE
statement:
char* updatestmt = "UPDATE testtable SET c1=:c1<char[49]> " "WHERE c1=:c2<char[49]>"; char whereValue[50] = "test_data123"; char data[50] = "otl test"; otl_stream otlCur(80, updatestmt, db); otlCur.set_commit(0); otlCur << data << whereValue;
Stored procedure
This example creates a stored procedure using otl_cursor::direct_exec
and then calls it using otl_stream
:
otl_cursor::direct_exec( db, "CREATE OR REPLACE PROCEDURE my_procOneIntOut " " (A IN NUMBER, B OUT NUMBER)" "IS " "BEGIN " " B := A;" "END;"); otl_stream otlCur( 1, "begin my_procOneIntOut(:A<int,in>, :B<int,out>);end;", db); otlCur.set_commit(0); int a = 10; otlCur << a; int b; otlCur >> b; cout << "B: " << b << endl;
Function
This example creates a function using otl_cursor::direct_exec
and then calls it using otl_stream
:
Note
This example is using the emp
table in the edb
sample database.
otl_cursor::direct_exec( db, "CREATE OR REPLACE FUNCTION get_no_int(e_name character " "varying(10)) " "RETURNS int AS $$ " "DECLARE retval int; " "BEGIN " "SELECT empno FROM emp WHERE ename = e_name INTO retval; " "RETURN retval; " "END; " "$$ LANGUAGE plpgsql;"); char ename[50] = "SCOTT"; otl_stream otlCur( 1, "begin " " :rc<int,out> := get_no_int(:c1<char[11],in>);" "end;", db); otlCur << ename; int eno; otlCur >> eno; cout << "Retrieved Value: " << eno << endl;
REF CURSOR
This example creates a package with a procedure that returns three ref cursors as OUT
parameters and then calls it.
Note
This example is using the emp
table in the edb
sample database.
otl_cursor::direct_exec( db, "CREATE OR REPLACE PACKAGE ref_test IS TYPE p_cursor IS REF CURSOR; PROCEDURE getdata(empc OUT p_cursor, salc OUT p_cursor, comc OUT p_cursor); END ref_test; " ); otl_cursor::direct_exec( db, "CREATE OR REPLACE PACKAGE BODY ref_test \ IS \ PROCEDURE getdata(empc OUT p_cursor, salc OUT p_cursor, comc OUT p_cursor) IS \ BEGIN \ open empc for select empno, ename from EMP; \ open salc for select ename, sal from EMP; \ open comc for select ename, comm from EMP; \ END; \ END ref_test;"); otl_stream otlCur(1, "BEGIN \ ref_test.getdata(:cur1<refcur,out[50]>, :cur2<refcur,out[50]>, :cur3<refcur,out[50]>); \ END;", db); otlCur.set_commit(0); otl_refcur_stream s1; // reference cursor streams for reading rows. otl_refcur_stream s2; // reference cursor streams for reading rows. otl_refcur_stream s3; // reference cursor streams for reading rows. otlCur >> s1; otlCur >> s2; otlCur >> s3; int e_no; char name[11]; double sal; double comm; cout << "=====> Reading :cur1..." << endl; while (!s1.eof()) { // while not end-of-data s1 >> e_no >> name; cout << "e_no=" << e_no << "\tname: " << name << endl; } cout << "=====> Reading :cur2..." << endl; while (!s2.eof()) { // while not end-of-data s2 >> name >> sal; cout << "name=" << name << "\tsalary: " << sal << endl; } cout << "=====> Reading :cur3..." << endl; while (!s3.eof()) { // while not end-of-data s3 >> name >> comm; cout << "name=" << name << "\tcommission: " << comm << endl; } s1.close(); s2.close(); s3.close();