📄 otl2.htm
字号:
<li><a href="otl_it01.htm">otl_output_iterator</a></li>
<li><a href="otl_it02.htm">otl_input_iterator</a></li>
</ul>
<p>
These two iterator classes make it possible to combine the power of <a
href="http://www.metabyte.com/~fbp/stl/readings.html">generic
programming</a> and Oracle into compact, reliable, top performance and
easy-to-maintain C++ database applications.
</p>
<p>
It would be cool to develop a PL/SQL-to-C++ converter which would
use STL container classes (to efficiently implement PL/SQL tables) and
OTL to take advantage of straight OCI in order to efficiently
implement Oracle cursor handling. Also, converting interpreted code
into code compiled into native machine instructions is not such a bad
idea.
</p>
<h2><a name="sec31">3.1. Example </h2>
<h4>Source code</h4>
<pre>
<font color="#FF0000">#include <iostream.h></font>
<font color="#FF0000">#include <stdio.h></font>
<font color="#FF0000">#include <otl_iter.h></font>
<font color="#FF0000">#include <vector.h></font>
<font color="#FF0000">#include <hash_map.h></font>
<font color="#FF0000">#include <iterator.h></font>
<a href="#ref002">otl_connect</a> db; <i><font color="#804000">// connect object</font></i>
<i><font color="#804000">// row container class</font></i>
<font color="#0000A0">class</font> row{
<font color="#0000A0">public</font>:
<font color="#0000A0">int</font> f1;
<font color="#0000A0">char</font> f2[32];
<i><font color="#804000">// default constructor</font></i>
row(){f1=0; f2[0]=0;}
<i><font color="#804000">// destructor</font></i>
~row(){}
<i><font color="#804000">// copy constructor</font></i>
row(<font color="#0000A0">const</font> row& row)
{
f1=row.f1;
strcpy(f2,row.f2);
}
<i><font color="#804000">// assignment operator</font></i>
row& <font color="#0000A0">operator</font>=(<font color="#0000A0">const</font> row& row)
{
f1=row.f1;
strcpy(f2,row.f2);
<font color="#0000A0">return</font> *<font color="#0000A0">this</font>;
}
};
<i><font color="#804000">// redefined operator>> for reading row& from otl_stream</font></i>
<a href="#ref001">otl_stream</a>& <font color="#0000A0">operator</font>>>(<a href="#ref001">otl_stream</a>& s, row& row)
{
s<a href="#ref004">>></a>row.f1<a href="#ref004">>></a>row.f2;
<font color="#0000A0">return</font> s;
}
<i><font color="#804000">// redefined operator<< for writing row& into otl_stream</font></i>
<a href="#ref001">otl_stream</a>& <font color="#0000A0">operator</font><<(<a href="#ref001">otl_stream</a>& s, <font color="#0000A0">const</font> row& row)
{
s<a href="#ref003"><<</a>row.f1<a href="#ref003"><<</a>row.f2;
<font color="#0000A0">return</font> s;
}
<i><font color="#804000">// redefined operator<< writing row& into ostream</font></i>
ostream& <font color="#0000A0">operator</font><<(ostream& s, <font color="#0000A0">const</font> row& row)
{
s<<<font color="#008080">"f1="</font><<row.f1<<<font color="#008080">", f2="</font><<row.f2;
<font color="#0000A0">return</font> s;
}
<a name="ref501"></a><h4><font color="#0000A0">void</font> insert()</h4>
<i><font color="#804000">// insert rows into table</font></i>
{
<a href="#ref001">otl_stream</a> o(50, <i><font color="#804000">// buffer size</font></i>
<font color="#008080">"insert into test_tab values(:f1<int>,:f2<char[31]>)"</font>,
<i><font color="#804000">// SQL statement</font></i>
db // connect object
);
row r; <i><font color="#804000">// single row buffer</font></i>
vector<row> vo; <i><font color="#804000">// vector of rows</font></i>
<i><font color="#804000">// populate the vector</font></i>
<font color="#0000A0">for</font>(<font color="#0000A0">int</font> i=1;i<=100;++i){
r.f1=i;
sprintf(r.f2,<font color="#008080">"Name%d"</font>,i);
vo.push_back(r);
}
cout<<<font color="#008080">"vo.size="</font><<vo.size()<<endl;
<i><font color="#804000">// insert vector into table</font></i>
copy(vo.begin(),
vo.end(),
<a href="otl_it01.htm#">otl_output_iterator</a><row>(o)
);
}
<a name="ref502"></a><h4><font color="#0000A0">void</font> select()</h4>
{
<a href="#ref001">otl_stream</a> i(50, <i><font color="#804000">// buffer size</font></i>
<font color="#008080">"select * from test_tab where f1>=:f<int> and f1<=:f*2"</font>,
<i><font color="#804000">// SELECT statement</font></i>
db <i><font color="#804000">// connect object</font></i>
);
<i><font color="#804000">// create select stream</font></i>
vector<int> inp_par; <i><font color="#804000">// vector of 1 element to demonstrate OTL iterators</font></i>
vector<row> v; <i><font color="#804000">// vector of rows</font></i>
<i><font color="#804000">// assigning :f = 8</font></i>
<i><font color="#804000">// this example demonstrates how both input</font></i>
<i><font color="#804000">// and output iterators may be attached to the</font></i>
<i><font color="#804000">// same otl_stream</font></i>
inp_par.push_back(8); <i><font color="#804000">// populate the vector with one element</font></i>
cout<<<font color="#008080">"inp_par.size="</font><<inp_par.size()<<endl;
<i><font color="#804000">// copy the vector into the input variable of the select statement</font></i>
copy(inp_par.begin(),inp_par.end(),<a href="otl_it01.htm#">otl_output_iterator</a><int>(i));
<i><font color="#804000"> // SELECT automatically executes when all input variables are</font></i>
<i><font color="#804000"> // assigned. First portion of out rows is fetched to the buffer</font></i>
<i><font color="#804000">// copy all rows to be fetched into the vector</font></i>
copy(<a href="otl_it02.htm#">otl_input_iterator</a><row,ptrdiff_t>(i),
<a href="otl_it02.htm#">otl_input_iterator</a><row,ptrdiff_t>(),
back_inserter(v));
cout<<<font color="#008080">"Size="</font><<v.size()<<endl;
<i><font color="#804000">// send the vector to cout</font></i>
copy(v.begin(), v.end(), ostream_iterator<row>(cout, <font color="#008080">"\n"</font>));
<i><font color="#804000">// clean up the vector</font></i>
v.erase(v.begin(),v.end());
<i><font color="#804000">// OTL traditional technique</font></i>
i<a href="#ref003"><<</a>4; <i><font color="#804000">// assigning :f = 4</font></i>
<i><font color="#804000"> // SELECT automatically executes when all input variables are</font></i>
<i><font color="#804000"> // assigned. First portion of out rows is fetched to the buffer</font></i>
<i><font color="#804000">// copy all rows to be fetched to the vector</font></i>
copy(otl_input_iterator<row,ptrdiff_t>(i),
otl_input_iterator<row,ptrdiff_t>(),
back_inserter(v));
cout<<<font color="#008080">"Size="</font><<v.size()<<endl;
<i><font color="#804000">// send the vector to cout</font></i>
copy(v.begin(), v.end(), ostream_iterator<row>(cout, <font color="#008080">"\n"</font>));
}
<h4><font color="#0000A0">int</font> main()</h4>
{
<a href="#ref006">otl_connect::otl_initialize()</a>; <i><font color="#804000">// initialize OCI environment</font></i>
<font color="#0000A0">try</font>{
db.<a href="#ref007">rlogon</a>(<font color="#008080">"scott/tiger"</font>); <i><font color="#804000">// connect to Oracle</font></i>
<a href="#sec24">otl_cursor::direct_exec</a>
(db,
<font color="#008080">"drop table test_tab"</font>,
otl_exception::disabled <i><font color="#804000">// disable OTL exceptions</font></i>
); <i><font color="#804000">// drop table</font></i>
<a href="#sec24">otl_cursor::direct_exec</a>
(db,
<font color="#008080">"create table test_tab(f1 number, f2 varchar2(30))"</font>
); <i><font color="#804000">// create table</font></i>
<a href="#ref501">insert()</a>; <i><font color="#804000">// insert records into table</font></i>
<a href="#ref502">select()</a>; <i><font color="#804000">// select records from table</font></i>
}
<font color="#0000A0">catch</font>(<a href="#sec23">otl_exception</a>& p){ <i><font color="#804000">// intercept OTL exceptions</font></i>
cerr<<<a href="#sec23">p.msg</a><<endl; <i><font color="#804000">// print out error message</font></i>
<font color="#0000A0">if</font>(p.stm_text)
cerr<<<a href="#sec23">p.stm_text</a><<endl; <i><font color="#804000">// print out SQL statement associated with the error</font></i>
}
db.<a href="#ref009">logoff(</a>); <i><font color="#804000">// disconnect from Oracle</font></i>
<font color="#0000A0">return</font> 0;
}
</pre>
<h4>Output</h4>
<xmp>
vo.size=100
inp_par.size=1
Size=9
f1=8, f2=Name8
f1=9, f2=Name9
f1=10, f2=Name10
f1=11, f2=Name11
f1=12, f2=Name12
f1=13, f2=Name13
f1=14, f2=Name14
f1=15, f2=Name15
f1=16, f2=Name16
Size=5
f1=4, f2=Name4
f1=5, f2=Name5
f1=6, f2=Name6
f1=7, f2=Name7
f1=8, f2=Name8
</xmp>
<h1><a name="app_a">Appendix A. How to download the source code</h1>
<P>In order to obtain a copy of the OTL header files, send email to <A HREF="mailto:skuchin@aceweb.com">skuchin@aceweb.com</A>,
<A HREF="mailto:skuchin@gmail.com">skuchin@gmail.comgmail</P>
<P>Here is the list of the OTL header files:</P>
<UL>
<LI><I><FONT COLOR="#804040">otl7.h</FONT></I> -- the OTL source code for
Oracle 7. </LI>
<LI><I><FONT COLOR="#804040">otl8.h</FONT></I> -- the OTL source code for
Oracle 8. Save the file as otl.h. </LI>
<LI><I><FONT COLOR="#804040">otl_iter.h</FONT></I> -- STL-compliant iterators
for otl_stream </LI>
</UL>
<p>
Besides, you need to have standard OCI header files and object
libraries. The location of the files and libraries is specific to the
operating system. See the Oracle manuals for more details.
</p>
<p>
The OCI7 standard header files are as follows:
<ul>
<li>ociapr.h</li>
<li>ocidfn.h</li>
<li>ocikpr.h</li>
<li>oratypes.h</li>
</ul>
</p>
<p>
The OCI8 standard header files are as follows:
<ul>
<li>nzerror.h</li>
<li>nzt.h</li>
<li>oci.h</li>
<li>ociap.h</li>
<li>ociapr.h</li>
<li>ocidef.h</li>
<li>ocidem.h</li>
<li>ocidfn.h</li>
<li>ociextp.h</li>
<li>ocikp.h</li>
<li>ocikpr.h</li>
<li>oratypes.h</li>
<li>ori.h</li>
<li>orid.h</li>
<li>orl.h</li>
<li>oro.h</li>
<li>ort.h</li>
<li>tnsapi.h</li>
</ul>
</p>
<p>
If you want to use the <a href="#sec3">STL-compliant iterators</a>
then you are going to need the <a
href="http://www.metabyte.com/~fbp/stl/">Standard Template Library</a>
(adaption by <a href="mailto:fbp@metabyte.com">Boris Fomitchev</a>) or <a
href="http://www.sgi.com/Technology/STL/">the original STL SGI, version 3.11</a>.
</p>
<h1><a name="app_b">Appendix B. OTL exception list</h2>
<p>
The following <a href="#sec23">OTL exceptions</a> can be raised by the
OTL functions:
</p>
<dl>
<dt><b>Code=32000</b>: Incompatible data types in stream operation
<dd><br>
<b>Cause</b>: The data type of a variable used in the current
stream operation is not compatible with the declared stream
format.
<br><br>
<b>Action</b>: Check placeholders and their data types
declaration.
<dt><br><b>Code=32001</b>: Row must be full for flushing output stream
<dd><br>
<b>Cause</b>: Stream is open for output and has a format of
output rows. An output row is a tuple of all output
variables put together. The current output row is not
filled yet but the flush function is invoked. The stream
buffer cannot be flushed until the current row of the
output buffer is full.
<br><br>
<b>Action</b>: Fill the row first, then flush the stream.
<dt><br><b>Code=32004</b>: Not all input variables have been initialized
<dd><br>
<b>Cause</b>: stream has input variables but not all
the variables have been initialized. An attempt to read
data from the stream was made.
<br><br>
<b>Action</b>: Assign all the input variables first.
<dt><br><b>Code=32004</b>: No input variables have been defined in SQL statement
<dd><br>
<b>Cause</b>: Stream has no input variables. An attempt
to write objects to the stream via one of the << operators
was made.
<br><br>
<b>Action</b>: Do not call the << operators for streams
which have no input variables defined.
</dl>
</body>
</html>
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -