60
DEVELOPING C/C++ ORACLE APPLICATIONS WITH How to easily and efficiently program Oracle effective applications in C/C++ Written by Vincent Rogier

Ocilib 3.5.0 User Guide

Embed Size (px)

Citation preview

Page 1: Ocilib 3.5.0 User Guide

DEVELOPING

C/C++ ORACLE APPLICATIONS

WITH

How to

easily and efficiently program

Oracle effective applications

in C/C++

Written by Vincent Rogier

Page 2: Ocilib 3.5.0 User Guide

Developing C/C++ Oracle applications with OCILIB

Copyright © 2008-2010 Vincent Rogier – http://www.ocilib.net - Document under GNU Free Documentation License v1.3

2

DEVELOPING

C/C++

ORACLE APPLICATIONS

WITH OCILIB

Copyright (C) Vincent Rogier

Permission is granted to copy, distribute and/or modify this document under the terms of the GNU Free Documentation License, Version 1.3

or any later version published by the Free Software Foundation; with no Invariant Sections, no Front-Cover Texts, and no Back-Cover Texts.

A copy of the license is included in the section entitled “GNU Free Documentation License".

Page 3: Ocilib 3.5.0 User Guide

Developing C/C++ Oracle applications with OCILIB

Copyright © 2008-2010 Vincent Rogier – http://www.ocilib.net - Document under GNU Free Documentation License v1.3

3

Contents

1. Introduction ......................................................................................................................... 5

Revision ................................................................................................................................. 5 Introduction ............................................................................................................................ 5 Complexity of OCI ................................................................................................................... 5 Why OCILIB? .......................................................................................................................... 6 Features ................................................................................................................................. 6 Documentation........................................................................................................................ 6

2. Installation ........................................................................................................................... 7

Requirements ......................................................................................................................... 7 Compatibilities ........................................................................................................................ 7 Installing OCILIB on Unix (Unix/Linux/Mac) ................................................................................ 7 Installing on Microsoft Windows ................................................................................................ 8 Oracle Instant Client Support .................................................................................................... 8 Project Configuration ............................................................................................................... 9 Charset support .................................................................................................................... 10 Unicode support .................................................................................................................... 11 Oracle Supported datatypes .................................................................................................... 11 OCILIB datatypes .................................................................................................................. 12

3. Connecting to Oracle .......................................................................................................... 13

Initializing OCILIB ................................................................................................................. 13 Creating a connection ............................................................................................................ 13 Using transactions ................................................................................................................. 14

4. Error handling .................................................................................................................... 15

Global error handling ............................................................................................................. 15 Contextual thread error handling ............................................................................................. 16

5. Executing SQL statements .................................................................................................. 17

SQL Statements .................................................................................................................... 17 Binding Variables ................................................................................................................... 17 Retrieving the result of a query ............................................................................................... 19 Resultset metadata information ............................................................................................... 20 Implicit conversions ............................................................................................................... 21 Scrollable statements ............................................................................................................ 22 PL/SQL blocks ....................................................................................................................... 23 Support for SQL RETURNING clause ......................................................................................... 24 Statements extra control ........................................................................................................ 25

6. Bulk Operations .................................................................................................................. 26

Oracle Array interface ............................................................................................................ 26 Example ............................................................................................................................... 27

7. Using Larges Objects .......................................................................................................... 28

Internal Objects (LOBs) .......................................................................................................... 28 External Objects (FILEs) ......................................................................................................... 30 Long Objects......................................................................................................................... 32

Page 4: Ocilib 3.5.0 User Guide

Developing C/C++ Oracle applications with OCILIB

Copyright © 2008-2010 Vincent Rogier – http://www.ocilib.net - Document under GNU Free Documentation License v1.3

4

8. Using dates and timestamps .............................................................................................. 34

Date handles ........................................................................................................................ 34 Timestamp handles ............................................................................................................... 34 Interval handles .................................................................................................................... 35

9. Using Oracle objects (U.D.T. / Named Types) .................................................................... 36

Autonomous Instances ........................................................................................................... 37 Selecting objects ................................................................................................................... 37

10. Using Oracle Collections ..................................................................................................... 38

Collections types ................................................................................................................... 38 Example ............................................................................................................................... 38

11. Loading data with Direct Path mode ................................................................................... 40

Oracle Direct Path Loading...................................................................................................... 40 Example ............................................................................................................................... 41

12. Advanced features .............................................................................................................. 42

Describing tables in a schema ................................................................................................. 42 Functions '"All In One" ........................................................................................................... 42 Optimizing performances ........................................................................................................ 45 Using OCILIB hash tables API ................................................................................................. 45 Using OCILIB thread API ........................................................................................................ 46 Remote database startup/shutdown ......................................................................................... 48 Database change notifications ................................................................................................. 48 Going deeper in OCI: direct use of OCI handles ......................................................................... 52

13. Annexes ............................................................................................................................. 53

GNU Free Documentation License ............................................................................................ 53

Page 5: Ocilib 3.5.0 User Guide

Developing C/C++ Oracle applications with OCILIB

Copyright © 2008-2010 Vincent Rogier – http://www.ocilib.net - Document under GNU Free Documentation License v1.3

5

1. Introduction

Revision

List of revisions of the document:

• 07/01/2008 - Released (version 1.5.1) • 13/02/2008 - Updated (version 2.0.0) • 21/02/2008 - Updated (added “optimizing performances”) • 07/03/2008 - Updated (corrected linker options) • 20/03/2008 - Updated (corrected “Features”) • 29/03/2008 - Updated (various fixes) • 01/04/2008 - Updated (version 2.3.0) • 24/04/2008 - Updated (version 2.4.0 + various modifications) • 21/07/2008 - Updated (version 2.5.0 + various modifications) • 13/10/2008 - Updated (version 3.0.0: major update) • 28/01/2009 - Updated (version 3.1.0) • 20/04/2009 - Updated (version 3.2.0) • 15/01/2010 - Rewritten (full rewrite, version 3.5.0, translation to English, added GNU FDL license)

Introduction

OCILIB is an open source and cross platform Oracle library that delivers really efficient and reliable access to Oracle databases. The library OCILIB:

• Provides a rich and easy API • Runs on all platforms Oracle • Is written in pure ISO C and has native ISO C Unicode support • Enables high productivity • Encapsulates OCI (Oracle Call Interface) • Is the most complete OCI wrapper available

Complexity of OCI

Oracle Call Interface (OCI) is an API provided by Oracle that allows developers to create applications using low C/C++ calls to access to Oracle databases. OCI controls all aspects of running SQL statements while supporting data types, calling conventions, syntax and semantics of C, C++ languages. OCI is a very powerful API (this is the lowest level API provided by Oracle) and used by many applications and tools (starting with SQL*Plus, SQL*Loader and all Oracle products) but also very complex and heavy to use... For example, connecting to an Oracle database requires at least almost 100 lines of code! In addition, most functions of OCI often require a list of arguments fairly consistent (like a dozen parameters) and complex (almost exclusive manipulation of pointers, pointers of pointers, etc. ...). Thus, an OCI application is often difficult to code, read and maintain!

Page 6: Ocilib 3.5.0 User Guide

Developing C/C++ Oracle applications with OCILIB

Copyright © 2008-2010 Vincent Rogier – http://www.ocilib.net - Document under GNU Free Documentation License v1.3

6

Why OCILIB?

OCILIB encapsulates OCI in order to provide optimal reusability of code. It is free (open source - LGPL license), rich (about 550 simple functions) and its source code is platform-independent (MS Windows, HP/UX, AIX, Solaris, Linux And Mac). OCILIB really boosts productivity of C/C++ database oriented development with its JDBC like API. OCILIB can combine the performance of C/C++ by proposing a pragmatic interface, easy to use, while maintaining richness in functionality. OCILIB is one of the few C/C++ based OCI libraries that provides complete Unicode support. An OCILIB application can be compiled either natively in ANSI or Unicode. Finally, OCILIB source code is 100% ISO C90 (and C99 for full Unicode support) and thus extremely portable! OCILIB does not require an Oracle client to develop Oracle application. Indeed, an application using OCILIB can link Oracle libraries at compilation time (static or dynamic linkage) or at runtime if the target OS supports dynamic loading of modules. OCILIB works on all platforms supported by Oracle (Microsoft Windows, Linux, UNIX, Mac ...). Currently, OCILIB is widely used in:

• Banking applications • Industrial applications • Generic databases frameworks as internal Oracle layer

Features

Here is a list of key features at the last revision of the tutorial (v3.5.0 released on 2009-12-21):

• Full ANSI and Unicode support on all platforms • Built-in error handling (global and thread context) • Support for ALL Oracle SQL and PL/SQL datatypes (scalars, objects, refs, collections, ..) • Support for non scalar datatype with trough library objects • Binding array Interface for fast and massive bulk operations • Reusable and scrollable statements • Connection Pooling • Global Transactions • Full PL/SQL support (blocks, cursors, Index by Tables and Nested tables) • Returning DML feature support • Direct Path loading • Runtime loading • Remote Instances Startup/Shutdown • Oracle Database Change notification / Continuous Query Notification • Oracle warnings support • Describe database schema objects • Hash tables API • Portable Threads and mutexes API

Documentation

• Online documentation : http://www.ocilib.net/doc/html/ • The documentation is also included in the distributions of OCILIB

Page 7: Ocilib 3.5.0 User Guide

Developing C/C++ Oracle applications with OCILIB

Copyright © 2008-2010 Vincent Rogier – http://www.ocilib.net - Document under GNU Free Documentation License v1.3

7

2. Installation

Requirements

• An Operating system supported by Oracle (MS Windows, Unixes, Mac, …) • An Oracle client (regular or Instant) (note that the client is not required for compilation)

Compatibilities

The following platforms have been validated (compilation, installation, build and execution):

Other platforms supported by Oracle (for example, z/OS) have not been officially "validated", but given the platforms already validated, porting OCILIB to these platforms should not be a big deal! The following compilers have been validated:

The following versions of Oracle (clients and servers) have been validated:

Installing OCILIB on Unix (Unix/Linux/Mac)

OCILIB uses GNU tools for deployment and installation:

Check the dynamic libraries path environment variable (LD_LIBRARY_PATH, LD_PATH...) and make sure that the Oracle and OCILIB shared libraries locations are included. Typically, just add theses to your .profile file. Example:

$ Export LD_LIBRARY_PATH =$LD_LIBRARY_PATH:$ORACLE_HOME/lib:/usr/local/lib

Unpack the current archive (ocilib-xyz-gnu.tar.gz) $ cd ocilib-x.y.z $ ./configure $ ./make $ ./make install (needs user root)

Oracle 8i (> 8.0) Oracle 9i (all) Oracle 10g (R1 and R2) Oracle 11g (R1)

Microsoft Compilers (VC++, VS200X) GCC and MinGW IBM XLC Proprietary CC (HP, AIX ...) LabView

Microsoft Windows Linux Solaris HP/UX AIX Mac OS X

Page 8: Ocilib 3.5.0 User Guide

Developing C/C++ Oracle applications with OCILIB

Copyright © 2008-2010 Vincent Rogier – http://www.ocilib.net - Document under GNU Free Documentation License v1.3

8

OCILIB supports 6 additional installation options:

Note: If the compiler is GCC, the default GNU tools (autoconf and automake) use the flags '-g-O2'. This therefore adds debugging in formations to the generated libraries:

• Until the 2.xx versions, this could increase the final size of the library 50% on average (total size 300 Kb on Linux)

• From version 3.0.0 (the source code has been split into several files, the increase may be 300%! (650 Kb on Linux)

• The strip command can remove debugging symbols from the OCILIB shared library (final size 150 Kb)

Installing on Microsoft Windows

On Microsoft Windows, 32bits and 64bits (x86) DLLs are provided and can be easily recompiled.

[x] is the compiled version of OCILIB ('a' -> ANSI, 'w' -> Unicode, 'm' -> Mixed)

Oracle Instant Client Support

On Microsoft Windows, there is no difference between using a regular Oracle client and an Instant Client with OCILIB. On Unix-like systems, the Instant Client is divided in different packages. Public headers and shared libraries are not part of the same package. So, you must provide the following options to the configure command:

If your instant client package containing the shared libraries does not have a symbolic link 'libclntsh.$(shared lib extension)' to the fully qualified shared lib real name, you must create it:

--with-oracle-headers-path : location the public header files --with-oracle-lib-path : location the oracle shared libraries

$ ln-s $ORALIBPATH/libclntsh.so.10.1 $ ORALIBPATH/libclntsh.so

--with-oracle-import = (linkage | runtime) --with-oracle-charset = (ANSI | Unicode | Mixed) --with-oracle-home = (oracle home) --with-oracle-headers-path = (location of OCI headers files) --with-oracle-lib-path = (location of OCI shared libraries) --with-custom-loader = (linker flag telling the target linker which loader to use when loading Oracle

shared libraries dynamically at runtime. This option must be provided if the platform does not use the default loader flag '-ldl') and if the --with-oracle-import is set to 'runtime')

Unpack the current archive (ocilib-xyz-windows.zip) Copy ocilib\include\ocilib.h : to a folder listed in the compiler headers folders Copy ocilib\lib32 |64\ocilib [x].Lib : to a folder listed in the linker libraries folders Copy ocilib\lib32|64\ocilib [x]. Dll : to a folder included in the PATH environment variable

Page 9: Ocilib 3.5.0 User Guide

Developing C/C++ Oracle applications with OCILIB

Copyright © 2008-2010 Vincent Rogier – http://www.ocilib.net - Document under GNU Free Documentation License v1.3

9

Project Configuration

To use OCILIB in a project, include the file “ocilib.h” Some options must be defined before including this header. Oracle linkage mode:

Oracle charset mode:

Calling Convention (MS Windows only):

Windows

For example, to use the ANSI built of OCILIB using the supplied DLLs with MS Visual Studio:

If all OCILIB import libraries builds (ocilib[x].lib) are accessible to the linker, then you must specify which one to use with:

Note: from version 3.2.0, static libraries are also provided for the Windows port of GCC: libociliba.a, libocilibm.a and libocilibw.a Unixes

For example, to use the ANSI built of OCILIB linking Oracle shared libraries are compile time (let’s suppose that the variable $USER_LIBS points to the parent directory where OCILIB is installed, default is usr/local/):

- Include "ocilib.h" - Add compile options the makefile

o -I$USER_LIBS/include (for header ocilib.h)

o -DOCI_IMPORT_LINKAGE -DOCI_CHARSET_ANSI (OCILIB options) - Add linkage options to the makefile

o -L/$ORACLE_HOME/lib (for Oracle shared lib) o -L$USER_LIBS/lib -locilib (for OCILIB shared lib)

#pragma comment (lib, "ocilib[x].lib")

- Create a new project - Include "ocilib.h" - Set OCI_API = __sdtcall in the project preprocessor options

- OCI_API: Undefined - OCI_API: __sdtcall to use precompiled dlls

- OCI_CHARSET_ANSI : all strings are in ANSI - OCI_CHARSET_UNICODE : all strings are Unicode (versions of Oracle> = 9i) - OCI_CHARSET_MIXED : SQL statements + metadata are in ANSI, user data and resultset data in Unicode

- OCI_IMPORT_LINKAGE: linking Oracle libraries (shared or static) at compilation time - OCI_IMPORT_RUNTIME: loading dynamically Oracle libraries at runtime

Page 10: Ocilib 3.5.0 User Guide

Developing C/C++ Oracle applications with OCILIB

Copyright © 2008-2010 Vincent Rogier – http://www.ocilib.net - Document under GNU Free Documentation License v1.3

10

Charset support

OCILIB supports ANSI and Unicode charsets OCILIB uses char/wchar_t strings for public interface and internal storage. Oracle started a real Unicode support with Oracle8i but only for user data. All SQL and PL/SQ/ statements, metadata string, database objects names, etc ... were still only supported in ANSI. With Oracle 9i, Oracle provides a full Unicode support. So depending on the compile time Oracle library or the runtime loaded library, the Unicode support differs. OCILIB supports:

OCILIB uses two types of strings:

mtext and dtext are declared as defines around char and wchar_t depending on the charset option Text macros :

Summary :

Element OCI_CHARSET_ANSI OCI_CHARSET_UNICODE OCI_CHARSET_MIXED

Dtext char wchar_t wchar_t

DT(x) x L ## x x

Dtext char wchar_t char

MT(x) X L ## x x

Additional macros:

Theses macros are based on the model: * mtsxxx() for mtext * typed strings * dtsxxx() for dtext * typed strings xxx is the standard C library string function name without the character type prefix (str/wcs). List of available macros: * mtsdup, dtsdup * mtscpy, dtscpy * mtsncpy, dtsncpy * mtscat, dtscat * mtsncat, dtsncat * mtslen, dtslen * mtscmp, dtscmp * mtscasecmp, dtscasecmp * mtsprintf, dtsprintf * mtstol, dtstol

MT(): 'meta text' -> meta data and strings passed to OCI calls DT(): 'data text' -> user input/output data

mtext: for metadata, SQL strings, object attributes. dtext: for input binds and output data

ANSI (char) Unicode (wchar_t) Mixed charset: ANSI for metadata, Unicode for user data

Page 11: Ocilib 3.5.0 User Guide

Developing C/C++ Oracle applications with OCILIB

Copyright © 2008-2010 Vincent Rogier – http://www.ocilib.net - Document under GNU Free Documentation License v1.3

11

Unicode support

Well, ISO C:

• Doesn’t know anything about Unicode. • Makes wide characters support tricky because the size of a wide character is not defined and is

freely adaptable by implementations. OCILIB fully supports Unicode on all platforms around the C data type wchar_t (UTF16/UTF32 between platforms). OCILIB, for Unicode builds, initialize OCI in UTF16 Unicode mode. Oracle implements this mode with a 2 bytes (fixed length) UTF16 encoding. So, on systems implementing wchar_t as 2 bytes based UTF16 (e.g. Ms Windows), input strings are directly passed to Oracle and taken back from it. On other systems (most of the unixes) that use UTF32 as encoding (4 bytes based wchar_t), OCILIB uses: * Temporary buffers to pass string to OCI for metadata strings * Buffer expansion from UTF16 to UTF32 for user data string: o allocation based on sizeof(wchar_t) o data filling based on sizeof(short) -> (UTF16 2 bytes) o data expansion to sizeof(wchar_t). The buffer expansion is done in place and has the advantage of not requiring extra buffer. That reduces the cost of the Unicode/ISO C handling overhead on Unixes.

Oracle Supported datatypes

OCILIB supports all data types provided by Oracle. List of supported types:

• All scalar types (strings, numeric...): CHAR / NCHAR, VARCHAR2/NVARCHAR2, NUMBER, FLOAT... • Types binary: RAW, LONG RAW, VARRAW... • Large Objects (LOBs and Files): BLOB, CLOB, NCLOB, BFILE, CFILE • Types LONG: LONG VAR LONG, LONG RAW ... • Date, Timestamps and Intervals: DATE, TIMESTAMP (all), INTERVAL (all) • PL / SQL types: Ref cursors, PL / SQL tables (tables) and PL / SQL Nested Tables • Objects (Named Types): user types and type systems • Objects References: REF Type • SQL Collections: VARRAY and Nested Tables • ROWID and UROWID

All these types can be binded to statements or be retrieved from a select statement.

Oracle TYPE OCILIB Type

Strings : CHAR/NCHAR, VARCHAR2/NVARCHAR2, ....

dtext * (char * or wchar_t * depending on build)

Numbers : INT, NUMBER, ... shorts, ints, big ints (signed/unsigned)

REAL : FLOAT, REAL, NUMBER(X,Y), .... double

RAW void *

LONG, LONG RAW, VARRAW, .. OCI_Long

BLOB / CLOB / NCLOB OCI_Lob

Page 12: Ocilib 3.5.0 User Guide

Developing C/C++ Oracle applications with OCILIB

Copyright © 2008-2010 Vincent Rogier – http://www.ocilib.net - Document under GNU Free Documentation License v1.3

12

DATE OCI_Date

TIMESTAMP, TIMESTAMP_TZ, TIMESTAMP_LTZ OCI_Timestamp

INTERVAL, INTERVAL_YM, INTERVAL_DS OCI_Interval

PL/SQL Ref Cursors OCI_Statement

PL/SQL Tables Tableaux C de types scalaires ou objets

OCILIB

PL/SQL Nested Tables OCI_Statement

Objects (User Types) OCI_Object

Objects References (REF) OCI_Ref

Collections (Varrays et Nested Tables) OCI_Coll et OCI_Elem

ROWID et UROWID dtext * (char * or wchar_t * depending on

build)

OCILIB datatypes

Here are the OCILIB data types with brief descriptions:

OCI_Bind Internal bind representation

OCI_Coll Oracle Collections (VARRAYs and Nested Tables) representation

OCI_Column Oracle SQL Column and Type member representation

OCI_Connection Oracle physical connection

OCI_ConnPool Oracle Connection Pool

OCI_Date Oracle internal date representation

OCI_DirPath OCILIB encapsulation of OCI Direct Path handle

OCI_Elem Oracle Collection item representation

OCI_Error Encapsulates an Oracle or OCILIB exception

OCI_Event OCILIB encapsulation of Oracle DCN event

OCI_File Oracle External Large objects:

OCI_HashEntry Hash table entry

OCI_HashTable OCILIB implementation of hash tables

OCI_HashValue Hash table entry value

OCI_Interval Oracle internal interval representation

OCI_Iter Oracle Collection iterator representation

OCI_Lob Oracle Internal Large objects:

OCI_Long Oracle Long datatype

OCI_Mutex OCILIB encapsulation of OCI mutexes

OCI_Object Oracle Named types representation

OCI_Ref Oracle REF type representation

OCI_Resultset Collection of output columns from a select statement

OCI_Statement Oracle SQL or PL/SQL statement

OCI_Subscription OCILIB encapsulation of Oracle DCN notification

OCI_Thread OCILIB encapsulation of OCI Threads

OCI_Timestamp Oracle internal timestamp representation

OCI_Transaction Oracle Transaction

OCI_TypeInfo Type info metadata handle

OCI_Variant Internal Variant type based on union C type

OCI_XID Global transaction identifier

Page 13: Ocilib 3.5.0 User Guide

Developing C/C++ Oracle applications with OCILIB

Copyright © 2008-2010 Vincent Rogier – http://www.ocilib.net - Document under GNU Free Documentation License v1.3

13

3. Connecting to Oracle

Initializing OCILIB

First of all, OCILIB must be initialized. This requires a call to OCI_Initilalize() before any other calls. This function initializes the library and takes as parameters:

• [Optional] a global error handler procedure • [Optional] Oracle shared library path (only if OCILIB is built with OCI_IMPORT_RUNTIME) • The library initialization mode

The possible values for the initialization mode are:

• OCI_ENV_DEFAULT : default mode (not thread safe) • OCI_ENV_THREADED : support for multithreading (thread safe) • OCI_ENV_CONTEXT : Enabling context error handling per thread

Any attempt to create any OCILIB objects before initializing OCILIB generates an error that can be recovered by OCI_GetLastError() if OCI_ENV_CONTEXT is set.

At the end of application, a call to OCI_Cleanup() is required to:

• Deallocate specifics objects not explicitly released by the program (connections, connection pools, statements, type info objects, thread keys)

• Unload the Oracle shared library (only if OCILIB is built with OCI_IMPORT_RUNTIME)

Creating a connection

Connecting to an Oracle database is done by OCI_ConnectionCreate() that takes as parameters:

• Oracle connection string (Service name, full TNS connection string or an easy connect string) • Oracle user • Oracle user password • The session mode

The possible values for the session mode are:

• OCI_SESSION_DEFAULT : default mode • OCI_SESSION_SYSDBA : Oracle SYSDBA mode • OCI_SESSION_SYSOPER : Oracle SYSOPER mode

#include "ocilib.h" int main() { if (!OCI_Initialize(NULL, NULL, OCI_ENV_DEFAULT)) return EXIT_FAILURE; /* ... application code here ... */ OCI_Cleanup(); return EXIT_SUCCESS; }

Page 14: Ocilib 3.5.0 User Guide

Developing C/C++ Oracle applications with OCILIB

Copyright © 2008-2010 Vincent Rogier – http://www.ocilib.net - Document under GNU Free Documentation License v1.3

14

This function connects to the server, creates a session and starts a transaction. If successful, it returns a connection handle and the application can immediately execute SQL statements.

To close the connection to the server, you need to free the connection object with OCI_ConnectionFree().

Using transactions

OCILIB supports local and global Oracle transactions. Local transactions are implicit within connection objects and there is no specific call or programming step for using it. By default, once the application has connected to Oracle, a local transaction is created. Any modification (insert, update, delete) is not visible to other sessions until the application explicitly commits the changes using OCI_Commit(). If the application does not want to validate changes made onto the database since the last commit (or connection if no commit done yet), it must call OCI_Rollback(). Note that OCILIB allows the application to auto commit changes after every SQL statement execution, so no call to OCI_Commit() is required. To turn on/off(default) this mode, use OCI_SetAutoCommit(). Global transactions are optional and are designed for distributed or global transaction environments.

#include "ocilib.h" int main(void) { OCI_Connection *cn; if (!OCI_Initialize(NULL, NULL, OCI_ENV_DEFAULT)) return EXIT_FAILURE; cn = OCI_ConnectionCreate("db", "usr", "pwd", OCI_SESSION_DEFAULT); if (cn != NULL) { printf(OCI_GetVersionServer(cn)); printf("Server major version : %i\n", OCI_GetServerMajorVersion(cn)); printf("Server minor version : %i\n", OCI_GetServerMinorVersion(cn)); printf("Server revision version : %i\n", OCI_GetServerRevisionVersion(cn)); printf("Connection version : %i\n", OCI_GetVersionConnection(cn)); /* ... application code here ... */ OCI_ConnectionFree(cn); } OCI_Cleanup(); return EXIT_SUCCESS; }

Page 15: Ocilib 3.5.0 User Guide

Developing C/C++ Oracle applications with OCILIB

Copyright © 2008-2010 Vincent Rogier – http://www.ocilib.net - Document under GNU Free Documentation License v1.3

15

4. Error handling

OCILIB provides two mechanisms for error handling:

• Global error handling through callbacks. • Contextual thread error handling

Exceptions are raised:

• On Oracle OCI API call error • On Oracle SQL statement error • On Internal OCILIB error (type checking, memory allocations ...) • On Oracle warnings (OCI API or from SQL) from v3.5.0 if warnings are enabled

The two mechanisms to handle errors are not exclusive and can be mixed. Thread contextual error is also available for single thread based applications Oracle warnings are raised through the OCI_Error API. Such error handles have their error type property set to OCI_ERR_WARNING. Warning handing is disabled by default. To activate/deactivate this feature, use OCI_EnableWarnings().

Global error handling

When an exception is raised, OCILIB calls the error handler provided by the application. The prototype of the callback to provide is:

A handle to an object OCI_Error is then supplied to the function. Exception properties are accessible through a set of functions.

#include "ocilib.h" void err_handler(OCI_Error *err) { printf("Error ORA-%05i - msg : %s\n", OCI_ErrorGetOCICode(err), OCI_ErrorGetString(err)); } int main() { OCI_Connection *cn; if (!OCI_Initialize(err_handler, NULL, OCI_ENV_DEFAULT)) return EXIT_FAILURE; cn = OCI_ConnectionCreate("wrong_db", "wrong_usr", "wrong_pwd", OCI_SESSION_DEFAULT); /* ... application code here ... */ OCI_Cleanup(); return EXIT_SUCCESS; }

typedef void (*POCI_ERROR) (OCI_Error *err);

Page 16: Ocilib 3.5.0 User Guide

Developing C/C++ Oracle applications with OCILIB

Copyright © 2008-2010 Vincent Rogier – http://www.ocilib.net - Document under GNU Free Documentation License v1.3

16

Contextual thread error handling

This mode permits retrieving the last error that occurred in the current thread (which may be the main thread of the application). In order to use the thread contextual error handling, you must call OCI_Initialize() with the flag OCI_ENV_CONTEXT. When activated, error handles are stored per thread and the last error that occurred within a thread can be retrieved with OCI_GetLastError() Note that any successful OCILIB call clears the last error.

Note that OCI_GetLastError() works like the MS Windows Win32 GetLastError() function.

#include "ocilib.h" int main() { OCI_Connection *cn; if (!OCI_Initialize(NULL, NULL, OCI_ENV_DEFAULT | OCI_ENV_CONTEXT)) return EXIT_FAILURE; cn = OCI_ConnectionCreate("wrong_db", "wrong_usr", "wrong_pwd", OCI_SESSION_DEFAULT); if (cn == NULL) { OCI_Error *err = OCI_GetLastError(); printf("errcode %d, errmsg %s", OCI_ErrorGetOCICode(err), OCI_ErrorGetString(err)); } OCI_Cleanup(); return EXIT_SUCCESS; }

Page 17: Ocilib 3.5.0 User Guide

Developing C/C++ Oracle applications with OCILIB

Copyright © 2008-2010 Vincent Rogier – http://www.ocilib.net - Document under GNU Free Documentation License v1.3

17

5. Executing SQL statements

SQL Statements

To execute SQL commands on the database, you must create a SQL statement object using the function OCI_CreateStatement(). Once this object is created, it is possible to execute any type of SQL or PL/SQL statement using OCI_ExecuteStmt().

OCI_ExecuteStmt() prepares and executes the given SQL statement and OCI_GetAffectedRows() retrieves the number of deleted rows in the table. To release a statement and its associated resources (resultset ...) when it is not more needed, call OCI_StatementFree(). Note that an OCI_Statement object can be reused to run as many SQL statements as necessary.

Binding Variables

OCILIB supports OCI data binding APIs It is therefore possible to link host user variables to SQL queries by providing their address statement. Then every time the statement is executed, it uses the current values at the binded addresses. Programs variables can be binded to an Oracle SQL PL/SQL statement in order to:

• Provide input data for SQL statement • Provide input/output data for PL/SQL blocks

OCILIB provides a set of binding functions to use with:

• Basic datatypes: string (char/wchar_t *), int, double, raw • Object datatypes: lobs, files, longs, dates, cursors, statements, timestamps, intervals, objects

OCI_Connection *cn; OCI_Statement *st; /* ... */ st = OCI_StatementCreate(cn); OCI_ExecuteStmt(st, "delete from my_table where code is null"); printf("%d row deleted", OCI_GetAffectedRows(st)); OCI_Commit(cn); OCI_StatementFree(st); /* ... */

Page 18: Ocilib 3.5.0 User Guide

Developing C/C++ Oracle applications with OCILIB

Copyright © 2008-2010 Vincent Rogier – http://www.ocilib.net - Document under GNU Free Documentation License v1.3

18

To use binding:

• Prepare a statement with OCI_Prepare() (see Executing statements) • Bind all variables by calling one of the OCI_Bindxxxxx() function for every input variable

referenced by the SQL statement • Setup up values of the program variables • Call OCI_Execute() as many times as needed • Each OCI_Execute() call may be preceded by an update of the program variables (for INSERTs for

example) OCILIB does not pre-parse statements (like other frameworks such as JDBC ...) and lets Oracle recognize input variables embedded within the SQL statements. Bind variables must be preceded in the SQL code by the character ':'. Oracle and OCILIB supports two ways of binding:

• by name (default mode in OCILIB): Oracle looks for variables in the SQL statement by searching their names provided to the binding function. So a variable can be binded once and used many times in the statement

• by position: Oracle binds variables by position, so every variable is binded with a position number OCILIB Default binding mode is OCI_BIND_BY_NAME. When using binding by position, provide the position to OCI_BindXXXX() call through the name parameter. Within this mode the bind name must be the position preceded by a semicolon like ':1', ':2', Note: Rebinding is disabled by default (see OCI_AllowRebinding()) In the previous example, the query was simple and did not require any input variable. Often, it is necessary to request handle values that are not known at compilation time. Moreover, it is useful to run several times the same SQL statement with different values without having to re-prepare the same SQL Oracle to optimize performance.

To make a mass insertion, we can proceed as follows:

OCI_Connection *cn; OCI_Statement *st; int code; /* ... */ st = OCI_StatementCreate(cn); OCI_Prepare(st, "delete from test_fetch where code = :code"); OCI_BindInt(st, ":code", &code); code = 3; OCI_Execute(st); printf("%d row deleted"; OCI_GetAffectedRows(st)); code = 56; OCI_Execute(st); printf("%d row deleted"; OCI_GetAffectedRows(st)); OCI_Commit(cn);

Page 19: Ocilib 3.5.0 User Guide

Developing C/C++ Oracle applications with OCILIB

Copyright © 2008-2010 Vincent Rogier – http://www.ocilib.net - Document under GNU Free Documentation License v1.3

19

However, Oracle supports "bulks operations" (see Chapter 6) that allows host arrays binding and thus a major increase of performance.

Retrieving the result of a query

OCILIB offers a really easy and smart mechanism to fetch data from a SQL Statement. It looks like what's found in JDBC and other object oriented databases frameworks. Only SELECT statements, DML with returning clause and some PL/SQL blocks return a cursor that can be fetched by host programs. That cursor, or resultset, is encapsulated in OCILIB by the OCI_Resultset object. So, after any successful call to an OCI_Executexxx() function that executed a fetchable statement or filled output bind variables, the resultset can be retrieved by calling OCI_GetResultset() The creation of a OCI_Resultset object consists in :

• Describing the output columns of the resultset • Allocating memory to hold the content data

OCILIB supports multi-row fetching for increasing performances. Instead of fetching data row by row from the server (that induces lots of roundtrips between the client and the server), the library prefetches data chunk by chunks (default is 20 rows). So, less network traffic and better performances. These mechanisms are completely hidden from the application which fetches the resultset row by row. Once the Resultset handle is retrieved:

• It can be fetched by calling OCI_FetchNext() as long as it returns TRUE. • To retrieve the value of a column, call OCI_GetXXXX() where XXXX is the type of data you want to

fetch. Note: If the column internal data does not match the requested type, OCILIB tries to convert the data when it's possible and throws an error if not. The properties (columns names, types ...) of the resultset are accessible through a set of APIs.

OCI_Connection *cn; OCI_Statement *st; int code; char name[30]; char value[20]; /* ... */ st = OCI_StatementCreate(cn); OCI_Prepare(st, "insert into my_table values(:code, :name, :value)"); OCI_BindInt(st, ":code", &code); OCI_BindString(st, ":name", name, 30); OCI_BindString(st, ":value", value, 20); for (code = 1; code < 1000; code++); { sprintf(name, "name %i", code); sprintf(value, "value %i", code); OCI_Execute(st); } OCI_Commit(cn); /* ... */

Page 20: Ocilib 3.5.0 User Guide

Developing C/C++ Oracle applications with OCILIB

Copyright © 2008-2010 Vincent Rogier – http://www.ocilib.net - Document under GNU Free Documentation License v1.3

20

In this example, OCI_GetRowCount() returns the number of rows fetched so far. Note: you can access the resultset columns values by column name instead of position by calling OCI_GetXXX2() functions. A statement object can be reused as many times as desired. Moreover, it is possible to create multiple statements and fetch them simultaneously, even nested.

Resultset metadata information

It is possible to retrieve metadata information about each column of resultset. To do this:

• OCI_GetColumnCount() returns the number of columns in the resultset • OCI_GetColumn() returns the column object at the given position in the resultset • OCI_GetColumn2() returns the column object from its name in the resultset • All properties of the returned column object are accessible by a series of functions

OCI_GetColumnXXX() where XXX is the property

OCI_Connection *cn; OCI_Statement *st1, *st2; OCI_Resultset *rs; /* ... */ st1 = OCI_StatementCreate(cn); st2 = OCI_StatementCreate(cn); int code; OCI_ExecuteStmt(st1, "select code from my_table"); OCI_Prepare(st2, "delete from my_table2 where code_ref = :code"); OCI_Bind(st2, ":code", &code); rs = OCI_GetResultset(st); while (OCI_FetchNext(rs)) { code = OCI_GetInt(rs, 1); OCI_Execute(st2); }

#include "ocilib.h" int main() { OCI_Connection *cn; OCI_Statement *st; OCI_Resultset *rs; if (!OCI_Initialize(NULL, NULL, OCI_ENV_DEFAULT)) return EXIT_FAILURE; cn = OCI_ConnectionCreate("db", "usr", "pwd", OCI_SESSION_DEFAULT); st = OCI_StatementCreate(cn); OCI_ExecuteStmt(st, "select * from products"); rs = OCI_GetResultset(st); while (OCI_FetchNext(rs)) printf("code: %i, name %s\n", OCI_GetInt(rs, 1) , OCI_GetString(rs, 2)); printf("\n%d row(s) fetched\n", OCI_GetRowCount(rs)); OCI_Cleanup(); return EXIT_SUCCESS; }

Page 21: Ocilib 3.5.0 User Guide

Developing C/C++ Oracle applications with OCILIB

Copyright © 2008-2010 Vincent Rogier – http://www.ocilib.net - Document under GNU Free Documentation License v1.3

21

Implicit conversions

OCI_GetString() performs an implicit conversion from the following datatypes:

• Numerics (based on the current connection handle numeric format) • OCI_Date (based on the current connection handle date format) • OCI_Timestamp (based on the current connection handle date format) • OCI_Interval (based on Oracle default conversion) • OCI_Lob (maximum number of character is defined by OCI_SIZE_BUFFER) • OCI_Long • OCI_File (maximum number of character is defined by OCI_SIZE_BUFFER) • RAW buffer

The following types are not supported for implicit conversion:

• OCI_Statement • OCI_Coll • OCI_Object

#include "ocilib.h" int main() { OCI_Connection *cn; OCI_Statement *st; OCI_Resultset *rs; if (!OCI_Initialize(NULL, NULL, OCI_ENV_DEFAULT)) return EXIT_FAILURE; cn = OCI_ConnectionCreate("db", "usr", pwd", OCI_SESSION_DEFAULT); st = OCI_StatementCreate(cn); OCI_ExecuteStmt(st, "select * from my_table"); rs = OCI_GetResultset(st); nb = OCI_GetColumnCount(rs); for(i = 1; i <= nb; i++) { col = OCI_GetColumn(rs, i); printf("%-20s%-10s%-8i%-8i%-8i%-s\n", OCI_GetColumnName(col), OCI_GetColumnSQLType(col), OCI_GetColumnSize(col), OCI_GetColumnPrecision(col), OCI_GetColumnScale(col), OCI_GetColumnNullable(col) == TRUE ? "Y" : "N"); } OCI_Cleanup(); return EXIT_SUCCESS; }

Page 22: Ocilib 3.5.0 User Guide

Developing C/C++ Oracle applications with OCILIB

Copyright © 2008-2010 Vincent Rogier – http://www.ocilib.net - Document under GNU Free Documentation License v1.3

22

Scrollable statements

OCILIB supports scrollable cursors introduced with Oracle 9i. These cursors (resultsets in OCILIB terms) can be fetched:

• Sequentially in both directions : OCI_FetchPrev() and OCI_FetchPrev() • To a relative position in the resultset : OCI_FetchSeek() with OCI_SFD_RELATIVE • To an absolute position in the resultset : OCI_FetchSeek() with OCI_SFD_ABOSLUTE • To the first or last row in the resultset : OCI_FetchFirst() and OCI_FetchLast()

Scrollable statements use more server and client resources and should only be used when necessary. Resultsets are 'forward only' by default. Call OCI_SetFetchMode() with OCI_SFM_SCROLLABLE to enable scrollable resultsets for a given statement. Warning: Any use of scrollable fetching functions with a resultset that depends on a statement with fetch mode set to OCI_SFM_DEFAULT will fail!

#include "ocilib.h" int main() { OCI_Connection *cn; OCI_Statement *st; OCI_Resultset *rs; if (!OCI_Initialize(NULL, NULL, OCI_ENV_DEFAULT)) return EXIT_FAILURE; cn = OCI_ConnectionCreate("db", "usr", "pwd", OCI_SESSION_DEFAULT); st = OCI_StatementCreate(cn); OCI_SetFetchMode(st, OCI_SFM_SCROLLABLE); OCI_ExecuteStmt(st, "select int_col1, str_col from my_table"); rs = OCI_GetResultset(st); /* get resultset row count */ OCI_FetchLast(rs); printf("resultset contains %i rows\n", OCI_GetRowCount(rs)); /* go to row 1 */ OCI_FetchFirst(rs); printf("%i - %s\n", OCI_GetInt(rs, 1), OCI_GetString(rs, 2)); /* enumerate from row 2 to row X */ while (OCI_FetchNext(rs)) printf("%i - %s\n", OCI_GetInt(rs, 1), OCI_GetString(rs, 2)); /* enumerate from row X back to row 1 */ while (OCI_FetchPrev(rs)) printf("%i - %s\n", OCI_GetInt(rs, 1), OCI_GetString(rs, 2)); /* print the 30th row */ OCI_FetchSeek(rs, OCI_SFD_ABSOLUTE, 30); printf("%i - %s\n", OCI_GetCurrentRow(rs), OCI_GetInt(rs, 1), OCI_GetString(rs, 2)); /* fetch next 30 rows */ while ((OCI_GetCurrentRow(rs) < 60) << OCI_FetchNext(rs)) printf("%0i - %s\n", OCI_GetInt(rs, 1), OCI_GetString(rs, 2)); /* move back to the 45th row */ OCI_FetchSeek(rs, OCI_SFD_RELATIVE, -15); printf("%i - %s\n", OCI_GetInt(rs, 1), OCI_GetString(rs, 2)); OCI_Cleanup(); return EXIT_SUCCESS; }

Page 23: Ocilib 3.5.0 User Guide

Developing C/C++ Oracle applications with OCILIB

Copyright © 2008-2010 Vincent Rogier – http://www.ocilib.net - Document under GNU Free Documentation License v1.3

23

PL/SQL blocks

OCILIB has a strong PL/SQL support:

• Blocks, procedures and function can be used with OCILIB statements. • Ref cursors • Nested tables • Tables (indexed by integer types) • Access to the server side output generated by the DBMS_OUTPUT package

Stored procedures/functions calls, blocks declarations are done like regular SQL calls using OCI_Prepare(), OCI_Execute(), OCI_ExecuteStmt() and OCI_ExecuteStmtFmt() functions. All PL/SQL statements must:

• start with a 'begin' or 'declare' keyword • end with a 'end;' keyword

/* Retrieving a PL/SQL cursor and fetch its results inside a C program : */ #include "ocilib.h" int main() { OCI_Connection *cn; OCI_Statement *st1; *st2; OCI_Resultset *rs; if (!OCI_Initialize(NULL, NULL, OCI_ENV_DEFAULT)) return EXIT_FAILURE; cn = OCI_ConnectionCreate("db", "usr", pwd", OCI_SESSION_DEFAULT); st1 = OCI_StatementCreate(cn); st2 = OCI_StatementCreate(cn); OCI_Prepare(st1, "begin open :c for select * from my_table; end;"); OCI_BindStatement(st2, ":c", st2); OCI_Execute(st1); rs = OCI_GetResultset(st2); while (OCI_FetchNext(rs)) { printf("value %s\n", OCI_GetString(rs, 1)); } OCI_Cleanup(); return EXIT_SUCCESS; }

/* basic PL/SQL call */ OCI_Statement *st; st = OCI_StatementCreate(cn); OCI_Prepare(st, "begin :n := trunc(sysdate+1)-trunc(sysdate-1); end;"); OCI_BindInt(st, ":n", &n); OCI_Execute(st); printf("Result : %i\n", n);

Page 24: Ocilib 3.5.0 User Guide

Developing C/C++ Oracle applications with OCILIB

Copyright © 2008-2010 Vincent Rogier – http://www.ocilib.net - Document under GNU Free Documentation License v1.3

24

Support for SQL RETURNING clause

OCILIB supports the Oracle feature 'Returning into' for DML statements. Let's Oracle talk about this feature: 'Using the RETURNING clause with a DML statement allows you to essentially combine two SQL

statements into one, possibly saving you a server round-trip. This is accomplished by adding an extra

clause to the traditional UPDATE, INSERT, and DELETE statements. The extra clause effectively adds a

query to the DML statement. In the OCI, the values are returned to the application through the use of

OUT bind variables.'

OCILIB implements this features by providing a set of functions that allows registering output placeholders for the returned values. Once the DML is executed with OCI_Execute(), the output returned data is available through a regular resultset object that can be fetched. Array binding interface is also supported with 'returning into' DML statement. Every iteration (or row of given arrays) generates a resultset object. Once a resultset is fetched, the next on can be retrieved with OCI_GetNextResultset(). OCI_Long are not supported for 'returning into' clause .This is a limitation imposed by Oracle. OCI_Column objects retrieved from output OCI_Resultset have the following particularities:

• Their names are the provided bind names to the DML statement (by example, ‘out1’). So any call to the functions OCI_GetXXX2() should be aware of it

• The detailed SQL columns attributes might be not all set or accurate. By example, the scale and precision are not set, the SQL type is the one chosen by OCILIB regarding the OCILIB object datatype and might be slightly different from the real one...

/* Retrieving server output */ #include "ocilib.h" int main(void) { OCI_Connection *cn; OCI_Statement *st; const dtext *p; if (!OCI_Initialize(NULL, NULL, OCI_ENV_DEFAULT)) return EXIT_FAILURE; cn = OCI_ConnectionCreate("db", "usr", "pwd", OCI_SESSION_DEFAULT); st = OCI_StatementCreate(cn); OCI_ServerEnableOutput(cn, 32000, 5, 255); OCI_ExecuteStmt(st, "begin " " dbms_output.put_line('First line'); " " dbms_output.put_line('Second line'); " "end;" ); while (p = OCI_ServerGetOutput(cn)) { printf(%s\n", p); } OCI_Cleanup(); return EXIT_SUCCESS; }

Page 25: Ocilib 3.5.0 User Guide

Developing C/C++ Oracle applications with OCILIB

Copyright © 2008-2010 Vincent Rogier – http://www.ocilib.net - Document under GNU Free Documentation License v1.3

25

Statements extra control

OCILIB offers a range of features to customize the behavior of a statement. For example, you can specify:

• The number of rows pre-fetchées by the Oracle client to reduce the number of roundtrips to the server

• The number of lines fetched internally by OCILIB to reduce calls OIC • The way of linking variables: by position or by name • The date format by default • Etc. ..

#include "ocilib.h" int main() { OCI_Connection *cn; OCI_Statement *st; OCI_Resultset *rs; if (!OCI_Initialize(NULL, NULL, OCI_ENV_DEFAULT)) return EXIT_FAILURE; cn = OCI_ConnectionCreate("db", "usr", "pwd", OCI_SESSION_DEFAULT); st = OCI_CreateStatement(cn); OCI_Prepare(st, "update products set code = code+10 returning code into :i"); OCI_RegisterInt(st, ":i"); OCI_Execute(st); rs = OCI_GetResultset(st); while (OCI_FetchNext(rs)) printf("%i\n", OCI_GetInt(rs, 1)); printf("count : %i\n", OCI_GetRowCount(rs)); OCI_Commit(cn); OCI_Cleanup(); return EXIT_SUCCESS; }

Page 26: Ocilib 3.5.0 User Guide

Developing C/C++ Oracle applications with OCILIB

Copyright © 2008-2010 Vincent Rogier – http://www.ocilib.net - Document under GNU Free Documentation License v1.3

26

6. Bulk Operations

The "bulk operations" are a powerful feature supported by Oracle that can perform mass updates (insert / update / update) of tables in record time. In a classic pattern, if one wishes to insert 1000 rows into a table for example, you can:

• prepare the application • bind variables • loop from 1 to 1000 to run the SQL bearing in each loop updated values.

This scheme will generate 1000 calls for execution of the request and then 1000 return trips to the server:

• Transmitting values • Rerun the SQL

All these calls and return trips are expensive for the network in terms of performance! If you want to insert 1 million rows, it can be long! Oracle proposes a simple solution that achieves optimal performance: OCI Array Interface.

Oracle Array interface

OCILIB supports the OCI array Interface by binding arrays of C scalar types and OCILIB object types.

• all types supported by the library can be used for array binding except OCI_Statement and OCI_Long

• Array binding is really fast for massive DML operations • For string/RAW arrays, the input array MUST BE a contiguous block of data and not an array of

pointers. So to bind an array of 10 elements for a varchar2(30) column, binded variable must be a like array[10][31]

In the preceding example, network traffic generated by a large number of single query executions is the main source of the slow final treatment. Oracle intends to minimize this traffic by providing arrays. Instead of providing 1 variable and send to 1000 times its value to the server, it provides an array of 1000 values that are sent at once. This system reduces the processing time by factors of 3 to 5 digits or more on large volumes. OCILIB supports this mechanism and provides the ability to bind arrays of any type supported by OCILIB (except OCI_Long and OCI_Statement)

Page 27: Ocilib 3.5.0 User Guide

Developing C/C++ Oracle applications with OCILIB

Copyright © 2008-2010 Vincent Rogier – http://www.ocilib.net - Document under GNU Free Documentation License v1.3

27

Example

#include "ocilib.h" int main() { OCI_Connection *cn; OCI_Statement *st; int tab_int[1000]; char tab_str[1000][21]; int i; if (!OCI_Initialize(NULL, NULL, OCI_ENV_DEFAULT)) return EXIT_FAILURE; /* ... create connection and statement ... */ cn = OCI_ConnectionCreate("db", "usr", "pwd", OCI_SESSION_DEFAULT); st = OCI_StatementCreate(cn); /* binding */ OCI_Prepare(st, "insert into products values(:i, :s)"); OCI_BindArraySetSize(st, 1000); OCI_BindArrayOfInts(st, ":i", (int*) tab_int, 0); OCI_BindArrayOfStrings(st, ":s", (char*) tab_str, 20, 0); /* filling arrays */ for(i = 0; i < 1000 ; i++) { tab_int[i] = i+1; sprintf(tab_str[i],"Name %d",i+1); } /* execute */ OCI_Execute(st); printf("row processed : %d\n", OCI_GetAffectedRows(st)); OCI_Commit(cn); OCI_Cleanup(); return EXIT_SUCCESS; }

Page 28: Ocilib 3.5.0 User Guide

Developing C/C++ Oracle applications with OCILIB

Copyright © 2008-2010 Vincent Rogier – http://www.ocilib.net - Document under GNU Free Documentation License v1.3

28

7. Using Larges Objects

Oracle 8 introduced the LOBs (Large Objects) in order to store and manipulate large objects of size (> several GB) to meet the storage needs of large files (multimedia, video, ...) and raw data within the DB. There are basically 2 types of large objects:

• The BLOB / CLOB: objects stored in binary (BLOB) / text (CLOB) • The BFILE: objects not stored in the DB. These are pointers to files accessible by the server (on the

same file system or not) and are manipulated by the client application

OCILIB fully supports these data types. Moreover, OCILIB also supports the old implementation of LOBs: types LONG, RAW and LONG RAW. These types always maintained by Oracle, are the "ancestors" of LOBs and accounted for in earlier versions (up to Oracle 7) the only way to store large volumes (but limited) in the DB. Types LONG are still being widely used in the Oracle databases and applications. Therefore OCILIB provides an API very similar to those of LOBs (while the undercoat OIC LONGWORDs management is very different from LOBs).

Internal Objects (LOBs)

OCILIB encapsulates Lobs by supplying:

• An OCI_Lob C type • A set of really easy APIs to manipulate OCI_Lob objects

OCILIB currently supports 3 types of Lobs :

• BLOB : Binary LOBs (replacement for LONG RAW datatype) • CLOB : Character LOBs (replacement for LONG datatype) • NCLOB : National Character LOBs

OCI_Lob objects can be:

• Created as standalone instances • Used for in/out binding • Retrieved from select statements • Manipulated (copy, append, ...)

Oracle 10g extended lobs by increasing maximum size from 4Go to 128 To. OCILIB, with version 2.1.0, supports now this new limit. For handling sizes and offsets up to 128 To, 64 bit integers are requested. So, a new scalar integer type has been introduced: big_uint (elderly lobsize_t). This type can be a 32 bits or 64 bits integer depending on:

• Compiler support for 64 bits integers (C99 compiler, MS compilers) • Oracle client version

Page 29: Ocilib 3.5.0 User Guide

Developing C/C++ Oracle applications with OCILIB

Copyright © 2008-2010 Vincent Rogier – http://www.ocilib.net - Document under GNU Free Documentation License v1.3

29

big_uint will be a 64 bits integer :

• if the compiler supports it • if OCILIB is build with option OCI_IMPORT_LINKAGE and the Oracle version is >= 10.1 • or OCILIB is build with option OCI_IMPORT_RUNTIME (oracle version is not known at compilation

stage)

#include "ocilib.h" int main() { OCI_Connection *cn; OCI_Statement *st; OCI_Lob *lob1, *lob2; int code, n; if (!OCI_Initialize(NULL, NULL, OCI_ENV_DEFAULT)) return EXIT_FAILURE; cn = OCI_ConnectionCreate("db", "usr", "pwd", OCI_SESSION_DEFAULT); st = OCI_StatementCreate(cn); OCI_ExecuteStmt(st, "select code, content from test_lob for update"); rs = OCI_GetResultset(st); while (OCI_FetchNext(rs)) { code = OCI_GetInt(rs, 1); lob1 = OCI_GetLob(rs, 2); lob2 = OCI_LobCreate(cn, OCI_CLOB); n = OCI_LobWrite(lob1, "Today, ", 7); OCI_LobSeek(lob1, n, OCI_SEEK_SET); n = OCI_LobWrite(lob2, "I'm going to the cinema !", 25); OCI_LobAppendLob(lob1, lob2); OCI_LobSeek(lob1, 0, OCI_SEEK_SET); n = OCI_LobRead(lob1, temp, 100); temp[n] = 0; printf("code: %i, action : %s\n", code, temp); OCI_LobFree(lob2); } printf("\n%d row(s) fetched\n", OCI_GetRowCount(rs)); OCI_Cleanup(); return EXIT_SUCCESS; }

Page 30: Ocilib 3.5.0 User Guide

Developing C/C++ Oracle applications with OCILIB

Copyright © 2008-2010 Vincent Rogier – http://www.ocilib.net - Document under GNU Free Documentation License v1.3

30

Example to insert the contents of a file in a BLOB field in a table:

External Objects (FILEs)

Objects of type FILE (OCI_File) are references to external files in the DB which can be opened for read by the server and the content can be retrieved by the client application. The object files are similar to LOBs and therefore their API is similar except that the files are read-only.

OCILIB encapsulates FILEs by supplying:

• An OCI_File C type • A set of really easy APIs to manipulate OCI_File objects

#include "ocilib.h" int main() { OCI_Connection *cn; OCI_Statement *st; OCI_Lob *lob; FILE *f; unsigned char buffer[1024]; int size; if (!OCI_Initialize(NULL, NULL, OCI_ENV_DEFAULT)) return EXIT_FAILURE; cn = OCI_ConnectionCreate("db", "usr", "pwd", OCI_SESSION_DEFAULT); st = OCI_StatementCreate(cn); f = fopen("My file", "rb"); if (f != NULL) { fseek (f , 0 , SEEK_END); size = ftell(f); rewind (f); printf("\nTotal bytes to write : %d\n", size); lob = OCI_LobCreate(cn, OCI_BLOB); OCI_Prepare(st, "insert into my_blob_table(code, content) values (1, :data)"); OCI_BindLob(st, ":data", lob); OCI_Execute(st); /* write data into table by chunks of 1024 bytes */ while ((n = fread(buffer, 1, sizeof(buffer), f))) { OCI_LobWrite(lg, buffer, n); } printf("\nTotal bytes written : %s\n", OCI_LobGetLenght(lob)); fclose(f); OCI_Commit(cn); OCI_LobFree(lob); } OCI_Cleanup(); return EXIT_SUCCESS; }

Page 31: Ocilib 3.5.0 User Guide

Developing C/C++ Oracle applications with OCILIB

Copyright © 2008-2010 Vincent Rogier – http://www.ocilib.net - Document under GNU Free Documentation License v1.3

31

OCILIB currently supports 2 types of FILEs:

• BFILE : Binary files • CFILE : Character files

Warning: FILEs are read-only.

#include "ocilib.h" int main() { OCI_Connection *cn; OCI_Statement *st; OCI_File *file; char buffer[256]; int n; if (!OCI_Initialize(err_handler, NULL, OCI_ENV_DEFAULT)) return EXIT_FAILURE; cn = OCI_ConnectionCreate("db", "usr", "pwd", OCI_SESSION_DEFAULT); st = OCI_StatementCreate(cn); file = OCI_FileCreate(cn, OCI_CFILE); OCI_FileSetName(file, "MYDIR", "MyfileName"); /* check if faile exists */ if (OCI_FileExists(file)) { printf("file size : %d\n", OCI_FileGetSize(file)); printf("file dir : %s\n", OCI_FileGetDirectory(file)); printf("file name : %s\n", OCI_FileGetName(file)); } /* bind for inserting into table */ OCI_Prepare(st, "insert into my_bfile_table(code, value) values (1, :bfile)"); OCI_BindFile(st, ":bfile", file); OCI_Execute(st); OCI_Commit(cn); /* free local file object */ OCI_FileFree(file), /* fetch bfile data from table */ OCI_ExecuteStmt(st, "select code, value from my_bfile_table"); rs = OCI_GetResultset(st); while (OCI_FetchNext(rs)) { file = OCI_GetFile(rs, 2); OCI_FileOpen(file); printf("file size %d\n", OCI_FileGetSize(file)); printf("file dir %s\n", OCI_FileGetDirectory(file)); printf("file name %s\n", OCI_FileGetName(file)); while (n = OCI_FileRead(file, buffer, sizeof(buffer)-1)) { buffer[n] = 0; printf(buffer); } OCI_FileClose(file); } OCI_Cleanup(); return EXIT_SUCCESS; }

Page 32: Ocilib 3.5.0 User Guide

Developing C/C++ Oracle applications with OCILIB

Copyright © 2008-2010 Vincent Rogier – http://www.ocilib.net - Document under GNU Free Documentation License v1.3

32

Long Objects

OCILIB implements the "old" Long (OCI_Long *) similarly to LOBs and files. The APIs for handling LONGWORDs fields are very close to those of Large Objects. Long Objects encapsulate Oracle LONGs datatypes and were used to store large buffers in Oracle database. They're still supported but are depreciated. Oracle now provides a newer and better way to deal with data that needs large storage: LOBs OCILIB supports this datatype because it was and still is widely used OCILIB provides a set of API for manipulating LONGs that is really close to the one provided for LOBs. OCILIB currently supports 3 types of Long Objects:

• OCI_BLONG : LONG RAW columns • OCI_CLONG : LONG columns

OCI_Long objects can be:

• Created as standalone instances • Used for in/out binding • Retrieved from select statement

Page 33: Ocilib 3.5.0 User Guide

Developing C/C++ Oracle applications with OCILIB

Copyright © 2008-2010 Vincent Rogier – http://www.ocilib.net - Document under GNU Free Documentation License v1.3

33

#include "ocilib.h" #define FILENAME "data.lst" int main() { OCI_Connection *cn; OCI_Statement *st; OCI_Long *lg; FILE *f; char buffer[2048]; int n; if (!OCI_Initialize(NULL, NULL, OCI_ENV_DEFAULT)) return EXIT_FAILURE; cn = OCI_ConnectionCreate("db", "usr", "pwd", OCI_SESSION_DEFAULT); st = OCI_StatementCreate(cn); /* INSERT LONGS -------------------------------------------- */ f = fopen(FILENAME, "rb"); if (f) { fseek (f , 0 , SEEK_END); n = ftell(f); rewind (f); printf("\n%d bytes to write\n", n); lg = OCI_LongCreate(st, OCI_BLONG); OCI_Prepare(st, "insert into test_long_raw(code, content) values (1, :data)"); OCI_BindLong(st, ":data", lg, n); OCI_Execute(st); /* write data into table by chunks of 2048 bytes */ while ((n = fread(buffer, 1, sizeof(buffer), f))) { OCI_LongWrite(lg, buffer, n); } printf("\n%d bytes written\n", OCI_LongGetSize(lg)); fclose(f); OCI_LongFree(lg); OCI_Commit(cn); } /* FETCHING LONGS -------------------------------------------- */ OCI_ExecuteStmt(st, "select content from test_long_raw where code = 1"); OCI_SetLongMaxSize(st, 1000000); rs = OCI_GetResultset(st); /* read data by chunks of 2048 bytes*/ while (OCI_FetchNext(rs)) { lg = OCI_GetLong(rs, 1); while ((n = OCI_LongRead(lg, buffer, sizeof(buffer)))) {} printf("\n%d bytes read\n", OCI_LongGetSize(lg)); } OCI_Cleanup(); return EXIT_SUCCESS; }

Page 34: Ocilib 3.5.0 User Guide

Developing C/C++ Oracle applications with OCILIB

Copyright © 2008-2010 Vincent Rogier – http://www.ocilib.net - Document under GNU Free Documentation License v1.3

34

8. Using dates and timestamps

Date handles

OCILIB can manipulate Oracle dates (day / hour) with ease. Example where a date is retrieved from a table and displayed, incremented by 5 days and 2 months and then redisplayed:

Timestamp handles

The timestamps are extensions to the type DATE:

• manage precise dates through the management of fractions of seconds • manage time zones

Example where the date / time is retrieved from the server and displayed with fractional seconds:

#include "ocilib.h" int main() { OCI_Connection *cn; OCI_Statement *st; OCI_Date *dt; char str[100]; int n; if (!OCI_Initialize(NULL, NULL, OCI_ENV_DEFAULT)) return EXIT_FAILURE; cn = OCI_ConnectionCreate("db", "usr", "pwd", OCI_SESSION_DEFAULT); st = OCI_StatementCreate(cn); OCI_ExecuteStmt(st, "select mon_champs_date from my_table"); rs = OCI_GetResultset(st); while (OCI_FetchNext(rs)) { dt = OCI_GetDate(rs, 1); OCI_DateToText(dt, "DD/MM/YYYY HH24:MI:SS", sizeof(str)-1, str); printf("Date is %s\n", str); OCI_DateAddDays(dt, 5); OCI_DateAddMonths(dt, 2); OCI_DateToText(dt, "DD/MM/YYYY HH24:MI:SS", sizeof(str)-1, str); printf("Date + 5 days and 2 months is %s\n", str); } OCI_Cleanup(); return EXIT_SUCCESS; }

Page 35: Ocilib 3.5.0 User Guide

Developing C/C++ Oracle applications with OCILIB

Copyright © 2008-2010 Vincent Rogier – http://www.ocilib.net - Document under GNU Free Documentation License v1.3

35

Interval handles

The intervals are periods of time expressed:

• in years and months • in days, hours, minutes and seconds

They can perform operations on timestamps. Example where the date / time is retrieved from local variable tm, then incremented by 1 day, 1 hour, 1 minute and 1 seconds and then displayed with fractional seconds:

#include "ocilib.h" #define SIZE_STR 260 int main() { OCI_Timestamp *tm; OCI_Interval *itv; if (!OCI_Initialize(NULL, NULL, OCI_ENV_DEFAULT)) return EXIT_FAILURE; tm = OCI_TimestampCreate(NULL, OCI_TIMESTAMP); itv = OCI_IntervalCreate(NULL, OCI_INTERVAL_DS); OCI_TimestampSysTimeStamp(tm); OCI_TimestampToText(tm, "DD/MM/YYYY HH24:MI:SS:FF3", SIZE_STR, str, 3); printf("%s\n", str); OCI_IntervalSetDaySecond(itv, 1,1,1,1,0); OCI_IntervalToText(itv, 10, 10, SIZE_STR, str); printf("%s\n", str); OCI_TimestampIntervalAdd(tm, itv); OCI_TimestampToText(tm, "DD/MM/YYYY HH24:MI:SS:FF3", SIZE_STR, str, 3); printf("%s\n", str); OCI_TimestampFree(tm); OCI_IntervalFree(itv); OCI_Cleanup(); return EXIT_SUCCESS; }

#include "ocilib.h" int main() { OCI_Connection *cn; OCI_Statement *st; OCI_Timestamp *tm; char str[100]; int n; if (!OCI_Initialize(NULL, NULL, OCI_ENV_DEFAULT)) return EXIT_FAILURE; cn = OCI_ConnectionCreate("db", "usr", "pwd", OCI_SESSION_DEFAULT); st = OCI_StatementCreate(cn); OCI_ExecuteStmt(st, "SELECT CURRENT_TIMESTAMP FROM dual"); rs = OCI_GetResultset(st); OCI_FetchNext(rs); tm = OCI_GetTimestamp(rs, 1); OCI_TimestampToText(tm, "DD/MM/YYYY HH24:MI:SS:FF3\n", 100, str, 3); printf(str); OCI_Cleanup(); return EXIT_SUCCESS; }

Page 36: Ocilib 3.5.0 User Guide

Developing C/C++ Oracle applications with OCILIB

Copyright © 2008-2010 Vincent Rogier – http://www.ocilib.net - Document under GNU Free Documentation License v1.3

36

9. Using Oracle objects (U.D.T. / Named Types)

OCILIB supports the "Named types", i.e. data types named by the user created or supplied by Oracle. A "TYPE" Oracle is seen as equivalent to a C structure. This is an aggregation of fields of scalar or aggregated types.

OCILIB implements Oracle Named types (user types and built-in types) through the OCI_Object type. OTT and C structures are not required to use objects in OCILIB. In order to manipulate objects attributes, OCILIB proposes a set of functions to get/set properties for various supported types. Objects can be:

• Created as standalone instances (transient objects) • Used for binding (persistent / transient objects) • Retrieved from select statements (persistent / embedded objects)

References (Oracle type REF) are identifiers (smart pointers) to objects and are implemented in OCILIB with the type OCI_Ref. OCILIB implements Oracle REFs as strong typed Reference (underlying OCI REFs are weaker in terms of typing). It means it's mandatory to provide type information to:

• create a local OCI_Ref handle. • register an OCI_Ref handle for a 'returning into' clause.

Note: See Oracle Database SQL Language Reference for more details about REF datatype

create type t_produit as object ( code number, libelle varchar2(30), prix number(5,3), reference varchar2(100) ); create table ventes_produits ( product t_produit, nombre int, date_vente date );

Page 37: Ocilib 3.5.0 User Guide

Developing C/C++ Oracle applications with OCILIB

Copyright © 2008-2010 Vincent Rogier – http://www.ocilib.net - Document under GNU Free Documentation License v1.3

37

Autonomous Instances

To create an autonomous instance, you first, must get a descriptor. This is achieved by a call to OCI_TypeInfoGet().

Selecting objects

Objects can be selected in the same way as the SQL data types.

#include "ocilib.h" int main() { OCI_Connection *cn; OCI_Statement *st; OCI_Resultset *rs; OCI_Object *prod; OCI_Date *date; int qte; if (!OCI_Initialize(NULL, NULL, OCI_ENV_DEFAULT)) return EXIT_FAILURE; cn = OCI_ConnectionCreate("db", "usr", "pwd", OCI_SESSION_DEFAULT); st = OCI_StatementCreate(cn); OCI_ExecuteStmt(st, "select * from ventes_produits"); rs = OCI_GetResultset(st); while (OCI_FetchNext(rs)) { prod = OCI_GetObject(rs, 1); qte = OCI_GeInt(rs, 2); date = OCI_GetDate(rs, 3); printf("Produit : %s, Ventes : %i\n", OCI_ObjectGetString(prod, "LIBELLE"), qte); } OCI_Cleanup(); return EXIT_SUCCESS; }

#include "ocilib.h" int main() { OCI_Connection *cn; OCI_Statement *st; OCI_Resultset *rs; OCI_Object *prod; OCI_Date *date; int qte; if (!OCI_Initialize(NULL, NULL, OCI_ENV_DEFAULT)) return EXIT_FAILURE; cn = OCI_ConnectionCreate("db", "usr", "pwd", OCI_SESSION_DEFAULT); st = OCI_StatementCreate(cn); prod = OCI_ObjectCreate(cn, OCI_TypeInfoGet(cn, "t_product", OCI_TIF_TYPE); date = OCI_DateCreate(cn); qte = 356; OCI_DateSysDate(date); OCI_ObjectSetInt(prod, "CODE", 1); OCI_ObjectSetString(prod, "LIBELLE", "USB KEY 2go"); OCI_ObjectSetDouble(prod, "PRIX", 12.99); OCI_ObjectSetString(prod, "REFERENCE", "A56547WSAA"); OCI_Prepare(st, "insert into ventes_produits values(:p, :n, :d)"); OCI_BindObject(st, ":p", prod); OCI_BindInt(st, ":n", &qte); OCI_BindDate(st, ":d", date); OCI_Execute(st); printf("\n%d row(s) inserted\n", OCI_GetAffectedRows(st)); OCI_Commit(cn); OCI_ObjectFree(obj); OCI_Cleanup(); return EXIT_SUCCESS; }

Page 38: Ocilib 3.5.0 User Guide

Developing C/C++ Oracle applications with OCILIB

Copyright © 2008-2010 Vincent Rogier – http://www.ocilib.net - Document under GNU Free Documentation License v1.3

38

10. Using Oracle Collections

Collections types

OCILIB supports all Oracle collections:

• PL/SQL Tables: only available in PL/SQL, unbounded, sparse arrays of homogeneous elements. • Varrays: available in SQL and PL/SQL, they are bounded arrays of homogeneous elements • Nested Tables: available in SQL and PL/SQL, they are unbounded arrays of homogeneous elements

and can become sparse through deletions PL/SQL tables are implemented by binding regular C arrays with the array interface (using OCI_BindArrayOfXXX() calls) Varrays and Nested tables are implemented in OCILIB with the type OCI_Coll. It's possible to bind and fetch Varrays and Nested tables using OCI_Coll handle. It's also possible to declare local collections based on some database type without using queries OCI (and thus OCILIB) offers the possibility to access collection elements:

• directly by index (OCI_CollGetAt() and OCI_CollSetAt()) • using an iterator (OCI_Iter) to iterate through the collection (OCI_IterGetNext(),

OCI_IterGetPrev()) Collection Items are implemented through the type OCI_Elem and use the series of calls OCI_ElemGetXXX() and OCI_ElemSetXXX() to manipulate elements content values

Example

Page 39: Ocilib 3.5.0 User Guide

Developing C/C++ Oracle applications with OCILIB

Copyright © 2008-2010 Vincent Rogier – http://www.ocilib.net - Document under GNU Free Documentation License v1.3

39

#include "ocilib.h" int main(void) { OCI_Connection *cn; OCI_Statement *st; OCI_Resultset *rs; OCI_Coll *coll; OCI_Iter *iter; OCI_Elem *elem; OCI_TypeInfo *type; OCI_Object *obj; int i, n; if (!OCI_Initialize(NULL, NULL, OCI_ENV_DEFAULT)) return EXIT_FAILURE; cn = OCI_ConnectionCreate("db", "usr", "pwd", OCI_SESSION_DEFAULT); /* Varray binding -------------------------------------------------------- */ st = OCI_StatementCreate(cn); /* create the collection */ type = OCI_TypeInfoGet(cn, "Varray_type", OCI_TIF_TYPE); coll = OCI_CollCreate(type); /* bind the local collection to a PL/SQL procedure */ OCI_Prepare(st, "begin load_array(:array); end;"); OCI_BindColl(st, ":array", coll); OCI_Execute(st); /* the procedure has filled the collection and we can iterate it using an iterator */ iter = OCI_IterCreate(coll); elem = OCI_IterGetNext(iter); while (elem != NULL) { printf("value %s\n", OCI_ElemGetString(elem)); elem = OCI_IterGetNext(iter); } OCI_IterFree(iter); OCI_CollFree(coll); /* Varray SQL fetch ------------------------------------------------------- */ /* query on a table with varray column */ OCI_ExecuteStmt(st, "SELECT * from table_article"); rs = OCI_GetResultset(st); while (OCI_FetchNext(rs)) { /* iterate the collection using an iterator */ coll = OCI_GetColl(rs, 2); iter = OCI_IterCreate(coll); elem = OCI_IterGetNext(iter); printf("article #%d\n", OCI_GetInt(rs, 1)); while (elem != NULL) { obj = OCI_ElemGetObject(elem); printf(".... code %d, name%s \n", OCI_ObjectGetInt(obj, "ID"), OCI_ObjectGetString(obj, "NAME")); elem = OCI_IterGetNext(iter); } OCI_IterFree(iter); } /* Nested table fetch ------------------------------------------------------- */ /* query on a table with nested table column */ OCI_ExecuteStmt(st, "SELECT * from table_sales"); rs = OCI_GetResultset(st); while (OCI_FetchNext(rs)) { coll = OCI_GetColl(rs, 2); printf("Sale #%d\n", OCI_GetInt(rs, 1)); /* iterate the collection by accessing element by index */ n = OCI_CollGetSize(coll); for(i = 1; i <= n; i++) { elem = OCI_CollGetAt(coll, i); obj = OCI_ElemGetObject(elem); printf(".... employee %s, amount %s \n", OCI_ObjectGetString(obj, "EMP"), OCI_ObjectGetString(obj, "AMOUNT")); } } OCI_Cleanup(); return EXIT_SUCCESS; }

Page 40: Ocilib 3.5.0 User Guide

Developing C/C++ Oracle applications with OCILIB

Copyright © 2008-2010 Vincent Rogier – http://www.ocilib.net - Document under GNU Free Documentation License v1.3

40

11. Loading data with Direct Path mode

Oracle Direct Path Loading

Oracle provides an API to load data directly into the tables without using the SQL engine. OCILIB (from version 3.2.0) support the OCI direct Path API. Actual implementation of direct path API does not support the following elements:

• Objects datatypes (User Defined Types and Object References) • Object tables • Nested tables • SQL String functions

All scalar datatypes (numerics, characters and date/time), including LOBs and LONG types are supported Oracle direct API features (from Oracle Documentation) : “The direct path load interface allows an application to access the direct path load engine of the Oracle

database server to perform the functions of the Oracle SQL*Loader utility. This functionality provides the

ability to load data from external files into Oracle database objects, either a table or a partition of a

partitioned table. The OCI direct path load interface has the ability to load multiple rows by loading a

direct path stream which contains data for multiple rows.”

Oracle direct API limitation (from Oracle Documentation) “The direct path load interface has the following limitations which are the same as SQL*Loader:

• triggers are not supported

• check constraints are not supported

• referential integrity constraints are not supported

• clustered tables are not supported

• loading of remote objects is not supported

• user-defined types are not supported

• LOBs must be specified after all scalar columns

• LONGs must be specified last”

Warning: It is recommended to use direct path interface with an Oracle client that is the same version than the database. With version < 10g, it is mandatory regarding that it causes segmentation faults and it's known from Oracle that advices to use the same version for client and server (see metalink KB) How to use direct path:

1. Create a direct path handle with OCI_DirPathCreate() 2. Set (optional) some direct path load attributes 3. Describe the columns to load with OCI_DirPathSetColumn() 4. Populate data with OCI_DirPathSetEntry() 5. Convert the data with OCI_DirPathConvert() 6. Load the data into the database with OCI_DirPathLoad() 7. Repeat step 4,5,6 + reset the stream with OCI_DirPathReset() until all rows has been loaded 8. Commit the load with OCI_DirPathFinish() 9. Free the direct path handle with OCI_DirPathFree()

Page 41: Ocilib 3.5.0 User Guide

Developing C/C++ Oracle applications with OCILIB

Copyright © 2008-2010 Vincent Rogier – http://www.ocilib.net - Document under GNU Free Documentation License v1.3

41

Example

#include "ocilib.h" #define SIZE_ARRAY 1000 #define SIZE_COL1 20 #define SIZE_COL2 30 #define SIZE_COL3 8 #define NUM_COLS 3 int main(void) { OCI_Connection *cn; OCI_DirPath *dp; OCI_TypeInfo *tbl; dtext val1[SIZE_COL1+1]; dtext val2[SIZE_COL2+1]; dtext val3[SIZE_COL3+1]; int i = 0, nb_rows = SIZE_ARRAY; if (!OCI_Initialize(NULL, NULL, OCI_ENV_DEFAULT)) return EXIT_FAILURE; cn = OCI_ConnectionCreate("db", "usr", "pwd", OCI_SESSION_DEFAULT); tbl = OCI_TypeInfoGet(cn, "test_directpath", OCI_TIF_TABLE); dp = OCI_DirPathCreate(tbl, NULL, NUM_COLS, nb_rows); /* optional attributes to set */ OCI_DirPathSetBufferSize(dp, 64000); OCI_DirPathSetNoLog(dp, TRUE); OCI_DirPathSetParallel(dp, TRUE); /* describe the target table */ OCI_DirPathSetColumn(dp, 1, "VAL_INT", SIZE_COL1, NULL); OCI_DirPathSetColumn(dp, 2, "VAL_STR", SIZE_COL2, NULL); OCI_DirPathSetColumn(dp, 3, "VAL_DATE", SIZE_COL3, "YYYYMMDD"); /* prepare the load */ OCI_DirPathPrepare(dp); nb_rows = OCI_DirPathGetMaxRows(dp); for (i = 1; i <= nb_rows; i++) { /* fill test values */ sprint_dt(val1, SIZE_COL1+1, "%04d", i); sprint_dt(val2, SIZE_COL2+1, "value %05d", i); sprint_dt(val3, SIZE_COL3+1, "%04d%02d%02d", (i%23)+1 + 2000, (i%11)+1, (i%23)+1); OCI_DirPathSetEntry(dp, i, 1, val1, (unsigned int) strlen(val1), TRUE); OCI_DirPathSetEntry(dp, i, 2, val2, (unsigned int) strlen(val2), TRUE); OCI_DirPathSetEntry(dp, i, 3, val3, (unsigned int) strlen(val3), TRUE); } /* load data to the server */ OCI_DirPathConvert(dp); OCI_DirPathLoad(dp); /* commits changes */ OCI_DirPathFinish(dp); printf("%04d row(s) processed\n", OCI_DirPathGetAffectedRows(dp)); printf("%04d row(s) loaded\n", OCI_DirPathGetRowCount(dp)); /* free direct path object */ OCI_DirPathFree(dp); OCI_Cleanup(); return EXIT_SUCCESS; }

Page 42: Ocilib 3.5.0 User Guide

Developing C/C++ Oracle applications with OCILIB

Copyright © 2008-2010 Vincent Rogier – http://www.ocilib.net - Document under GNU Free Documentation License v1.3

42

12. Advanced features

Describing tables in a schema

Functions '"All In One"

OCILIB provides functions "all in one" with a list of variable arguments. They reduce the number of lines of code to a minimum! For example, OCILIB can write in only 1 line of code following actions:

• Preparing SQL • Binding a variable • Query Execution • Fetch the result (1 row)

#include "ocilib.h" int main() { OCI_Connection *cn; OCI_TypeInfo *tbl; int n; if (!OCI_Initialize(NULL, NULL, OCI_ENV_DEFAULT)) return EXIT_FAILURE; cn = OCI_ConnectionCreate("db", "usr", "pwd", OCI_SESSION_DEFAULT); tbl = OCI_TypeInfoGet(cn, "MyTable", OCI_TIF_TABLE); if (tbl) { printf ("Column Name Type Length Prec. Scale Null ?\n"); printf ("---------------------------- ------------------------------\n"); n = OCI_TypeInfoGetColumnCount(tbl); for(i = 1; i <= n; i++) { col = OCI_TypeInfoGetColumntbl, i); printf("%-20s%-10s%-8i%-8i%-8i%-s\n", OCI_ColumnGetName(col), OCI_ColumnGetSQLType(col), OCI_ColumnGetSize(col), OCI_ColumnGetPrecision(col), OCI_ColumnGetScale(col), OCI_ColumnGetNullable(col) == TRUE ? "Y" : "N"); } } } OCI_Cleanup(); return EXIT_SUCCESS; }

Page 43: Ocilib 3.5.0 User Guide

Developing C/C++ Oracle applications with OCILIB

Copyright © 2008-2010 Vincent Rogier – http://www.ocilib.net - Document under GNU Free Documentation License v1.3

43

This is equivalent to the following code:

• OCI_Prepare (st, "select item from test_fetch where code =: i"); • OCI_Bind (st, "code", & code); • OCI_execute (st); • OCI_GetResultset (st); • OCI_FetchNext (rs); • OCI_GetString (rs, 1);

Which can be replaced by the following code:

• OCI_ImmediateFmt (cn, "select item from test_fetch where code =% i", code, OCI_ARG_TEXT, name);

OCILIB offers some smart routines that take a variable number of arguments in order to minimize OCILIB function calls and reduce the amount of code lines. On Windows platforms, the target programming language must support the __cdecl calling convention Note: OCI_Immediate() and OCI_ImmediateFmt() support all OCILIB supported types for output result, except :

• OCI_Long • OCI_Statement If a query output result contains one of these unsupported types, the function

returns FALSE In the parameter list, every output placeholder MUST be preceded by an integer parameter that indicates the type of the placeholder in order to handle correctly the given pointer. Possible values for indicating placeholders type:

• OCI_ARG_SHORT : short * • OCI_ARG_USHORT : unsigned short * • OCI_ARG_INT : int * • OCI_ARG_UINT : unsigned int* • OCI_ARG_BIGINT : big_int * • OCI_ARG_BIGUINT : unsigned big_int * • OCI_ARG_DOUBLE : double * • OCI_ARG_TEXT : dtext * • OCI_ARG_RAW : void * • OCI_ARG_DATETIME : OCI_Date * • OCI_ARG_LOB : OCI_Lob * • OCI_ARG_FILE : OCI_File * • OCI_ARG_TIMESTAMP : OCI_Timstamp * • OCI_ARG_INTERVAL : OCI_Interval * • OCI_ARG_OBJECT : OCI_Object * • OCI_ARG_COLLECTION : OCI_Coll * • OCI_ARG_REF : OCI_Ref *

For output strings and Raws, returned data is copied to the given buffer instead of returning a pointer the real data. So theses buffers must be big enough to hold the column content. No size check is performed.

• For strings, only the real string is copied. • For Raws, the number of bytes copied is the column size

Warning: Input parameters for formatted function only support a restricted set of datatypes!

Page 44: Ocilib 3.5.0 User Guide

Developing C/C++ Oracle applications with OCILIB

Copyright © 2008-2010 Vincent Rogier – http://www.ocilib.net - Document under GNU Free Documentation License v1.3

44

Supported input identifiers:

• * 's' : (dtext *) : input string (quotes are added) • * 'm' : (dtext *) : metadata string (no quotes added) • * 't' : (OCI_Date *) : Date • * 'p' : (OCI_Timestamp *) : timestamp • * 'v' : (OCI_Interval *) : Interval • * 'i' : (int) : signed 32 bits integer • * 'u' : (unsigned int) : unsigned 32 bits integer • * 'li' : (big_int) : signed 64 bits integer • * 'lu' : (big_uint) : unsigned 64 bits integer • * 'hi' : (short) : signed 16 bits integer • * 'hu' : (unsigned short) : unsigned 16 bits integer • * 'g' : (double ) : Numerics • * 'r' : (OCI_Ref *) : Reference • * 'o' : (OCI_Object *) : Object (not implemented yet) • * 'c' : (OCI_Coll *) : collection (not implemented yet)

Other examples:

#include "ocilib.h" int main() { OCI_Connection *cn; OCI_Statement *st; OCI_Resultset *rs; int code = 1; char name[50]; if (!OCI_Initialize(err_handler, NULL, OCI_ENV_DEFAULT)) return EXIT_FAILURE; cn = OCI_ConnectionCreate("db", "usr", "pwd", OCI_SESSION_DEFAULT); st = OCI_StatementCreate(cn); /* sql format with params ----------------------------------------------- */ OCI_ExecuteStmtFmt(st, "select article from test_fetch where code = %i", code); rs = OCI_GetResultset(st); while (OCI_FetchNext(rs)) printf("article : %s\n", OCI_GetString(rs, 1)); /* sql immediate (parse, exec, one fetch) ------------------------------- */ OCI_Immediate(cn, "select code, article from test_fetch where code = 1", OCI_ARG_INT, &code, OCI_ARG_TEXT, name); printf("article : %s - code %i\n", name, code); /* sql immediate (parse, exec, one fetch) with params ------------------- */ OCI_ImmediateFmt(cn, "select article from test_fetch where code = %i", code, OCI_ARG_TEXT, name); printf("article : %s\n", name); OCI_Cleanup(); return EXIT_SUCCESS; }

Page 45: Ocilib 3.5.0 User Guide

Developing C/C++ Oracle applications with OCILIB

Copyright © 2008-2010 Vincent Rogier – http://www.ocilib.net - Document under GNU Free Documentation License v1.3

45

Optimizing performances

Some tips to optimize the performance:

• Avoid OCI_xxxFmt function() because, although very useful, they require a parsing of the SQL and formatting of variables that can be costly if the queries are executed many times

• If a SQL statement must be repeated several times, it is preferable to prepare once with OCI_Prepare(), bind variables with OCI_Bindxxx() and then run it as many times as desired with OCI_Exectute()

• If possible, use tables to bind variables • If the values affected by a DML must then be reselected, use clause "Returning into" • Adjust the number of rows per fetch with OCI_SetFetchSize() • Adjust the number of lines préfetchées by the server with OCI_SetPrefetchSize() • Prefer to Lobs LONG and LONG RAW • To retrieve values from a resultet use access by index instead of access by column name to avoid

the use of maps index / name

Using OCILIB hash tables API

OCILIB uses hash tables internally for index/name columns mapping. OCILIB makes public its hash tables implementation public for general purpose uses. OCI_HashTable objects manage string keys / values that can be :

• integers • strings • pointers

This hash table implementation:

• handle collisions • allows multiple values per key

Internal conception

• The hash table is composed of an array of slots. • Each slot can hold a linked list of entries (one per key) • Each entry can hold a linked list of values

The internal hash function computes the index in the array where the entry has to be inserted/looked up. Collisions are handled by chaining method.

Page 46: Ocilib 3.5.0 User Guide

Developing C/C++ Oracle applications with OCILIB

Copyright © 2008-2010 Vincent Rogier – http://www.ocilib.net - Document under GNU Free Documentation License v1.3

46

Using OCILIB thread API

Oracle proposes a portable implementation of Mutex and Thread objects OCILIB implements these OCI features for portable multithreading support. Mutexes are designed for mutual exclusion between thread in order to lock resources temporarily Thread keys can be seen as process-wide variables that have thread-specific values. It allows creating a unique key identified by a name (string) that can store values specific to each thread. OCILIB exposes the types OCI_Mutex, OCI_Thread

#include "ocilib.h" int main(void) { int i, n; OCI_Connection *cn; OCI_Statement *st; OCI_Resultset *rs; OCI_HashTable *table; OCI_HashEntry *e; OCI_HashValue *v; if (!OCI_Initialize(NULL, NULL, OCI_ENV_DEFAULT)) return EXIT_FAILURE; cn = OCI_ConnectionCreate("db", "usr", "pwd", OCI_SESSION_DEFAULT); st = OCI_StatementCreate(cn); table = OCI_HashCreate(256, OCI_HASH_INTEGER); /* fill the hash table with data from DB */ OCI_ExecuteStmt(st, "select code, name from products"); rs = OCI_GetResultset(st); while (OCI_FetchNext(rs)) OCI_HashAddInt(table, OCI_GetString2(rs, "name"), OCI_GetInt2(rs, "code")); printf("%d row(s) fetched\n", OCI_GetRowCount(rs)); /* lookup an entry */ printf("code for %s is : %d\n", "Cars", OCI_HashGetInt(table, "Cars")); /* browse the hash table */ n = OCI_HashGetSize(table); for (i = 0; i < n; i++) { e = OCI_HashGetEntry(table, i); while (e != NULL) { printf (">key: '%s'\n", e->key); v = e->values; while (v != NULL) { printf ("..... value : '%i'\n", v->value.num); v = v->next; } e = e->next; } } /* destroy table */ OCI_HashFree(table); OCI_Cleanup(); return EXIT_SUCCESS; }

Page 47: Ocilib 3.5.0 User Guide

Developing C/C++ Oracle applications with OCILIB

Copyright © 2008-2010 Vincent Rogier – http://www.ocilib.net - Document under GNU Free Documentation License v1.3

47

Warning:

• OCILIB MUST be initialized with OCI_ENV_THREADED to enable threads support • OCI_Thread relies on Oracle API which uses natives threading capabilities of the supported

platform Using OCI_Mutex :

• On Microsoft Windows, a thread can call OCI_MutexAcquire() more than once wihtout any blocking. Just be sure that there is an OCI_MutexRelease() for every OCI_MutexAcquire() call

• On Unixes, a thread MUST call OCI_MutexRelease() after every call to OCI_MutexAcquire() in order to be able to call OCI_MutexAcquire() again. If not, it will be blocked...

#include "ocilib.h" #define MAX_THREADS 50 void key_cleanup(void *str) { free(str); } void worker(OCI_Thread *thread, void *data) { const void *id = OCI_HandleGetThreadID(thread); char *str = malloc(50); sprintf(str, "thread %p !\n", id); OCI_ThreadKeySetValue("ID", str); /* ... do some more processing here... */ str = OCI_ThreadKeyGetValue("ID"); printf(str); } int main(void) { OCI_Thread *th[MAX_THREADS]; int i; if (!OCI_Initialize(NULL, NULL, OCI_ENV_DEFAULT | OCI_ENV_THREADED)) return EXIT_FAILURE; OCI_ThreadKeyCreate("ID", key_cleanup); /* create threads */ for (i = 0; i < MAX_THREADS; i++) { th[i] = OCI_ThreadCreate(); OCI_ThreadRun(th[i], worker, NULL); } /* wait for threads and cleanup */ for (i = 0; i < MAX_THREADS; i++) { OCI_ThreadJoin(th[i]); OCI_ThreadFree(th[i]); } OCI_Cleanup(); return EXIT_SUCCESS; }

Page 48: Ocilib 3.5.0 User Guide

Developing C/C++ Oracle applications with OCILIB

Copyright © 2008-2010 Vincent Rogier – http://www.ocilib.net - Document under GNU Free Documentation License v1.3

48

Remote database startup/shutdown

OCILIB supports Oracle 11g client features for manipulating remote Oracle instances. Oracle instances (on the same computer or on a remote server) can be

• started with OCI_DatabaseStartup() • Shutdown with OCI_DatabaseShutdown()

Database change notifications

OCILIB supports Oracle 10gR2 feature Database Change Notifications (DCN) also named Continuous Query Notifications (CQN) This feature allows a client application to register notifications when some changes are made in a database:

• Database status changes: startup and shutdown • Database objects changes:

� DDL changes : alter or drop actions � DML changes : insert, delete, update actions

This feature can be really useful in applications that hold a cache of data. Instead of refreshing data periodically by connecting to the server, the application could only refresh modified data when necessary or perform specific tasks depending on the events. It saves application time, network traffic and can help the design of the application logic.

#include "ocilib.h" int main(void) { OCI_Initialize(NULL, NULL, OCI_ENV_DEFAULT); /* start remote instance */ OCI_DatabaseStartup("db", "sys_usr", "sys_pwd", OCI_SESSION_SYSDBA, OCI_DB_SPM_FULL, OCI_DB_SPF_FORCE, NULL); /* shutdown remote instance */ OCI_DatabaseShutdown("db", "sys_usr", "sys_pwd", OCI_SESSION_SYSDBA, OCI_DB_SDM_FULL, OCI_DB_SDF_ABORT); OCI_Cleanup(); return EXIT_SUCCESS; }

Page 49: Ocilib 3.5.0 User Guide

Developing C/C++ Oracle applications with OCILIB

Copyright © 2008-2010 Vincent Rogier – http://www.ocilib.net - Document under GNU Free Documentation License v1.3

49

The database status change notification is also interesting to be informed of instance startup / shutdown Check Oracle documentation for more details about this feature Note: No active database connection is required to receive the notifications as they are handled by the Oracle client using a dedicated socket connection to the server Database changes: The client application can be notified by any database status change (single DB or multiple DB in a RAC environment). Object changes: The notifications of object changes are based on the registration of a query ('select' SQL statement). Oracle server will notify of any changes of any object that is part of the statement result set. Registering a statement will notify about any changes on its result set rows performed after the registration of the query. The query can be a simple 'select * from table' or a complex query involving many tables and/or criteria in the where clause. For Object changes, the notification can be at:

• At Object level: only the object name (schema + object) is given • At row level: same that object level + ROWID of the altered row

Warning: Trying to use this features with a client/server version < 10gR2 will raise an error

#include "ocilib.h" #ifdef _WINDOWS #define sleep(x) Sleep(x*1000) #endif #define wait_for_events() sleep(5) void event_handler(OCI_Event *event); void error_handler(OCI_Error *err); int main(void) { OCI_Connection *con; OCI_Subscription *sub; OCI_Statement *st; printf("=> Initializing OCILIB in event mode...\n\n"); if (!OCI_Initialize(error_handler, NULL, OCI_ENV_EVENTS)) return EXIT_FAILURE; printf("=> Connecting to usr@db...\n\n"); con = OCI_ConnectionCreate("db", "usr", "pwd", OCI_SESSION_DEFAULT); OCI_SetAutoCommit(con, TRUE); printf("=> Creating statement...\n\n"); st = OCI_StatementCreate(con); printf("=> Creating tables...\n\n"); OCI_ExecuteStmt(st, "create table table1(code number)"); OCI_ExecuteStmt(st, "create table table2(str varchar2(10))"); printf("=> Registering subscription...\n\n"); sub = OCI_SubscriptionRegister(con, "sub-00", OCI_CNT_ALL, event_handler, 5468, 0);

Page 50: Ocilib 3.5.0 User Guide

Developing C/C++ Oracle applications with OCILIB

Copyright © 2008-2010 Vincent Rogier – http://www.ocilib.net - Document under GNU Free Documentation License v1.3

50

printf("=> Adding queries to be notified...\n\n"); OCI_Prepare(st, "select * from table1"); OCI_SubscriptionAddStatement(sub, st); OCI_Prepare(st, "select * from table2"); OCI_SubscriptionAddStatement(sub, st); printf("=> Executing some DDL operation...\n\n"); OCI_ExecuteStmt(st, "alter table table1 add price number"); wait_for_events(); printf("=> Executing some DML operation...\n\n"); OCI_ExecuteStmt(st, "insert into table1 values(1, 10.5)"); OCI_ExecuteStmt(st, "insert into table2 values('shoes')"); OCI_ExecuteStmt(st, "update table1 set price = 13.5 where code = 1"); OCI_ExecuteStmt(st, "delete from table2 "); wait_for_events(); printf("=> Droping tables...\n\n"); OCI_ExecuteStmt(st, "drop table table1"); OCI_ExecuteStmt(st, "drop table table2"); wait_for_events(); printf("=> Disconnecting from DB...\n\n"); OCI_ConnectionFree(con); printf("=> Stopping the remote database...\n\n"); OCI_DatabaseShutdown("db", "sys", "sys", OCI_SESSION_SYSDBA, OCI_DB_SDM_FULL, OCI_DB_SDF_IMMEDIATE); wait_for_events();; printf("=> Starting the remote database...\n\n"); OCI_DatabaseStartup("db", "sys", "sys", OCI_SESSION_SYSDBA, OCI_DB_SPM_FULL, OCI_DB_SPF_FORCE, NULL); wait_for_events(); printf("=> Unregistering subscription...\n\n"); OCI_SubscriptionUnregister(sub); printf("=> Cleaning up OCILIB resources...\n\n"); OCI_Cleanup(); printf("=> Done...\n\n"); return EXIT_SUCCESS; } void error_handler(OCI_Error *err) { int err_type = OCI_ErrorGetType(err); const char *err_msg = OCI_ErrorGetString(err); printf("** %s - %s\n", err_type == OCI_ERR_WARNING ? "Warning" : "Error", err_msg); }

Page 51: Ocilib 3.5.0 User Guide

Developing C/C++ Oracle applications with OCILIB

Copyright © 2008-2010 Vincent Rogier – http://www.ocilib.net - Document under GNU Free Documentation License v1.3

51

void event_handler(OCI_Event *event) { unsigned int type = OCI_EventGetType(event); unsigned int op = OCI_EventGetOperation(event); OCI_Subscription *sub = OCI_EventGetSubscription(event); printf("** Notification : %s\n\n", OCI_SubscriptionGetName(sub)); printf("...... Database : %s\n", OCI_EventGetDatabase(event)); switch (type) { case OCI_ENT_STARTUP: printf("...... Event : Startup\n"); break; case OCI_ENT_SHUTDOWN: printf("...... Event : Shutdown\n"); break; case OCI_ENT_SHUTDOWN_ANY: printf("...... Event : Shutdown any\n"); break; case OCI_ENT_DROP_DATABASE: printf("...... Event : drop database\n"); break; case OCI_ENT_DEREGISTER: printf("...... Event : deregister\n"); break; case OCI_ENT_OBJECT_CHANGED: printf("...... Event : object changed\n"); printf("........... Object : %s\n", OCI_EventGetObject(event)); switch (op) { case OCI_ONT_INSERT: printf("........... Action : insert\n"); break; case OCI_ONT_UPDATE: printf("........... Action : update\n"); break; case OCI_ONT_DELETE: printf("........... Action : delete\n"); break; case OCI_ONT_ALTER: printf("........... Action : alter\n"); break; case OCI_ONT_DROP: printf("........... Action : drop\n"); break; } if (op < OCI_ONT_ALTER) printf("........... Rowid : %s\n", OCI_EventGetRowid(event)); break; } printf("\n"); }

Page 52: Ocilib 3.5.0 User Guide

Developing C/C++ Oracle applications with OCILIB

Copyright © 2008-2010 Vincent Rogier – http://www.ocilib.net - Document under GNU Free Documentation License v1.3

52

Going deeper in OCI: direct use of OCI handles

OCILIB conception was focused on a full but closed encapsulation of OCI. All OCI headers, datatypes, prototypes are imported internally (linkage or runtime import). OCILIB public interface exposes only ISO C scalar types and OCILIB objects OCI is a wide and rich API that can deals with hundreds of options! OCILIB tries to implements most of it. But, sometimes in really specific contexts, it might be necessary to directly call OCI APIs in order to use uncovered OCI functionalities or options OCILIB proposes now a set of functions to retrieve its internal OCI handles Warning:

• OCILIB author strongly advises against the use of internal handles, unless there is no other way to accomplish the task

• Using these handles for direct application calls to OCI might lead to OCILIB instability or crash if handles are incorrectly used!

Page 53: Ocilib 3.5.0 User Guide

Developing C/C++ Oracle applications with OCILIB

Copyright © 2008-2010 Vincent Rogier – http://www.ocilib.net - Document under GNU Free Documentation License v1.3

53

13. Annexes

GNU Free Documentation License

GNU Free Documentation License Version 1.3, 3 November 2008 Copyright (C) 2000, 2001, 2002, 2007, 2008 Free Software Foundation, Inc. <http://fsf.org/> Everyone is permitted to copy and distribute verbatim copies of this license document, but changing it is not allowed. 0. PREAMBLE The purpose of this License is to make a manual, textbook, or other functional and useful document "free" in the sense of freedom: to assure everyone the effective freedom to copy and redistribute it, with or without modifying it, either commercially or noncommercially. Secondarily, this License preserves for the author and publisher a way to get credit for their work, while not being considered responsible for modifications made by others. This License is a kind of "copyleft", which means that derivative works of the document must themselves be free in the same sense. It complements the GNU General Public License, which is a copyleft license designed for free software. We have designed this License in order to use it for manuals for free software, because free software needs free documentation: a free program should come with manuals providing the same freedoms that the software does. But this License is not limited to software manuals; it can be used for any textual work, regardless of subject matter or whether it is published as a printed book. We recommend this License principally for works whose purpose is instruction or reference. 1. APPLICABILITY AND DEFINITIONS This License applies to any manual or other work, in any medium, that contains a notice placed by the copyright holder saying it can be distributed under the terms of this License. Such a notice grants a world-wide, royalty-free license, unlimited in duration, to use that work under the conditions stated herein. The "Document", below, refers to any such manual or work. Any member of the public is a licensee, and is addressed as "you". You accept the license if you copy, modify or distribute the work in a way requiring permission under copyright law. A "Modified Version" of the Document means any work containing the

Page 54: Ocilib 3.5.0 User Guide

Developing C/C++ Oracle applications with OCILIB

Copyright © 2008-2010 Vincent Rogier – http://www.ocilib.net - Document under GNU Free Documentation License v1.3

54

Document or a portion of it, either copied verbatim, or with modifications and/or translated into another language. A "Secondary Section" is a named appendix or a front-matter section of the Document that deals exclusively with the relationship of the publishers or authors of the Document to the Document's overall subject (or to related matters) and contains nothing that could fall directly within that overall subject. (Thus, if the Document is in part a textbook of mathematics, a Secondary Section may not explain any mathematics.) The relationship could be a matter of historical connection with the subject or with related matters, or of legal, commercial, philosophical, ethical or political position regarding them. The "Invariant Sections" are certain Secondary Sections whose titles are designated, as being those of Invariant Sections, in the notice that says that the Document is released under this License. If a section does not fit the above definition of Secondary then it is not allowed to be designated as Invariant. The Document may contain zero Invariant Sections. If the Document does not identify any Invariant Sections then there are none. The "Cover Texts" are certain short passages of text that are listed, as Front-Cover Texts or Back-Cover Texts, in the notice that says that the Document is released under this License. A Front-Cover Text may be at most 5 words, and a Back-Cover Text may be at most 25 words. A "Transparent" copy of the Document means a machine-readable copy, represented in a format whose specification is available to the general public, that is suitable for revising the document straightforwardly with generic text editors or (for images composed of pixels) generic paint programs or (for drawings) some widely available drawing editor, and that is suitable for input to text formatters or for automatic translation to a variety of formats suitable for input to text formatters. A copy made in an otherwise Transparent file format whose markup, or absence of markup, has been arranged to thwart or discourage subsequent modification by readers is not Transparent. An image format is not Transparent if used for any substantial amount of text. A copy that is not "Transparent" is called "Opaque". Examples of suitable formats for Transparent copies include plain ASCII without markup, Texinfo input format, LaTeX input format, SGML or XML using a publicly available DTD, and standard-conforming simple HTML, PostScript or PDF designed for human modification. Examples of transparent image formats include PNG, XCF and JPG. Opaque formats include proprietary formats that can be read and edited only by proprietary word processors, SGML or XML for which the DTD and/or processing tools are not generally available, and the machine-generated HTML, PostScript or PDF produced by some word processors for output purposes only. The "Title Page" means, for a printed book, the title page itself, plus such following pages as are needed to hold, legibly, the material this License requires to appear in the title page. For works in formats which do not have any title page as such, "Title Page" means the text near the most prominent appearance of the work's title, preceding the beginning of the body of the text. The "publisher" means any person or entity that distributes copies of the Document to the public.

Page 55: Ocilib 3.5.0 User Guide

Developing C/C++ Oracle applications with OCILIB

Copyright © 2008-2010 Vincent Rogier – http://www.ocilib.net - Document under GNU Free Documentation License v1.3

55

A section "Entitled XYZ" means a named subunit of the Document whose title either is precisely XYZ or contains XYZ in parentheses following text that translates XYZ in another language. (Here XYZ stands for a specific section name mentioned below, such as "Acknowledgements", "Dedications", "Endorsements", or "History".) To "Preserve the Title" of such a section when you modify the Document means that it remains a section "Entitled XYZ" according to this definition. The Document may include Warranty Disclaimers next to the notice which states that this License applies to the Document. These Warranty Disclaimers are considered to be included by reference in this License, but only as regards disclaiming warranties: any other implication that these Warranty Disclaimers may have is void and has no effect on the meaning of this License. 2. VERBATIM COPYING You may copy and distribute the Document in any medium, either commercially or noncommercially, provided that this License, the copyright notices, and the license notice saying this License applies to the Document are reproduced in all copies, and that you add no other conditions whatsoever to those of this License. You may not use technical measures to obstruct or control the reading or further copying of the copies you make or distribute. However, you may accept compensation in exchange for copies. If you distribute a large enough number of copies you must also follow the conditions in section 3. You may also lend copies, under the same conditions stated above, and you may publicly display copies. 3. COPYING IN QUANTITY If you publish printed copies (or copies in media that commonly have printed covers) of the Document, numbering more than 100, and the Document's license notice requires Cover Texts, you must enclose the copies in covers that carry, clearly and legibly, all these Cover Texts: Front-Cover Texts on the front cover, and Back-Cover Texts on the back cover. Both covers must also clearly and legibly identify you as the publisher of these copies. The front cover must present the full title with all words of the title equally prominent and visible. You may add other material on the covers in addition. Copying with changes limited to the covers, as long as they preserve the title of the Document and satisfy these conditions, can be treated as verbatim copying in other respects. If the required texts for either cover are too voluminous to fit legibly, you should put the first ones listed (as many as fit reasonably) on the actual cover, and continue the rest onto adjacent pages. If you publish or distribute Opaque copies of the Document numbering more than 100, you must either include a machine-readable Transparent copy along with each Opaque copy, or state in or with each Opaque copy a computer-network location from which the general network-using public has access to download using public-standard network protocols a complete Transparent copy of the Document, free of added material. If you use the latter option, you must take reasonably prudent steps, when you begin distribution of Opaque copies in quantity, to ensure

Page 56: Ocilib 3.5.0 User Guide

Developing C/C++ Oracle applications with OCILIB

Copyright © 2008-2010 Vincent Rogier – http://www.ocilib.net - Document under GNU Free Documentation License v1.3

56

that this Transparent copy will remain thus accessible at the stated location until at least one year after the last time you distribute an Opaque copy (directly or through your agents or retailers) of that edition to the public. It is requested, but not required, that you contact the authors of the Document well before redistributing any large number of copies, to give them a chance to provide you with an updated version of the Document. 4. MODIFICATIONS You may copy and distribute a Modified Version of the Document under the conditions of sections 2 and 3 above, provided that you release the Modified Version under precisely this License, with the Modified Version filling the role of the Document, thus licensing distribution and modification of the Modified Version to whoever possesses a copy of it. In addition, you must do these things in the Modified Version: A. Use in the Title Page (and on the covers, if any) a title distinct from that of the Document, and from those of previous versions (which should, if there were any, be listed in the History section of the Document). You may use the same title as a previous version if the original publisher of that version gives permission. B. List on the Title Page, as authors, one or more persons or entities responsible for authorship of the modifications in the Modified Version, together with at least five of the principal authors of the Document (all of its principal authors, if it has fewer than five), unless they release you from this requirement. C. State on the Title page the name of the publisher of the Modified Version, as the publisher. D. Preserve all the copyright notices of the Document. E. Add an appropriate copyright notice for your modifications adjacent to the other copyright notices. F. Include, immediately after the copyright notices, a license notice giving the public permission to use the Modified Version under the terms of this License, in the form shown in the Addendum below. G. Preserve in that license notice the full lists of Invariant Sections and required Cover Texts given in the Document's license notice. H. Include an unaltered copy of this License. I. Preserve the section Entitled "History", Preserve its Title, and add to it an item stating at least the title, year, new authors, and publisher of the Modified Version as given on the Title Page. If there is no section Entitled "History" in the Document, create one stating the title, year, authors, and publisher of the Document as given on its Title Page, then add an item describing the Modified Version as stated in the previous sentence. J. Preserve the network location, if any, given in the Document for public access to a Transparent copy of the Document, and likewise the network locations given in the Document for previous versions it was based on. These may be placed in the "History" section. You may omit a network location for a work that was published at least four years before the Document itself, or if the original publisher of the version it refers to gives permission. K. For any section Entitled "Acknowledgements" or "Dedications", Preserve the Title of the section, and preserve in the section all the substance and tone of each of the contributor acknowledgements and/or dedications given therein. L. Preserve all the Invariant Sections of the Document,

Page 57: Ocilib 3.5.0 User Guide

Developing C/C++ Oracle applications with OCILIB

Copyright © 2008-2010 Vincent Rogier – http://www.ocilib.net - Document under GNU Free Documentation License v1.3

57

unaltered in their text and in their titles. Section numbers or the equivalent are not considered part of the section titles. M. Delete any section Entitled "Endorsements". Such a section may not be included in the Modified Version. N. Do not retitle any existing section to be Entitled "Endorsements" or to conflict in title with any Invariant Section. O. Preserve any Warranty Disclaimers. If the Modified Version includes new front-matter sections or appendices that qualify as Secondary Sections and contain no material copied from the Document, you may at your option designate some or all of these sections as invariant. To do this, add their titles to the list of Invariant Sections in the Modified Version's license notice. These titles must be distinct from any other section titles. You may add a section Entitled "Endorsements", provided it contains nothing but endorsements of your Modified Version by various parties--for example, statements of peer review or that the text has been approved by an organization as the authoritative definition of a standard. You may add a passage of up to five words as a Front-Cover Text, and a passage of up to 25 words as a Back-Cover Text, to the end of the list of Cover Texts in the Modified Version. Only one passage of Front-Cover Text and one of Back-Cover Text may be added by (or through arrangements made by) any one entity. If the Document already includes a cover text for the same cover, previously added by you or by arrangement made by the same entity you are acting on behalf of, you may not add another; but you may replace the old one, on explicit permission from the previous publisher that added the old one. The author(s) and publisher(s) of the Document do not by this License give permission to use their names for publicity for or to assert or imply endorsement of any Modified Version. 5. COMBINING DOCUMENTS You may combine the Document with other documents released under this License, under the terms defined in section 4 above for modified versions, provided that you include in the combination all of the Invariant Sections of all of the original documents, unmodified, and list them all as Invariant Sections of your combined work in its license notice, and that you preserve all their Warranty Disclaimers. The combined work need only contain one copy of this License, and multiple identical Invariant Sections may be replaced with a single copy. If there are multiple Invariant Sections with the same name but different contents, make the title of each such section unique by adding at the end of it, in parentheses, the name of the original author or publisher of that section if known, or else a unique number. Make the same adjustment to the section titles in the list of Invariant Sections in the license notice of the combined work. In the combination, you must combine any sections Entitled "History" in the various original documents, forming one section Entitled "History"; likewise combine any sections Entitled "Acknowledgements", and any sections Entitled "Dedications". You must delete all sections Entitled "Endorsements".

Page 58: Ocilib 3.5.0 User Guide

Developing C/C++ Oracle applications with OCILIB

Copyright © 2008-2010 Vincent Rogier – http://www.ocilib.net - Document under GNU Free Documentation License v1.3

58

6. COLLECTIONS OF DOCUMENTS You may make a collection consisting of the Document and other documents released under this License, and replace the individual copies of this License in the various documents with a single copy that is included in the collection, provided that you follow the rules of this License for verbatim copying of each of the documents in all other respects. You may extract a single document from such a collection, and distribute it individually under this License, provided you insert a copy of this License into the extracted document, and follow this License in all other respects regarding verbatim copying of that document. 7. AGGREGATION WITH INDEPENDENT WORKS A compilation of the Document or its derivatives with other separate and independent documents or works, in or on a volume of a storage or distribution medium, is called an "aggregate" if the copyright resulting from the compilation is not used to limit the legal rights of the compilation's users beyond what the individual works permit. When the Document is included in an aggregate, this License does not apply to the other works in the aggregate which are not themselves derivative works of the Document. If the Cover Text requirement of section 3 is applicable to these copies of the Document, then if the Document is less than one half of the entire aggregate, the Document's Cover Texts may be placed on covers that bracket the Document within the aggregate, or the electronic equivalent of covers if the Document is in electronic form. Otherwise they must appear on printed covers that bracket the whole aggregate. 8. TRANSLATION Translation is considered a kind of modification, so you may distribute translations of the Document under the terms of section 4. Replacing Invariant Sections with translations requires special permission from their copyright holders, but you may include translations of some or all Invariant Sections in addition to the original versions of these Invariant Sections. You may include a translation of this License, and all the license notices in the Document, and any Warranty Disclaimers, provided that you also include the original English version of this License and the original versions of those notices and disclaimers. In case of a disagreement between the translation and the original version of this License or a notice or disclaimer, the original version will prevail. If a section in the Document is Entitled "Acknowledgements", "Dedications", or "History", the requirement (section 4) to Preserve its Title (section 1) will typically require changing the actual title. 9. TERMINATION

Page 59: Ocilib 3.5.0 User Guide

Developing C/C++ Oracle applications with OCILIB

Copyright © 2008-2010 Vincent Rogier – http://www.ocilib.net - Document under GNU Free Documentation License v1.3

59

You may not copy, modify, sublicense, or distribute the Document except as expressly provided under this License. Any attempt otherwise to copy, modify, sublicense, or distribute it is void, and will automatically terminate your rights under this License. However, if you cease all violation of this License, then your license from a particular copyright holder is reinstated (a) provisionally, unless and until the copyright holder explicitly and finally terminates your license, and (b) permanently, if the copyright holder fails to notify you of the violation by some reasonable means prior to 60 days after the cessation. Moreover, your license from a particular copyright holder is reinstated permanently if the copyright holder notifies you of the violation by some reasonable means, this is the first time you have received notice of violation of this License (for any work) from that copyright holder, and you cure the violation prior to 30 days after your receipt of the notice. Termination of your rights under this section does not terminate the licenses of parties who have received copies or rights from you under this License. If your rights have been terminated and not permanently reinstated, receipt of a copy of some or all of the same material does not give you any rights to use it. 10. FUTURE REVISIONS OF THIS LICENSE The Free Software Foundation may publish new, revised versions of the GNU Free Documentation License from time to time. Such new versions will be similar in spirit to the present version, but may differ in detail to address new problems or concerns. See http://www.gnu.org/copyleft/. Each version of the License is given a distinguishing version number. If the Document specifies that a particular numbered version of this License "or any later version" applies to it, you have the option of following the terms and conditions either of that specified version or of any later version that has been published (not as a draft) by the Free Software Foundation. If the Document does not specify a version number of this License, you may choose any version ever published (not as a draft) by the Free Software Foundation. If the Document specifies that a proxy can decide which future versions of this License can be used, that proxy's public statement of acceptance of a version permanently authorizes you to choose that version for the Document. 11. RELICENSING "Massive Multiauthor Collaboration Site" (or "MMC Site") means any World Wide Web server that publishes copyrightable works and also provides prominent facilities for anybody to edit those works. A public wiki that anybody can edit is an example of such a server. A "Massive Multiauthor Collaboration" (or "MMC") contained in the site means any set of copyrightable works thus published on the MMC site. "CC-BY-SA" means the Creative Commons Attribution-Share Alike 3.0 license published by Creative Commons Corporation, a not-for-profit corporation with a principal place of business in San Francisco, California, as well as future copyleft versions of that license

Page 60: Ocilib 3.5.0 User Guide

Developing C/C++ Oracle applications with OCILIB

Copyright © 2008-2010 Vincent Rogier – http://www.ocilib.net - Document under GNU Free Documentation License v1.3

60

published by that same organization. "Incorporate" means to publish or republish a Document, in whole or in part, as part of another Document. An MMC is "eligible for relicensing" if it is licensed under this License, and if all works that were first published under this License somewhere other than this MMC, and subsequently incorporated in whole or in part into the MMC, (1) had no cover texts or invariant sections, and (2) were thus incorporated prior to November 1, 2008. The operator of an MMC Site may republish an MMC contained in the site under CC-BY-SA on the same site at any time before August 1, 2009, provided the MMC is eligible for relicensing.