Vous êtes sur la page 1sur 21

www.techdos.

com

Oracle Develop an application in C / C + + with the library OCILIB


Wednesday, 14 May 2008

III. Installation III-A. Nearly required Having a system like Unix or Microsoft Windows supported by Oracle Have an Oracle client installed (not required for compilation, but for the execution) III-B. Compatibilities The following platforms have been validated (compilation, installation, build and implementation of a project): Microsoft Windows Linux Solaris HP / UX AIX The other platforms supported by Oracle (MacOS server, OpenVMS, z / OS) have not been officially tested, but in view of platforms already validated, it should not be too problematic! The compilers have been validated following: Microsoft Compilers (VC + +, VS200X) GCC and MinGW XLC CC owners The following versions of Oracle (clients and servers) have been validated: Oracle 8i Oracle 9i Oracle 10g Oracle 11g III-C. Installation under Unixes (Unix / Linux / Mac) OCILIB uses the GNU tools for its deployment and installation. Extracting the current archive (ocilib-xyz-gnu.tar.gz) $ Ocilib CD-x.y.z $. / Configure $. / Make $. / Make install (generally, you have to go to root for installation) Check environment variable paths dynamic libraries (LD_LIBRARY_PATH, LD_PATH, ..) so the directory of shared libraries Oracle is there and that is where installed OCILIB (typically / usr / local / Lib Linux) Typically, just add to its roster. Profile: > Export LD_LIBRARY_PATH = $ LD_LIBRARY_PATH: $ ORACLE_HOME / lib: / usr / local / lib OCILIB supports 3 installation options: -- with-oracle-import = (linkage | runtime) -- with-oracle-charset = (ansi | unicode | mixed) -- with-oracle-home = (oracle directory) III-D. Installation under Microsoft Windows Under Microsoft Windows, DLLs are provided for 32bits environment and 64bits (x86) and can be recompiled easily. Extracting the current archive (ocilib-xyz-windows.zip) Copy ocilib \ src \ ocilib.h in a directory included in the list to "file headers" compiler Copy ocilib \ lib32 | 64 \ ocilib [x]. Lib in a directory included in the list to "file library" of the editor link Copy ocilib \ lib32 | 64 \ ocilib [x]. Dll files in a directory included in the PATH
http://techdos.com Powered by Joomla! Generated: 21 July, 2011, 13:48

www.techdos.com

[x] represents the compiled version of OCILIB: "a" for Ansi, "w" for Unicode and "m" for mixed mode III-E. Setting up projects To use OCILIB in a project must include the header "ocilib.h." Some options must be defined before the inclusion of header ocilib.h => Mode liaison Oracle: OCI_IMPORT_LINKAGE: to link libraries (static or shared) the compilation (default Unix like) OCI_IMPORT_RUNTIME: to load dynamically bookstores oracle in execution (default option under MS Windows) => Charsets used: OCI_CHARSET_ANSI: any strings are Ansi (default) OCI_CHARSET_UNICODE: any strings are Unicode (versions of Oracle> = 9i) OCI_CHARSET_MIXED: Orders SQL, metadata to Ansi and user data supplied and recovered queries Unicode => Convention of Appeal (MS Windows only): OCI_API: not defined (default) OCI_API: __sdtcall to use dll precompiled On Windows, for use in OCILIB ANSI, using Dlls provided, it is enough to create a new project: Include "ocilib.h" Defining OCI_API = __sdtcall in options preprocessor Project If all variations ocilib [x]. Lib are available for the linker, then specify which version by inserting # pragma comment (lib, "ocilib [x]. Lib") in a file Project In Linux for use in OCILIB ANSI and with a linkage of shared libraries to the compilation, it requires: => Include "ocilib.h" => Add to makefile for compilo: -I/usr/local/include For the header ocilib.h - DOCI_IMPORT_LINKAGE-DOCI_CHARSET_ANSI to configure ocilib => Add to makefile for the linker: - L / $ ORACLE_HOME / lib-lclntsh bookstores for Oracle -L/usr/local/lib-Locilib for the library OCILIB IV. Log Oracle IV-A. Initialize OCILIB Above all else, OCILIB be set. This requires, first and foremost appeal to a function of the library, call OCI_Initilalize (). This feature makes the library and takes parameters: [Optional] A pointer to a function of management errors [Optional] A directory or is bookstores Oracle (if runtime loading and several customers Oracle installed) [Optional] mode initialization. Currently, only the value is supported OCI_ENV_DEFAULT Example # include "ocilib.h" int main () ( if (OCI_Initialize (err_handler, NULL, OCI_ENV_DEFAULT) == FALSE) Return EXIT_FAILURE; / * ... code application ... * / OCI_Cleanup ();
http://techdos.com Powered by Joomla! Generated: 21 July, 2011, 13:48

www.techdos.com

return EXIT_SUCCESS; ) At the end of the application, an appeal to OCI_Cleanup () is required to: Desallouer objects not explicitly released Download Oracle bookstores in the case of a runtime loading IV-B. Connections Connect to an Oracle database is done by the function OCI_CreateConnection () which takes parameters: The office Oracle (aka Oracle, SID, ... within the parameters of the Oracle client). The name of the user Oracle on which to connect The password from the user Oracle The mode of session (OCI_SESSION_DEFAULT, OCI_SESSION_SYSDBA, OCI_SESSION_SYSOPER) This function of charge to connect to server, create a session and establish a transaction. If successful, it returns a handle connection and the application can immediately execute orders SQL. Example OCI_Connection * CN; / * .... * / cn = OCI_CreateConnection ( "Database", "user", "password", OCI_SESSION_DEFAULT); if (cn! = NULL) ( printf ( "% s \ n", OCI_GetVersionServer (cn)); / * ... code application ... * / OCI_FreeConnection (cn); ) / * .... * / To close connection to the server, just call OCI_FreeConnection () IV-C. Error Handling OCILIB proposes a mechanism for handling errors based on the concept of callback to be triggered in the following cases: Error processed by OIC Error allocating memory Error internal OCILIB The prototype of the function is to provide as follows: typedef void (* POCI_ERROR) (* OCI_Error err); A handle on an object OCI_Error is then provided to the function. The library provides functions to access the properties of the error generated. Example of a function of management errors that merely display on the screen an SQL error: ErrorHandler void (* OCI_Error err) ( int sql_code = OCI_ErrorGetOCICode (err); if (sql_code! = 0) ( printf ( "Code: ORA-05i% \ n" "Msg:% s \ n", sql_code, OCI_ErrorGetString (err));
http://techdos.com Powered by Joomla! Generated: 21 July, 2011, 13:48

www.techdos.com

) ) IV-D. Transactions OCILIB support mechanisms transactions (local and global) proposed by Oracle via OIC. By default, once the application was connected to Oracle, a local transaction is created. Any modification of data (insert, update, delete) are not visible from other sessions as it was not explicitly endorsed the changes by a call to OCI_Commit (). If the application does not validate its changes and thus nullify the data changes made since the last validation (or default from the server connection), it must use OCI_Rollback (). There are cases where simple transactions local default is not enough: manage a connection to read only by example manage a global transaction in a distributed environment etc. .. In these cases, OCILIB proposes an explicit management transactions where it is possible to create a transaction, and link it to handle a connection. IV-E. Types of data supported OCILIB supports all types of data provided by Oracle, except for references and collections. List of types supported: All types scalar (strings, digital floating ..): CHAR / NCHAR, VARCHAR2/NVARCHAR2, NUMBER, FLOAT, ... Types binary: RAW, LONG RAW, VARRAW, .. Large Objects (Lobs and Files): BLOB, CLOB, NCLOB, BFILE, CFILE Types LONGs: LONG, VAR LONG, LONG RAW ... Date, Timestamps and Intervals: DATE, TIMESTAMP (all) INTERVAL (all) PL / SQL types: Ref cursors and Nested Tables Names Types: User types, XmlType, .... ROWIDs All of these types may be incurred related to statements or be recovered from a select. Oracle TYPE Type OCILIB Strings: CHAR / NCHAR, VARCHAR2/NVARCHAR2, .... dtext * (char * or wchar_t * by the build) Numbers without precision (whole): INT, NUMBER ... shorts, ints, big ints (signed / unsigned) Boat: FLOAT, REAL NUMBER (X, Y), .... double RAW void * LONG, LONG RAW, VARRAW, .. OCI_Long BLOB / CLOB / NCLOB OCI_Lob 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 Nested Tables OCI_Statement User Types OCI_Object ROWID dtext * (char * or wchar_t * by the build)
http://techdos.com Powered by Joomla! Generated: 21 July, 2011, 13:48

www.techdos.com

V. Carry out orders SQL V-A. SQL Statements To execute orders on the SQL database, we have to create an object SQL statement via function OCI_CreateStatement (). Once this object creates, it is possible to run queries on the function OCI_ExecuteStmt (). Example OCI_Connection * CN; OCI_Statement * st; / * ... * / st = OCI_CreateStatement (cn); OCI_ExecuteStmt (st, "delete from my_table where code is null"); printf ( "% d row deleted", OCI_GetAffectedRows (st)); OCI_Commit (cn); OCI_FreeStatement (St); / * ... * / OCI_ExecuteStmt () has prepared and carried out the order and SQL OCI_GetAffectedRows () has recovered the number of lines deleted from the table. Once the statement is more useful, a call to OCI_FreeStatement () frees all resources associated (resultset, ...). A OCI_Statement object can be reused to execute as many orders as necessary SQL. V-B. Linking variables In the previous example, the query was simple and not require any input variable. Often, it is necessary to provide a request values entries not known in advance. Moreover, it is useful to be able to execute several times a similar SQL with different values without having to repreparer SQL by Oracle to optimize performance. It is therefore possible to link variables of the programme by providing their address to the statement. In this case, it requires: Prepare SQL OCI_Prepare () Linking variables with the functions OCI_bindXXX () or XXX is the type of data Execute SQL OCI_Execute () Example OCI_Connection * CN; OCI_Statement * st; int code; / * ... * / st = OCI_CreateStatement (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));
http://techdos.com Powered by Joomla! Generated: 21 July, 2011, 13:48

www.techdos.com

OCI_Commit (cn); / * ... * / To make a mass insertion, we can proceed as follows: Example OCI_Connection * CN; OCI_Statement * st; int code; char name [30]; char value [20]; / * ... * / st = OCI_CreateStatement (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 <10000; code + +); ( sprintf (name, "name% i", code); sprintf (value, "value% i", code); OCI_Execute (St); ) OCI_Commit (cn); / * ... * / Nevertheless, Oracle supports "bulks operations" (see Chapter VI) which can manipulate arrays and provide unparalleled performance. V-C. Get the result of a select Get the result of a complaint is very simple. Just after the statement executed via OCI_Execute () or OCI_ExecuteStmt () call function OCI_GetResultSet () which returns a handle on an object OCI_Resultset. This includes 2 resultset things: The description of the columns returned by the query The data (lines results) To access the values of each column in the resultset, it requires: Browsing the resultset by a call to OCI_FetchNext () which returns TRUE as there are lines result Calling a function OCI_GetXXX () specifying the index of the column (or his name) and where XXX is the type: Int, String, Date, ... Example OCI_Connection * CN; OCI_Statement * st; OCI_Resultset * rs; / * ... * / st = OCI_CreateStatement (cn); OCI_ExecuteStmt (st, "select * from test_fetch");
http://techdos.com Powered by Joomla! Generated: 21 July, 2011, 13:48

www.techdos.com

rs = OCI_GetResultset (st); while (OCI_FetchNext (rs)) ( printf ( "code:% i, action:% s, price:% g date% s \ n", OCI_GetInt (rs, 1), OCI_GetString (rs, 2) OCI_GetDouble (rs 3), OCI_GetString (rs, 4)); ) printf ( "\ n% d row (s) fetched \ n", OCI_GetRowCount (rs)); / * .... * / OCI_GetRowCount () gives the number of lines of resultset already covered. The same example with access to columns by their names: Example OCI_Connection * CN; OCI_Statement * st; OCI_Resultset * rs; / * ... * / st = OCI_CreateStatement (cn); OCI_ExecuteStmt (st, "select * from test_fetch"); rs = OCI_GetResultset (st); while (OCI_FetchNext (rs)) ( printf ( "code:% i, action:% s, price:% g date% s \ n", OCI_GetInt2 (rs, "CODE"), OCI_GetStrin2g (rs, "ACTION") OCI_GetDouble2 (rs, "PRICE"), OCI_GetString2 (rs, "DATE")); ) printf ( "\ n% d row (s) fetched \ n", OCI_GetRowCount (rs)); / * .... * / A statement object can be reused as many times as you want. Moreover, it is possible to create multiple and the nest. Example OCI_Connection * CN; OCI_Statement * st1, * st2; OCI_Resultset * rs; / * ... * / st1 = OCI_CreateStatement (cn); st2 = OCI_CreateStatement (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))
http://techdos.com Powered by Joomla! Generated: 21 July, 2011, 13:48

www.techdos.com

( OCI_GetInt code = (rs, 1); OCI_Execute (st2); ) / * ... * / It is possible to retrieve information on (metadatas) each column of resulset (columns selected by the application). To do this: A call to OCI_GetColumnCount () can see the number of columns contained in the resultset A call to OCI_GetColumn () specifying index (position in the select) to get a handle on an object OCI_Column All properties of the column are accessible by a series of functions type OCI_GetColumnXXX () where XXX is the property Example OCI_Connection * CN; OCI_Statement * st; OCI_Resultset * rs; OCI_Column * col; / * ... * / st = OCI_CreateStatement (cn); OCI_ExecuteStmt (st, "select * from my_table"); rs = OCI_GetResultset (st); OCI_GetColumnCount nb = (rs); for (i = 1; i <= # 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"); ) / * ... * / V-D. PL / SQL blocks Variables can be linked both input and output. To execute PL / SQL, it is sufficient to cover the PL / SQL by a "begin" a beginning and an "end" in the end block. Example of a block PL / SQL OCI_Connection * CN; OCI_Statement * st; / * ... * / st = OCI_CreateStatement (cn); OCI_Prepare (st, "begin: n: trunc = (sysdate 1)-trunc (sysdate-1); end;"); OCI_BindInt (st, "n", & n); OCI_Execute (St);
http://techdos.com Powered by Joomla! Generated: 21 July, 2011, 13:48

www.techdos.com

printf ( "Result:% i \ n", n); / * ... * / Sample recovery of "a cursor PL / SQL and fetch his result in the program C: Example OCI_Connection * CN; OCI_Statement * st; / * ... * / st = OCI_CreateStatement (cn); st2 = OCI_CreateStatement (cn); OCI_Prepare (st, "begin open: c for select * from my_table; end;"); OCI_BindStatement (st, "c", st2); OCI_Execute (St); rs = OCI_GetResultset (st2); while (OCI_FetchNext (rs)) ( printf ( "my name is% s \ n", OCI_GetString (rs, 1)); ) / * ... * / V-E. Support of the clause SQL RETURNING Oracle offers a very interesting feature which is the SQL clause "into returning." The use of this clause in a DML (insert / update / delete) can combine 1 to 2 requests, thus reducing the number of trips between the client and server. The addition of this clause can select the lines affected by the DML within the same request. This is convenient, especially in the case of delete deleted because the values are recoverable! OCILIB implements this feature by creating an object OCI_Resultset from selected columns in the clause RETURNING. This resultset is then manipulated as a classic resultset. The Array Interface is also compatible with this clause. In this case, each entry of the table may affect different lines. OCILIB creates a resultset for each entry of the table. For example, if the table used to link variables statement contains 100 items, the application begins with the first resulset recover with a call to OCI_GetResulset (). Once this resultset come, resultset following is recoverable by a call to OCI_GetNextResultset (). OCILIB not ever pre-parse the SQL (for performance reasons) and therefore can not determine the fields (and their type) used in the clause RETURNING. Therefore, the application indicates explicitly columns of the clause by RETURNING functions OCI_RegisterXXX () or XXX is the type of data. OCILIB then resultsets built on the basis of columns and reported. Example selection of objects of a table: OCI_Connection * CN; OCI_Statement * st; OCI_Resultset * rs; / * ... * / St = OCI_CreateStatement (cn); OCI_Prepare (st, "my_table set update content = content | | to_char (code) returning code, content into: i: s"); OCI_RegisterInt (st, "i");
http://techdos.com Powered by Joomla! Generated: 21 July, 2011, 13:48

www.techdos.com

OCI_RegisterString (st, "s", 50); / * Updated data * / OCI_Execute (St); / * Fetch data changed * / Rs = OCI_GetResultset (st); While (OCI_FetchNext (rs)) ( printf ( "code:% i - content:% s \ n", OCI_GetInt (rs, 1), CI_GetInt (rs, 2)); ) Printf ( "count:% i \ n", OCI_GetRowCount (rs)); OCI_Commit (cn); / * ... * /

V-F. Check statements OCILIB proposes a series of functions to customize the behaviour of a statement. For example, it is possible to specify: The number of lines pre-fetchees by the Oracle client to reduce the number of roundtrips to the server The number of lines fetchees internalement by OCILIB to reduce calls OIC The mode of binding of variables: by name or position The date format default Etc. .. VI. Bulk Operations The "bulk operations" are a very powerful feature supported by Oracle, which can make massive updates (insert / update / update) tables in record times. In a pattern, if you want to insert 10000 rows in a table for example, it is possible to: prepare the complaint variables are linked wrap 1 to 10000 to execute the SQL bearing in each round loop updated values. This scheme will generate 10000 calls for execution of the request and therefore round 10000 / returns with the server for: Transmitting values Run again SQL All these calls and round / network returns are costly in terms of performance! If you want to add 1 million lines, it may be long! Oracle therefore proposes a simple solution that allows you to obtain optimal perfomances: OIC Interface Array VI-A. Oracle Array interface In the previous example, network traffic generated by a large number of executing a single complaint is the main source of the slow final treatment. Oracle proposes to minimize this traffic by providing arrays. Instead of providing 1 variable and send 10000 times its value to the server, it provides an array of 10000 values which is sent at once. The system reduces the processing time by factors of 3 to 5 digits at least on large volumes. OCILIB supports this mechanism and the possibility of linking tables of any type supported by OCILIB (except OCI_Long and OCI_Statement)
http://techdos.com Powered by Joomla! Generated: 21 July, 2011, 13:48

www.techdos.com

VI-B. Examples Example for inclusion in one fell swoop 10000 rows in a table:

OCI_Connection * CN; OCI_Statement * st; int tab_int [10000]; char tab_str [10000] [21]; / * ... * / OCI_Prepare (st, "insert into my_table values (: i: s)"); OCI_BindArraySetSize (st, 10000); OCI_BindArrayOfInts (st, "i", tab_int); OCI_BindArrayOfStrings (st, "s", tab_str, 20); / * Filling arrays * / for (i = 0; i <10000; 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)); / * ... * / VI. Using Large Objects Oracle 8 introduced LOBs (Large Objects) to store and manipulate large objects size (> several GB) to meet the storage needs of large files (multimedia, video, ...) and the raw data Within the DB. There are basically 2 types of large objects: The BLOB / CLOBS: objects stored in binary form (BLOBS) / text (CLOBS) The BFILES: objects not stored within 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 types of data. Moreover, OCILIB also supports the former implementation LOBs: the types LONG, LONG RAW and RAW. These types, always maintained by Oracle, are "ancestors" of LOBs and accounted for in earlier versions (up to Oracle 7) the only way to store large volumes (but more limited) in the DB. The types LONGs are still currently employed in the very bases and Oracle applications. That is why OCILIB proposes an API very close to those of LOBs (while the sub layer OIC management LONGs is very different from that of LOBs). VI-A. Internal Objects (LOBs) The BLOB / CLOB are stored in the database. Their use differs from those of other types of data. Indeed, a simple SQL does not read or write in a field of several hundred Mo. OCILIB offers a variety of functions can easily manipulate these objects (OCI_Lob *). For example, to insert the contents of a file in a field BLOB a table: OCI_Connection * CN; OCI_Statement * st; * OCI_Lob lob;
http://techdos.com Powered by Joomla! Generated: 21 July, 2011, 13:48

www.techdos.com

FILE * f; unsigned char buffer [1024]; int size; / * ... * / st = OCI_CreateStatement (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); OCI_LobCreate lob = (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); ) / * ... * / For example, to read the contents of a text file ANSI stored in a field of CLOB type of a table: Example OCI_Connection * CN; OCI_Statement * st; OCI_Resultset * rs; * OCI_Lob lob; FILE * f; char buffer [128]; / * ... * / st = OCI_CreateStatement (cn); OCI_ExecuteStmt (st, "select content from my_blob_table where code = 1"); rs = OCI_GetResultset (st); while (OCI_FetchNext (rs)) ( OCI_GetLob lob = (rs, 1); / * Read data from table by chunks of 128 bytes * / while ((n = OCI_LobRead (lob, buffer, sizeof (buffer) -1))
http://techdos.com Powered by Joomla! Generated: 21 July, 2011, 13:48

www.techdos.com

( buffer [n] = 0; printf ( "% s \ n", buffer); ) ) / * ... * / VI-B. External Objects (FILEs) The objects of type FILE (OCI_File *) are references to external files to the DB that can be opened for reading by the server and whose content can be retrieved by the client application. The objects FILEs are similar to the LOBs and therefore their API is similar except that FILEs are read-only. Sample reading of a field BILE an Oracle table: OCI_Connection * CN; OCI_Statement * st; OCI_Resultset * rs; OCI_File * file; unsigned char buffer [1024]; int n; / * ... * / st = OCI_CreateStatement (cn); OCI_ExecuteStmt (st, "select value from my_bfile_table where code = 1"); rs = OCI_GetResultset (st); while (OCI_FetchNext (rs)) ( file = OCI_GetFile (rs, 1); 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)) ( / * Do what you want content ... * / ) OCI_FileClose (file); ) / * ... * / VI-C. Long Objects OCILIB implements the "old" LONGs (OCI_Long *) similarly to the LOBs and FILEs. The APIs handling LONGs fields are very close to those of Large Objects. Examples to store a binary file in base and then retrieve the content: OCI_Connection * CN; OCI_Statement * st; OCI_Resultset * rs; OCI_Long * LG; unsigned char buffer [1024]; FILE * f; int n;
http://techdos.com Powered by Joomla! Generated: 21 July, 2011, 13:48

www.techdos.com

/ * .... * / st = OCI_CreateStatement (cn); / * Storage file in the DB * / f = fopen ( "file name", "rb"); if (f! = NULL) ( 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 1024 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_Commit (cn); OCI_LongFree (LG); ) / * Retrieving data from DB * / OCI_ExecuteStmt (st, "select content from test_long_raw where code = 1"); OCI_SetLongMaxSize (st, 100000); rs = OCI_GetResultset (st); / * Read data by chunks of 1024 bytes * / while (OCI_FetchNext (rs)) ( lg = OCI_GetLong (rs, 1); while ((n = OCI_LongRead (lg, buffer, sizeof (buffer)))) ( / * Do what one wants data * / ) printf ( "\ n% d bytes read \ n", OCI_LongGetSize (lg)); ) / * .... * / VIII. Handling Named Types OCILIB poropose "Named types", ie types of data appointed created by the user or provided by Oracle. A "TYPE" oracle is seen as the equivalent of a C. It is an aggregation of fields types scalar or aggregated. Example of creating a type of data: Create as object type t_produit
http://techdos.com Powered by Joomla! Generated: 21 July, 2011, 13:48

www.techdos.com

( code number, libel varchar2 (30), price number (5.3), REFERENCE varchar2 (100) ); create table ventes_produits ( T_produit product, Int number, Date_vente date ); OCILIB can: create instances of objects linking objects to SQL select items from one table manipulate the attributes of an object VIII-A. Autonomous Bodies To create an autonomous body, we must recover the descriptor of the type concerned. This is achieved by a call to OCI_SchemaGet (). Example create an instance of an object for insertion into a table: OCI_Connection * CN; OCI_Statement * st; OCI_Object * Prod; OCI_Date * date; int QTY; / * ... * / OCI_ObjectCreate prod = (cn, OCI_SchemaGet (cn, "t_product" OCI_SCHEMA_TYPE); date = OCI_DateCreate (cn); qty = 356; OCI_DateSysDate (date); OCI_ObjectSetInt (prod, "CODE", 1); OCI_ObjectSetString (prod, "LIBELLE", "USB KEY 2go"); OCI_ObjectSetDouble (prod, "PRICE", 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", & qty); OCI_BindDate (st, "d", date); OCI_Execute (St); printf ( "\ n% d row (s) inserted \ n", OCI_GetAffectedRows (st)); OCI_Commit (cn); OCI_ObjectFree (obj); / * ... * / VIII-B. Selecting objects Objects can be selected in the same way that SQL data types.
http://techdos.com Powered by Joomla! Generated: 21 July, 2011, 13:48

www.techdos.com

Example selection of objects of a table: OCI_Connection * CN; OCI_Statement * st; OCI_Resultset * rs; OCI_Object * Prod; OCI_Date * date; int QTY; / * ... * / OCI_ExecuteStmt (st, "select * from ventes_produits"); rs = OCI_GetResultset (st); while (OCI_FetchNext (rs)) ( OCI_GetObject prod = (rs, 1); OCI_GeInt qty = (rs, 2); OCI_GetDate date = (rs, 3); printf ( "Product:% s, Sales:% i \ n", OCI_ObjectGetString (prod, "LIBELLE"), qty); ) / * ... * / IX. Handling dates and timestamps IX-A. Dates OCILIB capable of handling dates Oracle (time) with ease. Example where a date is recovered from a table, then displayed, incremented by 5 days and 2 months and then redisplayed: Example OCI_Statement * st; OCI_Resultet * st; OCI_Date * DT; char str [100]; / * ... * / st = OCI_CreateStatement (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); ) IX-B. Timestamps The timestamps are extensions to the type DATE:
http://techdos.com Powered by Joomla! Generated: 21 July, 2011, 13:48

www.techdos.com

manage the exact dates through the management of fractions of seconds manage timezones Example where time is running recovered server and displayed with fractions of seconds: Example OCI_Statement * st; * OCI_Timestamp TM; char str [100]; / * ... * / st = OCI_CreateStatement (cn); OCI_ExecuteStmt (st, "SELECT FROM dual CURRENT_TIMESTAMP"); 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); IX-C. Intervals The intervals are periods of time expressed: either in years and months either in days, hours, minutes and seconds They can perform operations on timestamps. Example where time is running local recovered in variable tm, then incremented by 1 day, 1 hour, 1 minute and 1 second and then displayed with fractions of seconds: Example OCI_Connection * CN; * OCI_Timestamp TM; OCI_Interval * ITV; char str [100]; / * ... * / OCI_TimestampCreate tm = (cn, OCI_TIMESTAMP_TZ); ITV OCI_IntervalCreate = (cn, OCI_INTERVAL_DS); OCI_TimestampSysTimeStamp (TM); OCI_IntervalSetDaySecond (ITV, 1,1,1,1,0); OCI_TimestampIntervalAdd (tm, ITV); OCI_TimestampToText (tm, "DD / MM / YYYY HH24: MI: SS: FF3 \ n", 100, str, 3); printf (STR); OCI_IntervalToText (ITV, 10, 10, str, 100); printf (STR); X. To go further X-A. Support Unicode OCILIB fully supports Unicode on all platforms across the data type C wchar_t (UTF16/UTF32 according platforms). OCILIB for builds Unicode, initiates OIC UTF16 mode, which is implemented by Oracle by encoding a fixed size of 2 bytes.
http://techdos.com Powered by Joomla! Generated: 21 July, 2011, 13:48

www.techdos.com

So, on systems implementing wchar_t on 2 bytes (MS Windows), strings and buffers users are passed directly to Oracle. On other systems (almost all Unix and Linux), wchar_t is implemented on 4 bytes and UTF32 is usually used as encoding. In this case, OCILIB: uses buffers to pass a temporary OIC strings of characters of meta-data (queries, attributes, ...) allocates its buffers on the size of wchar_t and execute an expansion of UTF16 a UTF32 for buffer data The expansion of data is "inplace," which has the advantage of not requiring additional buffer. This helps to optimize the better management of variable size type wchar_t. X-B. Describe the tables a scheme OCILIB allows Decrire tables of a scheme. For example: OCI_Connection *cn; OCI_Schema *tbl; int n; /* .. */ tbl = OCI_SchemaGetTable(cn, "MyTable", FALSE); if (tbl) { printf ("Column Name Type Length Prec. Scale Null ?\n"); printf ("---------------------------- ------------------------------\n"); n = OCI_SchemaGetTableColumnCount(tbl); for(i = 1; i <= n; i++) { col = OCI_SchemaGetTableColumn(tbl, 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_SchemaFreeTable(tbl); } /* ... */ X-C. Functions "All In One" OCILIB offers functions "all in one" who have a list of arguments variables. They reduce the number of lines of code to the minimum possible! For example, OCILIB can write to 1 single line of code the following actions:

Preparation of SQL Liaison a variable Execute the statement Fetch the result (1 line) This is equivalent to the following code:
http://techdos.com Powered by Joomla! Generated: 21 July, 2011, 13:48

www.techdos.com

OCI_Prepare (st, "select article from test_fetch where code =: i"); OCI_Bind (st, "code", & code); OCI_Execute (St); OCI_GetResultset (St); OCI_FetchNext (rs); OCI_GetString (rs, 1); Who can be replaced by the following code: OCI_ImmediateFmt (cn, "select article from test_fetch where code =% i", code, OCI_ARG_TEXT, name); Other examples: Exemples OCI_Connection *cn; OCI_Statement *st; OCI_Resultser *rs; /* ... */ /* sql format with params ----------------------------------------------- */ st = OCI_CreateStatement(cn); OCI_ExecuteStmtFmt(st, "select * from test_fetch where code = %i", code); rs = OCI_GetResultset(st); /* ... */ /* 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("code %i - article : %s\n", code, name); /* ... */ /* 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); /* ... */ X-D. Documentation Consult the documentation online Download the online documentation XI. Optimize performance => Some tips to optimize the maximum performance: Avoid OCI_xxxFmt function () because, although very practical, they require a parsing of the order and a SQL formatting variables that can be costly if the complaints are executed many times If an order SQL must be repeated several times, it is better to prepare once with OCI_Prepare (), variables are linked with OCI_Bindxxx () and then execute it as many times as desired with OCI_Exectute () If possible, use tables to link variables If the values affected by a DML must then be reslectionnes, use clause "into Returning" Adjust the number of lines per fetch with OCI_SetFetchSize () Adjust the number of lines prfetches by the server with OCI_SetPrefetchSize () Prefer the Lobs and the LONG LONG RAW To retrieve the values of a resultet use access by index instead access by name columns in order to avoid the use of maps index / name XII. Download
http://techdos.com Powered by Joomla! Generated: 21 July, 2011, 13:48

www.techdos.com

Available at: OCILIB Project page on the site Sourceforge. XIII. Features (version 2.4.0) Here is a non-exhaustive list of main features to the date of the article: => Library: Pur ISO code C (C90 and C99 to support Unicode) Portable on all platforms supported by Oracle API simple and compact Support Unicode complete Supports dynamic loading bookstores Oracles (hence Oracle is not required to compile) Consumption reduced memory Provides hash tables => Type of data: Support of all types of data Oracle (except collections, Refs) All types scalar (strings, digital floating ..): CHAR / NCHAR, VARCHAR2/NVARCHAR2, NUMBER, FLOAT, ... Types binary: RAW, LONG RAW, VARRAW, .. Large Objects (Lobs and Files): BLOB, CLOB, NCLOB, BFILE, CFILE Type LONG (piecewise operations): LONG, LONG VAR, ... Date, Timestamps and Intervals: DATE, TIMESTAMP (all) INTERVAL (all) PL / SQL types: Ref cursors and Nested Tables Named Types: types users and types systems ROWIDs => Features: Compatible with Oracle 8, 8i, 9i, 10g, 11g Support across relational API provided by OIC Partial support of the API object provided by OIC + 310 simple functions Pools of connections API portable hash tables, threads and mutexes Error Handling Global Transactions Data Links Statements reusable SQL Description of a pattern Access to a select columns by position or by name Bulk operations (array interface): insert / update / delete liaison with arrays to accelerate performance Management simple reads / writes in the fields LONG / LOBS Support PL, SQL block, ref cursors Nested tables XIV. Conclusion OCILIB can develop easily and effectively implementing Oracle in C / C + +. The interface of this library has been designed to: Being the simplest possible Propose the wealth of OIC Reducing the number of lines of code and call functions necessary Propose functions with the least possible parameters Respect the principle of encapsulation to prnniser the library (which is why no structure data is public, for example) OCILIB currently does not implement fully OIC in the sense that certain features such as Refs, collections, queues, ... are not supported. It is an open source library and everyone can if it wishes to change the library to its own needs and let others benefit. This tutorial flew in broad library OCILIB. The HTML documentation provides more details and includes features not mentioned in this article.
http://techdos.com Powered by Joomla! Generated: 21 July, 2011, 13:48

www.techdos.com

The current roadmap is as follows: Version 3.0.0: Support comprehensive API Object Relationnal (References, Collections), Queues/SubscriptionsContact the author (Vincent Rogier): vicenzo (developpez.com), vince_del_paris (sourceforge.net) XV. Acknowledgments Corrections RideKick Formatting Franck.H (for its bars magic levels of difficulty)

http://techdos.com

Powered by Joomla!

Generated: 21 July, 2011, 13:48

Vous aimerez peut-être aussi