📄 otl1.htm
字号:
Step 3 SQLObject *pDb=new SQLSybase();
// Instantiate SQLObject object
Step 4 pDb->sqlLogin();
// Log into the database
Step 5 pDb->sqlExec("SELECT name, address FROM customer");
// execute the SQL command
Step 6 pDb->sqlBind(1,bindZSTRING,31,szName);
Step 7 pDb->sqlBind(2,bindZSTRING,31,szAddress);
// Binds the host variables to the column results
Step 8 while(pDb->sqlFetch() == TRUE)
{
cout << szName << " " << szAddress << "\n";
}
// Fetches the records from the data source
Step 9 pDb->sqlDisconnect();
// Disconnects from the data source
Step 10 delete pDb; // Deletes the object
</xmp>
<h4>The Same Sample Program in OTL streams</h4>
<p>
"As high as abstract and unified SQL stream interface":
</p>
<xmp>
Step 1 char szName[31];
Step 2 char szAddress[31];
Step 3 otl_stream s(20, // stream buffer size (in rows)
"SELECT name, address FROM customer",
// SELECT statement
db // connect object
;
Step 4,5,6,7
// no explicit binding, no explicit execution
Step 8 while(!s.eof())
{
s >> szName >> szAddress; // fetch one row
cout << szName << " " << szAddress << endl;
}
// Fetches the records from the data source
Step 9, 10
// Automatic destructor will do the job
</xmp>
<h4>The Same Sample Program in OTL lower code layer </h4>
<p>
"As low as the Oracle Call Interface interface":
</p>
<xmp>
Step 1 char szName[31];
Step 2 char szAddress[31];
Step 3 otl_select_cursor s(db); // db -- connect object
// Instantiate Cursor object
Step 4 // Everything is done in the constructor
Step 5 s.parse("SELECT name, address FROM customer");
// Parse the SQL command
Step 6 s.bind_cstring(1,szName,30);
Step 7 s.bind_cstring(2,sAddress,30);
// Binds the host variables to the column results
Step 8 while(s.next())
{
cout << szName << " " << szAddress << endl;
}
// Fetches the records from the data source
Step 9, 10
// Automatic constructor will do the job
</xmp>
<h4><a name="sec222">2.2.2. OTL vs. DBTools.h++ (by Rogue Wave)</h4>
<h4>Sample Program in DBTools.h++</h4>
<xmp>
// This example establishes a connection to a SYBASE database, creates
// a table on the server, and uses the reader to read back the values.
// The values are then stored on a Memory Table and accessed row by
// row. This example can run on both WINDOWS and SUN/SOLARIS or
// SUNOS.
//#define UNIX // To run examples on Unix SunOS/Solaris
#define WINDOWS // To run example on WINDOWS
#include <rw/db/db.h>
#include <rw/db/dbmgr.h>
#ifdef WINDOWS
#include <windows.h>
#endif
void write(const RWCString& w)
{
#ifdef WINDOWS
MessageBox(0,w.data(),"DBTOOLS_BOX",MB_OK);
#elif defined(UNIX)
cout << w.data() << endl;
#endif
}
void errorHandler(const RWDBStatus& s)
{
char buf[1040];
sprintf(buf,"Message: %s ",s.message().data());
write(RWCString(buf));
}
#ifdef WINDOWS
#pragma argsused
int PASCAL WinMain(HINSTANCE , HINSTANCE, LPSTR, int )
{
RWCString serverType("bdbsdld.dll");
#elif defined(UNIX)
int main()
{
RWCString serverType("SYBASE");
#endif
// Set the Error Handler
RWDBManager::setErrorHandler(errorHandler);
// Establish Connection
RWDBDatabase adb = RWDBManager::database(serverType,
"SYBASE100", // to the database.
"henri",
"meli12",
"SUPPORT");
if(!adb.isValid())
write("Hmmm !!! Cannot Connect. Exit...");
else {
RWDBConnection conn=adb.connection();
if(adb.table("TABLE1").exists())
adb.table("TABLE1").drop();
RWDBSchema mySchema;
mySchema.appendColumn("id_num",RWDBValue::Int);
mySchema.appendColumn("id_type", RWDBValue::String, 15);
mySchema.appendColumn("input_date", RWDBValue::DateTime);
mySchema.appendColumn("price", RWDBValue::Float);
adb.createTable("TABLE1",mySchema, conn);
RWDBTable tab=adb.table("TABLE1");
if(tab.exists())
write("Table 'TABLE1' successfully created.");
// Insert about 10 Values
int numberOfEntries=5;
char buffer[1040];
RWDBDateTime date;
float price=1.5f;
RWDBInserter ins = tab.inserter();
for(int i=0; i<numberOfEntries; i++)
{
sprintf(buffer,"Item%d",i);
date.addDays(1);
ins << i << RWCString(buffer) << date << << i*price;
ins.execute(conn);
}
// Select all of items
RWDBSelector sel = adb.selector();
sel << tab;
RWDBResult res = sel.execute(conn);
RWDBReader rdr=res.table().reader(conn);
RWDBMemTable memTab(rdr,numberOfEntries);
for(i=0;i<memTab.entries(); i++)
{
sprintf(buffer,"ROW[%d] ID_NUMBER %d ID_TYPE %s \n
INPUT_DATE %s INPUT_PRICE %f\n", i,
(memTab[i][0]).asInt(),
(memTab[i][1]).asString().data(),
(memTab[i][2]).asString().data(),
(memTab[i][3]).asFloat());
write(RWCString(buffer));
}
return 0;
}
return 0;
}
</xmp>
<h4>The Same Sample Program in OTL</h4>
<xmp>
// This example establishes a connection to an Oracle database, creates
// a table on the server, and reads the values back.
#include <stdio.h>
#include <iostream.h>
#include <otl.h>
otl_connect db; // connect object
void write(const char* w)
{
cout << w << endl; // Write a message
}
int main()
{
try{
db.rlogon("scott/tiger"); // connect to Oracle
otl_cursor::direct_exec
(
db,
"drop table TABLE1",
otl_exception::disabled // disable OTL exceptions
); // drop table
otl_cursor::direct_exec
(
db,
"create table TABLE1"
"( "
" id_num number(8),"
" id_type varchar2(15),"
" input_date date,"
" price number"
")"
); // create table
write("Table 'TABLE1' successfully created.");
// Insert about 10 Values
{
int numberOfEntries=5;
char buffer[1040];
int date=0;
float price=1.5f;
otl_stream ins(50, // buffer size (in rows)
"insert into TABLE1 values("
" :id_num<int>,"
" :id_type<char[64]>,"
" sysdate+:input_date<int>,"
" :price<float>"
")",
db // connect object
);
for(int i=0; i<numberOfEntries; i++){
sprintf(buffer,"Item%d",i);
++date;
ins << i << buffer << date << (float) i*price;
// insert one row into the table
}
}
// Select all of items
{
char buffer[1040];
int count=0;
int id_num;
char id_type[64];
char input_date[32];
float price;
otl_stream sel(10, // buffer size (in rows)
"select * TABLE1"
db // connect object
);
while(!sel.eof()){
sel >> id_num >> id_type >> input_date >> price;
// get one row
sprintf(buffer,
"ROW[%d] ID_NUMBER %d ID_TYPE %s \n"
"INPUT_DATE %s INPUT_PRICE %f\n",
++count,
id_num,
id_type,
input_date,
price
);
}
}
}
catch(otl_exception& p){ // intercept OTL exceptions
write(p.msg);
}
db.logoff(); // disconnect from Oracle
return 0;
}
</xmp>
<h2><a name="sec3">3. Library structure</h2>
<p>
OTL falls into two parts: template classes to create host variables
and arrays and non-template classes to provide programming interface
to the Oracle Call Interface.
</p>
<h3><a name="sec31">3.1. Host variable and array template classes</h3>
<p>
Two types of host objects are distinguished: scalar
variables and arrays. OTL has two generic template classes
(otl_variable and otl_array) from which the following
specialized classes are derived:
</p>
<ul>
<li><i><b>Numerical data types</b></i>
<ul>
<li>otl_double, otl_double_array
<li>otl_signed_char, otl_signed_char_array
<li>otl_short_int, otl_short_int_array
<li>otl_int, otl_int_array
<li>otl_long_int, otl_long_int_array
<li>otl_unsigned, otl_unsigned_array
</ul>
</ul>
<ul>
<li><i><b>String data types</b></i>
<ul>
<li>otl_ctring, otl_cstring_array
<li>otl_varchar2, otl_varchar2_array
<li>otl_long, otl_long_array
<li>otl_varchar, otl_varchar_array
<li>otl_varraw, otl_varraw_array
<li>otl_raw, otl_raw_array
<li>otl_char, otl_char_array
<li>otl_charz, otl_charz_array
</ul>
</ul>
<ul>
<li><i><b>Data types for Oracle LONG and LONG RAW columns</b></i>
<ul>
<li>otl_long_varchar
<li>otl_long_varraw
</ul>
</ul>
<ul>
<li><i><b>Oracle internal data types (DATE, ROWID, VARNUM and NUMBER)</b></i>
<ul>
<li>otl_date, otl_date_array
<li>otl_rowid, otl_rowid_array
<li>otl_varnum, otl_varnum_array;
<li>otl_number, otl_number_array
</ul>
</ul>
<p>
The otl_variable and otl_array classes define the following
kinds of buffers which are necessary for handling host
variables:
<ul>
<li>value buffer (data member <b>v</b>)
<li>indicator buffer (data member <b>ind</b>)
<li>returned length buffer (data member <b>rlen</b>)
<li>returned code buffer (data member <b>rcode</b>)
</ul>
</p>
<p>
These data members are defined to be public, so the user has
access to them and may freely assign and change their
values.
</p>
<p>
The otl_variable and otl_array classes have a common parent
(otl_generic_variable) which contains information about the buffer
addresses, dimensions and data type codes. When a host variable or
array is constructed from an instantiated template, constructors of
the corresponding template classes initialize the data members of the
otl_generic_variable class. otl_cursor has a couple of the bind
functions which have the second parameter of the otl_generic_variable
type. Any template instantiated variables or arrays may be substituted
as actual parameters into those bind finctions.
</p>
<h3><a name="sec100">Class otl_generic_variable</h3>
<xmp>
class otl_generic_variable{
public:
</xmp>
<ul>
<li>Default constructor
<xmp>
otl_generic_variable();
</xmp>
<li>Destructor
<xmp>
virtual ~otl_generic_variable();
</xmp>
<li>Assigning a name to the variable
<xmp>
void copy_name(const char* aname);
</xmp>
<li>Assigning a position (number) to the select list item (column)
<xmp>
void copy_pos(const int apos);
</xmp>
<li>For input variable/array
<br><br>
<ul>
<li>Set variable's value as NULL
<xmp>
virtual void set_null(int ndx=0);
</xmp>
<li>Set variable's buffer length
<xmp>
virtual void set_len(int len, int ndx=0);
</xmp>
<li>Set variable's value as NOT NULL
<xmp>
virtual void set_not_null(int ndx=0);
</xmp>
</ul>
<li>For output variable/array
<br><br>
<ul>
<li>Check if variable's value is NULL
<xmp>
virtual int is_null(int ndx=0);
</xmp>
<li>Check if variable's value has been fetched OK
<xmp>
virtual int is_success(int ndx=0);
</xmp>
<li>Check if variable's value is truncated
<xmp>
virtual int is_truncated(int ndx=0);
</xmp>
<li>Get pointer to variable's buffer
<xmp>
virtual void* val(int ndx=0);
</xmp>
</ul>
<li>Only for output arrays, defined in SELECT statement
<ul>
<br><br>
<li>Check if during fetch conversion error occurred
<xmp>
virtual int is_invalid_conversion(int ndx=0);
</xmp>
<li>Check if during fetch real overflow occurred
<xmp>
virtual int is_real_overflow(int ndx=0);
</xmp>
<li>Check if variable has unsupported data type
<xmp>
virtual int is_unsupported_datatype(int ndx=0);
</xmp>
</ul>
</ul>
</ul>
<xmp>
protected:
</xmp>
<ul>
<li>pointer to buffer
<xmp>
ub1* p_v;
</xmp>
<li>pointer to indicator variable/array
<xmp>
sb2* p_ind;
</xmp>
<li>pointer to column's returned length
<xmp>
ub2* p_rlen;
</xmp>
<li>poinetr column's returned code
<xmp>
ub2* p_rcode;
</xmp>
<li>external data type's code of the host variable/array
<xmp>
int ftype;
</xmp>
<li>array element/variable size
<xmp>
int elem_size;
</xmp>
<li>host array size (=1 in case of scalar host variable)
<xmp>
int array_size;
</xmp>
<li>variable name;
<xmp>
char* name;
</xmp>
<li>select list item position
<xmp>
int pos;
</xmp>
</ul>
<xmp>
};
</xmp>
<h3><a name="sec101">Class otl_variable</h3>
<p>
This is the OTL template variable class. It is the base class for
constructing specialized host variable classes.
</p>
<xmp>
template <class T, int atype>
class otl_variable: public otl_generic_variable{
public:
</xmp>
<ul>
<li>Default constructor
<xmp>
otl_variable();
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -