1<?xml version="1.0" encoding="UTF-8"?>
2<section id="oracle"><title>&oracle-link; Interface</title>
3<para>
4The &oracle-link; module allows a &clisp; program to act as client to an
5&oracle-link; database server.  The module includes full
6SQL support, transactions (including auto-commit), support for most
7&oracle-link; data types (<type>LONG</type>, <type>BLOB</type>,
8<type>CLOB</type>, <type>RAW</type>, etc.), automatic conversion
9between &oracle-link; and &cl; data types, database connection caching and
10retry, concurrent connections to multiple databases, proper handling
11of &oracle-link; errors, and more.</para>
12<para>The module can be used to build sophisticated &oracle-link; database
13applications in &cl;.</para>
14<simpara>When this module is present, &features-my; contains the
15 symbol <constant>:ORACLE</constant>.</simpara>
16
17<section id="ora-functionality"><title>Functions and Macros in
18  package <quote role="package">ORACLE</quote></title>
19<para>Access to &oracle-link; is via these functions and macros in
20package <quote role="package">ORACLE</quote>.
21When any &oracle-link; function fails, the general Lisp function
22&error; is called, with the condition string set to
23include the &oracle-link; error number, the &oracle-link; message text,
24and other context of the error (e.g., the text and parse location of a
25SQL query).</para>
26
27<!-- List of functions an macros -->
28<variablelist>
29
30		<!-- CONNECT -->
31
32<varlistentry id="ora-connect"><term><code>(ORACLE:CONNECT
33&user-r; &pass-r;
34<replaceable>server</replaceable>
35&optional-amp;
36<replaceable>schema</replaceable>
37<replaceable>auto-commit</replaceable>
38<replaceable>prefetch-buffer-bytes</replaceable>
39<replaceable>long-len</replaceable>
40<replaceable>truncate-ok</replaceable>)</code></term>
41<listitem>
42<simpara>
43
44Connect to an &oracle-link; database.  All subsequent operations will affect
45this database until the next call to &ora-connect;.  A
46single program can access different &oracle-link; schemas concurrently by
47repeated calls to &ora-connect;.  Database connections
48are cached and re-used: if you call &ora-connect; again
49with the same &user-r;,
50<replaceable>schema</replaceable>, and
51<replaceable>server</replaceable>, the previous &oracle-link; connection will
52be re-used.  &ora-connect; may not be called inside
53<function>WITH-TRANSACTION</function>.
54
55Returns: &t; if a cached connection was re-used, &nil; if a new
56connection was created (and cached).
57
58The meaning of the arguments is as follows:
59</simpara>
60<variablelist><title>Arguments for &ora-connect;</title>
61<varlistentry><term>&user-r;</term>
62 <listitem><simpara>&oracle-link; user ID</simpara></listitem></varlistentry>
63<varlistentry><term>&pass-r;</term>
64 <listitem><simpara>Password for user, or &nil; if
65   &user-r; has no password (!).
66</simpara></listitem></varlistentry>
67<varlistentry><term><replaceable>server</replaceable></term>
68 <listitem><simpara>&oracle-link; server ID (SID).
69</simpara></listitem></varlistentry>
70<varlistentry><term><replaceable>schema</replaceable></term>
71 <listitem><simpara>&oracle-link; default schema (default: &nil;).
72   If &nil;, same as user.  This allows you to log on with one user's
73   id/password but see the database as if you were some other user.
74</simpara></listitem></varlistentry>
75<varlistentry><term><replaceable>auto-commit</replaceable></term>
76 <listitem><simpara>Flag: whether to commit after every operation
77   (default: &t;). Set this to &nil; if you intend to do transactions
78   and call <function>COMMIT</function> explicitly.  However,
79   <function>WITH-TRANSACTION</function> is probably easier.
80</simpara></listitem></varlistentry>
81<varlistentry><term><replaceable>prefetch-buffer-bytes</replaceable></term>
82 <listitem><simpara>Number of bytes to cache from SQL SELECT fetches
83   (default: 64 Kbytes) If you are very short of memory, or have a slow
84   connection to &oracle-link;, you can reduce this to 10k or so.
85   Alternatively, if you have a fast connection to &oracle-link; and
86   regularly do large queries, you can increase throughput by increasing
87   this value.</simpara></listitem></varlistentry>
88
89<varlistentry><term><replaceable>long-len</replaceable></term>
90 <listitem><simpara>Number of bytes to fetch for "long" (LONG, [BC]LOB)
91   types.  Long data that exceeds this size will raise an error, or be
92   truncated depending on the value of <replaceable>truncate-ok</replaceable>
93   (below).  Setting <replaceable>long-len</replaceable> to zero and
94   <replaceable>truncate-ok</replaceable> to &nil; will disable long
95   fetching entirely.  If <replaceable>long-len</replaceable> is &nil;
96   or negative, defaults to 500k bytes.</simpara></listitem></varlistentry>
97
98<varlistentry><term><replaceable>truncate-ok</replaceable></term>
99 <listitem><simpara>Flag: if set, allow truncation of LONG columns to
100   <replaceable>long-len</replaceable> bytes on fetch; otherwise, fetches
101   of LONG columns exceeding <replaceable>long-len</replaceable> bytes
102   will raise an error.  Default: &nil;.</simpara></listitem></varlistentry>
103</variablelist></listitem></varlistentry>
104
105		<!-- DISCONNECT -->
106
107<varlistentry id="ora-disconnect"><term><code>(ORACLE:DISCONNECT)</code></term>
108<listitem>
109<simpara>
110Disconnect from the database currently connected.  No more calls can
111be made until &ora-connect; is called again.  The
112connection is closed and removed from the connection cache.  Does
113nothing if there is no connection.  <function>DISCONNECT</function>
114may not be called inside <function>WITH-TRANSACTION</function>.
115Returns &nil;.
116</simpara></listitem></varlistentry>
117
118
119		<!-- RUN-SQL -->
120
121<varlistentry id="ora-run-sql"><term><code>(ORACLE:RUN-SQL
122<replaceable>sql</replaceable>
123&optional-amp;
124<replaceable>params</replaceable>
125<replaceable>is-select</replaceable>)</code></term>
126<listitem>
127<simpara>Execute a SQL statement.  Must be &ora-connect;ed
128to a database.  Returns the number of rows affected by the SQL operation,
129for non-SELECT statements, zero for SELECT statements.  For
130destructive database operations (INSERT, UPDATE, DELETE), the results
131are committed to the database immediately if
132<replaceable>auto-commit</replaceable> when establishing the current
133connection; see &ora-connect;.  The meaning of the
134arguments is as follows: </simpara>
135<variablelist><title>Arguments for <function>RUN-SQL</function></title>
136<varlistentry><term><replaceable>sql</replaceable></term>
137 <listitem><simpara>Text of SQL statement, as a string.
138   The <replaceable>sql</replaceable> statement may contain
139   &oracle-link; "named parameters," e.g. ":myparam" whose values will
140   be substituted from the parameters given
141   in <replaceable>params</replaceable>.
142</simpara></listitem></varlistentry>
143<varlistentry><term><replaceable>params</replaceable></term>
144 <listitem><simpara>A mapping of the names of the bind-parameters in the
145   query to their values.  The set of named parameters in the query must
146   match exactly the keys mapped by <replaceable>params</replaceable>.
147   The mapping may be passed as either (1) a hash table whose keys are
148   the named parameters or (2) a list of pairs, ((name value) (name
149   value) ...).  Parameter values passed from Lisp are converted to the
150   appropriate &oracle-link; data types (see <function>FETCH</function>).
151</simpara></listitem></varlistentry>
152<varlistentry><term><replaceable>is-select</replaceable></term>
153 <listitem><simpara>Flag: whether the statement is a SELECT query.  You
154   usually do not need to set this as it is detected by default based on
155   the SQL text.  However, there are situations, such as when a SELECT
156   query begins with comment, that you need to specify it explicitly.
157</simpara></listitem></varlistentry></variablelist></listitem></varlistentry>
158
159		<!-- DO-ROWS -->
160
161<varlistentry id="ora-do-rows"><term><code>(ORACLE:DO-ROWS
162<replaceable>vars</replaceable> &body-amp; &body-r;)</code></term>
163 <listitem><simpara> Macro which loops over a SQL SELECT result,
164   evaluating, for each row in the result, the forms in &body-r;,
165   binding symbols given in <replaceable>vars</replaceable> to
166   corresponding database columns in the SELECT result.  The
167   argument <replaceable>vars</replaceable> must be a non-empty list of
168   symbols matching a subset of the columns of an active SELECT query.
169   If a SELECT column is an &oracle-link; expression such as
170   <literal>SUBSTR(mycol, 1, 10)</literal>, it is recommended to use a
171   column alias, e.g., <literal>SELECT SUBSTR(mycol, 1, 10) AS
172    myvar</literal>, in which case the column alias will be used as the
173   symbol bound to the column value.</simpara>
174  <simpara>As <function>DO-ROWS</function> expands into a &do-star;
175   loop, it may be terminated prematurely, before all rows are fetched,
176   by using &return; anywhere in &body-r;.</simpara>
177  <simpara>It is allowed to call &ora-connect; in the
178   &body-r; of the loop, but only to switch the connection to a database
179   other than the one that was used to do the SELECT.  This is useful
180   for reading from one database while writing to another.
181  </simpara>
182  <simpara>In <replaceable>vars</replaceable>, instead of a single
183   symbol, a pair (<replaceable>bound-var</replaceable>
184   <replaceable>"column-name"</replaceable>) may be specified, which
185   will cause values from the SELECTed column or alias ,
186   <replaceable>column-name</replaceable>, to be bound to Lisp variable,
187   <replaceable>bound-var</replaceable>.  This is for unusual cases
188   where a Lisp variable cannot be created with the same name as the
189   column (e.g., a column named "T"), or when it is inconvenient or
190   impossible to alias the column with <literal>SELECT ... AS</literal>.
191</simpara></listitem></varlistentry>
192
193		<!-- FETCH -->
194<varlistentry id="ora-fetch"><term><code>(ORACLE:FETCH
195   &optional-amp; &res-type-r;)</code></term>
196 <listitem><para>Fetch a single row of data.  Returns a row of values
197   corresponding to the columns of an active SELECT statment.  The row
198   data is returned in one of three different forms, depending on the
199   value of the symbol &res-type-r;:
200<variablelist><title>Return values for <function>FETCH</function></title>
201 <varlistentry><term><classname>ARRAY</classname></term>
202  <listitem><simpara>Values will be returned in an &array-t; with the
203    same number of columns as in the SELECT statement, in the same
204    order.  This is the default.</simpara></listitem></varlistentry>
205 <varlistentry><term><classname>PAIRS</classname></term>
206  <listitem><simpara>A list of pairs, <literal>((column, value)
207     ...)</literal> is be returned.  The number and order of pairs is
208    the same as the columns in the SELECT statement.
209 </simpara></listitem></varlistentry>
210 <varlistentry><term><classname>HASH</classname></term>
211  <listitem><simpara>A &hash-table-t; whose keys are the column names
212    and whose values are the column values in the row.  The SELECT
213    columns <emphasis>must be unique</emphasis> and be valid Lisp
214    symbols to use this option. If you are SELECTing an expression, you
215    probably want to use a column alias: <literal>SELECT &lt;expr&gt; AS
216    some_alias ...</literal></simpara></listitem></varlistentry>
217</variablelist></para>
218<para>The following data type conversions are done between &oracle-link;
219 datatypes and &cl; data types:
220 <informaltable id="ora-fetch-data-types-tab" frame="all"><tgroup cols="2">
221   <thead><row><entry>&oracle-link; type</entry>
222     <entry>Converts to/from &cl; type</entry></row></thead>
223   <tbody><row><entry>Numeric (NUMBER, INTEGER, FLOAT)</entry>
224     <entry>The appropriate &cl; numeric type (&fixnum-t;, &bignum-t;,
225      &float-t;)</entry></row>
226    <row><entry>String (CHAR, VARCHAR, VARCHAR2)</entry>
227     <entry>A &cl; &string-t;.  Note that CHAR will be padded out to its
228      full, fixed length as defined in &oracle-link;; VARCHAR will be a
229      string of variable length.  Also note that &oracle-link; has no
230      "zero-length string" value - it returns the SQL special value
231      &c-NULL; which is converted to &nil; (see below).</entry></row>
232    <row><entry>DATE</entry>
233     <entry>A string of the form "YYYY-MM-DD HH:MM:SS" where HH is
234      24-hour form.  If you want dates formatted differently, convert
235      them to strings in &oracle-link; using <literal>SELECT
236       TO_CHAR(mydate, '<replaceable>template</replaceable>') AS
237       mydate</literal>; the result will then be returned as a string,
238      formatted as per <replaceable>template</replaceable>.</entry></row>
239    <row><entry>RAW, LONG RAW</entry>
240     <entry>A hexadecimal string, with two hex digits for each byte of
241      &oracle-link; data.  Note that this means the Lisp string will be
242      twice the size, in bytes, as the &oracle-link; data.</entry></row>
243    <row><entry>"Large" types (LONG, BLOB, CLOB)</entry>
244     <entry>A Lisp string of (arbitrary, possibly binary) data.  Note
245      that truncation may occur; see the &ora-connect;
246      parameters <replaceable>long-len</replaceable>
247      and <replaceable>truncate-ok</replaceable>.</entry></row>
248    <row><entry>&c-NULL;</entry>
249     <entry>The &cl; value &nil;</entry></row>
250 </tbody></tgroup></informaltable>
251</para></listitem></varlistentry>
252
253		<!-- FETCH-ALL -->
254
255<varlistentry id="ora-fetch-all"><term><code>(ORACLE:FETCH-ALL
256&optional-amp;
257<replaceable>max-rows</replaceable>
258&res-type-r;
259<replaceable>item-type</replaceable>)</code></term>
260<listitem><simpara>Fetch some or all the rows from a query and return
261result as a sequence of sequences.  Arguments are all optional:
262<replaceable>max-rows</replaceable> limits the result to
263that numbers of rows;
264&res-type-r; is the type of
265sequence of the rows, either
266'<classname>ARRAY</classname> (the default) or
267'<classname>LIST</classname>;
268<replaceable>item-type</replaceable> is the type of
269sequence of the column values for each row, either
270'<classname>ARRAY</classname> (the default) or
271'<classname>LIST</classname>.
272Each row fetched always contains the full set of column values SELECTed.
273</simpara>
274<simpara>
275<function>FETCH-ALL</function> is often useful in conjunction with
276<function>MAP</function> or <function>REDUCE</function> to iterate
277over an entire SELECT result to construct a single Lisp value.
278
279</simpara>
280</listitem>
281</varlistentry>
282
283		<!-- PEEK-->
284
285<varlistentry id="ora-peek"><term><code>(ORACLE:PEEK &optional-amp;
286   &res-type-r;)</code></term><listitem>
287<simpara>
288
289Peek at next row of data (without fetching it).  Returns a row a la
290<function>FETCH</function>, except does not advance to the next row.
291Repeated calls to <function>PEEK</function> will thus return the same
292row of data.  Returns &nil; if at EOF.  If data is available, returns
293row data just as <function>FETCH</function> (see
294<function>FETCH</function> for data format and conversions done).
295Optional argument &res-type-r; is the type
296of sequence of the column values for the returned row, either
297&array-t; (the default) or &list-t;.
298<function>PEEK</function> is a useful look-ahead
299for database reporting functions that may need to "break" on changes in
300data to print headers, summaries, etc.
301</simpara></listitem></varlistentry>
302
303		<!-- COLUMNS -->
304
305<varlistentry id="ora-columns"><term><code>(ORACLE:COLUMNS)</code></term>
306<listitem><para>Returns information on the columns of a SELECT
307  result, in the form of an array of SQLCOL structures, one for each
308  result column in the most recent SELECT statement.  It is not
309  necessary to have called <function>FETCH</function> before requesting
310  column information on the query, however the query must have been
311  compiled and executed with <function>RUN-SQL</function>.  Each SQLCOL
312  structure has these slots:
313<variablelist><title>Slots of <classname>SQLCOL</classname></title>
314 <varlistentry><term>NAME</term>
315  <listitem><simpara>The &oracle-link; column name or the expression
316    selected.  If the query used a column alias, <literal>SELECT
317     <replaceable>expr</replaceable> AS
318     <replaceable>alias</replaceable></literal>, then
319    <replaceable>alias</replaceable> will be returned as the column name.
320 </simpara></listitem></varlistentry>
321 <varlistentry><term>TYPE</term>
322  <listitem><simpara>&oracle-link; data type (VARCHAR, NUMBER, DATE, ...)
323 </simpara></listitem></varlistentry>
324 <varlistentry><term>SIZE</term>
325  <listitem><simpara>&oracle-link; data length (useful mostly for
326    character types)</simpara></listitem></varlistentry>
327 <varlistentry><term>SCALE</term>
328  <listitem><simpara>For numeric (NUMBER) types, number of digits to right of
329    decimal; NIL for FLOAT</simpara></listitem></varlistentry>
330 <varlistentry><term>PRECISION</term>
331  <listitem><simpara>For numeric types, total number of significant
332    digits (decimal digits for NUMBER, bits for FLOAT)</simpara></listitem></varlistentry>
333 <varlistentry><term>NULL_OK</term>
334  <listitem><simpara>&t; if &c-NULL;s allowed, &nil; if &c-NULL;s are
335    not allowed.</simpara></listitem></varlistentry>
336 </variablelist></para>
337 <simpara>To access the values of the SQLCOL structures, use the standard
338 accessor functions, e.g., <literal>(ORACLE:SQLCOL-NAME (elt
339  (ORACLE:COLUMNS) 0))</literal></simpara></listitem></varlistentry>
340
341		<!-- EOF -->
342
343<varlistentry id="ora-eof"><term><code>(ORACLE:EOF)</code></term>
344<listitem>
345<simpara>
346Returns EOF status.  A SELECT query cursor is considered at EOF if the next
347FETCH would return no data.  Must be connected to a database, and have
348an active SELECT statement.
349</simpara></listitem></varlistentry>
350
351		<!-- INSERT-ROW -->
352<varlistentry id="ora-insert-row"><term><code>(ORACLE:INSERT-ROW
353<replaceable>table</replaceable>
354<replaceable>values</replaceable>)</code></term>
355<listitem>
356<simpara>
357Inserts a single row into <replaceable>table</replaceable>.
358Second argument <replaceable>values</replaceable> is a map of
359column names to values: either a hash table whose keys are the column
360names, or a list of (name, value) pairs.  Columns missing from the map
361will be given the default &oracle-link; value, or &c-NULL;.
362Returns the number of rows inserted (i.e., always 1).
363</simpara></listitem></varlistentry>
364
365		<!-- UPDATE-ROW -->
366<varlistentry id="ora-update-row"><term><code>(ORACLE:UPDATE-ROW
367<replaceable>table</replaceable>
368<replaceable>condition</replaceable>
369<replaceable>vals</replaceable>
370&optional-amp;
371<replaceable>params</replaceable>)</code></term>
372<listitem>
373<simpara>
374Updates rows in <replaceable>table</replaceable>.  Second argument
375<replaceable>condition</replaceable> is a string expression for a WHERE
376clause (without the "WHERE") which determines which rows are updated.
377Third argument <replaceable>vals</replaceable> is a map of columns to
378be updated to their new values: a hash table whose keys are column
379names, or list of (name, value) pairs.  Optional
380<replaceable>params</replaceable> specifies values for named
381parameters that may occur in <replaceable>condition</replaceable>,
382e.g., when the condition is a match on a primary key, e.g.: <literal>"pk_column
383= :pk_val"</literal>.  Returns the number of rows updated.
384</simpara></listitem></varlistentry>
385
386		<!-- ROW-COUNT -->
387
388<varlistentry id="ora-row-count"><term><code>(ORACLE:ROW-COUNT)</code></term>
389<listitem>
390<simpara>
391For SELECT statements, returns the number of rows
392<function>FETCH</function>ed (&not-e;
393<function>PEEK</function>ed) so far.  For other statements (e.g.,
394INSERT, UPDATE, DELETE), returns the number of rows affected by the
395last operation (e.g., inserted, updated, deleted).  Must be connected
396to a database and have an active SQL statement.
397</simpara></listitem></varlistentry>
398
399		<!-- WITH-TRANSACTION -->
400
401<varlistentry id="ora-with-transaction"><term><code>(ORACLE:WITH-TRANSACTION
402&body-amp;
403&body-r;)</code></term>
404<listitem>
405<simpara>
406
407Evaluates the forms in &body-r; atomically as a
408database transaction, ensuring that either all the database operations
409done in &body-r; complete successfully, or none
410of them do.  If pending (un-committed) changes exist when this macro
411is entered, they are <emphasis>rolled back</emphasis> (undone), so
412that the database is affected only by the subsequent updates inside
413&body-r;.  Nesting of
414<function>WITH-TRANSACTION</function> blocks is not allowed and will
415raise an error.  There is no effect on the status of
416<replaceable>auto-commit</replaceable> given in
417&ora-connect;; it resumes its previous state when the
418macro exits.  The value of the <function>WITH-TRANSACTION</function>
419expression is that of the last form in &body-r;.
420</simpara></listitem></varlistentry>
421
422		<!-- COMMIT -->
423
424<varlistentry id="ora-commit"><term><code>(ORACLE:COMMIT)</code></term>
425<listitem>
426<simpara>
427Commits (makes permanent) any pending changes to the database.  The
428<replaceable>auto-commit</replaceable> parameter to
429&ora-connect; must not have been set to use this
430function, nor can it be called inside a
431<function>WITH-TRANSACTION</function> block. Always returns NIL.
432</simpara></listitem></varlistentry>
433
434		<!-- ROLLBACK -->
435
436<varlistentry id="ora-rollback"><term><code>(ORACLE:ROLLBACK)</code></term>
437<listitem>
438<simpara>
439Rolls back (undoes and abandons) any pending changes to the database.
440The <replaceable>auto-commit</replaceable> parameter to
441&ora-connect; must not have been set to use this
442function, nor can it be called inside a
443<function>WITH-TRANSACTION</function> block. Always returns NIL.
444</simpara></listitem></varlistentry>
445
446		<!-- AUTO-COMMIT -->
447
448<varlistentry id="ora-auto-commit"><term><code>(ORACLE:AUTO-COMMIT)</code></term>
449<listitem>
450<simpara>
451Toggles the state of <replaceable>auto-commit</replaceable> initially
452given to &ora-connect; for the current connection.
453With <replaceable>auto-commit</replaceable> enabled, modifications to
454the database are committed (made permanent) after each destructive SQL
455operation made with calls to <function>RUN-SQL</function>,
456<function>INSERT-ROW</function>, <function>UPDATE_ROW</function>, etc.
457With <replaceable>auto-commit</replaceable> disabled, transactional
458integrity is under the programmer's control and is managed either by
459(1) explicitly calling <function>COMMIT</function> or
460<function>ROLLBACK</function> to commit or undo the pending
461operations, or (2) wrapping code blocks with database operations
462inside the <function>WITH-TRANSACTION</function> macro.
463<function>AUTO-COMMIT</function> returns the previous status of
464<replaceable>auto-commit</replaceable>.
465<function>AUTO-COMMIT</function> may not be called inside
466<function>WITH-TRANSACTION</function>.
467</simpara></listitem></varlistentry>
468
469
470<!-- =-=-==-=-==-=-==-=-==-=-==-=-=   End of functions section -->
471
472</variablelist>
473</section>
474
475<section id="ora-example"><title>&oracle-link; Example</title>
476
477<para>
478Below is a simple example script which uses &oracle-link;'s demo database
479schema, <literal>SCOTT</literal>.
480
481<programlisting language="lisp">
482(setf server "orcl") <lineannotation>; Change this to your server's SID</lineannotation>
483(oracle:connect "scott" "tiger" server)
484
485(oracle:run-sql "SELECT deptno, dname, loc FROM dept ORDER BY DNAME")
486(oracle:do-rows (deptno dname loc)
487  (format t "Dept. no is '~A', " deptno)
488  (format t "Dept. name is '~A', " dname)
489  (format t "Dept. loc is '~A'~%" loc))
490
491(oracle:update-row "dept" "dname = :acctval" '(("dname" "NEWACCT")) '(("acctval" "ACCOUNTING")))
492
493(oracle:run-sql "SELECT deptno, dname, loc FROM dept ORDER BY DNAME")
494(oracle:do-rows (deptno dname loc)
495  (format t "Dept. no is '~A', " deptno)
496  (format t "Dept. name is '~A', " dname)
497  (format t "Dept. loc is '~A'~%" loc))
498
499(oracle:update-row "dept" "dname = :acctval" '(("dname" "ACCOUNTING")) '(("acctval" "NEWACCT")))
500</programlisting>
501</para>
502</section>
503
504
505
506
507<section id="ora-config"><title>&oracle-link; Configuration</title>
508
509<para>Obviously, a working &oracle-link; environment is required.  It is
510recommended that you first be able to log on and use the &oracle-link;
511SQL*Plus application to test your environment
512&before-e; attempting &oracle-link; access via the &clisp; module.
513At a minimum you will need to set environment variables
514<envar>ORACLE_HOME</envar> to the &oracle-link; base directory and
515<envar>LD_LIBRARY_PATH</envar> to include
516<literal>$<envar>ORACLE_HOME</envar>/lib</literal> and possibly other
517directories.</para>
518
519</section>
520
521<section id="ora-build"><title>Building the &oracle-link; Interface</title>
522
523<para>The module uses the &oracle-link; Call Interface (&oracle-oci;)
524&c-lang; library.  To build the module you will need the &oracle-link;
525&oracle-oci; headers and link libraries; as a quick check, make sure
526you have the file <filename>oci.h</filename> somewhere
527under <envar>ORACLE_HOME</envar>, probably
528in <filename>$<envar>ORACLE_HOME</envar>/rdbms/demo/oci.h</filename>.</para>
529
530<para>To build the module into &clisp;, configure with
531<command>./configure ... --with-module=oracle ...</command>.
532The &full; &linkset; will contain the module,
533so you will need to use the &opt-K; option to use it.
534You can test that you really have the &oracle-link;-enabled &clisp; by
535evaluating <code>(&describe; 'oracle:connect)</code>.</para>
536
537<note><para>It may be necessary to edit file
538<filename role="clisp-cvs">modules/oracle/Makefile.in</filename>
539prior to running <command>./configure</command>.</para></note>
540
541
542</section>
543
544</section>
545