PK :Aoa,mimetypeapplication/epub+zipPK:AiTunesMetadata.plist] artistName Oracle Corporation book-info cover-image-hash 385976244 cover-image-path OEBPS/dcommon/oracle-logo.jpg package-file-hash 147555682 publisher-unique-id E21637-04 unique-id 38946571 genre Oracle Documentation itemName Oracle® TimesTen In-Memory Database C Developer's Guide, 11g Release 2 (11.2.2) releaseDate 2012-09-18T18:39:01Z year 2012 PK`@Ib]PK:AMETA-INF/container.xml PKYuPK:A OEBPS/oci.htm TimesTen Support for OCI

3 TimesTen Support for OCI

TimesTen and Oracle IMDB Cache support the Oracle Call Interface (OCI) for C or C++ programs.

This chapter provides an overview and TimesTen-specific information regarding OCI, especially emphasizing differences between using OCI with TimesTen versus with Oracle Database. For complete information about OCI, you can refer to Oracle Call Interface Programmer's Guide in the Oracle Database library.

Also note that Chapter 2, "Working with TimesTen Databases in ODBC", contains information that may be of general interest regarding TimesTen features.

The following topics are covered:

Overview of OCI

OCI is an API that provides functions you can use to access the database server and control SQL execution. OCI supports the data types, calling conventions, syntax, and semantics of the C and C++ programming languages. You compile and link an OCI program much as you would any C or C++ program. There is no preprocessing or precompilation step.

The OCI library of database access and retrieval functions is in the form of a dynamic runtime library that can be linked into an application at runtime. The OCI library includes the following functional areas:

The following are among the many useful features that OCI provides or supports:

For general information about OCI, you can refer to Oracle Call Interface Programmer's Guide, included with the Oracle Database documentation set.

Overview of TimesTen OCI support

This chapter contains information specific to using OCI with TimesTen and IMDB Cache. For supported features, TimesTen OCI syntax and usage is the same as that in Oracle Database.

This section covers the following topics:

OCI libraries and architecture

TimesTen OCI depends on the Oracle Database client library and the TimesTen ODBC libraries. TimesTen OCI support enables you to run many existing OCI applications with TimesTen direct connections or client/server connections. It also enables you to use other Oracle Database products, such as Pro*C/C++ and ODP.NET, that use OCI as a database interface. (You can also call PL/SQL from OCI, Pro*C/C++, and ODP.NET applications.) Figure 3-1 shows where OCI support is positioned in the TimesTen architecture.

TimesTen provides Oracle Instant Client as the OCI client library. This is configured through the appropriate ttenv script, as discussed in "Setting the environment for development".

Figure 3-1 OCI in the TimesTen architecture

Description of Figure 3-1 follows
Description of "Figure 3-1 OCI in the TimesTen architecture"

TimesTen 11g Release 2 (11.2.2) OCI is based on Oracle Database release 11.2.0.2 OCI and supports the contemporary OCI 8 style APIs. For example, the OCIStmtExecute() function is supported but not the older oexec() function. See "Obsolete OCI Routines" in Oracle Call Interface Programmer's Guide in the Oracle Database documentation.

Globalization support

This section discusses TimesTen OCI support for globalization.

Character sets

To specify a character set for the connection, OCI programs can set the NLS_LANG environment variable or call OCIEnvNlsCreate(). The setting in the sys.odbc.ini or user odbc.ini file is used by default if not overridden by NLS_LANG or OCIEnvNlsCreate(). Setting the character set explicitly is recommended. The default is typically AMERICAN_AMERICA.US7ASCII.

Note that because TimesTen OCI does not support language or locale (territory) settings, the language and territory components of NLS_LANG, such as AMERICAN_AMERICA above, are ignored. Even when not specifying the language and locale, however, you must still have the period in front of the character set when setting NLS_LANG. For example, either of the following would work, although AMERICAN_AMERICA is ignored:

NLS_LANG=AMERICAN_AMERICA.WE8ISO8859P1

Or:

NLS_LANG=.WE8ISO8859P1

Notes:

  • An NLS_LANG environment setting overrides the TimesTen default character set.

  • The TIMESTEN8 character set is not supported.

  • On Windows, the NLS_LANG setting is searched for in the registry if it is not in the environment. If your OCI or Pro*C/C++ program has trouble connecting to TimesTen, verify that the NLS_LANG setting under HKEY_LOCAL_MACHINE\Software\ORACLE\, if that key exists, is valid and indicates a character set supported by TimesTen. (The NLS_LANG registry setting may not exist or may be set to an invalid value, such as "NA". In these cases, the TimesTen installer will use AMERICAN_AMERICA.US7ASCII.) This is likely only an issue on systems that previously had Oracle9i or earlier Oracle Database versions installed.

  • Refer to "Choosing a Locale with the NLS_LANG Environment Variable" in Oracle Database Globalization Support Guide for information about NLS_LANG.

  • Refer to "OCIEnvNlsCreate()" in Oracle Call Interface Programmer's Guide for information about that OCI call.


Additional globalization features

TimesTen OCI also supports the following additional globalization features. These can be set as environment variables, TimesTen general connection attributes, or TimesTen ODBC connection options. For the connection options, the names here are prepended by "TT_". An environment variable setting takes precedence over a corresponding connection attribute or connection option setting. A connection option setting takes precedence over a corresponding connection attribute setting.

  • NLS_LENGTH_SEMANTICS: By default, the lengths of character data types CHAR and VARCHAR2 are specified in bytes, not characters. For single-byte character encoding this works well. For multibyte character encoding, you can use NLS_LENGTH_SEMANTICS to create CHAR and VARCHAR2 columns using character-length semantics instead. Supported settings are BYTE (default) and CHAR. (NCHAR and NVARCHAR2 columns are always character-based. Existing columns are not affected.)

  • NLS_SORT: This specifies the type of sort for character data. It overrides the default value from NLS_LANGUAGE. Valid values are BINARY or any linguistic sort name supported by TimesTen. For example, to specify the German linguistic sort sequence, set NLS_SORT=German.

  • NLS_NCHAR_CONV_EXCP: This determines whether an error is reported when there is data loss during an implicit or explicit character type conversion between NCHAR or NVARCHAR data and CHAR or VARCHAR2 data. Valid settings are TRUE and FALSE. The default value is FALSE, resulting in no error being reported.

Refer to "Globalization Support" in Oracle TimesTen In-Memory Database Operations Guide and "Setting Up a Globalization Support Environment" in Oracle Database Globalization Support Guide for additional information on these environment variables and related features. See "Option support for SQLSetConnectOption and SQLGetConnectOption" for information about TimesTen connection option support.

TimesTen restrictions and differences

This section discusses the following areas of restrictions and differences for OCI in TimesTen compared to in the Oracle Database:

Oracle Database features not supported

TimesTen does not support OCI calls that are related to functionality that does not exist in TimesTen or IMDB Cache. For example, TimesTen and IMDB Cache do not support these Oracle Database features:

  • Advanced Queuing

  • Any Data

  • Object support

  • Collections

  • Cartridge Services

  • Direct path loading

  • Date/time intervals

  • Iterators

  • BFILEs

  • Cryptographic Toolkit

  • XML DB support

  • Spatial Services

  • Event handling

  • Session switching

  • Scrollable cursors

Additional TimesTen OCI restrictions

TimesTen OCI has the following restrictions:

  • The TypeMode data store attribute must be set to 0, which corresponds to Oracle Database behavior.

  • The DuplicateBindMode general connection attribute must be set to 0, which corresponds to Oracle Database behavior.

  • The DDLCommitBehavior general connection attribute must be set to 0, which corresponds to Oracle Database behavior.

  • Asynchronous calls are not supported.

  • Connection pooling and session pooling are not supported.

  • Describing objects with OCIDescribeAny() is supported only by name. Describing PL/SQL objects is not supported. (Also see the entry for this function under "Supported OCI calls".)

  • TimesTen Client/Server automatic client failover is not supported.

  • The TNSPING utility does not recognize connections to TimesTen.

  • Retrieving implicit ROWID values from INSERT, UPDATE, and DELETE statements is not supported. (This is supported for SELECT FOR UPDATE statements, however.)

  • TimesTen built-in procedures that return result sets are not supported directly.

  • Only a single REF CURSOR can be returned from a PL/SQL block, procedure call, or function call.

  • Binding and defining of structures through OCIBindArrayOfStruct() and OCIDefineArrayOfStruct() is supported for SQL statements but not for PL/SQL. (Also see the entries for these functions under "Supported OCI calls".)

  • Oracle Database utilities such as SQL*Plus and SQL*Loader are not supported. (In TimesTen, you can use ttIsql instead of SQL*Plus and ttBulkCp instead of SQL*Loader. See "Utilities" in Oracle TimesTen In-Memory Database Reference.)

  • Array binding, the ability to bind arrays into PL/SQL statements, is supported for associative arrays (index-by tables or PL/SQL tables) but is not supported for varrays (variable size arrays) or nested tables. (See "Associative array bindings in TimesTen OCI".)

Additional TimesTen OCI differences

Be aware of the following:

  • Both TimesTen and Oracle Database support XA, but TimesTen does not support XA through OCI.

  • With OCI, TimesTen automatically disables autocommit for DML statements. Transactions should be explicitly committed or rolled back when finished.

  • There are differences in the usage of hexadecimal literals in TimesTen. See the description of HexadecimalLiteral in "Constants" in Oracle TimesTen In-Memory Database SQL Reference.

The ttSrcScan utility

If you have an existing OCI program and want to see whether it uses OCI features that TimesTen does not support, you can use the ttSrcScan command line utility to scan your program for unsupported functions, types, type codes, attributes, modes, and constants. This is a standalone utility that can be run without TimesTen or Oracle Database being installed and runs on any platform supported by TimesTen. It reads source code files as input and creates HTML and text files as output. If the utility finds unsupported items, then they are logged and alternatives are suggested. You can find the ttSrcScan executable in the quickstart/sample_util directory in your TimesTen installation.

Specify an input file or directory for the program to be scanned and an output directory for the ttSrcScan reports. Other options are available as well. See the README file in the sample_util directory for information.

Getting started with TimesTen OCI

This section discusses the following topics for getting started with a TimesTen OCI application:

Environment variables for TimesTen OCI

Environment variables for executing a TimesTen OCI application are described in Table 3-1. Settings apply to both direct connections and client/server connections except as noted.

After installation, you can modify environment variables as appropriate through the TimesTen install_dir/bin/ttenv script or quickstart/ttquickstartenv script applicable to your operating system. Also see "Setting the environment for development".

You can also use the TimesTen OCI and Pro*C/C++ Makefiles provided with the Quick Start demos to implement appropriate environment settings. These are in the following locations:

quickstart/sample_code/oci/
quickstart/sample_code/proc/

Refer to "Environment variables" in Oracle TimesTen In-Memory Database Installation Guide for additional information about environment variables and ttenv.


Note:

To ensure proper generation of OCI programs to be run on TimesTen, do not set ORACLE_HOME (or unset it if it was set previously) for OCI compilations.

Table 3-1 Environment variables for TimesTen OCI

VariableRequired or optionalSettings

LD_LIBRARY_PATH (UNIX)

PATH (Windows)

Required

Must be set so that the TimesTen Instant Client directory precedes the Oracle Database libraries in the path. The path will be set properly if you use either of the following scripts under install_dir (the second path assuming the standard Quick Start location):

bin/ttenv
quickstart/ttquickstartenv

TNS_ADMIN

Required if you use the tnsnames naming method

Specifies the directory where the tnsnames.ora file is located. This is also where TimesTen looks for a sqlnet.ora file.

TWO_TASK (UNIX)

LOCAL (Windows)

Optional

You can use this, whichever is appropriate for your platform, instead of specifying the dbname argument in your OCI logon call. The setting consists of a valid TNS name or easy connect string.

See "Connecting to a TimesTen database from OCI" for more information.

NLS_LANG

Optional

See "Character sets". Only the character set component is honored and it must indicate a character set supported by TimesTen. The language and territory values are ignored.

This environment variable overrides the TimesTen default character set.

NLS_SORT

Optional

See "Additional globalization features". The sort order must be a value supported by TimesTen.

This overrides the TimesTen NLS_SORT general connection attribute.

NLS_LENGTH_SEMANTICS

Optional

See "Additional globalization features".

This overrides the TimesTen NLS_LENGTH_SEMANTICS general connection attribute.

NLS_NCHAR_CONV_EXCP

Optional

See "Additional globalization features".

This overrides the TimesTen NLS_NCHAR_CONV_EXCP general connection attribute.



Note:

Refer to "NLS general connection attributes" in Oracle TimesTen In-Memory Database Reference for information about the NLS connection attributes mentioned in the table.

Compiling and linking OCI applications

No changes are required between Oracle Database and TimesTen for the steps to compile and link an OCI application.

OCI programs that use the Oracle Client 11.2.0.2 library do not have to be recompiled or relinked to be executed with TimesTen.

Connecting to a TimesTen database from OCI

TimesTen OCI uses the Oracle Instant Client to connect to the TimesTen database. You can connect to the database through either the tnsnames or the easy connect naming method, similarly to how you would connect to an Oracle database through those methods.

This section covers the following topics:

Refer to "Configuring Naming Methods" in Oracle Database Net Services Administrator's Guide for additional information about tnsnames, easy connect, and the tnsnames.ora file.


Notes:

  • Although the sqlnet mechanism is used for a TimesTen OCI connection, the connection goes through the TimesTen ODBC driver, not the Oracle sqlnet driver.

  • Privilege to connect to the database must be explicitly granted, through the CREATE SESSION privilege, to every user other than the instance administrator who wants to connect to TimesTen. Refer to "Access control for connections".


Using the tnsnames naming method to connect

TimesTen supports tnsnames syntax. You can use a TimesTen tnsnames.ora entry the same way you would use an Oracle tnsnames.ora entry.

The syntax of a TimesTen entry in tnsnames.ora is as follows:

tns_entry = (DESCRIPTION =
              (CONNECT_DATA =
                (SERVICE_NAME = dsn)
                (SERVER = timesten_direct | timesten_client)))

Where tns_entry is the arbitrary TNS name you assign to the entry. You can use this as the dbname argument in OCILogon(), OCILogon2(), and OCIServerAttach() calls.

DESCRIPTION and CONNECT_DATA are required as shown.

For SERVICE_NAME, dsn must be a TimesTen DSN that is configured in the sys.odbc.ini or user odbc.ini file that is visible to a user running your OCI application. On Windows, the DSN can be specified by using the ODBC Data Source Administrator. See "Managing TimesTen Databases" in Oracle TimesTen In-Memory Database Operations Guide.

For SERVER, timesten_direct specifies a direct connection to TimesTen or timesten_client specifies a client/server connection. If you choose timesten_client, the DSN must be configured as a client/server database.

As always, the host and port of the TimesTen server are determined from entries in the sys.ttconnect.ini file, according to the DSN. See "Working with the TimesTen Client and Server" in Oracle TimesTen In-Memory Database Operations Guide.

Here is a sample tnsnames.ora entry for a direct connection:

my_tnsname = (DESCRIPTION = 
               (CONNECT_DATA = 
                 (SERVICE_NAME = my_dsn)
                 (SERVER = timesten_direct))) 

You can use the TNS name, my_tnsname, in either of the following ways:

  • Specify "my_tnsname" for the dbname argument in your OCI logon call.

  • Specify an empty string for dbname and set TWO_TASK or LOCAL to "my_tnsname".

For example:

OCILogon2(envhp, errhp, &svchp,
         (text *)"user1", (ub4)strlen("user1"),
         (text *)"pwd1", (ub4)strlen("pwd1"), 
         (text *)"my_tnsname", (ub4)strlen((char*)"my_tnsname"), OCI_DEFAULT)); 

Refer to "Connect, Authorize, and Initialize Functions" in Oracle Call Interface Programmer's Guide for details about OCI logon calling sequences.

Or on a UNIX system, for example, you can set TWO_TASK to "my_tnsname" and use an OCI logon call with an empty string for dbname:

OCILogon2(envhp, errhp, &svchp,
         (text *)"user1", (ub4)strlen("user1"),
         (text *)"pwd1", (ub4)strlen("pwd1"), 
         (text *)"", (ub4)0, OCI_DEFAULT)); 

Using an easy connect string to connect

TimesTen supports easy connect syntax, which enhances the Instant Client package by allowing connections to be made without configuring tnsnames.ora. An easy connect string has syntax similar to a URL, in the following format:

[//]host[:port]/service_name:server[/instance]

The initial double-slash is optional. A host name must be specified to satisfy easy connect syntax, but is otherwise ignored by TimesTen. The name "localhost" is typically used by convention. Any value specified for the port is also ignored. For client/server connections, the host and port of the TimesTen server are determined from entries in the sys.ttconnect.ini file, according to the TimesTen DSN.

Specify the DSN for service_name. Specify timesten_client or timesten_direct, as appropriate, for server.

TimesTen ignores the instance field and does not require that it be specified.

For example, the following easy connect string connects to a TimesTen server using the client/server libraries. Assume a DSN ttclient in the sys.odbc.ini file is resolved as a client/server data source and connects to the corresponding host and port specified in the sys.ttconnect.ini file:

"localhost/ttclient:timesten_client"

The following easy connect string is for a direct connection to TimesTen. Assume the DSN ttdirect is defined in sys.odbc.ini:

"localhost/ttdirect:timesten_direct"

You can use an easy connect string in either of the following ways:

  • Specify it for the dbname argument in your OCI logon call.

  • Specify an empty string for dbname and set TWO_TASK or LOCAL to the easy connect string, in quotes.

For example:

OCILogon2(envhp, errhp, &svchp,
         (text *)"user1", (ub4)strlen("user1"),
         (text *)"pwd1", (ub4)strlen("pwd1"),
         (text *)"localhost/ttclient:timesten_client",
         (ub4)strlen((char*)"localhost/ttclient:timesten_client"), OCI_DEFAULT));

Refer to "Connect, Authorize, and Initialize Functions" in Oracle Call Interface Programmer's Guide for details about OCI logon calling sequences.

Or on a UNIX system, for example, you can set TWO_TASK to "localhost/ttclient:timesten_client" and use an OCI logon call with an empty string for dbname:

OCILogon2(envhp, errhp, &svchp,
         (text *)"user1", (ub4)strlen("user1"),
         (text *)"pwd1", (ub4)strlen("pwd1"), 
         (text *)"", (ub4)0, OCI_DEFAULT)); 

Configuring whether to use tnsnames.ora or easy connect

If a sqlnet.ora file is present, it specifies the naming methods that will be tried and the order in which they will be tried. The Instant Client will look for a sqlnet.ora file at the TNS_ADMIN location, if applicable. If TNS_ADMIN has not been set but ORACLE_HOME has been (such as if you had a previous Instant Client installation), the default sqlnet.ora location is the Oracle Database default location as noted in "Parameters for the sqlnet.ora File" in Oracle Database Net Services Reference.

If sqlnet.ora is found and does not indicate a particular naming method, you cannot use that method. If sqlnet.ora is not found, you can use either method.

In TimesTen, sample copies of tnsnames.ora and sqlnet.ora are in the install_dir/network/admin/samples directory. Here is the sqlnet.ora file that TimesTen provides, which supports both tnsnames and easy connect ("EZCONNECT"):

# To use ezconnect syntax or tnsnames, the following entries must be
# included in the sqlnet.ora configuration.
#
NAMES.DIRECTORY_PATH= (TNSNAMES, EZCONNECT)

With this file, TimesTen will first look for tnsnames syntax in your OCI logon calls. If it cannot find tnsnames syntax, it will look for easy connect syntax.

Connecting as an externally identified user in OCI

You can connect through OCI as an externally identified user (external user) by specifying the user name in brackets, such as "[myadmin]", and the password as an empty string, "".

In particular, this is useful in connecting as the instance administrator, which in TimesTen is always an external user.

Adapting an earlier example:

OCILogon2(envhp, errhp, &svchp,
         (text *)"[myadmin]", (ub4)strlen("[myadmin]"),
         (text *)"", (ub4)strlen(""), 
         (text *)"my_tnsname", (ub4)strlen((char*)"my_tnsname"), OCI_DEFAULT)); 

This functionality uses OCI proxy syntax. You can refer to the discussion of client access through a proxy in Oracle Call Interface Programmer's Guide.

Error reporting

Errors under TimesTen OCI applications return Oracle Database error codes. TimesTen attempts to report the same error code as Oracle Database would under similar conditions. The error messages may come from either the TimesTen catalog or the Oracle Database catalog. Some error messages may indicate the accompanying TimesTen error code if appropriate.

Fatal errors are those that make the database inaccessible until after error recovery. When a fatal error occurs, all database connections are required to disconnect in order to avoid out-of-memory conditions. No further operations may complete. Shared memory from the old TimesTen instance will not be freed until all active connections at the time of the error have disconnected.

Fatal errors in OCI are indicated by the Oracle Database error code ORA-03135 or ORA-00600. Error handling for these errors should be different from standard error handling. In particular, the application error-handling code should have a disconnect from the database.

Signal handling and diagnostic framework considerations

The OCI diagnostic framework installs signal handlers that may impact any signal handling that you use in your application. You can disable OCI signal handling by setting DIAG_SIGHANDLER_ENABLED=FALSE in the sqlnet.ora file. Refer to "Fault Diagnosability in OCI" in Oracle Call Interface Programmer's Guide for information.

OCI demo programs

TimesTen ships OCI demo programs. They are in the quickstart/sample_code/oci directory. The README file in the directory explains how to compile and run the demos.

Refer to the Quick Start welcome page at install_dir/quickstart.html for information.

Additional features of TimesTen OCI

This section covers the following topics for developers using TimesTen OCI:

TimesTen deferred prepare

In OCI, a prepare call is expected to be a lightweight operation performed on the client. To allow TimesTen to be consistent with this expectation, and to avoid unwanted round trips between client and server, the TimesTen client library implementation of SQLPrepare performs what is referred to as a deferred prepare, where the request is not sent to the server until required. See "TimesTen deferred prepare".

Parameter binding features in TimesTen OCI

This section discusses features relating to binding parameters into SQL or PL/SQL from an OCI application:

Duplicate parameter bindings in TimesTen OCI

"Binding duplicate parameters in SQL statements" discusses the two supported modes for binding duplicate parameters in a SQL statement, either the Oracle mode or the traditional TimesTen mode. As in that section, consider the following query. Note that in TimesTen OCI, only the Oracle mode is supported.

SELECT * FROM employees
  WHERE employee_id < :a AND manager_id > :a AND salary < :b;

In OCI, as in the Oracle mode in general, two occurrences of parameter a are considered to be separate parameters. However, OCI allows both occurrences of a to be bound with a single call to OCIBindByPos():

OCIBindByPos(..., 1, ...); /* both occurrences of :a */
OCIBindByPos(..., 3, ...); /* occurrence of :b */

Alternatively, OCI also allows the two occurrences of a to be bound separately:

OCIBindByPos(..., 1, ...); /* first occurrence of :a */
OCIBindByPos(..., 2, ...); /* second occurrence of :a */
OCIBindByPos(..., 3, ...); /* occurrence of :b */

Note that in both cases, parameter b is considered to be in position 3.


Note:

OCI also allows parameters to be bound by name, rather than by position, using OCIBindByName().

Associative array bindings in TimesTen OCI

Associative arrays, formerly known as index-by tables or PL/SQL tables, are supported as IN, OUT, or IN OUT bind parameters in TimesTen PL/SQL, such as from an OCI application. This enables arrays of data to be passed efficiently between an application and the database.

An associative array is a set of key-value pairs. In TimesTen, for associative array binding (but not for use of associative arrays only within PL/SQL), the keys, or indexes, must be integers (BINARY_INTEGER or PLS_INTEGER). The values must be simple scalar values of the same data type. For example, there could be an array of department managers indexed by department numbers. Indexes are stored in sort order, not creation order.

You can declare an associative array type and then an associative array from PL/SQL as in the following example (note the INDEX BY):

declare
   TYPE VARCHARARRTYP IS TABLE OF VARCHAR2(30) INDEX BY BINARY_INTEGER;
   x VARCHARARRTYP;
   ...

For Pro*C/C++, see "Associative array bindings in TimesTen Pro*C/C++".

For related information, see "Using associative array binds from applications" in Oracle TimesTen In-Memory Database PL/SQL Developer's Guide.


Notes:

Note the following restrictions in TimesTen:
  • The following types are not supported in binding associative arrays: LOBs, REF CURSORs, TIMESTAMP, ROWID.

  • Associative array binding is not allowed in passthrough statements.

  • General bulk binding of arrays is not supported in TimesTen OCI. Varrays and nested tables are not supported as bind parameters.


TimesTen supports associative array binds in OCI by supporting the maxarr_len and *curelep parameters of the OCIBindByName() and OCIBindByPos() functions. These parameters are used to indicate that the binding is for an associative array.

The complete calling sequences for those functions are as follows:

sword OCIBindByName ( OCIStmt *stmtp,
                      OCIBind **bindpp,
                      OCIError *errhp,
                      const OraText *placeholder,
                      sb4 placeh_len,
                      void *valuep,
                      sb4 value_sz,
                      ub2 dty,
                      void *indp,
                      ub2 *alenp,
                      ub2 *rcodep,
                      ub4 maxarr_len,
                      ub4 *curelep,
                      ub4 mode );

sword OCIBindByPos ( OCIStmt *stmtp,
                     OCIBind **bindpp,
                     OCIError *errhp,
                     ub4 position,
                     void *valuep,
                     sb4 value_sz,
                     ub2 dty,
                     void *indp,
                     ub2 *alenp,
                     ub2 *rcodep,
                     ub4 maxarr_len,
                     ub4 *curelep,
                     ub4 mode );

The maxarr_len and *curelep parameters are used as follows when you bind an associative array. (They should be set to 0 if you are not binding an associative array.)

  • maxarr_len: This is an input parameter indicating the maximum array length. This is the maximum number of elements that the associative array can accommodate.

  • *curelep: This is an input/output parameter indicating the current array length. It is a pointer to the actual number of elements in the associative array before and after statement execution.

For additional information about these functions, see "OCIBindByName()" and "OCIBindByPos()" in Oracle Call Interface Programmer's Guide.


Note:

In TimesTen, the OCIBindDynamic() function and the OCI_DATA_AT_EXEC mode setting for OCIBindByName() and OCIBindByPos() are not supported. (In Oracle Database, OCIBindDynamic() can be used to register user-defined callback functions to provide or receive data in "at exec" mode to set up additional bind attributes at execution time.)

In Example 3-1, an OCI application binds an integer array and a character array to corresponding OUT associative arrays in a PL/SQL procedure.

Example 3-1 Binding to an associative array from OCI

Assume the following SQL setup.

DROP TABLE FOO;
 
CREATE TABLE FOO (CNUM INTEGER,
                  CVC2 VARCHAR2(20));
 
INSERT INTO FOO VALUES ( null,
     'VARCHAR  1');
INSERT INTO FOO VALUES (-102,
     null);
INSERT INTO FOO VALUES ( 103,
     'VARCHAR  3');
INSERT INTO FOO VALUES (-104,
     'VARCHAR  4');
INSERT INTO FOO VALUES ( 105,
     'VARCHAR  5');
INSERT INTO FOO VALUES ( 106,
     'VARCHAR  6');
INSERT INTO FOO VALUES ( 107,
     'VARCHAR  7');
INSERT INTO FOO VALUES ( 108,
     'VARCHAR  8');
 
COMMIT;

Assume the following PL/SQL package definition. This has the INTEGER associative array type NUMARRTYP and the VARCHAR2 associative array type VCHARRTYP, used for output associative arrays c1 and c2, respectively, in the definition of procedure P1.

CREATE OR REPLACE PACKAGE PKG1 AS
  TYPE NUMARRTYP IS TABLE OF INTEGER INDEX BY BINARY_INTEGER;
  TYPE VCHARRTYP IS TABLE OF VARCHAR2(20) INDEX BY BINARY_INTEGER;
 
  PROCEDURE P1(c1 OUT NUMARRTYP,c2 OUT VCHARRTYP);
 
END PKG1;
/
 
CREATE OR REPLACE PACKAGE BODY PKG1 AS
 
  CURSOR CUR1 IS SELECT CNUM, CVC2 FROM FOO;
 
  PROCEDURE P1(c1 OUT NUMARRTYP,c2 OUT VCHARRTYP) IS
  BEGIN
    IF NOT CUR1%ISOPEN  THEN
      OPEN CUR1;
    END IF;
    FOR i IN 1..8 LOOP
      FETCH CUR1 INTO c1(i), c2(i);
      IF CUR1%NOTFOUND THEN
        CLOSE CUR1;
        EXIT;
      END IF;
    END LOOP;
  END P1;
 
END PKG1;

The following OCI program calls PKG1.P1, binds arrays to the P1 output associative arrays, and prints the contents of those associative arrays. Note in particular the OCIBindByName() function calls to do the binding.

static OCIEnv *envhp;
static OCIServer *srvhp;
static OCISvcCtx *svchp;
static OCIError *errhp;
static OCISession *authp;
static OCIStmt *stmthp;
static OCIBind *bndhp[MAXCOLS];
static OCIBind *dfnhp[MAXCOLS];
 
STATICF VOID outbnd_1()
{
  int   i;
  int   num[MAXROWS];
  char*   vch[MAXROWS][20];
 
  unsigned int    numcnt   = 5;
  unsigned int    vchcnt = 5;
 
  unsigned short    alen_num[MAXROWS];
  unsigned short    alen_vch[MAXROWS];
  unsigned short    rc_num[MAXROWS];
  unsigned short    rc_vch[MAXROWS];
 
  short    indp_num[MAXROWS];
  short    indp_vch[MAXROWS];
 
/* Assume the process is connected and srvhp, svchp, errhp, authp, and stmthp 
   are all allocated/initialized/etc. */
 
  char  *sqlstmt = (char *)"BEGIN PKG1.P1(:c1, :c2); END; ";
 
  for (i = 0; i < MAXROWS; i++)
  {
    alen_num[i] = 0;
    alen_vch[i] = 0;
    rc_num[i] = 0;
    rc_vch[i] = 0;
    indp_num[i] = 0;
    indp_vch[i] = 0;
  }
 
  DISCARD printf("Running outbnd_1.\n");
  DISCARD printf("\n----> %s\n", sqlstmt);
  checkerr(errhp, OCIStmtPrepare(stmthp, errhp, sqlstmt, 
           (unsigned int)strlen((char *)sqlstmt),
           (unsigned int) OCI_NTV_SYNTAX, (unsigned int) OCI_DEFAULT));
 
  bndhp[0] = 0;
  bndhp[1] = 0;
 
  checkerr(errhp, OCIBindByName(stmthp, &bndhp[0], errhp,
                  (char *) ":c1", (sb4) strlen((char *) ":c1"),
                  (dvoid *) &num[0], (sb4) sizeof(num[0]), SQLT_INT,
                  (dvoid *) &indp_num[0], (unsigned short *) &alen_num[0],
                  (unsigned short *) &rc_num[0],
                  (unsigned int) MAXROWS, (unsigned int *) &numcnt, 
                  (unsigned int) OCI_DEFAULT));
 
  checkerr(errhp, OCIBindByName(stmthp, &bndhp[1], errhp,
                  (char *) ":c2", (sb4) strlen((char *) ":c2"),
                  (dvoid *) vch[0], (sb4) sizeof(vch[0]), SQLT_CHR,
                  (dvoid *) &indp_vch[0], (unsigned short *) &alen_vch[0],
                  (unsigned short *) &rc_vch[0],
                  (unsigned int) MAXROWS, (unsigned int *) &vchcnt, 
                  (unsigned int) OCI_DEFAULT));
 
  DISCARD printf("\nTo execute the PL/SQL statement.\n");
 
  checkerr(errhp, OCIStmtExecute(svchp, stmthp, errhp, (unsigned int) 1, 
                  (unsigned int) 0, (const OCISnapshot*) 0,
                  (OCISnapshot*) 0,  (unsigned int) OCI_DEFAULT));
 
  DISCARD printf("\nHere are the results:\n\n");
 
  DISCARD printf("Column 1, INTEGER: \n");
  for (i = 0; i < numcnt; i++)
  {
    if (indp_num[i] == -1)
      DISCARD printf("-NULL- ");
    else
      DISCARD printf("%5d, ", num[i]);
    DISCARD printf("ind = %d,  len = %d, rc = %d\n",
                             indp_num[i], alen_num[i], rc_num[i]);
  }
 
  DISCARD printf("\nColumn 2, VARCHAR2(20): \n");
  for (i = 0; i < vchcnt; i++)
  {
    if (indp_vch[i] == -1)
      DISCARD printf("-NULL-      ");
    else
      DISCARD printf("%.*s, ", alen_vch[i], vch[i]);
    DISCARD printf("ind = %d,  len = %d, rc = %d\n",
                             indp_vch[i], alen_vch[i], rc_vch[i]);
  }
 
  DISCARD printf("\nDone\n");
  return;
}

Note:

The alen_* arrays are arrays of lengths; the rc_* arrays are arrays of return codes; the indp_* arrays are arrays of indicators.

IMDB Cache with TimesTen OCI

This section discusses TimesTen OCI features related using the IMDB Cache:

Specifying the Oracle Database password in OCI for IMDB Cache

To use IMDB Cache, there must be a cache user in the TimesTen database with the same name as an Oracle Database user who can select from and update the cached Oracle Database tables. This Oracle Database user, for example, can be the cache administration user or a schema user. The password of the TimesTen cache user can be different from the password of the Oracle Database user with the same name. See "Setting Up a Caching Infrastructure" in Oracle In-Memory Database Cache User's Guide for details.

For use of OCI with the IMDB Cache, TimesTen allows you to pass the Oracle Database user's password through OCI by appending it to the password field in an OCILogon() or OCILogon2() call when you log in to TimesTen. Use the attribute OraclePWD in the connect string, such as in the following example:

text *cacheuser = (text *)"cacheuser1";
text *cachepwds = (text *)"ttpwd;OraclePWD=orclpwd";
text *ttdbname = (text *)"tt_tnsname";
....
OCILogon2(envhp, errhp, &svchp,
       (text *)cacheuser, (ub4)strlen(cacheuser),
       (text *)cachepwds, (ub4)strlen(cachepwds),
       (text *)ttdbname, (ub4)strlen(ttdbname), OCI_DEFAULT)); 

You must always specify OraclePWD, even if the Oracle Database user's password is the same as the TimesTen user's password.

Note the following for the example:

  • The name of the TimesTen cache user, as well as the name of the Oracle Database user who can access the cached Oracle Database tables, is cacheuser1.

  • The password of the TimesTen cache user is ttpwd.

  • The password of the Oracle Database user is orclpwd.

  • The TNS name of the TimesTen database being connected to is tt_tnsname.

The Oracle database is specified through the TimesTen OracleNetServiceName general connection attribute in the sys.odbc.ini or user odbc.ini file.

Alternatively, instead of using a TNS name, you could use easy connect syntax or the TWO_TASK or LOCAL environment variable, as discussed in preceding sections.

Determining the number of cache groups affected by an action

In TimesTen OCI, following the execution of a FLUSH CACHE GROUP, LOAD CACHE GROUP, REFRESH CACHE GROUP, or UNLOAD CACHE GROUP statement, the OCI Function OCIAttrGet() with the OCI_ATTR_ROW_COUNT argument returns the number of cache instances that were flushed, loaded, refreshed, or unloaded.

For related information, see "Determining the number of cache instances affected by an operation" in the Oracle In-Memory Database Cache User's Guide.

LOBs in TimesTen OCI

TimesTen supports LOBs (large objects). This includes CLOBs (character LOBs), NCLOBs (national character LOBs), and BLOBs (binary LOBs).

See "Working with LOBs". That section is ODBC-oriented but also provides some general overview of LOBs, differences between TimesTen and Oracle Database LOBs, and LOB programming interfaces.

This section focuses on LOB locators, temporary LOBs, and OCI LOB APIs and features.

See "LOB data types" in Oracle TimesTen In-Memory Database SQL Reference for additional information about LOBs in TimesTen.

For complete information about LOBs and how to use them in OCI, refer to "LOB and BFILE Operations" in Oracle Call Interface Programmer's Guide, keeping in mind that TimesTen does not support BFILEs, SecureFiles, array reads and writes for LOBs, or callback functions for LOBs.

The following topics are covered here for OCI:


Note:

The LOB piecewise data interface is not applicable to OCI applications in TimesTen. (You can, however, manipulate LOB data in pieces through features of the LOB locator interface.)

LOB locators in OCI

OCI provides the LOB locator interface, where a LOB consists of a LOB locator and a LOB value. The locator acts as a handle to the value. When an application selects a LOB from the database, it receives a locator. When it updates the LOB, it does so through the locator. And when it passes a LOB as a parameter, it is passing the locator, not the actual value. See "Using the LOB locator interface in OCI". (Note that in OCI it is also possible to use the simple data interface, which does not involve a locator. See "Using the LOB simple data interface in OCI".)

To update a LOB, your transaction must have an exclusive lock on the row containing the LOB. You can accomplish this by selecting the LOB with a SELECT ... FOR UPDATE statement. This results in a writable locator. With a simple SELECT statement, the locator is read-only. Read-only and writable locators behave as follows:

  • A read-only locator is read consistent, meaning that throughout its lifetime, it sees only the contents of the LOB as of the time it was selected. Note that this would include any uncommitted updates made to the LOB within the same transaction prior to when the LOB was selected.

  • A writable locator is updated with the latest data from the database each time a write is made through the locator. So each write is made to the most current data of the LOB, including updates that have been made through other locators.

The following example details behavior for two writable locators for the same LOB:

  1. The LOB column contains "XY".

  2. Select locator L1 for update.

  3. Select locator L2 for update.

  4. Write "Z" through L1 at offset 1.

  5. Read through locator L1. This would return "ZY".

  6. Read through locator L2. This would return "XY", because L2 remains read-consistent until it is used for a write.

  7. Write "W" through L2 at offset 2.

  8. Read through locator L2. This would return "ZW". Prior to the write in the preceding step, the locator was updated with the latest data ("ZY").

Temporary LOBs in OCI

A temporary LOB exists only within an application, and in TimesTen OCI has a lifetime no longer than the transaction in which it was created (as is the case with the lifetime of any LOB locator in TimesTen). You can think of a temporary LOB as a scratch area for LOB data.

An OCI application can instantiate a temporary LOB explicitly, for use within the application, through the appropriate API. (See "Using the LOB locator interface in OCI".) A temporary LOB may also be created implicitly by TimesTen. For example, if a SELECT statement selects a LOB concatenated with an additional string of characters, TimesTen will implicitly create a temporary LOB to contain the concatenated data and an OCI application would receive a locator for the temporary LOB.

Temporary LOBs are stored in the TimesTen temporary data partition.

Differences between TimesTen LOBs and Oracle Database LOBs in OCI

A key difference between the TimesTen LOB implementation and the Oracle Database implementation is that in TimesTen, LOB locators do not remain valid past the end of the transaction. All LOB locators are invalidated after a commit or rollback, whether explicit or implicit. This includes after any DDL statement if TimesTen DDLCommitBehavior is set to 0 (the default), for Oracle Database behavior.

Also see "Differences between TimesTen LOBs and Oracle Database LOBs".

Using the LOB simple data interface in OCI

The simple data interface enables applications to access LOB data by binding and defining, as with other scalar data types. The application can use a LOB type that is compatible with the corresponding variable type. Use OCIStmtPrepare() to prepare a statement. For binding parameters, use OCIBindByName() or OCIBindByPos(). For defining result columns, use OCIDefineByPos().

For example, an OCI application can bind a CLOB parameter by calling OCIBindByName() with a data type of SQLT_CHR. Use OCIStmtExecute() to execute the statement. For an NCLOB parameter, use data type SQLT_CHR and set the OCI csform attribute (OCI_ATTR_CHARSET_FORM) to SQLCS_NCHAR. For a BLOB parameter, you can use data type SQLT_BIN.

Use of the simple data interface through OCI is shown in the following examples.


Note:

The simple data interface, through OCIBindByName(), OCIBindByPos(), or OCIDefineByPos(), limits bind sizes to 64 KB.

Example 3-2 Example table and variables

For examples that follow, assume the table and variables shown here.

person(ssn number, resume clob)
 
OCIEnv *envhp;
OCIServer *srvhp;
OCISvcCtx *svchp;
OCIError *errhp;
OCISession *authp;
OCIStmt *stmthp;
 
/* Bind Handles */
OCIBind *bndp1 = (OCIBind *) NULL; 
OCIBind *bndp2 = (OCIBind *) NULL;
 
/* Define Handles */
OCIDefine *defnp1 = (OCIDefine *) NULL;
OCIDefine *defnp2 = (OCIDefine *) NULL;
 
#define DATA_SIZE 50
#define PIECE_SIZE 10
#define NPIECE (DATA_SIZE/PIECE_SIZE)
 
char col2[DATA_SIZE];
char col2Res[DATA_SIZE];
ub2 col2len = DATA_SIZE;
sb4 ssn = 123456;
...

text *ins_stmt = (text *)"INSERT INTO PERSON VALUES (:1, :2)";
text *sel_stmt = (text *)"SELECT * FROM PERSON_1 ORDER BY SSN";
...

Example 3-3 Insert LOB data using simple data interface

This example executes an INSERT statement using the simple data interface in OCI. It uses the table and variables from the preceding Example 3-2, including the INSERT statement defined through the variable ins_stmt.

for (i=0;i<DATA_SIZE;i++) 
  col2[i] = 'A';
 
/* prepare SQL insert statement */
OCIStmtPrepare (stmthp, errhp, ins_stmt, strlen(ins_stmt), OCI_NTV_SYNTAX,
    OCI_DEFAULT);
 
/* bind parameters 1 and 2 using OCI_DEFAULT (not data-at-exec) */
OCIBindByPos (stmthp, &bndp1, errhp, 1, (dvoid *) &ssn, sizeof(ssn), 
 SQLT_INT, 0, 0, 0, 0, 0, OCI_DEFAULT);
OCIBindByPos (stmthp, &bndp2, errhp, 2, (dvoid *) col2, col2len,
                           SQLT_CHR, 0, 0, 0, 0, 0, OCI_DEFAULT);
 
/* execute insert statement */
OCIStmtExecute (svchp, stmthp, errhp, 1, 0, 0, 0, OCI_DEFAULT);

Example 3-4 Select LOB data using simple data interface

This example executes a SELECT statement using the simple data interface in OCI. It uses the table and variables from the earlier Example 3-2, including the SELECT statement defined through the variable sel_stmt.

/* prepare select statement */
OCIStmtPrepare (stmthp, errhp, sel_stmt, strlen(sel_stmt), OCI_NTV_SYNTAX,
    OCI_DEFAULT);
 
/* define result columns 1 and 2 using OCI_DEFAULT (not data-at-exec) */
OCIDefineByPos (stmthp, &defnp1, errhp, 1, (dvoid*) &ssn, sizeof(ssn), 
                              SQLT_INT, 0, 0, 0, OCI_DEFAULT);
OCIDefineByPos (stmthp, &defnp2, errhp, 2, (dvoid *) col2Res, sizeof(col2), 
                              SQLT_CHR, 0, &col2len, 0, OCI_DEFAULT);
 
/* execute select statement */
OCIStmtExecute (svchp, stmthp, errhp, (ub4)1, (ub4)0, (OCISnapshot *) NULL, 
                              (OCISnapshot *) NULL, OCI_DEFAULT));
 
/* col2Res should now have a DATA_SIZE sized string of 'A's. */

Using the LOB locator interface in OCI

You can use the OCI LOB locator interface to work with either a LOB from the database or a temporary LOB, either piece-by-piece or in whole chunks.

In order to use the LOB locator interface, the application must have a valid LOB locator. For a temporary LOB, this is obtained through the OCILobCreateTemporary() call, for explicitly created LOBs, or through a SQL statement that results in implicit creation of a temporary LOB (such as SELECT c1 || c2 FROM myclob). For a persistent LOB, use a SQL statement to obtain the LOB locator from the database. (There are examples later in this section.)

Bind types are SQLT_CLOB for CLOBs and SQLT_BLOB for BLOBs. For NCLOBs, use SQLT_CLOB and also set the OCI csform attribute (OCI_ATTR_CHARSET_FORM) to SQLCS_NCHAR.

Refer to "LOB Functions" in Oracle Call Interface Programmer's Guide for detailed information and additional examples for OCI LOB functions, noting that TimesTen does not support features specifically intended for BFILEs, SecureFiles, array reads and writes for LOBs, or callback functions for LOBs.


Important:

LOB manipulations through APIs that use LOB locators result in usage of TimesTen temporary space. Any significant number of such manipulations may necessitate a size increase for the TimesTen temporary data partition. See "TempSize" in Oracle TimesTen In-Memory Database Reference.


Notes:

  • If an invalid LOB locator is assigned to another LOB locator using OCILobLocatorAssign(), the target of the assignment is also freed and marked as invalid.

  • OCILobLocatorAssign() can be used on a temporary LOB, but OCILobAssign() cannot.


Create a temporary LOB in OCI

An OCI application can create a temporary LOB by using the OCILobCreateTemporary() function, which has an input/output parameter for the LOB locator, after first calling OCIDescriptorAlloc() to allocate the locator. When you are finished, use OCIDescriptorFree() to free the allocation for the locator and use OCILobFreeTemporary() to free the temporary LOB itself.


Important:

In TimesTen, creation of a temporary LOB will result in creation of a database transaction if one is not already in progress. To avoid error conditions, you must execute a commit or rollback to close the transaction.

In TimesTen, any duration supported by Oracle Database (OCI_DURATION_SESSION, OCI_DURATION_TRANSACTION, or OCI_DURATION_CALL) is permissible in the OCILobCreateTemporary() call; however, in TimesTen the lifetime of the temporary LOB itself will be no longer than the lifetime of the transaction.

Note that the lifetime of a temporary LOB can be shorter than the lifetime of the transaction in the following scenarios:

  • If OCI_DURATION_CALL is specified

  • If the application calls OCILobFreeTemporary() on the locator before the end of the transaction

  • If the application calls OCIDurationBegin() to start a user-specified duration for the temporary LOB, then calls OCIDurationEnd() before the end of the transaction

Following are examples of some of the OCI LOB functions mentioned above. For details about the use of temporary LOBs and a complete example, see "Temporary LOB Support" in Oracle Call Interface Programmer's Guide.

if (OCIDescriptorAlloc((void*)envhp, (void **)&tblob,(ub4)OCI_DTYPE_LOB,
    (size_t)0, (void**)0))
{
   printf("failed in OCIDescriptor Alloc in select_and_createtemp \n");
   return OCI_ERROR;
}
 
...
 
if (OCILobCreateTemporary(svchp, errhp, tblob, (ub2)0, SQLCS_IMPLICIT,
    OCI_TEMP_BLOB, OCI_ATTR_NOCACHE, OCI_DURATION_TRANSACTION))
{
   (void) printf("FAILED: OCILobCreateTemporary() \n");
   return OCI_ERROR;
}
 
...
 
if(OCILobFreeTemporary(svchp,errhp,tblob))
{
   printf ("FAILED: OCILobFreeTemporary() call \n");
   return OCI_ERROR;
}
Access the locator of a persistent LOB in OCI

An application typically accesses a LOB from the database by using a SQL statement to obtain or access a LOB locator, then passing the locator to an appropriate API function.

A LOB that has been created using the EMPTY_CLOB() or EMPTY_BLOB() SQL function has a valid locator, which an application can then use to insert data into the LOB by selecting it.

Assume the following table definition:

CREATE TABLE clobtable (x NUMBER, y DATE, z VARCHAR2(30), lobcol CLOB);
  1. Prepare an INSERT statement. For example:

    INSERT INTO clobtable ( x, y, z, lobcol )
       VALUES ( 81, sysdate, 'giants', EMPTY_CLOB() )
       RETURNING lobcol INTO :a;
    

    Or, to initialize the LOB with some data:

    INSERT INTO clobtable ( x, y, z, lobcol )
       VALUES ( 81, sysdate, 'giants', 'The Giants finally won a World Series' )
       RETURNING lobcol INTO :a;
    
  2. Bind the LOB locator to :a as shown.

  3. Execute the statement. After execution, the locator will refer to the newly created LOB.

Then the application can use the LOB locator interface to read or write LOB data through the locator.

Alternatively, an application can use a SELECT statement to access the locator of an existing LOB.

Example 3-5 Select LOB locator using LOB locator interface

This example uses the following table:

person(ssn number, resume clob)

It selects the locator for the LOB column in the PERSON table.

text *ins_stmt = (text *)"INSERT INTO PERSON VALUES (:1, :2)";
text *sel_stmt = (text *)"SELECT * FROM PERSON WHERE SSN = 123456";
text *ins_empty = (text *)"INSERT INTO PERSON VALUES ( 1, EMPTY_CLOB())";
 
OCILobLocator *lobp;
 
ub4   amtp = DATA_SIZE;
ub4   remainder = DATA_SIZE;
ub4    nbytes = PIECE_SIZE;
 
/* Allocate lob locator */
OCIDescriptorAlloc (envhp, &lobp, OCI_DTYPE_LOB, 0, 0);
 
/* Insert an empty locator */
OCIStmtPrepare (stmhp, errhp, ins_empty, strlen(ins_empty), OCI_NTV_SYNTAX, 
                               OCI_DEFAULT);
OCIStmtExecute (svchp, stmhp, errhp, 1, 0, 0, 0, OCI_DEFAULT);
 
/* Now select the locator */
 
OCIStmtPrepare (stmhp, errhp, sel_stmt, strlen(sel_stmt), OCI_NTV_SYNTAX,
                OCI_DEFAULT);
 
/* Call define for the lob column */
OCIDefineByPos (stmthp, &defnp2, errhp, 1, &lobp, 0 , SQLT_CLOB, 0, 0, 0,
                OCI_DEFAULT);
 
OCIStmtExecute (svchp, stmhp, errhp, 1, 0, 0, 0, OCI_DEFAULT);
Read and write LOB data using the OCI LOB locator interface

An OCI application can use OCILobOpen() and OCILobClose() to open and close a LOB. If you do not explicitly open and close a LOB, it will be opened implicitly before a read or write and closed implicitly at the end of the transaction.

An application can use OCILobRead() or OCILobRead2() to read LOB data, OCILobWrite() or OCILobWrite2() to write LOB data, OCILobWriteAppend() or OCILobWriteAppend2() to append LOB data, OCILobErase() or OCILobErase2() to erase LOB data, and various other OCI functions to perform a variety of other actions.

For example, consider a CLOB with the content "Hello World!" You can overwrite and append data by calling OCILobWrite() with an offset of 7 to write "I am a new string". This would result in CLOB content being updated to "Hello I am a new string". Or, to erase data from the original "Hello World!" CLOB, you can call OCILobErase() with an offset of 7 and an amount (number of characters) of 5, for example, to update the CLOB to "Hello      !" (six spaces).

All the OCI LOB locator interface functions are covered in detail in "LOB Functions" in Oracle Call Interface Programmer's Guide.


Notes:

  • Oracle Database emphasizes use of the "2" versions of the OCI read and write functions for LOBs (the non-"2" versions are deprecated as of the Oracle Database 11.2 release); however, currently in TimesTen there is no technical advantage in using OCILobRead2(), OCILobWrite2(), and OCILobWriteAppend2(), which are intended for LOBs larger than what TimesTen supports.

  • In using any of the LOB read or write functions, be aware that the callback function parameter must be set to NULL or 0, because TimesTen does not support callback functions for LOB manipulation.

  • Because TimesTen does not support binding arrays of LOBs, the OCILobArrayRead() and OCILobArrayWrite() functions are not supported.


Example 3-6 Write and read LOB data using LOB locator interface

This example shows how to write LOB data using the OCI LOB function OCILobWrite() and how to read data using OCILobRead(). It uses the table and variables from the preceding Example 3-5.

for (i=0;i<DATA_SIZE;i++) 
  col2[i] = 'A';
 
/*************** Writing to the LOB *****************/
 
amt = DATA_SIZE;
offset = 1;
 
/* Write contents of col2 buffer into the LOB in a single chunk via locator lobp */
OCILobWrite (svchp, errhp, lobp, &amt, offset, col2, DATA_SIZE, OCI_ONE_PIECE,
                        0, 0, 0, SQLCS_IMPLICIT);
 
/*************** Reading from the LOB *****************/
 
/* Get the length of the LOB */
OCILobGetLength (svchp, errhp, lobp, &len);
amt = len;
 
/* Read the LOB data in col2Res in a single chunk */
OCILobRead (svchp, errhp, lobp, &amt, offset, col2Res, DATA_SIZE, 0, 0, 0,  
                        SQLCS_IMPLICIT);

OCI client-side buffering

OCI provides a facility for client-side buffering on a per-LOB basis. It is enabled for a LOB by a call to OCILobEnableBuffering() and disabled by a call to OCILobDisableBuffering().

Enabling buffering for a LOB locator creates a 512 KB write buffer. This size is not configurable. Data written by the application through the LOB locator is buffered. When possible, the client library will satisfy LOB read requests from the buffer as well. An application can flush the buffer by a call to OCILobFlushBuffer(). Note that buffers are not flushed automatically when they become full, and an attempt to write to the LOB through the locator when the buffer is full will result in an error.

The following restrictions apply when you use client-side buffering:

  • Buffering is incompatible with the following functions: OCILobAppend(), OCILobCopy(), OCILobCopy2(), OCILobErase(), OCILobGetLength(), OCILobTrim(), OCILobWriteAppend(), and OCILobWriteAppend2().

  • An application can use OCILobWrite() or OCILobWrite2() only to append to the end of a LOB.

  • LOB data becomes visible to SQL and PL/SQL (server-side) operations only after the application has flushed the buffer.

  • When a LOB is selected while there are unflushed client-side writes in its buffer, the unflushed data is not included in the select.

LOB prefetching in OCI

To reduce round trips to the server in client/server connections, LOB data can be prefetched from the database and cached on the client side during fetch operations. LOB prefetching in OCI has the same functionality in TimesTen as in Oracle Database.

Configure LOB prefetching through the following OCI attributes. Note that size refers to bytes for BLOBs and to characters for CLOBs or NCLOBs.

  • OCI_ATTR_DEFAULT_LOBPREFETCH_SIZE: Use this to enable prefetching and specify the default prefetch size. A value of 0 (default) disables prefetching.

  • OCI_ATTR_LOBPREFETCH_SIZE: Set this attribute for a column define handle to specify the prefetch size for the particular LOB column.

  • OCI_ATTR_LOBPREFETCH_LENGTH: This attribute can be set TRUE or FALSE (default) to prefetch LOB metadata such as LOB length and chunk size.

The OCI_ATTR_DEFAULT_LOBPREFETCH_SIZE and OCI_ATTR_LOBPREFETCH_LENGTH settings are independent of each other. You can use LOB data prefetching independently of LOB metadata prefetching.

Refer to "Prefetching of LOB Data, Length, and Chunk Size" in Oracle Call Interface Programmer's Guide for more information and an example.


Note:

The above attribute settings are ignored for TimesTen direct connections.

Passthrough LOBs in OCI

Passthrough LOBs (LOBs in Oracle Database accessed through TimesTen) are exposed as TimesTen LOBs and are supported by TimesTen in much the same way that any TimesTen LOB is supported, but note the following:

  • You cannot use OCILobCreateTemporary() to create a passthrough LOB.

  • In addition to copying from one TimesTen LOB to another TimesTen LOB—such as through OCILobCopy(), OCILobCopy2(), or OCILobAppend()—you can copy from a TimesTen LOB to a passthrough LOB, from a passthrough LOB to a TimesTen LOB, or from one passthrough LOB to another passthrough LOB. Any of these copies the LOB value to the target destination. For example, copying a passthrough LOB to a TimesTen LOB copies the LOB value into the TimesTen database.

    An attempt to copy a passthrough LOB to a TimesTen LOB when the passthrough LOB is larger than the TimesTen LOB size limit will result in an error.

  • TimesTen LOB size limitations do not apply to storage of passthrough LOBs, but do apply to binding. Also, if a passthrough LOB is copied to a TimesTen LOB, the size limit applies to the copy.

  • As with TimesTen local LOBs, a locator for a passthrough LOB does not remain valid past the end of the transaction.

Example 3-7 Copying between TimesTen LOBs and passthrough LOBs

The examples here highlight key functionality in copying between TimesTen LOBs and passthrough LOBs on Oracle Database. After the table and data setup, the first example uses OCILobAppend() to copy LOB data from Oracle Database to TimesTen and the second example uses OCILobCopy() to copy LOB data from TimesTen to Oracle Database. (Either call could be used in either case.) Then, for contrast, the third example uses an UPDATE statement to copy LOB data from Oracle Database to TimesTen and the fourth example uses an INSERT statement to copy LOB data from TimesTen to Oracle Database.

   /* Table and data setup */
  call ttoptsetflag(''passthrough'', 3)';
  DROP TABLE oratab';
  CREATE TABLE oratab (i INT, c CLOB)';
  INSERT INTO oratab VALUES (1, ''Copy from Oracle to TimesTen'')';
  INSERT INTO oratab VALUES (2, EMPTY_CLOB())';
  COMMIT;
 
  call ttoptsetflag(''passthrough'', 0)';
  DROP TABLE tttab';
  CREATE TABLE tttab (i INT, c CLOB)';
  INSERT INTO tttab VALUES (1, ''Copy from TimesTen to Oracle'')';
  INSERT INTO tttab VALUES (2, EMPTY_CLOB())';
  INSERT INTO tttab VALUES (3, NULL)';
  COMMIT;
  /* Table and data setup end */
 
  /*
   * Below are four OCI pseudocode examples, for copying LOBs between
   * TimesTen and Oracle using OCI API and INSERT/UPDATE statements.
   */
 
  /* Init OCI Env */
 
  /* Set the passthrough level to 1 */
  OCIStmtPrepare (..., "call ttoptsetflag(''passthrough'', 1)'", ...);
  OCIStmtExecute (...);
 
  /*
   * 1. Copy a passthrough LOB on Oracle to a TimesTen LOB
   */
 
  /* Select a passthrough locator on Oracle */
  OCIStmtPrepare (..., "SELECT c FROM oratab WHERE i = 1", ...);
  OCIDefineByPos (..., (dvoid *)&ora_loc_1, 0 , SQLT_CLOB, ...);
  OCIStmtExecute (...);
 
  /* Select a locator on TimesTen for update */
  OCIStmtPrepare (..., "SELECT c FROM tttab WHERE i = 2 FOR UPDATE", ...);
  OCIDefineByPos (..., (dvoid *)&tt_loc_2, 0 , SQLT_CLOB, ...);
  OCIStmtExecute (...);
 
  /* Copy a passthrough LOB on Oracle to a TimesTen LOB */
  OCILobAppend(..., tt_loc_2, ora_loc_1);
 
  /*
   * 2. Copy a TimesTen LOB to a passthrough LOB on Oracle
   */
 
  /* Select a passthrough locator on Oracle for update */
  OCIStmtPrepare (..., "SELECT c FROM oratab WHERE i = 2 FOR UPDATE", ...);
  OCIDefineByPos (..., (dvoid *)&ora_loc_2, 0 , SQLT_CLOB, ...);
  OCIStmtExecute (...);
 
  /* Select a locator on TimesTen */
  OCIStmtPrepare (..., "SELECT c FROM tttab WHERE i = 1", ...);
  OCIDefineByPos (..., (dvoid *)&tt_loc_1, 0 , SQLT_CLOB, ...);
  OCIStmtExecute (...);
 
  /* Copy a passthrough LOB on Oracle to a TimesTen LOB */
  OCILobCopy(..., ora_loc_2, tt_loc_1, 28, 1, 1);
 
  /*
   * 3. UPDATE a TimesTen LOB with a passthrough LOB on Oracle
   */
 
  /* A passthrough LOB, (selected above in case 1) is bound to an UPDATE statement
   * on TimesTen table */
  OCIStmtPrepare (..., "UPDATE tttab SET c = :1 WHERE i = 3", ...);
  OCIBindByPos (..., (dvoid *)&ora_loc_1, 0 , SQLT_CLOB, ...);
  OCIStmtExecute (...);
 
  /*
   * 4. INSERT a passthrough table on Oracle with a TimesTen LOB
   */
 
  /* A TimesTen LOB, (selected above in case 2) is bound to an INSERT statement
   * on a passthough table on Oracle */
  OCIStmtPrepare (..., "INSERT INTO oratab VALUES (3, :1)", ...);
  OCIBindByPos (..., (dvoid *)&tt_loc_1, 0 , SQLT_CLOB, ...);
  OCIStmtExecute (...);
 
  OCITransCommit (...);
 
  /* Cleanup OCI Env */

TimesTen OCI support reference

This is a reference section for TimesTen support of OCI features, covering the following areas:

Supported OCI calls

Table 3-2 lists TimesTen support for OCI calls that are documented for Oracle Database release 11.2.0.2.

Some groups of calls are represented with an asterisk in the name. For example, the calls related to Advanced Queuing, which TimesTen does not support, have names that start with OCIAQ and are represented in the table as OCIAQ*(). OCI date functions, which TimesTen does support, are designated by OCIDate*().

Table 3-2 TimesTen OCI supported calls

OCI callSupportedNotes

OCIAQ*()

No

TimesTen does not support Advanced Queuing.

OCIAnyData*()

No

TimesTen does not support Any Data.

OCIAppCtxClearAll()

Yes


OCIAppCtxSet()

Yes


OCIArrayDescriptorAlloc()

Yes


OCIArrayDescriptorFree()

Yes


OCIAttrGet()

Yes

TimesTen support includes special usage with cache groups. See "IMDB Cache with TimesTen OCI".

OCIAttrSet()

Yes


OCIBinXml*()

No

TimesTen does not support XML DB.

OCIBindArrayOfStruct()

Yes

This is supported for SQL statements but not PL/SQL.

OCIBindByName()

Yes

The following are unsupported values for the mode parameter:

  • OCI_DATA_AT_EXEC

  • OCI_IOV

OCIBindByPos()

Yes

The following are unsupported values for the mode parameter:

  • OCI_DATA_AT_EXEC

  • OCI_IOV

OCIBindDynamic()

No


OCIBindObject()

No

TimesTen does not support user-defined objects.

OCIBreak()

No


OCICache*()

No

TimesTen does not support user-defined objects.

OCICharSetConversionIsReplacementUsed()

Yes


OCICharSetToUnicode()

Yes


OCIClientVersion()

Yes


OCIColl*()

No

TimesTen does not support collections.

OCIConnectionPoolCreate()

No


OCIConnectionPoolDestroy()

No


OCIContext*()

No

TimesTen does not support Data Cartridge.

OCIDBShutdown()

No


OCIDBStartup()

No


OCIDate*()

Yes

See Table 3-4 for information about descriptor support.

OCIDefineArrayOfStruct()

Yes

This is supported for SQL statements but not PL/SQL.

OCIDefineByPos()

Yes

The following are unsupported values for the mode parameter:

  • OCI_DATA_AT_EXEC

  • OCI_IOV

OCIDefineDynamic()

No


OCIDefineObject()

No


OCIDescribeAny()

Yes

PL/SQL objects are not supported.

Describing objects is supported only by name.

The following are unsupported values for the objptr_typ parameter:

  • OCI_OTYPE_REF

  • OCI_OTYPE_PTR

The following are unsupported values for the objtyp parameter:

  • OCI_PTYPE_PKG

  • OCI_PTYPE_FUNC

  • OCI_PTYPE_PROC

  • OCI_PTYPE_SYN

  • OCI_PTYPE_TYPE

When you use the setting OCI_PTYPE_DATABASE for the objtyp parameter, use the predetermined name $TT_DB_NAME$ as the database name for the *objptr parameter.

OCIDescriptorAlloc()

Yes


OCIDescriptorFree()

Yes


OCIDirPath*()

No

TimesTen does not support Direct Path Loading.

OCIDurationBegin()

Yes

Supported for LOBs. Regardless of the duration setting, the duration cannot exceed the lifetime of the transaction.

OCIDurationEnd()

Yes

Supported for LOBs. Regardless of the duration setting, the duration cannot exceed the lifetime of the transaction.

OCIDuration*()

No

TimesTen does not support Data Cartridge.

OCIEnvCreate()

Yes

The following are unsupported values for the mode parameter:

  • OCI_EVENTS

  • OCI_NEW_LENGTH_SEMANTICS

  • OCI_NCHAR_LITERAL_REPLACE_ON

  • OCI_NCHAR_LITERAL_REPLACE_OFF

  • OCI_NO_MUTEX (Instead use OCI_ENV_NO_MUTEX.)

OCIEnvInit()

Yes

The following are unsupported values for the mode parameter:

  • OCI_NO_MUTEX

  • OCI_ENV_NO_MUTEX

Note: Use OCIEnvCreate() instead of OCIEnvInit(). OCIEnvInit() is supported for backward compatibility.

OCIEnvNlsCreate()

Yes

The following are unsupported values for the mode parameter:

  • OCI_EVENTS

  • OCI_NCHAR_LITERAL_REPLACE_ON

  • OCI_NCHAR_LITERAL_REPLACE_OFF

  • OCI_NO_MUTEX (Instead use OCI_ENV_NO_MUTEX.)

OCIErrorGet()

Yes


OCIExtProc*()

No

TimesTen does not support Data Cartridge.

OCIExtract*()

No

TimesTen does not support Data Cartridge.

OCIFile*()

No

TimesTen does not support Data Cartridge.

OCIFormatInit()

No

TimesTen does not support Data Cartridge.

OCIFormatString()

No

TimesTen does not support Data Cartridge.

OCIFormatTerm()

No

TimesTen does not support Data Cartridge.

OCIHandleAlloc()

Yes


OCIHandleFree()

Yes


OCIInitialize()

Yes

The following are unsupported values for the mode parameter:

  • OCI_NO_MUTEX

  • OCI_ENV_NO_MUTEX

Note: Use OCIEnvCreate() instead of OCIInitialize(). OCIInitialize() is supported for backward compatibility.

OCIInterval*()

Yes

See Table 3-4 for information about descriptor support.

OCIIter*()

No

TimesTen does not support collections.

OCILdaToSvcCtx()

No


OCILob*()

Yes

TimesTen supports OCILob*() functions other than the following:

  • Functions specifically intended for array reads and writes

  • Functions specifically intended for BFILEs

  • Functions specifically intended for SecureFiles

Notes:

OCILogoff()

Yes


OCILogon()

Yes


OCILogon2()

Yes

OCI_DEFAULT is the only supported value for the mode parameter.

OCIMemory*()

No

TimesTen does not support Data Cartridge.

OCIMessage*()

No

TimesTen does not support Data Cartridge.

OCIMultiByte*()

Yes


OCINls*()

Yes


OCINumber*()

Yes


OCIObject*()

No

TimesTen does not support user-defined objects.

OCIParamGet()

Yes


OCIParamSet()

Yes


OCIPasswordChange()

No


OCIPing()

Yes


OCIRaw*()

Yes


OCIRef*()

No


OCIReset()

No


OCIRowidToChar()

Yes


OCIServer*()

Yes

OCI_DEFAULT is the only supported value for the mode parameter of OCIServerAttach.

OCISessionBegin()

Yes

OCI_CRED_RDBMS is the only supported value for the credt parameter.

OCI_DEFAULT is the only supported value for the mode parameter.

OCISessionEnd()

Yes


OCISessionGet()

Yes

TimesTen does not support switching between sessions.

OCISessionPoolCreate()

No


OCISessionPoolDestroy()

No


OCISessionRelease()

Yes


OCISharedLibInit()

No


OCIStmtExecute()

Yes

The following are unsupported values for the mode parameter:

  • OCI_BATCH_ERRORS

  • OCI_STMT_SCROLLABLE_READONLY

Note: Using OCI_COMMIT_ON_SUCCESS results in improved performance, avoiding an extra round trip to the server to commit a transaction.

OCIStmtFetch()

Yes


OCIStmtFetch2()

Yes

The only supported values for the orientation parameter are OCI_DEFAULT and OCI_FETCH_NEXT.

OCIStmtGetBindInfo()

Yes


OCIStmtGetPieceInfo()

No


OCIStmtPrepare()

Yes

The only supported value for the language parameter is OCI_NTV_SYNTAX.

OCIStmtPrepare2()

Yes

The only supported value for the mode parameter is OCI_DEFAULT.

For statement caching, TimesTen supports the key argument to tag a statement for future calls to OCIStmtPrepare2() or OCIStmtRelease().

OCIStmtRelease()

Yes

The only supported value for the mode parameter is OCI_DEFAULT.

For statement caching, TimesTen supports the key argument to tag a statement. This can be the key from OCIStmtPrepare2().

OCIStmtSetPieceInfo()

No


OCIString*()

Yes


OCISubscription*()

No

TimesTen does not support Advanced Queuing.

OCISvcCtxToLda()

No


OCITable*()

No


OCITerminate()

No


OCIThread*()

Yes


OCITransCommit()

Yes

The only supported value for the mode parameter is OCI_DEFAULT.

OCITransDetach()

No


OCITransForget()

No


OCITransMultiPrepare()

No


OCITransPrepare()

No


OCITransRollback()

Yes


OCITransStart()

No


OCIType*()

No


OCIUnicodeToCharSet()

Yes


OCIUserCallbackGet()

Yes


OCIUserCallbackRegister()

Yes


OCIWideChar*()

Yes


OCIXmlDbFreeXmlCtx()

No

TimesTen does not support XML DB.

OCIXmlDbInitXmlCtx()

No

TimesTen does not support XML DB.


Supported handles and attributes

Table 3-3 lists the handles and attributes that TimesTen OCI supports.

Table 3-3 TimesTen OCI supported handles and attributes

HandleC objectSupported attributes

Environment

OCIEnv

OCI_ATTR_ENV_CHARSET_ID

OCI_ATTR_ENV_NCHARSET_ID

OCI_ATTR_ENV_UTF16

OCI_ATTR_EVTCTX

OCI_ATTR_OBJECT

Error

OCIError

OCI_ATTR_DML_ROW_OFFSET

Service context

OCISvcCtx

OCI_ATTR_ENV

OCI_ATTR_IN_V8_MODE

OCI_ATTR_SERVER

OCI_ATTR_SESSION

OCI_ATTR_TRANS

Statement

OCIStmt

OCI_ATTR_BIND_COUNT

OCI_ATTR_CURRENT_POSITION

OCI_ATTR_ENV

OCI_ATTR_FETCH_ROWID

OCI_ATTR_NUM_DML_ERRORS

OCI_ATTR_PARAM_COUNT

OCI_ATTR_PREFETCH_MEMORY

OCI_ATTR_PREFETCH_ROWS

OCI_ATTR_ROW_COUNT

OCI_ATTR_ROWID

OCI_ATTR_ROWS_FETCHED

OCI_ATTR_SQLFNCODE

OCI_ATTR_STATEMENT

OCI_ATTR_STMT_TYPE

Bind

OCIBind

OCI_ATTR_CHARSET_FORM

OCI_ATTR_CHARSET_ID

OCI_ATTR_MAXCHAR_SIZE

OCI_ATTR_MAXDATA_SIZE

Define

OCIDefine

OCI_ATTR_CHARSET_FORM

OCI_ATTR_CHARSET_ID

OCI_ATTR_MAXCHAR_SIZE

Describe

OCIDescribe

OCI_ATTR_PARAM

OCI_ATTR_PARAM_COUNT

Server

OCIServer

OCI_ATTR_ENV

OCI_ATTR_IN_V8_MODE

OCI_ATTR_SERVER_GROUP

OCI_ATTR_SERVER_STATUS

User session

OCISession

OCI_ATTR_CLIENT_IDENTIFER

OCI_ATTR_CLIENT_INFO

OCI_ATTR_CURRENT_SCHEMA

OCI_ATTR_DRIVER_NAME

OCI_ATTR_INITIAL_CLIENT_ROLES

OCI_ATTR_MODULE

OCI_ATTR_PROXY_CREDENTIALS

OCI_ATTR_USERNAME

Authentication

OCIAuthInfo

Same as for user session handle

Transaction

OCITrans

OCI_ATTR_TRANS_NAME

OCI_ATTR_TRANS_TIMEOUT

Thread

OCIThreadHandle



Supported descriptors

Table 3-4 lists the descriptors that TimesTen OCI supports.

Table 3-4 TimesTen OCI supported descriptors

DescriptorC object

Parameter (read-only)

OCIParam

ROWID

OCIRowid

ANSI DATE

OCIDateTime

TIMESTAMP

OCIDateTime

TIMESTAMP WITH TIME ZONE

OCIDateTime

TIMESTAMP WITH LOCAL TIME ZONE

OCIDateTime

INTERVAL YEAR TO MONTH

OCIInterval

INTERVAL DAY TO SECOND

OCIInterval

User callback

OCIUcb


Supported SQL data types

Table 3-5 lists the SQL data types that TimesTen OCI supports.

Table 3-5 TimesTen OCI supported SQL data types

SQL data typeNotes

SQLT_AFC


SQLT_AVC


SQLT_BDOUBLE


SQLT_BFLOAT


SQLT_BIN


SQLT_BLOB


SQLT_CHR


SQLT_CLOB

To write to or read from an NCLOB, set the character set form (csfrm) parameter to SQLCS_NCHAR for applicable function calls.

SQLT_DAT


SQLT_DATE


SQLT_FLT


SQLT_IBDOUBLE


SQLT_IBFLOAT


SQLT_INT


SQLT_INTERVAL_DS

Not stored in TimesTen.

SQLT_INTERVAL_YM

Not stored in TimesTen.

SQLT_LBI


SQLT_LNG


SQLT_LVB

Truncated at 4 MB when stored in TimesTen.

SQLT_LVC

Truncated at 4 MB when stored in TimesTen.

SQLT_NUM


SQLT_ODT


SQLT_RDD

Rowids are returned in Oracle Database format.

SQLT_RSET

Only one result set parameter is allowed for each statement.

SQLT_STR


SQLT_TIME


SQLT_TIME_TZ

Time zone is ignored when stored in TimesTen.

SQLT_TIMESTAMP


SQLT_TIMESTAMP_LTZ

Time zone is ignored when stored in TimesTen.

SQLT_TIMESTAMP_TZ

Time zone is ignored when stored in TimesTen.

SQLT_UIN


SQLT_VBI


SQLT_VCS


SQLT_VNU


SQLT_VST



Supported parameter attributes

Table 3-6 that follows lists supported parameter attributes.

Table 3-6 TimesTen OCI supported parameter attributes

ParameterSupported attributes

All parameters

OCI_ATTR_NUM_PARAMS

OCI_ATTR_OBJ_NAME

OCI_ATTR_OBJ_SCHEMA

OCI_ATTR_PTYPE

Table and view parameters

OCI_ATTR_NUM_COLS

OCI_ATTR_LIST_COLUMNS

PL/SQL procedure and function parameters

OCI_ATTR_LIST_ARGUMENTS

PL/SQL subprogram parameters

OCI_ATTR_LIST_ARGUMENTS

OCI_ATTR_NAME

PL/SQL package parameters

OCI_ATTR_LIST_SUBPROGRAMS

Sequence parameters

OCI_ATTR_OBJID

OCI_ATTR_MIN

OCI_ATTR_MAX

OCI_ATTR_INCR

OCI_ATTR_CACHE

OCI_ATTR_ORDER

OCI_ATTR_HW_MARK

Column parameters

OCI_ATTR_CHAR_USED

OCI_ATTR_CHAR_SIZE

OCI_ATTR_DATA_SIZE

OCI_ATTR_DATA_TYPE

OCI_ATTR_NAME

OCI_ATTR_PRECISION

OCI_ATTR_SCALE

OCI_ATTR_IS_NULL

OCI_ATTR_TYPE_NAME

OCI_ATTR_SCHEMA_NAME

OCI_ATTR_CHARSET_ID

OCI_ATTR_CHARSET_FORM

Argument and result parameters

OCI_ATTR_NAME

OCI_ATTR_POSITION

OCI_ATTR_DATA_TYPE

OCI_ATTR_DATA_SIZE

OCI_ATTR_PRECISION

OCI_ATTR_SCALE

OCI_ATTR_LEVEL

OCI_ATTR_IS_NULL

OCiI_ATTR_CHARSET_ID

OCI_ATTR_CHARSET_FORM

List parameters

OCI_LTYPE_COLUMN

OCI_LTYPE_SCH_OBJ

OCI_LTYPE_DB_SCH

Database parameters

OCI_ATTR_VERSION

OCI_ATTR_CHARSET_ID

OCI_ATTR_NCHARSET_ID

OCI_ATTR_LIST_SCHEMAS

OCI_ATTR_MAX_PROC_LEN

OCI_ATTR_MAX_COLUMN_LEN

OCI_ATTR_ATTR_CURSOR_COMMIT_BEHAVIOR

OCI_ATTR_MAX_CATALOG_NAMELEN

OCI_ATTR_CATALOG_LOCATION

OCI_ATTR_SAVEPOINT_SUPPORT

OCI_ATTR_NOWAIT_SUPPORT

OCI_ATTR_AUTOCOMMIT_DDL

OCI_ATTR_LOCKING_MODE


PK"t\iPK:AOEBPS/cover.htmO Cover

Oracle Corporation

PK[pTOPK:AOEBPS/whatsnew.htmh What's New

What's New

This section summarizes new features and functionality of Oracle TimesTen In-Memory Database 11g Release 2 (11.2.2) that are documented in this guide, providing links into the guide for more information.

New features in Release 11.2.2.4.0

New features in Release 11.2.2.2.0

New features in Release 11.2.2.0.0

PKPK:AOEBPS/compiling.htmG> C Development Environment

1 C Development Environment

This chapter provides information about the C development environment and related considerations for developing TimesTen applications. The following topics are covered:

Setting the environment for development

Environment variable settings for TimesTen are discussed in "Environment variables" in the Oracle TimesTen In-Memory Database Installation Guide.

On UNIX platforms, set the environment for TimesTen by using one of the following scripts:

install_dir/bin/ttenv.sh
install_dir/bin/ttenv.csh

On Windows, set the environment during installation or use the following:

install_dir\bin\ttenv.bat

Notes:

  • The ttenv scripts also configure access to the Oracle Instant Client, required for OCI programming.

  • You can optionally use the appropriate ttquickstartenv script instead of ttenv. This is a superset of ttenv that also sets up the TimesTen Quick Start demo environment.

  • To ensure proper generation of OCI and Pro*C/C++ programs to be run on TimesTen, do not set ORACLE_HOME (or unset it if it was set previously) for OCI and Pro*C/C++ compilations.


Linking options

A TimesTen application can link specifically with the TimesTen ODBC direct driver or ODBC client driver without a driver manager, or can link with a driver manager.

Linking without an ODBC driver manager

Applications to be used solely with TimesTen can link specifically with either the TimesTen ODBC direct driver or the ODBC client driver, without a driver manager. This avoids the performance overhead of a driver manager and is the simplest way to access TimesTen. However, developers of applications linked without a driver manager should be aware of the following issues.

  • The application can only connect to a DSN that uses the driver with which it is linked. It cannot connect to a database of any other vendor, nor can it connect to a TimesTen DSN of a different TimesTen driver or a different version or type.

  • Windows ODBC tracing is not available.

  • The ODBC cursor library is not available.

  • Applications cannot use ODBC functions that are usually implemented by a driver manager, such as SQLDataSources and SQLDrivers.

  • Applications that use SQLCancel to close a cursor instead of SQLFreeStmt(..., SQL_CLOSE) will receive a return code of SQL_SUCCESS_WITH_INFO and a SQL state of 01S05. This warning is intended to be used by the driver manager to manage its internal state. Applications should treat this warning as success.

Linking with an ODBC driver manager

Applications that link with the ODBC driver manager can connect to any DSN that references an ODBC driver and can even connect simultaneously to multiple DSNs that use different ODBC drivers. Note, however, that driver managers are not available by default on most non-Windows platforms. In addition, using a driver manager may add significant synchronization overhead to every ODBC function call and has the following limitations:

  • The TimesTen option TT_PREFETCH_COUNT cannot be used with applications that link with a driver manager. For more information on using TT_PREFETCH_COUNT, see "Prefetching multiple rows of data".

  • Applications cannot set or reset the TimesTen-specific TT_PREFETCH_CLOSE connection option. For more information about using the TT_PREFETCH_CLOSE connection option, see "Enable TT_PREFETCH_CLOSE for Serializable transactions" in the Oracle TimesTen In-Memory Database Operations Guide.

  • Transaction Log API (XLA) calls cannot be used when applications are linked with a driver manager.

  • The ODBC C types SQL_C_BIGINT, SQL_C_TINYINT, and SQL_C_WCHAR are not supported for an application linked with a driver manager when used with TimesTen. You cannot call methods that have any of these types in their signatures.

  • The driver manager does not support LOB locator APIs or LOB data types, which are not part of the ODBC standard. However, you can use the LOB simple data interface or piecewise data interface as documented in "Working with LOBs".


Note:

TimesTen supplies a driver manager for both Windows and UNIX with the Quick Start sample applications. This driver manager is not fully supported. It supports only the TimesTen direct driver and client driver and does not have the functionality or performance limitations described above. Applications that must concurrently use both direct connections and client/server connections to TimesTen can use this driver manager to achieve this with very little impact on performance.

Compiling and linking applications

This section discusses compiling and linking C applications on Windows or UNIX.

Compiling and linking applications on Windows

To compile TimesTen applications on Windows, you are not required to specify the location of the ODBC include files. These files are included with Microsoft Visual C++. However, you must indicate the location of TimesTen include files by using the /I compiler option. (See "TimesTen include files".)

The Makefile in Example 1-1 shows how to build a TimesTen application on Windows systems. This example assumes that install_dir\lib has already been added to the LIB environment variable.

Example 1-1 Building a TimesTen application in Windows

CFLAGS = "/Iinstall_dir\"
LIBSDM = ODBC32.LIB
LIBS = tten1122.lib ttdv1122.lib
LIBSDEBUG = tten1122d.lib ttdv1122d.lib
LIBSCS = ttclient1122.lib

# Link with the ODBC driver manager
appldm.exe:appl.obj
           $(CC) /Feappldm.exe appl.obj $(LIBSDM)

# Link directly with the TimesTen
# ODBC production driver
appl.exe:appl.obj
         $(CC) /Feappl.exe appl.obj\
         $(LIBS)

# Link directly with the TimesTen
# ODBC debug driver
appldebug.exe:appl.obj
              $(CC) /Feappldebug.exe appl.obj\
              $(LIBSDEBUG)

# Link directly with the TimesTen
# ODBC client driver
applcs.exe:appl.obj
           $(CC) /Feapplcs.exe appl.obj\
           $(LIBSCS)

Compiling and linking applications on UNIX

On UNIX platforms:

  • Compile TimesTen applications using the TimesTen header files from the TimesTen installation directory.

  • Link with the TimesTen ODBC direct driver or client driver, each of which is provided as a shared library.

On UNIX, applications using the SQL_C_ULONG, SQL_C_SLONG, SQL_C_USHORT or SQL_C_SSHORT ODBC data types must specify the TT_USE_ALL_TYPES preprocessor option while compiling. This is typically done using the -DTT_USE_ALL_TYPES C compiler option.

To use the TimesTen include files, add the following to the C compiler command, where install_dir is the TimesTen installation directory path:

-Iinstall_dir/

To link with the TimesTen ODBC direct driver, add the following to the link command:

-Linstall_dir/lib -ltten

The -L option tells the linker to search the TimesTen lib directory for library files. The -ltten option links in the TimesTen ODBC direct driver.

To link with the TimesTen ODBC client driver, add the following to the link command:

-Linstall_dir/lib -lttclient

On Solaris, the default TimesTen ODBC client driver was compiled with Studio 11. The library enables you to link an application compiled with the Sun Studio 11 C/C++ compiler directly with the TimesTen client.

On AIX, when linking applications with the TimesTen ODBC client driver, the C++ runtime library must be included in the link command (because the client driver is written in C++ and AIX does not link it automatically) and must follow the client driver:

-Linstall_dir/lib -lttclient -lC_r

You can use Makefiles in subdirectories under the quickstart/sample_code directory, or you can use Example 1-2 to guide you in creating your own Makefile.

Example 1-2 Makefile to link the application

CFLAGS = -Iinstall_dir/
LIBS = -Linstall_dir/lib -ltten
LIBSDEBUG = -Linstall_dir/lib -lttenD
LIBSCS = -Linstall_dir/lib -lttclient

# Link directly with the TimesTen
# ODBC production driver
appl:appl.o
     $(CC) -o appl appl.o $(LIBS)

# Link directly with the TimesTen ODBC debug driver
appldebug:appl.o
     $(CC) -o appldebug appl.o $(LIBSDEBUG)

# Link directly with the TimesTen client driver
applcs:appl.o
     $(CC) -o applcs appl.o $(LIBSCS)

Notes:

  • To directly link your application to the debug TimesTen ODBC driver, substitute -lttenD for -ltten on the link line.

  • On Solaris, when compiling with Sun C/C++ compilers, TimesTen applications must be compiled and linked with the -mt option.


About the TimesTen C demos

After you have configured your C environment, you can confirm that everything is set up correctly by compiling and running TimesTen Quick Start demo applications. Refer to the Quick Start welcome page at install_dir/quickstart.html, especially the links under SAMPLE PROGRAMS, for information on the following topics.

PKzIL>G>PK:AOEBPS/xla_event.htm XLA and TimesTen Event Management

5 XLA and TimesTen Event Management

The Transaction Log API (XLA) is a set of C language functions that enable you to implement applications to perform the following:

The primary purpose of XLA is as a high-performance, asynchronous alternative to triggers.


Note:

In the unlikely event that TimesTen replication solutions described in Oracle TimesTen In-Memory Database Replication Guide do not meet your needs, it is possible to use XLA functions to build a custom data replication solution.

This chapter includes the following topics:

For a complete description of each XLA function, see Chapter 9, "XLA Reference".

XLA concepts

This section includes the following topics:

XLA functions mentioned here are documented in Chapter 9, "XLA Reference".

XLA basics

TimesTen XLA obtains update records directly from the transaction log buffer or transaction log files, so the records are available for as long as they are needed. The logging model also enables multiple readers to simultaneously read transaction log updates.

The ttXlaPersistOpen XLA function opens a connection to the database.

When initially created, TimesTen configures a transaction log handle for the same version as the TimesTen release to which the application is linked. You can also use the ttXlaGetVersion and ttXlaSetVersion XLA functions to interoperate with earlier XLA versions.

How XLA reads records from the transaction log

As applications modify a database, TimesTen generates transaction log records that describe the changes made to the data and other events such as transaction commits.

New transaction log records are always written to the end of the log buffer as they are generated.

Transaction log records are periodically flushed in batches from the log buffer in memory to transaction log files on disk. When XLA is initialized, the XLA application does not have to be concerned with which portions of the transaction log are on disk or in memory. Therefore, the term "transaction log" as used in this chapter refers to the "virtual" source of transaction update records, regardless of whether those records are physically located in memory or on disk.

Applications can use XLA to monitor the transaction log for changes to the database. XLA reads through the transaction log, filters the log records, and delivers to XLA applications a list of transaction records that contain the changes to the tables and columns of interest.

XLA sorts the records into discrete transactions. If multiple applications are updating the database simultaneously, transaction log records from the different applications will be interleaved in the transaction log.

XLA transparently extracts all transaction log records associated with a particular transaction and delivers them in a contiguous list to the application.

Only the records for committed transactions are returned. They are returned in the order in which their final commit record appears in the transaction log. XLA filters out records associated with changes to the database that have not yet been committed.

If a change is made but then rolled back, XLA does not deliver the records for the aborted transaction to the application.

Most of these basic XLA concepts are demonstrated in Example 5-1 that follows and summarized in the bulleted list following the example.

Consider the example transaction log illustrated in Figure 5-1.

Figure 5-1 Records extracted from the transaction log

Description of Figure 5-1 follows
Description of "Figure 5-1 Records extracted from the transaction log"

Example 5-1 Reading transaction log records

In this example, the transaction log contains the following records:


CT1 - Application C updates row 1 of table W with value 7.7.
BT1 - Application B updates row 3 of table X with value 2.
CT2 - Application C updates row 9 of table W with value 5.6.
BT2 - Application B updates row 2 of table Y with value "XYZ".
AT1 - Application A updates row 1 of table Z with value 3.
AT2 - Application A updates row 3 of table Z with value 4.
BT3 - Application B commits its transaction.
AT3 - Application A rolls back its transaction.
CT3 - Application C commits its transaction.

An XLA application that is set up to detect changes to tables W, Y, and Z would see the following:


BT2 and BT3 - Update row 2 of table Y with value "XYZ" and commit.
CT1 - Update row 1 of table W with value 7.7.
CT2 and CT3 - Update row 9 of table W with value 5.6 and commit.

This example demonstrates the following:

  • Transaction records of applications B and C all appear together.

  • Although the records for application C begin to appear in the transaction log before those for application B, the commit for application B (BT3) appears in the transaction log before the commit for application C (CT3). As a result, the records for application B are returned to the XLA application ahead of those for application C.

  • The application B update to table X (BT1) is not presented because XLA is not set up to detect changes to table X.

  • The application A updates to table Z (AT1 and AT2) are never presented because it did not commit and was rolled back (AT3).

About XLA and materialized views

You can use XLA to track changes to both tables and materialized views. A materialized view provides a single source from which you can track changes to selected rows and columns in multiple detail tables. Without a materialized view, the XLA application would have to monitor and filter the update records from all of the detail tables, including records reflecting updates to rows and columns of no interest to the application.

In general, there are no operational differences between the XLA mechanisms used to track changes to a table or a materialized view. However, for asynchronous materialized views, be aware that the order of XLA notifications for an asynchronous materialized view is not necessarily the same as it would be for the associated detail tables, or the same as it would be for a synchronous materialized view. For example, if there are two inserts to a detail table, they may be done in the opposite order in the asynchronous materialized view. Furthermore, an update to a detail table of a materialized view may be reported by XLA as a delete followed by an insert. Also, multiple operations, such as multiple inserts or multiple deletes, may be combined into a single operation. Applications that depend on precise ordering should not use asynchronous materialized views.

For more information about materialized views, see the following:

About XLA bookmarks

Each XLA reader uses a bookmark to maintain its position in the log update stream. Each bookmark consists of two pointers that track update records in the transaction log by using log record identifiers:

  • An Initial Read log record identifier points to the most recently acknowledged transaction log record. Initial Read log record identifiers are stored in the database, so they are persistent across database connections, shutdowns, and failures.

  • A Current Read log record identifier points to the record currently being read from the transaction log.

The rest of this section covers the following:

Creating or reusing a bookmark

As described in "Initializing XLA and obtaining an XLA handle", when you call the ttXlaPersistOpen function to initialize an XLA handle, you have a tag parameter to identify either a new bookmark or one that exists in the system, and an options parameter to specify whether it is a new non-replicated bookmark, a new replicated bookmark, or an existing (reused) bookmark. At this time, the Initial Read log record identifier associated with the bookmark is read from the database and cached in the XLA handle (ttXlaHandle_h). It designates the start position of the reader in the transaction log.

See "ttLogHolds" in Oracle TimesTen In-Memory Database Reference for related information. That TimesTen built-in procedure returns information about transaction log holds.

How bookmarks work

When an application first initializes XLA and obtains an XLA handle, its Current Read log record identifier and Initial Read log record identifier both point to the last record written to the database, as shown in Figure 5-2 that follows.

Figure 5-2 Log record indicator positions upon initializing an XLA handle

Description of Figure 5-2 follows
Description of "Figure 5-2 Log record indicator positions upon initializing an XLA handle"

As described in "Retrieving update records from the transaction log", use the ttXlaNextUpdate or ttXlaNextUpdateWait function to return a batch of records for committed transactions from the transaction log in the order in which they were committed. Each call to ttXlaNextUpdate resets the Current Read log record identifier of the bookmark to the last record read, as shown in Figure 5-3. The Current Read log record identifier marks the start position for the next call to ttXlaNextUpdate.

Figure 5-3 Records retrieved by ttXlaNextUpdate

Description of Figure 5-3 follows
Description of "Figure 5-3 Records retrieved by ttXlaNextUpdate"

You can use the ttXlaGetLSN and ttXlaSetLSN functions to reread records, as described in "Changing the location of a bookmark". However, calling the ttXlaAcknowledge function permanently resets the Initial Read log record identifier of the bookmark to its Current Read log record identifier, as shown in Figure 5-4. After you have called the ttXlaAcknowledge function to reset the Initial Read log record identifier, all previously read transaction records are flagged for purging by TimesTen. Once the Initial Read log record identifier is reset, you cannot use ttXlaSetLSN to go back and reread any of the previously read transactions.

Figure 5-4 ttXlaAcknowledge resets bookmark

Description of Figure 5-4 follows
Description of "Figure 5-4 ttXlaAcknowledge resets bookmark"


Note:

A ttXlaAcknowledge call will reset the bookmark even if there are no relevant update records to acknowledge. This may be useful in managing transaction log space, but should be balanced against the expense of the operation. Be aware that XLA purges transaction logs a file at a time. Refer to "ttXlaAcknowledge" for details on how the operation works.

The number of bookmarks created in a database is limited to 64. Each bookmark can be associated with only one active connection at a time. However, a bookmark over its lifetime may be associated with many connections. An application can open a connection, create a new bookmark, associate the bookmark with the connection, read a few records using the bookmark, disconnect from the database, reconnect to the database, create a new connection, associate this new connection with the bookmark, and continue reading transaction log records from where the old connection stopped.

Replicated bookmarks

If you are using an active standby pair replication scheme, you have the option of using replicated bookmarks according to the options settings in your ttXlaPersistOpen calls. For a replicated bookmark, operations on the bookmark are replicated to the standby database as appropriate. This results in more efficient recovery of your bookmark positions in the event of failover. Reading resumes from the stream of XLA records close to the point at which they left off before the switchover to the new active store. Without replicated bookmarks, reading must go through numerous duplicate records that were returned on the old active store.

You can only read and acknowledge a replicated bookmark in the active database. Each time you acknowledge a replicated bookmark, the acknowledge operation is asynchronously replicated to the standby database.

Be aware of the following usage notes:

  • The position of the bookmark in the standby database will be very close to that of the bookmark in the active database; however, because the replication of acknowledge operations is asynchronous, you may see a small window of duplicate updates in the event of a failover, depending on how often acknowledge operations are performed.

  • It is recommended that you close and reopen all bookmarks on a database after it changes from standby to active status, using the ttXlaClose and ttXlaPersistOpen functions. The state of a replicated bookmark on a standby database does change during normal XLA processing, as the replication agent automatically repositions bookmarks as appropriate on standby databases. If you attempt to use a bookmark that was open before the database changed to active status, you will receive an error indicating that the state of the bookmark was reset and that it has been repositioned. While it is permissible to continue reading from the repositioned bookmark in this scenario, you can avoid the error by closing and reopening bookmarks.

  • If replicated bookmarks exist at the time you enable the active standby pair scheme, the bookmarks will automatically be added to the replication scheme.

  • It is permissible to drop the active standby pair scheme while replicated bookmarks exist. The bookmarks will cease to be replicated at that point.

  • You cannot delete replicated bookmarks as long as the replication agent is running.

XLA bookmarks and transaction log holds

You should be aware that when XLA is in use, there is a hold on TimesTen transaction log files until the XLA bookmark advances. The hold prevents transaction log files from being purged until XLA can confirm it no longer needs them. If a bookmark becomes stuck, which can occur if an XLA application terminates unexpectedly or disconnects without first deleting its bookmark or disabling change tracking, the log hold will persist and there may be an excessive accumulation of transaction log files. This accumulation may result in disk space being filled.

For information about monitoring and addressing this situation, see "Monitoring accumulation of transaction log files" in Oracle TimesTen In-Memory Database Operations Guide.

About XLA data types

Table 5-1 shows the data type mapping between internal SQL data types and XLA data types before release 7.0 and since release 7.0. For more information about TimesTen data types, see "Data Types" in Oracle TimesTen In-Memory Database SQL Reference.

Table 5-1 XLA data type mapping

Internal SQL data typeXLA data type before Release 7.0XLA data type since Release 7.0

TT_CHAR

SQL_CHAR

TTXLA_CHAR_TT

TT_VARCHAR

SQL_VARCHAR

TTXLA_VARCHAR_TT

TT_NCHAR

SQL_WCHAR

TTXLA_NCHAR_TT

TT_NVARCHAR

SQL_WVARCHAR

TTXLA_NVARCHAR_TT

CHAR

-

TTXLA_CHAR

NCHAR

-

TTXLA_NCHAR

VARCHAR2

-

TTXLA_VARCHAR

NVARCHAR2

-

TTXLA_NVARCHAR

TT_TINYINT

SQL_TINYINT

TTXLA_TINYINT

TT_SMALLINT

SQL_SMALLINT

TTXLA_SMALLINT

TT_INTEGER

SQL_INTEGER

TTXLA_INTEGER

TT_BIGINT

SQL_BIGINT

TTXLA_BIGINT

BINARY_FLOAT

SQL_REAL

TTXLA_BINARY_FLOAT

BINARY_DOUBLE

SQL_DOUBLE

TTXLA_BINARY_DOUBLE

TT_DECIMAL

SQL_DECIMAL

TTXLA_DECIMAL_TT

NUMBER

-

TTXLA_NUMBER

NUMBER(p,s)

-

TTXLA_NUMBER

FLOAT

-

TTXLA_NUMBER

TT_TIME

SQL_TIME

TTXLA_TIME

TT_DATE

SQL_DATE

TTXLA_DATE_TT

TT_TIMESTAMP

SQL_TIMESTAMP

TTXLA_TIMESTAMP_TT

DATE

-

TTXLA_DATE

TIMESTAMP

-

TTXLA_TIMESTAMP

TT_BINARY

SQL_BINARY

TTXLA_BINARY

TT_VARBINARY

SQL_VARBINARY

TTXLA_VARBINARY

ROWID

-

TTXLA_ROWID

BLOB

-

TTXLA_BLOB

CLOB

-

TTXLA_CLOB

NCLOB

-

TTXLA_NCLOB


XLA offers functions to convert between internal SQL data types and external programmatic data types. For example, you can use ttXlaNumberToCString to convert NUMBER columns to character strings. TimesTen provides the following XLA data type conversion functions:

Access control impact on XLA

"Considering TimesTen features for access control" provides a brief overview of how TimesTen access control affects operations in the database. Access control impacts XLA as follows:

  • Any XLA functionality, such as the following, requires the system privilege XLA:

    • Connecting to TimesTen (which also requires the CREATE SESSION privilege) as an XLA reader, such as by the ttXlaPersistOpen C function

    • Executing any other XLA-related TimesTen C functions, documented in Chapter 9, "XLA Reference"

    • Executing any XLA-related TimesTen built-in procedures

      The procedures ttXlaBookmarkCreate, ttXlaBookmarkDelete, ttXlaSubscribe, and ttXlaUnsubscribe are documented in "Built-In Procedures" in Oracle TimesTen In-Memory Database Reference.

  • A user with the XLA privilege has capabilities equivalent to the SELECT ANY TABLE, SELECT ANY VIEW, and SELECT ANY SEQUENCE system privileges, and can capture DDL statement records that occur in the database. Note that as a result, the user can obtain information about database objects that he or she has not otherwise been granted access to.

XLA limitations

Be aware of the following limitations when you use TimesTen XLA:

  • XLA is available on all platforms supported by TimesTen. However, XLA does not support data transfer between different platforms or between 32-bit and 64-bit versions of the same platform.

  • XLA support for LOBs is limited. See "Specifying which tables to monitor for updates" for information.

  • XLA does not support applications linked with a driver manager library or the client/server library.

  • An XLA reader cannot subscribe to a table that uses in-memory columnar compression.

  • For autorefresh cache groups, the change-tracking trigger on Oracle does not have column-level resolution. (To have that would be very expensive.) Therefore the autorefresh feature will update all the columns in the row, and XLA can only report that all the columns have changed, even if data did not actually change in all columns.

XLA demo

TimesTen provides the xlaSimple demo showing how to use many of the XLA functions described in this chapter. It is located in the quickstart/sample_code/odbc/xla directory:

See "About the TimesTen C demos" for an overview of TimesTen demo programs for C developers. Refer to install_dir/quickstart.html for details. The README file in the odbc directory contains instructions for building and running xlaSimple, among others.

Most of this chapter, including the sample code shown in "Writing an XLA event-handler application" starting immediately below, is based on the xlaSimple demo. For this demo, a table MYDATA has been created in the APPUSER schema. While you are logged in as APPUSER, you will be making updates to the table. While you are logged in as XLAUSER, the xlaSimple demo reports on the updates.

To run the demo, execute xlaSimple at one command prompt. You will be prompted for the password of XLAUSER, which is specified when the sample database is created. Start ttIsql at a separate command prompt, connecting to the TimesTen sample database as APPUSER. Again, you will be prompted for a password that is specified when the sample database is created.

At the ttIsql command prompt you can enter DML statements to alter the table. Then you can view the XLA output in the xlaSimple window.

Writing an XLA event-handler application

This section describes the general procedures for writing an XLA application that detects and reports changes to selected tables in a database. With the possible exception of "Inspecting column data", the procedures described in this section are applicable to most XLA applications.

The following procedures are described:

The example code in this section is based on the xlaSimple demo application.

XLA functions mentioned here are documented in Chapter 9, "XLA Reference".


Important:

In addition to files noted in "TimesTen include files", an XLA application must include tt_xla.h.


Note:

To simplify the code examples, routine error checking code for each function call has been omitted. See "Handling XLA errors" for information on error handling.

Obtaining a database connection handle

As with every ODBC application, an XLA application must initialize ODBC, obtain an environment handle (henv), and obtain a connection handle (hdbc) to communicate with the specific database.

Initialize the environment and connection handles:

SQLHENV henv = SQL_NULL_HENV;
SQLHDBC hdbc = SQL_NULL_HDBC;

Pass the address of henv to the SQLAllocEnv ODBC function to allocate an environment handle:

rc = SQLAllocEnv(&henv);

Pass the address of hdbc to the SQLAllocConnect ODBC function to allocate a connection handle for the database:

rc = SQLAllocConnect(henv, &hdbc);

Call the SQLDriverConnect ODBC function to connect to the database specified by the connection string (connStr), which in this example is passed from the command line:

static char connstr[CONN_STR_LEN];
...
rc = SQLDriverConnect(hdbc, NULL, (SQLCHAR*)connstr, SQL_NTS, NULL, 0,
                      NULL, SQL_DRIVER_COMPLETE);

Note:

After an ODBC connection handle is opened for use by an XLA application, the ODBC handle cannot be used for ODBC operations until the corresponding XLA handle is closed by calling ttXlaClose.

Call the SQLSetConnectOption ODBC function to turn autocommit off:

rc = SQLSetConnectOption(hdbc, SQL_AUTOCOMMIT, SQL_AUTOCOMMIT_OFF);

Initializing XLA and obtaining an XLA handle

After initializing ODBC and obtaining an environment and connection handle as described in the preceding section, "Obtaining a database connection handle", you can initialize XLA and obtain an XLA handle to access the transaction log. Create only one XLA handle per ODBC connection. If your application uses multiple XLA reader threads (each connected to its own XLA bookmark), create a separate XLA handle and ODBC connection for each thread.

This section describes how to initialize XLA.

Before initializing XLA, initialize a bookmark. Then initialize an XLA handle as type ttXlaHandle_h:

unsigned char bookmarkName [32];
...
strcpy((char*)bookmarkName, "xlaSimple");
...
ttXlaHandle_h xla_handle = NULL;

Pass bookmarkName and the address of xla_handle to the ttXlaPersistOpen function to obtain an XLA handle:

rc = ttXlaPersistOpen(hdbc, bookmarkName, XLACREAT, &xla_handle);

The XLACREAT option is used to create a new non-replicated bookmark. Alternatively, use the XLAREPL option to create a replicated bookmark. In either case, the operation will fail if the bookmark already exists.

To use a bookmark that already exists, call ttXlaPersistOpen with the XLAREUSE option, as shown in the following example.

#include <tt_errCode.h>      /* TimesTen Native Error codes */
...
    if ( native_error == 907 ) { /* tt_ErrKeyExists */
      rc = ttXlaPersistOpen(hdbc, bookmarkName, XLAREUSE, &xla_handle);
    ...
    }

If ttXlaPersistOpen is given invalid parameters, or the application was unable to allocate memory for the handle, the return code will be SQL_INVALID_HANDLE. In this situation, ttXlaError cannot be used to detect this or any further errors.

If ttXlaPersistOpen fails but still creates a handle, the handle must be closed to prevent memory leaks.

Specifying which tables to monitor for updates

After initializing XLA and obtaining an XLA handle as described in the preceding section, "Initializing XLA and obtaining an XLA handle", you can specify which tables or materialized views you want to monitor for update events.

You can determine which tables a bookmark is subscribed to by querying the SYS.XLASUBSCRIPTIONS table. You can also use SYS.XLASUBSCRIPTIONS to determine which bookmarks have subscribed to a specific table.

The ttXlaNextUpdate and ttXlaNextUpdateWait functions retrieve XLA records associated with DDL events. DDL XLA records are available to any XLA bookmark. DDL events include CREATAB, DROPTAB, CREAIND, DROPIND, CREATVIEW, DROPVIEW, CREATSEQ, DROPSEQ, CREATSYN, DROPSYN, ADDCOLS, DRPCOLS, and TRUNCATE transactions. See "ttXlaUpdateDesc_t" for information about these event types.

The ttXlaTableStatus function subscribes the current bookmark to updates to the specified table. Or it determines whether the current bookmark is already monitoring DML records associated with the table.

Call the ttXlaTableByName function to obtain both the system and user identifiers for a named table or materialized view. Then call the ttXlaTableStatus function to enable XLA to monitor changes to the table or materialized view.


Note:

LOB support in XLA is limited, as follows:
  • You can subscribe to tables containing LOB columns, but information about the LOB value itself is unavailable.

  • ttXlaGetColumnInfo returns information about LOB columns.

  • Columns containing LOBs are reported as empty (zero length) or null (if the value is actually NULL). In this way, you can tell the difference between a null column and a non-null column.


Example 5-2 Specifying a table to monitor for updates

This example tracks changes to the MYDATA table:

#define TABLE_OWNER "APPUSER"
#define TABLE_NAME "MYDATA"
...
SQLUBIGINT SYSTEM_TABLE_ID = 0;
...
SQLUBIGINT userID;

rc = ttXlaTableByName(xla_handle, TABLE_OWNER, TABLE_NAME,
                      &SYSTEM_TABLE_ID, &userID);

When you have the table identifiers, you can use the ttXlaTableStatus function to enable XLA update tracking to detect changes to the MYDATA table. Setting the newstatus parameter to a nonzero value results in XLA tracking changes made to the specified table:

SQLINTEGER oldstatus;
SQLINTEGER newstatus = 1;
...
rc = ttXlaTableStatus(xla_handle, SYSTEM_TABLE_ID, 0,
                      &oldstatus, &newstatus);

The oldstatus parameter is output to indicate the status of the table at the time of the call.

At any time, you can use ttXlaTableStatus to return the current XLA status of a table by leaving newstatus null and returning only oldstatus. For example:

rc = ttXlaTableStatus(xla_handle, SYSTEM_TABLE_ID, 0,
                      &oldstatus, NULL);
...
if (oldstatus != 0)
     printf("XLA is currently tracking changes to table %s.%s\n",
             TABLE_OWNER, TABLE_NAME);
else
     printf("XLA is not tracking changes to table %s.%s\n",
             TABLE_OWNER, TABLE_NAME);

Retrieving update records from the transaction log

Once you have specified which tables to monitor for updates, you can call the ttXlaNextUpdate or ttXlaNextUpdateWait function to return a batch of records from the transaction log. Only records for committed transactions are returned. They are returned in the order in which they were committed. You must periodically call the ttXlaAcknowledge function to acknowledge receipt of the transactions so that XLA can determine which records are no longer needed and can be purged from the transaction log. These functions impact the position of the application bookmark in the transaction log, as described in "How bookmarks work". Also see "ttLogHolds" in Oracle TimesTen In-Memory Database Reference for related information. That TimesTen built-in procedure returns information about transaction log holds.


Note:

The ttXlaAcknowledge function is an expensive operation and should be used only as necessary.

Each update record in a transaction returned by ttXlaNextUpdate begins with an update header described by the ttXlaUpdateDesc_t structure. This update header contains a flag indicating if the record is the first in the transaction (TT_UPDFIRST) or the last commit record (TT_UPDCOMMIT). The update header also identifies the table affected by the update. Following the update header are zero to two rows of data that describe the update made to that table in the database.

Figure 5-5 that follows shows a call to ttXlaNextUpdate that returns a transaction consisting of four update records from the transaction log. Receipt of the returned transaction is acknowledged by calling ttXlaAcknowledge, which resets the bookmark.


Note:

This example is simplified for clarity. An actual XLA application would likely read records for multiple transactions before calling ttXlaAcknowledge.

Figure 5-5 Update records

Description of Figure 5-5 follows
Description of "Figure 5-5 Update records"

Example 5-3 Retrieving update records from the transaction log

The xlaSimple demo continues to monitor our table for updates until stopped by the user.

Before calling ttXlaNextUpdateWait, the example initializes a pointer to the buffer to hold the returned ttXlaUpdateDesc_t records (arry) and a variable to hold the actual number of returned records (records). Because the example calls ttXlaNextUpdateWait, it also specifies the number of seconds to wait (FETCH_WAIT_SECS) if no records are found in the transaction log buffer.

Next, call ttXlaNextUpdateWait, passing these values to obtain a batch of ttXlaUpdateDesc_t records in arry. Then process each record in arry by passing it to the HandleChange() function described in Example 5-4. After all records are processed, call ttXlaAcknowledge to reset the bookmark position.

#define FETCH_WAIT_SECS 5
...
SQLINTEGER records;
ttXlaUpdateDesc_t** arry;
int j;

while (!StopRequested()) {

    /* Get a batch of update records */
    rc = ttXlaNextUpdateWait(xla_handle, &arry, 100,
                             &records, FETCH_WAIT_SECS);
    if (rc != SQL_SUCCESS {
      /* See "Handling XLA errors" */
    }

    /* Process the records */
    for(j=0; j < records; j++){
      ttXlaUpdateDesc_t* p;
      p = arry[j];
      HandleChange(p); /* Described in the next section */
    }

    /* After each batch, Acknowledge updates to reset bookmark.*/
    rc = ttXlaAcknowledge(xla_handle);
    if (rc != SQL_SUCCESS {
      /* See "Handling XLA errors" */
    }
} /* end while !StopRequested() */

The actual number of records returned by ttXlaNextUpdate or ttXlaNextUpdateWait, as indicated by the nreturned output parameter of those functions, may be less than the value of the maxrecords parameter. Figure 5-6 shows an example where maxrecords is 10, the transaction log contains transaction AT that is made up of seven records, and transaction BT that is made up of three records. In this case, both transactions are returned in the same batch and both maxrecords and nreturned values are 10. However, the next three transactions in the log are CT with 11 records, DT with two records, and ET with two records. Because the commit record for the DT transaction appears before the CT commit record, the next call to ttXlaNextUpdate returns the two records for the DT transaction and the value of nreturned is 2. In the next call to ttXlaNextUpdate, XLA detects that the total records for the CT transaction exceeds maxrecords, so it returns the records for this transaction in two batches. The first batch contains the first 10 records for CT (nreturned = 10). The second batch contains the last CT record and the two records for the ET transaction, assuming no commit record for a transaction following ET is detected within the next seven records.

See "ttXlaNextUpdate" and "ttXlaNextUpdateWait" for details of the parameters of these functions.

Figure 5-6 Records retrieved when maxrecords=10

Description of Figure 5-6 follows
Description of "Figure 5-6 Records retrieved when maxrecords=10"

XLA reads records from either a memory buffer or transaction log files on disk, as described in "How XLA reads records from the transaction log". To minimize latency, records from the memory buffer are returned as soon as they are available, while records not in the buffer are returned only if the buffer is empty. This design enables XLA applications to see changes as soon as the changes are made and with minimal latency. The trade-off is that there may be times when fewer changes are returned than the number requested by the ttXlaNextUpdate or ttXlaNextUpdateWait maxrecords parameter.


Note:

For optimal throughput, XLA applications should make the "fetch" and "process record" procedures asynchronous. For example, you can create one thread to fetch and store the records and one or more other threads to process the stored records.

Inspecting record headers and locating row addresses

Now that there is an array of update records where the type of operation each record represents is known, the returned row data can be inspected.

Each record returned by the ttXlaNextUpdate or ttXlaNextUpdateWait function begins with an ttXlaUpdateDesc_t header that describes the following:

  • The table on which the operation was performed

  • Whether the record is the first or last (commit) record in the transaction

  • The type of operation it represents

  • The length of the returned row data, if any

  • Which columns in the row were updated, if any

Figure 5-7 shows one of the update records in the transaction log.

Figure 5-7 Address of row data returned in an XLA update record

Description of Figure 5-7 follows
Description of "Figure 5-7 Address of row data returned in an XLA update record"

The ttXlaUpdateDesc_t header has a fixed length and, depending on the type of operation, is followed by zero to two rows (or tuples) from the database. You can locate the address of the first returned row by obtaining the address of the ttXlaUpdateDesc_t header and adding it to sizeof(ttXlaUpdateDesc_t):

tup1 = (void*) ((char*) ttXlaUpdateDesc_t + sizeof(ttXlaUpdateDesc_t));

This is shown in Example 5-4 below.

The ttXlaUpdateDesc_t ->type field describes the type of SQL operation that generated the update. Transaction records of type UPDATETTUP describe UPDATE operations, so they return two rows to report the row data before and after the update. You can locate the address of the second returned row that holds the value after the update by adding the address of the first row in the record to its length:

if (ttXlaUpdateDesc_t->type == UPDATETUP) {
  tup2 = (void*) ((char*) tup1 + ttXlaUpdateDesc_t->tuple1);
}

This is also shown in Example 5-4.

Example 5-4 Inspecting record headers for SQL operation type

This example passes each record returned by the ttXlaNextUpdateWait function to a HandleChange() function, which determines whether the record is related to an INSERT, UPDATE, or CREATE VIEW operation. To keep this example simple, all other operations are ignored.

The HandleChange() function handles each type of SQL operation differently before calling the PrintColValues() function described in Example 5-13.

void HandleChange(ttXlaUpdateDesc_t* xlaP)
{
  void*  tup1;
  void*  tup2;
 
  /* First confirm that the XLA update is for the table we care about. */
  if (xlaP->sysTableID != SYSTEM_TABLE_ID)
    return ;
 
  /* OK, it's for the table we're monitoring. */
 
  /* The last record in the ttXlaUpdateDesc_t record is the "tuple2"
   * field.  Immediately following this field is the first XLA record "row". */
 
  tup1 = (void*) ((char*) xlaP + sizeof(ttXlaUpdateDesc_t));
 
  switch(xlaP->type) {
 
  case INSERTTUP:
    printf("Inserted new row:\n");
    PrintColValues(tup1);
    break;
 
  case UPDATETUP:
 
    /* If this is an update ttXlaUpdateDesc_t, then following that is
     * the second XLA record "row".  
     */
 
    tup2 = (void*) ((char*) tup1 + xlaP->tuple1);
    printf("Updated row:\n");
    PrintColValues(tup1);
    printf("To:\n");
    PrintColValues(tup2);
    break;
 
  case DELETETUP:
    printf("Deleted row:\n");
    PrintColValues(tup1);
    break;
 
  default:
    /* Ignore any XLA records that are not for inserts/update/delete SQL ops. */
    break;
 
  } /* switch (xlaP->type) */
}

Inspecting column data

As described in "Inspecting record headers and locating row addresses", zero to two rows of data may be returned in an update record after the ttXlaUpdateDesc_t structure. For each row, the first portion of the data is the fixed-length data, which is followed by any variable-length data, as shown in Figure 5-8.

Figure 5-8 Column offsets in a row returned in an XLA update record

Description of Figure 5-8 follows
Description of "Figure 5-8 Column offsets in a row returned in an XLA update record"

The procedures for inspecting column data are described in the following sections:

Obtaining column descriptions

To read the column values from the returned row, you must first know the offset of each column in that row. The column offsets and other column metadata can be obtained for a particular table by calling the ttXlaGetColumnInfo function, which returns a separate ttXlaColDesc_t structure for each column in the table. You should call the ttXlaGetColumnInfo function as part of your initialization procedure. This call was omitted from the discussion in "Initializing XLA and obtaining an XLA handle" for simplicity.

When calling ttXlaGetColumnInfo, specify a colinfo parameter to create a pointer to a buffer to hold the list of returned ttXlaColDesc_t structures. Use the maxcols parameter to define the size of the buffer.

Example 5-5 Using column descriptions

The sample code from the xlaSimple demo below guesses the maximum number of returned columns (MAX_XLA_COLUMNS), which sets the size of the buffer xla_column_defs to hold the returned ttXlaColDesc_t structures. An alternative and more precise way to set the maxcols parameter would be to call the ttXlaGetTableInfo function and use the value returned in ttXlaColDesc_t ->columns.

#define MAX_XLA_COLUMNS 128
...
SQLINTEGER ncols;
...
ttXlaColDesc_t xla_column_defs[MAX_XLA_COLUMNS];
...
rc = ttXlaGetColumnInfo(xla_handle, SYSTEM_TABLE_ID, userID,
             xla_column_defs, MAX_XLA_COLUMNS, &ncols);
  if (rc != SQL_SUCCESS {
    /* See "Handling XLA errors" */
}

As shown in Figure 5-9, the ttXlaGetColumnInfo function produces the following output:

  • A list, xla_column_defs, of ttXlaColDesc_t structures into the buffer pointed to by the ttXlaGetColumnInfo colinfo parameter.

  • An nreturned value, ncols, that holds the actual number of columns returned in the xla_column_defs buffer.

Figure 5-9 ttXlaColDesc_t structures returned by ttXlaGetColumnInfo

Description of Figure 5-9 follows
Description of "Figure 5-9 ttXlaColDesc_t structures returned by ttXlaGetColumnInfo"

Each ttXlaColDesc_t structure returned by ttXlaGetColumnInfo has an offset value that describes the offset location of that column. How you use this offset value to read the column data depends on whether the column contains fixed-length data (such as CHAR, NCHAR, INTEGER, BINARY, DOUBLE, FLOAT, DATE, TIME, TIMESTAMP, and so on) or variable-length data (such as VARCHAR, NVARCHAR, or VARBINARY).

Reading fixed-length column data

For fixed-length column data, the address of a column is the offset value in the ttXlaColDesc_t structure, plus the address of the row.

Figure 5-10 Locating fixed-length data in a row

Description of Figure 5-10 follows
Description of "Figure 5-10 Locating fixed-length data in a row"

Example 5-6 Reading fixed-length column data

See Example 5-13 for a complete working example of computations such as those shown here.

The first column in the MYDATA table is of type CHAR. If you use the address of the tup1 row obtained earlier in the HandleChange() function (Example 5-4) and the offset from the first ttXlaColDesc_t structure returned by the ttXlaGetColumnInfo function (Example 5-5), you can obtain the value of the first column with computations such as the following:

char*  Column1;

Column1 = ((unsigned char*) tup1 + xla_column_defs[0].offset);

The third column in the MYDATA table is of type INTEGER, so you can use the offset from the third ttXlaColDesc_t structure to locate the value and recast it as an integer using computations such as the following. The data is guaranteed to be aligned properly.

int Column3;

Column3 = *((int*) ((unsigned char*) tup +
           xla_column_defs[2].offset));

The fourth column in the MYDATA table is of type NCHAR, so you can use the offset from the fourth ttXlaColDesc_t structure to locate the value and recast it as a SQLWCHAR type, with computations such as the following:

SQLWCHAR*  Column4;

Column4 = (SQLWCHAR*) ((unsigned char*) tup +
                      xla_column_defs[3].offset);

Unlike the column values obtained in the above examples, Column4 points to an array of two-byte Unicode characters. You must iterate through each element in this array to obtain the string, as shown for the SQL_WCHAR case in Example 5-13.

Other fixed-length data types can be cast to their corresponding C types. Complex fixed-length data types, such as DATE, TIME, and DECIMAL values, are stored in an internal TimesTen format, but can be converted by applications to their corresponding ODBC C value using the XLA conversion functions, as described in "Converting complex data types".


Note:

Strings returned by XLA are not null-terminated. See "Null-terminating returned strings".

Reading NOT INLINE variable-length column data

For NOT INLINE variable-length data (VARCHAR, NVARCHAR, and VARBINARY), the data located at ttXlaColDesc_t ->offset is a four-byte offset value that points to the location of the data in the variable-length portion of the returned row. By adding the offset address to the offset value, you can obtain the address of the column data in the variable-length portion of the row. The first n bytes (where n is 4 on 32-bit platforms or 8 on 64-bit platforms) at this location is the length of the data, followed by the actual data. For variable-length data, the ttXlaColDesc_t ->size value is the maximum allowable column size. Figure 5-11 shows how to locate NOT INLINE variable-length data in a row.

Figure 5-11 Locating NOT INLINE variable-length data in a row

Description of Figure 5-11 follows
Description of "Figure 5-11 Locating NOT INLINE variable-length data in a row"

Example 5-7 Reading NOT INLINE variable-length column data

See Example 5-13, "Complete PrintColValues() function" for a complete working example of computations such as those shown here.

Continuing with our example, the second column in the returned row (tup1) is of type VARCHAR. To locate the variable-length data in the row, first locate the value at the column's ttXlaColDesc_t ->offset in the fixed-length portion of the row, as shown in Figure 5-11 above. The value at this address is the four-byte offset of the data in the variable-length portion of the row (VarOffset). Next, obtain a pointer to the beginning of the variable-length column data (DataLength) by adding the VarOffset offset value to the address of VarOffset. Assuming the operation is performed on a 32-bit platform, the first four bytes at the DataLength location is the length of the data. The next byte after DataLength is the beginning of the actual data (Column2).

The sample code here assumes the operation is performed on a 32-bit platform, so DataLength is initialized as a 32-bit type. On a 64-bit platform, DataLength must be initialized as a 64-bit type and the Column2 data would appear 64 bits + 1 after the offset address, DataLength.

void*  VarOffset; /* offset of data */
long*  DataLength; /* length of data */
char*  Column2; /* pointer to data */

VarOffset = (void*) ((unsigned char*) tup1 +
             xla_column_defs[1].offset);
     /*
      * If column is out-of-line, pColVal points to an offset
      * else column is inline so pColVal points directly to the string length.
      */

      if (xla_column_defs[1].flags & TT_COLOUTOFLINE)
      DataLength = (long*)((char*)VarOffset + *((int*)VarOffset));
      else
      DataLength = (long*)VarOffset;
      Column2 = (char*)(DataLength+1);

VARBINARY types are handled in a manner similar to VARCHAR types. If Column2 were an NVARCHAR type, you could initialize it as a SQLWCHAR, get the value as shown in the above VARCHAR case, then iterate through the Column2 array, as shown for the NCHAR value, CharBuf, in Example 5-13.


Note:

In the preceding example, DataLength is type long, which is described as being a 64-bit (8-byte) type on 64-bit systems and a 32-bit (4-byte) type on 32-bit systems. This is true on most UNIX systems; however, on Windows 64-bit systems long is a 4-byte type.

Null-terminating returned strings

Strings returned from record row data are not terminated with a null character. You can null-terminate a string by copying it into a buffer and adding a null character, '\0', after the last character in the string.

The procedures for null-terminating fixed-length and variable-length strings are slightly different. The procedure for null-terminating fixed-length strings is described in Example 5-8. Example 5-9 that follows describes the procedure for null-terminating variable-length strings of a known size. Example 5-10 then describes the procedure for strings of an unknown size.

Example 5-8 Null-terminating fixed-length strings

See Example 5-13 for a complete working example of computations such as those shown here.

To null-terminate the fixed-length CHAR(10) Column1 string returned in Example 5-6, establish a buffer large enough to hold the string plus null character. Next, obtain the size of the string from ttXlaColDesc_t ->size, copy the string into the buffer, and null-terminate the end of the string, using computations such as the following. You can now use the contents of the buffer. In this example, the string is printed:

char buffer[10+1];
int size;

size = xla_column_defs[0].size;
memcpy(buffer, Column1, size);
buffer[size] = '\0';

printf(" Row %s is %s\n", ((unsigned char*) xla_column_defs[0].colName), buffer);

Null-terminating a variable-length string is similar to the procedure for fixed-length strings, only the size of the string is the value located at the beginning of the variable-length data offset, as described in "Reading NOT INLINE variable-length column data".

Example 5-9 Null-terminating variable-length strings of known size

(See Example 5-13 for a complete working example of computations such as those shown here.)

If the Column2 string obtained in Example 5-7 is a VARCHAR(32), establish a buffer large enough to hold the string plus null character. Use the value located at the DataLength offset to determine the size of the string, using computations such as the following:

char buffer[32+1];

memcpy(buffer, Column2, *DataLength);
buffer[*DataLength] = '\0';

printf(" Row %s is %s\n", ((unsigned char*) xla_column_defs[1].colName), buffer);

If you are writing general purpose code to read all data types, you cannot make any assumptions about the size of a returned string. For strings of an unknown size, statically allocate a buffer large enough to hold the majority of returned strings. If a returned string is larger than the buffer, dynamically allocate the correct size buffer, as shown in Example 5-10.

Example 5-10 Null-terminating variable-length strings of unknown size

If the Column2 string obtained in Example 5-7 is of an unknown size, you might statically allocate a buffer large enough to hold a string of up to 10000 characters. Then check that the DataLength value obtained at the beginning of the variable-length data offset is less than the size of the buffer. If the string is larger than the buffer, use malloc() to dynamically allocate the buffer to the correct size.

#define STACKBUFSIZE 10000
char VarStackBuf[STACKBUFSIZE];
char*  buffer;

buffer = (*DataLength+1 <= STACKBUFSIZE) ? VarStackBuf :
           malloc(*DataLength+1);

memcpy(buffer,Column2,*DataLength);
buffer[*DataLength] = '\0';

printf(" Row %s is %s\n", ((unsigned char*) xla_column_defs[1].colName), buffer);
if (buffer != VarStackBuf) /* buffer was allocated */
        free(buffer);

Converting complex data types

Values for complex data types such as TT_DATE, TT_TIME, and TT_DECIMAL are stored in an internal TimesTen format that can be converted into corresponding ODBC C types using the XLA type conversion functions. Table 5-2 contains descriptions of these conversion functions.

Table 5-2 XLA data type conversion functions

FunctionConverts

ttXlaDateToODBCCType

Internal TT_DATE value to an ODBC C value

ttXlaTimeToODBCCType

Internal TT_TIME value to an ODBC C value

ttXlaTimeStampToODBCCType

Internal TT_TIMESTAMP value to an ODBC C value

ttXlaDecimalToCString

Internal TT_DECIMAL value to a string value

ttXlaDateToODBCCType

Internal TTXLA_DATE_TT value to an ODBC C value

ttXlaDecimalToCString

Internal TTXLA_DECIMAL_TT value to a character string

ttXlaNumberToBigInt

Internal TTXLA_NUMBER value to a TT_BIGINT value

ttXlaNumberToCString

Internal TTXLA_NUMBER value to a character string

ttXlaNumberToDouble

Internal TTXLA_NUMBER value to a long floating point number value

ttXlaNumberToInt

Internal TTXLA_NUMBER value to an integer

ttXlaNumberToSmallInt

Internal TTXLA_NUMBER value to a TT_SMALLINT value

ttXlaNumberToTinyInt

Internal TTXLA_NUMBER value to a TT_TINYINT value

ttXlaNumberToUInt

Internal TTXLA_NUMBER value to an unsigned integer

ttXlaOraDateToODBCTimeStamp

Internal TTXLA_DATE value to an ODBC timestamp

ttXlaOraTimeStampToODBCTimeStamp

Internal TTXLA_TIMESTAMP value to an ODBC timestamp

ttXlaTimeToODBCCType

Internal TTXLA_TIME value to an ODBC C value

ttXlaTimeStampToODBCCType

Internal TTXLA_TIMESTAMP_TT value to an ODBC C value


These conversion functions can be used on row data in the ttXlaUpdateDesc_t types: UPDATETUP, INSERTTUP and DELETETUP.

Example 5-11 Converting complex data types

(See Example 5-13 for a complete working example of computations such as those shown here.)

If you use the address of the tup1 row obtained earlier in the HandleChange() function (Example 5-4) and the offset from the fifth ttXlaColDesc_t structure returned by the ttXlaGetColumnInfo function (Example 5-5), you can locate a column value of type TIMESTAMP. Use the ttXlaTimeStampToODBCCType function to convert the column data from TimesTen format and store the converted time value in an ODBC TIMESTAMP_STRUCT. You could use code such as the following to print the values:

void*  Column5;
TIMESTAMP_STRUCT timestamp;

Column5 = (void*) ((unsigned char*) tup1 +
                  xla_column_defs[4].offset);

rc = ttXlaTimeStampToODBCCType(Column5, &timestamp);
  if (rc != SQL_SUCCESS) {
    /* See "Handling XLA errors" */
  }
printf(" %s: %04d-%02d-%02d %02d:%02d:%02d.%06d\n",
      ((unsigned char*) xla_column_defs[i].colName),
        timestamp.year,timestamp.month, timestamp.day,
        timestamp.hour,timestamp.minute,timestamp.second,
        timestamp.fraction);

If you use the address of the tup1 row obtained earlier in the HandleChange() function (Example 5-4) and the offset from the sixth ttXlaColDesc_t structure returned by the ttXlaGetColumnInfo function (Example 5-5), you can locate a column value of type DECIMAL. Use the ttXlaDecimalToCString function to convert the column data from TimesTen decimal format to a string. You could use code such as the following to print the values.

char decimalData[50];

Column6 = (float*) ((unsigned char*) tup +
           xla_column_defs[5].offset);
precision = (short) (xla_column_defs[5].precision);
scale = (short) (xla_column_defs[5].scale);

rc = ttXlaDecimalToCString(Column6, (char*)&decimalData,
                           precision, scale);
  if (rc != SQL_SUCCESS) {
    /* See "Handling XLA errors" */
  }

printf(" %s: %s\n", ((unsigned char*) xla_column_defs[5].colName), decimalData);

Detecting null values

For nullable table columns, ttXlaColDesc_t ->nullOffset points to the column's null byte in the record. This field is 0 (zero) if the column is not nullable, or greater than 0 if the column can be null.

For nullable columns (ttXlaColDesc_t ->nullOffset > 0), to determine if the column is null, add the null offset to the address of ttXlaUpdate_t* and check the (unsigned char) byte there to see if it is 1 (NULL) or 0 (NOT NULL).

Example 5-12 Detecting null values

Check whether Column6 is null as follows:

if (xla_column_defs[5].nullOffset != 0) {
  if (*((unsigned char*) tup +
     xla_column_defs[5].nullOffset) == 1) {
         printf("Column6 is NULL\n");
  }
}

Putting it all together: a PrintColValues() function

Example 5-13 shows a function that checks the ttXlaColDesc_t ->dataType of each column to locate columns with a data type of CHAR, NCHAR, INTEGER, TIMESTAMP, DECIMAL, and VARCHAR, then prints the values. This is just one possible approach. Another option, for example, would be to check the ttXlaColDesc_t ->ColName values to locate specific columns by name.

The PrintColValues() function handles CHAR and VARCHAR strings up to 50 bytes in length. NCHAR characters must belong to the ASCII character set.

Example 5-13 Complete PrintColValues() function

The function in this example first checks ttXlaColDesc_t ->nullOffset to see if the column is null. Next it checks the ttXlaColDesc_t ->dataType field to determine the data type for the column. For simple fixed-length data (CHAR, NCHAR, and INTEGER), it casts the value located at ttXlaColDesc_t ->offset to the appropriate C type. The complex data types, TIMESTAMP and DECIMAL, are converted from their TimesTen formats to ODBC C values using the ttXlaTimeStampToODBCCType and ttXlaDecimalToCString functions.

For variable-length data (VARCHAR), the function locates the data in the variable-length portion of the row, as described in "Handling XLA errors".

void PrintColValues(void* tup)
{ 
 
  SQLRETURN rc ;
  SQLINTEGER native_error;
 
  void* pColVal;
  char buffer[50+1]; /* No strings over 50 bytes */
  int i;
 
  for (i = 0; i < ncols; i++)
  {
 
    if (xla_column_defs[i].nullOffset != 0) {  /* See if column is NULL */
      /* this means col could be NULL */
      if (*((unsigned char*) tup + xla_column_defs[i].nullOffset) == 1) {
        /* this means that value is SQL NULL */
        printf("  %s: NULL\n", 
               ((unsigned char*) xla_column_defs[i].colName));
        continue; /* Skip rest and re-loop */
      }
    }
 
    /* Fixed-length data types: */
    /* For INTEGER, recast as int */
 
    if (xla_column_defs[i].dataType == TTXLA_INTEGER) {
 
      printf("  %s: %d\n",
             ((unsigned char*) xla_column_defs[i].colName),
             *((int*) ((unsigned char*) tup + xla_column_defs[i].offset)));
    }

    /* For CHAR, just get value and null-terminate string */
 
    else if (   xla_column_defs[i].dataType == TTXLA_CHAR_TT
             || xla_column_defs[i].dataType == TTXLA_CHAR) {
 
      pColVal = (void*) ((unsigned char*) tup + xla_column_defs[i].offset);
 
      memcpy(buffer, pColVal, xla_column_defs[i].size);
      buffer[xla_column_defs[i].size] = '\0';
 
      printf("  %s: %s\n", ((unsigned char*) xla_column_defs[i].colName), buffer);
    }
 
    /* For NCHAR, recast as SQLWCHAR.
       NCHAR strings must be parsed one character at a time */
 
    else if (   xla_column_defs[i].dataType == TTXLA_NCHAR_TT  
             || xla_column_defs[i].dataType == TTXLA_NCHAR ) {
      SQLUINTEGER j;
      SQLWCHAR* CharBuf;
 
      CharBuf = (SQLWCHAR*) ((unsigned char*) tup + xla_column_defs[i].offset);

      printf("  %s: ", ((unsigned char*) xla_column_defs[i].colName));
 
      for (j = 0; j < xla_column_defs[i].size / 2; j++)
      { 
        printf("%c", CharBuf[j]);
      }
      printf("\n");
    }
    /* Variable-length data types:
       For VARCHAR, locate value at its variable-length offset and null-terminate.
       VARBINARY types are handled in a similar manner.
       For NVARCHARs, initialize 'var_data' as a SQLWCHAR, get the value as shown 
       below, then iterate through 'var_len' as shown for NCHAR above */
 
    else if (   xla_column_defs[i].dataType == TTXLA_VARCHAR
             || xla_column_defs[i].dataType == TTXLA_VARCHAR_TT) {
 
      long*  var_len;
      char* var_data;
      pColVal = (void*) ((unsigned char*) tup + xla_column_defs[i].offset);
      /*
       * If column is out-of-line, pColVal points to an offset
       * else column is inline so pColVal points directly to the string length.
       */
      if (xla_column_defs[i].flags & TT_COLOUTOFLINE)
        var_len = (long*)((char*)pColVal + *((int*)pColVal));
      else
        var_len = (long*)pColVal;
 
      var_data = (char*)(var_len+1);
 
      memcpy(buffer,var_data,*var_len);
      buffer[*var_len] = '\0';
 
      printf("  %s: %s\n", ((unsigned char*) xla_column_defs[i].colName), buffer);
    }
    /* Complex data types require conversion by the XLA conversion methods
       Read and convert a TimesTen TIMESTAMP value.
       DATE and TIME types are handled in a similar manner  */
 
    else if (   xla_column_defs[i].dataType == TTXLA_TIMESTAMP
             || xla_column_defs[i].dataType == TTXLA_TIMESTAMP_TT) {
 
      TIMESTAMP_STRUCT timestamp;
      char* convFunc;
 
      pColVal = (void*) ((unsigned char*) tup + xla_column_defs[i].offset);
 
      if (xla_column_defs[i].dataType == TTXLA_TIMESTAMP_TT) {
        rc = ttXlaTimeStampToODBCCType(pColVal, &timestamp);
        convFunc="ttXlaTimeStampToODBCCType";
      }
      else {
        rc = ttXlaOraTimeStampToODBCTimeStamp(pColVal, &timestamp);
        convFunc="ttXlaOraTimeStampToODBCTimeStamp";
      }
 
      if (rc != SQL_SUCCESS) {
        handleXLAerror (rc, xla_handle, err_buf, &native_error);
        fprintf(stderr, "%s() returns an error <%d>: %s", 
                convFunc, rc, err_buf);
        TerminateGracefully(1);
      }

      printf("  %s: %04d-%02d-%02d %02d:%02d:%02d.%06d\n",
             ((unsigned char*) xla_column_defs[i].colName),
             timestamp.year,timestamp.month, timestamp.day,
             timestamp.hour,timestamp.minute,timestamp.second,
             timestamp.fraction);
    }
 
    /* Read and convert a TimesTen DECIMAL value to a string. */
 
    else if (xla_column_defs[i].dataType == TTXLA_DECIMAL_TT) {
 
      char decimalData[50]; 
      short precision, scale;
      pColVal = (float*) ((unsigned char*) tup + xla_column_defs[i].offset);
      precision = (short) (xla_column_defs[i].precision);
      scale = (short) (xla_column_defs[i].scale);
 
      rc = ttXlaDecimalToCString(pColVal, (char*)&decimalData, precision, scale);
      if (rc != SQL_SUCCESS) {
        handleXLAerror (rc, xla_handle, err_buf, &native_error);
        fprintf(stderr, "ttXlaDecimalToCString() returns an error <%d>: %s", 
                rc, err_buf);
        TerminateGracefully(1);
      }
 
      printf("  %s: %s\n", ((unsigned char*) xla_column_defs[i].colName),
             decimalData);
    }
    else if (xla_column_defs[i].dataType == TTXLA_NUMBER) {
      char numbuf[32];
      pColVal = (void*) ((unsigned char*) tup + xla_column_defs[i].offset);
 
      rc=ttXlaNumberToCString(xla_handle, pColVal, numbuf, sizeof(numbuf));
      if (rc != SQL_SUCCESS) {
        handleXLAerror (rc, xla_handle, err_buf, &native_error);
        fprintf(stderr, "ttXlaNumberToDouble() returns an error <%d>: %s",
                rc, err_buf);
        TerminateGracefully(1);
      }
      printf("  %s: %s\n", ((unsigned char*) xla_column_defs[i].colName), numbuf);
    }
 
  } /* End FOR loop */
}

Notes:

  • In the preceding example, var_len is type long, assumed to be a 64-bit (8-byte) type on 64-bit systems and a 32-bit (4-byte) type on 32-bit systems. This is true on most UNIX systems; however, on Windows 64-bit systems long is a 4-byte type.

  • See "Terminating an XLA application" for a sample TerminateGracefully() method.


Handling XLA errors

Each time you call an ODBC or XLA function, you must check the return code for any errors. If the error is fatal, terminate the program as described in "Terminating an XLA application".

An error can be checked using either its error code (error number) or tt_Err string. For the complete list of TimesTen error codes and error strings, see the install_dir/include/tt_errCode.h file. For a description of each message, see "List of errors and warnings" in Oracle TimesTen In-Memory Database Error Messages and SNMP Traps.

If the return code from an XLA function is not SQL_SUCCESS, use the ttXlaError function to retrieve XLA-specific errors on the XLA handle.

Also see "Checking for errors".

Example 5-14 Checking the return code and calling the error-handling function

This example, after calling the XLA function ttXlaTableByName, checks to see if the return code is SQL_SUCCESS. If not, it calls an XLA error-handling function followed by a function to terminate the application. See "Terminating an XLA application".

rc = ttXlaTableByName(xla_handle, TABLE_OWNER, TABLE_NAME,
                      &SYSTEM_TABLE_ID, &userID);
if (rc != SQL_SUCCESS) {
  handleXLAerror (rc, xla_handle, err_buf, &native_error);
  fprintf(stderr,
    "ttXlaTableByName() returns an error <%d>: %s", rc, err_buf);
  TerminateGracefully(1);
}

Your XLA error-handling function should repeatedly call ttXlaError until all XLA errors are read from the error stack, proceeding until the return code from ttXlaError is SQL_NO_DATA_FOUND. If you must reread the errors, you can call the ttXlaErrorRestart function to reset the error stack pointer to the first error.

The error stack is cleared after a call to any XLA function other than ttXlaError or ttXlaErrorRestart.


Note:

In cases where ttXlaPersistOpen cannot create an XLA handle, it returns the error code SQL_INVALID_HANDLE. Because no XLA handle has been created, ttXlaError cannot be used to detect this error. SQL_INVALID_HANDLE is returned only in cases where no memory can be allocated or the parameters provided are invalid.

Depending on your application, you may be required to act on specific XLA errors, including those shown in Table 5-3.

Table 5-3 XLA errors and codes

ErrorCode

tt_ErrDbAllocFailed

802 (transient)

tt_ErrCondLockConflict

6001 (transient)

tt_ErrDeadlockVictim

6002 (transient)

tt_ErrTimeoutVictim

6003 (transient)

tt_ErrPermSpaceExhausted

6220 (transient)

tt_ErrTempSpaceExhausted

6221 (transient)

tt_ErrBadXlaRecord

8024

tt_ErrXlaBookmarkUsed

8029

tt_ErrXlaLsnBad

8031

tt_ErrXlaNoSQL

8034

tt_ErrXlaNoLogging

8035

tt_ErrXlaParameter

8036

tt_ErrXlaTableDiff

8037

tt_ErrXlaTableSystem

8038

tt_ErrXlaTupleMismatch

8046

tt_ErrXlaDedicatedConnection

8047


Example 5-15 Calling the handleXLAerror() function

This example shows handleXLAerror(), the error function for the xlaSimple demo program.

void handleXLAerror(SQLRETURN rc, ttXlaHandle_h xlaHandle, 
                    SQLCHAR* err_msg, SQLINTEGER* native_error)
{
  SQLINTEGER retLen;
  SQLINTEGER code;
 
  char* err_msg_ptr;
 
  /* initialize return codes */
  rc = SQL_ERROR;
  *native_error = -1;
  err_msg[0] = '\0';
  
  err_msg_ptr = (char*)err_msg;
  
  while (1)
  {
    int rc = ttXlaError(xlaHandle, &code, err_msg_ptr,
                        ERR_BUF_LEN - (err_msg_ptr - (char*)err_msg), &retLen);
    if (rc == SQL_NO_DATA_FOUND)
    {
      break;
    }
    if (rc != SQL_SUCCESS && rc != SQL_SUCCESS_WITH_INFO) {
      sprintf(err_msg_ptr,
              "*** Error fetching error message via ttXlaError(); rc=<%d>.",rc) ;
      break;
    }
    rc = SQL_ERROR;
    *native_error = code ; 
    /* append any other error messages */
    err_msg_ptr += retLen;
  }
}

Dropping a table that has an XLA bookmark

Before you can drop a table that is subscribed to by an XLA bookmark, you must unsubscribe the table from the bookmark. There are several ways to unsubscribe a table from a bookmark, depending on whether the application is connected to the bookmark.

If XLA applications are connected and using bookmarks that are tracking the table to be dropped, then perform the following tasks.

  1. Each XLA application must call the ttXlaTableStatus function and set the newstatus parameter to 0. This unsubscribes the table from the XLA bookmark in use by the application.

  2. Drop the table.

If XLA applications are not connected and using bookmarks associated with the table to be dropped, then perform the following tasks:

  1. Query the SYS.XLASUBSCRIPTIONS system table to see which bookmarks have subscribed to the table you want to drop.

  2. Use the ttXlaUnsubscribe built-in procedure to unsubscribe the table from each XLA bookmark with a subscription to the table.

  3. Drop the table.

Deleting bookmarks also unsubscribes the table from the XLA bookmarks. See the next section, "Deleting bookmarks".

Deleting bookmarks

You may want to delete bookmarks when you terminate an application or drop a table. Use the ttXlaDeleteBookmark function to delete XLA bookmarks if the application is connected and using the bookmarks.

As described in "About XLA bookmarks", a bookmark may be reused by a new connection after its previous connection has closed. The new connection can resume reading from the transaction log from where the previous connection stopped. Note the following:

  • If you delete the bookmark, subsequent checkpoint operations such as the ttCkpt or ttCkptBlocking built-in procedure will free the disk space associated with any unread update records in the transaction log.

  • If you do not delete the bookmark, when an XLA application connects and reuses the bookmark, all unread update records that have accumulated since the program terminated are read by the application. This is because the update records are persistent in the TimesTen transaction log. However, the danger is that these unread records can build up in the transaction log files and consume a lot of disk space.


Notes:

  • You cannot delete replicated bookmarks while the replication agent is running.

  • When you reuse a bookmark, you start with the Initial Read log record identifier in the transaction log file. To ensure that a connection that reuses a bookmark begins reading where the prior connection left off, the prior connection should call ttXlaAcknowledge to reset the bookmark position to the currently accessed record before disconnecting.

  • See "ttLogHolds" in Oracle TimesTen In-Memory Database Reference for related information. That TimesTen built-in procedure returns information about transaction log holds.

  • Be aware that ttCkpt and ttCkptBlocking require ADMIN privilege. TimesTen built-in procedures and any required privileges are documented in "Built-In Procedures" in Oracle TimesTen In-Memory Database Reference.


Example 5-16 Deleting bookmarks

The InitHandler() function in the xlaSimple demo deletes the XLA bookmark upon exit, as shown in the following example.

if (deleteBookmark) {
    ttXlaDeleteBookmark(xla_handle);
    if (rc != SQL_SUCCESS) {
    /* See "Handling XLA errors" */
    }
    xla_handle = NULL; /* Deleting the bookmark has the */
                       /* effect of disconnecting from XLA. */
}
/* Close the XLA connection as described in the next section, 
"Terminating an XLA application". */

If the application is not connected and using the XLA bookmark, you can delete the bookmark either of the following ways:

  • Close the bookmark and call the ttXlaBookmarkDelete built-in procedure.

  • Close the bookmark and use the ttIsql command xladeletebookmark.

Terminating an XLA application

When your XLA application has finished reading from the transaction log, gracefully exit by rolling back uncommitted transactions and freeing all handles. There are two approaches to this:

  • Unsubscribe from all tables and materialized views, delete the XLA bookmark, and disconnect from the database.

Or:

  • Disconnect from the database but keep the XLA bookmark in place. When you reconnect at a later time, you can resume reading records from the bookmark.

For the first approach, complete the following steps.

  1. Call ttXlaTableStatus to unsubscribe from each table and materialized view, setting the newstatus parameter to 0.

  2. Call ttXlaDeleteBookmark to delete the bookmark. See "Deleting bookmarks".

  3. Call ttXlaClose to disconnect the XLA handle.

  4. Call the ODBC function SQLTransact with the SQL_ROLLBACK setting to roll back any uncommitted transaction.

  5. Call the ODBC function SQLDisconnect to disconnect from the TimesTen database.

  6. Call the ODBC function SQLFreeConnect to free memory allocated for the ODBC connection handle.

  7. Call the ODBC function SQLFreeEnv to free the ODBC environment handle.

For the second approach, maintaining the bookmark, skip the first two steps but complete the remaining steps.

Be aware that resources should be freed in reverse order of allocation. For example, the ODBC environment handle is allocated before the ODBC connection handle, so for cleanup free the connection handle before the environment handle.

Example 5-17 Terminating an XLA application

This example shows TerminateGracefully(), the termination function in the xlaSimple Quick Start demo.

void TerminateGracefully(int status)
{
 
  SQLRETURN     rc;
  SQLINTEGER    native_error ; 
  SQLINTEGER    oldstatus;
  SQLINTEGER    newstatus = 0;
    
  /* If the table has been subscribed to through XLA, unsubscribe it. */
 
  if (SYSTEM_TABLE_ID != 0) {
    rc = ttXlaTableStatus(xla_handle, SYSTEM_TABLE_ID, 0,
                          &oldstatus, &newstatus);
    if (rc != SQL_SUCCESS) {
      handleXLAerror (rc, xla_handle, err_buf, &native_error);
      fprintf(stderr, "Error when unsubscribing from "TABLE_OWNER"."TABLE_NAME
              " table <%d>: %s", rc, err_buf);
    }
    SYSTEM_TABLE_ID = 0;
  }
 
  /* Close the XLA connection. */
 
  if (xla_handle != NULL) {
    rc = ttXlaClose(xla_handle);
    if (rc != SQL_SUCCESS) {
      fprintf(stderr, "Error when disconnecting from XLA:<%d>", rc);
    }
    xla_handle = NULL;
  }
 
  if (hstmt != SQL_NULL_HSTMT) {
    rc = SQLFreeStmt(hstmt, SQL_DROP);
    if (rc != SQL_SUCCESS) {
      handleError(rc, henv, hdbc, hstmt, err_buf, &native_error);
      fprintf(stderr, "Error when freeing statement handle:\n%s\n", err_buf);
    }
    hstmt = SQL_NULL_HSTMT;
  }
 
  /* Disconnect from TimesTen entirely. */
    
  if (hdbc != SQL_NULL_HDBC) {
    rc = SQLTransact(henv, hdbc, SQL_ROLLBACK);
    if (rc != SQL_SUCCESS) {
      handleError(rc, henv, hdbc, hstmt, err_buf, &native_error);
      fprintf(stderr, "Error when rolling back transaction:\n%s\n", err_buf);
    }
 
    rc = SQLDisconnect(hdbc);
    if (rc != SQL_SUCCESS) {
      handleError(rc, henv, hdbc, hstmt, err_buf, &native_error);
      fprintf(stderr, "Error when disconnecting from TimesTen:\n%s\n", err_buf);
    }
 
    rc = SQLFreeConnect(hdbc);
    if (rc != SQL_SUCCESS) {
      handleError(rc, henv, hdbc, hstmt, err_buf, &native_error);
      fprintf(stderr, "Error when freeing connection handle:\n%s\n", err_buf);
    }
    hdbc = SQL_NULL_HDBC;
  }
 
  if (henv != SQL_NULL_HENV) {
    rc = SQLFreeEnv(henv);
    if (rc != SQL_SUCCESS && rc != SQL_SUCCESS_WITH_INFO) {
      handleError(rc, henv, hdbc, hstmt, err_buf, &native_error);
      fprintf(stderr, "Error when freeing environment handle:\n%s\n", err_buf);
    }
    henv = SQL_NULL_HENV;
  }
  exit(status);
}

Using XLA as a replication mechanism

TimesTen replication as described in Oracle TimesTen In-Memory Database Replication Guide is sufficient for most customer needs; however, it is also possible to use XLA functions to replicate updates from one database to another. Implementing your own replication scheme on top of XLA in this way is fairly complicated, but can be considered if TimesTen replication is not feasible for some reason.


Note:

You cannot use XLA to replicate updates between different platforms or between 32-bit and 64-bit versions of the same platform.

In this section, the sending database is referred to as the master and the receiving database as the subscriber. To use XLA to replicate changes between databases, first use the ttXlaPersistOpen function to initialize the XLA handles, as described in "Initializing XLA and obtaining an XLA handle".

After the XLA handles have been initialized for the databases, take the steps described in the following sections:

XLA functions mentioned here are documented in Chapter 9, "XLA Reference".

Checking table compatibility between databases

Before transferring update records from one database to the other, verify that the tables in the master and subscriber databases are compatible with one another:

Checking table and column descriptions

Use the ttXlaTableByName, ttXlaGetTableInfo, and ttXlaGetColumnInfo functions to return ttXlaTblDesc_t and ttXlaColDesc_t descriptions for each table you want to replicate. These operations are described in "Specifying which tables to monitor for updates" and "Obtaining column descriptions". You can then pass these descriptions to the ttXlaTableCheck function. The output parameter, compat, specifies whether the tables are compatible. A value of 1 indicates compatibility and 0 indicates non-compatibility. The following example demonstrates this.

Example 5-18 Checking table and column descriptions for compatibility

SQLINTEGER compat;
ttXlaTblDesc_t table;
ttXlaColDesc_t columns[20];

rc = ttXlaTableCheck(xla_handle, &table, columns, &compat);
if (compat) {
    /* Go ahead and start replicating */
}
else {
    /* Not compatible or some other error occurred */
}

Checking table and column versions

Use the ttXlaVersionTableInfo and ttXlaVersionColumnInfo functions to retrieve the table structure information of an update record at the time the record was generated.

The following example verifies that the table associated with the pXlaRecord update record from the pCmd source is compatible with the hXlaTarget target.

Example 5-19 Checking table and column versions for compatibility

BOOL CUTLCheckXlaTable (SCOMMAND* pCmd,
                        ttXlaHandle_h hXlaTarget,
                        const ttXlaUpdateDesc_t* pXlaRecord)
{
  /* locals */
  ttXlaTblVerDesc_t tblVerDescSource;
  ttXlaColDesc_t colDescSource [255];
  SQLINTEGER iColsReturned = 0;
  SQLINTEGER iCompatible = 0;
  SQLRETURN rc;

  /* only certain update record types should be checked */
  if (pXlaRecord->type == INSERTTUP ||
      pXlaRecord->type == UPDATE>STUP ||
      pXlaRecord->type == DELETETUP)
  {
     /* Get source table description associated with this record */
     /* from the time it was generated. */
     rc = ttXlaVersionTableInfo (pCmd->pCtx->con->hXla,
             (ttXlaUpdateDesc_t*) pXlaRecord, &tblVerDescSource);

     if (rc == SQL_SUCCESS)
     {
         /* Get the source column descriptors for this table */
         /* at the time the record was generated. */
         rc = ttXlaVersionColumnInfo (pCmd->pCtx->con->hXla,
                 (ttXlaUpdateDesc_t*) pXlaRecord,
                 colDescSource, 255, &iColsReturned);

         if (rc == SQL_SUCCESS)
         {
             /* Check compatibility. */
             rc = ttXlaTableCheck (hXlaTarget,
                     &tblVerDescSource.tblDesc, colDescSource,
                     &iCompatible);
         }
     }
  }
}

Replicating updates between databases

When you are ready to begin replication, use the ttXlaNextUpdate or ttXlaNextUpdateWait function to obtain batches of update records from the master database and ttXlaApply to write the records to the subscriber database. The following example shows this.

Example 5-20 Replicating updates between databases

int j;
ttXlaHandle_h h;
SQLINTEGER records;
ttXlaUpdateDesc_t** arry;

  do {
    /* get up to 15 updates */
    rc = ttXlaNextUpdate(h,&arry,15,&records);
    if (rc != SQL_SUCCESS) {
      /* See "Handling XLA errors" */
    }
 
    /* print number of updates returned */
    printf("Records returned by ttXlaNextUpdate : %d\n",records);
 
    /* apply the received updates */  
    for (j=0;j < records;j++) {
      ttXlaUpdateDesc_t* p;
 
      p = arry[j];
      rc = ttXlaApply(h, p, 0);
      if (rc != SQL_SUCCESS){
      /* See "Handling XLA errors" and */
      /* "Handling timeout and deadlock errors" below */
      }
    }
 
    /* print number of updates applied */
    printf("Records applied successfully : %d\n",records);
 
  } while (records != 0);

Important:

If you are packaging data to be replicated across a network, or anywhere between processes not using the same memory space, you must ensure that the ttXlaUpdateDesc_t data structure is shipped in its entirely. Its length is indicated by ttXlaUpdateDesc_t ->header.length, where the header element is a ttXlaNodeHdr_t structure that in turn has a length element. Also see "ttXlaUpdateDesc_t" and "ttXlaNodeHdr_t".

Handling timeout and deadlock errors

The return code from ttXlaApply indicates whether the update was successful. If the return code is not SQL_SUCCESS, then the update may have encountered a transient problem, such as a deadlock or timeout, or a persistent problem. You can use ttXlaError to check for errors, such as tt_ErrDeadlockVictim or tt_ErrTimeoutVictim. Recovery from transient errors is possible by rolling back the replicated transaction and reexecuting it. Other errors may be persistent, such as those for duplicate key violations or key not found. Such errors are likely to repeat if the transaction is reexecuted.

If ttXlaApply returns a timeout or deadlock error before applying the commit record (ttXlaUpdateDesc_t ->flags = TT_UPDCOMMIT) for a transaction to the subscriber database, you can do either of the following:

  • Use ttXlaRollback to roll back the transaction.

  • Use ttXlaCommit to commit the changes in the records that have been applied to the subscriber database.

To enable recovery from transient errors, you should keep track of transaction boundaries on the master database and store the records associated with the transaction currently being applied to the subscriber in a user buffer, so you can reapply them if necessary. The transaction boundaries can be found by checking the flags member of the ttXlaUpdateDesc_t structure. Consider the following example. If this condition is true, then the record was committed:

(pXlaRecords [iRecordIndex]->flags & TT_UPDCOMMIT)

If you encounter an error that requires you to roll back a transaction, call ttXlaRollback to roll back the records applied to the subscriber database. Then call ttXlaApply to reapply all the rolled back records stored in your buffer.


Note:

An alternative to buffering the transaction records in a user buffer is to call ttXlaGetLSN to get the transaction log record identifier of each commit record in the transaction log, as described in "Changing the location of a bookmark". If you encounter an error that requires you to roll back a transaction, you can call ttXlaSetLSN to reset the bookmark to the beginning of the transaction in the transaction log and reapply the records. However, the extra overhead associated with the ttXlaGetLSN function may make this a less efficient option.

Checking for update conflicts

If you have applications making simultaneous updates to both your master and subscriber databases, you may encounter update conflicts. Update conflicts are described in detail in "Resolving Replication Conflicts" in Oracle TimesTen In-Memory Database Replication Guide.

To check for update conflicts in XLA, you can set the ttXlaApply test parameter to compare the old row value (ttXlaUpdateDesc_t ->tuple1) in each record of type UPDATETUP with the existing row in the subscriber database. If the old row value in the update description does not match the corresponding row in the subscriber database, an update conflict is probably the reason. In this case, ttXlaApply does not apply the update to the subscriber and returns an sb_ErrXlaTupleMismatch error.

Replicating updates to a non-TimesTen database

If you are replicating changes to a non-TimesTen database, you can use the ttXlaGenerateSQL function to convert the record data into a SQL statement that can be read by the non-TimesTen subscriber. For update and delete records, ttXlaGenerateSQL requires a primary key or a unique index on a non-nullable column to generate the correct SQL.

The ttXlaGenerateSQL function accepts a ttXlaUpdateDesc_t record as a parameter and outputs its SQL equivalent into a buffer.


Important:

The SQL returned by ttXlaGenerateSQL uses TimesTen SQL syntax. The SQL statement may fail on a non-TimesTen subscriber if there are SQL syntax incompatibilities between the two systems. In addition, the SQL statement is encoded in the connection character set associated with the XLA handle.

Example 5-21 Replicating updates to a non-TimesTen database

This example translates a record (record) and stores the resulting SQL output in a 200-character buffer (buffer). The actual size of the buffer is returned in the actualLength parameter.

ttXlaUpdateDesc_t record;
char buffer[200];
SQLINTEGER actualLength;

rc = ttXlaGenerateSQL(xla_handle, &record, buffer, 200, &actualLength);

if (rc != SQL_SUCCESS) {
    handleXLAerror (rc, xla_handle, err_buf, &native_error);
    if ( native_error == 8034 ) { // tt_ErrXlaNoSQL
      printf("Unable to translate to SQL\n");
    }
}

Other XLA features

The following sections describe how to use additional XLA features:

Changing the location of a bookmark

At any point during a connection, you can call the ttXlaGetLSN function to query the system for the Current Read log record identifier. If you must replay a set of updates, you can use the ttXlaSetLSN function to reset the Current Read log record identifier to any valid value larger than the Initial Read log record identifier set by the last ttXlaAcknowledge call. In this context, "larger" only applies if the log record identifiers being compared are from records in the same transaction. If that is not the case, then any log record identifier from a transaction that committed before another transaction is the "smaller" log record identifier, even if the numeric value of the log record identifier is larger. The only way to enable the Initial Read log record identifier to move forward to the Current Read log record identifier is by calling the ttXlaAcknowledge function, which indicates that you have received and processed all transaction log records up to the Current Read log record identifier. Once you have called ttXlaAcknowledge on a particular bookmark, you can no longer access transaction log records with a log record identifier smaller than the Current Read log record identifier.

Passing application context

Although it is not an XLA function, writers to the transaction log can call the ttApplicationContext built-in procedure to pass binary data associated with an application to XLA readers. This procedure specifies a single VARBINARY value that is returned in the next update record produced by the current transaction. XLA readers can obtain a pointer to this value as described in "Reading NOT INLINE variable-length column data".


Note:

A context value will be applied to only one update record. After it has been applied it is reset. If the same context value should be applied to multiple updates, then it must be reestablished before each update.

To set the context:

  1. Declare two program variables for invoking the ttApplicationContext procedure. The variable contextBuffer is a CHAR array that is declared to be large enough to accommodate the longest application context that you will use. The variable contextBufferLen is of type INTEGER and is used to convey the actual length of the context on each call to ttApplicationContext.

  2. Initialize a statement handle with a compiled invocation of the ttApplicationContext built-in procedure:

    rc = SQLPrepare(hstmt, "call ttApplicationContext(?)", SQL_NTS);
    rc = SQLBindParameter(hstmt, 1, SQL_PARAM_INPUT, SQL_C_BINARY,
                          SQL_VARBINARY, 0, 0, &contextBuffer,
                          sizeof contextBuffer, &contextBufferLen);
    
  3. When the application context must be set later, copy the context value into contextBuffer, assign the length of the context to contextBufferLen, and invoke ttApplicationContext with the call:

    rc = SQLExecute(hstmt);
    

    The transaction is then committed with the usual call on SQLTransact:

    rc = SQLTransact(NULL, hdbc, SQL_COMMIT);
    

    Note:

    If a SQL operation fails after a call to ttApplicationContext, the context may not be stored in the next SQL operation and therefore may be lost. If this happens, the application can call ttApplicationContext again before the next SQL operation.

PK(H>>PK:AOEBPS/title.htmz Oracle TimesTen In-Memory Database C Developer's Guide, 11g Release 2 (11.2.2)

Oracle® TimesTen In-Memory Database

C Developer's Guide

11g Release 2 (11.2.2)

E21637-04

September 2012


Oracle TimesTen In-Memory Database C Developer's Guide, 11g Release 2 (11.2.2)

E21637-04

Copyright © 1996, 2012, Oracle and/or its affiliates. All rights reserved.

This software and related documentation are provided under a license agreement containing restrictions on use and disclosure and are protected by intellectual property laws. Except as expressly permitted in your license agreement or allowed by law, you may not use, copy, reproduce, translate, broadcast, modify, license, transmit, distribute, exhibit, perform, publish, or display any part, in any form, or by any means. Reverse engineering, disassembly, or decompilation of this software, unless required by law for interoperability, is prohibited.

The information contained herein is subject to change without notice and is not warranted to be error-free. If you find any errors, please report them to us in writing.

If this is software or related documentation that is delivered to the U.S. Government or anyone licensing it on behalf of the U.S. Government, the following notice is applicable:

U.S. GOVERNMENT END USERS: Oracle programs, including any operating system, integrated software, any programs installed on the hardware, and/or documentation, delivered to U.S. Government end users are "commercial computer software" pursuant to the applicable Federal Acquisition Regulation and agency-specific supplemental regulations. As such, use, duplication, disclosure, modification, and adaptation of the programs, including any operating system, integrated software, any programs installed on the hardware, and/or documentation, shall be subject to license terms and license restrictions applicable to the programs. No other rights are granted to the U.S. Government.

This software or hardware is developed for general use in a variety of information management applications. It is not developed or intended for use in any inherently dangerous applications, including applications that may create a risk of personal injury. If you use this software or hardware in dangerous applications, then you shall be responsible to take all appropriate fail-safe, backup, redundancy, and other measures to ensure its safe use. Oracle Corporation and its affiliates disclaim any liability for any damages caused by use of this software or hardware in dangerous applications.

Oracle and Java are registered trademarks of Oracle and/or its affiliates. Other names may be trademarks of their respective owners.

Intel and Intel Xeon are trademarks or registered trademarks of Intel Corporation. All SPARC trademarks are used under license and are trademarks or registered trademarks of SPARC International, Inc. AMD, Opteron, the AMD logo, and the AMD Opteron logo are trademarks or registered trademarks of Advanced Micro Devices. UNIX is a registered trademark of The Open Group.

This software or hardware and documentation may provide access to or information on content, products, and services from third parties. Oracle Corporation and its affiliates are not responsible for and expressly disclaim all warranties of any kind with respect to third-party content, products, and services. Oracle Corporation and its affiliates will not be responsible for any loss, costs, or damages incurred due to your access to or use of third-party content, products, or services.

PK ÊPK:AOEBPS/c_ref.htm TimesTen Utility API

8 TimesTen Utility API

The TimesTen Utility Library C language functions documented in this chapter provide a programmable interface to some of the command line utilities documented in "Utilities" in Oracle TimesTen In-Memory Database Reference.

Applications that use this set of C language functions must include ttutillib.h and link with both the TimesTen driver library (libtten on UNIX or ttdv1122.lib and tten1122.lib on Windows) and the TimesTen utility library (libttutil on UNIX and ttutil1122.lib on Windows platforms).


Important:

Applications must call the ttUtilAllocEnv C function before calling any other TimesTen utility library function. In addition, applications must call the ttUtilFreeEnv C function when done using the TimesTen utility library interface.

These functions are not supported with TimesTen Client or for Java applications. They are supported only for TimesTen ODBC applications using the direct driver.

Return codes

Unless otherwise indicated, the utility functions return these codes as defined in ttutillib.h.

CodeDescription
TTUTIL_SUCCESSIndicates success.
TTUTIL_ERRORIndicates an error occurs.
TTUTIL_WARNINGUpon success, indicates a warning has been generated.
TTUTIL_INVALID_HANDLEIndicates an invalid utility library handle is specified.


Note:

The application must call the ttUtilGetError C function to retrieve all actual error or warning information.


ttBackup

Description

Creates either a full or an incremental backup copy of the database specified by connStr. You can back up a database either to a set of files or to a stream. You can restore the database at a later time using either the ttRestore function or the ttRestore utility.

For an overview of the TimesTen backup and restore facility, see "Migration, Backup, and Restoration" in Oracle TimesTen In-Memory Database Installation Guide.

Required privilege

ADMIN

Syntax

ttBackup (ttUtilHandle handle, const char* connStr,
          ttBackUpType type, ttBooleanType atomic,
          const char* backupDir, const char* baseName,
          ttUtFileHandle stream)

Parameters

ParameterTypeDescription
handlettUtilHandleSpecifies the TimesTen utility library environment handle allocated using ttUtilAllocEnv.
connStrconst char*This is a null-terminated string specifying a connection string that describes the database to be backed up.
typettBackupTypeSpecifies the type of backup to be performed. Valid values are as follows:
  • TT_BACKUP_FILE_FULL: Performs a full file backup to the backup path specified by the backupDir and baseName parameters. The resulting backup is not enabled for incremental backup.

  • TT_BACKUP_FILE_FULL_ENABLE: Performs a full file backup to the backup path specified by the backupDir and baseName parameters. The resulting backup is enabled for incremental backup.

  • TT_BACKUP_FILE_INCREMENTAL: Performs an incremental file backup to the backup path specified by the backupDir and baseName parameters, if that backup path contains an incremental-enabled backup of the database. Otherwise, an error is returned.

  • TT_BACKUP_FILE_INCR_OR_FULL: Performs an incremental file backup to the backup path specified by the backupDir and baseName parameters of that backup path contains an incremental-enabled backup of the database. Otherwise, it performs a full file backup of the database and marks it incremental enabled.

  • TT_BACKUP_STREAM_FULL: Performs a stream backup to the stream specified by the stream parameter.

  • TT_BACKUP__INCREMENTAL_STOP: Does not perform a backup. Disables incremental backups for the backup path specified by the backupDir and baseName parameters. This prevents transaction log files from accumulating for an incremental backup.

atomicttBooleanTypeSpecifies the disposition of an existing backup with the same baseName and backupDir while the new backup is being created.

This parameter has an effect only on full file backups when there is an existing backup with the same baseName and backupDir. It is ignored for incremental backups because they augment, rather than replace, an existing backup. It is ignored for stream backups because they write to the given stream, ignoring the baseName and backupDir parameters.

The following are valid values:

  • TT_FALSE: The existing backup is destroyed before the new backup begins. If the new backup fails to complete, neither the new, incomplete, backup nor the existing backup can be used to restore the database. This option should be used only when the database is being backed up for the first time, when there is a another backup of the database that uses a different baseName or backupDir, or when the application can tolerate a window of time (typically tens of minutes long for large databases) during which no backup of the database exists.

  • TT_TRUE: The existing backup is destroyed only after the new backup has completed successfully. If the new backup fails to complete, the old backup is retained and can be used to restore the database. If there is an existing backup with the same baseName and backupDir then the use of this option ensures that there is no window of time during which neither the existing backup nor the new backup is available for restoring the database, and it ensures that the existing backup will be destroyed only if it has been successfully superseded by the new backup. However, it does require enough disk space for both the existing and new backups to reside in the backupDir at the same time.

backupDirconst char*Specifies the backup directory for file backups. It is ignored for stream backups. Otherwise it must be non-null.

For TT_BACKUP_INCREMENTAL_STOP, it specifies the directory portion of the backup path that is to be disabled.

For TT_BACKUP_INCREMENTAL_STOP or a file backup, an error is returned if NULL is specified.

baseNameconst char*Specifies the file prefix for the backup files in the backup directory specified by the backupDir parameter for file backups.

It is ignored for stream backups.

If NULL is specified for this parameter, the file prefix for the backup files is the file name portion of the DataStore attribute in the ODBC definition of the database.

For TT_BACKUP_INCREMENTAL_STOP, this parameter specifies the basename portion of the backup path that is to be disabled.

streamttUtFileHandleFor stream backups, this parameter specifies the stream to which the backup is to be written.

On UNIX, it is an integer file descriptor that can be written to by using write(2). Pass 1 to write the backup to stdout.

On Windows, it is a handle that can be written to using WriteFile. Pass the result of GetStdHandle(STD_OUTPUT_HANDLE) to write the backup to the standard output.

This parameter is ignored for file backups.

The application can pass TTUTIL_INVALID_FILE_HANDLE for this parameter.


Example

This example backs up the database for the payroll DSN into C:\backup.

ttUtilHandle  utilHandle;
int           rc;
rc = ttBackup (utilHandle,  "DSN=payroll", TT_BACKUP_FILE_FULL,
     TT_TRUE, "c:\\backup", NULL, TTUTIL_INVALID_FILE_HANDLE);

Upon successful backup, all files are created in the C:\backup directory.

Note

Each database supports only eight incremental-enabled backups.

See also


ttRestore
"ttBackup" and "ttRestore" utilities in Oracle TimesTen In-Memory Database Reference

ttDestroyDataStore

Description

Destroys a database, including all checkpoint files, transaction logs and daemon catalog entries corresponding to the database specified by the connection string. It does not delete the DSN itself defined in the sys.odbc.ini or user odbc.ini file on the supported UNIX platforms or in Windows registry on the supported Windows platforms.

Required privilege

Instance administrator

Syntax

ttDestroyDataStore (ttUtilHandle handle, const char* connStr,
                    unsigned int timeout)

Parameters

ParameterTypeDescription
handlettUtilHandleSpecifies the TimesTen utility library environment handle allocated using ttUtilAllocEnv.
connStrconst char*This is a null-terminated string specifying the connection string that describes the database to be destroyed. All attributes in this connection string, except the DSN and the DataStore attribute, are ignored.
timeoutunsigned intSpecifies the number of times to retry before returning to the caller. ttDestroyDataStore continually retries the destroy operation every second until it is successful or the timeout is reached. This is useful in those situations where the destroy fails due to some temporary condition, such as when the database is in use.

No retry is performed if this parameter value is 0.


Example

This example destroys a database defined by the payroll DSN, consisting of files C:\dsns\payroll.ds0, C:\dsns\payroll.ds1, and several transaction log files C:\dsns\payroll.logn.

char            errBuff [256];
int             rc;
unsigned int    retCode;
ttUtilErrType   retType;
ttUtilHandle    utilHandle;
...
...
rc = ttDestroyDataStore (utilHandle, "DSN=payroll", 30);
if (rc == TTUTIL_SUCCESS)
   printf ("Datastore payroll successfully destroyed.\n");
else if (rc == TTUTIL_INVALID_HANDLE)
   printf ("TimesTen utility library handle is invalid.\n");
else
  while ((rc = ttUtilGetError (utilHandle, 0, &retCode,
           &retType, errBuff, sizeof (errBuff), NULL)) !=
           TTUTIL_NODATA)
    {
  ...
  ...
}

ttDestroyDataStoreForce

Description

Destroys a database, including all checkpoint files, transaction logs and daemon catalog entries corresponding to the database specified by the connection string. It does not delete the DSN itself defined in the sys.odbc.ini or user odbc.ini file on the supported UNIX platforms or in the Windows registry on supported Windows platforms.

Required privilege

Instance administrator

Syntax

ttDestroyDataStoreForce (ttUtilHandle handle, const char* connstr,
                         unsigned int timeout)

Parameters

ParameterTypeDescription
handlettUtilHandleSpecifies the TimesTen utility library environment handle allocated using ttUtilAllocEnv.
connStrconst char*This is a null-terminated string specifying the connection string that describes the database to be destroyed. All attributes in this connection string, except the DSN and the DataStore attribute, are ignored.
timeoutunsigned intSpecifies the number of seconds to retry before returning to the caller. The ttDestroyDataStoreForce utility continually retries the destroy operation every second until it is successful or the timeout is reached. This is useful when the destroy fails due to some temporary condition, such as when the database is in use.

No retry is performed if this parameter value is 0.


Example

This example destroys a database defined by the payroll DSN, consisting of files C:\dsns\payroll.ds0, C:\dsns\payroll.ds1, and several transaction log files C:\dsns\payroll.logn.

char              errBuff [256];
int               rc;
unsigned int      retCode;
ttUtilErrType     retType;
ttUtilHandle      utilHandle;
...
...
rc = ttDestroyDataStoreForce (utilHandle, "DSN=payroll", 30);
if (rc == TTUTIL_SUCCESS)
  printf ("Datastore payroll successfully destroyed.\n");
else if (rc == TTUTIL_INVALID_HANDLE)
  printf ("TimesTen utility library handle is invalid.\n");
else
  while ((rc = ttUtilGetError (utilHandle, 0, &retCode,
                               &retType, errBuff, sizeof (errBuff), NULL)) !=
                               TTUTIL_NODATA)
    {
  ...
  ...
}

ttRamGrace

Description

Specifies the number of seconds the database specified by the connection string is kept in RAM by TimesTen after the last application disconnects from the database. TimesTen then unloads the database. This grace period can be set or reset at any time but is only in effect if the RAM policy is TT_RAMPOL_INUSE.

Required privilege

Instance administrator

Syntax

ttRamGrace (ttUtilHandle handle, const char* connStr, unsigned int seconds)

Parameters

ParameterTypeDescription
handlettUtilHandleSpecifies the TimesTen utility library environment handle allocated using ttUtilAllocEnv.
connStrconst char*This is a null-terminated string specifying a connection string that describes the database for which the RAM grace period is set.
secondsunsigned intSpecifies the number of seconds TimesTen keeps the database in RAM after the last application disconnects from the database. TimesTen then unloads the database.

Example

This example sets the RAM grace period of 10 seconds for the payroll DSN.

ttUtilHandle   utilHandle;
int            rc;
rc = ttRamGrace (utilHandle, "DSN=payroll", 10);

See also


ttRamLoad
ttRamPolicy
ttRamUnload

ttRamLoad

Description

Causes TimesTen to load the database specified by the connection string into the system RAM. For a permanent database, a call to ttRamLoad is valid only when RamPolicy is set to TT_RAMPOL_MANUAL. For a temporary database, a call to ttRamLoad loads the database into RAM.

Refer to "ttRamPolicySet" in Oracle TimesTen In-Memory Database Reference or to ttRamPolicy for related information.

Required privilege

Instance administrator

Syntax

ttRamLoad (ttUtilHandle handle, const char* connStr)

Parameters

ParameterTypeDescription
handlettUtilHandleSpecifies the TimesTen utility library environment handle allocated using ttUtilAllocEnv.
connStrconst char*This is a null-terminated string specifying a connection string that describes the database to be loaded into RAM.

Example

This example loads the database for the payroll DSN.

ttUtilHandle   utilHandle;
int            rc;
rc = ttRamLoad (utilHandle, "DSN=payroll");

See also


ttRamGrace
ttRamPolicy
ttRamUnload

ttRamPolicy

Description

Defines the policy used to determine when TimesTen loads the database specified by the connection string into the system RAM.

Required privilege

Instance administrator

Syntax

ttRamPolicy (ttUtilHandle handle, const char* connStr,
             ttRamPolicyType policy)

Parameters

ParameterTypeDescription
handlettUtilHandleSpecifies the TimesTen utility library environment handle allocated using ttUtilAllocEnv.
connStrconst char*This is a null-terminated string specifying a connection string that describes the database for which the RAM policy is to be set.
policyttRamPolicyTypeSpecifies the policy used to determine when TimesTen loads the specified database into system RAM. Valid values are the following:
  • TT_RAMPOL_ALWAYS: Specifies that the database should always remain in RAM.

  • TT_RAMPOL_MANUAL: Specifies that the database can be loaded into RAM explicitly using either the ttRamLoad C function or the ttAdmin -ramLoad command. Similarly, the database can be unloaded from RAM explicitly by using ttRamUnload C function or using ttAdmin -ramUnload command.

  • TT_RAMPOL_INUSE: Specifies that the database is to be loaded into RAM when an application wants to connect to the database. This RAM policy may be further modified using the ttRamGrace C function or using the ttAdmin -ramGrace command.

If you do not explicitly set the RAM policy for the specified database, the default RAM policy is TT_RAMPOL_INUSE.


Example

This example sets the RAM policy to manual for the payroll DSN.

ttUtilHandle   utilHandle;
int            rc;
rc = ttRamPolicy (utilHandle, "DSN=payroll", TT_RAMPOL_MANUAL);

Note

The policy cannot be set for a temporary database.

See also


ttRamGrace
ttRamLoad
ttRamUnload

ttRamUnload

Description

Causes TimesTen to unload the database specified by the connection string from the system RAM if the TimesTen RAM policy is set to manual. For a permanent database, this call is valid only when RAM policy is set to TT_RAMPOL_MANUAL. For a temporary database, a call to ttRamUnload always tries to unload the database from RAM because RAM policy cannot be set for such a database.

Refer to "ttRamPolicySet" in Oracle TimesTen In-Memory Database Reference or to ttRamPolicy for related information.

Required privilege

Instance administrator

Syntax

ttRamUnload (ttUtilHandle handle, const char* connStr)

Parameters

ParameterTypeDescription
handlettUtilHandleSpecifies the TimesTen utility library environment handle allocated using ttUtilAllocEnv.
connStrconst char*This is a null-terminated string specifying a connection string for the database to be unloaded from RAM.

Example

This example unloads the database from RAM for the payroll DSN.

ttUtilHandle   utilHandle;
int            rc;
rc = ttRamUnload (utilHandle, "DSN=payroll");

Notes

When using this function with a temporary database, TimesTen always attempts to unload the database.

See also


ttRamGrace
ttRamLoad
ttRamPolicy

ttRepDuplicateEx

Description

Creates a replica of a remote database on the local system. The process is initiated from the receiving local system. From there, a connection is made to the remote source database to perform the duplicate operation.


Notes:

  • This utility has features to recover from a site failure by creating a disaster recovery (DR) read-only subscriber as part of the active standby pair replication scheme. See "Using a disaster recovery subscriber in an active standby pair" in Oracle TimesTen In-Memory Database Replication Guide for additional information.

  • If the database does not use cache groups, the following items discussed below are not relevant: cacheuid and cachepwd data structure elements; TT_REPDUP_NOKEEPCG, TT_REPDUP_RECOVERINGNODE, TT_REPDUP_INITCACHEDR, and TT_REPDUP_DEFERCACHEUPDATE flag values.

  • There are elements in the ttRepDuplicateExArg structure that is a parameter of this utility, localIP and remoteIP, that allow you to optionally specify which local network interface to use, which remote network interface to use, or both.


Required privilege

Requires an instance administrator on the receiving local database (where ttRepDuplicateEx is called) and a user with ADMIN privilege on the remote source database. Create the internal user on the remote source store as necessary.

In addition, be aware of the following requirements to execute ttRepDuplicateEx:

Syntax

ttRepDuplicateEx (ttUtilHandle handle,
                  const char* destConnStr,
                  const char* srcDatabase,
                  const char* remoteHost,
                  ttRepDuplicateExArg* arg
                  )
typedef struct
{
      unsigned int size; /*set to size of(ttRepDuplicateExArg) */
      unsigned int flags;
      const char* uid;
      const char* pwd;
      const char* pwdcrypt;
      const char* cacheuid;
      const char* cachepwd;
      const char* localHost;
      int truncListLen;
      const char** truncList;
      int dropListLen;
      const char** dropList;
      int maxkbytesPerSec;
      int remoteDaemonPort;
      int nThreads4initDR;
      const char* localIP
      const char* remoteIP
      int crsManaged;
      /*new struct elements can only be added here at the end */
} ttRepDuplicateExArg

Parameters

ParameterTypeDescription
handlettUtilHandleSpecifies the TimesTen utility library environment handle allocated using ttUtilAllocEnv.
destConnStrconst char*This is a null-terminated string specifying the connection string for a local database into which the replica of the remote database is created.
srcDatabaseconst char*This is a null-terminated string specifying the remote source database name. This name is the last component of the database path name.
remoteHostconst char*This is a null-terminated string specifying the TCP/IP host name of the system where the remote source database is located.
argttRepDuplicateExArg*This is the address of the structure containing the desired ttRepDuplicateEx arguments. If NULL is passed in for arg or if the value of arg ->size is invalid, TimesTen returns error 12230, "Invalid argument value", and TTUTIL_ERROR.

Struct elements

The ttRepDuplicateExArg structure contains these elements:

ElementTypeDescription
sizeunsigned intSize

This must be set up to sizeof (ttRepDuplicateExArg).

flagsunsigned intBit-wise union of values chosen from the list in the table of flag values
uidconst char*User name of a user on the remote source database with ADMIN privileges

This user name is used to connect to the remote source database to perform the duplicate operation.

pwdconst char*Password associated with the user ID
pwdcryptconst char*Encrypted password associated with the user ID
cacheuidconst char*Cache administration user ID
cachepwdconst char*Cache administration user password
localHostconst char*Null-terminated string specifying the TCP/IP host name of the local system

This element is ignored if remoteRepStart is TT_FALSE. This explicitly identifies the local host. This parameter can be null, which is useful if the local host uses a nonstandard name such as an IP address.

truncListLenintNumber of elements in the truncList
truncListconst char**List of non-replicated tables to truncate after duplicate
dropListLenintNumber of elements in dropList
dropListconst char**List of non-replicated tables to drop after the duplicate operation
maxkbytesPerSecintMaximum kilobytes per second

Setting this to a nonzero value specifies that the duplicate operation should not put more than maxkbytesPerSec kilobytes of data per second onto the network. Setting it to 0 or a negative number indicates that the duplicate operation should not attempt to limit its bandwidth.

remoteDaemonPortintRemote daemon port

Setting this to 0 results in the daemon port number for the target database being set to the port number used for the daemon on the source database.

This option cannot be used in duplicate operations for databases with automatic port configuration.

nThreads4initDRintNumber of threads for initialization

For the disaster recovery subscriber, this determines the number of threads used to initialize the Oracle database on the disaster recovery site.

After the TimesTen database is copied to the disaster recovery system, the Oracle database tables are truncated and the data from the TimesTen cache groups is copied to the Oracle database on the disaster recovery system.

Also see the TT_REPDUP_INITCACHEDR flag below.

localIPconst char*A null-terminated string specifying the alias or IP address (IPv4 or IPv6) of the local network interface to use for the duplicate operation. Set this to NULL if you do not want to specify the local network interface, in which case any compatible interface may be used.
remoteIPconst char*A null-terminated string specifying the alias or IP address (IPv4 or IPv6) of the remote network interface to use for the duplicate operation. Set this to NULL if you do not want to specify the remote network interface, in which case any compatible interface may be used.

Note: You can specify both localIP and remoteIP, or either one by itself, or neither.

crsManagedintFor internal use

This should be set to 0 (default).


The ttRepDuplicateExArg flags element is constructed from these values:

ValueDescription
TT_REPDUP_NOFLAGSIndicates no flags.
TT_REPDUP_COMPRESSEnables compression of the data transmitted over the network for the duplicate operation.
TT_REPDUP_REPSTARTDirects ttRepDuplicateEx to set the replication state (with respect to the local database) in the remote database to the start state before the remote database is copied across the network. This ensures that all updates made after the duplicate operation are replicated from the remote database to the newly created or restored local database.
TT_REPDUP_RAMLOADKeeps the database in memory upon completion of the duplicate operation. It changes the RAM policy for the database to manual.
TT_REPDUP_DELXLADirects ttRepDuplicateEx to remove all the XLA bookmarks as part of the duplicate operation.
TT_REPDUP_NOKEEPCGDo not preserve the cache group definitions; ttRepDuplicateEx converts all cache group tables into regular tables.

By default, cache group definitions are preserved.

TT_REPDUP_RECOVERINGNODESpecifies that ttRepDuplicateEx is being used to recover a failed node for a replication scheme that has an AWT or autorefresh cache group. Do not specify TT_REPDUP_RECOVERINGNODE when rolling out a new or modified replication scheme to a node. If ttRepDuplicateEx cannot update metadata stored on the Oracle database and all incremental autorefresh cache groups are replicated, then updates to the metadata will be automatically deferred until the cache and replication agents are started.
TT_REPDUP_DEFERCACHEUPDATEForces the deferral of changes to metadata stored on the Oracle database until the cache and replication agents are started and the agents can connect to the Oracle database. Using this option can cause a full autorefresh if some incremental cache groups are not replicated or if ttRepDuplicateEx is being used for rolling out a new or modified replication scheme to a node.
TT_REPDUP_INITCACHEDRInitializes disaster recovery. You must also specify cacheuid and cachepwd in the data structure. Also see nThreads4initDR in the data structure.

Example

This example creates a replica of a remote TimesTen DSN, remote_payroll with the database path name C:\dsns\payroll, to a local DSN local_payroll.

ttUtilHandle utilHandle;
int rc;
ttRepDuplicateExArg arg;

memset(&arg, 0, sizeof(arg));
arg.size = sizeof(ttRepDuplicateExArg);
arg.flags = TT_REPDUP_REPSTART | TT_REPDUP_DELXLA;
arg.localHost = "mylocalhost";
arg.uid="myuid";
arg.pwd="mypwd";
rc=ttRepDuplicateEx(utilHandle,"DSN=local_payroll","payroll","remotehost", &arg);

See also

The following built-in procedures are described in "Built-In Procedures" in Oracle TimesTen In-Memory Database Reference.


ttReplicationStatus
ttRepPolicySet
ttRepStop
ttRepSubscriberStateSet
ttRepSyncGet
ttRepSyncSet

ttRestore

Description

Restores a database specified by the connection string from a backup that has been created using the ttBackup C function or ttBackup utility. If the database already exists, ttRestore will not overwrite it.

For an overview of the TimesTen backup and restore facility, see "Migration, Backup, and Restoration" in Oracle TimesTen In-Memory Database Installation Guide.

Required privilege

Instance administrator

Syntax

ttRestore (ttUtilHandle handle, const char* connStr, 
           ttRestoreType type, const char* backupDir, 
           const char* baseName, ttUtFileHandle stream,
           unsigned intflags)

Parameters

ParameterTypeDescription
handlettUtilHandleSpecifies the TimesTen utility library environment handle allocated using ttUtilAllocEnv.
connStrconst char*This is a null-terminated string specifying a connection string that describes the database to be restored.
typettRestoreTypeIndicates whether the database is to be restored from a file or a stream backup. Valid values are the following:
  • TT_RESTORE_FILE: The database is to be restored from a file backup located at the backup path specified by the backupDir and baseName parameters.

  • TT_RESTORE_STREAM: The database is to be restored from a stream backup read from the given stream.

backupDirconst char*For TT_RESTORE_FILE, specifies the directory where the backup files are stored.

For TT_RESTORE_STREAM, this parameter is ignored.

baseNameconst char*For TT_RESTORE_FILE, specifies the file prefix for the backup files in the backup directory specified by the backupDir parameter.

If NULL is specified, the file prefix for the backup files is the file name portion of the DataStore attribute of the database ODBC definition.

For TT_RESTORE_STREAM, this parameter is ignored.

streamttUtFileHandleFor TT_RESTORE_STREAM, specifies the stream from which the backup is to be read.

On UNIX, it is an integer file descriptor that can be read from using read(2). Pass 0 to read the backup from stdin.

On Windows, it is a handle that can be read from using ReadFile. Pass the result of GetStdHandle(STD_INPUT_HANDLE) to read from the standard input.

For TT_RESTORE_FILE, this parameter is ignored. The application can pass TTUTIL_INVALID_FILE_HANDLE for this parameter.

flagsunsigned intThis is reserved for future use. Set it to 0.

Example

This example restores the database for the payroll DSN from C:\backup.

ttUtilHandle   utilHandle;
int            rc;

rc = ttRestore (utilHandle, "DSN=payroll", TT_RESTORE_FILE,
              "c:\\backup", NULL, TTUTIL_INVALID_FILE_HANDLE, 0);

See also


ttBackup
"ttBackup" and "ttRestore" utilities in Oracle TimesTen In-Memory Database Reference

ttUtilAllocEnv

Description

Allocates memory for a TimesTen utility library environment handle and initializes the TimesTen utility library interface for use by an application. An application must call ttUtilAllocEnv before calling any other TimesTen utility library function. In addition, an application should call ttUtilFreeEnv when it is done using the TimesTen utility library interface.

Required privilege

None

Syntax

ttUtilAllocEnv (ttUtilHandle* handle_ptr, char* errBuff,
                unsigned int buffLen, unsigned int* errLen)

Parameters

ParameterTypeDescription
handle_ptrttUtilHandle*Specifies a pointer to storage where the TimesTen utility library environment handle is returned.
errBuffchar*This is a user allocated buffer where error messages (if any) are returned. The returned error message is a null-terminated string. If the length of the error message exceeds buffLen-1, it is truncated to buffLen-1. If this parameter is null, buffLen is ignored and TimesTen does not return error messages to the calling application.
buffLenunsigned intSpecifies the size of the buffer errBuff. If this parameter is 0, TimesTen does not return error messages to the calling application.
errLenunsigned int*This is a pointer to an unsigned integer where the actual length of the error message is returned. If it is NULL, this parameter is ignored.

Return codes

This utility returns the following code as defined in ttutillib.h.

CodeDescription
TTUTIL_SUCCESSReturned upon success.

Otherwise, it returns a TimesTen-specific error message as defined in tt_errCode.h and a corresponding error message in the buffer provided by the caller.

Example

This example allocates and initializes a TimesTen utility library environment handle with the name utilHandle.

char           errBuff [256];
int            rc;
ttUtilHandle   utilHandle;

rc = ttUtilAllocEnv (&utilHandle, errBuff, sizeof(errBuff), NULL);

See also


ttUtilFreeEnv
ttUtilGetError
ttUtilGetErrorCount

ttUtilFreeEnv

Description

Frees memory associated with the TimesTen utility library handle.

An application must call ttUtilAllocEnv before calling any other TimesTen utility library function. In addition, an application should call ttUtilFreeEnv when it is done using the TimesTen utility library interface.

Required privilege

None

Syntax

ttUtilFreeEnv (ttUtilHandle handle, char* errBuff,
               unsigned int buffLen, unsigned int* errLen)

Parameters

ParameterTypeDescription
handlettUtilHandleSpecifies the TimesTen utility library environment handle allocated using ttUtilAllocEnv.
errBuffchar*This is a user-allocated buffer where error messages are to be returned. The returned error message is a null-terminated string. If the length of the error message exceeds buffLen-1, it is truncated to buffLen-1. If this parameter is NULL, buffLen is ignored and TimesTen does not return error messages to the calling application.
buffLenunsigned intSpecifies the size of the buffer errBuff. If this parameter is 0, TimesTen does not return error messages to the calling application.
errLenunsigned int*This is a pointer to an unsigned integer where the actual length of the error message is returned. If it is NULL, this parameter is ignored.

Return codes

This utility returns the following codes as defined in ttutillib.h.

CodeDescription
TTUTIL_SUCCESSReturned upon success.
TTUTIL_INVALID_HANDLEReturned if an invalid utility library handle is specified.

Otherwise, it returns a TimesTen-specific error message as defined in tt_errCode.h and a corresponding error message in the buffer provided by the caller.

Example

This example frees a TimesTen utility library environment handle named utilHandle.

char           errBuff [256];
int            rc;
ttUtilHandle   utilHandle;

rc = ttUtilFreeEnv (utilHandle, errBuff, sizeof(errBuff), NULL);

See also


ttUtilAllocEnv
ttUtilGetError
ttUtilGetErrorCount

ttUtilGetError

Description

Retrieves the errors and warnings generated by the last call to the TimesTen C utility library functions excluding ttUtilAllocEnv and ttUtilFreeEnv.

Required privilege

None

Syntax

ttUtilGetError (ttUtilHandle handle, unsigned int errIndex,
                unsigned int* retCode, ttUtilErrType* retType,
                char* errbuff, unsigned int buffLen,
                unsigned int* errLen)

Parameters

ParameterTypeDescription
handlettUtilHandleSpecifies the TimesTen utility library environment handle allocated using ttUtilAllocEnv.
errIndexunsigned intIndicates error or warning record to be retrieved from the TimesTen utility library error array. Valid values are as follows:
  • 0: Retrieve the next record from the utility library error array.

  • 1...n: Retrieve the specified record from the utility library error array, where n is the error count returned by the ttUtilGetErrorCount call.

retCodeunsigned int*Returns the TimesTen-specific error or warning codes as defined in tt_errCode.h.
retTypettUtilErrType*Indicates whether the returned message is an error or warning. The following are valid return values:
  • TTUTIL_ERROR

  • TTUTIL_WARNING

errBuffchar*This is a user allocated buffer where error messages (if any) are to be returned. The returned error message is a null-terminated string. If the length of the error message exceeds buffLen-1, it is truncated to buffLen-1. If this parameter is NULL, buffLen is ignored and TimesTen does not return error messages to the calling application.
buffLenunsigned intSpecifies the size of the buffer errBuff. If this parameter is 0, TimesTen does not return error messages to the calling application.
errLenunsigned int*A pointer to an unsigned integer where the actual length of the error message is returned. If it is NULL, TimesTen ignores this parameter.

Return codes

This utility returns the following codes as defined in ttutillib.h.

CodeDescription
TTUTIL_SUCCESSReturned upon success.
TTUTIL_INVALID_HANDLEReturned if an invalid utility library handle is specified.
TTUTIL_NODATAReturned if no error or warming information is retrieved.

Example

This example retrieves all error or warning information after calling ttDestroyDataStore for the DSN named payroll.

char            errBuff[256];
int             rc;
unsigned int    retCode;
ttUtilErrType   retType;
ttUtilHandle    utilHandle;

rc = ttDestroyDataStore (utilHandle, "DSN=PAYROLL", 30);
if ((rc == TTUTIL_SUCCESS) 
  printf ("Datastore payroll successfully destroyed.\n");
else if (rc == TTUTIL_INVALID_HANDLE)
  printf ("TimesTen utility library handle is invalid.\n");
else
    while ((rc = ttUtilGetError (utilHandle, 0,
        &retCode, &retType, errBuff, sizeof (errBuff),
        NULL)) != TTUTIL_NODATA)
    {
...
...
}

Notes

Each of the TimesTen C functions can potentially generate multiple errors and warnings for a single call from an application. To retrieve all of these errors and warnings, the application must make repeated calls to ttUtilGetError until it returns TTUTIL_NODATA.

See also


ttUtilAllocEnv
ttUtilFreeEnv
ttUtilGetErrorCount

ttUtilGetErrorCount

Description

Retrieves the number of errors and warnings generated by the last call to the TimesTen C utility library functions, excluding ttUtilAllocEnv and ttUtilFreeEnv. Each of these functions can potentially generate multiple errors and warnings for a single call from an application. To retrieve all of these errors and warnings, the application must make repeated calls to ttUtilGetError until it returns TTUTIL_NODATA.

Required privilege

None

Syntax

ttUtilGetErrorCount (ttUtilHandle handle,
                     unsigned int* errCount)

Parameters

ParameterTypeDescription
handlettUtilHandleSpecifies the TimesTen utility library environment handle allocated using ttUtilAllocEnv.
errCountunsigned int*Indicates the number of errors and warnings generated by the last call, excluding ttUtilAllocEnv and ttUtilFreeEnv, to the TimesTen utility library.

Return codes

The utility returns the following codes as defined in ttutillib.h.

CodeDescription
TTUTIL_SUCCESSReturned upon success.
TTUTIL_INVALID_HANDLEReturned if an invalid utility library handle is specified.

Example

This example retrieves the error and warning count information after calling ttDestroyDataStore for the DSN named payroll.

int            rc;
unsigned int   errCount;
ttUtilHandle   utilHandle;

rc = ttDestroyDataStore (utilHandle, "DSN=payroll", 30);
if (rc == TTUTIL_SUCCESS) 
  printf ("Datastore payroll successfully destroyed.\n")

else if (rc == TTUTIL_INVALID_HANDLE) 
  printf ("TimesTen utility library handle is invalid.\n");
else
{
rc = ttUtilGetErrorCount(utilHandle, &errCount);
  ...
  ...
}

Notes

Each of the TimesTen utility library functions can potentially generate multiple errors and warnings for a single call from an application. To retrieve all of these errors and warnings, the application must make repeated calls to ttUtilGetError until it returns TTUTIL_NODATA.

See also


ttUtilAllocEnv
ttUtilFreeEnv
ttUtilGetError

ttXactIdRollback

Description

Rolls back the transaction indicated by the transaction ID that is specified. The intended user of ttXactIdRollback is the ttXactAdmin utility. However, programs that want to have a thread with the power to roll back the work of other threads must ensure that those threads call the ttXactIdGet built-in procedure before beginning work and put the results into a location known to the thread that wishes to roll back the transaction. (Refer to "ttXactIdGet" in Oracle TimesTen In-Memory Database Reference.)

Required privilege

ADMIN

Syntax

ttXactIdRollback (ttUtilHandle handle, const char* connStr,
                  const char* xactId)

Parameters

ParameterTypeDescription
handlettUtilHandleSpecifies the TimesTen utility library environment handle allocated using ttUtilAllocEnv.
connStrconst char**Specifies the connection string of the database, which contains the transaction to be rolled back.
xactIdconst char*Indicates the transaction ID for the transaction to be rolled back.

Example

This example rolls back a transaction with the ID 3.4567 in the database named payroll.

char            errBuff [256];
int             rc;
unsigned int    retCode;
ttUtilErrType   retType;
ttUtilHandle    utilHandle;
...
rc = ttXactIdRollback (utilHandle, "DSN=payroll", "3.4567");
if (rc == TTUTIL_SUCCESS)
  printf ("Transaction ID successfully rolled back.\n");
else if (rc == TTUTIL_INVALID_HANDLE)
  printf ("TimesTen utility library handle is invalid.\n");
else
  while ((rc = ttUtilGetError (utilHandle, 0, &retCode,
  &retType, errBuff, sizeof (errBuff), NULL)) != TTUTIL_NODATA)
   {
  ...
}
PKw;D=)PK:AOEBPS/preface.htm 1 Preface

Preface

Oracle TimesTen In-Memory Database is a memory-optimized relational database. Deployed in the application tier, TimesTen operates on databases that fit entirely in physical memory using standard SQL interfaces. High availability for the in-memory database is provided through real-time transactional replication.

TimesTen supports a variety of programming interfaces, including PL/SQL (Oracle procedural language extension for SQL), ODBC (Open Database Connectivity), JDBC (Java Database Connectivity), OCI (Oracle Call Interface), Pro*C/C++ (Oracle precompiler for embedded SQL and PL/SQL instructions in C or C++ code), TTClasses (TimesTen C++ Interface Classes), and ODP.NET (Oracle Data Provider for .NET).

This document covers TimesTen support for ODBC, OCI, and Pro*C/C++.

The following topics are discussed in the preface:

Audience

This guide is for anyone developing or supporting applications that use TimesTen through ODBC, OCI, or Pro*C/C++.

In addition to familiarity with the particular programming interface you use, you should be familiar with TimesTen, SQL (Structured Query Language), and database operations.

Related documents

TimesTen documentation is available on the product distribution media and on the Oracle Technology Network:

http://www.oracle.com/technetwork/products/timesten/documentation/

Oracle documentation is also available on the Oracle Technology network. This may be especially useful for Oracle features that TimesTen supports but does not attempt to fully document, such as OCI and Pro*C/C++:

http://www.oracle.com/technetwork/database/enterprise-edition/documentation/

In particular, the following Oracle documents may be of interest.

This manual frequently refers to ODBC API reference documentation for further information. This is available from Microsoft or a variety of third parties. For example:

http://msdn.microsoft.com/en-us/library/ms714562(VS.85).aspx

Note that TimesTen supports ODBC 2.5, Extension Level 1, with additional features for Extension Level 2 where those features are included in Chapter 10, "TimesTen ODBC Functions and Options".

Conventions

TimesTen supports multiple platforms. Unless otherwise indicated, the information in this guide applies to all supported platforms. The term Windows applies to all supported Windows platforms. The term UNIX applies to all supported UNIX and Linux platforms. Refer to the "Platforms" section in Oracle TimesTen In-Memory Database Release Notes for specific platform versions supported by TimesTen.


Note:

In TimesTen documentation, the terms "data store" and "database" are equivalent. Both terms refer to the TimesTen database unless otherwise noted.

This document uses the following text conventions:

ConventionMeaning
italicItalic type indicates terms defined in text, book titles, or emphasis.
monospaceMonospace type indicates code, commands, URLs, function names, attribute names, directory names, file names, text that appears on the screen, or text that you enter.
italic monospaceItalic monospace type indicates a placeholder or a variable in a code example for which you specify or use a particular value. For example:

Driver=install_dir/lib/libtten.sl

Replace install_dir with the path of your TimesTen installation directory.

[ ]Square brackets indicate that an item in a command line is optional.
{ }Curly braces indicated that you must choose one of the items separated by a vertical bar ( | ) in a command line.
|
A vertical bar (or pipe) separates alternative arguments.
. . .An ellipsis (. . .) after an argument indicates that you may use more than one argument on a single command line. An ellipsis in a code example indicates that what is shown is only a partial example.
%
The percent sign indicates the UNIX shell prompt.

In addition, TimesTen documentation uses the following special conventions.

ConventionMeaning
install_dirThe path that represents the directory where TimesTen is installed.
TTinstanceThe instance name for your specific installation of TimesTen. Each installation of TimesTen must be identified at installation time with a unique instance name. This name appears in the installation path.
bits or bbTwo digits, either 32 or 64, that represent either a 32-bit or 64-bit operating system.
release or rrThe first three parts in a release number, with or without dots. The first three parts of a release number represent a major TimesTen release. For example, 1122 or 11.2.2 represents TimesTen 11g Release 2 (11.2.2).
DSNTimesTen data source name (for the TimesTen database).

Documentation Accessibility

For information about Oracle's commitment to accessibility, visit the Oracle Accessibility Program website at http://www.oracle.com/pls/topic/lookup?ctx=acc&id=docacc.

Access to Oracle Support

Oracle customers have access to electronic support through My Oracle Support. For information, visit http://www.oracle.com/pls/topic/lookup?ctx=acc&id=info or visit http://www.oracle.com/pls/topic/lookup?ctx=acc&id=trs if you are hearing impaired.

PK&K1 1PK:AOEBPS/index.htm Index

Index

A  B  C  D  E  F  G  I  K  L  M  N  O  P  Q  R  S  T  U  V  W  X 

A

access control
connection attributes, 2.1.3
for connections, 2.1.4
impact on XLA, 5.1.6
overview of impact, 2.4
acknowledge records have been read, XLA, 9.2.3
AIX, linking considerations, 1.3.2
allocating memory, utility library environment handle, 8
application context, passing, XLA, 5.4.2
applying database updates, XLA, 9.2.3
array binds--see associative array binds
associative array binds
in OCI, 3.4.2.2
in Pro*C, 4.4.1
AUTOCOMMIT with XA, 6.2.5.1
automatic client failover, 2.6

B

backing up a database, 8
batch SQL operations, 7.2
bind variable--see binding parameters
binding parameters
associative array binds in OCI, 3.4.2.2
associative array binds in Pro*C, 4.4.1
duplicate parameters in OCI, 3.4.2.1
duplicate parameters in PL/SQL, 2.2.6.7
duplicate parameters in SQL, 2.2.6.6
floating point data, 2.2.6.8
input parameters, 2.2.6.3
input/output parameters, 2.2.6.5
output parameters, 2.2.6.4
parameter type assignments and conversions, 2.2.6.2
performance impact, 7.3
precision, 2.2.6.1
scale, 2.2.6.1
SQL_WCHAR and SQL_WVARCHAR with driver manager, 2.2.6.9
SQLBindParameter, 2.2.6.1
bookmarks--see XLA bookmarks
buildtms command, XA, 6.4.2
built-in procedures
calling TimesTen built-ins, 2.3.1
ttApplicationContext, 5.4.2, 9.2.3
ttXactIdGet, 8
bulk fetch, 2.2.5, 7.6
bulk insert, update, delete (batching), 7.2

C

C language functions--see Utility Library.
cache
autorefresh cache groups and XLA, 5.1.7
cache groups, cache instances affected, OCI, 3.4.3.2
cache groups, cache instances affected, ODBC, 2.3.3.3
get passthrough status, 2.3.3.2
Oracle password, specifying, OCI, 3.4.3.1
Oracle password, specifying, Pro*C/C++, 4.3.3.3
set passthrough level, 2.3.3.1
CALL
PL/SQL procedures and functions, 2.3.1
TimesTen built-in procedures, 2.3.1
character set
SQLGetInfo info type, 10.3
SQLGetInfo info type for size, 10.3
character set conversion, 2.3.4
client failover
automatic client failover, 2.6
configuration, 2.6.2
failover callback functions, 2.6.3
closing a transaction log API handle, XLA, 9.2.3
column data, inspecting, XLA, 5.2.6
committing a transaction
ODBC, 2.2.11
XLA, 9.2.3
compiling applications
OCI applications, 3.3.2
Pro*C/C++ applications, 4.3.2
UNIX, 1.3.2
Windows, 1.3.1
concurrency control, 10.2.1
connection attributes
first connection attributes, 2.1.3
general connection attributes, 2.1.3
connections
access control, 2.1.4
attributes, setting programmatically, 2.1.3
connecting to database, 2.1.2
disconnecting from database, 2.1.2
external user (OCI), 3.3.3.4
external user (Pro*C/C++), 4.3.3.4
managing, 2.1
OCI, connecting to database, 3.3.3
Pro*C/C++, connecting to database, 4.3.3
SQLConnect, SQLDriverConnect, SQLAllocConnect, SQLDisconnect, 2.1.1
SQLSetConnectOption and SQLGetConnectOption supported options, 10.2.1
cursors
REF CURSORs, 2.2.7
usage, 2.2.3

D

data structures, XLA
summary, 9.2.3
tt_LSN_t, 9.2.3
tt_XlaLsn_t, 9.2.3
ttXlaColDesc_t, 9.2.3
ttXlaNodeHdr_t, 9.2.3
ttXlaTblDesc_t, 9.2.3
ttXlaTblVerDesc_t, 9.2.3
ttXlaUpdateDesc_t, 9.2.3
ttXlaVersion_t, 9.2.3
data types
conversions and performance, 7.5
ODBC 2.0 versus ODBC 3.0 types, 2.3.6
type mapping/conversion for parameter binding, 2.2.6.2
XLA, 5.1.5
database
applying updates, XLA, 9.2.3
backing up, 8
connection handle, obtaining, XLA, 5.2.1
destroying, 8, 8
RAM usage, 8, 8, 8, 8
replicating, 8
restoring, 8
deadlock error, 5.3.3
deferred prepare
OCI, 3.4.1
ODBC, 2.2.4
demo applications, Quick Start, 1.4
destroying a database, 8, 8
diagnostic framework considerations (OCI), 3.3.5
disaster recovery, 8
distributed transaction processing (XA)
also see XA
overview, 6.1
resource manager, 6.1.1
transaction manager, 6.1.1
transaction recovery, 6.2.2
DML returning, 2.2.8
driver manager
linking with, 1.2.2
performance impact, 7.1
using SQL_WCHAR and SQL_WVARCHAR, 2.2.6.9
XA, support (Windows), 6.3
dropping a table with XLA bookmark, 5.2.8
duplicate parameter binding
in OCI, 3.4.2.1
Oracle vs. TimesTen modes, 2.2.6.6
DuplicateBindMode general connection attribute, 2.2.6.6
DurableCommit, XA, 6.2.1

E

easy connect
with OCI, 3.3.3.2
with Pro*C/C++, 4.3.3.2
environment variables
OCI, 3.3.1
TimesTen, 1.1
errors
error and warning levels, 2.5.2
error handling, 2.5
OCI error reporting, 3.3.4
Pro*C/C++ error reporting, 4.3.4
recovery, 2.5.3
transaction log API error handling, 5.2.7
utility library errors, count, 8
utility library errors, retrieving, 8
event management (XLA), 5
execution of SQL
executing the statement, 2.2.2.2
SQLExecDirect and SQLExecute, 2.2.2.1
external user, connecting
OCI, 3.3.3.4
Pro*C/C++, 4.3.3.4

F

failover, 2.6
fetching results
bulk fetch, prefetch, 2.2.5, 7.6
example, 2.2.3
first connection attributes, 2.1.3
floating point data, binding, 2.2.6.8
freeing memory, utility library environment handle, 8

G

general connection attributes, 2.1.3
globalization options
OCI, 3.2.2
ODBC, 2.3.4

I

-I flag (compiling), 1.3.1, 1.3.2
IMDB Cache--see cache
include files, TimesTen (#include), 2.2.1
info types supported, SQLGetInfo, 10.3
initializing a database handle, XLA, 9.2.3
input parameters, 2.2.6.3
input/output parameters, 2.2.6.5
isolation level, 10.2.1

K

key not found error, 5.3.3

L

-L flag (compiling), 1.3.2
linking applications
AIX considerations, 1.3.2
OCI applications, 3.3.2
Pro*C/C++ applications, 4.3.2
Solaris considerations, 1.3.2
UNIX, 1.3.2
Windows, 1.3.1
with driver manager, 1.2.2
with TimesTen driver, 1.2.1
LOBs
OCI, 3.4.4
ODBC, 2.2.10
overview, 2.2.10
Pro*C, 4.4.2
XLA limitations, 5.1.7
XLA support, 5.2.3, 9.2.3
-lodbc flag (compiling), 1.3.2
log record identifier, 5.1.4

M

materialized views with XLA, 5.1.3

N

NVARCHAR type, 5.2.6.3

O

OCI
architecture in TimesTen, 3.2.1
call support, 3.5.1
compiling and linking applications, 3.3.2
connecting as external user, 3.3.3.4
connecting to a TimesTen database, 3.3.3
deferred prepare, 3.4.1
demo applications, 3.3.6
descriptor support, 3.5.3
diagnostic framework considerations, 3.3.5
easy connect, using, 3.3.3.2
environment variables, 3.3.1
error reporting, 3.3.4
external user connection, 3.3.3.4
handle support, 3.5.2
Oracle password, specifying for cache, 3.4.3.1
overview, 3.1
parameter attribute support, 3.5.5
restrictions in TimesTen, 3.2.3
signal handling considerations, 3.3.5
SQL data type support, 3.5.4
statement caching, 3.1, 3.5.1
TimesTen support, 3.2
tnsnames, using, 3.3.3.1
OCIBindByPos, 3.4.2.1
ODBC functions, supported in TimesTen, 10.1
Oracle Call Interface support, 3
output parameters, 2.2.6.4

P

parallel replication, user-defined, setup and ODBC support, 2.3.5
parameter binding
associative array binds in OCI, 3.4.2.2
associative array binds in Pro*C, 4.4.1
duplicate parameters in OCI, 3.4.2.1
duplicate parameters in PL/SQL, 2.2.6.7
duplicate parameters in SQL, 2.2.6.6
floating point data, 2.2.6.8
input parameters, 2.2.6.3
input/output parameters, 2.2.6.5
output parameters, 2.2.6.4
parameter type assignments and conversions, 2.2.6.2
SQL_WCHAR and SQL_WVARCHAR with driver manager, 2.2.6.9
SQLBindParameter, 2.2.6.1
passthrough
get status with TT_STMT_PASSTHROUGH_TYPE ODBC option, 2.3.3.2, 10.2.2
set level with ttOptSetFlag, 2.3.3.1
performance
batch SQL operations, 7.2
binding parameters, 7.3
bulk fetch, prefetch, 7.6
data type conversions, 7.5
SQLGetData, 7.4
PL/SQL procedures and functions, calling, 2.3.1
precision, 2.2.6.1
prefetch multiple rows, 2.2.5, 7.6
preparation of SQL
deferred prepare, 2.2.4
preparing the statement, 2.2.3
privileges--see access control
Pro*C/C++ Precompiler
architecture in TimesTen, 3.2.1
building an application, 4.3.2, 4.3.2
commands and clauses, unsupported or restricted (summary), 4.2.7
connecting as external user, 4.3.3.4
connecting to a TimesTen database, 4.3.3
connection restrictions, 4.2.6, 4.2.6
demo applications, 4.3.5
easy connect, using, 4.3.3.2
embedded PL/SQL restrictions, 4.2.4
embedded SQL restrictions, 4.2.2
error reporting, 4.3.4
external user connection, 4.3.3.4
getting started, 4.3
option setting, 4.5.2
option support, 4.5.1, 4.5.1
Oracle password, specifying for cache, 4.3.3.3
overview, 4.1
semantic checking restrictions, 4.2.3
SQLLIB support, 4.2.2
TimesTen support, 4.2
tnsnames, using, 4.3.3.2
transaction restrictions, 4.2.5

Q

query results, working with cursors, 2.2.3
query threshold (or for any statement), 2.3.2.2
query timeout (or for any statement), 2.3.2.1
Quick Start, demo applications, 1.4

R

RAM usage
ttRamGrace, 8
ttRamLoad, 8
ttRamPolicy, 8
ttRamUnload, 8
record headers, inspecting, XLA, 5.2.5
REF CURSORs, 2.2.7
replicating a database
utility function, 8
XLA, using for replication, 5.3
replication invalid, SQLGetInfo info type, 10.3
resource manager, XA, 6.1.1
restoring a database, 8
RETURNING INTO clause, 2.2.8
rolling back a transaction
utility function, 8
XLA, 9.2.3
rowid
convert ROWID to string, XLA, 9.2.3
using rowids, ROWID type, 2.2.9

S

sb_ErrXlaTupleMismatch error, 5.3.4, 9.2.3, 9.2.3
scale, 2.2.6.1
security--see access control
signal handling considerations (OCI), 3.3.5
Solaris, linking considerations, 1.3.2
SQL_QUERY_TIMEOUT option, 2.3.2.1
SQL_WCHAR and SQL_WVARCHAR with driver manager, 2.2.6.9
SQLAllocConnect, 2.1.1
SQLBindCol, performance, 7.3
SQLBindParameter
arguments, usage, 2.2.6.1
performance, 7.3
SQLColAttributes TimesTen descriptors
TT_COLUMN_INLINE, 10.4
TT_COLUMN_LENGTH_SEMANTICS, 10.4
SQLConnect, 2.1.1
SQLDisconnect, 2.1.1
SQLDriverConnect, 2.1.1, 2.1.3
SQLExecDirect, 2.2.2.1
SQLExecute, 2.2.2.1
SQLGetConnectOption, supported options, 10.2.1
SQLGetData and performance, 7.4
SQLGetInfo TimesTen info types
TT_DATA_STORE_INVALID, 10.3
TT_DATABASE_CHARACTER_SET, 10.3
TT_DATABASE_CHARACTER_SET_SIZE, 10.3
TT_DATABASE_TYPE_MODE, 10.3
TT_PLATFORM_INFO, 10.3
TT_REPLICATION_INVALID, 10.3
SQLGetInfo, supported info types, 10.3
SQLGetStmtOption() ODBC function
TT_STMT_PASSTHROUGH_TYPE option, 2.3.3.2
SQLGetStmtOption, supported options, 10.2.2
SQLLIB support (Pro*C/C++), 4.2.2
SQLParamOptions function, 7.2
SQLRowCount, 2.2.11, 2.3.3.3
SQLSetConnectOption, supported options, 10.2.1
SQLSetStmtOption, supported options, 10.2.2
statement caching, OCI, 3.1, 3.5.1
statement execution (SQL)
executing the statement, 2.2.2.2
SQLExecDirect and SQLExecute, 2.2.2.1
statement options, SQLSetStmtOption and SQLGetStmtOption, supported options, 10.2.2
statement preparation (SQL)
deferred prepare, 2.2.4
preparing the statement, 2.2.3

T

tables to monitor, XLA, 5.2.3
threshold for SQL statements, 2.3.2.2
timeout
for SQL statements, 2.3.2.1
handing timeout errors, 5.3.3
timesten.h
brief description, 2.2.1
globalization options, 2.3.4
ttFailoverCallback_t structure, 2.6.3
tnsnames
with OCI, 3.3.3.1
with Pro*C/C++, 4.3.3.2
transaction log API
also see XLA
bookmarks, 5.1.4
closing handle, 9.2.3
data structures, 9.2.3
demos, 5.1.8
error handling, 5.2.7
functions, overview, 9.1
functions, summary, 9.2
overview, 5
replication, 5.3
tt_LSN_t data structure, 9.2.3
tt_XlaLsn_t data structure, 9.2.3
ttXlaAcknowledge, 9.2.3
ttXlaApply, 9.2.3
ttXlaClose, 9.2.3
ttXlaColDesc_t data structure, 9.2.3
ttXlaCommit, 9.2.3
ttXlaConvertType, 9.2.3
ttXlaDateToODBCCType, 9.2.3
ttXlaDecimalToCString, 9.2.3
ttXlaDeleteBookmark, 9.2.3
ttXlaError, 9.2.3
ttXlaErrorRestart, 9.2.3
ttXlaGenerateSQL, 9.2.3
ttXlaGetColumnInfo, 9.2.3
ttXlaGetLSN, 9.2.3
ttXlaGetTableInfo, 9.2.3
ttXlaGetVersion, 9.2.3
ttXlaLookup, 9.2.3
ttXlaNextUpdate, 9.2.3
ttXlaNextUpdateWait, 9.2.3
ttXlaNodeHdr_t data structure, 9.2.3
ttXlaNumberToBigInt, 9.2.3
ttXlaNumberToCString, 9.2.3
ttXlaNumberToDouble, 9.2.3
ttXlaNumberToInt, 9.2.3
ttXlaNumberToSmallInt, 9.2.3
ttXlaNumberToTinyInt, 9.2.3
ttXlaNumberToUInt, 9.2.3
ttXlaOraDateToODBCTimeStamp, 9.2.3
ttXlaOraTimeStampToODBCTimeStamp, 9.2.3
ttXlaPersistOpen, 9.2.3
ttXlaRollback, 9.2.3
ttXlaRowdToCString, 9.2.3
ttXlaSetLSN, 9.2.3
ttXlaSetVersion, 9.2.3
ttXlaTableByName, 9.2.3
ttXlaTableCheck, 9.2.3
ttXlaTableStatus, 9.2.3
ttXlaTableVersionVerify, 9.2.3
ttXlaTblDesc_t data structure, 9.2.3
ttXlaTblVerDesc_t data structure, 9.2.3
ttXlaTimeStampToODBCCType, 9.2.3
ttXlaTimeToODBCCType, 9.2.3
ttXlaUpdateDesc_t data structure, 9.2.3
ttXlaVersion_t data structure, 9.2.3
ttXlaVersionColumnInfo, 9.2.3
ttXlaVersionCompare, 9.2.3
ttXlaVersionTableInfo, 9.2.3
transaction manager, XA, 6.1.1
TT_COLUMN_INLINE SQLColAttributes descriptor, 10.4
TT_COLUMN_LENGTH_SEMANTICS SQLColAttributes descriptor, 10.4
TT_DATA_STORE_INVALID SQLGetInfo info type, 10.3
TT_DATABASE_CHARACTER_SET SQLGetInfo info type, 10.3
TT_DATABASE_CHARACTER_SET_SIZE SQLGetInfo info type, 10.3
TT_DATABASE_TYPE_MODE SQLGetInfo info type, 10.3
tt_ErrBadXlaRecord, 5.2.7
tt_ErrCondLockConflict, 5.2.7
tt_ErrDbAllocFailed, 5.2.7
tt_ErrDeadlockVictim, 5.2.7
tt_ErrDeadlockVictim error, 5.3.3
tt_ErrPermSpaceExhausted, 5.2.7
tt_ErrTempSpaceExhausted, 5.2.7
tt_ErrTimeoutVictim, 5.2.7
tt_ErrTimeoutVictim error, 5.3.3
tt_ErrXlaBookmarkUsed, 5.2.7
tt_ErrXlaDedicatedConnection, 5.2.7
tt_ErrXlaLsnBad, 5.2.7
tt_ErrXlaNoLogging, 5.2.7
tt_ErrXlaNoSQL, 5.2.7
tt_ErrXlaParameter, 5.2.7
tt_ErrXlaTableDiff, 5.2.7
tt_ErrXlaTableSystem, 5.2.7
tt_ErrXlaTupleMismatch, 5.2.7
tt_LSN_t data structure, XLA, 9.2.3
TT_NLS_LENGTH_SEMANTICS ODBC option, 2.3.4.2
TT_NLS_NCHAR_CONV_EXCP ODBC option, 2.3.4.3
TT_NLS_SORT ODBC option, 2.3.4.1
TT_PLATFORM_INFO SQLGetInfo info type, 10.3
TT_PREFETCH_CLOSE connection option, 1.2.2
TT_PREFETCH_COUNT, 2.2.5, 7.6
TT_QUERY_THRESHOLD, 2.3.2.2
TT_REPLICATION_INVALID SQLGetInfo info type, 10.3
TT_STMT_PASSTHROUGH_TYPE ODBC option, 10.2.2
tt_xa_context() function, XA, 6.2.4
tt_xa_switch, XA, 6.2.6.2
tt_xla.h include file, 5.2
tt_XlaLsn_t data structure, XLA, 9.2.3
ttApplicationContext, 5.4.2, 5.4.2, 9.2.3
ttBackup, 8
ttCkpt built-in procedure, 5.2.9
ttCkptBlocking built-in procedure, 5.2.9
ttDestroyDataStore, 8
ttDestroyDataStoreForce, 8
ttDurableCommit, XA, 6.2.1
ttRamGrace, 8
ttRamLoad, 8
ttRamPolicy, 8
ttRamUnload, 8
ttRepDuplicateEx, 8
ttRestore, 8
ttSrcScan utility, 3.2.4, 4.2.8
ttUtilAllocEnv, 8
ttUtilFreeEnv, 8
ttUtilGetError, 8
ttUtilGetErrorCount, 8
ttXactIdGet built-in procedure, 8
ttXactIdRollback, 8
ttxadm43.dll library, XA, 6.3.2
ttXlaAcknowledge, 5.2.4, 9.2.3
ttXlaApply, 5.3.2, 9.2.3
ttXlaBookmarkDelete built-in procedure, 5.2.9
ttXlaClose, 9.2.3
ttXlaColDesc_t, 5.2.6.1
ttXlaColDesc_t data structure, XLA, 9.2.3
ttXlaCommit, 5.3.3, 5.3.3, 9.2.3
ttXlaConvertCharType, 9.2.3
ttXlaDateToODBCCType, 5.2.6.5, 5.2.6.5, 9.2.3
ttXlaDecimalToCString, 5.2.6.5, 5.2.6.5, 9.2.3
ttXlaDeleteBookmark, 5.2.9, 9.2.3
ttXlaError, 5.2.7, 9.2.3
ttXlaErrorRestart, 5.2.7, 9.2.3
ttXlaGenerateSQL, 5.3.5, 9.2.3
ttXlaGetColumnInfo, 5.2.6.1, 9.2.3
ttXlaGetLSN, 5.3.3, 9.2.3
ttXlaGetTableInfo, 5.2.6.1, 9.2.3
ttXlaGetVersion, 9.2.3
ttXlaHandle_h XLA handle, 5.2.2
ttXlaLookup, 9.2.3
ttXlaNextUpdate, 5.2.4, 9.2.3
ttXlaNextUpdateWait, 5.2.4, 9.2.3
ttXlaNodeHdr_t, 9.2.3
ttXlaNodeHdr_t data structure, XLA, 9.2.3
ttXlaNumberToBigInt, 5.2.6.5, 9.2.3
ttXlaNumberToCString, 5.2.6.5, 9.2.3
ttXlaNumberToDouble, 5.2.6.5, 9.2.3
ttXlaNumberToInt, 5.2.6.5, 9.2.3
ttXlaNumberToSmallInt, 5.2.6.5, 9.2.3
ttXlaNumberToTinyInt, 5.2.6.5, 9.2.3
ttXlaNumberToUInt, 5.2.6.5, 9.2.3
ttXlaOraDateToODBCTimeStamp, 5.2.6.5, 9.2.3
ttXlaOraTimeStampToODBCTimeStamp, 5.2.6.5, 9.2.3
ttXlaPersistOpen, 5.2.2, 9.2.3
ttXlaRollback, 5.3.3, 9.2.3
ttXlaRowdToCString, 9.2.3
ttXlaSetLSN, 5.3.3, 9.2.3
ttXlaSetVersion, 9.2.3
ttXlaTableByName, 5.2.3, 9.2.3
ttXlaTableCheck, 9.2.3
ttXlaTableStatus, 5.2.3, 9.2.3
ttXlaTableVersionVerify, 9.2.3
ttXlaTblDesc_t data structure, XLA, 9.2.3
ttXlaTblVerDesc_t data structure, XLA, 9.2.3
ttXlaTimeStampToODBCCType, 5.2.6.5, 5.2.6.5, 9.2.3
ttXlaTimeToODBCCType, 5.2.6.5, 5.2.6.5, 9.2.3
ttXlaUnsubscribe built-in procedure, 5.2.8
ttXlaUpdateDesc_t
description, usage, 9.2.3
rows of data following in update record, 5.2.6
TT_AGING flag, 9.2.3
TT_CASCDEL flag, 9.2.3
TT_UPDCOLS flag, 9.2.3
TT_UPDCOMMIT flag, 9.2.3
TT_UPDDEFAULT flag, 9.2.3
TT_UPDFIRST flag, 9.2.3
TT_UPDREPL flag, 9.2.3
ttXlaAddColumnTup_t, 9.2.3
ttXlaCreateIndexTup_t, 9.2.3
ttXlaCreateSeqTup_t, 9.2.3
ttXlaCreateSynTup_t, 9.2.3
ttXlaDropColumnTup_t, 9.2.3
ttXlaDropindexTup_t, 9.2.3
ttXlaDropSeqTup_t, 9.2.3
ttXlaDropSynTup_t, 9.2.3
ttXlaDropTableTup_t, 9.2.3
ttXlaDropViewTup_t, 9.2.3
ttXlaSetColumnTup_t, 9.2.3
ttXlaSetStatusTup_t, 9.2.3
ttXlaSetTableTup_t, 9.2.3
ttXlaTruncateTableTup_t, 9.2.3
ttXlaViewDesc_t, 9.2.3
update header, described, 5.2.4
what it describes, 5.2.5
ttXlaVersion_t data structure, XLA, 9.2.3
ttXlaVersionColumnInfo, 9.2.3
ttXlaVersionCompare, 9.2.3
ttXlaVersionTableInfo, 9.2.3
Tuxedo, configuration for XA, 6.4
two-phase commit protocol, XA, 6.1.2
type mapping/conversion for parameter binding, 2.2.6.2

U

UBBCONFIG file, XA, 6.4.3
UNIX, compiling and linking applications, 1.3.2
update conflicts, XLA, 5.3.4
update records, retrieving, XLA, 5.2.4
Utility Library
described, overview, 8
ttBackup, back up database, 8
ttDestroyDataStore, destroy database, 8
ttDestroyDataStoreForce, destroy database, 8
ttRamGrace, RAM usage, 8
ttRamLoad, RAM usage, 8
ttRamPolicy, RAM usage, 8
ttRamUnload, RAM usage, 8
ttRepDuplicateEx, replicate database, 8
ttRestore, restore database, 8
ttUtilAllocEnv, allocate library environment handle, 8
ttUtilFreeEnv, free library environment handle, 8
ttUtilGetError, utility library errors, 8
ttUtilGetErrorCount, utility library error count, 8
ttXactIdRollback, roll back transaction, 8

V

VARBINARY type, 5.2.6.3
VARCHAR type, 5.2.6.3

W

Windows, compiling and linking applications, 1.3.1

X

XA
AUTOCOMMIT with XA, 6.2.5.1
driver manager support (Windows), 6.3
DurableCommit, 6.2.1
resource manager, 6.1.1
transaction manager, 6.1.1
transaction recovery, 6.2.2
tt_xa_context() function, 6.2.4
tt_xa_switch, 6.2.6.2
ttDurableCommit, 6.2.1
Tuxedo configuration, 6.4
two-phase commit, 6.1.2
XID parameter, 6.2.3.3
xa_close() function, 6.2.3.2
xa_open() function, 6.2.3.1
xa_switch_t, 6.2.6.1
XID parameter, XA, 6.2.3.3
XLA
access control, 5.1.6
acknowledge records have been read, 9.2.3
also see transaction log API
also see XLA bookmarks
application context, passing, 5.4.2
applying database updates, 9.2.3
closing a transaction log API handle, XLA, 9.2.3
column data, inspecting, 5.2.6
column information, retrieving, 9.2.3
committing a transaction, 9.2.3
concepts, 5.1
data structures, 9.2.3
data types, 5.1.5
database connection handle, obtaining, 5.2.1
dropping a table with bookmark, 5.2.8
errors, reading transaction log errors, 9.2.3
errors, resetting the transaction log error stack, 9.2.3
event-handler application, 5.2
functions, overview, 9.1
functions, summary, 9.2
initializing a database handle, 9.2.3
limitations, 5.1.7
LOB support, 5.2.3, 9.2.3
materialized views, using, 5.1.3
record headers, inspecting, 5.2.5
record, looking up, 9.2.3
replication using XLA, 5.3
rolling back a transaction, 9.2.3
table compatibility, verifying, 9.2.3
table information, retrieving, 9.2.3, 9.2.3
table status, 9.2.3
tables to monitor, specifying, 5.2.3
terminating XLA application, 5.2.10
update conflicts, 5.3.4
update data, retrieving, 9.2.3
update records, retrieving, 5.2.4
version, retrieving the Transaction Log API version, 9.2.3
version, setting the Transaction Log API version, 9.2.3
XLA handle, initializing, 5.2.2
XLA bookmarks
creating or reusing, 5.1.4.1
deleting, 5.2.9, 9.2.3
determining tables subscribed to, 5.2.3
how they work, 5.1.4.2
location, changing, 5.4.1
overview, 5.1.4
replicated bookmarks, 5.1.4.3
reporting DDL events, 5.2.3
X/Open DTP model, 6.1.1
PK0 `vPK:AOEBPS/img/reset_bookmark.gifg,GIF89ad @@@𿿿ࠠ???```pppPPP000 ___///oooOOO! ,d@pH,Ȥrl:ШtJZجvzxL.hqn iBu~y  xY BBxWB_QCm C m C  C D C l HGC$|*\ȰahC$2@Z>8SDtM{>|<) Dh*R|`p2ANF? :Jf}Ra ȸcO3"3%vb$$" B⇢|qU]]̸c?Y~pA&uO!)K$K ARtu!S1j)ck}̻Z"^lkc6 v\$5rZ[k4շ'4ӫ {_ߌ3Q,JO|]kQ7?]gmރFp *J8dJb Зdg$5tǸW`YxwHOz<-kp>t$iJѓ!su+[#S‚ԓDYDEGxCx+,(sߣZ0!Xs'>D /XN *w>a>Ӝ M*Pkq N1 1@Mda9P3;'ᰴlDhQH)ZHh OKX):֥n<qp8R5&`|yXI+Q !t|XRAYCD@n*{s:ʲaPPQUG;!h铑N5%r$&9ez!` B)?D_NH\ $/Z ?ɂܤIe.3 GX&GO1uPO(*- )&}9p?I<E1_99`d*bvGA G"),a::3+iJٗ*0E9* DJ. ŌE'ƽn}Lal@NGQOd#]LR8IrD8죂`L"HN&;P#]OzCDLv|0מǽs?|>'O(/~"ȯ g=}=S KATh?HU>2,(X}8x| X0؀phWhH{%()$*؁#{1Ȃ2 ҁ'? 0 CW}|Px|QH~|WX~7}\H}[x݇`(~f;hAhXW0PЄsx1l4oq#7Qv8Q+؈x76x1{h(PІU V@OU N03UO`z iSg`ȅZc}b(W_h\Y׃wX`N#D3 UW5X(؏&(y-I ȊO S@T`MSL h{` z{̨}8{@P9 }ј{]xHi{ܧ÷{w¸\ّ8acy$)eCfWEdLp 9FzR K`:\gQ:P7SDs &Q=Ђ#šf:$\e1\dry PKly 9KO;EB[IBOC{J K۳E[tha$*{@ ʧQ8aW\PGWR?y{)Z~8Ppp{6Z~{Д@JR)LpNxp"}Wj!gbB\*7q^RFTA   +6u 0=1360eG0pp4N`k" =s@N"f#%[<THF搾TF۴;DKMX7XXꂁgu+@uhw0p|{`j hɀЙS0XVQܚmĺYA=$P3JE_Y =5TJ\IT›#Cߪ 0\0B u 0W{ x %FQ8 bak|gVٷ7|f딷vUٶR(5*Pә(ꓴg-j{Jjpgзk{}Mvp{{{8ʋ[{|׸<p,0Cu|,LkQAH|<^NL>q[cJ |LBm\{14N[4!1:J*<XpvwP'  <¶3x-1Hp9*6ZX gm9kEPlc0+l|.zAdIpϺ%Fs+ k0jyNƥl32Bk;B2aB AlY f2X{KNX{R1 ʲwȕ +UɁY{Pתs ,7>p8!D|y9; 77i #a¨{ K |CIAiظ< К:n{{DkC9SK~– V ( rq OS2ڀذ ^c J2eoV@BfRLx@6zE:X0 ɀ}%h"mAJρZI-HK_v)3l~HPV.9񪁑aBJ c>?"`Ӈ1&5밄zxȪ[~oC)}Jѧؓ}Hy :doE;_/ĞF5 Nska4;PJI0M_ io+o.2X@QPJ6COИ\6́nnyC(Gy2\/7"> !#%A'/1#><>? :ACGIEJ=OMAEY<`Ig]WkQUq[Y_Gem}y=i{s;on[2A.A'%+˿/߿ d2_A{Q2`}꣗%bB0}2m4.S:H1y|x'QA@K/aƔ9fM7gJP@ ,3DQFB4ЧVPծEFWAz(fԱlJSg4#|f3>,b >tSdJռsgϟA=tiӧQVukׯaǖ=vϗq[lwo߿>xq;VysϡGvg׾{w?)ƧW}{_׿w>.οLP|(C(k 1P '< ¾ I,Q(l LQiF7tP) rQ%lIЬE3+RKvv ߪp1,1H3L3Sl1,9O,2L?MTQ -67{sI)T92OA'GA PQ/N@`9ZRWP P Wј5 @VXu}H&MTDh79C^HČ.5aoBvt1!IВot(Ac5ځ֍U ^V[\#D΀]ݕ2(EcPvjsZa`?Xr4  8=$v/E:Y2 wbnl v‹l$V cˈ ;x2XیLjz F;l}2&oAyˡn`@']}@ 7r5p-Z98$Xb``I*z]:&uq_A  T@wn]tW=gAh5֝;On8{ Qz cEP L-U#"%,Fn!Ǿ{HV% jBTX-l2A u.$`Dbn3$%AY.L) hyc(702·=#1?0 ߁ R"g#ɰ:ƅh &q" % &KbȍE cp@>laHME#CyJ 2q(ЊvGe𒙤Np%90ǢqhK"A?j$x@ @6UaSeˆUD0yI,s|P1kzb&]Rb<2Z\6L }2_8!CvIfP)ob$ e')92AՈGx3mE=G.\5iM$M4ҟ=Y0ZǁhH Q. -VMXPg> V(ˆ@yD6&^:Pxjc1+ `.O:hG˾5{q ӷ:p~Y ŷBpEҵ1;ֆ+({ʄՍq} ,apwSa7Cqy3 (+7rRK(#_63߂N+LޕKssg=#{g@2s}I@(wj2bay̭{ζ<Ґ[!{(:%Jh%@-sS2nՑDqkL ;vc |hU_ΡrDpk'>3IXF'[ŜT/;Ta[N =mž_wSU =fDf, Odbә݌. `!dsjyKֳK- `~KqXCD8r~!x`ڕzas/!J?E2@ԏ7) )j0gN"53 1cd "聢yNX;Ldcɵ6`:[h"@-&~==K I,bܐ{z!"(n у.4=Xec}`X΄ˆykԊSRu&zr\}֍w I1sID]exg #9hȠ37%_OEZJB7ڠkKo"݆p%M0ԨgB2وrA"|  Z f c P""PCCꈉ ^ /^ ?wJ 4p eqha0 #EUH0f`H%Jf̊Alj"Be0L E(JI2hko0hp -hhB"$ <o wjxF:ѬlM;VeBjA 0$plB)NveHQEunap t[egHH''|lQl}wVK@*jX;ɦ7- Vqg$2BhN@řT' ,2Hj"c Ce[@Ƒf\jP0 ueZhAej n"`() |]!)Ey^\R()zw)nm' iڬAX,-蹴) 0 }*g) ().2Cdr*Qj&)3< RS297b0F`,e3;4Oz:@4M5q%DS\6m3j6urs7}Sz7s88is93Z95go:ӗ:3Qs;O;Ls<[θ&a]=<3bPO!3#><$d=#?C?sM^3 n_E5u`U'`\6a`a`vb5f1GHh 3Fd>vt'^Tv Ef&@!/HnVr6c-nP e@x%NP@dgJfgbVv(6z['nTd{zV6Am%a'{r6V%jV6#v\I zN@N5@y&$ NJ`^6vngvsy6cne] FbV fjc!UlqraⲹHhod1dZ u[eѨ$&e.s-s jVzszlV+CDLz ntkVA8dw.=PVOd`G2jj q*/ I~r@hRWJ\n"oMoW6\=ǴM&h;mH(il@ڌ\oXꘄ:8|*sWFYr^f]@7[@ 6l^fhz ohqC24%{KXzh{4TvwJ)Bgcw&Ah7u Ws-bOFg@o.kUy`czF*, #&XiEjpgF!J? Q%vbHM**J&2y4./xTǡX2f]\Ȓ)#zhz\u. U,a6A 3Vˈes4hYFCoqILƑoG ke&h‘^}RN `Zo$Gg$Db"AMNa# 歹tn82# @]fdA"XЙcj0-w~KgE(8Z L{  |C1vOɳ-(I&k70 agX+4`Me $Ii1ؐ X}QO"@;e::¸)y)w8;𤓋P(21oXʣ:N f\иu; \E{J;$/<> %ͪ{_r 䎷mdreM;&乛G.}I2ˋ::2Ba~%tی9Ww*$[#쀆~EҰv/(2<覫$U +R(]L -l' gG,Wlgw ,$l(_{e0,4l8<@-DmH|.PG-TWmXG}FY_tW1[MjK-vQ i4vc߱11+;`x렸.xz:簹 &OC8LC8|~X 6>78~8y:7V 4(6385H2X*z_ 9 {/oѫ?=񵛏9)&m+!00'~F}s'y i= ԏ&e 6_\L(@ >z- gP1 H-M,aq&TBO4 kv/Ӣ zh+$'e)%BNP O 51}mD`2zp\p#l`I([ vc[ԖZDQ$5 z)_҆b.S3⒴CYl LtbqpK! 0ͪQ 1e(x4Zy!=O$2#T>Ĩ#XA&%!RR䡞h?!CzȤTuHP ]hw&{&R,' *KѠۓ b)мP  N.2x4$UR IB:(#4U˛S5 AK#B#1t!a's } ,[ʻ2Ѻ+@Qc,K\(rw 0$x # J 'x5t ;Q5ag G[ȡV.l'o ĩM lB&#نbɻQ#Ő%rFZ\Aq$_ Ƥbƿ{LHT2[ \QcpJiPqǶǻ~5[P%e 3Qu4 zRV ;Qo0 ggbQ&wj Sʖ8 -pL G ;Q! - @#ţrirHb^4 s 4-٘m0]2okءY:y.ڳm>Mۙm>zۼ=; g]3:,*ܨ$UOIUQy-,F=-[e"&Xgxݝ%ROP / й P5R[/tQ>T&=OU7=x"ihWgçT  YzwB`Bڋ% #[YN~'Y`y0cn0T^^4_ v_?fZwnKx:>Rg<k32l) }PzP"5Pa wR@R X]H:Ȧ ~xpi./Rދ;9Z|7ukD{L|^GxN/j:`Qf n~V<H|/>RJqmlf6Hۡ[H.lݓ 0[] t9udDQ2JBv  ײK.ftp@|iyMɨΙ{ ^`EOdq{]0iq8P_N+&l7݊$3JݝڶnCa/D̍ܭo? t/S7e6=77=7Ux׌2֔_ר;PK,PK:AOEBPS/img/odbc_diagram.gif|GIF89a,ڋ޼H扦ʶ L ĢL*̦ !ԪjܮN zWl'8HXh8xh(9IYIi) *:JIzc kK[k7{˫ ,|;l|LT|6L]\ m@3 m. ]>>=tN^,/POj0,Rr}V91-70m2FO]E8X1D QE}\D %ʒ<'i2ȝ,Ŝ0kdGo aK ¡ %jz>m:s733kXu׾n;c[2;+wo>KIruڻoG7>?;1hEEt ̓t Nh̃D cajathЇ *$v)(ʊ0848H<CB:J.I>"LIeV^eZne^Z)bIfcőPfn gmIgpޓk1~eJxޡ瞞Ph hwVGèNindfYꩪV *vF*묧 P믛櫻z֫lĢCs0lVh`*b?vKjj*t nkbng:'y|p 3\' 1G\ YjX)_,Èn1o \O<4L/ lA s* :L"zZvJ{;޺Ǭ5En70,w޵6;d[_,p7yAK/?9{wMt[Wx,g;nKXzU<x)#J(߹Mxk/B^O? og+!O>f-9a6fbqW!ј跽|4La)TaƊP'ۣܗJяW#$W'DZ#߅Hh-_T%'uI$'wCEjr)dMyHkB%xIQG+J28%nRr!/B&nW3yeL$4;FMeq~Ep}L*9ωts.H; xsl3(S\ܧ?_LS|0 TgBMvЇJ{ u(*-:ѺethDQT$ GEҒ2S,=SˏL02 FԦ,Lq}ԧ#*K:TC&էK5.ԩjI:d6զ[*U1b&X9Ֆ;FתRu`nŗTЫ ǠVUfкfk^kxHI3>lA;(9ʰKFAQl SaεdWӱrp̠g 7 ,_iWâVgBFխo X[N33]/[k\dh\ϴE+nfWqK=rXՖrݓ#z\ dh&|[]{WL+] +Ѽ X鞻$ n{v~E-e7H1Hlx†x<`x]~5ka9.zN̾$ߘmp78f@p'WcH)#dfx* gua>8[d[6xu4d16 ;|dv'8lŁ0}YlcI3޴YDlgFHG:~&ֲ5f⵲jm-`腓FrjǵaV6W-۽ߒ=QU7tϜT񨡝ex 6?fFJmܿ:7uV~4*y/+Ѿ7U[pYo۩?OlVCng3@=qtC^qs,o_r|4o|AъY?_5ix~%Y3{('v\6|qaaɕl ȁHb #.H'H]+8t,%/(L3h7m;胖Ճ?(UChwIXm>DŽMOQ(SHUބ@KYȅeU]cMdhgkbLo(1 VOcT[8-yP괇qH/ב1 {hi҈SGs ҉2tPېҊ2Iӆp(1hֱh (hM񌫄H 8(H6aɠҍ-p dRԎ}߀61 S荂a"Z!)A/h?#aD )H9M@A1*Q 4+9i%yn4ՃƑ#ʁ5ٓAը2 .)qO IJ!AHRŐKhN) m間ѕ,jxB/I>1y1gF33ٖ )r)Y!Yِ*!1| b~n1Hiy/9 yDQy M&9 IQ/$陮!яҙQYɍRi }iΙL1aљE銤)xWymi Q9:Έ7d`i Qɞ0Y1ɛ IX EYF٠IJ"H(7謹P๤V );N P!h1 )HR b:2h*Be+M rJҸ_}Z٨^A#WlѨ:Xhj饙ڣzt0::Z⸫礟ZNJ sjLBsȬڬ* ZKj:IʭߊF*9D@犮֣ :gi'"F! J 󊆡R+p*i X$H%e Kz@v {> E"ѦY7)3 *mٕ!i$K0:-{̙!)H$& 򡚘鏿@˹RK #"];!:˕PYS)+ Of;.:c[ʴ5F*}k;J7{ ?)ɏ0+kX鷥{{K&y"[;Aj' 2 ۺr'Z Qk@bi;뺜!K C{nr;O+I{K:p *˛ {|+(׻R@ʾ)i Ș{YB{Ȳ :;g< ˺ 1\:X۸; \_ \ Y,묷 Tk z1۸ܑ[۶>lKHa%Jŵɳt?j˵+Y˖F\\C w~p|?,[Q/;kwl+b 4+|ȶZȋ̫y; gjƕ~ɣUBɟ#,7Bʥ<#/ʫ"!˱!Lb˷ ˽ #l̴Z ,L՜N;PK/|PK:AOEBPS/img/xla_char.gifGIF89a vV@@@o%6BEƿ069STUace !V, vV !܅U H[ȰÇ!Hŋ:`A =P+I$D:0!!*8 1< IL TĈ1Ē`"%JJFAP @AHDܳ% uZB0IP0ځ' -ٖ'& rU4XR x h)#K*?9+*.!)@+.&( `6HzQG(hB#ALqW>1W+C d Zޜ%WZ<ɹyM@Byl>7` Ђ69UGca7L7e8ЕA{m!!.m] QfE[PͅA2q8c=l Db rIr2F|~T[$Z F $y]Z @\V Ez 2gP$B|ipZ@ U! <!g9UpRI$ ȍ;*0e!^ D:e_i 5 F -!BW'&Qi*k5 q坜k'iat RMT.͖:z Li{I֥=6V$i+µaյvKe٫${0k%m!b,$Kś+mʎD]&x%MHXⱋkZȲ&qd] -dgLtb HtSM{KΉ =s-tDY8QӤQg@aULJP^'v؈jT+ݼ ұM !mrnԯq7;ΆYV9t\f6#:SzUM%2 :M1ǣحSA884`C0*P d4Tʲ ,;%R.N4įݫc]f8@Ef:&@RS?G$rt/mĂTv! 'O8xiF1ڭ 0_0Κ1V@ڄ5@UhgwsxĵPh4MPaϴ5aE33_R1Eݝ{KyS,,N$ mdH])D(f⭅wh(Ym3CNn-ʖZpۼuOpnv99% >prJ6>/c;)9S#~sE1x8QH'cA/2@Psw=ʒ)SR06[D0x~BS'vQ&P9A4ws1q8@R9>H"@1Dx &20Q;}6SDD+zq0P%^=nG~q7&Vc#BȇhF]8Ra{ppRrg:W8 ,DK<~~~?a%t7=owr,o$ 0C0uD]?'9~`Ruэ IkSaQ,tw$A1Dm(QB':!rE%(.BLXy#BrJ/"%*2&H8'B1ՀE>Ix[ae+jwPy"(e[S*[(#3eQ({c!` >g1Mjw0^9 OSWR-?! M?ٗPA& Gc: pvy:藒dXO`(6ui 9Ybi =YY@YAa蕛ٛ9YyșEvh9 @q Qڹٝ9Yy詝 "#ڙY)]))<12f'`[)y\ڠ O&* ˗tgb'#$*e)z Zke3ٟǢ52 R+6u8:yأ@4O&{9CJz դ"RSLz *b|f]f a+ʴ+ʦτi ^c'P1)e+FR(꧸vUo jevJ bj*:#ZpBɞɝh9 +/;2Șʰ ˎɴ<˸˃<˵ 0ʥ\#|Sʬ̼˒L͕άL ì#|,\Ͷ |΍l9͒\ψ<|!ϑK|RϽ- ] ,A}k ]M ̬l,8b|ҸҾ<$&=Ъ* ӗ\*p /]*`<2 -Mf]9&Y](S;$\/ ,L$@$Ϭ,\]]%jK= pb?\X V!hdO?!TQr|] /&s,%@s=) *PւMdm.T֊$1LTX{DfMTPh{ee0 ftpl:} & 1$@\l΂_-T=&@F$pY{\4@cmDUM۝CJT5o{պ]-.1]-p-*'@-`ڃ\i5TpK0:0 8D@+pp=n/ =p7,PpR`/b.>EXNktiF `TzMeo5i>?hƍ܃] `\:fTlkdGZ\ 4^&eTM\T#i@Evz-ܝHHy2 ho}ۃ?hs-*-P%p(Tӧ]L>;0SEμ=O;&7.\+0+&m4oNdUeWuՕ?`dr?lǽ_^pnUENF]@ZPi _aF҆T3 Tn҄%Ӎ18'1 -i'`$m.'0=;;S0T2@S`: LKp|h>@P/tO-=ڙϾ}Dh(Umd\?EGcWd No]_ʍ dcG/nEed|c$~Faoخ@$%G~12)m=+p]T* ڄ\ڻT 2:?9@60Z߂⹭RFڣ]ނUT"UTUTUT!UU TU T"T !ɊވVVT VT R*\ȰC)+."!TT$ SlP C -\!C Ss 2iLa`I)" %8$>Da4 *&.ׯ`F,!QU6J3B"UR*:*T82S a. .hPUVYVڡVU<lõ:3-װc˞[qTY(J"''aAZ?ʐ Q7xtȄ%P 3vԤæN+V`(*H)&OX@')e ŗͧW`%X!`y"gLY'!aUH]\0jPa)x2׃FۑH&$;DqD@V<D@=sr`2F z>i eJSRptɗRT1QÞ~NCB(1F%%C/YB'H$duW E / ¢[P@i6 J^hjxWȊ1xg6fi*`͆aXlpbJ` m*kn<<84` @ ,=ePR)- TB -G  I'Tp S@LS AEL6@PihaG ) '8\u])&8jRY61=fT !"4ɨH "Cze"(d XL$x"4x!BA <&۾F.9|6'dCw |]Hd dNP 7 I^}8X2%Jf( Ж"UA^H9.W8NwiWQNcEu|3̓|i+)=m39:!G Xs? N '{ `p+K!ڐ,݃:xp@ J"J!]ĢMPbx(EPX̢<6QT-'Vh ӈ+jpWPt$ >61T#HByDo '@NHA2vd>3R 1V4F@Z e,%g0 0ISYf(4IjZl̦6nz 4prDֈvN~d3I=̧>~ @JЂ І:D'JъZhDHώz HG@;PK'PK:AOEBPS/img/update_records.gifC,GIF89a6cqsu@@@89:```egjppp000UVXPPP568FGI235 cdfkmp*+,ǭLMO~ PQT?@BBDF((*xz~ϋ ]_bXZ]rtw&&'???ߟ___ooo///OOO<<=!c,6cUUƌ(a( H[‡#JHb3 3jrhG|/d|I2Ɠ8\yƉ0cxCLr2JρQ QgN(C=RMsMsP=ʕ^С`u Dzb6,avb[e!ݡUKa*j即iB }ë Y"vSFe/J\nv法X4\}\"eeMٵѶ#eX/d$gW F1=A䄍eȱ!q1<0 BGO1x'x/ LsËcsk3g~ȐT <$pG[X1p2Đ'4C b ZmPX8r\/>tT]qFi3 6P8Ԕ =2d"I)IL=2 2=`UaaXc*cߍc<\ bEU2錒 fv2D#a%J[R*yW{֣qbY "jc3r깖,e2h9b.諚Vz郙:2#*G 8U>k nj 666([f1[:-gC 70yrV;.L&F\%6v[N )+Yɕ'jUzIã8K".r?## a:XT ؖ "v!k p 3 ڼz4KC87EY}h1%ǡ5աk(8iaؕȡ7u]H4eCKpCԑKފwGt4<9Km#=XKF "_Q#<@K  1lBkSLg?0{A~O?cvqI%4( 8D[gAJP(!D<"0 [؉8 i @y \"/C$:P+D(Z'QE,z2qc\G6AitH/1b8;Q IBL"Z㏐$'IJZ̤&7Nz (GIRL*WV򕰌"`.'91 `d?Lf)`eΌ&(PiNf&{ILm $ fӀ<:1TsuK']Oۼ& ok VvWmmP @Pn1pv`P wCfr W|_Ak_Fd2dP{- dV>JAw ' RAh & D^,\U   V80wJe{dUg/+梖4b*{pCZۆnOPCK! x-VY @Tui"'@f:% "\@L$Wb`*6cH@/̻>]Bi@&A M4n ڶ8:D @/}K[nag.:v,i ˂ giRA @x)bCv{{ Xw-L[Uh ֲ8@!Sy DN?q]LZ"Vf+Kzm*%l{ m:nN0 X@~/bWc8cIPz2H,`Yxٽ}V 1tW a2O6̡nNiY.`SN8Gc*p @M:.>O˒w|\ηΚ?kk @{[AbaᆒX 4>D@80+[7W5]ww Ε'Vl [ iwlCJ[PԬo!M]p.Q?DG>q[:B_gKkkƿoNt`p~MQ#*9~8(JCo ~hPfW$XP&xJ OEwEN"Up,&&g,؃/I `Nm&U3XnKF^VMREIioVh^MF`5Ex_Ir dgO)q]ddRk4[M &Y4]0p}^p@cU`eLgtWT_0VczXR51c_Zf^() wmoN @pmIGv eI&Z'%od`XP 0o]U\gcOt芖UF_ ^8TEVx64rrf`uJpVNmoFT^G`(k9\6n 0}T ׊Xԏ_37n @LnVZX p^bT@}bi'raѨOp1L$kep g$k`'yp)IH&&H>ZEd5Y@b ]0rOwƍ`]؋o$0l crO`͔Zrs]5Zq]dy jvИsEWvnsiVP gU8U|Nɘy%Xw6e5&R@} R0]o(@^vt{u6^(ɛg%wgUi_1pyd% wwc[i<)0ryyWd.Dv^Zus6cPb3F(驞ƄWc|YMU5Ye2)ahtbEvp_mEM@LNLML@0QQBP|ncY1|Pfz`gVpbj]IHUvapĦpptdwzud6|N~ IkNfhyWb_NSƙG::!z44P^H"H##NJ>ըjĺ>:OZ3 5Hj֬: zruڭJzNZ:TzMZ jMZ)8T_Mrڰ;[{۱ ";$[&{(*Xк4( Iĸx-z{kU gy s;{HtUcG۳Űy:nRxP`YxZn/gIwy"jgzWti[eqpJrKˆs@y+]b) ʒt[tKfeoP6XeAk`L@[Y5 ~Wel3Xh`JKYw$ `lz֪[˸ av{VDOI.ںȮ]ul[:[hWFaOg^uKY~ȄcɔeL;lwKgoMiQXcpx`p忥zvWcU盧}K~5W x6s¼'uL ýPKLbV~tCYV'hMGc%O[p7g7LmY¼f•DfeWikV3 \jƃƃq^ɚɜɝ̵hY+Q|d9MWyvv9h7ruZSXFuU~G_lj• _df+LTq~KV譽c\/LTVo^`难>ꪾ벮>븞ntzƎ~NNӞ~;מY~۾מ~>_y^.^ ? ?Nu?n&/ >E.#_3( :0>^D90J( pP @pUSoWoIY_\@p @ﶮk^w?_8 p>b ?bnObs  .,O?꘯C_T`b~@' p*?ͯ뎟X``b) ` c bb` !`ҿ¥Ń & &&&b,)Й8yՠ :`(A]a`pA1 x!)`Ӏ26H 0(@I]54qiD xE61EʝKY g >}\Ƶׯ` X0&6E"9&xaPYCmup@Cs JNFd`LkܬFƲz#y1n%YkCBCJ-8n rݒ&v `482L ڹ{J ( B  @F>`1 zeAAbg6&"v@[,ͱ֚NTJaVHUbxAV@;`ckqbl hf,0b(ف KB@6 ,=[(F!W *21O^`'7 G b@~wdII0gQbbP*@EPB[$N!Ҫ& H\-|SІ=*B=j4"Z8Ṕ@\(ҥ3_jf8VZ%j.Z# jRG§% (%6iR^z|h~K7BF혤."`Ŵ )tqFk(W f6qL?.YrrI4lj20$nޣPLƱVFn>/Ugw'dPɣAYDhV%;_k՚%҈h`!"$V[쓴q) ʾIHs*3BRr<8]H/WR ݆hpbmyvf%?@w% @0d%?/op%xgem7,@@D6Tw2Z իp-}uw这* k[y@Gn'$I 5 ,AL< &| rQ ! ,hْtr30#h^V mH' I$ B.؀ 0tL+1pHh + V@V$@ v#L fY(T ?o 'T/~"]~_,q5ё#Đ s8@1d g"a@)ebZp&aiC ]@HI*ZBqIg:$0Ý`J6 pAĀ<zbs 3Qx&KQ1>(be[L H)5\rViV6/:ِ,@K,`tN򗿳Yڶj ~X6Mōc%g0jP|,d %% _xWG?HZ"؛敁;:HꋐtF2Pʻ, f"BԄ"Hf)Fy$yabcQÝ\ #݈%KE4wC`#*ypL0N("QO$@WaYojn DU VǪd @W4F TG{AN{n<@G}T^-+6D[)fk  e~F9Ջ _F殄"=^8C{Vί~D[g.׋%Uآ8;*=VS 8Y5@kOk_AK"Uv{#o-Xaea[TjRq|֦pofSBauOޚe ChgvraSd{7J|8x)e YԧN&Y}d#]&ƯБ͓#G74VzN/sH ja@3PL|uW4- x*}x@x{*;Y ('/LJ$|6T<^Da,7.\7/3-Y?-$3_( +IlЏ~Xޚeo!O 9aH"-0yz gEo zCM`"q!'1{|hh$8Pb$(`@CxwiEb+β1WKPxܧƊ*H.K2'c'D~Dn%% ;5+PcKć0 hk(* Y0#Y *]ȏwؓ6'98 DX߈W~#tgO(XzaMS+àU{r~i  蕚` OD`IGvz@AgIX7ĄC^dg{a2UF&`GҕvA@q3$ @gw(~d3) ws[4&136OX9V &c&@$Z7\%&A32"z'Y1sy9 *&tُS'Y&a13!#V 4ڂ3M $1Yzge gHwP*K&็}9d4†!i D,v:fiwPLw0*APQ!o5, @u& NxX>wf q$& u@$X&R"R1K2lـVd`^IA)QZ;RC} 0l7A Wk"9*_9 ), p/2hdzZ8*Xzuu{zdڬ_@B;D[<@FL۴NR;T˳ :[ZD8\;d^ J[jQn+W btkg x;uA{ΐ|P+ [=Р˷~8[ |۶˷ { ;n붛 \[[ Z+p;cP+;*;TۻK vk_[A5ͻH@ LP;T˽㋽[. K Gb`; [A 3;CD{MkbP;KP{A| /뿚A+"гC[#I[;=kD,̴_ b?{k–`@<9,>4XZ̳3),` kbp<[bp+K={bPB]\Xeg0ƌơKȁ\ F:@;|.31\ LCF5`F0GCƈL\jF= {\0§tLV\ c쳅̱lɘ;ɟL3y=_@,kG?,F.0TA,o쳑K"\\̳FA,,K@3PEЍ E0;[C+ƨ-t= ,@]gD B50̷ RK,l(,.N0.4n˳-A:@ P~.P盾 ;-y}@+K"@ĩ_;>nbuw3nڄ7.kO싍5LSδV^ n5֫NÞK;>A޵ᾣ>ˮ޷~;Knѷ.  9? [~^(?w*,.02?UW{ֻ>?u@BDF/H6pXZ\^`XpbhjӰnpW Vv`O;PK=71H,C,PK:AOEBPS/img/xla_record.gif`>GIF89aDFleu{@@@???2:=Jlxࠠ``` 000PPPpppϰ___/// ~ooo&+.LW\OOO%6BE!l,DFl Ю  jj¢j l   jSÎMQHy#JH *\ɲe4m =< B6f  h`$?iS@ iMGh4A5 \˶Q zu7jg2}@dnK8  (C :sx"QW `.'a) d;1A`( 6X'ɉBaX}KNY0dx.ɠV8%&Q 5+0$o$'0ȨF{]5q8FAgP{H2Ncr܌ n!sxD~$B ZY)7&So8:=a=D9T B 8q#R hؗ#6Ǜ}gIZV B; 0$I\J@ ,n! )$&9n'6P82$So.{ܒI>g0A%I 7T5L!tBh 't,mІI']P+4N(Y~)Qr5Iʦ5 )F 1Ft͇ Qg!^ǴA^!f #%| ":#ct%&4ͪVψMFD'916lP0SH6I2Do2HIF r2-l q$24g"9cLq6 0ۆ>QD}-,"a#WVGKZA`E8@LNøHpxB@8!ވ`^04HdUpĽ .G4Bp nN1\|vF45 inԑ9}ˊD  5K!Q)CZ+ _lɇwע, x Kru {{&aI?D\#5:2%R,RPeO,\<&𝯔Z_FЅ4W8 9Zbu^xeOD(||YY58W=@9pX3d,\F*NUBMC/@؋2Pha2@R| (O 2#,Ոk$e: 兢eT"Œ.뚄{2ָNC[-ض2?]/HԔ #B[;Ҧ#gn؋ l"2B{6k=zTv+l{ue]WCo{\kb [|lx6, 9 &N𩇊p6"c􄜧kP+w@d3 kj@<Pz mpXCDoZS! |]Cw)6!{g9K,Hj ?  ?j@ʤJ)`!9j m܊'97vYÑe^#׭Ȗ8XFߊq21jSZ A#P1ڳɱ[jIL5{aY(|#8CZJ ?Z: ?Js?J/k1аPZ1qE })W'z(wں~(FQ[ggٗ V x~1w?zG~xXg]-pD a{1C?jSr+ !o+`jˏ(I5U!`wt95{GH':jY`T 6pZ댔k J#j!#p>Agðx#K٧bdO{z{tuXL5i4'cL'pY=}+I팫əg̅p\ xszg[Sh:] *׀؂=؄}@؀}،؎)mi]cʙ縪WuͪyΩәXϽc`]Ћ]۶}۸ۺۼ!J;=MDUʽ̽E==$s؝ڽ}1PӺUQ{pg(,ˍla, ^B-.php >>`SVފʲ`kf]ߚzHM*^P^6~8 ~: ȗסg%l)?zL3>^V~X@BD B=^~kPNnogSnppf3 tkiQm>^7..]nw GA=AU}^>nσE|Q~ּ>uN긆1UɮNm.~T뺎jTԣ,n}5n,59e۾4<0^5Nnrfz[]9'zZ: Xl\K/: = <0?j;>Z:* >.S6K!4\C4P]vcXy ^y|{Yy 6=/ %2)0-085p~20-2j r+Xaj82*j38<5>*0=/h*0j2<7/j/53/*j:hill j lj"j&i H4(h@"D xp"F5}ӰЀ5+>5)Dp! و! I &ZP83 ̑&nHJT .j5ʕR$^ȺKnqIƌ^1jEt R֗\nYE2Ԡၷ"7(#5jԅ񕴚-u+gɞMmqV7@BžM͆j/!Hch# @8,+kYS ,Ҩq_SZQeןLaAi@TX`UXiڄ 'u!#/C^!j]rɰ!8Ih!`X">< ;:5!{!2R l\v9N9ipYnN4'h7 `4&`Pojd #jT_4` igx0r!* fՃFhI%3f!c"=!]}-Bɭ32;$ 8v"eHFɈ< &%Nڒ-Ҫ ^+v9@@kpZrv 3Mr 4w.|PHS0J§'Ԕ*_8\5I|l*|*7꠬:Id< $x=>kx ~-"@}c`cŠ-X !:mz=>"n΂A*t"o;m2[3 3OWӰBV71 ')v2g5hN D2̦M6CV"o tقI1#7$S+UʸջМv.kkn4<} mUӹP+ 5ŀA `C>׸Aa@*yG(C%4؉ !PTt4kP쬂3ڹFCrq0Bik2ą UO/j &COY'"VCBkEz8x@7?,CA#  XtJOQ405"1@bT`jPHП@ZDupOs  LܤV(q+Lf,U0xa`1D \ؐi= ]SF aD>(Kt-f4IOl 59Q0%s‘  ƜFݟL:Rv%j`Nט-2,c%Z!'Fz4dCa~57fiSPe‹rv3TtmB--ԮpSͫuP[ (ZARx+"문:r)7 (SY&UYkU(`'DZ֨k*zQRV?+Zh)MjWֺlgKVh1AŬw Kɲmq+AЍh++AȮvz xKw*~&Wƅr߻ܩ*ϭ~ ׽…oso6W*}jLᨎ΀Ƅ1a E0f $w8o ]LcZ!>5`#~pz,&9pe&8˂XWv e SYŜ$YB(Ln(gπjBC¡ M5daΐJSv2OhxӠGMRԟPVդVu@GEָεw^Ml^k>cX0@ˎ6:!j 稊nkl(1mud.w(;nٛyl|b{H&[{2§5$āoZ&H]$' |x# >qƾ\ 9pq|whѮpo[4y{}. SdË}9y5gi5/5rfɧB5`iy[>$CYaaC㰃x znr3uN:r?\^aTqFhҎ_li^7f{"{q@+Yh Dv1"eI-6O }Mc/DS~1Mߝmtk&mWNإ?GL`?0[OŁǹq>`Tw y%.xD2" q&Obh0H',%`@+)}hm|0~y Js<$;#d 14DwcFw%eg$qlgT`TQ'x;3$3"3;V,La>XVHAІhklrH&S*&~}vWyuw8hxsv7>ctF~밈m}sqv=EXp8rcIXQG 逄h%8nҷxeTxꀍˈ_t |xxè p X86ƌsa>Xm*xиx`{8g[3G  ^`Ymv@Ym8|^`MfD`'Ym "609u^>@B*Ax55'9q@Za SZUyT WZYI ]Z_[y aZc)eikZLiqYGmQc|@P?K )t{ٗ Iզ؋Yty j@֖M1j0 ky%s8Lۖ ٜ)iBŹljٝٹڧ9IsٗB7Oap q7;6Zrlwi9jŠ pըyylb&S YA/la2珲)s  0w:KMI( `  Uꠣ`> re 2l02:՘6:qh٧3i39"C l0PjgwSVJ xy X:: /qبj G9I/꧀ڗ:8:PxÎ0GsOТ wڬ* j:myُ zjl Ng 90ʔAP|y:o ~plp氢pt/Ŏ rdjm} v:[|/>=x`V0j i*juIFx$*wjԉ:QۙןАlp* &-Ocp)ڴ?;WV)}tԟ{p`  93ן$PƱัtUj=[uxm5/FNJ [Zr*u|a ູ'ې Zҋ X0p9 &!ٻIUۺ֦8ِ)kطx90z @PkKFl!ֈxrxO[j6; 0˿0;ӚNԛXf`죞aʉ`Dr @ɉ[7?ʩO;L0<'*NS6O\V*DWVZF\d`i4e{h>jrnvsYvL754l{8[|t ܦ됮szʢ7{ 7 qwҺ<8ʖXɕm Lll^u\Oбy'OnX|ͨ7chs*΢ۨ'[j5rr @"jϡН6ПmЊ PM e)GG N͉ m 쑯+n` `& [$G `2=s탥`2A}66:v]V\GsުYL) ?;`Ks9*;mYvE{稔 ><fbhjʐ I`;>Z]=Ԅi識,FhIt LK>X[Wkj`ij+jGFR L۫ʯ0Iȶi &AȊǴ=)ͻǩ똸sM59UV  {獼l`"M{y-ym& ڨмw`N9iըi} ڵ[ِ}VH  w9^X]`:bxQrV[p R^p}  &Y*8@ܟ[<Νs*AnH[p4u ; prJO{b0ܿ=,wOA54 xs բO)/ܹ^'£xy>齱}NʎcȽN0~ؾSo~&(k و^ف<{^szG^8cb?ʾ8uzɮ zTh!HT8(.?#4󀜎<_@ĢjyFmf'GLq$Tt.tS_Zr}BW[(/fϔ~jkq9?0^ҙI~?_Y`9?_d?_(@{N?ρmB?_jƿvQ_؟ݮCy?_oR?_įkl#ôͦ%݈##Aͻ` \Ȱa|"JzqpǏ RIY ؐ1˗0%4IH(ɳϟ@wVk3ѣ;Up!E PU*ϖZzH`ÊK룲hӂUȫڷcʹI9(߿ioÈqT!ĐvdD}I]3f͜MӨ;R6iպ[LhaFǍ\)xn;Y국79gtbz_7OG#Igd`z~1yȀ8)WzUh)]av`|f_-"~! Ǣ!^ZRc}%}#$"""17c!?wMQ7e%%o=rY$xGYy"IBxe!UweMgysY\9~'(='ve8(uh\un. ٩$}g禀F)qbp~2J e[ZRImj[zb>*F)쭁km(N 'e>.?Nb>(k wknn\vm­Ry6r'xy;ӮL ٰ!e~R~4%#LjR`̣(;M|$Z*uy2nd^)Xbe0Jr yNŬp0R4Q$%6K>s0)Dm14{I59t:wOGdYW r L(2':H[N"?#{힓}:1j3sKc~( 9S1s)<SuԎʹ)>' NC}L ? 5[&E4?)/LZUUw%Ԡ%F~GiZ9y`5ej%I\Bk^uWO՗YU(JVIa rjD[Ϯ>%-B- V̚w;54TyVT ,N*X, pKکMp *V%TsزǥLb&SFM`f"41yUe|{ Y{ԺV%LeF:PG$F9"*aa>ʅ=b]VF;".1g"*^WkŶzCjl>Guql7AN2Cd, t1M*wJ(Kc`Ɨ-G sL 5{f6 f6u]q㼛9wt,=.~hp>4EmE79{4 -Pƴsr.U=VC095Iizոu#=~zk^zV}eDǖHlf v1moP"85k{scflc[ݦ-5{9ސ ^X7, <~ o;OJETS)>t#//P<+`L6q{ͅ (Ṕ!̃ Cv'# Hp)[>pLPtjh;KЁ 1n ;BX^3b%8 o#IIA;VF`@ 6xne? ;j0:D /?|"*0ƻ;%X.s !@|@5Wڎ^|` 5_Ʌ/ E +zVuw6?p}Xtv0{@@t)pt#P@z—xWa'4&xrXv5@"@+h@{kvA@ DPf Rtذ}W $sda8!THH%"Exk)P90uZX0>ӵo%8/0|(:00t{a}P"tXSX2 k(~ƣ 5tt`8t81HU0̱`ky4"22{瀞A)P I:W3ȸ"xzt 48iۈ|Z=@b%H^{D%̗gH%qs@}Fgu1 `cXh蘆Fݨ R"Dj0CAՠppFI<@0!)"٨@4@81kH 7ẇxE $ Ih'! vc'3prv4pxHXZ)vC"d'T@itp{j [Ci8! QBS#(FY{Beȕ^9WEy`y0y@agCrH@v@mƟly0p x{G tv jz ! ti@ JJpA`@Hv|> k/ZB aϗu(~DYxRI{^@ a#zqIgd~dGA0s 54y>u{*׊t0r:~w$~Zک 7B8J(tAx Ɋ{J !|ՀZxC62Y qWt;*osyC>QqC (AHA(5x`j> GC8 (Ө,@7Bt+R {P:s'z&>x%Lagpts 9(1 ֩s/X( ? @k‬ؙCp 7 Tkص3.HAZň1X7䲻ǥȺ:^{{(H ŽpLb:[5F@Hb(:>l H6ȷwt ل64@RrA&=|۴qH0X?sF:pTr;>+EZ %:Ȭ)܄!t/tBɍ< 5B^x8XPp(%F^uD7 ˜t ؠAPC=l,'{``0BujH#DمА Acy\87{з l 7?+@+{QKy!)0Fa8&uZEzEֽ^{gS)BCY>1ԸъkxS>x~pnHՙ@sj|d<͙0lI jϬ 5_|<\L\ 0=]} =]m ;PKLe>`>PK:AOEBPS/img/xla_coldesc.gifKnGIF89a4k235@@@egj2:=eu{LMO~&&'XZ]rtw?@BР```000 PPPppp?IM&+.Xfl~LW\r ￿???///___OOOooo͘Q\`6;>IMN<>?xBJM]inEKN.47rz}"')!k,4k  "k!"Ǝ  Ӵ"k@R 6QXU&͑p<e˗0cʜIH84<`SC\3(r8UUD#y . hk ٳhӪ]KTGA%18" 2ҀX ,B_SP,!9udZkBZn(AI![=LZT)4o8ʲsB~K, 7fKؙ@!w׀A̦]  0@' }H0|ӒCd"   e=At@ O %'BkVxؔ! 6YZ d9 `7iHL6d=M  v 0 Xk !֔4%!<]5ܖn).pi Dؐ]h*)$e!CmC9R h؎W "[TIv)UȚ[j j88ؐhk6 $(0Lh'e  Vf$.D:;ىWopk Yʆ@_DxJ:Ax< -M:Y`LoPط@(A 80;" b}`Hi;U i@RD(n nѿw8$80XCB g t$i Y /lȀ9$F OOd7INsY'&dNzb{9aBD6Sl%ԢuB3P8(ٔh?SMqsċ4k42(J^"9TF71 = @*(!RG%q bb~x ĪDdDB< -Ty:uNQb1x(2`TM,x3UXW.CQTFj4VCpC]j*TfB=Y>P8Ŋb:>6Z1*R-sj&Bڝ{JTVQUkOM5mVY=T8qmunc`Jʈgdn [ehD0c2BYSV[t^&9fKJCk0uK@^1YoUR@]B=f([/Bn%{DBȽp4bDL ߩT>3n'[MnBPõJ#4u5cn`" 2^RS!vO)WXndڰyM"8"c)gv*Hx)@"" 1Ynkh,%FDh(.DJ)~:!5d$G agYu8<[fy|$Q %cUrcqD2rSW'TH&A]e*ZĮwcYC.wde/ kP@U%} oWv&\sGAZF W&^ ]ryf q`_&!m{fr[o!:uys7i+r Ձi0]p&[g+~ 6}+  iw}!!ð0*1w-`>i5XbgOX h#'%hNW_Ղ +1&4c&7P}v( dDSif c>FO@WW%8y"}])~jjsYWtGg |%yeqF"$Qr@7LwFk*aTcFɐjD&cD])E%v}Q}3/ 2v-zvE! gL1'|X&PS3ċwtgr }RW0'АҖèt`1&B0k' M8>E.] sD@MY 1=`>‘w%P0:qdehFl塅x{ uU7? 6`*&v9B0VZyni1n =r5VTyX Xi)1Y]i[]pl'ylQi;ɖ0ژ掄Dk'ԉ(z酼6ҵ_Ybe[b@%6L/NjIg8{Nme=!82OCoZ=C/5{YAS T2{UIO!z*5{dPP"+JyCF4,:{Tr( N e@ DZFzHJLڤNPR:TZVzXZ\ڥ^U:dZfzhjlZr:tZvzxz|ڧЧ:𧅚}*:qz*Щ:ZzB:Zz:ګ*zȪ0ZϺjںʭʭZ蚬ؚ욬ڮzZJگ;j{* ˮ ;jڰˮ*"˭[('걾ߚ  +yȕ R|{-\,\Ω*] 4 f$ުM|0{j0.㹫6ވF[;M\ ^T!.L)~y/~N.Ξ潬ӛޝ Sdz* >.Kp=; z  9ʭ B\1^Ŋ=.ߪ,̞0ګ\M1̬ͻ;5.9!o>o?-{k9ް.ͼjͫ pf<c|[~c :>۩<,RӪ ޾k _[ܝ*Ɇ=[şӫmȘ{Æ.OА]s芞ng^I,]+/\ ڳߡ_, Ͻjjjj j jjjņ՞kkȞ   SԳ]􅛶H .PDP$P5Sj$ 'JcAp!e()'BJO6mXԡߠ \ $W0> zHEO7H=ldȼ!v WVJ+JS)y8b+,> AOok WZEybn0`׷!-/pe&˹Pu}uٳ&(0O?I@;D'A#5ك#@0amLg܃@-\K u\GJgȶg!c ,.]CeA~FHMX'PPA# y}'5ГEI̔wi"X^YXtičJɍf'Dp/TO!9੧BP^ v%*+ ^ܤ9b6. O&q} !ۗ9z'ȗ,f+bVl:抲  `/f5s%K$zS"9t-g-*CІ+-,m1ۅ b1!.) ݦSap˿[˹rf-(K.PGM׮RWmն̅\GS`}K.2mvZڗ4U/GNp׭mvz~ނۆ.ws7 y߀O^8'^y~/N7ocݒ-zy:۞}N;خ.꺫;ԕ@ Oәam{r8"NFտ'=+B|d|\ΰS>ekoK_b`0Q-j{ȈBH{Ol[zPE!@QyPd 0 !Is%*.=. ?U qN{Hal%عXB_YbBļe&Ҵc^⫅(!k%is!I\†3Ȩ脿v񱁁C\uGQ]4 Z,x% qg K(GR̔B .&Tk#B`S٫ إqG$l^ǎC%T'*@⌘u@bPg:@ (OP'%Ld)4("H:@3/Rk㛥M?ȨČB%T$Wx{!g? Mgt)R.  (lړ;/'?CӀ޴1e~S6b#VR]XP !*"L(U`~0g:WQY87xChEbu iFޤ@x7o\ѡT?3#G4A|i"JP" }`Ȳ '"m"h{a&u`d6K[gA;%CE`SYOK[C.b(XP?ۘN5uq-w :jہ] :D 0B\ u E] v4-B9tJ#d'{6+ j.F!>k$$,9Zy DFP`(/եDqK| ᙉn&Bʘk quILב8)v.s>e%NRʳb*߉ޱEDbQ)zHuV8÷DҬPk `zE`<$Bb#}ų0=9\ҜxB} (x arKH,ƓW<mW"ȼpWeKs&])=-̴J'j=Ei4+c->3%m2-} "bJyddl!Z47ɉvJDAؙ%R"Ɏ0OhsmCWe$.r!\b,deɶ$+Sc;:L @L(11b(Ѷ)ds- 5l+q C|$[r&F`\i$=x>f7nVI (@ Tcdľ{X`1enbq¸ѻK-Ar {=E͟H[E~fA}qAz"jxUPL?VݪNo}{oS~FoxR RM~UvӡyOp^b45ʻ=UW O%\z4]%RY*vQ0Ϥ>q $W;t f\B B(7!4C%dAw`@.)I 8=w8X d=HcqA4PU lJHiK=& @Nh Z5PԅKW`XYc5)TJeahx1m(#9ȆOrht+S#ӀJcH8jh31h(@pC͔+?0c3ؐ1+Ҁ`2#rd IaapEq1a+P@̣>\A?j+4U^( 46LБ5 43`  q D!ŸZ$GȋRSe px H ԏҎ5iOH(2^1 #6glDRs Aא  r+HE?Ӌ!5x%4$I,80s䏵mPb4 77$"8  h)X686 4rM ]!g)^@8kina%g 2(' /27đcvUS}*+Awrcd T!#SWFA)E .{,eU CiZSv+e6P ʼn `*RL M CTY' Y\*1y$9TTͤe1 0rQ pRV2Bc9^e;i*i'ə a 02M5BD9K]%)bBrY ~B I] YI.pbibAtx*2'~ȅpA0}ΗpiB0Pyu2f!^bd%AN6 I>s`/GTa X T+Ps 2耊$Bwr-x"r3pXy瘜G"QP {1'eceN;#V؀NrFmX0ey%ꧩZ *a b j OfY)CJjf}z ٬v򬉊\Һw%1DwGY2D/yP @iC&Sa">8-4Q U,ez_9Du1gU 2a*z(=qXS(zo!J0qbFl988qA$z8 cuuxϙ>G9 Tatb #&in9f~ao4q  eh) )$' pNdKQ@r)?Z2sQoIKoN[` iÒ0'a\`Dt؀Gv\h!O;9({ D5 zWSWL w]̥a/qvȐ gV{e+Qqqg ڻ!H\BJ2`s$C`' qq BvTǛwBC@!`+&K's*A)GFA h*cf>؉:(mkpl*P;אyi*,W.e2֛;Ɉ(am42Y5.&|yȠXAVv+ OƀâYP ~ py!!AH$UC҂e M Vl1vGW4a "%{c|"<0` k<U+QgPUE|`/z u&9 +` Ů , 䘦 !iY y/E.6,RU$.QCIGy gR!pL\Z@CUV_EvAHEj yVGI"|n?i~^rx [WH7B|0w`U,)Ӆ`:sDZ /vytx Kӆv OUԂ0" [e9\R579] qct!` Rq zK 4]~SӅ @DGs\KX)' X2Asܱ $pL, ʣ)5BE#* Ui0!紺1MȢXQyIä rpKD¯(x.ɞP 8Rq \J)8Aؚw 2).Ҁə*A**rG ߑ21y!Yvqq*^  /ί~ϟLm!ޡ)5l.P>T!.-" MLG^E) ŀf`0)/Cnd0,bK#9r2##00+ ƒB@5эA BsQv<:xȕ.;> N!OlZW ћ3A[:nܗvr{$`4499ކ>4Nnn}ޅٞվў+㮅ݎҔA:b׆>[Dn6ZȸX^ T&io p'C`x(oC,/ OMH> Pg3aE7E:;3QA>}*y;C"9a4HHx1ovxx3(O#! Eg-Q\:~u>& IJ!a:sZ};fxik fIH8;@r$С3j._`Oz'@`0#`p d!%7hT i,e UA4).CΨ \ U2 i=ni@e_x켺e)w4_lLjj jjj jj ͏ăȋκ kk겆 tH$T:z[X))bfE 1頥S Y ȱe]FhE3zsӒHhN8ΞHTjFzC&EO?5*yp៿HI@uJ :<q?e#s!`KG5u+5 ;MXXHwvۯ_r Whf,)4&.@bI$OIeRѱ3uW A vLB!BU@"Hp*@ @H_˃; }H^_NT<(kEz%{𑔞{s_Cr^a|4b3(( $[TpNEӋ Ü%dr  N6@ I$aILVxH:sؓY=F^)ZYV"AH( Adgm*G cj&/Sl&j}r|\FiK D-oVF1Z٨š_)]i祧Y+&:q&ZI.P$ҥթlVidjːx{,n4m&կu羓\{jHln!,Itنl+1CS [ުs˱}\mV[K%M b 'ODz:rҤ!,+-ȥ-X hl' Siӣm[XVt=yLIyL1~]ҟȤ<=T!IrJj)btIg9.CLdZ$a;?knd4]iyn1T$8: -RҘm _P QEOUQ5jW4۪&٦2&ްeի&vm  ҮbC$Ҿ?\+R 6z/[ªyjeDuV=jn..iKZf @ uiFw;ޣV.^lHI+֯ R[֨G]K]Lqepl%q?L(UJܯwX5ms{^VC 8/5$$vΰ7{8uŇ5%v1<Ưq<ؘ@qE<Ưc}&;L *[Xβx`L2h4p9x>{mgЙЈF;ѐ,`EGҘδ7iGӠGMRԨ.u&-TհuEָε]׿@Mb؀f:@Mj[] p`C@q;(׍jhu-xF6oc,u׻[ԫs݀doǝړ㭁O|0xsW7"9  \#7 X T5ͳjwO>uKonSٞjrMm  @£` 3 p??/yPKuoGOjz[8ߝ珿sG=s;z/{W}>Gx__C˧G9ots>ꇾҙ{Y^"`=7|hGwfrq{{Wrz7x}PxwGw@xηGn*ugT}wul{:Xu Hugxwwygx͗;nGugxvHmG.G}I-(tgxvWx)zrYx oOws9w Hw 0gvDgt7jzXsv˷wbGvWyȂs wVv7ׇTguyyv}>w'k~tWyyRȉ+B7`f~V[Xs?v `Om{$x؃>Ggvu#Hwgx|s]vw#~WǸ+wstuSvsh~xukgO`HwXXsWOY\wHYk#Y̷u%xw(Y'ϗ&t7v&rHu(tE(xD)jqus먍.E9PǐH'>7`GT7pOyr9-ɅY )ryqkssh7s'9Pד:G>gpy)sIXBg1ٙW~pZs7Fqs5陮9j8r;Ysiɋ͘Ĉtvٛ&:5YqP)qRɈpXYsrph shVpfYGB߹~w1W'|I왟 gyq7Gᘗ''1 '1WxGpqKYqvr7'Zih&)穏6:c 7'pq^qIRpɭ `Jlo`פ*گfvoijm j\m;zFɟ6koĊ{m n#[2Ym'K.[oކ86";|j6 l6kFj+n(60F K B0NklPK*+Ԧ)G;P K3p09l4 OʵCd[7zjlVw0p*4и:и˵2p>{@P^*\;2 jjK jW l ;k+Kl9;KjZjk3jr jGy;7P9BX{ҋ6и9`6P5+&xk[k`ߛkP@k[l+k:`k*[g9<@`99jP 2@ 떼۸5\; Lg"p-8ދ®:=7>k᪶>Ij[,k{Z|KE<@ő;{n*+;k?`Olj ø[n7= fP:`@pa,\6@j|Dž>p2iio;ʚv+ʦhL,ʃz3˲ʏa7ʈJt:520\|Ȝbp| & ,XTPǜP[\d<DM@D<e@2l+PLy뻖iP} m }C0==<04J0_C& cIPC8k{\Zp'}>@-J0FF(>P2MӠzK==]^m` mid Ra]VXK =v |}n S qͬBAE< iאВ~ ل=iKm؇i0FH ّؕ-ښ}ق٘dٟ ڸۻ ۯ-o=ӵ=۩m׾մ]ܑz)` P m'c *`(P }))0]m%-i%)=ٍM݂j M&  F]#`, ]>m&%%&]n,.+. d m,@>=#-nޢM- {=,0,}~ l^½''N.P+RM&`$(p$`='`c,+`JN' `$-O=Ҧn #@֍N'&PPY^Q>#p%@ޣU~M&)N~(,nC.un\ĝ +0R=+ߪ iPi吮$+%iJT* qge~T%`M0c.MO-,Nnn#.O _*=} /J>/o `xn6R] ֭­$@ҪNJt?QN&p+,q?Ї^( /Ѓ*خNDJCr#ޞg''+%^|?/-_G> ̯}}}-PE}䕾)ob %i ii# $-#i $)-, * k . &i#+i,-߉$(+*%+#i(($,.2!1*E `PmSH⻀đ8iӊҘ& |#qhԹG.Xh4N0Нž)]ʴӧPJ4+05F adeA Y#Z0N/_V{ͦ QR% dL)z b@o*JpESD-͚nJbR?zJ0d!gQNȓ+eН Nֳ?GRޫ+3Yӫ_Ͼ.>ֹ^~RRh&^|Zw_atMxx΅ (0huX݃*bOh82Fbgb2%L62<)SHFe}5>`zeUcWe1ep)cXgʘkb&~o)蠄Ww"{اrdVjRy$)ajꩾd⦫vbFfj뭵z"je)yjpj!j!4 )Vk-NȬN K䖋cnn~`]k{66讀:^p_l c̰)4NZ$3u~~q!,Μ_BJLD q1-Իl.sG>.K2[= j*Z щMm)=zt^-G=kHF-ャ}6 ~Rw"Cy{gyjB#$X(+ˆ ڼ$ em3?k7tr.& `w>ީB:p!ЗY 䔄gTֶ#ke젯;Z=Ҡ&PtPd N0o $T#D9Fh j9A RL%ʋZPp0(oIj+NŔ`<H  -.t}/:1\-8 b% 183j]#X8>lgL$#љ3`(*|epd QQlP(PH)PP"."P R!Y90\&IXG-b2i(*a"~)`k44uGUp\[%\r<2sMesoLþvgA*'Ι8uva;#yQ`)^!r20q3@b'%*Fz~g/Δ 2, 5Ey9R_Z<Ҩ8 3:40)zY)Ke2|c'pH9X 5F3HihJ (0^JP5RcAԯ5I +UyJ 6ND ҧX ӬhSC1DT3{0|S: F'xICUcIJ,`m,ސ=/Ev}XicGoPKV&b%G,"C-% "CcI)Zպ vH(*d_ײA2L{T󶈾\, 5̐+tW=א`7- };WXvi7&w.asO'k) ˧"p!`xsbI?^jgFM2jdr4G[IJZYm|Z-j6z٬3gIrxpg0t3gz9l~tlV8? !*h)-%[i3EQlg].////;>OOO2= ooo?EZ~gs"-Pioُ_دM\9K??ǿ/O?y?V]o?_&._O}o/R]??/tOBMo/]l{_kno?bl?KNYkO[^_/FM+.Ofm=L/i{o//܏I[p/k_OTjo{~Or|o/O`y_ԏڟO׿ݯ͟OwĿo0;?ݰ됾̐`v~?!,W H*\ȰÇ#JHŋ3jȱǏ CII dr˗0cʜI͛8 .P3RigP @(A=JJիX'`P'j$@Q[Ӫ]˶۪^@t3&HU@o La`ya8m`i*^@`iʮ`pAj AYr8][9A zpE`:,\%`P1P"5@@|Kn )@*F%%x#6ȩ:P@A T9v- |w`LkVv `_;Ai:>Obb{ݙʴ;P!6F M*XʈguN!`3^hIn騢|g=EO?"YKhNS9>/W/io6D}\·;E@v`5_A~R&y tإRpi\$?R]5l0ZmRL vrr$b1%@CH*ZqPqB D'TAP&.5S*s6pƥ8x@ @ IBL"F:򑐌$'IJZ̤&G2 z (GIJPiL*W D؈'IYr.K]20ave0K0ӗ|-O9̍\X̦6nz3P7Ir ~L:uӜwy<ǩyS>߶}'@剖ug8fnI0ŨP|-G0]X,b;5*ˈkdZ w͋n/B,?+]T1$IˈƳ,J1Z@ƒFR[fMTYx9Nʊ]D9\mY6}!|kCzVa&ъKwx}H\+TMl}ʽs+;)9>V,c'ѴFD|Ud'rVKaG] kIMK+eYf%R:v'j/ +tRٽ5-r/eY]kݶnWmni˂!nWm2dgo[l ۵&-o!+ܲu /v !B;齯xa؆!mm\uxInH"հBZ76e0kTϋr:NIZ82zK|/$C^1nbG2L,?$-kal.ӬgW~u3;-Wټa -Y.W 3 Eyg>-e.d%0+m2 N{iٽɭ )[ &f;iZֳ~ܥK6`Gi@{j'nHmPCmH;k]@jT#s?]wnpױPnh1vJ#~ 5R/9O{ W&݀-Н԰qtI6PrI,'>,]'貱Ԉ3Nwȳ ˜p'>|)=9h @d~›NК}ޞlaP pƁKMBK>w2Ai!̼̝l`y;\> t<}<"A_'N8I/%'݂v-MY> 8X:y4lZh"b}iQ% CWU~#h"]WzP"qxbXdG KAaidu7;Fg(x \6mXH/'ye\/7U5Q5pN!T5AZԃV,{B7^Q)|WC^$0Y:#ovrd)ffvXh~Mv[sxJ@xa hmQGu%oM#h#2vDGF_n7"h}1WňMՈs1x`j(`Qold,1Y)&atj†Avj%V%X0ZIՖ5 @%7Iuq}w:{gg<߸Yh0ml$~/c+6"pb0Wwx&+bmX1<89uQ\cƂ4 g8{QGxl􁞸#8 i@e2!#tsVa_(z!R>)8 1ѓ& |B r)HY>6A8()~q'b.T_h)X8U’⎶BCv*$fWdWj){ׅ2l".JjH+; nD5–JRDqr#]I;{r'$yx Ӛbn1Z0ӛ/ ^x~5 h79FJjh&h!El8x~bJX#=||i0|AY r \ᅣ087 A{_5Ԩ?~r~VE~u"qY -!~"l$!n1'Cs'G&c*ʢZ^72љ qS= ч ƣB%9%n2WBizsxBtW]ץ!ѡ뉃yJBd I;)ٞ 5ٔY*4nk"Q_]{*걜!+ !*n?Z!nbP8 ^,)wE"$!56Y"wGwZg̙y%F:e:xvA1FJ;4{1 )gkyZ!}8AZ#)xԅ(s(=7Zѯb;ϩ }be| ltwd CKz9x&7{G6)\$&n5iRysEKD!;&5;"K6Z@K!!{RJy‘&gbw(7}y-@IUG]Ԫh7{y0m“ 1B xW+&K-ZNb- x%P[1j?gWq#{&ge,"#HV릴{jY,[zS rƭ",2: ~<|,>#pq)1NhoUa 3M1jgE"m-I[$a Rhډ  nқ61hJj$V:0AIK܉k'+__'aVfV:N tiKFka w+Z>dK`i:h`8ô9j,v&al՛kpudZ`5}#%̥qÜ857y{ {i:6BkdG^jEdĕbf? 5v+ֽH,J…mƏ&qc ǚLyi{^ki\?pwѼcCf`Z-^<Nj|ɸ$d N NBNTSHmN$PNMJ߄PTMP}ۤ]ZMVDVN'f}hjl}OprmZq6s}xmM|=ױx)8؆Iz؊m؋lPpؔmri-Tm ٚ oד֛:BHE,k0˫M;E۵VW-5En%3uMU}To25};E,I}S"9!N-5m$qϾEdޕ}EbqQwM?4+Q~8ɵVk!DQ̘dUj!-}&N~*NE,FX'e$>6Q}!lQ?./Am k!AK0-Dja ZndI^A`bg^#晔T!p>(~It?kxzyX1Q^I?~V>TsV 霮3#pn꧞N:~.1^sSAZnv>칎~>I=.ĎTsQnjn~#~%9A!>7._6\D71 g" |6/vH ;_H춌4N%om'H)͎^1H3:!O#/9H=7??A`E;.0I/~ VXZPZ`b?d_fhjle^_0Q/B5?7?Vo `&` ( >` o}_/}?|oO/_?oşo~?osu0SUP ?_$8PB* q*%NXE5nGR YI)#H%@KSy*U6U:ej)TP*ԩ| :Ѣ:s.**T79)Ѭ8u)X=~ ՠXڵӰ9o]klTjK׬g Ewna= Wm:gE ]4L.O8f L(mܹuoߦCɕ/8s詡v[^·k6q=3/#P."H; *P%.36:NRL1LESP)S(SBa]QFe4DYԱc,HqHO,dH 2D)t#dq%lH($rG*DRH/2(dN7H0MlA8pQF+ʰQH?0R@L)-2;+)R<{ 5Sl1/#TX UVE}Z_{=& )UGuIRN1aK5$̃N3TrM@Or4$U7s1,z|Wl4͒om_tv-`y,Exf/v6Z/-uO<=VbYD=Q56"RVUM5OLS*َ)c!8j>6 R+2[9T]ZV%Vxf>5kFU]mk5CjQ: D{8Pv7~| naɵ\6\s`~wG%tC*tP8#M"XbJ\2Mi“hp+4pA Y죟{^We/{\h^+cA`͟;1 JeSla/+ِ<Jy dXsxC`B`4C$JW/K\PBҵma#셺xxؿ\B cZH͎F8RZa KLbd X80jHZn``Fk" OPi TЃ 1Tm}e+_X6Q|yZ8 "8O DS Jt`9`"d8:d ;@@ƒh_<(!? 2Г `0E,^ѢӸؑS )p# $T G$'9A&`# TXTTpB IEP?gRk" @`: reVQ M3LLO0O .8(Ed XR0* '(]nK PT{i)m?pc)@ PJ @@T0N k@U#`/A:p?  nh@hfXM@`:LA06.B 1 P3t L`3D,go}[![HdڠHE \ ԢAX4w ] CȐMJW!][^Դ$o)RqTīLQP*68 p8L՜Pa'#V;ŷ^V~06\ ():BW{,U @*;p)TxR yj4+FWaܠw  & +@M4Xs X*9g!6CBk*؂QF"(9  *F@' tx +0 0(0 㾴:   ;uȂڊsRX8T)ȁ ;HBM)\*L1-.BB +9(SDȀ3 0p@KĞ$$@>Dťʰ]܎BpXCZTDcNdNOTP€X2Ae*8x RЁXf0IA,@ Q00$S9.SЃ́R.2X 7&'U@W8P%,XU@ 0 *ԃ<& FMFJFn HjD;ȁ/8;=(4T(\ P± (H,=8:002`+-'Ѐ pUx(0h:$̜pXHz7{>l{T#@P+02hC `(C  @#8 ȃ `*PI/!P x9ə$ȀG% &ʥ!M , \Q|8Cpb> 08 89 `X6 `pUO캭ʁ!-Ё1 B( $  NS H"x=X>>@ @+F>S 9诳2 f  j (>T  &0H*S`&C`%S,uRT`1 +P1Q\#O0(OHO3@:x (+&xȓ@),xA'(2Qa$N}2&'6U 0!%*NHm`cUl,&CSx:H!"R5`]N8-II@VOWUSH% 'h=;sVc]`WI:ēFDEuBFmG=Ʊ0p202 T8/d;<: rH~pWT"848t?9 (!w+(+Tp 0RXT0S3؅=$X/ C]Q3(s'#850P aX-H8="-DOވ]G}%3n0%` 8@:81HP PP0P %`:HKЂa\R`s@x0>!HC 4,2VŜ:'1:3Ћȁ J ȉ0 P) 4h | p `5v6 (&(@0", (# =L<fíGI$"  9c-((C))\ a h$@)@ln&@\3 -0'XtBx !$g$hRP 2k}qnEQidiz:>kD%\;>fA=n ` ^ H" &r!<X>B%5&-^s t!r pOt! u;tp#^ 'Pq\ ``P P B HTP$Ækf mvnvovp wr/wsv2s_wv mwx?XxpϊuP'q~ 0vFvPvhUuGiHggTxxxvx'yP_vgyO(Hg_yHp̗yy7TPxmW@E[onXq Wx'hG_'_+{ߪ8ж{¯{m'|~ qIw 1 `buDiݑVV[`b5oQ'g]^u&W1XcU!AE6Ix)&bJ)@)v 6$tPve_9RWpB*,*"=~)d)-H^9V5PTY'%eUiVu 7zתJJNcBH,-iSB@*%ɪPVw!Pײ(Sͧ6Ky$Z{Mﮗn{.U{&VJBh V%$i E P{1rb,Su>DdSr)\N xeX,;E* {yژr/ղ_-1Ŕ/RZUY(`TU?V*#Ъήj%+`eӚ)>ZR $Kr*k{4lL5Tgf院 -;3V6;1X?5VY_-w :ڦg%h3gJ!:Le[wӎ\wzi[x#H&>̤#r E@qdtYb@!W(J`]D'n*$B,/[$WHъY!>B-4KIP# pX:HE!7,|Iv3pXXfsԜ`((n@B&F@I2ԑ#H?2Os|C_?TD2\Kh>..gn_fzK>< YшԺeEQ[S Q G 8i9dOKî\k ~::gy`&mDj*4eҶ%}؁@p1"ȈDL5*P`B5r DjL [% #k@a g*ZYLtk*"hKX @k 2ipG9\\, A.rauXPEqE<"]FeDu r"F5ZgYvZ\Pv[oN SD&R!>4& IM`N#n_8Аz]?1hc '8Xn]wV:ݟpYЅ0gQ.]4bL)%ƖP\ ]i7eѡL,$"hd5 zN,Y2W1xqAعNf{znskdx%4igA,ܗi'k7f4_B;~Id%ג= fgnF YJ4lO740Z?Q뭄nL,bgqxDw"~<. :CJ"bNӓ[gFRAFID2)QJSxv]p3g*T*e(ċ6Tj榢TĶǓ [hE@`2Ӟ+"x##A}n:,<A* `ƀLDZmQ 2^Αy¡朓I.`;!e0 A;NSLJPP.5\x{K`k?KC6Bn hkI,D,d~>Q`; Mэ@ղI _M م=y=%']우]| ńODT_ R nL A v_ ph\ EN zPZ(@M0h(:=%Yq "!!@T!."@#F"!F J$^^Xb$:"h"#B%zb!"N(")#$b!FE+ VO.!bb4!!H`gFT0#11#x2.#3k4#4FcT؆4Vc365f2 !.-vaG#*)|cv:#;;Vq)#=cq9Rg#>l d;@c:u#<.>#?]vB fBA6$E2E9BdGCErI6;DH>EP|Iȡs$@8&8 9z?2>>?dRFJJ$An$RJeB.LSbKf$W$L>LV%BQF$F$JvZEvTdVGeSzeE$;&AGdDѕ`D,յ]]^b|ODPPvDL **BgRIhfifihBhiz_|h&i lfofn nJ!'oforl&qfj"s'n2t*glfw&t~g$'kr^'uknl&i H@@*܍σA?%~SD[F%^^hTҥ2dL$BV(UVG(:膖U%XneK(ReD&HD<,&.ik_=6VQV}DXJ9qVާZ5HT'M%SQnkZeJjeYhe>e(h\%]h[(%卮e꨿bh]QX>1DAX?YVAzDXD*ǮJ}ۅqэFONݵBg)hd''"{VF&{ wiw2*v:6"-F 'iFgx:- gDsgaDnGf1ס'L]B5]CL*8Idf#T@$%Yve.%򫆒$nfGk~%G |Ǐ'EDX\ @:]^jG۹: elF쐖,4^d]х][Q\b_rDznV+AB шbA /07?0GO0W_0 3 КMj ,mG^rDӁ)0zl_]cX,^B=Dm J,"fk]BPTX A@@W}T@qqq1q~+fhnLƀ 2q$'r!ӱq r1{r(1)#%qETex։`MO.@ܙm^8EEXLQ^Gj[)l]@mOO_q,:}PCpā X6A0@ ` AD A0BwGG t(h G(@*c4oL`J~Dۺ-`NG$JDNtu>;hX?3nԁ,t @ `@  h`HFW5\uV_uWouW u[5V{ZuX/t[[u\W5[Y5]s1V)hDY/#$uVVW5`5e5dvZsuXW[_X׵f_\5< h;VLR!>ǶMDqDnvcA 0CU N00€V@D@ 6uW7vvS>TS'ꮍk#[w모%#(7 ĀFj}q"6>+# /wvwwp7ΆpujyB-VV-v2mi rS,ڎ)vxw퇋v^-i۸7lIvS;h.xznz(h(=)@b7Ty:9]Vzh77"#5: k8yfoKmr폛‹Ǹ/׆kxn);,73x+w񎫌"{+z׺07 9~+/:!9wX_#G7.yyk9k3Ȫww Rj[m۸8'*)ď&: "<8Oėm2|{{zůL{?ǿkwɫwy;;c^|?;+}3<뷾6v~9~s~?͟/}Ћkp k/%@/04AKTpP,t4Q* 4xrbD)VxcF9vH #I4yTPt0U*NRESUSrB թRL SϠCyOR 'ϠJZhOTttة4业6ZLF*@2+uܛ;:`E' hrYWrGY3l]jf×I6ӫYTɲu1gHxwnݻy"U6zPjH6@1* Sd@,CO2#C"hC@@AѨ hDFTFRM <0\dv, B,6s:F<RHH%32X8&rHE4@D^Jn€NaS08@'7~ P8 (f`Š 2 A4Q38+B9ZD5$>c&=EsL5GPZ4o=*efӎbӣg{gF͙PoVe M)?NM0 EWZP}ڴ.(3-*S{ R!Khf,)GIT7߄8SNeLmVLg¹ 5%+@AzԩwMT8Ս(~]VY_Cݺ|$k)ĺo~ڞc%ְ6!s5l`G5t^ۙWڲbFN6-vnQ*u\&mK\:7ӕnq]*uBr>nurS ׼ʭTwn7ͭ/y_7e~XzKv/GoKV4n3b8!I\b)VYb.0xaF0F cA\d#IVd'?Qf&n@UMc-a/yiVQ3CmsG e;yg?'{sW`KծpU7/Sm`" pkZ5 ]`z֧&`40io;VݩQzSeR'Y\ҠrD7)r,[S van[ӜZ̺ ,jWҦﱚlkQǞֳfEڍ?UXALA*v-9dM>o Ra/.qjڶtGCsR5U{OeU4I}(Z+CU>:8,B Iiݝ3213=bAkOa=OrE< >Ƴ3 [ȇvC_0R,aNxk!޳y~|osn{_o.7 %L!@^nr $q&0V:I p47^L> 0`O&%.G /ERk2 RNR!Z Ā  l JA F d!"`\ER, x @La f@V`@ y$b j.".حbIԊDn  x/f@j"" V@N @*X@NfIxN0pxn**dPrj t`EUFP0Na ) @*N I|j3jm("*`n IF'ުPZ sg bN.1O"Jq7pQ)Q!(@~T0R pRbVcL P BuPc'"(q(Jz@ .C"PjBdN8)$@+&`@RA0(gTl@m@I nF&&orR)'Q )0(''Ҭ B`ti' ~` X ~ 4 bRah~ : 2 0`5\0 ddTp0 Hlh2g// 12!,2m'oq=(wq' =1{2q&s;(e43V "@'0P2B+ EkC!p@Q/o4@03୭(&M1+3T@GK\.@ H2b rfH PĀ 1/ \ED9A+?LB A-0NٔVx%ApBnu@ `@ R@ @ 0PA R $ $` a `7pQxW,FTߨ>%T0>FSGQVVxJ!`J0Kα(N rL^!D0b2`Bqj#9/" 0`I1`hUQ'V'd$+u:Z KQR7FRC~XqWqYw`B U$@z`Y C R &Y` U * V_a@s`4wtAtoW 5pWv% jv{cc d WidP5TS!kU===K1RJL cEnB%FIH `sF'V'Uk$11j(hS2s?VWyp;؃Y`  a U@ Fx@ ?Ҁ r7tpw uzPuw ARڠK@@ESJF $D>4SD` a @Vt J"JA 0*A@ @K!@0Q LfObX٩Ra\VSYӳ) î{#]4bW`#t|#bR!W'WA%"a"\"& \1H#G%;\I ;;6&\=m ?_9bW@`%|"@8 #]S@#W!"" R<겟7 { i3Nv@؇؋-9&<ؗ}_d˸y}c ,\, !-&`c`;"}{ѷs.ݽݳ'{W!'Yީ!<ݾ[ 4.`)ܽݻ X4B;:u\{IzVl^~jcåzi<& ERHWA|{t|4ݾ[&"!8;޵-%!4N%!!`I]H囜!|&'~.!VAICo@C뺫_:|>w>5C{OzKZwq>Y"!<9O[oOȀ fkvgN l(H%)))@)RJ)0hJ &`2!*X!J":HRh!Ba1~"'8 9AH\uƤM{d0dEfa,!Zz.JvZqffjޚn*@(`A~ As DB X{ZErPЙ)D WA-0wVƀ50z qP@ ,přmJxaI8%FXRB1VaZ]۬JW}cH-v,\D){[r,ZIc{-jEQ2d*p̐ `_X2ukbM{o>|O|igH\@@p@@~ g \ @ R@ \rxru * 0 BC{\˴%@*>]C\@ \@C_ e ́,'PP < iiH\`ric!*heXbG~]x_^eFf䉃\֫]K_`]wJ:YCn:M]OԗIJpq $tqq/kj/' }1r(L1:ʕ-b-;˲3g1ZbX"rEF**, JhK,Jb\.w_R`Q # P1Z"bIzRbHd,jqԋϛ4v $Bψ4qll8qtۨ$NȀMrG0v1_Hø*Bb֛%/I$J%ĉ< f!1\ k . phiX)CWʒ)<Ő t7HD)ŗmW>2$7TostslgYHΙ|x?`A lHwsf9K΃*t LOIA[: 5AaIJT21da6cQԧK^*4ڄw``J^2`!mPXN6MKmSzNJuT:ᙁ`Ŵ u2V#AǩԧV&jm[8J ̔*-XRԂlI7TP\kQAמ1UӫPMuM["U"0?׳3obi65YjݧE2Yޖ8Er^чy.rrKqut%ŅnGȅYV@@U1rEr1!tZTؚ "(Ccզm`|)v?(]:XըլFOXRR`-Z؈* X;Cq!B^j\9D~F1auKr}E)garyZf'}5>fyz8yhcS/>Kx /r]_ǵrwwh9_옃ve;ǡP; t}"8S-q&iFue݃(81{S_]rwbXNwy|& x4gײvӮ͜sSme% Bj󩡀ίYNջ׽_=6Cן_(c){E{r'|VlF|{3gk"W{f|݅hH?DhSaͷ4r #}D}je}+G#*}gšnpy @v!~R3 `iJ I1jvkgxqpWwbxNwh4?DuhwyhG$s"g{ 6|>sւ\~7vp_涄c `58}B2"`diZ7 ?3uA4B a*gTeƕeecH]\nep6e\f9(]x\9 (Hhⵍ_&Elv"t6}^8d7Y&+|`8lvGɀ'ry)XkYmGeȑE8Ψ8XeeѸddX&eee\f"钧s8rd5dSI͘[X#yZّMV_bg|Ɩwt7x&GYaF_g~l6W71ŔNw RrV5>-/ ! %ٗå2 'ofe\ TY^)8HcyO9,\6px| ɏV{oIB|hdxlIImIYѩeTViYU9+5+P5+5k㙞癞YN rĜWwIPU`)%Q]ٖmǠ'׆X)m4'2y8 ˒,`xȇF :9 UI5jr-`/`У-/`))?gI V0 )PG@[pn.1Jig$WWiIlʆ(sgCJND`C! _ I+TwY*Ef dB֨ʩ1yG|e,HFizd.\ĨN娐 }(* `g9 vxY)=@a5)eΊs٢K9s{Z I kJmzwŪZZ+ j皮 1ʯs5w Hjj˛* C*%{ET1kj[wY^inw7k` 0p* {ǰ2k!;٩,[#\=qȓɌcLfǘ`9[[7:,XWK&kr*+8q W;kj:{ ,E.T0[K)9YZ)ٷ^[DY4I"|ےK ۶UY$ E˼4ۭC[w$5ʳN+VB+ܻvkEP˼y[]𸌍ɶwk\h\jKڻn[ٷ[辧zEbU K빺|{vʹy{R l3ڥ3L5l50ΫKjJkʴB콕 M,Z9-:>ܼ+q_ nFgd@hiG XU9EY[ۚ< #Džpj!5:-=6D 5'ӳwza˿l{^k|Q@hʩ,fBB "#!!}0 bf 6\ =LN, zJOMܽpzslG` 1$p j p9Gt~0P6^P<0$@P`K+q'`H pW5,3PH){ek$e[=y,} uP]$ViC  e \p"| b` Ef ;vP `jF` p[ Y5DHԼF"|1QO^ ,1P000M= ;wce[j}1P@Jp`2!8(p4CA`(mb|#n%ENЊ͏kSLsI^~`~%KUL!>؜ ּٛ/VL; aߑ< ˪DO-˝<̖p~n5,޹l].n:/°\^`)e /oFxM1{M}C4p & {4P &*#@O8 _ ??Q)hP R&NhxJ ABt8 .(qD?>HO&QcŎ A&ʌ9KR%ˍ;adaRM>UԥR UVYSVXe͞EVm+ݾW\uśW^}Xp^k _?YdʫYfΝ=ZhҥMFZj֭Gs[6YdzmƝ[n޽}\ÍGN`͝?]tխ_δxrݍ/^x͟G Gj]MJSMITe%Uo{US T@ 1 5sP1R @!S2>SPB -4QD tJ0PL'-eQH S@R$QK5-US)%UPLY O7}S[G]TTmUYO=4`/-W`wTb%YD]TV#}VKeM6[]liUYjuZc[QåouTN3Oe-AG:5sLä1J64`4TG8%f`-~lc!2c:+~䂹c=~rf2Cy"M9ddyK/Bu8jj+tUXfWpk]^vvwv}V;_Z^^l=ZyV]E^pq&o{pƓT]ߩG'=+lff1;fHϔdL= W.i"]Qs9O2@ ~WxDyyEf`죟z۩ JG?}h߅\xcqvw~{Q'7=]y۞x4BZבuIk P';QV>O}'h.y`>{>QІ3`9$u6]sЈC$p! 1߃pTK!VtZ QƩa+øB)-^JCw!(GVd>0hTHPB2!f $*8` :0@jl%}ms;w/].\K|7rngK^YԥLqv-K)Z8F5j(e%MSb@ b`sC<pOjҕ&e@ w7CMCFfBX<=1@ !yu24b AST%0DЁ e6@>AD` AF NM@:PSZɌ&hLͱd7-k*nf19Mdk+\W՘Ҧ]q:A*PP/=Pf@ @\ ^LaB YBp N(5 VáSd `D QB 58Djr_ktFڡQ|( xȈfp5&+^DZ-(wIouإzH8V` JŅ Pt`0(0 - k7"I0 2QY+e>X885Ͻ<,_9cosWr,uxf7zpDbc2]RH`j#T*&U NpTlV JML1EXH6oGg7ҙyMD/::P H(`ЃK)` (AU D2A6q D` Kq6tqӖ@w=nrFwսnvw=ozAAo,AxATx; 6 X0h`#D< 3 P*$PT!y8*F@.چyl[ny1z]0v9P?VA]IZQWl P/ȁ<ОThB%Ua@I@2` p HYxp  HP ]px ,|y%n|5yw}ɗ0 C}D,ҥ>C)t&^ CzOw}B; "^ >om3"7}RyW~}o?Vs>>ҥf:Hs+:Ϲ+tO|HGݯi6"3?9x٣?!Ѐ ) ܊=1+:&%{_ʛl«@sҚ DAZuR1@\r,C|@t"2$?؁D3`$H& 2 z=c= t#B(NS>zSCd7L/ӏ`C/b˽P94z%3D8{+&|^*%t2RܥeA(A)A*[&EUEVd'X&RyYxIX PF8P$y$B!IHE8x@XyQ!&@6K![A.Yy}j(@4HM"XI!Mș˿ڿ\$ 俥ù\KC,@S$?pU0P8-x.` 2Ȁ" SU1? 7(S@S X#*@SpJ  sP1Ⱦl 4Es@E\6LGݣCÌM#̴4#Lğ*`*XSXz / ;S48ȯS8Ā(SPS5; `0U0DUΜ5J,S?8 [2L>|LCCBL4:rC;C<\\H,>D-1D^  0 1yNS` 0*O vL=Xn?+x   N Fa`$[<Lܶa\ Baa \d\%A1E(b̥aᘀ  xxn 6vcHhc@H9cH `xP <^> 8 GfI+R٭W#O+Rd{],]Td.aӥU]_ـ H^N[7b?f  f^gVP ev HL^ gF f@秘NLswxygqx_^ ((kn g UP Xm^h x6ho gH訰Xc6|_ .L L%2陦隶i>ԜiFT&f.v2g`ff B^6v jVVNckF4^ >~h:n/&i@nf 3^kAff = >k7N1dkPjnN5vVx֮is jvcmnmhj~j漪~If^.}6fAn 0f͎n f pf ƊN p&f `P0khq~lc^ nf7no& nR]?* x G kjGTNqnqTH% 7q 𘮀q 'T q"\..>.o0fN&ngX3(f^ F*&TfV?V3s: n.Od8Gne&w3,+AA{Aa"p#St iSN7TtRrt#uM"u>{Yp'-Fh `fbOf;eNdppuuOwt_Nqr{ s-|]fxH^ HDkNox9諨k˞DnFank7va w/y,gDFN`v 8:U8jBnyc0fz⽖}cHD ]C%@(_]I{{MxqGuN{{HUAB*TР*t8(QT fAUÇ'R,X)UNReT)%GEm-mAAT mxr٩0r9H⵩[  "d.(|ē7>Uȥ#8S?}vX"*l)T`4YH@P *))bʈfxa("&a)*zء!Xb2(b;f2"/$5.YJ MBt lr ЕYnlB)%9pefɥx7qd*n9HJW)S y*⩥vn*ltD7^pV;(7XN=Ҡ2۬&v-W LH!N6Ycd昸yZ~g}kٹjngMp% Պ\ ^^{^[v0pǖ^pp3ilE'Flǰ!*pDA[1rf]*8os2@D Ugh"6guK.9 ςcM_! %M6>xd¾M$^+-d:9u7Ú¾L) x'BJ)BW2jp.@XLJDD0\B w{̩hJ8Fi\"vR1Tu@x(*t+ T @?oA1RbR*D=px! .:2\x^I{[D~EhJ$UCٜ5ij 9M*#t$2 :P"8B8.e3ԔRDiU%)2ϩT>:Cl=! n*(k Rr2͉*I˵š/pr`kԫ@LT] 9O( 0AVE'nf[(.1IOR:'uG.37hS_4SacGgވ\Z\/,L?l,jV\da4nlyi .O, Z`ڗyកTp@y"^~6E3}qSaF[ћWu^ƜUvB^p` WUD}|Ii5I_ց.V]߂tZyO蝲O0YOT`!PQ AH@᳜-5\Q.R!A^잛klQqNR&(a `UH6^䍈 ѝW@@aF)ZA"9yA_v9U"RqR-W8*HŢeya6cb ĠOQ`- Tb5dDi $bkLbs"v̇aCar#ǥ `qM֕ uIEbRZ+*[0_a5d9aMK@0p*vYRڸ[1!X,Y/DWdMdb-fP'^'-S6%] q#W^?64"epter c%v-.(ӺIdRO0hA ZaNbW9ܷ"aY=׺=թe^#pO0)gP6UU$d6HJ˕a d"xf)Wv#-O6>95Uc AgtJgMuBgu2 `gw , x'vxbӠuX*zFgy|Fgu`*p'}xZD~wY5"p"N$!h*(Q[sOrh| K drb9.LJh舒*\hE̊~=茮荒EKl-h )5h|Yv(7H\qZ#iT@ T librr)TifCtz)*H)~雖C* b)ii)6**@JR*)))j +î,^>l7+ (:(+]{%lƫv,f+l"H췞VRSa+֬J܀T bK*ĊlBѺʬ6#n+A"a b٢Vϴ\ S% ե&TQR!$ Um>mNV*‘!Q!u߮!a#XD\.t<,>@zqWP<LHmvk6-j7qlϚ2 Au&/>l˶&kNo2p}U{u"ĆoRo7Edrl hb9aPHFmU֡6TZ"M|#Ddph_pK@H0k{p[0 w0G#0 ۰0 p {@pp6W0 p p[1 _01 0p ow.N`]fy5ۨZWVDB&f\[: RmѦ"f*h(((X @A0ZrdT H0)-zn5EשM Y(@pW(\z͜,23$/ Wu8s93*tckq G1Oqqsqǰ3<{ |. `@tZ@x~h؀:3s@< =;33I30sXɱ3Qs `rTWR,bO n֒l>'/Zk%KBToN,FF x(B@ ހC@zlWoV{otn0qM+6atE` فEuP+cVQ ޘtg{gvhYA AہY@DhvmtaCwSt-]c*Bpy9֍"U]h af'$c+[ne2b[p*m,zrJ-L,r@ E w`_7{wqBz,%7'+)nCWo[EquWa*4]O~E*"CR($7u&gv8m\;l{ @/ AxCw MFPX^ݴP\bV1污bDD>h\SJRmUjgn : , (2qzߊ:p:l[{Z}%+kw_3yr{+xM;s\$t;Ԣs+owyWm*8U0㞺zn$/0kT&;zF%ćno|-8BWǣzO<1{|ÃRq|#(s3z{gjuyg#:8=3C=6SZ`/}{_=25ϣ=1e:{:W̷}z͋z ;ݣ}S|<<=ݿMbmkS&+Whs޻37S#o)d@)kg \F HA{/hd A(A{W8o{}|/gK۲T ==7uG=uI8}Oz_c{) @ǝ(ϪB?@:uJS *AK2*"B .JĊ fdP"Œ-*qcDbTdJI\3U?:hQG&UiSOF-Z M1W>4H,$M n{,IJ0يرس$_N*\hWܷ)CI2Y(q0Ka 4p@b ~CKSFv(Q%As hcHk*7穟=&Wysϡznaj xuٴcIÿ>Գ{m>t[p"8> !D"ANA* NB(!SD8@$280`$=nP!!BHh  CL/b$Oj IZrȇ))+*J TJAR0%RL14K1,2LKSS9DSM7L;L8N63>0T? 4A1mG9SG7MN)=AA&^P1("R$H"Tl#%@P SBN:`5^x pL7(e /PE$XEX(3E?-QS-5RB3vUI WNIw`KO8!Xb'L+|NIM0$7; -TQv -rA,xւHUd#HЀTxTnh!Sx@@#9 RAQT*pMd2YSrnanR /@JL_U8SC%X̀3\ImrUT̹z<_O!}snCL0{b F.ARDt7 CLA/HC-aRH Kbp%B`;w`Gwqt°- ,tP8)6Aw~-I!,f2"Gu,1"008@)takIA~0AqAL?@N4,  BY` FnLo}.EIp>NٴU ǁu%URטT:K^:~`uI}\d%='KT / pJ * "k8)R4 D(`' #( AZ0d@ (#?%|@Ue(EHYt 32R3]y*Lpxt;Y2|2|x41 NP!lEJ"X$#Z\ATp)EpVHi TQ 4>#H>0!!P 9擟-=q cU*_BUUn]WVe5YњVmu[WʑS]2*4Aը~[B*4+bK3AX2RVeh,Y|/A UY\a[Ζmq[n5o4Ô ?VÞvi$c B5m[έszn$P;]:oYdNΗQn_IqYRolzk&0kZjW*`.W;;`5}naK c 5OgN6r:ztvSR~L.ihuJ#$s${yXenBֲLU}Yvh<`Rx.xS"4/ưzqA745)HFxfxyi|9ϥlrS2$A'zɬ__=eCnulk5Úʹ׬oǓܦ6M2/[%7mHi;j"cw20A}arGXN= &4Y"6һ p2"w5&s?vxTGSLH)hP d 8%~o<-^q.\G9Yq\9qoy]2?a^"oRs>q ԛ^uKXnx  <@l@5L`6D 1#r%-5lE֞, q q06/5%q6p!Q8ό8[%tP%s @ `LR@;SPҠBR 0LF'D E>IeKs {0WF T"$k i 1( *B07d CԂR!D0""@L" "Ħ!`@"BFQT0#SX `B^t^@!.FJ<$y(P6+~d5 -9,x L}xL MW͛v5ϴ| N7qKyRz ZOF@2WPa>OR&QOL! Z^P `` $ʴ@ J>S?4nU+h*m)*uV3?VsDa}U',V{Qd4$>c"`CB"x[0 $3"&A&s< @x@@"D$TuU44(i5_9 ssR 68EMN#bM5Ӕaa3S%vab`@ @ @ ^    R f?UԠ @ Kl ` v  0@ V R X_!%D'r!l?VB# ߖ D!kuo30!> "* *: #"!jq"Bx P@@bq  #J`1KA xFtlYu Va53HWRWXRYRw5 Ywxow,7,1zxQFliZ5Yxqxy}zwwX7zCxRX0wwx|q)W}IWlw{KlP#%2*(pvAWDD'n6! pVzwm/XBm5ӨTxB!-V9$m]FCqwn-x0t`vXC,b D ."hb~<,p` nNo{W{7}w~!}|۷ywu}8wHG8/:" 4&%jW "_'b2Q@xA#Ʈ7N9ulL ̴L)6mM1N^:T4B7G`tSQiTZ`XZ-MP K;T8 u؁_8؀3Xyx| Mco9# X!xj/t2 "@ u2 "BZCD~". 0`Tx`&7@x@2 0 ^@jR|p >@fM W95Ld 9֨1V`97;b3v7vd:ad86Qt9ګCT>֤Ѐ`Pa  L ` @ J! $A  Gu N SɀV @  Rj V`J VZL @Ś}̘z58x5XXX&G*"b $F + D>T l`2b VC"v@u"< \v@" xw U\OZ\[!| `U3d;%erIM$@PAv * RnR (u\*iV\Qaq\u<(rA DZj(A '#5pJ<\I޷:v:K deS':?6ISwQaQb;1r[ t+؜IŜˁyYXCݹ^EIY?BLQ,{aVw J2 )TOReJST $(A BTA7>80!F 9np4(CFdY$HGJ,y&C{fr&Ϗ]YSVIJիXjʵׯ`ÊKj$=ĩ͡) 4&[vLVf۽}dJףMީ֧ą}]3㹌[1ӏK7N%h]=j:e9uG _|`Բȓ+_μgQN8_ˬs=-g;ķC ɦgG{7V뾩_ wtp@(pPVp(TpNZa'(!$f!z]d=@)rMg^lǖvoqW^N]k%8Jn$ eDR~IK E~uOZsL k{ve"{Xng$ǂ4X;%[*0UA+[aTStp8cfPr!TؽT}{5ea <`e@*ʲ   s@0@* @V!ƫ,* ,+  B>RYAŒ0X9KPAJZ&7Nz (GIRL*WJMJ TTc=ISe@@RIU1"Hfpc* Q*ǴJRA+\)ojEX 'V x,xBI+{% VI.JU*PB;&3KT(%>4t,c\Rv|iN=E$X(eJe 9өL $UTJ p LũҠbWU,Ud+JժZXͪVUWf-q:]rT昀.Rq#& LR\p; d)Rʁ4 .ɪU*bU) u*X4IGAQx@N)`6`U'Wpi#ݸ68,"/ScS*"|(|818 k\FɰS]CK8P]W!W9Z.sM(υ(Q8@2~CGt_ BעX-ؿvާ9m"0PL TQTQ"9GP3L&TML _3Šl*^͖1‚ qbzdҮ"`,Ȁ *r@.{`J@ {=f[ٚkgL7= ҘTb;ioU `7bj6.e)ASB: #iW \"cdq*Xr^*ys<O*\6llGT/kpiZwr 7 =\s|96MF}yPjټ5{ ~0smLDÒ^&m a5"l|mYc4SɬiGZ`*)jt.H6Ahd0Hoӎ=}sZ!(5~:7vY^m03_e',k2Xځ9ߵ۞o-mew mKwZ!p8 q d7ejZǖSZOe&ʃ @njj}S@n#qjcRřJSiR ҵ(w5A_`-ytUdCW: k+nuHMtvwk8uzH?igvvxv#(??3d,]cpPVe76Fxgx@Gwp5T>F3yB24Vx\UΔŅvdR XŌ{TMaS&D{dpDX4xvnԷmVnlV8H^mmR&(Q^R9VP솏ʦ*8&:$g]c'phZ:7x5 58 GA"y;tNи 䂉#whHwjlw2XWhv}}huWuxjh5>ɒPw7];ɆbMwLYuW5[5 `Pgb9hhh ,0eY_"_ y/8zi7 H=*enHG%ߧCI&}i}]~ʦ~CWCBɘuD6_Vl\yyOHQInn9nC7H}!йnyd xg pY6&`\fٞI5] fi؏fBl)&阢CK@UÞ;9P|C4D"}yD D$C~i^:z@IKHtOCؔE0[gPB)V9LvVڒSitZκx;*{ lݙͿ$--=m鍪  Ӿ) & q0 0|}s=s'M4yx/ ån9iX5[wgikH"ฺ]m5X@(nvȠɧؘ]*Z{M^Ȝ=K1WY&0/`-)`)`,dnu:A0knnNs~ej+nMP+!R"1!3"4r!3P./'j~"1R #"#AL̈@,BC힮E_>n 䚍ק%<؁l3/|9;O7 6*0U(*!Z_, ĵ%kHAL+W6L@ \˳7M(TR3OF*EʳSA=խF~PUZ Ԯlf}UheJ^}EK\uKXmq~=Xg:>\1gJKYqM'4d͓QM5澢OmY 34iq |<R*CO.%ȌѺKRO2qyʔRNAETTŔSJQSTY+p@DA@ 0Pp@3|PC E EpEY4FA S|qg0DD&QP"1T11F"?I}R+dr2u<316H6T TP L7lR ۯRQ@GZ.&ē4Vi,% &HcNT:54:(S{ROnQ`)ڊ7Xm2؎evݞl:mD#ܢ}m0jS*e#{,8pyL] 0f6w*%Xl= o%Z֜xa \qR4X& ^HчTCϠ8Df@F@dSLWXX-x9rM@6J>S1:?7ET,LAT3l@̚G 6k;ԲI%;L/l< uI>t9NɸFp W _\m9 C 8 &g>-zQćd09(>GIfE#e8M:9=m!7׈R_BQEe6F6T p͖ "PA@A8x "(.i*:`# xXJV{*hekq/Ղbdhq0Z@ƃ{X_. ! v Z,oy00-@F ܐ"$Ec0O8r0E`"L H(BP"d g ֐ +>d6 XC!**Tu"!yz^ H)@7ԓ,IGaM<[ηq,3g6G@H@6@B` X AN1\H6 p.x0PQ 2)*8@Pp MRA*R+e۝ȣ"5)h2z S+3|`X/ R+,]ͬBp]xa3b;ιj Efdx\Z`^R@QJQ 7A^HU>pjT%T0h)Ph"3 b87$eWFe֕Z&7md;  0N5[Kkc(~Xĝ*S4K;x_u"[PaR[=JM1F,h%8AzU@HE L,z0@8P4PUE*P$À%()0;Q64bT,RAVSr<~BҀm'emϷz4 m0&p` kgers^u , Wwj,sb5"3%R` )صOGAJ;eE  |i.3rY_1Ɩ-+O"I@GHBL pXwSi)Gt{2pS&+??=coÜ 2d #/a*B@  @8  `<8 4S( a#|/Q@(㐤{d>IQMYO6>UYGIH;ѿ*7;0ZC)7|BC0©$C7;÷! A"9n%TH!G%8EۣPAA%tdKYch(|((h"?C+,CUjArO5NJ33; 7ɫ3M<зKM$i\ЧK L̨L1KPѤ/ L8jGc̕ Qͬ&DP]O#},73ͳ;TO1 #OdOrһS4++383-SFTC\yTSnll75FLlNv|)ߴ%9-)25SG}"(ITJTKTLTM5}TO' u կI=S $%UUU"*UxRA]U^WO=UXVfmVg}VhViVjVkVlVmVnVoVp WqWr-WlmTdMiWw}WxWyWzW{W|W}W~WW XX-X=}%;PKnťPK:AOEBPS/img/dtp.gif$nGIF89a ???ooo___@@@///OOOppp PPP000```! ,@pH,Ȥr8ШtJZجvzxL2zn|N~togqxHl Ž̑ӈkGy篠y*EÇ.!ċIȱŌ Cر$-(S3ҙʗ0y1͛HY#@IgУ1iSJl*ƨRYR ֬%v+XbɪgĴk~kV!\xѭn޿a]+@|H9- eV$!PYcD X2w/@Gc# P<`PZ@BpDWu6 P0'+P> @  $T Ppz}`xf@}ss A}`eT!zw W,h' (w֝) V@7J$0c̆H$%p(g|gɱ~Ru#Қ)Y@z| Ըڅp@o8) U)0#-p}%|s))ى9_ AUgQ)b.('rI, bfF:npVW+D͛9޹7\*s*@ẑgr$>r|aX YK6G `20̂@8(fy͙=\;VH?Kd*atZ-,t +J!W|O -gpv0vK1.-{P0kv`$6:*Ny\VO̓/fH8ݚZ4Lp Ab{ {Haȳe|X7Nˋr=Zg ׻t#&Bӗ?۵#/PϽo_߆S_$`x%Ph@.^- fy`9>H?P=) pB+K ](ڐ?4 w8Cpk! DQD,bW$**L(BpTD2\AЀDb6zAc,( u@D L 耡:`6L@@fh$ @fT4]@ H% PL2C$Oh]e s0@*& >vfJY,& kIE2$A.{Q&.=ҔE8$g:NqFt=IAA(em}:s'+mf0ؒCQ9H}j@~Q9 Pa…Ѐ-t`B!Gꆒ~ओM携NƁ2 Y9=@`i8bTa@"jps@s`O³VZa9 _ݧPī0 dEX V̷0Ь=cQDA;LoqP[c/34*_JHa[%j(^"Jw! 6ꫫ}!8Ͷ;Umú m1 &8warQ5Q Zfe\hU1+P‹Vh 82 4Tgfv 퍣u8’ݚÚ)ptpntF t4 (qDYp8ΑPm_ 1oAɎ~pjj(vKk9O&#4m&}׀Ŷ/\L'0Xi0(.` >9 YŅ@i?^@3\@4έ9G+A5@''2U3L o@'Hz8 y* am@APz@r1Q& w7`(^w :O §IOᧄ]x>!.  Irv>WzJp;LN:/[/dŇhT:ϔp|^݃ pӑu5=EaPpӅ@`a9h_ۈ&{ B0l7|n'yn Yuz psNV@q^D} ` 'rGI@'(txf~Kwig Ppir wTiCzxw‡a|'ֆy9a(ydtW(|ܧyQlg @g30{d$wdnfGXr6H{0q}XqbgybTICP-2!J  YAPXp{h}!vJL,$RkHR=$wwrDЈ4׷Vi$gIQslgȈxM: 4T/@p UeaRER7vqDnXT¨ +K2cW%RYB8 "U_s pr!'BqƏbmnWlx퐐I@^%$fS9E2]\d2_Zbf P8G 1vn'hM`b4YZ1A' z'"S-S#XS%'R N)hEoymkW658hTGPpG 1QTgR52m6'4%(c"!Y8)+fK`:h@X`XMPNaee_rp)R/"Ty&i+b$OY"k:|暰Uz )vxdSdPi7ihvXrH/( TsLpitJ Qs)$#$1Ar$ LC0":+t{Dži{{:l&Fqs@yqWv`aXhtpxdy> B6 DjpF0hLPau* ["ȊTYc6iTbZզxZm!0<(zdNJVd~h~'pyaT{N`IltrGILw4'JzYdKJ% sCyX(zgVG`X,zEcxO.z0jB) u sDa4s7qWr֣V}/ԮfMVvʘl7KSOz}OZvS avwNJvNjv|6qH*|t [EڰN:zC`QDaH`T8u-rNK"Gv+A'Ǘ~|KtdHw0+l趴ǷdZW4zPg{=dʩEg>hwc8ZJjM^KJfn40+Cpvڸv@ԔMA9`7lوzgBn ;}DеwhpaHJaLր H6|{}%{ Y `N[Qh 6 Uvd{v;pg{ sG: y{}pg4`zGkKtۿwmDrLru[{`!Y! K7%̄X(nH@֨ڨH7T'¼CqrKxzhe{VKqA?S7qZZv`Pák|N wmW5v{u8lIvY迊6oKxHh.k16YuLjtP6 wwhLgnPLʞʪ,ʥ\}0ǭFMƖLMAҫiS8\\%ּ0^|$`\ӜBd> dτpϞ0-[ @hJо-%Aw">G4 ݒ"ySxSSP]lƅpҴG5|Q1M|uDm 8-xMQ~-y/̑{I`P~pPR-OoԐ?JtVi_GREԔ&m#FMoa2J=x-NKT'}|:tT,CҠ ]ڦ}ڨM<[hlpfZ۲٥gسۻElY!}mRs#Dz`ݔ#Bp[|qM<ڝBԝ} =ܝ MEM-ݼ}̽]BKݥ#  mD..v}= МwW!5d(%3P .= CH0|:<$Ka紃 hJ"}.$RgzW;qLIi}.ڦ~N `^NBXA[0߆ nn:þ Ůf^^9>y6ٞ `z.j^,tT&ﮰp^`@!qeYwZ]qL/ ֵ d>i-P1ؐJ_ NH> , H..nA?C 9 @Wd )~^̠9ڍr1lQ(-1X?泝r?09 2)EPrt q鉏Y}i /f .?ȁ(o_ 'ONss8pE$;#K0?:6-];0of_'1.i"5#,6$$ @Y?o׃/;VS$"2(C~ y5" 1P\^b( np>> ( >>>8@CEGIKMOQSUWY[A7;c>  " |%1?6v?ze`9 pC(! ,#l׵;hXs ӥ*p_.)(fYT,@*eK/a-%aP@*22C0gX4hcJeHTT2S`: ;A#g@qچaӵ=% 4/A;#%)dҦH9re,F.tXYڤprQ5GQ";` tBVeI5dP#a4b.ݘ`gf $a [DC)qKFk\$@ĉ4ޫǗ/3fP2(k`P+B zdT."Q"-X@<*B-,j&;  Ȣ:MN7N2Lph 4{o%l"|>x'%$ *w>(0,QXyswp'"tgU 2)PbBpA9ר  -b+- S14P24I'QMI(JV#ơuVer]cUU~щM @ȉYM(@bPd } aJVeu#-8=Uͷ2V}_k`~0@WUBV!b"Bh ) WPRߓQV`Y7`iZ)6Y49y~]-bV梑D瞙Fy夡-n&z馹V鬉Y.譻nI(Ц**(,9T;f­&'&ڊC{Dv[s;@C\J[e)?zAoՌ qY< u*V\yVVuC[chzOL')h->C6"x#i/d u Ԣ7"ח=  WG4@Go @;SCfC ~/]-zN fJ e$CFOD!RWH')֍yyg5Q4 . PR_QPFא)!`OI-ٌ`.Y)^h BR ""6 8DZ,5mVYg[!I9"Mq;vk"QyNA4QARbf'A=@T5VE&΢nb G`5`H+Yxj#<䋽8ɑ/*P/HY pIg`nᶟ)0w5F{D] zbTV.)DܚQ@\ 9ʐ?6a6.J n..!7.! K&Mf_t( IN K*\Ypn8.p $-w0rpf Ҟ- ]yU 'P086 ' CNF Po 0&p0Րذ OH o%]!nq"*Q.21_&1:>Q 1k?KG/UF\q`dqorvg=0+o51q;1nc1qٱ1qQ1q͑2 Ro M .@&@&d8Aa>!92 '+!!g @8Ab! d#;r&ɑ4P prF ; jg3 c@`48"*&r2 5,@ #<jl2 Z|A:2 *`s6*$r1o /`.f+|-˅A.)"[g!v,2/8rj1an!! J9c(`4@ )6JF%6w6`36S. &M(x 7UrA.1~:'α s?m#+Ff JD6c ')Ԁn8-N$1ӌ@ m00:`?E&=`s@  D.),t28R9-" 62`:HsD &` VdbT-Lc<(**4FL`"'IpI MttNTNtOOuP PuQQQ!5R=0;PKOa$$PK:AOEBPS/img/current_read_lsn.gif(GIF89art@@@```pppPPP000 !,rt $dihlp,tmx|pH,Ȥh:%H' zxL.h@ w@uv* "km"rc$TV:l\lb @7M " #YL Y¹V Q M$   %' # NQ?4`($ =x-p)!0-v1)68] ;,@60lɳO~HLf@IHZJL)6VY!$(HX:aB=IcS # eh;aK]@AG-@K 4Ih) *tTDCOx+]!Mi **1 C(gZUtpIɒk[/=;-V `УKGlMe+Gd2F讓>@Tf՚VD 8οյ7 +`NɁyYVq4]eEXֹ^9Z$h>ЀL$K !D ;`@Nu&qG6pg14q4:'vf-@Apw=й о(`L z `[CXg#{4 6'bV |@ܭU%O 4 zw9}0a @֚,$');6 8L{kCbК%)1_J xGUE0`uAXQ N k# d;|c!mA#t<%+iQH (FpaX݄x%4ٖ  \'{JҊ$FT2v|%giB3GH $aBK(SL=ҫ7j#%!_1-&X,` Ty!1)5 0 ? db:HTG2ʌlbțw ?\1\²B+w -b-:=RJ#%k YĖE'Jԋh-vQD*T: ^U@+;,V\) Fm ;҇@&HjFWJۜH"~qn/O69N yVYq;1$> &ʴi t=ٓf]d29ⲝEҺEf?HH6e'J~v"X"xپq37oMKʋ=*À{(mS!fsŮo'84P庝f-RKت*7z oB֪$Ő{jU5y"A<Ŗl#Oy|8% < WLhHfp*|aDӗN)k?q2lna+ӢPMĝLxԷ-Ew[ jTܵK0Iq2h=.|Eꕊxذ)`azNV?@Nz1G0BȈY$Upy| CbtՎ6ML'EvLb"/:X l+bX~mR]k>g0% ٫*_l5\_| x&n`iw %%#'CG \4צ>8jNbOߴyEnj1 T-\QU&>q*`{k\PNeo(Uu0vPG47p_h |{TLKT[ibvcBU KdY1P7Rmhkcp Jts'& p )# OY;% >0):pl4lV0J.@=GFB_(fiF9> Ty72y>A'>,xBڞyD (z"5)BKL£TP49 SCjɥ>3fN9jfӉ&RpHDr:Mj1bJ1 7f> ~Zl nZGp|`ڥ_:vZ"Zz-ԧS*2@:YBDꨍ*$O Z0:Z-Szګš/-z›ȺzӬ Zz,pںBɭ_2zs⚮j S&"!R)7#: O*PT ۰~"(T){5lZ `)9(<0TWB-ʪ2;,бz6{j4<>B-j۳D[ R-ŲE۴[b9ےN[*ҍB[)j^kk-ǒR_{ rzڂn;#؂)RvWokhŚE݇ ۟^Z :A!4h@ҵy[*kj*=Q?AG8TD=[{v&9y@pO#B,@tL=䌋^ .$z*)h8$ fg Kj+k3|;uzjV+ܓqjѽ>p[ڛ(HR3$+)N3{Ic ds$! W O}LJꁞP?`802Wʀ놜IYrDY *`FV/O W \ DUЀЃ0 ) 7@k&2Y R ?xb wboaˆ\r \ kruB HįkeX9,=, +Ѐ}  xxdv<śjVܭFbX1w6w|2Z댢!pʭqizyUP4 ^ӐNjpyz0tw9Vg qבqcq6@ţsʬ5' D+HV Gh\g\\XCHD{U3Fq ̃e 5ZfpsGnh$\Mlf\+ ^"'As?Q:fd&Z%z j\kX3T"FBԵw[UL-enn,mr>,q>v+u~z*yu ŋ(CK) nlL0T;>~(g97躆^ɖ 0ޟ<1jy=x|٫:] K?~@GҾU4K'PyC Ģ'p'1Ȣs`Ęzev  \I`wСn4cdYPPN37<}^ZDC^d'G2 `h WuvU{m$f'@#XwmUNVTo^q yrrpb 瀽=?rDLXm]j椬[w=5L{3:MOAV{GIe'ڶ|#t&_zQj y#F\PGCM ?Omm!,/,/҈Wb8 X뚾&ʫʓbPZi!('":ޘ"oN%w$=2Iny "&*.26:>BFJN8,ͩɰ<pn X~B \H$@ ( -BBزIs=$A*` R0l UZ:JAU#O-4 !  sb8u2HzF"Mt)Sx* DC l#0v>x 1~@\,e`=d2` 6,`-p:[쥎:per#k x[ЀAtÎ=C9' Q w*ot8Ə#T@i)P( `; $;wbA% 1uٽv`-,/Sp@0``Bl^FH7D#@# Q_xgzGv #z'H32CY tOBSRY 8PX٥_c%k٦o Iw♧{٧Z"A;PKcP<-(PK:AOEBPS/img/records_retrieved.gif'? n$;" # E k @ ?q %(@# 8$c qDU`l(#@,/`U a j(w6N<` Gz0cʜIS1͛\tcW D\lȀ YB##tRٳhctġBC2 6'J%CѶIp%,6NLFkɀ'm9&֦ \T֋ {d{2"`b Nf~n\}@WJ/` o LuP@pc:N[D 2-lj9uPd]ODswv4%7 kdWAPI@\bJKh'XFcQHt\vR @"bn!I8','b@ t8K"'hYfiu4Fi^Vj饘:駠**1J ܨ*(ꬴj뭸뮼+k&6F+Vk(Mv+k覫] k;,lp 7ZZz6Jx4o D8Ot jCB|S,{4lͼ0pA}]FAYp%|ь%-T0>(g&p p8 R}#|A27ij4 _[B"pp'_ =ȩD%aM?İ3[xȘ(>pTQ@FCtWG&~S8=qg wF< JA"F $2?TqLyՙt'&N'hcPިS*5#i"Ac*>JDtpUEVٞ2ay) PFYSe2{a/?LhiP%k$x*Јߢ!MNhP70Gs4Y䊡TƜ\g"X-` |T:`b|j\4h&Mh fM[@< ndHLKjTl)[s>Qx'zrjң~'L"ej(;BTлpCyY/7džWSX5뫀@@&ı=`(I ȦnHEh1?)&Ƅ6*`[z[cŤMrUk2Qmx*$J.E\4]CA@]%ml;8f1g5pw= m1eS%UF0N&X=US_= =%5U$=%A.Wb EAND1ќn+ o㽒#Bw "\xj5XfyC&4<MbÂ&Ӎd>đMNU@e_Otkv2Bs6LǹSW0d٭|=ϙ (z h4q!g$!r c3sU&h`^ Oa@$֐-qn؅u1K6ESӼ/RQ}#f~L5YƂ:ɣ* Zj@խ͹hqvvɀPgň&=<-D]^AٷACee,ޔ&'(jhP TqWLB'&_0 AC,U[+)D%yc!)>Jxf'!&H!p6h6OdnȤ;#vkL+.`_O!ZZ݊]5Ѫ$$h!卲}1n]>!,X4sXcR_#U, ƿDN!@UDHjdyB|l̡a ] f*B3jD޶Z|xNPƁ5k {s!:"h)pv\vjgw1ut2p 77(ClfxY([~&*7WgR,h}X2n0Qet¤2o=f- j$y$@:Ç 6(qaDM*%' dpzt+ *  F ' QYoN%1&ZPi' L pN=eX` qX  @PbuL@c (Pbx1IbڠIJ@$(cV|%Y2(2ԔYLag&Td1  Xn=5 ~& '%j7J(Re}p`#<1> p_a8/]IUj12ck a #W.Ek!CM72A~$: Nvv-Гcy0TGKUə0p}Wc7u5xwvVb]ي @j U(H77!sRhHwh!q% }F$;  }h h T!yb=d*r=rNA @>dH F7De.KQK(Tz0КIws`̨) @ (fY"L@'1j]wEp)fO CH=v&% ֆ9lWP.>(ԳyTi3H81 GOccJ6^)' ?ɖ1Х8Hf`E&a>*(\|/&YD)VzK^d1ɨn!ԡ%Çw)ũy::@(@tD}F䚳B.QW_* D6yzF*HdqEǺӬj7eʫ㨚g*B_4S*B?j.Ʈjw: תÊí KK[ 4P ۱$kցz'K&.Kz1)0[48J-:ҳ5;@+1K; ;/ӴNPR;T[V+.K+@\۵^`b;d[f{h\]Ҷnpr;t[v{xzx˶|k [)+ ߹ZS;+(~KY>W#v; :[ᆺ9)˺ckO;&/뻅ʺBc[;)k͛tK2)[yKM-r;)\ݒ+;)^-;BK--;R+)ݲ ,--+ܢ,/- <-\Ȕ!,#)|Ͳ›,,0L3RÐ6L,:=Ê+@+DlG\ĻĄJ+N Qĵ2|kT*X[Ũx ^*ble<ƙrthnǖq)v|xz2&Ќ2l!Cd' Qgh(!cp&\=CbVPoJ F=94jB_!,S=6Y ) Il(P dd$P'j:=do l'Fl$BpI% ;XlΉ gqrl|,z{#o՜s[clvn1MJ`u,Dx0- Q,[CmM8 p] *ur4F<a%v6Q$Կe=S(MIޡ} !LM-=QIY k2yGV:0sLql'ZrJIbCVK6 M sնLdIF0N]LlQ"Drא !(>ωL (sJ=` ރ 6:uB3I P* P'}RzI5]Ceڞ% fٯvȵQJpl|e*Q1a@7!W:dRҌ-4U"H mpoB _t P-8Dxl/ lP-;mR q(\ E"ba3y p,"b1 `D hP!ujq"zpf|& m$]`WyB5B2)& Ac3.6l5<|8ja%N$q(} V0*zJb1- {j-1@t& 55hTRQzaC nls4vg#HםPB.=!Q#k>R,&n0wbp# 0a"w"W"%EY'cbrڙr̮S{{NlbB"]!&Qq*EGSj. ap)8V{qq-whpGyJcAr,5yAIg.&i?IY G N&qA!BRm&|gF-EA8="br`짞UV "]tx_ը ^եVwSV'2o,bAГ.(uxG01&\j4!_N- bw%5ro2A\;yu]+/k~%vO^8]"__Vfm_(_m$IC8kq!Q*p{%BM/ #94!}誐OA8hW"rc@P 'u HPL$2""UJ4Yv9cDw@v5~9]P0b7}q1% 0, ,4X 60X 2A(<,<(i.@@,0D-& <5>f~y gnֵ"0 !8u&5,$a 4E^i4 @D/ 8e0ppQ͛ ,`@8ʢY:`p`M|<h` OС)% \^3%W]WPA WQ{ * ha`%8EE A$S6ܤ}xPiK}.pM~\ɛh oъ !%,m1o?9 Q" 7(@hŠ eQ 0E_wQ>1 7PVF t$ SE&Y&!C$V\ wa5)&PUqBdRg(yz 6_YG S0ĤgS21h 8akMlUߟ.@`zrE٠TϦ7 Ț)Jh!"ZРg0JLh ׬Bl$0̕brUC[-Pj\ ̛/a&[@r XC1csܱ#\'+ܲ/3\7㜳;ܳ?C]G#KLC>7WcMsYsݵ#ocpe螽olq]r}{۝7߁^8փI#8S^cʗk޹!s_:駣驳;уi3sTVF }܄I$3 ZDJII${co^IԳf}ٓ/KC C PCRV{˗//;ww]~!/f RN0xPT̲,h!0[v &4f P^w fTa򸏆Իl"(?ů 0!^h53'Lp8OȲE\X+fA K UGF3d|^Uq{ "{ܠb 1i7(獩9 U0@c#36vI p-ɜLM V B{ R5RB+eMK: '0`^ #ɆZ*g`kXxśCT<$iCR6kZ(@5σa4fQ[*ٙu]F'M0 hLCaEB ]R+TD):rI5  ,kI{QAV̒ 7إ(R\CĂ JRS|nT(M!H)$Dj`u* lAd5{EJY e*Z=xe*NQ XO&ZuQ #Jm| eZXtS0ix4@}\((`=!) -Ej n'C#/z,چH{(];ܛ&De xz@@!։bP}k7/8/kEДXA`% % " vK5h Pe/ u&4n mJbD*U]&@4( blJ^2'Cپ>h#L8":ϫVyApbf3b&!0SL]$U9ӄVhJgdzӠs$OནTZ)9bk e&2zv7w";+d *ØƐYyz'^6Ul~3aI gcstc2}iX{?D+/dXZzl*8@@COX  rIY~3&) 1ף_EM 4T)4-8X:C&EnSPi\RB5nБީ<yPyvP.hI6)* @'rĖ a٧c T tYaJ9E/D~x5DV.!`@3,+G\I$@0$VLΤa b7i B'Xa^J F^IX J܀l(tI~0yC*V~LZJTD AU "΄rA% $ \[!*Z0A|;V4.#dT")F5͙C 8Q]AQKT)_ S#Ul⳱n$ fkQV2JdY US (%zآȜc]I@>ZSǨ.cCݷ}UAK70I"}lM91vQ2J A'eyS2 \$de_!) '@Y|leeQUcofUj#Y 0C`4* \L'v:X5&;B.d\E|(<$C6`Ʀz3"q*ͮ2[v" SDTg @ [1Nz|0ߛNt6cOS?6@; S! ;& LD Lq(9ufb3(("%!'歸抋F C&q^3y"u1)ɟ8 @G"&V(m `M8H5ճj:/{|Rސr饮lp*N]Ct+H>e VhrNCrBÃ,%l 4\ UӺJ*G-ԗphDCЎ42 {)pG:rp r".$gOf̜r; o4Ѳ9ozZgʩ{8όrfTWntڜW:0Քou 9XlV--!Pr( lʝ1@EuvnJ@iV͚,PO,9!Jo` Y [\Hs4̐nZ.=]ͩFj +r!| HXsè숦[ɟb0wx(FL|0a0-,7PVF".rHBcF3D0݀&7J==ZX48HEBFw1hL($lHGLụ>r IB^$ `!FG8#'IJ˳&7\CZx(GIOL*W l0,G̥.Z>5R.IL>I1L=җ̊Ijgʀ8%&ς)F0٤:Fy򇭆Be?m? Hmh 6HGҖ>84RRKH#MH] zp̡:W+c#" bH`(QH!\E@ADUJo"*$ >׾:JQF42 ,WH-.m#U &³l`sFCMjW֞* JۏԵͭnw n"c%*SՑ@bT&ht:z1Df'Z= Xhz|^ UB0"LBŒV@l^e$JaLv2,:XAR?@b)l%!d]^%Jq"*V~s Flp "BTސ?( o'HL)`N@n™f;n/gH>x<&XVq!ǵ].(Hz +"8@~^b71|TF=iQN&S^fGRʦ  xgxgreC(!94#SSAՌY EJ$VCѸEX2eW`%Nv&M8`hyhHU.6 !FG`U˦H`*Oz$sv$P`^lY,yH`.J4$De^H0RFb9쥐EIPI_0PM{>qWz`ŗdigHi9_?^ ?N`v6l'Z ^`vUpePMp ^0 e&Hy`Sfv&^r^]8v]Ip @ k7kG`5p{)EI 9s FUMP@uTxYʙ5eIe2x;3"L 8 mP$3p)euYg mړ`) X@RǏ^Ux*ٙ@ j,Ca8U"t0݀Cqa ‰Ia:cE8*Uщמ˶^N^Xv Q|Pܤ89Ba*Go8w7 0 %W7DͶ_l铧I^e(8fgvWڥOjv:`^N `Ʌi|q"+S 0C+"9EU.ۂ"ֈr{:;wH 5D'P 9h S 3k`k1€ ښV(v+nN)<ٕšXˠeAi[l8`z̀wQ\g25ѐQ"k-!!p)޺>0j;Vr&L"؂ʞGwv>N^GvӾrds^ 8N~Q%\~>\D4_@tgVM[`H ` 2!LnIRo .ϱMŤo$_4YE0 +at-/ "ԄB xwM?pR OM_1Q=!/#e(%hQFNuoR,aY/W6$Q[`w3?QCH?J/O'g/ O#M_.MO? O8J2Q~e SthG  D}OtmaL;?Mt_9MAKR?vL;0"}USO0 :N83611741O7N˧N º+369  $ȰÇ|cËc!' Hɓ(ˇŔ0cFz`]JFB`Sϟ@/ݳ2Q"OʎJzT׌EjWUJl}̪]i)l͈vݻ8 ݿFLÈ+^|8"ǐ#KYUc-kĀϠCMӡ'^ͺk԰c6-۸sͻ Nȓ̜3УKNإO@˽{ Ë}ˆӫO?I˟Oϟ(%Ll݃1( B`{fv8xHr0fb`(8!:nH@^bD7#X=F)#O@`T pY35  50a@L , p$ ]M22 8H =2N ;a LB)0+(PAH`z&W ׾arFV Pp.|e@W'h p>6kM 5p>2t mH`Cau&t@11S@X9 j(&D rC]RTxhN#J oA&sg3'' H+gc 0/fd]20n`!(A,PR3ǵѹs3[ -QpJ5/r}uMi2De9YY*@5dU@@(0 l 'z b *QN(0q8}3@)EdHєG p'(wTP ='|GЂ,.>q2O>ΰ$[*-9{ XɨR>gA2={i5AڌaiP}(b iŪV4Mf(&ź?k>v] a FF `@(s(M0Z$ysA N0y)x >er0 s0X B}JHI]ҩv푩_F!( ¼'|n`}l(XjTs>p(=]+l 浂x}4S9ӝUn5t#G(To,;FL[ Mr f0B 72go^Jj:% c&=ΙhO*\A"j>+{wUs|Zcnxe5\w<:IcؿBi`p L~1wHbd%oxr2:̅~*4qoݬk# iZk&,y u$E b~.uڤjO\3lhe E)*3 sg*n,7%QG zP(;4ʱucw\[$SZ YYtd]Td3LqPq!dWҏ焌W%p (R$էsFy,x0}ј^FjbҨxW wC'XtL@4-2h%'HYŮ>"&%tvԿ) $syVPy6/{JHbUjNu O:_>{Mqjl}[rxޢ Qt2?@X$*HzR+Q+d3(lW]",fA,OA,Q)uV2"X:5;o@2>`@9RѓD) 7 sLFٔPPY&V 9^X<&jkY po9t vyzIӰĐ~07 Y  ٘) y YI Y ٙ @ YY Qٚ O IPYY ֛@l)ĉ Ж¹0 ϙrYәF yٛy㖈1 o 홝07: {Pڠ  Zzڡ ":$Z 0i ְ  G  -1* 9hzG2j +Z 9/ 8Gj䰙 НPaaGI* vi@P^ )zsr oI; i oq;Spjkʙ{F ocХ5 sʢxX Ť* PQ0)j ЕA: y T 렫j` М.V7z `hrԫ5* *j J %<Y0=p:  ٣z3joPJ p5) ;F$P ;Q{:НQ 1Yp# @ Ǚ ;j  i @" [YjtO e hPꮺ VGWk !HwQ-e SF쪴Pj{  q j aj%O Z- 6 iaaop[omTP0O w`oi E Bt[K"f뒽'i ÷kkQi*pv {c[ {Z0#9GLw@[wV' p^ʀ; h Qla8SOY P++mo) ɪ;ko0q;=kG$;w0Ka?R"L '֠훧 ;\ lB ҫk 7 m;%Qi Ǐ0ͺoZlGyf QEI \z F9pHx0ȫ}ƿ3Yr 56SȿY û=·ϫ=EG}*\@#CذŋG=ȱ0CpǓ(q$ɲKq&S<͛8aŜ3b͜@ |?*] ѧ2JuSXIʵkYYê구YyWŪF۷Ү-ܻxɥזݼ۷_"\aŐ# bxcɘS,rw7! =^mV--lI8LD(]kT6ƺ8d׽c@ > Z'|Hp#T4eW=l_˾)C&B=n>- &,h^ $pw`B} |$xG * >!X"--֨ߎ7Ч  ,by *V^|PJp @-> %}`nO Ym=,wl@0"o@$-f`Bpisw0 ' @8p"h>0z|ƚx-ej&-4iz݉#&=á, 6V*Pij˩Ek$gퟴdK1٦Ѐ9ˏ|m䲯;=zHmQA61.PGXy'@-f+83 $ |-܈Xz`]ւ칌AiH3 $jui%ssh3&X ]B&`v`ܜ@bX j1-XxxW&VI\ &G:.jRzx50j5O0ϔItvC3.7ļ$zM_\as/CX ӄ'~iO`壆r5,zbAl$KImh7 '8.>*0~ 8$ @? uA1E {qIt`Q/ 'Lb("jpǢL9$YqqYL !ȠL !XeE-6*gZ(1ђx '(P +I o@! eɺcꨦk@8'M`Q.>p0Rrվx"@^F\AMEx(q"sEke~zln "e,A>H6I|CODZٜ܈͑%:k!?#ya\,W8Ah/(Pm8$C x+j)oHŗK2 w{=o&.ꗗT M{$P56Ms*S1n" zE"|]dg:(ҫ՛@ƂR_J*[鄦zxF nVғUXř7rlTy` ޟ.(\a]Xpag-!bJ+](-`|c鸌`u"J+3`ҏP*0D0хZmRH: _+~N>@G{X@Qsm= ۨhlpv 0gN8Ϲ_8@ޒ*6sA ( o@ 4@ @Ԃ7>F 8; 7@0F}puBp`܂XЉuA!>9=q8 [ϼ7{Gy`NVֻو!_7/Y- @0$7~]j Ѐ䁀 4ڑ|+R yOv- 0P=Ŕ'zzzѦ~@p{p~VidnjvVt'~8fk`}w0~7ocgo70nv'~7|Wft @k v@B8gzs0x GVnGFm'z@Glax ~exv`x x8rdDž^xІkn1Xt`nhlsqGFH  )g &z7w&yht /GΗh`@v q*p GH iH>Xx׈`m F L@nxlx~@l#G}Fxhl~ͷ|֍X@H&Gx898j@HlXjk qxʆuƀL7 趐( kg"'d>qHdBɈi>``vy7r0qgv"YZyZمh7`ؔxpqgN.)/x 蓲xtMٔҸ9~w i  v鈍) Ɂ9~ c@0s00z8y8pylnwljC,5r>y+>py yF`))y:@>ɚx6+gy1@+r/Py) 3+ٹyٝ]&~1`y9p3)05`W:`+`iy뙟q)@ )0p牞&*&2*Yy7ɨ M0AYwi<;`i%z+053;ڣі@I:`5`ꠖyT+'*ZZyɥfщtjQ׀G);GY)j zwuZzОwzywʩ]qm pr@g(jy*6`5pi:О/<gMv?*qB7 v /Zy; zy蚮 iX -YnIh`ְ7l*8r>Ϧb}`*#hxv PG[4K iB}↱^0KM P;\gpGe;Cj[ } >˹ jJx `k `q@ʒzh tzzK%z 0h f۴|93>tkj tY L@ΰВ`|Pq r&{ UjqؔBGh޸z|zO0&l)wHka滆{kz xTfxfo&; 8_{t^t눓W&j](+z,&׿LxJ{L'r GmN6hbn\lPl|-܅klri' l>w=+J}xkrl!lkJbۀ'ʆl(qӇ٭x0F|ewwqH2fhvT3䴷| :]M^lؖ}^i  jj{hLwh9{jvx~j:|@wmtg8j(tGf"(Kyʏ8}lZOLh~,\'XNe=:~aLxxm_"6֓1r+@> >@  <)171+<0//)2/30);Ơ @ Ξ>19<<3t`U^谱FQ/ݛHqTo3jȱǏ CfW(>p+VJ2^Re.P7|AӤcE JѣH=Y1g>~p#X(:bF ]d2[*hҳhӪ]RZCCxX `Z02em+^̸1Ʒ0a(P|7bhٰYǨS^riS9f jTy옋[dPiȓ+_uQ,CٖaF XXmȡVĖ:#<μbpP+_uG '1 "(|%߃F| SCzfxbvEQa)8 ڈh(!,h㍛('r@#DGcH&ܐE6YڑJF)cL:i%YPNiUy&ed %h#fl tix|矀ҙnj(FP6裐F*餔Vj饘f s觠bijjQ 0: 0j뭸>N0믥3jk 4CZкl>n* lZ"@k5*ھ+*AZK6*/Z, G ", g` op$ ʺnjJB̫%o2Ӭs@7Aщ%-PQW]7[520@[(,b}VD)@1 "[f7Q#߄(Յ'/+8l㔻@ω](Bjs.6>zߣ kh5cn{F]'?ҙo'7%`gwo觯~ @? (@d  ȿ'H Z̠P2O , < W.6_ s!i"(AlC#:P(aZ` c8*ц6#k%xc%3ꑅBҐ|Ԓ)\aIJZ0SZ%5IInq 1)%M2#@')8S򔤌))̥.wiK; 0m `#0i \_I[լ5x 8'cvS/̧>O@@O0#'AO `DIuhE HGJR $MJC*6У+HM*RqLwڃ:iLi u>}*Ӗ1ujQ ՙ>)ՒӦeՏ&e*@ZֳKM+K]?Z![Jԋt^W gbe`֭.cXͫ_1ٗb]q#X(ljYﲜ F{oa4 W5k5-iuᦵ?nYݲW| [[۟NU.O?ySꗻ%z^7iuۗAy_hoZ8U]p{ 6èvQ w0W*bn' k+~k^ 20{c5qU}b wiMn[:w*M&cW2<^ٱJ6je9b2`4Y:޳m^٫A"C4-^Bpf8Qљd4LY3{Vӝ1OLh 2Ti"Ȏ)Z2ӛ~s @Y3ּv1kq=i2La?ځvMgG[!oqlGę&6-6'cuHwmIfYkNo?Z%܋~ vzاֳ1`+9@A]J/|iRon1Bg7=1-;Fx?P:ӝ|`@B0n\yT鵷=t⨮kg@phw}ź<}]!Pi:į^6كV'EǝwaOpُiMqC/vxƞG7?w.V!Zu$-TUG6i0A:?t?5@Hv gڟԞM@$s?P=K?IОFx#0>03vtdezJw0>`BRte*HIJs`,բt[^T@ТM'5tgC0utL8dL?PcNg{g7:G0iPg`pED?@I0T`Rj=0&ED#MjTE`G>PrZD!@fM8du0ժtt)7#]4 tM֩%XxK^@5' u u??0: uбNWK٤8BBI O ;>pt-u#5+v?6#KP{X#SK{M"KrXK![`GyzD\W_5L3ݕ@[?Ƶ[E;DKY_٣'Ǫ#xkGj ۪y#+DT0$;^o;˦v+5Zs^DKHjks9JF+?64t?<պ?k\554*㻄 #{NOƛ?zKfQkET|[ZDZ7龵j{rD?06+ JNj?vu:|jR#vDjv#/T=uP:B+\ńkB%HwIex0QKDXEK MȬ <qԜijK\LLs$d7& $P BL!9rbw۾@[@4HX{B@*t]?r$t"Ϥt#B.32BDH?eB9TvOBH0GȫJ[PPDhpty%]*! v%7Jq]m-ժ᛹-ɚgjjM+&B]ܰeL&FtrL4 {ӊt÷4rDI=vPr@Uta' BU[juc+HPwW_r%wvFs˴j]֊J@=\ |jG4=:bǿ;@%cy{K4[$"-|b\5;Dqlw…|vwLC6۫pǤ`grM(k^t%͆-$ ~mJCKBdwuJv?wj&?@,<ܭ+5} bM{׿4TG޾Bu!ը[㬜9m7a[0?MGa MlI? ; VG;@[ӄ A?^Q C@y xJu@l?Ec|LY;O{1K*[N{e{{3Ų¡l?kB@}@7+H芵Y)MPu? w1雎+HZ:u&WL'Jުs= KLS[ᾎQ'vÿ0Cu Ǩ:O*{%lڪͻCPp2W?P^!抚0^_G|yLHk]_jLZ'HagG`r)L䞇rjpH䓽zڃ_+t9@dԪ=D&Xr<$9_ȟʿ/ʱڿ?_;PKr}4-,PK:AOEBPS/img_text/dtp.htmj Description of the illustration dtp.eps

This figure shows the following:

  • An application communicating global transactions to a transaction manager through the TX or a proprietary transaction interface.

  • The transaction manager and resource managers communicating transaction services through XA or JTA.

  • Resource managers and the application communicating through a native interface (ODBC or JDBC).

End of description.

PK|mojPK:A#OEBPS/img_text/current_read_lsn.htmn Description of the illustration current_read_lsn.eps

This figure shows transaction log records FT1 (oldest), ZT1, QT1, FT2, QT2, FT3, ZT2, QT3, QT4, XT1, ZT3, ZT4, XT2, ZT5, and AT1 (newest). The Initial Read log record identifier and Current Read log record identifier both point to AT1.

End of description.

PK\{PK:A"OEBPS/img_text/transaction_log.htm Description of the illustration transaction_log.eps

Refer to the text for the "Reading transaction log records" example that follows.

As discussed in the example, this figure shows the transaction log records CT1 (oldest), BT1, CT2, BT2, AT1, AT2, BT3, AT3, and CT3 (newest); and it shows the records the XLA application would see: BT2, BT3, CT1, CT2, and CT3. A pointer is shown to CT3 in the transaction log.

End of description.

PK PK:AOEBPS/img_text/odbc_diagram.htms Description of the illustration odbc_diagram.eps

This figure shows the positioning of OCI support in the TimesTen architecture. OCI is shown on top of ODBC (along with JDBC and TTClasses), and Pro*C and ODP.NET are shown on top of OCI.

End of description.

PKekPK:A!OEBPS/img_text/reset_bookmark.htmd Description of the illustration reset_bookmark.eps

The figure shows the transaction log records AT1 (oldest), CT1, BT1, AT2, BT2, AT3, CT2, BT3, AT4, DT1, CT3, CT4, DT2, CT5, and DT3 (newest). The Initial Read log record identifier and Current Read log record identifier both point to AT4. All records older than that (AT1, CT1, BT1, AT2, BT2, AT3, CT2, and BT3) are shown as flagged for purging.

As in the previous figure, this figure shows the records retrieved from the transaction log: BT1, BT2, BT3, AT1, AT2, AT3, and AT4; but now they are shown as associated with a ttXlaAcknowledge call.

End of description.

PKpCOPK:AOEBPS/img_text/xla_varchar.htm0 Description of the illustration xla_varchar.eps

As in the previous figure (also refer to that description), this figure shows there is fixed-length data and variable-length data in a tuple tup1. This time, the variable-length data is shown to include some VARCHAR data, and the VARCHAR data is shown to begin with information about the data length.

The following equation is shown with an arrow pointing into the fixed-length data:

VarOffset=(void*)((unsigned char*)tup1 + ttXlaColDesc_t[1].offset);

The following equation is shown with an arrow pointing into the data length information in the VARCHAR data:

Column2=(char*)(DataLength +1);

The following equation is shown next to an arrow pointing from the fixed-length data into the variable-length data, at the point in the variable-length data where the VARCHAR data begins:

DataLength=(int*)((char*)VarOffset + *((int*)VarOffset))

End of description.

PK(PK:AOEBPS/img_text/maxrecords.htm H Description of the illustration maxrecords.eps

This figure shows a series of transaction log records and depicts returned records from a series of four ttXlaNextUpdate calls. The transaction log records shown are AT1, BT1, BT2, AT2, AT3, AT4, BT3 AT5, AT6, AT7, CT1, DT1, CT2, CT3, CT4, CT5, DT2, CT6, CT7, CT8, CT9, CT10, CT11, ET1, AND ET2; maxrecords is shown to equal 10.

The first ttXlaNextUpdate call returns 10 records (nreturned=10): BT1, BT2, BT3, AT1, AT2, AT3, AT4, AT5, AT6, and AT7. The Initial Read log record identifier points to AT1 (the oldest record shown) in the transaction log. The Current Read log record identifier points to AT7 in the transaction log.

The second ttXlaNextUpdate call returns two records (nreturned=2): DT1 and DT2. The Current Read log record identifier points to DT2 in the transaction log.

The third ttXlaNextUpdate call returns 10 records (nreturned=10): CT1, CT2, CT3, CT4, CT5, CT6, CT7, CT8, CT9, and CT10. The Current Read log record identifier points to CT10 in the transaction log.

The fourth ttXlaNextUpdate call returns three records (nreturned=3): CT11, ET1, and ET2. The Current Read log record identifier points to ET2 in the transaction log.

End of description.

PK{ PK:A&OEBPS/img_text/xla_record_row_addr.htm& Description of the illustration xla_record_row_addr.eps

In this figure, the update record is shown to contain an update header (a ttXlaUpdateDesc_t instance), the row Tuple1, and the row Tuple2. Tuple1 and Tuple2 are identified as "row data". A pointer indicates the address of Tuple1 at the beginning of that row; another pointer indicates the address of Tuple2 at the beginning of that row (UPDATETTUP only).

Beneath the depiction of the update record, a series of eight transaction log records is depicted. The second of these records is identified as the first transaction update record. The third is shown to be the update record that is displayed. The seventh is identified as the transaction commit record.

End of description.

PKME{PK:A$OEBPS/img_text/records_retrieved.htm) Description of the illustration records_retrieved.eps

This figure shows the transaction log records ZT4 (oldest), XT2, ZT5, AT1, CT1, BT1, AT2, BT2, AT3, CT2, BT3, AT4, DT1, CT3, CT4, DT2, CT5, and DT3 (newest). The Initial Read log record identifier points to AT1 and the Current Read log record identifier points to AT4.

The figure also shows the records retrieved from the transaction log by ttXlaNextUpdate: BT1, BT2, BT3, AT1, AT2, AT3, and AT4.

End of description.

PKN=PK:AOEBPS/img_text/xla_record.htmj Description of the illustration xla_record.eps

This figure focuses on the same update record, within the same series of transaction log records, as in the previous figure (also refer to that description). This time, however, the update record is depicted with a single Tuple row that is expanded to show there is fixed-length data and variable-length data. An arrow pointing from the fixed-length data to the variable-length data indicates an address used to locate variable-length data. Column offsets are shown to be ttXlaColDesc_t ->offset + rowAddress, with four arrows pointing to various positions within the fixed-length data.

End of description.

PKݎojPK:AOEBPS/img_text/xla_char.htmR Description of the illustration xla_char.eps

This figure shows there is fixed-length data and variable-length data in a tuple tup1, and the fixed-length data is shown to include some CHAR data. The figure also displays the following equation, with an arrow pointing to the beginning of the fixed-length data:

Column1=(void*)((unsigned char*)tup1 + ttXlaColDesc_t[0].offset);

End of description.

PKWRPK:A!OEBPS/img_text/update_records.htmo Description of the illustration update_records.eps

This figure depicts a set of four update records returned from the transaction log by ttXlaNextUpdate. The figure also depicts the ttXlaAcknowledge call back to the transaction log. Each of the four update records is shown as consisting of an update header and data. From left to right, the first of the four update records corresponds to TT_UPDFIRST and the last corresponds to TT_UPDCOMMIT.

End of description.

PKՕPK:AOEBPS/img_text/xla_coldesc.htm Description of the illustration xla_coldesc.eps

This figure shows column descriptions for NAME, ADDRESS, CUSTNO, SERVICE, TSTAMP, and PRICE in the MYDATA table. The column descriptions are indicated to be in the ttXlaGetColumnInfo(...colinfo) buffer.

ttXlaColDesc_t[0] shows the following information, indicated to be for the NAME column:


colName: 'NAME'
sysColNum: 1
dataType: CHAR
offset:
etc.

ttXlaColDesc_t[1] shows the following information, indicated to be for the ADDRESS column:


colName: 'ADDRESS'
sysColNum: 2
dataType: VARCHAR2
offset:
etc.

ttXlaColDesc_t[2] shows the following information, indicated to be for the CUSTNO column:


colName: 'CUSTNO'
sysColNum: 3
dataType: NUMBER
offset:
etc.

ttXlaColDesc_t[3] shows the following information, indicated to be for the SERVICE column:


colName: 'SERVICE'
sysColNum: 4
dataType: NCHAR
offset:
etc.

ttXlaColDesc_t[4] shows the following information, indicated to be for the TSTAMP column:


colName: 'TSTAMP'
sysColNum: 5
dataType: TIMESTAMP
offset:
etc.

ttXlaColDesc_t[5] shows the following information, indicated to be for the PRICE column:


colName: 'PRICE'
sysColNum: 6
dataType: NUMBER
offset:
etc.

End of description.

PK PK:AOEBPS/pro_c.htm TimesTen Support for Pro*C/C++

4 TimesTen Support for Pro*C/C++

TimesTen and Oracle IMDB Cache support the Oracle Pro*C/C++ Precompiler for C and C++ applications. You can use the precompiler with embedded SQL and PL/SQL applications that access the TimesTen database.

This chapter provides an overview and TimesTen-specific information regarding Pro*C/C++, especially emphasizing differences between using Pro*C/C++ with TimesTen versus with Oracle Database. For complete information about Pro*C/C++, you can refer to Pro*C/C++ Programmer's Guide in the Oracle Database library.

Also note that Chapter 2, "Working with TimesTen Databases in ODBC", contains information that may be of general interest regarding TimesTen features.

This chapter includes the following topics:

Overview of the Oracle Pro*C/C++ Precompiler

The Oracle Pro*C/C++ Precompiler enables you to embed SQL statements or PL/SQL blocks directly into C or C++ code. Further, you can use your C or C++ program host variables in your embedded SQL or PL/SQL.

You use a precompilation step to convert the Pro*C/C++ source file into a C or C++ source file. The precompiler accepts the Pro*C/C++ file as input, translates embedded SQL statements into standard Oracle Database runtime library calls, and generates a modified source code file that you can then compile and link. Pro*C/C++ code is linked against the Oracle precompiler SQLLIB library, which is shipped with TimesTen as part of the Oracle Instant Client.

Overview of TimesTen support for Pro*C/C++

TimesTen support for the Oracle Pro*C/C++ Precompiler depends on TimesTen OCI. TimesTen OCI depends on the Oracle client library and the TimesTen ODBC libraries. See Figure 3-1 to see where OCI and Pro*C/C++ fit in the TimesTen architecture.

This chapter contains information specific to using the Oracle Pro*C/C++ Precompiler with TimesTen. The syntax and usage of the Oracle Pro*C/C++ Precompiler with TimesTen is essentially the same as with Oracle Database.

The rest of this section includes the following topics.

TimesTen OCI support

Because TimesTen support of the Oracle Pro*C/C++ Precompiler depends on TimesTen OCI support, restrictions for TimesTen OCI apply to Pro*C/C++ applications.

In addition, TimesTen does not support OCI calls that are related to functionality that does not exist in TimesTen.

For more information about TimesTen OCI support, see Chapter 3, "TimesTen Support for OCI." Much of the information there may apply to Pro*C/C++ applications as well.

Embedded SQL support and restrictions

The TimesTen Pro*C/C++ Precompiler does not support embedded SQL for functionality that TimesTen and IMDB Cache do not support. See "TimesTen restrictions and differences".

TimesTen provides the following support for SQLLIB functions:

  • SQLErrorGetText (sqlglmt) is supported.

  • SQLRowidGet() is supported following only SELECT FOR UPDATE statements.

In addition, TimesTen support for the Oracle Pro*C/C++ Precompiler has the following restrictions:

  • REGISTER CONNECT is not supported.

  • Stored Java subprograms are not supported.

Semantic checking restrictions

TimesTen support for the Oracle Pro*C/C++ Precompiler does not provide semantic checking during precompilation. A SQLCHECK precompiler option setting that specifies semantic checking is permissible but has no effect.

It is important to be aware, however, that a setting of SEMANTICS results in a database connection even though precompilation semantic checking is not performed. Therefore, a setting of SEMANTICS requires the following during precompilation:

  • The database must be running.

  • The USERID precompiler option must be set, either on the command line or in the pcscfg.cfg configuration file. You must provide the user name and password for an existing TimesTen user, and a TNS name that points to the database. In the following example, you will be prompted for the password:

    USERID=user1@my_tnsname
    

    Alternatively, you can enter USERID=user1/mypassword@my_tnsname, but for security reasons it is not advisable to specify a password on a command line or in a configuration file.

See "Connecting to a TimesTen database from Pro*C/C++" for information about usage and syntax for TNS names.

See the next section, "Embedded PL/SQL restrictions", for related information about Pro*C/C++ programs that use PL/SQL.

Embedded PL/SQL restrictions

In TimesTen, if a Pro*C/C++ application contains PL/SQL blocks, then Pro*C/C++ acts as though the SQLCHECK setting is SEMANTICS. It is important to be aware that this results in a database connection even though precompilation semantic checking is not performed. Therefore, using PL/SQL in a Pro*C/C++ application requires the following during precompilation:

  • The database must be running.

  • The USERID precompiler option must be set, specifying an existing TimesTen user. See the preceding section, "Semantic checking restrictions", for details about setting this option.

Transaction restrictions

Regarding transactions, TimesTen support for the Oracle Pro*C/C++ Precompiler does not provide the following:

  • SAVEPOINT SQL statement

  • SET TRANSACTION SQL statement

    You can still have transactions with commit and rollback, just not the SET TRANSACTION SQL statement.

  • Fetch across commits

  • Distributed transactions

Connection restrictions

Regarding connections, TimesTen support for the Oracle Pro*C/C++ Precompiler does not provide the following:

  • ALTER AUTHORIZATION clause

  • Automatic connections to the database

  • Making connections to the database with SYSDBA or SYSOPER privilege, given that these privileges do not exist in TimesTen

  • Implicit connections (dblinks) to a TimesTen or Oracle Database

For information about supported connection syntax, see "Connecting to a TimesTen database from Pro*C/C++".

Summary of unsupported or restricted executable commands and clauses

Given restrictions including those noted in the preceding sections, this section summarizes the Pro*C/C++ EXEC SQL executable commands, categories of commands, and command clauses that TimesTen does not support or supports only partially:

  • ALTER AUTHORIZATION

  • CACHE FREE ALL

  • CALL

    This is supported only for calling PL/SQL. To call TimesTen built-in procedures, use dynamic SQL statements.

  • Any "COLLECTION..." command

  • COMMIT FORCE 'some text'

  • COMMIT WORK COMMENT 'some text' RELEASE

    The COMMENT clause is not supported.

  • CONNECT BY

  • CONTEXT OBJECT OPTION GET

  • CONTEXT OBJECT OPTION SET

  • DECLARE CURSOR

    The WITH HOLD clause is not supported.

  • DECLARE TABLE

    Only Oracle Database data types are supported.

  • DECLARE TYPE

  • EXPLAIN PLAN

  • IN SYSDBA MODE

  • IN SYSOPER MODE

  • LOCK TABLE

  • Any "OBJECT..." command

  • PARTITION

  • REGISTER CONNECT

  • RETURN

  • RETURNING

  • SAVEPOINT

  • SET DESCRIPTOR

    You cannot set CHARACTER_SET_NAME.

  • SET TRANSACTION

  • START WITH

  • TO SAVEPOINT

The ttSrcScan utility

If you have an existing Pro*C/C++ program and want to see whether it uses Pro*C/C++ features that TimesTen does not support, you can use the ttSrcScan command line utility to scan your program for unsupported embedded SQL functions and types. This is a standalone utility that can be run without TimesTen or Oracle Database being installed and runs on any platform supported by TimesTen. It reads source code files as input and creates HTML and text files as output. If the utility finds unsupported items, they are logged and alternatives are suggested. You can find the ttSrcScan executable in the quickstart/sample_util directory in your TimesTen installation.

Specify an input file or directory for the program to be scanned and an output directory for the ttSrcScan reports. Other options are available as well. See the README file in the sample_util directory for information.

Getting started with TimesTen Pro*C/C++

This section covers the following topics for getting started with a Pro*C/C++ application for TimesTen:

Environment and configuration for TimesTen Pro*C/C++

The Pro*C/C++ system configuration file pcscfg.cfg contains the precompiler options for precompilation of your Pro*C/C++ source code. In TimesTen, you must use the version of this file that TimesTen provides. This will typically happen automatically if you ensure appropriate configuration for TimesTen by executing the TimesTen ttenv script. Also see "Environment variables for TimesTen OCI" and "Setting the environment for development".


Note:

To ensure proper generation of OCI and Pro*C/C++ programs to be run on TimesTen, do not set ORACLE_HOME (or unset it if it was set previously) for OCI and Pro*C/C++ compilations.

Building a Pro*C/C++ application

Before building a Pro*C/C++ application, you must set up your environment:

  1. You can use the TimesTen OCI and Pro*C/C++ Makefiles provided with the Quick Start demos to implement appropriate environment settings. These are in the following locations (assuming the standard Quick Start location):

    install_dir/quickstart/sample_code/oci/
    install_dir/quickstart/sample_code/proc/
    
  2. Confirm LD_LIBRARY_PATH or PATH is set so that the Oracle Instant Client directory precedes the Oracle Database libraries in the path. The path will be set properly if you use the install_dir/bin/ttenv script or quickstart/ttquickstartenv script. See "Environment variables" in Oracle TimesTen In-Memory Database Installation Guide for information about environment variables and ttenv.

Then use steps such as the following to build a Pro*C/C++ application. The steps shown here present a basic example for a UNIX system and assume the program has no other includes (#include) or links to other libraries. The designation instant_client represents the directory where Oracle Instant Client is installed.

See the Quick Start Pro*C/C++ Makefile in the quickstart/sample_code/proc directory for complete, platform-specific examples.

  1. Precompile the Pro*C/C++ source file by using the proc command from your system prompt. For example:

    % proc iname=sample.pc
    

    The proc utility takes a .pc source file as input and produces a .c file.

  2. Compile the resulting C code file. On Linux platforms, enter a command similar to the following:

    % gcc -c sample.c -I(instant_client)/sdk/
    
  3. Link the resulting object modules with modules in SQLLIB. For example:

    % gcc -o sample sample.o -L(instant_client)/lib -lclntsh
    

Connecting to a TimesTen database from Pro*C/C++

This section provides information on connecting to TimesTen from a Pro*C/C++ application. Also see "Connecting to a TimesTen database from OCI" for information about using the tnsnames naming method or easy connect naming method to connect to the database.

The following topics are covered here:


Note:

A TimesTen connection cannot be inherited from a parent process. If a process opens a database connection before creating (forking) a child process, the child must not use the connection. In Pro*C/C++, to avoid having a child process inadvertently inherit a connection from its parent, use EXEC SQL COMMIT RELEASE in the parent before creating the child.

Connection syntax and parameters

TimesTen supports the following connection syntax:

EXEC SQL CONNECT{:user IDENTIFIED BY :pwd | :user_string}
  [[AT{dbname |:host_variable}]USING :connect_string];

The parameters are described in Table 4-1.

Table 4-1 Connection parameters

ParameterDescription

user

User name

pwd

Password

user_string

Alternative to separate user and pwd entries

This is a user name and password separated by a slash, such as user1/pwd1. After an "@" sign, you can also have a database identifier, instead of using dbname, or a TNS name or easy connect string, instead of using connect_string. See examples in the next section, "Using tnsnames or easy connect".

dbname

Database identifier declared in a previous DECLARE DATABASE statement

host_variable

Variable whose value is a database identifier

connect_string

Valid TNS name or easy connect string for a TimesTen database


Using tnsnames or easy connect

Your EXEC SQL CONNECT syntax can be simplified if you use the Oracle tnsnames or easy connect method.

From Pro*C/C++, you can use a host variable to specify the user name, password, and a TNS name. For example:

EXEC SQL CONNECT :dbstring

Where dbstring is set to "user1/pwd1@my_tnsname".

Alternatively, the host variable could specify the user name, password, and an easy connect string. For example, dbstring could be set to "user1/pwd1@localhost/ttclient:timesten_client".

Or, if the TWO_TASK or LOCAL environment variable, as applicable for your operating system, is set to "my_tnsname" or "localhost/ttclient:timesten_client", you could connect as in the following example:

EXEC SQL CONNECT :user1 IDENTIFIED BY :pwd1

Specifying the Oracle Database password in Pro*C/C++ for IMDB Cache

To use IMDB Cache, there must be a cache user in the TimesTen database with the same name as an Oracle Database user who can select from and update the cached Oracle Database tables. This Oracle Database user, for example, can be the cache administration user or a schema user. The password of the TimesTen cache user can be different from the password of the Oracle Database user with the same name. See "Setting Up a Caching Infrastructure" in Oracle In-Memory Database Cache User's Guide for details.

For use of Pro*C/C++ with IMDB Cache, TimesTen allows you to pass the Oracle Database user's password through Pro*C/C++ by appending it to the password field in an EXEC SQL CONNECT call when you log in to TimesTen. Use the attribute OraclePWD in the connect string, such as in the following example:

text *cacheuser = (text *)"cacheuser1";
text *cachepwds = (text *)"ttpwd;OraclePWD=orclpwd";
text *dbname = (text *)"tt_tnsname";
....
EXEC SQL CONNECT :cacheuser IDENTIFIED BY :cachepwds AT :dbname

You must always specify OraclePWD, even if the Oracle Database user's password is the same as the TimesTen user's password. Furthermore, in the circumstance of specifying an Oracle Database password for IMDB Cache, you must use a form of EXEC SQL CONNECT that specifies the password as a separate host variable. In this example, cacheuser1 is the name of the TimesTen cache user as well as the name of the Oracle Database user who can access the cached Oracle Database tables, ttpwd is the password of the TimesTen cache user, orclpwd is the password of the Oracle Database user, and tt_tnsname is the TNS name of the TimesTen database being connected to. The Oracle database is specified through the TimesTen OracleNetServiceName general connection attribute in the sys.odbc.ini or user odbc.ini file.

Alternatively, instead of using the AT clause with a TNS name, you could use the TWO_TASK or LOCAL environment variable, as discussed in "Connecting to a TimesTen database from OCI".

Connecting as an externally identified user in Pro*C/C++

You can connect through Pro*C/C++ as an externally identified user (external user) by specifying the user name in brackets, such as "[myadmin]", and the password as an empty string, "".

In particular, this is useful in connecting as the instance administrator, which in TimesTen is always an external user.

Consider the following example.

text *instanceadmin = (text *)"[myadmin]";
text *instanceadminpwd = (text *)"";
text *dbname = (text *)"tt_tnsname";
....
EXEC SQL CONNECT :instanceadmin IDENTIFIED BY :instanceadminpwd AT :dbname

This functionality uses OCI proxy syntax. You can refer to the discussion of client access through a proxy in Oracle Call Interface Programmer's Guide.

Error reporting and handling

Be aware of the following regarding error conditions and error reporting:

  • Errors under TimesTen Pro*C/C++ applications return Oracle Database error codes. TimesTen attempts to report the same error code as Oracle Database would under similar conditions. The error messages may come from either the TimesTen catalog or the Oracle Database catalog. Some error messages may indicate the accompanying TimesTen error code if appropriate. Pro*C/C++ applications that rely on parsing error codes should be checked.

  • TimesTen supports the WHENEVER SQLERROR directive, to go to an error handler if an error occurs, and the WHENEVER NOT FOUND directive, to go to a handling section if a "no data found" condition occurs. TimesTen does not support the WHENEVER SQLWARNING directive.

    Examples:

    EXEC SQL WHENEVER NOT FOUND GOTO close_cursor;
    ...
    EXEC SQL WHENEVER SQLERROR GOTO error_handler;
    

Pro*C/C++ demo programs

TimesTen ships Pro*C/C++ demo programs. They are in the quickstart/sample_code/proc directory. The README file in the directory explains how to compile and run the demos.

Refer to the Quick Start welcome page at install_dir/quickstart.html for information.

Additional features of TimesTen Pro*C/C++

This section covers additional features you can use with Pro*C/C++ in TimesTen:

Associative array bindings in TimesTen Pro*C/C++

As discussed in "Associative array bindings in TimesTen OCI", associative arrays, formerly known as index-by tables or PL/SQL tables, are supported as IN, OUT, or IN OUT bind parameters in TimesTen PL/SQL. See that section for additional information and limitations.

You can pass associative arrays between PL/SQL blocks and Pro*C/C++ applications as well as OCI applications. They can be indexed by a PL/SQL variable of type BINARY_INTEGER or PLS_INTEGER.

Normally, the entire host array is passed to PL/SQL, but you can use the Pro*C/C++ ARRAYLEN statement to specify a smaller array dimension.

For more information, refer to "PL/SQL Tables", "Host Arrays", and "ARRAYLEN Statement" under "Embedded PL/SQL" in Pro*C/C++ Programmer's Guide.

Example 4-1 Binding to an associative array from Pro*C/C++

This code excerpt shows the array salary[] being bound from Pro*C/C++ into the associative array num_tab in PL/SQL.

...
float salary[100];
/* populate the host array */
EXEC SQL EXECUTE
  DECLARE
    TYPE NumTabTyp IS TABLE OF REAL
                   INDEX BY BINARY_INTEGER;
    median_salary REAL;
    n BINARY_INTEGER;
...
  FUNCTION median (num_tab NumTabTyp, n INTEGER)
    RETURN REAL IS
  BEGIN
    -- compute median
  END;
  BEGIN
    n := 100;
    median_salary := median(:salary, n);
    ...
  END;
END-EXEC;
...

LOBs in TimesTen Pro*C/C++

TimesTen supports LOBs (large objects). This includes CLOBs (character LOBs), NCLOBs (national character LOBs), and BLOBs (binary LOBs).

See "Working with LOBs". That section is ODBC-oriented but also provides a general overview of LOBs, differences between TimesTen and Oracle Database LOBs, and LOB programming interfaces. Also see "LOBs in TimesTen OCI" for information about LOB locators, temporary LOBs, using the simple data interface or LOB locator interface in OCI, and additional OCI LOB features.

This section focuses on key Pro*C/C++ LOB features and TimesTen-specific support and restrictions.

See "LOB data types" in Oracle TimesTen In-Memory Database SQL Reference for additional information about LOBs in TimesTen.

For complete information about LOBs and how to use them in Pro*C/C++, refer to "LOBs" in Pro*C/C++ Programmer's Guide, keeping in mind that TimesTen does not support BFILEs, SecureFiles, array reads and writes for LOBs, or callback functions for LOBs. In particular, see "How to Use LOBs in Your Program" within that chapter.

The following topics are covered for Pro*C/C++:


Important:

As indicated in the OCI chapter, in TimesTen a LOB used in an application does not remain valid past the end of the transaction.


Note:

The LOB piecewise data interface is not applicable to OCI or Pro*C/C++ applications in TimesTen. (You can, however, manipulate LOB data in pieces through features of the LOB locator interface.)

Using the LOB simple data interface in Pro*C/C++

The simple data interface enables applications to manipulate LOB data similarly to how they would manipulate other types of scalar data, such as by using EXEC SQL INSERT and EXEC SQL SELECT. The application can use a LOB type that is compatible with the corresponding variable type.

An application can use the EMPTY_BLOB() or EMPTY_CLOB() function, as appropriate, to initialize a persistent LOB. This is similar to using ALLOCATE in the LOB locator interface, discussed next. Consider the following tables:

EXEC SQL CREATE TABLE lob_table ( a_blob BLOB, a_clob CLOB );
...
EXEC SQL INSERT INTO lob_table (a_blob, a_clob) 
                VALUES (EMPTY_BLOB(), EMPTY_CLOB());
...
EXEC SQL CREATE TABLE data_table
         ( name VARCHAR2(30), length NUMBER(10), bincol BLOB, charcol CLOB );

The following selects LOB data from data_table into myblob and myclob, then inserts the LOB data into lob_table.

...
OCIBlobLocator *myblob;
OCIClobLocator *myclob;
...
EXEC SQL SELECT bincol, charcol INTO :myblob, :myclob FROM data_table 
                WHERE name = :key;
...
// Put data into lob_table.
...
EXEC SQL INSERT INTO lob_table (a_blob, a_clob) VALUES (:myblob, :myclob);

To use an NCLOB, declare the variable as follows:

OCIClobLocator CHARACTER SET IS NCHAR_CS *mynclob;

Note:

The simple data interface, through OCI or Pro*C/C++, limits bind sizes to 64 KB.

Using the LOB locator interface in Pro*C/C++

You can use the Pro*C/C++ LOB locator interface to work with either LOBs from the database or temporary LOBs, either piece-by-piece or in whole chunks.

Refer to "LOB Statements" in Pro*C/C++ Programmer's Guide for detailed information about Pro*C/C++ statements for LOBs, noting that TimesTen does not support features specifically intended for BFILEs, SecureFiles, array reads and writes for LOBs, or callback functions for LOBs.

Refer to the lobdemo1.pc example in "LOBs" in Pro*C/C++ Programmer's Guide for an end-to-end example.

Also see "Using the LOB locator interface in OCI" for related information and usage notes.


Note:

If Pro*C/C++ syntax does not provide enough functionality to fully specify what you want to accomplish for any operation, you can use the corresponding OCI function as an alternative.

Create a temporary LOB in Pro*C/C++

A Pro*C/C++ application can create a temporary LOB by using the CREATE TEMPORARY embedded SQL feature, after first using the ALLOCATE feature to allocate the locator. Use FREE to free the allocation for the locator and FREE TEMPORARY to free the temporary LOB itself. This is shown below.

Also see "Create a temporary LOB in OCI".


Important:

In TimesTen, creation of a temporary LOB will result in creation of a database transaction if one is not already in progress. To avoid error conditions, you must execute a commit or rollback to close the transaction.

OCIClobLocator *tempclob;
EXEC SQL ALLOCATE :tempclob;
EXEC SQL LOB CREATE TEMPORARY :tempclob;
...
// (Manipulate LOB as desired.)
...
EXEC SQL FREE TEMPORARY :tempclob;
EXEC SQL FREE :tempclob;

Alternatively, if you want to specify the LOB character set (here NCHAR), you can use the corresponding OCI function:

status = OCILobCreateTemporary(svc, err, tempclob, OCI_DEFAULT, SQLCS_NCHAR,
         OCI_TEMP_CLOB, TRUE, OCI_DURATION_TRANSACTION); 
Access the locator of a persistent LOB in Pro*C/C++

An application typically accesses a LOB from the database by using a SQL statement to obtain a LOB locator, then passing the locator to an appropriate API function.

Also see "Access the locator of a persistent LOB in OCI".

The following excerpts are from the previously mentioned lobdemo1.pc example in Pro*C/C++ Programmer's Guide. The example uses a CLOB license_txt and table license_table whose columns are social security number, name, and text summarizing driving offenses (a CLOB column).

OCIClobLocator *license_txt;
...
EXEC SQL ALLOCATE :license_txt;
...
EXEC SQL SELECT name, txt_summary INTO :name, :license_txt FROM license_table
                WHERE sss = :sss;
Read and write LOB data using the Pro*C/C++ LOB locator interface

A Pro*C/C++ application can use LOB OPEN and LOB CLOSE to open and close a LOB, LOB READ to read LOB data, LOB WRITE or LOB WRITE APPEND to write or append LOB data, LOB DESCRIBE to obtain information about a LOB, and various other Pro*C/C++ features to perform a variety of other actions. All the Pro*C/C++ LOB locator interface features are covered in detail in "LOBs" in Pro*C/C++ Programmer's Guide.

To write data, use LOB WRITE ONE to write the data in a single chunk. TimesTen does not support LOB WRITE FIRST, LOB WRITE NEXT, or LOB WRITE LAST (features of the piecewise data interface).

Also see "Read and write LOB data using the OCI LOB locator interface".

Here is an example of an EXEC SQL LOB READ statement:

EXEC SQL LOB READ :amt FROM :blob INTO :buffer;

Refer to "Read a File, WRITE a BLOB Example" in "LOBs" in Pro*C/C++ Programmer's Guide for additional information.

Here is an example of an EXEC SQL LOB WRITE statement (writing the LOB data in one chunk):

EXEC SQL LOB WRITE ONE :amt FROM :buffer INTO :blob;

Refer to "READ a BLOB, Write a File Example" in "LOBs" in Pro*C/C++ Programmer's Guide for additional information.

Here is an example of an EXEC SQL LOB WRITE APPEND statement:

EXEC SQL LOB WRITE APPEND :amt FROM :writebuf INTO :blob;

Note:

Opening a LOB is similar conceptually, but not technically, to opening a file. Opening a LOB is more like a hint regarding resources to be required.

Be aware that a LOB being accessed by OCILobRead(), OCILobWrite(), or equivalent functionality is opened automatically as necessary.


Example 4-2 Write a LOB using Pro*C/C++ LOB locator interface

The following excerpt is from the previously mentioned lobdemo1.pc example in Pro*C/C++ Programmer's Guide.

...
OCIClobLocator *a_clob;
char *charbuf;
ub4 ClobLen, WriteAmt;
int CharLen = strlen(charbuf);
int NewCharbufLen = CharLen + DATELENGTH + 4;
varchar *NewCharbuf;
NewCharbuf = (varchar *)malloc(2 + NewCharbufLen);
NewCharbuf->arr[0] = '\n';
NewCharbuf->arr[1] = '\0';
strcat((char *)NewCharbuf->arr, charbuf);
NewCharbuf->arr[CharLen + 1] = '\0';
strcat((char *)NewCharbuf->arr, curdate);
NewCharbuf->len = NewCharbufLen;
EXEC SQL LOB DESCRIBE :a_clob GET LENGTH INTO :ClobLen;
WriteAmt = NewCharbufLen;
EXEC SQL LOB WRITE ONE :WriteAmt FROM :NewCharbuf WITH LENGTH :NewCharbufLen 
                       INTO :a_clob;
...

Example 4-3 Write and append to a LOB using Pro*C/C++ LOB locator interface

This example, like the preceding one, uses LOB WRITE ONE. Then it also uses LOB WRITE APPEND to append additional data. It writes or appends to the BLOB in 1 K chunks up to MAX_CHUNKS.

...
 EXEC SQL select b into :blob from t where pk = 1 for update;
 EXEC SQL LOB OPEN :blob READ WRITE;
 
 // Write/append to the BLOB
 for (i = 0; i < MAX_CHUNKS; i++) {
   if (i==0) { // FIRST CHUNK
     /*
     Write the first piece
     */
     EXEC SQL LOB WRITE ONE :amt FROM :writebuf INTO :blob;
 
   }
   else { // All Other Chunks
     /*
     At this point, APPEND all the next pieces
     */
     EXEC SQL LOB WRITE APPEND :amt FROM :writebuf INTO :blob ;
   }
   ...
 }
...

TimesTen Pro*C/C++ Precompiler options

This section discusses Pro*C/C++ Precompiler option support by TimesTen.

Precompiler option support

Table 4-2 describes TimesTen Pro*C/C++ Precompiler option support.

Table 4-2 TimesTen Pro*C/C++ Precompiler option support

OptionNotes

AUTO_CONNECT

Supported value: NO (default)

CHAR_MAP

Supported

CINCR

Not applicable

Setting has no effect because TimesTen supports only CPOOL=NO.

CLOSE_ON_COMMIT

Supported value: YES

The Oracle Database default value of NO is overridden by TimesTen.

CMAX

Not applicable

Setting has no effect because TimesTen supports only CPOOL=NO.

CMIN

Not applicable

Setting has no effect because TimesTen supports only CPOOL=NO.

CNOWAIT

Not applicable

Setting has no effect because TimesTen supports only CPOOL=NO.

CODE

Supported

COMP_CHARSET

Supported

CONFIG

Supported

CPOOL

Supported value: NO (default)

CPP_SUFFIX

Supported

CTIMEOUT

Not applicable

Setting has no effect because TimesTen supports only CPOOL=NO.

DB2_ARRAY

Supported

DBMS

Supported value: NATIVE (default)

DEF_SQLCODE

Supported

DEFINE

Supported

DURATION

Not applicable

Setting has no effect because TimesTen does not support objects.

DYNAMIC

Supported

ERRORS

Supported

ERRTYPE

Not supported

EVENTS

Not applicable

Both values allowed, but TimesTen OCI does not support Advanced Queuing.

FIPS

Supported

HEADER

Supported

HOLD_CURSOR

Supported

IMPLICIT_SVPT

Supported value: NO (default)

INAME

Supported

INCLUDE

Supported

INTYPE

Supported

LINES

Supported

LNAME

Supported

LTYPE

Supported

MAX_ROW_INSERT

Supported

MAXLITERAL

Supported

MAXOPENCURSORS

Supported

MODE

Supported

NATIVE_TYPES

Supported

NLS_CHAR

Supported

NLS_LOCAL

Supported value: NO (default)

OBJECTS

Not applicable

Setting has no effect because TimesTen does not support objects.

ONAME

Supported

ORACA

Supported

OUTLINE

Not applicable

All values are allowed, but TimesTen does not support Oracle Database optimization.

OUTLNPREFIX

Not applicable

Both values are allowed, but TimesTen does not support Oracle Database optimization.

PAGELEN

Supported

PARSE

Supported

PREFETCH

Supported

RELEASE_CURSOR

Supported

RUNOUTLINE

Not applicable

Both values (yes|no) are allowed but ignored.

SELECT_ERROR

Supported

SQLCHECK

Not applicable

Any of the SQLCHECK settings is allowed, but TimesTen does not support semantic checking during precompilation.

Whenever a Pro*C/C++ application uses PL/SQL, Pro*C/C++ acts as though the SQLCHECK setting is SEMANTICS.

Important: A setting of SEMANTICS (or FULL, which is synonymous) always results in a connection to the database, even though precompilation semantic checking is not performed.

See "Semantic checking restrictions".

STMT_CACHE

Supported

SYS_INCLUDE

Supported

THREADS

Supported

TYPE_CODE

Supported

UNSAFE_NULL

Supported

USERID

Supported

UTF16_CHARSET

Supported value: NCHAR_CHARSET

VARCHAR

Supported

VERSION

Not applicable

Setting has no effect because TimesTen does not support objects.



Note:

TimesTen does not support the default value for CLOSE_ON_COMMIT. TimesTen supports only CLOSE_ON_COMMIT=YES.

Setting precompeiler options

You can set precompiler options in the following ways.

  • At compile time, either in the configuration file pcscfg.cfg or on the Pro*C/C++ command line

    A setting on the command line takes precedence over a setting in the configuration file.

  • At runtime through the EXEC ORACLE OPTION command

    A runtime setting takes precedence over a compile-time setting.

For example, the following shows portions of the configuration file that ships with TimesTen.

ltype=short
parse=full
close_on_commit=yes
...

The following command line would override the ltype=short setting from the configuration file:

% proc ltype=long ... iname=sample.pc

The following runtime command would override the ltype=long setting from the command line:

EXEC ORACLE OPTION LTYPE=NONE;
PKtePK:A OEBPS/toc.ncx \ Oracle® TimesTen In-Memory Database C Developer's Guide, 11g Release 2 (11.2.2) Cover Table of Contents Oracle TimesTen In-Memory Database C Developer's Guide, 11g Release 2 (11.2.2) Preface What's New C Development Environment Working with TimesTen Databases in ODBC TimesTen Support for OCI TimesTen Support for Pro*C/C++ XLA and TimesTen Event Management Distributed Transaction Processing: XA ODBC Application Tuning TimesTen Utility API XLA Reference TimesTen ODBC Functions and Options Index Copyright PKqN PK:AOEBPS/tuning.htm. ODBC Application Tuning

7 ODBC Application Tuning

This chapter describes how to tune an ODBC application to run optimally on a TimesTen database. See "TimesTen Database Performance Tuning" in Oracle TimesTen In-Memory Database Operations Guide for more general tuning tips.

This chapter includes the following topics:

Bypass driver manager if appropriate

TimesTen permits ODBC applications that do not need some of the functionality provided by a driver manager to link without one. In particular, applications that do not need ODBC access to database systems other than TimesTen should omit the driver manager. This is done by linking the application directly with the TimesTen direct or client driver, as described in "Linking options". The performance improvement will be significant.


Note:

It is permissible for some applications connected to a database to be linked with the driver manager, while others connected to the same database are direct-linked.

Using arrays of parameters for batch execution

You can improve performance by using groups, referred to as batches, of statement executions in your application.

The SQLParamOptions ODBC function enables an application to specify multiple values for the set of parameters assigned by SQLBindParameter. This is useful for processing the same SQL statement multiple times with various parameter values. For example, your application can specify multiple sets of values for the set of parameters associated with an INSERT statement, and then execute the INSERT statement once to perform all the insert operations.

TimesTen supports the use of SQLParamOptions with INSERT, UPDATE, DELETE, and MERGE statements, but not with SELECT statements. TimesTen recommends the following batch sizes for TimesTen 11g Release 2 (11.2.2):

  • 256 for INSERT statements

  • 31 for UPDATE statements

  • 31 for DELETE statements

  • 31 for MERGE statements

Table 7-1 provides a summary of SQLParamOptions arguments. Refer to ODBC API reference documentation for details.

Table 7-1 SQLParamOptions arguments

ArgumentTypeDescription

hstmt

SQLHSTMT

Statement handle

crow

SQLROWSETSIZE

Number of values for each parameter

pirow

SQLROWSETSIZE

Pointer to storage for the current row number


Assuming the crow value is greater than 1, the rgbValue argument of SQLBindParameter points to an array of parameter values and the pcbValue argument points to an array of lengths. (Also see "SQLBindParameter function".)

Refer to the TimesTen Quick Start demo source file bulkinsert.c for a complete working example of batching. (Also, for programming in C++ with TTClasses, see bulktest.cpp.)


Note:

When using SQLParamOptions with the TimesTen Client/Server driver, data-at-execution parameters are not supported. (An application can pass the value for a parameter either in the SQLBindParameter rgbValue buffer or with one or more calls to SQLPutData. Parameters whose data is passed with SQLPutData are known as data-at-execution parameters. These are commonly used to send data for SQL_LONGVARBINARY and SQL_LONGVARCHAR parameters and can be mixed with other parameters.)

Avoid excessive binds

The purpose of a SQLBindCol or SQLBindParameter call is to associate a type conversion and program buffer with a data column or parameter. For a given SQL statement, if the type conversion or memory buffer for a given data column or parameter is not going to change over repeated executions of the statement, it is better not to make repeated calls to SQLBindCol or SQLBindParameter. Simply prepare once and bind once to execute many times.


Note:

A call to SQLFreeStmt with the SQL_UNBIND option unbinds all columns.

Avoid SQLGetData

SQLGetData can be used for fetching data without binding columns. This can sometimes have a negative impact on performance because applications have to issue a SQLGetData ODBC call for every column of every row that is fetched. In contrast, using bound columns requires only one ODBC call for each fetched column. Further, the TimesTen ODBC driver is more highly optimized for the bound columns method of fetching data.

SQLGetData can be very useful, though, for doing piecewise fetches of data from long character or binary columns. (This is discussed with respect to LOBs in "Using the LOB piecewise data interface in ODBC".)

Avoid data type conversions

TimesTen instruction paths are so short that even small delays due to data conversion can cause a relatively large percentage increase in transaction time. To avoid data type conversions:

  • Match input argument types to expression types.

  • Match the types of output buffers to the types of the fetched values.

  • Match the connection character set to the database character set.

Bulk fetch rows of TimesTen data

TimesTen provides the TT_PREFETCH_COUNT option, which can be set through SQLSetStmtOption and enables an application to fetch multiple rows of data. This feature is available for applications that use the Read Committed isolation level. For applications that retrieve large amounts of TimesTen data, fetching multiple rows can increase performance greatly. However, locks are held on all rows being retrieved until the application has received all the data, decreasing concurrency. For more information on how to use TT_PREFETCH_COUNT, see "Prefetching multiple rows of data".

PK.&A/.PK:AOEBPS/content.opf'F Oracle® TimesTen In-Memory Database C Developer's Guide, 11g Release 2 (11.2.2) en-US E21637-04 Oracle Corporation Oracle Corporation Oracle® TimesTen In-Memory Database C Developer's Guide, 11g Release 2 (11.2.2) 2012-09-18T18:39:01Z Provides information about developing C applications to access the Oracle TimesTen In-Memory Database through ODBC. It also includes information about TimesTen support for XLA, OCI, and the Pro*C/C++ Precompiler. PK!''PK:AOEBPS/dcommon/prodbig.gif GIF87a!!!)))111BBBZZZsss{{ZRRcZZ!!1!91)JB9B9)kkcJJB991ssc絽Zcc!!{祽BZc!9B!c{!)c{9{Z{{cZB1)sJk{{Z{kBsZJ91)Z{!{BcsRsBc{9ZZk甽kBkR!BZ9c)JJc{!))BZks{BcR{JsBk9k)Zck!!BZ1k!ZcRBZcZJkBk1Z9c!R!c9kZRZRBZ9{99!R1{99R{1!1)c1J)1B!BJRkk{ƽ絵ތkk絵RRs{{{{JJsssBBkkk!!9ss{{ZZssccJJZZRRccRRZZ))cBBJJ99JJ!!c11991199Z11!c!!))Z!!!1BRck{)!cJBkZRZ,HP)XRÇEZ֬4jJ0 @ "8pYҴESY3CƊ@*U:lY0_0#  5tX1E: C_xޘeKTV%ȣOΏ9??:a"\fSrğjAsKJ:nOzO=}E1-I)3(QEQEQEQEQEQEQE֝Hza<["2"pO#f8M[RL(,?g93QSZ uy"lx4h`O!LŏʨXZvq& c՚]+: ǵ@+J]tQ]~[[eϸ (]6A&>ܫ~+כzmZ^(<57KsHf妬Ϧmnẁ&F!:-`b\/(tF*Bֳ ~V{WxxfCnMvF=;5_,6%S>}cQQjsOO5=)Ot [W9 /{^tyNg#ЄGsֿ1-4ooTZ?K Gc+oyڙoNuh^iSo5{\ܹ3Yos}$.nQ-~n,-zr~-|K4R"8a{]^;I<ȤL5"EԤP7_j>OoK;*U.at*K[fym3ii^#wcC'IIkIp$󿉵|CtĈpW¹l{9>⪦׺*ͯj.LfGߍԁw] |WW18>w.ӯ! VӃ :#1~ +މ=;5c__b@W@ +^]ևՃ7 n&g2I8Lw7uҭ$"&"b eZ":8)D'%{}5{; w]iu;_dLʳ4R-,2H6>½HLKܹR ~foZKZ࿷1[oZ7׫Z7R¢?«'y?A}C_iG5s_~^ J5?œ tp]X/c'r%eܺA|4ծ-Ե+ْe1M38Ǯ `|Kյ OVڅu;"d56, X5kYR<̭CiطXԮ];Oy)OcWj֩}=܅s۸QZ*<~%뺃ȶp f~Bðzb\ݳzW*y{=[ C/Ak oXCkt_s}{'y?AmCjޓ{ WRV7r. g~Q"7&͹+c<=,dJ1V߁=T)TR՜*N4 ^Bڥ%B+=@fE5ka}ędܤFH^i1k\Sgdk> ֤aOM\_\T)8靠㡮3ģR: jj,pk/K!t,=ϯZ6(((((((49 xn_kLk&f9sK`zx{{y8H 8b4>ÇНE|7v(z/]k7IxM}8!ycZRQ pKVr(RPEr?^}'ðh{x+ՀLW154cK@Ng C)rr9+c:׹b Жf*s^ fKS7^} *{zq_@8# pF~ [VPe(nw0MW=3#kȵz晨cy PpG#W:%drMh]3HH<\]ԁ|_W HHҡb}P>k {ZErxMX@8C&qskLۙOnO^sCk7ql2XCw5VG.S~H8=(s1~cV5z %v|U2QF=NoW]ո?<`~׮}=ӬfԵ,=;"~Iy7K#g{ñJ?5$y` zz@-~m7mG宝Gٱ>G&K#]؃y1$$t>wqjstX.b̐{Wej)Dxfc:8)=$y|L`xV8ߙ~E)HkwW$J0uʟk>6Sgp~;4֌W+חc"=|ř9bc5> *rg {~cj1rnI#G|8v4wĿhFb><^ pJLm[Dl1;Vx5IZ:1*p)إ1ZbAK(1ׅ|S&5{^ KG^5r>;X׻K^? s fk^8O/"J)3K]N)iL?5!ƾq:G_=X- i,vi2N3 |03Qas ! 7}kZU781M,->e;@Qz T(GK(ah(((((((Y[×j2F}o־oYYq $+]%$ v^rϭ`nax,ZEuWSܽ,g%~"MrsrY~Ҿ"Fت;8{ѰxYEfP^;WPwqbB:c?zp<7;SBfZ)dϛ; 7s^>}⍱x?Bix^#hf,*P9S{w[]GF?1Z_nG~]kk)9Sc5Ո<<6J-ϛ}xUi>ux#ţc'{ᛲq?Oo?x&mѱ'#^t)ϲbb0 F«kIVmVsv@}kҡ!ˍUTtxO̧]ORb|2yԵk܊{sPIc_?ħ:Ig)=Z~' "\M2VSSMyLsl⺿U~"C7\hz_ Rs$~? TAi<lO*>U}+'f>7_K N s8g1^CeКÿE ;{+Y\ O5|Y{/o+ LVcO;7Zx-Ek&dpzbӱ+TaB0gNy׭ 3^c T\$⫫?F33?t._Q~Nln:U/Ceb1-im WʸQM+VpafR3d׫é|Aү-q*I P7:y&]hX^Fbtpܩ?|Wu󭏤ʫxJ3ߴm"(uqA}j.+?S wV ~ [B&<^U?rϜ_OH\'.;|.%pw/ZZG'1j(#0UT` Wzw}>_*9m>󑓀F?EL3"zpubzΕ$+0܉&3zڶ+jyr1QE ( ( ( ( ( ( ( (UIdC0EZm+]Y6^![ ԯsmܶ捆?+me+ZE29)B[;я*wGxsK7;5w)}gH~.Ɣx?X\ߚ}A@tQ(:ͧ|Iq(CT?v[sKG+*רqҍck <#Ljα5݈`8cXP6T5i.K!xX*p&ќZǓϘ7 *oƽ:wlຈ:Q5yIEA/2*2jAҐe}k%K$N9R2?7ýKMV!{W9\PA+c4w` Wx=Ze\X{}yXI Ү!aOÎ{]Qx)#D@9E:*NJ}b|Z>_k7:d$z >&Vv󃏽WlR:RqJfGإd9Tm(ҝEtO}1O[xxEYt8,3v bFF )ǙrPNE8=O#V*Cc𹾾&l&cmCh<.P{ʦ&ۣY+Gxs~k5$> ӥPquŽўZt~Tl>Q.g> %k#ú:Kn'&{[yWQGqF}AЅ׮/}<;VYZa$wQg!$;_ $NKS}“_{MY|w7G!"\JtRy+贾d|o/;5jz_6fHwk<ѰJ#]kAȎ J =YNu%dxRwwbEQEQEQEQEQEQEQEQEQE'fLQZ(1F)hQ@X1KEQE-Q@ 1KE3h=iPb(((1GjZ(-ʹRPbR@ 1KE7`bڒyS0(-&)P+ ڎԴP11F)h&:LRmQ@Q@Š((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((([ufT5K9 ر1S^q|&o2R}E"Ȟib!8ct@>vz\][j3>˘]lNTC\ xo>#,/uY.wI匡܌ FF=cD}w09>&ݪNY'4QTմuHtu D&MZ4%uL䏕xoG; +ooy۳nspq8=} hPE?NѷU95m6R.]B5 |V2]yS9#n@}*%Jw}fvۜآ(ow:O7|Osዹd0jefұY5fXA`㏔(?⏈uG/u$_f+7d(d=w(%9N>x{Ρ\yzI,$f6< AR}E?<+kq-ljthgI+#-AEN=[MTKP}B-̦T^9d@;ZEczvv Ү`GlNOW5-[MѭT-,`g]L)lXqhOMմfݮ4Br%*8%IPEcYH4yGپgn͹񎹭(oyZnۄ?fsscku>Lx­n ] 0%A; OnQESԵm7F[SP"u2ĥNbp DZ QEQEQEQEQEQEQEQEQEQEQEQEQEgmk+='CGW ;£FWW ;£FP oz ԖLTH(N̠&00s5_|LVyA# ; l9#q3C'C?IWPϟ <,~$xj)|Sywu,RFP^UUJM`r|PV?xHIc=B֦Y$;]XRz?IaY?TT~O4 O.4/Fүc˃n/mm(r`n#\ލΟ$:tRk N!V9 H$gOQm}ldm4[{$%LT,@$-SYz6[Ӓ/淑Uq%𦉯j{U3Zn#Ϋde+b9q_w.E>nwlMo8u~CķskV\}ibHT#s9F$K7c +w|% HGU FH6,ۘ#; >3kM8rWT;#nrv{e|RፎomJ%[CܒFPrN~RYr >ᩯ|+O %/t$c J\ vxy|'`? OR7Ul>&|Etx : 8%nFq8eo.cW]m> si:įyAT]ЬMmSkyg{h]zԎe%|=NJ>Z{<rc2)#$H9Si3nu-~I4K.cc0#  @/[7wȡvVqr+jEE@i C񗄄3ޤ-jeC%n(˜0n:;IaXTW ;£FWW ;£FP oz ԖLTH(N̠&00s5_|LVyA# ; l9#q3C'C?IWPo5og K£$yQWa ߃kc^8,T 9F_PNpV >\p29Voo>o 1 Q!A*ŏqCq$o iqG(;z֤O|I}[SLKe$7|̏ X&ߴ_t'6K{Kaj31;GZO[f%&`*bA0F ɬQ6~ x>Zg&yco%ʳ(q(FF8<_> ?MkP,MTIHd0&,Cag;y_]覮 ?J Z|. ZkWcKFn@ysk(ý{I5<{?ZYF&& V \"'/EgVIrQy6h%X4裰oc &|s]G>oZy5=vSs<P Y`gh(((((((((((((+5.K^! k6};}kb+G𶍠:g]j׏y9.1ֶ( { h~(,{{H0\y6! ۨ(  [F%gKY%32y&\ ˒z('oikkQ2 ζ({/$Ð$%pGNÞk2O 4m. "9 Q\X9eִ{K(d*m,Q}MnQ@~:v]& [}d[7m`Õ @<acoiqv$0vdpV(-ZxİYqހ(i;G^ֶ(ym"h%BG"WR0Acijc#aȠ\;WyESt7Fk}/OGk ĥHPpϰvѭᯉXEۙtgkRH(  #s fgKq`m& ,?|}&"^&v<#o;MF> 47B+tk,MVW ɉpY."B8-5h&&psw&AV;Sٜ2OBQ_?²Yo;7o׵>Tlv]}zǨ_w##\NI&=2Rk?J&Odt4[G"0Y3&THL t:M.yjT<aW=<^I[`!71']^_x{Lm}=RC# ,O#ȭ (>xk<=q,<٥v|1}x$P**oT xOjC°¡Amd8cg|xGo[89= =x߄!]7񕅙+IԐJC PQ^Os(_|'DZ$)BCѐ.*x4{k8dműl()C#N9+k#֭4wZp7LAP$nVBJȤ('955|=|4~eraUT NpWpo-/e)g 0JǑQh8*R4]? xRէ@|yfb0# US F>J|:n+ȗsmD6UHr1Ѷ1Ѷ|Nw!~ԢmYq88oG>ێQ^'|ovf}j<:F[] R  $/ut jޡ}Q<2KXDݴUMB"8lk|rl7q}Z}+ʊm%/glkC8]W9Q^wׇ4mrI^Ю HV, Y:;7W-zΡ"i4q+q] &TcQ^O G?5V >#4J|ՕdT+1V h.OCZVօpjʫ(EpÿNwumKF-Ɨ]ڜhZ1_*STq+oǞ:Ȗu"Òe$/+ͷn/~.—2Љe}hc (_.hSEM̀}f灷$ >1G\׈5As}|/쎋s1޸gK\+g 7_jWhr#D]R fBv=HdzW { (lU%!ߕ+d@8[?#HI2lqߔFqܞn巸9 I]H#P>MYmk]MornoJcBb&PIaOJ<8m6)G%C6Ff$ ;I'ulʗzYb2 tdtMtg h(u& x).͉nr_ .%"F [rI'5앇 i3ю$#h(ɵ8ǂ|&|ͪiwznR#(RQNryޓh_~0X]Oэf< .wv730qP|`Ïxqt; js,47;rFG$8$z_gjw&%uC0ۿr$x8~ vK5eZh2ؼ3vphCmO'[x~)zof,+0uCr#v/O3pAEn:GON+𧀴:g_YVY!b8\UFP=OK;,MԵ 7t5˺vF cI {M7XԐopV]*e=?w1~l!.OσQy5֓_O/5Ŕ 9V I <瓘/WR+^\B<'r#PB>@Υ=N; sU;& H8a#\tsK5;hld?FpA"\K*]0#e;ʠ'ѓӒO4^ 𷊵9|;]fIa}Бw׃fyHvvrY8g'yƭV~ 1xz+6 DsS#l@x.9gi 2F8ɖp0r3:w/&{+fa*!A'rk~$|9o:wA4Z@-z('V4JgF-E;@u #8>M|cp KPBDWW!TyjT!VK1ujpYFp9%Aln8O-oK_GԒHN#s0Paԣf4O<72SCC\DCkoQH8Ppb>x}8J1x؅TU##:sz@'<ǂn⸷$w0A9z#:[iՌwvbTYH*z8$t&E+38fK¸ӂžZ'XḕIQ]p Ƞ%>Es A$pivB ~g wHvd ׁ^xsH𶖺ncr,ǩfbK$-?ˣjA26S`@8ʓGz{17?h$shO)7~V<8yޣOcZ4k_Kfg}^L0@*x#Z?t=$/edHp U~Q,޵P__iD*kb|9^Կ\Ys4=TGnxc9"5~ o- $B޸@V焾S^iRKFBa8"|U@9?PTz^j Z[4?d1tb8UxĞ |QZqϢ}au $:A<[oqsA*92<G >,$P W`tm9^_K hZ1s\fdFtl) pAg}E"[7~KCc*e$0PxS~eMN9mOy8\ \/_αgWEP9M@, N'KsKӴ95#!1 m*Fwg#rkmX럴oN;;D'm8 AZ> O>oO/9ٝ㏽GJ |cⵊHoS/f)W*#{cr Xv<wjom.9R(nP bN@r8oJҬt=.L-MD2I$I$gÞ:Dm^E6Eyn%E3u pw߳9//Vc=< a00`zPKIoQ%zc[v~妇a$Z.w;9{VS5[+mi8U.'Óp9/ïYagkuMm  H?/~ktsK5;hld?FpA"yU.ecAp 7=y'Pm}7ZWݭrɰ* .@RXl~ м5iyL;fQYp02k(((((((((s;jMb9&%6'iH$.qRI=8;d,~kZD7ܐѻIM{Ew_$o&a@x]rX= ( +x~|k+ GwF <8ǵvQEy_=[RuPS)s32,00}h((((7O-mGwz"-[Sg]Aߏ|N_뗟kPxU#ucQEx?uo.Mqhv{#{(9^MΪdH:|}ޞEcNSny'uu3sjXp2I[QEQEqGß5m[I=O.}E<0 HPaExmtkR2{ok$+`-x OAka: /A |dmQzQ@WSյ-?_ h.213"̾l 1>ր=R((((( { h~(,{{H0\y6! ۨ($-rp*fݦB-$H W]=xFN$53 +)psJ+g|xGo[89= =QEQEQEQEQEQEQEQEQEQEQEQEx!'_oQ7᷒nLGݐP[F=o܍xK Ancx2!W8ʮq,o;8,.໵;&A"6  88 €8]?a+7[%V᦯iw2G=K#OC؊/OzgfU~Fɠ7\8`22 lͽܩcFO?|dv<XmKOû{-B Lpȳ/Àp F7M!"7x^tU(se8==}o'? &niiQ)NLo{jZ7ln4BvFfRda^k6~u{kiJ E\ y$ ;IaXT|`>kH$n #}Xh=߉?,ψOxz~l ih່҇ ұ PxX(qyVO{x$P** Huw҈+6!J#O<5`_K7+* 쓝a8  >4YxJӧд{Cj]W)'ݙpA`x/~/.<5M/CcaSm8~PBԵwz^^]dT1Ѷ4e/u^'a!8FF8U$$(cWx/g]߇L cBv+ RfWCX]5h#ӝlB176w )PM AAcZNj OwXm/TG;2.UK;fݏi?:4 0ivy3$iX]3F9A~.>%е-kޤW-3e"FD-1+'' Sğ4:MWh+  w>Q@o.|IԵ B- ڷ) 2GLn\gs5׃v8 ݵ%\g nA?~xC5=O[m|aG$9$2M\jEE@~Q!ӴYA̅Y  P1]_ xys>I_+oG/pW!;^ i ]gP;!C/=rNIrvio^5֏q 5\tHn7!*ʀ,Bp `xz>6&EYE0Nїhfq1%7vo IbG=cx^yuB_O?$-!k+X<h@$t>?yͻdWu]i؞4; Vnݻ ]qd|XVM7P[;c  xaʩ( fF]E`"|yI<dד-Fo xU-n0ds J'5P[eZxV׵]w[cn*XaY 18Ƈ< _|1h>Wm6pzWaEG<[oqsA*92<G#[񞫠Z`oЕn#Nk(?}\jmb>U$³ #cq>il2-N o=&rQ#rH`,qEyo"_Y״JR3-#~ǁ_zIv>oc({aEyO_xYN姊9Ն~EY,>bǞsOv:/u^:>觻U (V ,냂[T(񟁴_iicE 1>n !e񝤂0@x=@#5K?A C\[v'oE>q zWQ@C|iw9ppO\QEy߆_𱿲o7]~gV[Ta$ q`1^Eq~Okx_O?67H{p鏺:aEQEQEQEQEQEQEQEQEQEQEQEQEk6~u{kiJ E\ y$ %<.nwIZ+A~\ y lÜo_i~𥤲EwhŊUp|0~zXmmⷷ8`GjQ@P_xKa|-59-T[ۛr? ڜfE^ v;X]i KEa&@ }פW ;£FPW8.5v<:~El!80LyQ ϮW?'%Ujė.&_wW^nHAWAI=w ?J +?u/_xSIcg, '1Jѳ,N|$a8(ⷋ-AO aܺ*؆d;ß;CuDzIujlQ6umr|<5ͣxWH6y2JD H5+U'0J.#3ܨ@ʽV^p"OHuw.'6Ԙ`>|tc^@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@?>wiT|N>Q'<}}׺lK/.q d8ڏ>.Z/k1-@Wڀ; P'Tۊs ?J _9>*`ų~Xy$k5[jvzu林+yd![p`r9\uC7͸+khqz(vr@6<k',t~>gs<#2)Qϥy>|MiO"]-IeّBLnO#h/uMg\=u0{*J3Ý͗?/W==#תi1CXŪM[ƷR0(Q=P?sjU|*/+Ȓ@<9?jڗvҤi}@tc O[yu=_M:|o#$"ٍ ɒ9I j|kX<>tBU8@@}9#- -DW*]4 ojzed?1G*H^?%O~ XaǣװPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPT7O-}2C L'.@9>֮Q@Q@Q@Q@Q@Q@Q@Q@'MѭK,`g.±)l3*PEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPPK 9wwPK:AOEBPS/dcommon/contbig.gif`GIF87a!!!111999BBBJJJRRRccckkksss{{{skk{{ZRRRJJƽ{sZRJRJB91)kcZB9)sskZRJ1޽ƽ{{ssskkkcƵZZRccZRRJJJB{BB9991ssckkZccR))!RRB!!JJ1))99!11ƌ)1R)k֔)s1RZJR{BJs9R1J!11J1J9k{csZk!1J!)cBR9J1B)91B!cRs{!)s!){1B!k!s!{ksksckckZc9B)1!)!)BJ9B1919έƌ!!)JJcZZ{!!!1RR{JJsBBkJJ{!!9BB{1!!J9)!!Z!!c1!!kR!!s9Z!BckJs)19!!c!!ZRZ,H rrxB(Kh" DժuICiи@S z$G3TTʖ&7!f b`D 0!A  k,>SO[!\ *_t  Exr%*_}!#U #4 & ֩3|b]L ]t b+Da&R_2lEٱZ`aC)/яmvUkS r(-iPE Vv_{z GLt\2s!F A#葡JY r|AA,hB}q|B`du }00(䡆<pb,G+oB C0p/x$…– ]7 @2HFc ) @AD \0 LHG',(A` `@SC)_" PH`}Y+_|1.K8pAKMA @?3҄$[JPA)+NH I ,@8G0/@R T,`pF8Ѓ)$^$ DDTDlA@ s;PKPK:AOEBPS/dcommon/darbbook.cssPKPK:A!OEBPS/dcommon/O_signature_clr.JPG"(JFIF``C    $.' ",#(7),01444'9=82<.342C  2!!22222222222222222222222222222222222222222222222222" }!1AQa"q2#BR$3br %&'()*456789:CDEFGHIJSTUVWXYZcdefghijstuvwxyz w!1AQaq"2B #3Rbr $4%&'()*56789:CDEFGHIJSTUVWXYZcdefghijstuvwxyz ?( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( (?O '~MQ$Vz;OlJi8L%\]UFjޙ%ԯS;rA]5ފ<׈]j7Ouyq$z'TQuw7Ŀ KX߁M2=S'TQt?.5w'97;~pq=" ~k?`'9q6 E|yayM^Om'fkC&<5x' ?A?Zx'jß={=SßM gVC.5+Hd֪xc^)Җufz{Cީ|D Vkznq|+Xa+{50rx{|OG.OϞ~f/ xxX[2H )c+#jpUOZYX\=SG ߨC|K@;_߆'e?LT?]:?>w ڔ`D^So~xo[Ӡ3i7B:Q8 Vc-ďoi:FM292~y_*_闱YN\Fr=xZ3鳎OwW_QEzW~c]REeaSM}}Hӏ4&.E]u=gMѠ+mF`rNn$w9gMa꺢nTuhf2Xv>އ a(Û6߭?<=>z'TQuw7Ŀ KX߁M2=S'TQt?.5Kko\.8S$TOX߀Gw?Zx汴X)C7~.i6(Щ=+4{mGӭ¸-]&'t_kV*I<1)4thtIsqpQJ+> \m^[aJ5)ny:4o&QEnyAEPEEss 72,PDۢ׃K W{Wjr+wگ iM/;pd?~&?@;7E4gv8 $l'z'TQuw7Ŀ Gֱ=ɿ&G?. iR(5W*$|?w᫼gkmIbHe/_t>tg%y.l}N5[]+Mk0ĠeHdPrsst'UiC,y8`V%9ZIia|ܪvi מYG,o}+kk{YbyIeb*sAtի82zWoEK5z*o-eo;n(P u-I)4Š(HQEQEQEQEhz(X/Đ?}Bk˩ ݏrk0]4>8XzV? }6$}d^F>nU K ?Bտk_9׾x~w'ߞ  uDŽtL ؈5c-E/"|_Oo.IH쐍=i*Iw5(ںw?t5s.)+tQ2dUt5Vĺ.jZ"@IRrZƅY4ߡ_;}ų(KyQf1Aǵt?sZg+?F5_oQR&Dg߿]6FuRD u>ڿxl7?IT8'shj^=.=J1rj1Wl$얲cPx;E,p$֟ˏkw qg"45(ǛkV/=+ũ)bYl~K#˝J_כ5&\F'I#8/|wʾ_Xj Q:os^T1.M_|TO.;?_  jF?g N 8nA2F%i =qW,G=5OU u8]Rq?wr'˻S+۾.ܼ 87Q^elo/T*?L|ۚ<%<,/v_OKs B5f/29n0=zqQq(ª=VX@*J(э(f5qJN_EVǞQEOuoѕOuoa5}gO?:߂8Wא|cڽ~]N&O( (<]>͠@VQ=^~U ̴m&\խ5i:}|}r~9՝f}_>'vVֲ$~^f30^in{\_.O F8to}?${φ|#x^#^n~w=~k~?'KRtO.㌡h![3Zu*ٷճ(ԟ]z_/W1(ԟ]v~g|Yq<ז0 ; b8֮s,w9\?uEyStKaª@\,)) (!EPEPEPEPEPzѧts{v>C/"N6`d*J2gGӧWqBq_1ZuΓ\X]r?=Ey88Mp&pKtO-"wR2 K^-Z< \c>V0^@O7x2WFjs<׻kZ(<Т(OFw/6$1[:ޯԯ#q~4|,LVPem=@=YLUxӃV}AUbcUB.Ds5*kٸAeG>PJxt͝ b88?*$~@ׯD VkraiJs}Q.20x&mXξ,Z]“A-J#`+-E/"<]\a'tZGy.(|lދ~gMK OZdxDŽU9T6ϯ^<Ϡt5CZ]].t۫S=s`ڳ%8iVK:nqe+#<.T6U>zWoy3^I {F?J~=G}k)K$$;$de8*G Uӟ4Ocºw}|]4=ݣ\x$ʠms?q^ipw\"ȿPs^Z Q_0GڼU.t}ROM[G#]8wٞ ӫ87}Cgw vHȩBM55vof =A_٭`Ygx[6 P,5}>蚊(0(+?>+?> k|TuXq6_ +szk :u_ Z߶Ak_U}Jc2u/1[_»ݸG41-bሬ۴}}Eȹפ_c?5gi @cL\L<68hF_Ih>X4K7UТ sMj =J7CKo>Օ5s:߀t ~ηaٿ?|gdL8+gG%o?x`دOqȱwc¨&TW_V_aI=dpG!wu۞սZ1yL50$(l3(:~'ַo A}a3N*[0ǭ HKQV}G@֜$ 9of$ArNqUOgË05#m?D)^_h//5_/<?4}Jį+GkpG4"$ r| >S4Ђ"S 1%R:ȝ 8;PKPz PK:AOEBPS/dcommon/feedback.gif7GIF89a'%(hp|fdx?AN5:dfeDGHɾTdQc`g*6DC\?ؘ||{;=E6JUՄfeA= >@,4`H.|`a (Q 9:&[|ځ,4p Y&BDb,!2@, $wPA'ܠǃ@CO~/d.`I @8ArHx9H75j L 3B/` P#qD*s 3A:3,H70P,R@ p!(F oԥ D;"0 ,6QBRɄHhI@@VDLCk8@NBBL2&pClA?DAk%$`I2 #Q+l7 "=&dL&PRSLIP)PɼirqМ'N8[_}w;PK-PK:AOEBPS/dcommon/booklist.gifGIF89a1޵֥΄kZ{Jk1Rs!BZ)B),@I9Z͓Ca % Dz8Ȁ0FZЌ0P !x8!eL8aWȠFD(~@p+rMS|ӛR$ v "Z:]ZJJEc{*=AP  BiA ']j4$*   & 9q sMiO?jQ = , YFg4.778c&$c%9;PKː5PK:AOEBPS/dcommon/cpyr.htm1 Oracle Legal Notices

Oracle Legal Notices

Copyright Notice

Copyright © 1994-2012, Oracle and/or its affiliates. All rights reserved.

Trademark Notice

Oracle and Java are registered trademarks of Oracle and/or its affiliates. Other names may be trademarks of their respective owners.

Intel and Intel Xeon are trademarks or registered trademarks of Intel Corporation. All SPARC trademarks are used under license and are trademarks or registered trademarks of SPARC International, Inc. AMD, Opteron, the AMD logo, and the AMD Opteron logo are trademarks or registered trademarks of Advanced Micro Devices. UNIX is a registered trademark of The Open Group.

License Restrictions Warranty/Consequential Damages Disclaimer

This software and related documentation are provided under a license agreement containing restrictions on use and disclosure and are protected by intellectual property laws. Except as expressly permitted in your license agreement or allowed by law, you may not use, copy, reproduce, translate, broadcast, modify, license, transmit, distribute, exhibit, perform, publish, or display any part, in any form, or by any means. Reverse engineering, disassembly, or decompilation of this software, unless required by law for interoperability, is prohibited.

Warranty Disclaimer

The information contained herein is subject to change without notice and is not warranted to be error-free. If you find any errors, please report them to us in writing.

Restricted Rights Notice

If this is software or related documentation that is delivered to the U.S. Government or anyone licensing it on behalf of the U.S. Government, the following notice is applicable:

U.S. GOVERNMENT RIGHTS Programs, software, databases, and related documentation and technical data delivered to U.S. Government customers are "commercial computer software" or "commercial technical data" pursuant to the applicable Federal Acquisition Regulation and agency-specific supplemental regulations. As such, the use, duplication, disclosure, modification, and adaptation shall be subject to the restrictions and license terms set forth in the applicable Government contract, and, to the extent applicable by the terms of the Government contract, the additional rights set forth in FAR 52.227-19, Commercial Computer Software License (December 2007). Oracle America, Inc., 500 Oracle Parkway, Redwood City, CA 94065.

Hazardous Applications Notice

This software or hardware is developed for general use in a variety of information management applications. It is not developed or intended for use in any inherently dangerous applications, including applications that may create a risk of personal injury. If you use this software or hardware in dangerous applications, then you shall be responsible to take all appropriate fail-safe, backup, redundancy, and other measures to ensure its safe use. Oracle Corporation and its affiliates disclaim any liability for any damages caused by use of this software or hardware in dangerous applications.

Third-Party Content, Products, and Services Disclaimer

This software or hardware and documentation may provide access to or information on content, products, and services from third parties. Oracle Corporation and its affiliates are not responsible for and expressly disclaim all warranties of any kind with respect to third-party content, products, and services. Oracle Corporation and its affiliates will not be responsible for any loss, costs, or damages incurred due to your access to or use of third-party content, products, or services.

Alpha and Beta Draft Documentation Notice

If this document is in prerelease status:

This documentation is in prerelease status and is intended for demonstration and preliminary use only. It may not be specific to the hardware on which you are using the software. Oracle Corporation and its affiliates are not responsible for and expressly disclaim all warranties of any kind with respect to this documentation and will not be responsible for any loss, costs, or damages incurred due to the use of this documentation.

Oracle Logo

PKN61PK:AOEBPS/dcommon/masterix.gif.GIF89a1ޜΌscJk1Rs!Bc1J),@IS@0"1 Ѿb$b08PbL,acr B@(fDn Jx11+\%1 p { display: none; } /* Class Selectors */ .ProductTitle { font-family: sans-serif; } .BookTitle { font-family: sans-serif; } .VersionNumber { font-family: sans-serif; } .PrintDate { font-family: sans-serif; font-size: small; } .PartNumber { font-family: sans-serif; font-size: small; } PKeӺ1,PK:AOEBPS/dcommon/larrow.gif#GIF87a絵ƌֵƽ{{ss֜ƔZZ{{{{ZZssZZccJJJJRRBBJJJJ991111))!!{,@pH,Ȥrl:ШtpHc`  өb[.64ꑈ53=Z]'yuLG*)g^!8C?-6(29K"Ĩ0Яl;U+K9^u2,@@ (\Ȱ Ë $P`lj 8x I$4H *(@͉0dа8tA  DсSP v"TUH PhP"Y1bxDǕ̧_=$I /& .)+ 60D)bB~=0#'& *D+l1MG CL1&+D`.1qVG ( "D2QL,p.;u. |r$p+5qBNl<TzB"\9e0u )@D,¹ 2@C~KU 'L6a9 /;<`P!D#Tal6XTYhn[p]݅ 7}B a&AƮe{EɲƮiEp#G}D#xTIzGFǂEc^q}) Y# (tۮNeGL*@/%UB:&k0{ &SdDnBQ^("@q #` @1B4i@ aNȅ@[\B >e007V[N(vpyFe Gb/&|aHZj@""~ӎ)t ? $ EQ.սJ$C,l]A `8A o B C?8cyA @Nz|`:`~7-G|yQ AqA6OzPbZ`>~#8=./edGA2nrBYR@ W h'j4p'!k 00 MT RNF6̙ m` (7%ꑀ;PKl-OJPK:AOEBPS/dcommon/index.gifGIF89a1޵ΥΥ{sc{BZs,@IM" AD B0 3.R~[D"0, ]ШpRNC  /& H&[%7TM/`vS+-+ q D go@" 4o'Uxcxcc&k/ qp zUm(UHDDJBGMԃ;PK(PK:AOEBPS/dcommon/bookbig.gif +GIF89a$!!!)))111999BBBJJJRRRZZZccckkksss{{{skkB991)))!!B11))1!JB9B9!!cZ9ƭƽssk{ZZRccZRRJJJBBB9c!!ν)1)k{s絽ƌkssֽZccJRRBJJ{9BB)11)99!!))11!!k!JZ!)RcJccBcs)1c)JZ!BR!)BZ)99J!Rk9!c11B)Z{)9Bkc1kB9BZ!Z{9Rs)Jkksk9kB1s1Jk9Rƥc{k9s)Z{1k91)s1Rk)Jc1J!))BZ!1k{csc{)19B!)Bcsc{ksc{kZs!RkJkJkքc{9Zks{ck9R)Bks9R9R1J!)Z1B!)c)9)99BR19kksBBJcc{ccBBZ))9kk!!199c11ZBB{9!!R!!Z!!c))!!kR!!s!!BcksRZ1c9B)R91c1)Z!R9B9k1)RcZ{)!1B9JB9B)!)J9B!& Imported from GIF image: bookbig.gif,$!!!)))111999BBBJJJRRRZZZccckkksss{{{skkB991)))!!B11))1!JB9B9!!cZ9ƭƽssk{ZZRccZRRJJJBBB9c!!ν)1)k{s絽ƌkssֽZccJRRBJJ{9BB)11)99!!))11!!k!JZ!)RcJccBcs)1c)JZ!BR!)BZ)99J!Rk9!c11B)Z{)9Bkc1kB9BZ!Z{9Rs)Jkksk9kB1s1Jk9Rƥc{k9s)Z{1k91)s1Rk)Jc1J!))BZ!1k{csc{)19B!)Bcsc{ksc{kZs!RkJkJkքc{9Zks{ck9R)Bks9R9R1J!)Z1B!)c)9)99BR19kksBBJcc{ccBBZ))9kk!!199c11ZBB{9!!R!!Z!!c))!!kR!!s!!BcksRZ1c9B)R91c1)Z!R9B9k1)RcZ{)!1B9JB9B)!)J9BH`\Ȑ:pظа"A6DBH,V@Dڹ'G"v Æ ܥ;n;!;>xAܽ[G.\rQC wr}BŊQ A9ᾑ#5Y0VȒj0l-GqF>ZpM rb ;=.ސW-WѻWo ha!}~ْ ; t 53 :\ 4PcD,0 4*_l0K3-`l.j!c Aa|2L4/1C`@@md;(H*80L0L(h*҇҆o#N84pC (xO@ A)J6rVlF r  fry†$r_pl5xhA+@A=F rGU a 1х4s&H Bdzt x#H%Rr (Ѐ7P`#Rщ'x" #0`@~i `HA'Tk?3!$`-A@1l"P LhʖRG&8A`0DcBH sq@AXB4@&yQhPAppxCQ(rBW00@DP1E?@lP1%T` 0 WB~nQ@;PKGC PK:AOEBPS/dcommon/rarrow.gif/GIF87a絵ƌֵƽ{{ss֜ƔZZ{{{{ZZssZZccJJJJRRBBJJJJ991111))!!{,@pH,Ȥrl:ШLlԸ NCqWEd)#34vwwpN|0yhX!'+-[F 'n5 H $/14w3% C .90" qF 7&E "D mnB|,c96) I @0BW{ᢦdN p!5"D`0 T 0-]ʜ$;PKJV^PK:AOEBPS/dcommon/mix.gifkGIF89aZZZBBBJJJkkk999sss!!!111cccֽ{{{RRR)))猌ƭ{s{sks!,@@pH,B$ 8 t:<8 *'ntPP DQ@rIBJLNPTVEMOQUWfj^!  hhG H  kCúk_a Ǥ^ h`B BeH mm  #F` I lpǎ,p B J\Y!T\(dǏ!Gdˆ R53ټ R;iʲ)G=@-xn.4Y BuU(*BL0PX v`[D! | >!/;xP` (Jj"M6 ;PK枰pkPK:AOEBPS/dcommon/doccd_epub.jsM /* Copyright 2006, 2012, Oracle and/or its affiliates. All rights reserved. Author: Robert Crews Version: 2012.3.17 */ function addLoadEvent(func) { var oldOnload = window.onload; if (typeof(window.onload) != "function") window.onload = func; else window.onload = function() { oldOnload(); func(); } } function compactLists() { var lists = []; var ul = document.getElementsByTagName("ul"); for (var i = 0; i < ul.length; i++) lists.push(ul[i]); var ol = document.getElementsByTagName("ol"); for (var i = 0; i < ol.length; i++) lists.push(ol[i]); for (var i = 0; i < lists.length; i++) { var collapsible = true, c = []; var li = lists[i].getElementsByTagName("li"); for (var j = 0; j < li.length; j++) { var p = li[j].getElementsByTagName("p"); if (p.length > 1) collapsible = false; for (var k = 0; k < p.length; k++) { if ( getTextContent(p[k]).split(" ").length > 12 ) collapsible = false; c.push(p[k]); } } if (collapsible) { for (var j = 0; j < c.length; j++) { c[j].style.margin = "0"; } } } function getTextContent(e) { if (e.textContent) return e.textContent; if (e.innerText) return e.innerText; } } addLoadEvent(compactLists); function processIndex() { try { if (!/\/index.htm(?:|#.*)$/.test(window.location.href)) return false; } catch(e) {} var shortcut = []; lastPrefix = ""; var dd = document.getElementsByTagName("dd"); for (var i = 0; i < dd.length; i++) { if (dd[i].className != 'l1ix') continue; var prefix = getTextContent(dd[i]).substring(0, 2).toUpperCase(); if (!prefix.match(/^([A-Z0-9]{2})/)) continue; if (prefix == lastPrefix) continue; dd[i].id = prefix; var s = document.createElement("a"); s.href = "#" + prefix; s.appendChild(document.createTextNode(prefix)); shortcut.push(s); lastPrefix = prefix; } var h2 = document.getElementsByTagName("h2"); for (var i = 0; i < h2.length; i++) { var nav = document.createElement("div"); nav.style.position = "relative"; nav.style.top = "-1.5ex"; nav.style.left = "1.5em"; nav.style.width = "90%"; while (shortcut[0] && shortcut[0].toString().charAt(shortcut[0].toString().length - 2) == getTextContent(h2[i])) { nav.appendChild(shortcut.shift()); nav.appendChild(document.createTextNode("\u00A0 ")); } h2[i].parentNode.insertBefore(nav, h2[i].nextSibling); } function getTextContent(e) { if (e.textContent) return e.textContent; if (e.innerText) return e.innerText; } } addLoadEvent(processIndex); PKo"nR M PK:AOEBPS/dcommon/toc.gifGIF89a1ΥΥ{c{Z{JkJk1Rk,@IK% 0| eJB,K-1i']Bt9dz0&pZ1o'q(؟dQ=3S SZC8db f&3v2@VPsuk2Gsiw`"IzE%< C !.hC IQ 3o?39T ҍ;PKv I PK:AOEBPS/dcommon/topnav.gifGIF89a1ֽ筽ޭƔkZZk{Bc{,@ ) l)-'KR$&84 SI) XF P8te NRtHPp;Q%Q@'#rR4P fSQ o0MX[) v + `i9gda/&L9i*1$#"%+ ( E' n7Ȇ(,҅(L@(Q$\x 8=6 'נ9tJ&"[Epljt p#ѣHb :f F`A =l|;&9lDP2ncH R `qtp!dȐYH›+?$4mBA9 i@@ ]@ꃤFxAD*^Ŵ#,(ε  $H}F.xf,BD Z;PK1FAPK:AOEBPS/dcommon/bp_layout.css# @charset "utf-8"; /* bp_layout.css Copyright 2007, Oracle and/or its affiliates. All rights reserved. */ body { margin: 0ex; padding: 0ex; } h1 { display: none; } #FOOTER { border-top: #0d4988 solid 10px; background-color: inherit; color: #e4edf3; clear: both; } #FOOTER p { font-size: 80%; margin-top: 0em; margin-left: 1em; } #FOOTER a { background-color: inherit; color: gray; } #LEFTCOLUMN { float: left; width: 50%; } #RIGHTCOLUMN { float: right; width: 50%; clear: right; /* IE hack */ } #LEFTCOLUMN div.portlet { margin-left: 2ex; margin-right: 1ex; } #RIGHTCOLUMN div.portlet { margin-left: 1ex; margin-right: 2ex; } div.portlet { margin: 2ex 1ex; padding-left: 0.5em; padding-right: 0.5em; border: 1px #bcc solid; background-color: #f6f6ff; color: black; } div.portlet h2 { margin-top: 0.5ex; margin-bottom: 0ex; font-size: 110%; } div.portlet p { margin-top: 0ex; } div.portlet ul { list-style-type: none; padding-left: 0em; margin-left: 0em; /* IE Hack */ } div.portlet li { text-align: right; } div.portlet li cite { font-style: normal; float: left; } div.portlet li a { margin: 0px 0.2ex; padding: 0px 0.2ex; font-size: 95%; } #NAME { margin: 0em; padding: 0em; position: relative; top: 0.6ex; left: 10px; width: 80%; } #PRODUCT { font-size: 180%; } #LIBRARY { color: #0b3d73; background: inherit; font-size: 180%; font-family: serif; } #RELEASE { position: absolute; top: 28px; font-size: 80%; font-weight: bold; } #TOOLS { list-style-type: none; position: absolute; top: 1ex; right: 2em; margin: 0em; padding: 0em; background: inherit; color: black; } #TOOLS a { background: inherit; color: black; } #NAV { float: left; width: 96%; margin: 3ex 0em 0ex 0em; padding: 2ex 0em 0ex 4%; /* Avoiding horizontal scroll bars. */ list-style-type: none; background: transparent url(../gifs/nav_bg.gif) repeat-x bottom; } #NAV li { float: left; margin: 0ex 0.1em 0ex 0em; padding: 0ex 0em 0ex 0em; } #NAV li a { display: block; margin: 0em; padding: 3px 0.7em; border-top: 1px solid gray; border-right: 1px solid gray; border-bottom: none; border-left: 1px solid gray; background-color: #a6b3c8; color: #333; } #SUBNAV { float: right; width: 96%; margin: 0ex 0em 0ex 0em; padding: 0.1ex 4% 0.2ex 0em; /* Avoiding horizontal scroll bars. */ list-style-type: none; background-color: #0d4988; color: #e4edf3; } #SUBNAV li { float: right; } #SUBNAV li a { display: block; margin: 0em; padding: 0ex 0.5em; background-color: inherit; color: #e4edf3; } #SIMPLESEARCH { position: absolute; top: 5ex; right: 1em; } #CONTENT { clear: both; } #NAV a:hover, #PORTAL_1 #OVERVIEW a, #PORTAL_2 #OVERVIEW a, #PORTAL_3 #OVERVIEW a, #PORTAL_4 #ADMINISTRATION a, #PORTAL_5 #DEVELOPMENT a, #PORTAL_6 #DEVELOPMENT a, #PORTAL_7 #DEVELOPMENT a, #PORTAL_11 #INSTALLATION a, #PORTAL_15 #ADMINISTRATION a, #PORTAL_16 #ADMINISTRATION a { background-color: #0d4988; color: #e4edf3; padding-bottom: 4px; border-color: gray; } #SUBNAV a:hover, #PORTAL_2 #SEARCH a, #PORTAL_3 #BOOKS a, #PORTAL_6 #WAREHOUSING a, #PORTAL_7 #UNSTRUCTURED a, #PORTAL_15 #INTEGRATION a, #PORTAL_16 #GRID a { position: relative; top: 2px; background-color: white; color: #0a4e89; } PK3( # PK:AOEBPS/dcommon/bookicon.gif:GIF87a!!!)))111999BBBJJJRRRZZZccckkksss{{{ޭ{{ZRRcZZRJJJBB)!!skRB9{sν{skskcZRJ1)!֭ƽ{ZZRccZJJBBB999111)JJ9BB1ZZB!!ﭵBJJ9BB!!))Jk{)1!)BRZJ{BsR!RRJsJ!J{s!JsBkks{RsB{J{c1RBs1ZB{9BJ9JZ!1BJRRs!9R!!9Z9!1)J19JJRk19R1Z)!1B9R1RB!)J!J1R)J119!9J91!9BkksBBJ119BBR!))9!!!JB1JJ!)19BJRZckތ1)1J9B,H*\hp >"p`ƒFF "a"E|ժOC&xCRz OBtX>XE*O>tdqAJ +,WxP!CYpQ HQzDHP)T njJM2ꔀJ2T0d#+I:<жk 'ꤱF AB @@nh Wz' H|-7f\A#yNR5 /PM09u UjćT|q~Yq@&0YZAPa`EzI /$AD Al!AAal 2H@$ PVAB&c*ؠ p @% p-`@b`uBa l&`3Ap8槖X~ vX$Eh`.JhAepA\"Bl, :Hk;PKx[?:PK:AOEBPS/dcommon/conticon.gif^GIF87a!!!)))111999BBBJJJRRRZZZccckkksss{{{ZRR޽{{ssskkkcccZ991ccRZZBBJJZck)19ZcsBJZ19J!k{k)Z1RZs1!B)!J91{k{)J!B!B911)k{cs!1s!9)s!9!B!k)k1c!)Z!R{9BJcckZZcBBJ99B119{{!!)BBRBBZ!))999R99Z!!999c1!9!)19B1)!B9R,  oua\h2SYPa aowwxYi 9SwyyxxyYSd $'^qYȵYvh ч,/?g{н.J5fe{ڶyY#%/}‚e,Z|pAܠ `KYx,ĉ&@iX9|`p ]lR1khٜ'E 6ÅB0J;t X b RP(*MÄ!2cLhPC <0Ⴁ  $4!B 6lHC%<1e H 4p" L`P!/,m*1F`#D0D^!AO@..(``_؅QWK>_*OY0J@pw'tVh;PKp*c^PK:AOEBPS/dcommon/blafdoc.cssL@charset "utf-8"; /* Copyright 2002, 2011, Oracle and/or its affiliates. All rights reserved. Author: Robert Crews Version: 2011.10.7 */ body { font-family: Tahoma, sans-serif; /* line-height: 125%; */ color: black; background-color: white; font-size: small; } * html body { /* http://www.info.com.ph/~etan/w3pantheon/style/modifiedsbmh.html */ font-size: x-small; /* for IE5.x/win */ f\ont-size: small; /* for other IE versions */ } h1 { font-size: 165%; font-weight: bold; border-bottom: 1px solid #ddd; width: 100%; } h2 { font-size: 152%; font-weight: bold; } h3 { font-size: 139%; font-weight: bold; } h4 { font-size: 126%; font-weight: bold; } h5 { font-size: 113%; font-weight: bold; display: inline; } h6 { font-size: 100%; font-weight: bold; font-style: italic; display: inline; } a:link { color: #039; background: inherit; } a:visited { color: #72007C; background: inherit; } a:hover { text-decoration: underline; } a img, img[usemap] { border-style: none; } code, pre, samp, tt { font-family: monospace; font-size: 110%; } caption { text-align: center; font-weight: bold; width: auto; } dt { font-weight: bold; } table { font-size: small; /* for ICEBrowser */ } td { vertical-align: top; } th { font-weight: bold; text-align: left; vertical-align: bottom; } ol ol { list-style-type: lower-alpha; } ol ol ol { list-style-type: lower-roman; } td p:first-child, td pre:first-child { margin-top: 0px; margin-bottom: 0px; } table.table-border { border-collapse: collapse; border-top: 1px solid #ccc; border-left: 1px solid #ccc; } table.table-border th { padding: 0.5ex 0.25em; color: black; background-color: #f7f7ea; border-right: 1px solid #ccc; border-bottom: 1px solid #ccc; } table.table-border td { padding: 0.5ex 0.25em; border-right: 1px solid #ccc; border-bottom: 1px solid #ccc; } span.gui-object, span.gui-object-action { font-weight: bold; } span.gui-object-title { } p.horizontal-rule { width: 100%; border: solid #cc9; border-width: 0px 0px 1px 0px; margin-bottom: 4ex; } div.zz-skip-header { display: none; } td.zz-nav-header-cell { text-align: left; font-size: 95%; width: 99%; color: black; background: inherit; font-weight: normal; vertical-align: top; margin-top: 0ex; padding-top: 0ex; } a.zz-nav-header-link { font-size: 95%; } td.zz-nav-button-cell { white-space: nowrap; text-align: center; width: 1%; vertical-align: top; padding-left: 4px; padding-right: 4px; margin-top: 0ex; padding-top: 0ex; } a.zz-nav-button-link { font-size: 90%; } div.zz-nav-footer-menu { width: 100%; text-align: center; margin-top: 2ex; margin-bottom: 4ex; } p.zz-legal-notice, a.zz-legal-notice-link { font-size: 85%; /* display: none; */ /* Uncomment to hide legal notice */ } /*************************************/ /* Begin DARB Formats */ /*************************************/ .bold, .codeinlinebold, .syntaxinlinebold, .term, .glossterm, .seghead, .glossaryterm, .keyword, .msg, .msgexplankw, .msgactionkw, .notep1, .xreftitlebold { font-weight: bold; } .italic, .codeinlineitalic, .syntaxinlineitalic, .variable, .xreftitleitalic { font-style: italic; } .bolditalic, .codeinlineboldital, .syntaxinlineboldital, .titleinfigure, .titleinexample, .titleintable, .titleinequation, .xreftitleboldital { font-weight: bold; font-style: italic; } .itemizedlisttitle, .orderedlisttitle, .segmentedlisttitle, .variablelisttitle { font-weight: bold; } .bridgehead, .titleinrefsubsect3 { font-weight: bold; } .titleinrefsubsect { font-size: 126%; font-weight: bold; } .titleinrefsubsect2 { font-size: 113%; font-weight: bold; } .subhead1 { display: block; font-size: 139%; font-weight: bold; } .subhead2 { display: block; font-weight: bold; } .subhead3 { font-weight: bold; } .underline { text-decoration: underline; } .superscript { vertical-align: super; } .subscript { vertical-align: sub; } .listofeft { border: none; } .betadraft, .alphabetanotice, .revenuerecognitionnotice { color: #e00; background: inherit; } .betadraftsubtitle { text-align: center; font-weight: bold; color: #e00; background: inherit; } .comment { color: #080; background: inherit; font-weight: bold; } .copyrightlogo { text-align: center; font-size: 85%; } .tocsubheader { list-style-type: none; } table.icons td { padding-left: 6px; padding-right: 6px; } .l1ix dd, dd dl.l2ix, dd dl.l3ix { margin-top: 0ex; margin-bottom: 0ex; } div.infoboxnote, div.infoboxnotewarn, div.infoboxnotealso { margin-top: 4ex; margin-right: 10%; margin-left: 10%; margin-bottom: 4ex; padding: 0.25em; border-top: 1pt solid gray; border-bottom: 1pt solid gray; } p.notep1 { margin-top: 0px; margin-bottom: 0px; } .tahiti-highlight-example { background: #ff9; text-decoration: inherit; } .tahiti-highlight-search { background: #9cf; text-decoration: inherit; } .tahiti-sidebar-heading { font-size: 110%; margin-bottom: 0px; padding-bottom: 0px; } /*************************************/ /* End DARB Formats */ /*************************************/ @media all { /* * * { line-height: 120%; } */ dd { margin-bottom: 2ex; } dl:first-child { margin-top: 2ex; } } @media print { body { font-size: 11pt; padding: 0px !important; } a:link, a:visited { color: black; background: inherit; } code, pre, samp, tt { font-size: 10pt; } #nav, #search_this_book, #comment_form, #comment_announcement, #flipNav, .noprint { display: none !important; } body#left-nav-present { overflow: visible !important; } } PKʍPK:AOEBPS/dcommon/rightnav.gif&GIF89a1ֽ筽ޭƔkZZk{Bc{,@ ) l)- $CҠҀ ! D1 #:aS( c4B0 AC8 ְ9!%MLj Z * ctypJBa H t>#Sb(clhUԂ̗4DztSԙ9ZQҀEPEPEPEPEPEPEPM=iԍP Gii c*yF 1׆@\&o!QY00_rlgV;)DGhCq7~..p&1c:u֫{fI>fJL$}BBP?JRWc<^j+χ5b[hֿ- 5_j?POkeQ^hֿ1L^ H ?Qi?z?+_xɔŪ\썽O]χ>)xxV/s)e6MI7*ߊޛv֗2J,;~E4yi3[nI`Ѱe9@zXF*W +]7QJ$$=&`a۾?]N T䏟'X)Ɣkf:j |>NBWzYx0t!* _KkoTZ?K Gc+UyڹgNuh^iSo5{\ܹ3Yos}.>if FqR5\/TӮ#]HS0DKu{($"2xִ{SBJ8=}Y=.|Tsц2UЫ%.InaegKo z ݎ3ֹxxwM&2S%';+I',kW&-"_¿_ Vq^ܫ6pfT2RV A^6RKetto^[{w\jPZ@ޢN4/XN#\42j\(z'j =~-I#:q[Eh|X:sp* bifp$TspZ-}NM*B-bb&*xUr#*$M|QWY ~p~- fTED6O.#$m+t$˙H"Gk=t9r娮Y? CzE[/*-{c*[w~o_?%ƔxZ:/5𨴟q}/]22p qD\H"K]ZMKR&\C3zĽ[PJm]AS)Ia^km M@dК)fT[ijW*hnu Ͳiw/bkExG£@f?Zu.s0(<`0ֹoxOaDx\zT-^ѧʧ_1+CP/p[w 9~U^[U<[tĽwPv[yzD1W='u$Oeak[^ |Gk2xv#2?¹TkSݕ| rݞ[Vi _Kz*{\c(Ck_܏|?u jVڔ6f t?3nmZ6f%QAjJf9Rq _j7Z-y.pG$Xb]0')[_k;$̭?&"0FOew7 z-cIX岛;$u=\an$ zmrILu uٞ% _1xcUW%dtÀx885Y^gn;}ӭ)場QEQ@Q@Q@Q@Q@Q@!4xPm3w*]b`F_931˜[ן+(> E ly;<;MF-qst+}DH @YKlLmؤciN<|]IU)Lw(8t9FS(=>og<\Z~u_+X1ylsj'eՃ*U3`C!N9Q_WܱhKc93^ua>H ƕGk=8~e#_?{ǀe-[2ٔ7;=&K挑5zsLdx(e8#{1wS+ΝVkXq9>&yஏh$zq^0~/j@:/«Vnce$$uoPp}MC{$-akH@ɫ1O !8R9s5ԦYmϧ'OUṡ5T,!Ԛ+s#1Veo=[)g>#< s)ƽُA^䠮ωFUj(ǩ|N3Jڷ睁ϱuږZYGOTsI<&drav?A^_f׻B$,O__ԿC`it{6>G׈C~&$y؎v1q9Sc1fH[ѽ>,gG'0'@Vw,BO [#>ﱺg5ΒFVD%Yr:O5 Tu+O멃]ی38Ze}R&ѝ_xzc1DXgس;<,_,{ƽY'AS#oF.M#~cBuEx7G+Y)(5q+GCV;qF+CLQ)qEC&6z𿊘z}?&w=+)??&\g{;V??׻xGœdٿ׼-Nc')3K]N)iLTӿCdb7Q^a N sd>Fz[0S^s'Zi 77D}kWus ab~~H(>.fif9,~|Jk;YN3H8Y(t6Q݉k͇_÷Z+2߄&[ +Tr^藺97~c܎=[f1RrBǓ^kEMhxYVm<[џ6| kqbѱ| YA{G8p?\UM7Z66 g1U1igU69 u5Pƪ:VVZC=[@ҹ¨$kSmɳО\vFz~i3^a Osŧυ9Q}_3 όO{/wgoet39 vO2ea;Ύ7$U#?k+Ek&dpzbӱ+TaB0gN{[N7Gי}U7&@?>Fz~E!a@s ?'67XxO*!?qi]֏TQN@tI+\^s8l0)2k!!iW8F$(yOּT.k,/#1:}8uT˾+5=O/`IW G֯b.-<= HOm;~so~hW5+kS8s.zwE| ?4ӿw/K N 9?j(#0UT` Wzw}:_*9m>󑓀F?ELzv=8q:=WgJ`nDr Zе<ֹ](Q@Q@Q@Q@Q@Q@Q@Q@ 'IdC0EYJVcMty_~u+Sw-aO n<[YJgL#6i g5ЖDZ14cʝ!!\/M}/_AYR__>oC? _?7_G#RERW쏞KB}JxGSkǕA pƱơP m]hwB7U$Zq M95"3q1ioATߚ{g.t uu2k=;h#YB= fgS :TdLԃ!44mFK{Hrd^7oz|BVr<{)6AXգV»|>*/hS܏z͆OM=Εq (s|s׊LKQI :9NJ)P+!ʣoAF>+=@I}"x/}۠1aנc¹4emC:>p_xWKX` >R3_S½èųp3޺u3N e یbmͺ<_ mnݮ1Op?Gm)Qb%N585'%Ahs\6yw!"&Ɨ._wk)}GP;Z!#\"< *oƾ\)}N>"լ/~]Lg}pBG X?<zZ#x69S=6) jzx=y9O&>+e!!? ?s~k5Gʏ)?*ce7Ox~k5􇔾Q/e7/Ԑ#3OgNC0] ;_FiRl>Q.g>!%k#ú:Kn'&}?U@\pџPtp)v<{_i}Oվֲ3XIYIx~b<D?(=_JXH=bbi=Oh?_ C_O)}oW쏜? %Ƶ;-RYFi`wۭ{ϖZMtQ$"c_+ԃx1*0b;ԕ݋ESQEQEQEQEQEQEQEQEQEQZ(1F)h1K@XLRE&9P (bf{RӨ&)PEPEPbԴPGKZ(iإbn(:A%S0(-&)P+ ڎԴP11F)h&:LRmQ@Q@Š(((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((PKje88PK:AOEBPS/dcommon/help.gif!GIF89a1εֵ֜֜{kZsBc{,@ )sƠTQ$8(4ʔ%ŌCK$A HP`$h8ŒSd+ɡ\ H@%' 6M HO3SJM /:Zi[7 \( R9r ERI%  N=aq   qƦs *q-n/Sqj D XZ;PKއ{&!PK:A OEBPS/toc.htmWm Table of Contents

Contents

Title and Copyright Information

Preface

What's New

1 C Development Environment

2 Working with TimesTen Databases in ODBC

3 TimesTen Support for OCI

4 TimesTen Support for Pro*C/C++

5 XLA and TimesTen Event Management

6 Distributed Transaction Processing: XA

7 ODBC Application Tuning

8 TimesTen Utility API

9 XLA Reference

10 TimesTen ODBC Functions and Options

Index

PK\ʚ\mWmPK:AOEBPS/xa_dtp.htm Distributed Transaction Processing: XA

6 Distributed Transaction Processing: XA

This chapter describes the TimesTen implementation of the X/Open XA standard.

The TimesTen implementation of the XA interfaces is intended for use by transaction managers in distributed transaction processing (DTP) environments. You can use these interfaces to write a new transaction manager or to adapt an existing transaction manager, such as Oracle Tuxedo, to operate with TimesTen resource managers.

The purpose of this chapter is to provide information specific to the TimesTen implementation of XA and is intended to be used with the following documents:

This chapter includes the following topics:


Important:

  • The TimesTen XA implementation does not work with IMDB Cache. The start of any XA transaction will fail if the cache agent is running.

  • You cannot execute an XA transaction if replication is enabled.

  • Do not execute DDL statements within an XA transaction.


Overview of XA

This section provides a brief overview of the following XA concepts:

X/Open DTP model

Figure 6-1 that follows illustrates the interfaces defined by the X/Open DTP model.

Figure 6-1 Distributed transaction processing model

Description of Figure 6-1 follows
Description of "Figure 6-1 Distributed transaction processing model"

The TX interface is what applications use to communicate with a transaction manager. The figure shows an application communicating global transactions to the transaction manager. In the DTP model, the transaction manager breaks each global transaction down into multiple branches and distributes them to separate resource managers for service. It uses the XA interface to coordinate each transaction branch with the appropriate resource manager.

In the context of TimesTen XA, the resource managers can be a collection of TimesTen databases, or databases in combination with other commercial databases that support XA.

Global transaction control provided by the TX and XA interfaces is distinct from local transaction control provided by the native ODBC interface. It is generally best to maintain separate connections for local and global transactions. Applications can obtain a connection handle to a TimesTen resource manager in order to initiate both local and global transactions over the same connection. See "TimesTen tt_xa_context function to obtain ODBC handle from XA connection" for more information.

Two-phase commit

In an XA implementation, the transaction manager commits the distributed branches of a global transaction by using a two-phase commit protocol.

  1. In phase one, the transaction manager directs each resource manager to prepare to commit, which is to verify and guarantee it can commit its respective branch of the global transaction. If a resource manager cannot commit its branch, the transaction manager rolls back the entire transaction in phase two.

  2. In phase two, the transaction manager either directs each resource manager to commit its branch or, if a resource manager reported it was unable to commit in phase one, rolls back the global transaction.

Note the following optimizations:

  • If a global transaction is determined by the transaction manager to have involved only one branch, it skips phase one and commits the transaction in phase two.

  • If a global transaction branch is read-only, where it does not generate any transaction log records, the transaction manager commits the branch in phase one and skips phase two for that branch.


Note:

The transaction manager considers the global transaction committed if and only if all branches successfully commit.

Using XA in TimesTen

The TimesTen implementation of XA provides an API that is consistent with the API specified in Distributed Transaction Processing: The XA Specification. This section describes what you should know when using the TimesTen implementation of XA, covering the following topics:

TimesTen database requirements for XA

To guarantee global transaction consistency, TimesTen XA transaction branches must be durable. The TimesTen implementation of the xa_prepare(), xa_rollback(), and xa_commit() functions log their actions to disk, regardless of the value set in the DurableCommits general connection attribute or by the ttDurableCommit built-in procedure. (The behavior is equivalent to what occurs with a setting of DurableCommits=1. See "DurableCommits" in Oracle TimesTen In-Memory Database Reference for related information.) If you must recover from a failure, both the resource manager and the TimesTen transaction manager have a consistent view of which transaction branches were active in a prepared state at the time of failure.

Global transaction recovery in TimesTen

When a database is loaded from disk to recover after a failure or unexpected termination, any global transactions that were prepared but not committed are left pending, or in doubt. Normal processing is not enabled until the disposition of all in-doubt transactions has been resolved.

After connection and recovery are complete, TimesTen checks for in-doubt transactions. If there are no in-doubt transactions, operation proceeds as normal. If there are in-doubt transactions, other connections may be created, but virtually all operations are prohibited on those connections until the in-doubt transactions are resolved. Any other ODBC or JDBC calls result in the following error:

Error 11035 - "In-doubt transactions awaiting resolution in recovery must be 
resolved first"

The list of in-doubt transactions can be retrieved through the XA implementation of xa_recover(), then dealt with through the XA call xa_commit(), xa_rollback(), or xa_forget(), as appropriate. After all of the in-doubt transactions are cleared, operation proceeds normally.

This scheme should be adequate for systems that operate strictly under control of the transaction manager, since the first thing the transaction manager should do after connect is to call xa_recover().

If the transaction manager is unavailable or cannot resolve an in-doubt transaction, you can use the ttXactAdmin utility -HCommit or -HAbort option to independently commit or abort the individual transaction branches. Be aware, however, that these ttXactAdmin options require ADMIN privilege. See "ttXactAdmin" in Oracle TimesTen In-Memory Database Reference.

Considerations in using standard XA functions with TimesTen

This section describes some issues concerning the use of TimesTen XA functions, which are of interest if you are writing your own transaction manager.

xa_open()

The xa_info string used by xa_open() should be a connection string identical to that supplied to SQLDriverConnect, such as:

"DSN=DataStoreResource;UID=MyName"

XA limits the length of the string to 256 characters. See MAXINFOSIZE in the xa.h header file.

The xa_open() function automatically turns off autocommit when it opens an XA connection.

A connection opened with xa_open() must be closed with a call to xa_close().


Note:

Any user, other than the instance administrator, who wishes to connect to TimesTen must be granted the CREATE SESSION privilege. Refer to "Access control for connections".

xa_close()

The xa_info string used by xa_close() should be empty.

Transaction id (XID) parameter

XA uniquely identifies global transactions by using a transaction ID, referred to as an XID. The XID is a required parameter for XA functions that manipulate a transaction. Internally, TimesTen maps XIDs to its own transaction identifiers.

The XID defined by the XA standard has some of its members (such as formatID, gtrid_length, and bqual_length) defined as type long. Be aware that this can cause problems when 32-bit client applications connect to a 64-bit server, or 64-bit client applications connect to a 32-bit server. This is because long is a 32-bit integer on 32-bit platforms but a 64-bit integer on 64-bit platforms, other than 64-bit Windows. Hence, TimesTen internally uses only the 32 least significant bits of those XID members regardless of the platform type of client or server. TimesTen does not support any value in those XID members that does not fit in a 32-bit integer.

TimesTen tt_xa_context function to obtain ODBC handle from XA connection

TimesTen provides the function tt_xa_context(), which enables you to acquire the ODBC connection handle associated with an XA connection opened by xa_open().

Syntax

#include <tt_xa.h>
int tt_xa_context(int* rmid, SQLHENV* henv, SQLHDBC* hdbc);

Parameters

ParameterTypeDescription
rmidintThe specified resource manager ID

If this is non-null, the function returns the handles associated with the rmid value.

If the specified rmid is null, the function returns the handles associated with the first connection on this thread. For example, specify a null value if the connection has been opened outside the scope of the user-written code, where rmid is unknown. This establishes context in the application environment.

henvout SQLHENVThe environment handle associated with the current xa_open() context
hdbcout SQLHDBCThe connection handle associated with the current xa_open() context

Return values

0: Success

1: rmid not found

-1: Invalid parameter

Example

In the following example, assume Tuxedo has used xa_open() and xa_start() to open a connection to the database and start a transaction. To do further ODBC processing on the connection, use the tt_xa_context() function to locate the SQLHENV and SQLHDBC handles allocated by xa_open().

Example 6-1 Using tt_xa_context() to locate handles

do_insert()
{

    SQLHENV henv;
    SQLHDBC hdbc;
    SQLHSTMT hstmt;

    /* retrieve the handles for the current connection */
    tt_xa_context(NULL, &henv, &hdbc);

    /* now we can do our ODBC programming as usual */
    SQLAllocStmt(hdbc, &hstmt);

    SQLExecDirect(hstmt, "insert into t1 values (1)", SQL_NTS);

    SQLFreeStmt(hstmt, SQL_DROP);
}

Considerations in calling ODBC functions over XA connections in TimesTen

This section describes some TimesTen issues to be aware of when calling ODBC functions using an ODBC handle associated with an XA connection opened by xa_open().

Autocommit

To simplify operation and prevent possible contradictions, xa_open() automatically turns off autocommit when it opens an XA connection.

Autocommit may subsequently be turned on or off during local transaction work, but must be turned off before xa_start() is called to begin work on a global transaction branch. If autocommit is on, a call to xa_start() returns the following error:

Error 11030 - "Autocommit must be turned off when working on global (XA) transactions"

Once xa_start() has been called to begin work on a global transaction branch, autocommit may not be turned on until such work has been completed through a call to xa_end(). Any attempt to turn on autocommit in this case will result in the same error as above.

Local transaction COMMIT and ROLLBACK

Once work on a global transaction branch has commenced through a call to xa_start(), attempts to perform a local commit or rollback using SQLTransact results in the following error:

Error 11031 - "Illegal combination of local transaction and global (XA) transaction"

Closing open cursors

Any open statement cursors must be closed using SQLFreeStmt with a value of SQL_CLOSE before calling xa_end() to end work on a global transaction branch. Otherwise, the following error is returned:

Error 11032 - "XA request failed due to open cursors"

XA resource manager switch

Each resource manager defines a switch in its xa.h header file that provides the transaction manager with access to the XA functions in the resource managers. The transaction manager never directly calls an XA interface function. Instead, it calls the function in the switch table, which, in turn, points to the appropriate function in the resource manager. This enables resource managers to be added and removed without the requirement to recompile the applications.

In the TimesTen implementation of XA, the functions in the XA switch, xa_switch_t, point to their respective functions defined in a TimesTen switch, tt_xa_switch.

xa_switch_t

The xa_switch_t structure defined by the XA specification is as follows:

/* XA Switch Data Structure */
#define RMNAMESZ       32         /* length of resource manager name, */
                                  /* including the null terminator */
#define MAXINFOSIZE    256        /* maximum size in bytes of xa_info strings, */
                                  /* including the null terminator */

struct xa_switch_t
{

    char name[RMNAMESZ];                /* name of resource manager */
    long flags;                         /* resource manager specific options */
    long version;                       /* must be 0 */

int (*xa_open_entry)(char*, int, long);        /* xa_open function pointer */
int (*xa_close_entry)(char*, int, long);       /* xa_close function pointer*/
int (*xa_start_entry)(XID*, int, long);        /* xa_start function pointer */
int (*xa_end_entry)(XID*, int, long);          /* xa_end function pointer */
int (*xa_rollback_entry)(XID*, int, long);     /* xa_rollback function pointer */
int (*xa_prepare_entry)(XID*, int, long);      /* xa_prepare function pointer */
int (*xa_commit_entry)(XID*, int, long);       /* xa_commit function pointer */
int (*xa_recover_entry)(XID*, long, int, long); /* xa_recover function pointer*/
int (*xa_forget_entry)(XID*, int, long);        /* xa_forget function pointer */
int (*xa_complete_entry)(int*, int*, int, long); /* xa_complete function pointer */
};

typedef struct xa_switch_t xa_switch_t;
/*
 * Flag definitions for the RM switch
 */
#define TMNOFLAGS 0x00000000L     /* no resource manager features selected */
#define TMREGISTER 0x00000001L    /* resource manager dynamically registers */
#define TMNOMIGRATE 0x00000002L   /* RM does not support association migration */
#define TMUSEASYNC 0x00000004L    /* RM supports asynchronous operations */

tt_xa_switch

The tt_xa_switch names the actual functions implemented by a TimesTen resource manager. It also indicates explicitly that association migration is not supported. In addition, dynamic registration and asynchronous operations are not supported.

struct xa_switch_t
tt_xa_switch =
{
    "TimesTen", /* name of resource manager */
    TMNOMIGRATE, /* RM does not support association migration */
    0,
    tt_xa_open,
    tt_xa_close,
    tt_xa_start,
    tt_xa_end,
    tt_xa_rollback,
    tt_xa_prepare,
    tt_xa_commit,
    tt_xa_recover,
    tt_xa_forget,
    tt_xa_complete
};

XA error handling in TimesTen

The XA specification has a limited and strictly defined set of errors that can be returned from XA interface calls. The ODBC SQLError function returns XA-defined errors along with any additional information.

The TimesTen XA-related errors begin at number 11000. Errors 11002 through 11020 correspond to the errors defined by the XA standard.

See "Warnings and Errors" in Oracle TimesTen In-Memory Database Error Messages and SNMP Traps for the complete list of errors.

XA support through the Windows ODBC driver manager

This section discusses issues and procedures for using XA with the Windows ODBC driver manager. (UNIX ODBC driver managers are not considered.)

Issues to consider

XA support through the ODBC driver manager requires special handling. There are two fundamental problems:

  • The XA interface is not part of the defined ODBC interface. If the XA symbols are directly referenced in an application, it is not possible to link with only the driver manager library to resolve all the external references.

  • By design, the driver manager determines which driver .dll file to load at connect time, when you call SQLConnect or SQLDriverConnect. XA dictates that the connection should be opened through xa_open(). But the correct xa_open() entry point cannot be located until the .dll is loaded during the connect operation itself.

Note that the driver manager objective of database portability is generally not applicable here, since each XA implementation is essentially proprietary. The primary benefit of driver manager support for XA-enabled applications is to enable TimesTen-specific applications to run transparently with either the TimesTen direct driver or the TimesTen Client/Server driver.

Linking to the TimesTen ODBC XA driver manager extension library

On Windows installations, TimesTen provides a driver manager extension library, ttxadm1122.dll, for XA functions. Applications can make XA calls directly, but must link in the extension library.

To link with the ttxadm1122.dll library, applications must include ttxadm1122.lib before odbc32.lib in their link line. For example:

# Link with the ODBC driver manager
appldm.exe:appl.obj
       $(CC) /Feappldm.exe appl.obj ttxadm1122.lib odbc32.lib

Note:

The XA driver manager extension is implemented only for 32-bit Windows applications.

Configuring Tuxedo to use TimesTen XA

To configure Tuxedo to use the TimesTen resource managers, perform the following tasks.


Important:

Though TimesTen XA has been demonstrated to work with the Oracle Tuxedo transaction manager, TimesTen cannot guarantee the operation of DTP software beyond the TimesTen implementation of XA.


Notes:

  • The examples in this section use the direct driver. You can also use the client/server library or driver manager library with the XA extension library.

  • Information on configuring TimesTen for object-relational mapping frameworks and application servers, including Oracle WebLogic Application Server, is available in the TimesTen Quick Start. Click J2EE and OR Mapping under Configuration and Setup.


Update the $TUXDIR/udataobj/RM file

To integrate the TimesTen XA resource manager into the Oracle Tuxedo system, update the $TUXDIR/udataobj/RM file to identify the TimesTen resource manager, the name of the TimesTen resource manager switch (tt_xa_switch), and the name of the library for the resource manager.

On UNIX platforms, add the following:

TimesTen:tt_xa_switch:-Linstall_dir/lib -ltten

For example:

TimesTen:tt_xa_switch:-L/opt/TimesTen/giraffe/lib -ltten

On Windows platforms, add the following:

TimesTen;tt_xa_switch;install_dir\lib\ttdv1122.lib

For example:

TimesTen;tt_xa_switch;C:\TimesTen\giraffe\lib\ttdv1122.lib

Note:

The install_dir is the path to the TimesTen home directory.

Build the Tuxedo transaction manager server

Use the buildtms command to build a transaction manager server for the TimesTen resource manager. Then copy the TMS_TT file created by buildtms to the $TUXDIR/bin directory.

On UNIX platforms, the commands are the following:

buildtms -o TMS_TT -r TimesTen -v
cp TMS_TT $TUXDIR/bin

On Windows platforms, the commands are the following:

buildtms -o TMS_TT -r TimesTen -v
copy TMS_TT.exe %TUXDIR%\bin

Update the GROUPS section in the UBBCONFIG file

For TMSNAME, specify the TMS_TT file created by the buildtms command described in the preceding section.

TMSNAME=TMS_TT

Enter a line for each TimesTen resource manager that specifies a group name, followed by the LMID, GRPNO, and OPENINFO parameters. Your OPENINFO string should look like this:

OPENINFO="TimesTen:DSN=DSNname"

Where DSNname is the name of the database.

Note that on Windows, Tuxedo servers run as user SYSTEM. Add the UID general connection attribute to the OPENINFO string to specify a user other than SYSTEM:

OPENINFO="TimesTen:DSN=DSNname;UID=user"

Do not specify a CLOSEINFO parameter for any TimesTen resource manager.

Example 6-2 shows the portions of a UBBCONFIG file used to configure two TimesTen resource managers, GROUP1 and GROUP2.

Example 6-2 Configuring TimesTen resource managers

*RESOURCES
...
*MACHINES
...
ENGSERV LMID=simple
*GROUPS
DEFAULT: TMSNAME=TMS_TT TMSCOUNT=2
GROUP1
    LMID=simple GRPNO=1 OPENINFO="TimesTen:DSN=MyDSN1;UID=MyName"
GROUP2
    LMID=simple GRPNO=2 OPENINFO="TimesTen:DSN=MyDSN2;UID=MyName"
*SERVERS
DEFAULT:
    CLOPT="-A"
simpserv1 SRVGRP=GROUP1 SRVID=1
simpserv2 SRVGRP=GROUP2 SRVID=2

*SERVICES
TOUPPER
TOLOWER

Compile the servers

Set the CFLAGS environment variable to include the install_dir/include directory that contains the TimesTen include files. Then use the buildserver command to construct an Oracle Tuxedo ATMI server load module.

On UNIX platforms, enter the following.

export CFLAGS=-Iinstall_dir/
buildserver -o server -f server.c -r TimesTen -s SERVICE

On Windows platforms, enter the following.

set CFLAGS=-Iinstall_dir\
buildserver -o server -f server.c -r TimesTen -s SERVICE

Note:

The install_dir is the path to the TimesTen home directory.

Example 6-3 shows an example of how to use the buildclient command to construct the client module (simpcl) and the buildserver command to construct the two server modules described in the UBBCONFIG file in Example 6-2 above.

Example 6-3 Construct server modules

set CFLAGS=-IC:\TimesTen\giraffe\
buildclient -o simpcl -f simpcl.c
buildserver -v -t -o simpserv1 -f simpserv1.c -r TimesTen -s TOUPPER
buildserver -v -t -o simpserv2 -f simpserv2.c -r TimesTen -s TOLOWER
PKքPK:AOEBPS/writing_app.htm Working with TimesTen Databases in ODBC

2 Working with TimesTen Databases in ODBC

This chapter covers TimesTen programming features and describes how to use ODBC to connect to and use the TimesTen database. It includes the following topics:

Note that TimesTen supports ODBC 2.5, Extension Level 1, with additional features for Extension Level 2 where those features are included in Chapter 10, "TimesTen ODBC Functions and Options".


Notes:


Managing TimesTen database connections

The Oracle TimesTen In-Memory Database Operations Guide contains information about creating a DSN for the database. The type of DSN you create depends on whether your application will connect directly to the database or will connect by a client.

If you intend to connect directly to the database, refer to "Managing TimesTen Databases" in Oracle TimesTen In-Memory Database Operations Guide. There are sections on creating a DSN for a direct connection from UNIX or Windows.

If you intend to create a client connection to the database, refer to "Working with the TimesTen Client and Server" in Oracle TimesTen In-Memory Database Operations Guide. There are sections on creating a DSN for a client/server connection from UNIX or Windows.


Notes:

  • In TimesTen, the user name and password must be for a valid user who has been granted CREATE SESSION privilege to connect to the database.

  • A TimesTen connection cannot be inherited from a parent process. If a process opens a database connection before creating (forking) a child process, the child must not use the connection.


The rest of this section covers the following topics:

SQLConnect, SQLDriverConnect, SQLAllocConnect, SQLDisconnect functions

The following ODBC functions are available for connecting to a database and related functionality:

  • SQLConnect: Loads a driver and connects to the database. The connection handle points to where information about the connection is stored, including status, transaction state, results, and error information.

  • SQLDriverConnect: This is an alternative to SQLConnect when more information is required than what is supported by SQLConnect, which is just data source (the database), user name, and password.

  • SQLAllocConnect: Allocates memory for a connection handle within the specified environment.

  • SQLDisconnect: Disconnect from the database. Takes the existing connection handle as its only argument.

Refer to ODBC API reference documentation for additional details about these functions.

Connecting to and disconnecting from a database

This section provides examples of connecting to and disconnecting from the database.

Example 2-1 Connect and disconnect (excerpt)

This code fragment invokes SQLConnect and SQLDisconnect to connect to and disconnect from the database named FixedDs. The first invocation of SQLConnect by any application causes the creation of the FixedDs database. Subsequent invocations of SQLConnect would connect to the existing database.

#include <sql.h>
SQLRETURN retcode;
SQLHDBC hdbc;

...
retcode = SQLConnect(hdbc,
                     (SQLCHAR*)"FixedDs", SQL_NTS,
                     (SQLCHAR*)"johndoe", SQL_NTS,
                     (SQLCHAR*)"opensesame", SQL_NTS);
...
retcode = SQLDisconnect(hdbc);
...

Example 2-2 Connect and disconnect (complete program)

This example contains a complete program that creates, connects to, and disconnects from a database. The example uses SQLDriverConnect instead of SQLConnect to set up the connection, and uses SQLAllocConnect to allocate memory. It also shows how to get error messages. (In addition, you can refer to "Handling Errors".)

#ifdef WIN32
#include <windows.h>
#else
#include <sqlunix.h>
#endif
#include <sql.h>
#include <sqlext.h>
#include <stdio.h>
#include <string.h>
#include <stdlib.h>

static void chkReturnCode(SQLRETURN rc, SQLHENV henv,
                          SQLHDBC hdbc, SQLHSTMT hstmt,
                          char* msg, char* filename,
                          int lineno, BOOL err_is_fatal);
#define DEFAULT_CONNSTR "DSN=sampledb_1122;PermSize=32"

int
main(int ac, char** av)
{
   SQLRETURN rc = SQL_SUCCESS;
                  /* General return code for the API */
   SQLHENV henv = SQL_NULL_HENV;
                  /* Environment handle */
   SQLHDBC hdbc = SQL_NULL_HDBC;
                  /* Connection handle */
   SQLHSTMT hstmt = SQL_NULL_HSTMT;
                  /* Statement handle */
   SQLCHAR connOut[255];
                  /* Buffer for completed connection string */
   SQLSMALLINT connOutLen;
                  /* Number of bytes returned in ConnOut */
   SQLCHAR *connStr = (SQLCHAR*)DEFAULT_CONNSTR;
                  /* Connection string */
   rc = SQLAllocEnv(&henv);
   if (rc != SQL_SUCCESS) {
      fprintf(stderr, "Unable to allocate an "
             "environment handle\n");
    exit(1);
   }
   rc = SQLAllocConnect(henv, &hdbc);
   chkReturnCode(rc, henv, SQL_NULL_HDBC,
              SQL_NULL_HSTMT,
              "Unable to allocate a "
              "connection handle\n",
              __FILE__, __LINE__, 1);

   rc = SQLDriverConnect(hdbc, NULL,
                         connStr, SQL_NTS,
                         connOut, sizeof(connOut),
                         &connOutLen,
                         SQL_DRIVER_NOPROMPT);
   chkReturnCode(rc, henv, hdbc, SQL_NULL_HSTMT,
                 "Error in connecting to the"
                 " database\n",
                 __FILE__, __LINE__, 1);
   rc = SQLAllocStmt(hdbc, &hstmt);
   chkReturnCode(rc, henv, hdbc, SQL_NULL_HSTMT,
                 "Unable to allocate a "
                 "statement handle\n",
                 __FILE__, __LINE__, 1);

   /* Your application code here */

   if (hstmt != SQL_NULL_HSTMT) {
     rc = SQLFreeStmt(hstmt, SQL_DROP);
     chkReturnCode(rc, henv, hdbc, hstmt,
                   "Unable to free the "
                   "statement handle\n",
                    __FILE__, __LINE__, 0);
   }

   rc = SQLDisconnect(hdbc);
   chkReturnCode(rc, henv, hdbc,
                 SQL_NULL_HSTMT,
                 "Unable to close the "
                 "connection\n",
                 __FILE__, __LINE__, 0);

   rc = SQLFreeConnect(hdbc);
   chkReturnCode(rc, henv, hdbc,
                 SQL_NULL_HSTMT,
                 "Unable to free the "
                 "connection handle\n",
                 __FILE__, __LINE__, 0);

   rc = SQLFreeEnv(henv);
   chkReturnCode(rc, henv, SQL_NULL_HDBC,
                 SQL_NULL_HSTMT,
                 "Unable to free the "
                 "environment handle\n",
                 __FILE__, __LINE__, 0);
     return 0;
   }

   static void
   chkReturnCode(SQLRETURN rc, SQLHENV henv,
                 SQLHDBC hdbc, SQLHSTMT hstmt,
                 char* msg, char* filename,
                 int lineno, BOOL err_is_fatal)
   {
      #define MSG_LNG 512
      SQLCHAR sqlState[MSG_LNG];
      /* SQL state string */
      SQLINTEGER nativeErr;
      /* Native error code */
      SQLCHAR errMsg[MSG_LNG];
      /* Error msg text buffer pointer */
      SQLSMALLINT errMsgLen;
      /* Error msg text Available bytes */
      SQLRETURN ret = SQL_SUCCESS;
      if (rc != SQL_SUCCESS &&
          rc != SQL_NO_DATA_FOUND ) {
         if (rc != SQL_SUCCESS_WITH_INFO) {
          /*
           * It's not just a warning
           */
         fprintf(stderr, "*** ERROR in %s, line %d:"
                  " %s\n",
                  filename, lineno, msg);
     }
     /*
      * Now see why the error/warning occurred
      */
     while (ret == SQL_SUCCESS ||
            ret == SQL_SUCCESS_WITH_INFO) {
       ret = SQLError(henv, hdbc, hstmt,
                      sqlState, &nativeErr,
                      errMsg, MSG_LNG,
                      &errMsgLen);
       switch (ret) {
         case SQL_SUCCESS:
           fprintf(stderr, "*** %s\n"
                    "*** ODBC Error/Warning = %s, "
                    "TimesTen Error/Warning "
                    " = %d\n",
                    errMsg, sqlState,
                    nativeErr);
         break;
       case SQL_SUCCESS_WITH_INFO:
         fprintf(stderr, "*** Call to SQLError"
                 " failed with return code of "
                 "SQL_SUCCESS_WITH_INFO.\n "
                 "*** Need to increase size of"
                 " message buffer.\n");
         break;
       case SQL_INVALID_HANDLE:
         fprintf(stderr, "*** Call to SQLError"
                 " failed with return code of "
                 "SQL_INVALID_HANDLE.\n");
         break;
       case SQL_ERROR:
         fprintf(stderr, "*** Call to SQLError"
                 " failed with return code of "
                 "SQL_ERROR.\n");
         break;
       case SQL_NO_DATA_FOUND:
         break;
        } /* switch */
      } /* while */
      if (rc != SQL_SUCCESS_WITH_INFO && err_is_fatal) {
        fprintf(stderr, "Exiting.\n");
        exit(-1);
      }
   }
}

Setting connection attributes programmatically

You can set or override connection attributes programmatically by specifying a connection string when you connect to a database.

Refer to Oracle TimesTen In-Memory Database Operations Guide for general information about connection attributes. General connection attributes require no special privilege. First connection attributes are set when the database is first loaded, and persist for all connections. Only the instance administrator can load a database with changes to first connection attribute settings. Refer to "Connection Attributes" in Oracle TimesTen In-Memory Database Reference for additional information, including specific information about any particular connection attribute.

Example 2-3 Connect and use store-level locking

This code fragment connects to a database named mydsn and indicates in the SQLDriverConnect call that the application should use a passthrough setting of 3. Note that PassThrough is a general connection attribute.

SQLHDBC hdbc;
SQLCHAR ConnStrOut[512];
SQLSMALLINT cbConnStrOut;
SQLRETURN rc;

rc = SQLDriverConnect(hdbc, NULL,
    "DSN=mydsn;PassThrough=3", SQL_NTS,
    ConnStrOut, sizeof (ConnStrOut),
    &cbConnStrOut, SQL_DRIVER_NOPROMPT);

Note:

Each connection to a database opens several files. An application with many threads, each with a separate connection, has several files open for each thread. Such an application can exceed the maximum allowed (or configured maximum) number of file descriptors that may be simultaneously open on the operating system. In this case, configure your system to allow a larger number of open files. See "Limits on number of open files" in Oracle TimesTen In-Memory Database Reference.

Access control for connections

In order for any user (other than the instance administrator) to connect to a database, the CREATE SESSION privilege must be granted. This is a system privilege so must be granted to the user by the instance administrator or someone with ADMIN privilege, either directly or through the PUBLIC role. Refer to "Managing Access Control" in Oracle TimesTen In-Memory Database Operations Guide for additional information and examples.

To create an XLA connection and execute XLA functionality, a user must be granted the XLA privilege, discussed in "Access control impact on XLA", in addition to the CREATE SESSION privilege.

Managing TimesTen data

This section provides detailed information on working with data in a TimesTen database. It includes the following topics.

TimesTen include files

In addition to standard C "include" files, your application must include the TimesTen files shown in the following table.

Include fileDescription
timesten.hTimesTen ODBC include file
tt_errCode.hTimesTen native error codes

SQL statement execution within C applications

"Working with Data in a TimesTen Database" in Oracle TimesTen In-Memory Database Operations Guide describes how to use SQL to manage data. This section describes general formats used to execute a SQL statement within a C application. The following topics are covered:


Note:

Access control privileges are checked both when SQL is prepared and when it is executed in the database. Refer to "Considering TimesTen features for access control" for related information.

SQLExecDirect and SQLExecute functions

There are two ODBC functions to execute SQL statements:

  • SQLExecute: Executes a statement that has been prepared with SQLPrepare. After the application is done with the results, they can be discarded and SQLExecute can be run again using different parameter values.

    This is typically used for DML statements with bind parameters, or statements that are being executed more than once.

  • SQLExecDirect: Prepares and executes a statement.

    This is typically used for DDL statements or for DML statements that would execute only a few times and without bind parameters.

Refer to ODBC API reference documentation for details about these functions.

Executing a SQL statement

You can use the SQLExecDirect function as shown in Example 2-4.

The next section, "Preparing and executing queries and working with cursors", shows usage of the SQLExecute and SQLPrepare functions.

Example 2-4 Executing a SQL statement with SQLExecDirect

This code sample creates a table, NameID, with two columns: CustID and CustName. The table maps character names to integer identifiers.

#include <sql.h>
SQLRETURN rc;
SQLHSTMT hstmt;
...
rc = SQLExecDirect(hstmt, (SQLCHAR*)
     "CREATE TABLE NameID (CustID INTEGER, CustName VARCHAR(50))",
     SQL_NTS);
if (rc != SQL_SUCCESS && rc != SQL_SUCCESS_WITH_INFO)
     ... /* handle error */

Preparing and executing queries and working with cursors

This section shows the basic steps of preparing and executing a query and working with cursors. Applications use cursors to scroll through the results of a query, examining one result row at a time.


Important:

In TimesTen, any operation that ends your transaction, such as a commit or rollback, closes all cursors associated with the connection.

In the ODBC setting, a cursor is always associated with a result set. This association is made by the ODBC driver. The application can control cursor characteristics, such as the number of rows to fetch at one time, using SQLSetStmtOption options documented in "Option support for SQLSetStmtOption and SQLGetStmtOption". The steps involved in executing a query typically include the following.

  1. Use SQLPrepare to prepare the SELECT statement for execution.

  2. Use SQLBindParameter, if the statement has parameters, to bind each parameter to an application address. See "SQLBindParameter function". (Note that Example 2-5 below does not bind parameters.)

  3. Call SQLBindCol to assign the storage and data type for a column of results, binding column results to local variable storage in your application.

  4. Call SQLExecute to execute the SELECT statement. See "SQLExecDirect and SQLExecute functions".

  5. Call SQLFetch to fetch the results. Specify the statement handle.

  6. Call SQLFreeStmt to free the statement handle. Specify the statement handle and either SQL_CLOSE, SQL_DROP, SQL_UNBIND, or SQL_RESET_PARAMS.

Refer to ODBC API reference documentation for details on these ODBC functions. Examples are shown throughout this chapter and in the TimesTen Quick Start (through the "ODBC (C)" link under SAMPLE PROGRAMS).


Notes:

  • Access control privileges are checked both when SQL is prepared and when it is executed in the database. Refer to "Considering TimesTen features for access control" for related information.

  • By default (when connection attribute PrivateCommands=0), TimesTen shares prepared statements between connections, so subsequent prepares of the same statement on different connections execute very quickly.


Example 2-5 Executing a query and working with the cursor

This example illustrates how to prepare and execute a query using ODBC calls. Error checking has been omitted to simplify the example. In addition to ODBC functions mentioned previously, this example uses SQLNumResultCols to return the number of columns in the result set, SQLDescribeCol to return a description of one column of the result set (column name, type, precision, scale, and nullability), and SQLBindCol to assign the storage and data type for a column in the result set. These are all described in detail in ODBC API reference documentation.

#include <sql.h>

SQLHSTMT hstmt;
SQLRETURN rc;
int i;
SQLSMALLINT numCols;
SQLCHAR colname[32];
SQLSMALLINT colnamelen, coltype, scale, nullable;
SQLULEN collen [MAXCOLS];
SQLLEN outlen [MAXCOLS];
SQLCHAR* data [MAXCOLS];

/* other declarations and program set-up here */

/* Prepare the SELECT statement */
rc = SQLPrepare(hstmt,
(SQLCHAR*) "SELECT * FROM EMP WHERE AGE>20",
SQL_NTS);
/* ... */

/* Determine number of columns in result rows */
rc = SQLNumResultCols(hstmt, &numCols);

/* ... */

/* Describe and bind the columns */
for (i = 0; i < numCols; i++) {
    rc = SQLDescribeCol(hstmt,
         (SQLSMALLINT) (i + 1),
         colname,(SQLSMALLINT)sizeof(colname), &colnamelen, &coltype, &collen[i],
         &scale, &nullable);

    /* ... */

   data[i] = (SQLCHAR*) malloc (collen[i] +1);  //Allocate space for column data.
   rc = SQLBindCol(hstmt, (SQLSMALLINT) (i + 1),
                   SQL_C_CHAR, data[i],
                   COL_LEN_MAX, &outlen[i]);

   /* ... */

}
/* Execute the SELECT statement */
rc = SQLExecute(hstmt);

/* ... */

/* Fetch the rows */
if (numCols > 0) {
  while ((rc = SQLFetch(hstmt)) == SQL_SUCCESS ||
          rc == SQL_SUCCESS_WITH_INFO) {
    /* ... "Process" the result row */
  } /* end of for-loop */
  if (rc != SQL_NO_DATA_FOUND)
    fprintf(stderr,
            "Unable to fetch the next row\n");

/* Close the cursor associated with the SELECT statement */
  rc = SQLFreeStmt(hstmt, SQL_CLOSE);
}

TimesTen deferred prepare

In standard ODBC, a SQLPrepare call compiles a SQL statement so that information about the statement, such as column descriptions for the result set, is available to the application and accessible through calls such as SQLDescribeCol. To accomplish this, the SQLPrepare call must communicate with the server for processing.

This is in contrast, for example, to expected behavior under Oracle Call Interface (OCI), where a prepare call is expected to be a lightweight operation performed on the client to simply extract names and positions of parameters.

To avoid unwanted round trips between client and server, and also to make the behavior consistent with OCI expectations, the TimesTen client library implementation of SQLPrepare performs what is referred to as a "deferred prepare", where the request is not sent to the server until required. Examples of when the round trip would be required:

  • When there is a SQLExecute call. Note that if there is a deferred prepare call that has not yet been sent to the server, a SQLExecute call on the client is converted to a SQLExecDirect call.

  • When there is a request for information about the query that can only be supplied by the SQL engine, such as when there is a SQLDescribeCol call, for example. Many such calls in standard ODBC can access information previously returned by a SQLPrepare call, but with the deferred prepare functionality the SQLPrepare call is sent to the server and the information is returned to the application only as needed.


Note:

Deferred prepare functionality is not implemented (and not necessary) with the TimesTen direct driver.

The deferred prepare implementation requires no changes at the application or user level; however, be aware that calling any of the following functions may result in a round trip to the server if the required information from a previously prepared statement has not yet been retrieved:

  • SQLColAttributes

  • SQLDescribeCol

  • SQLDescribeParam

  • SQLNumResultCols

  • SQLNumParams

  • SQLGetStmtOption (for options that depend on the statement having been compiled by the SQL engine)

Also be aware that when calling any of these functions, any error from an earlier SQLPrepare call may be deferred until one of these calls is executed. In addition, these calls may return errors specific to SQLPrepare as well as errors specific to themselves.

Prefetching multiple rows of data

A TimesTen extension to ODBC enables applications to prefetch multiple rows of data into the ODBC driver buffer. This can improve performance of client/server applications.

The TT_PREFETCH_COUNT connection option determines how many rows a SQLFetch call will prefetch. Note that this option provides no benefit for an application using a direct connection to TimesTen.

TT_PREFETCH_COUNT can be set in a call to either SQLSetConnectOption or SQLSetStmtOption. The value can be any integer from 0 to 128, inclusive. Following is an example.

rc = SQLSetConnectOption(hdbc, TT_PREFETCH_COUNT, 100);

With this setting, the first SQLFetch call on the connection will prefetch 100 rows. Subsequent SQLFetch calls will fetch from the ODBC buffer instead of from the database, until the buffer is depleted. After it is depleted, the next SQLFetch call will fetch another 100 rows into the buffer, and so on.

To disable prefetch, set TT_PREFETCH_COUNT to 1.

When the prefetch count is set to 0, TimesTen uses a default value, depending on the isolation level you have set for the database. With Read Committed isolation level, the default prefetch value is 5. With Serializable isolation level, the default is 128. The default prefetch value is a good setting for most applications. Generally, a higher value may result in better performance for larger result sets, at the expense of slightly higher resource use.

Binding parameters and executing statements

This section discusses how to bind input or output parameters for SQL statements. The following topics are covered:


Note:

The term "bind parameter" as used in TimesTen developer guides (in keeping with ODBC terminology) is equivalent to the term "bind variable" as used in TimesTen PL/SQL documents (in keeping with Oracle PL/SQL terminology).

SQLBindParameter function

The ODBC SQLBindParameter function is used to bind parameters for SQL statements. This could include input, output, or input/output parameters.

To bind an input parameter through ODBC, use the SQLBindParameter function with a setting of SQL_PARAM_INPUT for the fParamType argument. Refer to ODBC API reference documentation for details about the SQLBindParameter function. Table 2-1 provides a brief summary of its arguments.

To bind an output or input/output parameter through ODBC, use the SQLBindParameter function with a setting of SQL_PARAM_OUTPUT or SQL_PARAM_INPUT_OUTPUT, respectively, for the fParamType argument. As with input parameters, use the fSqlType, cbColDef, and ibScale arguments (as applicable) to specify data types.

Table 2-1 SQLBindParameter arguments

ArgumentTypeDescription

hstmt

SQLHSTMT

Statement handle

ipar

SQLUSMALLINT

Parameter number, sequentially from left to right, starting with 1

fParamType

SQLSMALLINT

Indicating input or output: SQL_PARAM_INPUT, SQL_PARAM_OUTPUT, or SQL_PARAM_INPUT_OUTPUT

fCType

SQLSMALLINT

C data type of the parameter

fSqlType

SQLSMALLINT

SQL data type of the parameter

cbColDef

SQLULEN

The precision of the parameter, such as the maximum number of bytes for binary data, the maximum number of digits for a number, or the maximum number of characters for character data

ibScale

SQLSMALLINT

The scale of the parameter, referring to the maximum number of digits to the right of the decimal point, where applicable

rgbValue

SQLPOINTER

Pointer to a buffer for the data of the parameter

cbValueMax

SQLLEN

Maximum length of the rgbValue buffer, in bytes

pcbValue

SQLLEN*

Pointer to a buffer for the length of the parameter



Note:

Refer to "Data Types" in Oracle TimesTen In-Memory Database SQL Reference for information about precision and scale of TimesTen data types.

Determination of parameter type assignments and type conversions

Bind parameter type assignments are determined as follows.

  • Parameter type assignments for statements that execute in TimesTen are determined by TimesTen. Specifically:

    • For SQL statements that execute within TimesTen, the TimesTen query optimizer determines data types of SQL parameters.

  • Parameter type assignments for statements that execute in Oracle Database, or according to Oracle Database functionality, are determined by the application as follows.

    • For SQL statements that execute within Oracle Database—that is, passthrough statements from the Oracle In-Memory Database Cache (IMDB Cache)—the application must specify data types through its calls to the ODBC SQLBindParameter function, according to the fSqlType, cbColDef, and ibScale arguments of that function, as applicable.

    • For PL/SQL blocks or procedures that execute within TimesTen, where the PL/SQL execution engine has the same basic functionality as in Oracle Database, the application must specify data types through its calls to SQLBindParameter (the same as for SQL statements that execute within Oracle Database).

      So regarding host binds for PL/SQL (the variables, or parameters, that are preceded by a colon within a PL/SQL block), note that the type of a host bind is effectively declared by the call to SQLBindParameter, according to fSqlType and the other arguments as applicable, and is not declared within the PL/SQL block.

The ODBC driver performs any necessary type conversions between C values and SQL or PL/SQL types. For any C-to-SQL or C-to-PL/SQL combination that is not supported, an error will occur. These conversions can be from a C type to a SQL or PL/SQL type (input parameter), from a SQL or PL/SQL type to a C type (output parameter), or both (input/output parameter).

Table 2-2 documents the mapping between ODBC types and SQL or PL/SQL types.

Table 2-2 ODBC SQL to TimesTen SQL or PL/SQL type mappings

ODBC type (fSqlType)SQL or PL/SQL type

SQL_BIGINT

NUMBER

SQL_BINARY

RAW(p)

SQL_BIT

PLS_INTEGER

SQL_CHAR

CHAR(p)

SQL_DATE

DATE

SQL_DECIMAL

NUMBER

SQL_DOUBLE

NUMBER

SQL_FLOAT

BINARY_DOUBLE

SQL_INTEGER

PLS_INTEGER

SQL_NUMERIC

NUMBER

SQL_REAL

BINARY_FLOAT

SQL_REFCURSOR

REF CURSOR

SQL_ROWID

ROWID

SQL_SMALLINT

PLS_INTEGER

SQL_TIMESTAMP

TIMESTAMP(s)

SQL_TINYINT

PLS_INTEGER

SQL_VARBINARY

RAW(p)

SQL_VARCHAR

VARCHAR2(p)

SQL_WCHAR

NCHAR(p)

SQL_WVARCHAR

NVARCHAR2(p)



Notes:

  • The notation (p) indicates precision is according to the SQLBindParameter argument cbColDef.

  • The notation (s) indicates scale is according to the SQLBindParameter argument ibScale.

  • Most applications should use SQL_VARCHAR rather than SQL_CHAR for binding character data. Use of SQL_CHAR may result in unwanted space padding to the full precision of the parameter type.


Binding input parameters

For input parameters to PL/SQL in TimesTen, use the fSqlType, cbColDef, and ibScale arguments (as applicable) of the ODBC SQLBindParameter function to specify data types. This is in contrast to how SQL input parameters are supported, as noted in the preceding section, "Determination of parameter type assignments and type conversions".

In addition, the rgbValue, cbValueMax, and pcbValue arguments of SQLBindParameter are used as follows for input parameters:

  • rgbValue: Before statement execution, points to the buffer where the application places the parameter value to be passed to the application.

  • cbValueMax: For character and binary data, indicates the maximum length of the incoming value that rgbValue points to, in bytes. For all other data types, cbValueMax is ignored, and the length of the value that rgbValue points to is determined by the length of the C data type specified in the fCType argument of SQLBindParameter.

  • pcbValue: Points to a buffer that contains one of the following before statement execution:

    • The actual length of the value that rgbValue points to

      Note: For input parameters, this would be valid only for character or binary data.

    • SQL_NTS for a null-terminated string

    • SQL_NULL_DATA for a null value

Binding output parameters

For output parameters from PL/SQL in TimesTen, as noted for input parameters previously, use the fSqlType, cbColDef, and ibScale arguments (as applicable) of the ODBC SQLBindParameter function to specify data types.

In addition, the rgbValue, cbValueMax, and pcbValue arguments of SQLBindParameter are used as follows for output parameters:

  • rgbValue: During statement execution, points to the buffer where the value returned from the statement should be placed.

  • cbValueMax: For character and binary data, indicates the maximum length of the outgoing value that rgbValue points to, in bytes. For all other data types, cbValueMax is ignored, and the length of the value that rgbValue points to is determined by the length of the C data type specified in the fCType argument of SQLBindParameter.

    Note that ODBC null-terminates all character data, even if the data is truncated. Therefore, when an output parameter has character data, cbValueMax must be large enough to accept the maximum data value plus a null terminator (one additional byte for CHAR and VARCHAR parameters, or two additional bytes for NCHAR and NVARCHAR parameters).

  • pcbValue: Points to a buffer that contains one of the following after statement execution:

    • The actual length of the value that rgbValue points to (for all C types, not just character and binary data)

      Note: This is the length of the full parameter value, regardless of whether the value can fit in the buffer that rgbValue points to.

    • SQL_NULL_DATA for a null value

Example 2-6 Binding output parameters

This example shows how to prepare, bind, and execute a PL/SQL anonymous block. The anonymous block assigns bind parameter a the value 'abcde' and bind parameter b the value 123.

SQLPrepare prepares the anonymous block. SQLBindParameter binds the first parameter (a) as an output parameter of type SQL_VARCHAR and binds the second parameter (b) as an output parameter of type SQL_INTEGER. SQLExecute executes the anonymous block.

{
  SQLHSTMT      hstmt;
  char          aval[11];
  SQLLEN        aval_len;
  SQLINTEGER    bval;
  SQLLEN        bval_len;
 
  SQLAllocStmt(hdbc, &hstmt);
 
  SQLPrepare(hstmt,
        (SQLCHAR*)"begin :a := 'abcde'; :b := 123; end;",
        SQL_NTS);
 
  SQLBindParameter(hstmt, 1, SQL_PARAM_OUTPUT, SQL_C_CHAR, SQL_VARCHAR,
         10, 0, (SQLPOINTER)aval, sizeof(aval), &aval_len);
 
  SQLBindParameter(hstmt, 2, SQL_PARAM_OUTPUT, SQL_C_SLONG, SQL_INTEGER,
         0, 0, (SQLPOINTER)&bval, sizeof(bval), &bval_len);
 
  SQLExecute(hstmt);
  printf("aval = [%s] (length = %d), bval = %d\n", aval, (int)aval_len, bval);
}

Binding input/output parameters

For input/output parameters to and from PL/SQL in TimesTen, as noted for input parameters previously, use the fSqlType, cbColDef, and ibScale arguments (as applicable) of the ODBC SQLBindParameter function to specify data types.

In addition, the rgbValue, cbValueMax, and pcbValue arguments of SQLBindParameter are used as follows for input/output parameters:

  • rgbValue: This is first used before statement execution as described in "Binding input parameters". Then it is used during statement execution as described in the preceding section, "Binding output parameters". Note that for an input/output parameter, the outgoing value from a statement execution will be the incoming value to the statement execution that immediately follows, unless that is overridden by the application. Also, for input/output values bound when you are using data-at-execution, the value of rgbValue serves as both the token that would be returned by the ODBC SQLParamData function and as the pointer to the buffer where the outgoing value will be placed.

  • cbValueMax: For character and binary data, this is first used as described in "Binding input parameters". Then it is used as described in the preceding section, "Binding output parameters". For all other data types, cbValueMax is ignored, and the length of the value that rgbValue points to is determined by the length of the C data type specified in the fCType argument of SQLBindParameter.

    Note that ODBC null-terminates all character data, even if the data is truncated. Therefore, when an input/output parameter has character data, cbValueMax must be large enough to accept the maximum data value plus a null terminator (one additional byte for CHAR and VARCHAR parameters, or two additional bytes for NCHAR and NVARCHAR parameters).

  • pcbValue: This is first used before statement execution as described in "Binding input parameters". Then it is used after statement execution as described in the preceding section, "Binding output parameters".


Important:

For character and binary data, carefully consider the value you use for cbValueMax. A value that is smaller than the actual buffer size may result in spurious truncation warnings. A value that is greater than the actual buffer size may cause the ODBC driver to overwrite the rgbValue buffer, resulting in memory corruption.

Binding duplicate parameters in SQL statements

TimesTen supports two distinct modes for binding duplicate parameters in a SQL statement. (Regarding PL/SQL statements, see "Binding duplicate parameters in PL/SQL".)

  • Oracle mode, where multiple occurrences of the same parameter name are considered to be distinct parameters

  • Traditional TimesTen mode, as in earlier releases, where multiple occurrences of the same parameter name are considered to be the same parameter

You can choose the desired mode through the DuplicateBindMode TimesTen general connection attribute. DuplicateBindMode=0 (the default) is for the Oracle mode, and DuplicateBindMode=1 is for the TimesTen mode. Because this is a general connection attribute, different connections to the same database can use different values. Refer to "DuplicateBindMode" in Oracle TimesTen In-Memory Database Reference for additional information about this attribute.

The rest of this section provides details for each mode, considering the following query:

SELECT * FROM employees
  WHERE employee_id < :a AND manager_id > :a AND salary < :b;

Notes:

  • This discussion applies only to SQL statements issued directly from ODBC (not through PL/SQL, for example).

  • The use of "?" for parameters, not supported in Oracle Database, is supported by TimesTen in either mode.


Oracle mode for duplicate parameters

In Oracle mode, where DuplicateBindMode=0, multiple occurrences of the same parameter name in a SQL statement are considered to be different parameters. When parameter position numbers are assigned, a number is given to each parameter occurrence without regard to name duplication. The application must, at a minimum, bind a value for the first occurrence of each parameter name. For any subsequent occurrence of a given parameter name, the application has the following choices.

  • It can bind a different value for the occurrence.

  • It can leave the parameter occurrence unbound, in which case it takes the same value as the first occurrence.

In either case, each occurrence still has a distinct parameter position number.

To use a different value for the second occurrence of a in the SQL statement above:

SQLBindParameter(..., 1, ...); /* first occurrence of :a */
SQLBindParameter(..., 2, ...); /* second occurrence of :a */
SQLBindParameter(..., 3, ...); /* occurrence of :b */

To use the same value for both occurrences of a:

SQLBindParameter(..., 1, ...); /* both occurrences of :a */
SQLBindParameter(..., 3, ...); /* occurrence of :b */

Parameter b is considered to be in position 3 regardless.

In Oracle mode, the SQLNumParams ODBC function returns 3 for the number of parameters in the example.

TimesTen mode for duplicate parameters

In TimesTen mode, where DuplicateBindMode=1, SQL statements containing duplicate parameters are parsed such that only distinct parameter names are considered as separate parameters.

Binding is based on the position of the first occurrence of a parameter name. Subsequent occurrences of the parameter name are not given their own position numbers. All occurrences of the same parameter name take on the same value.

For the SQL statement above, the two occurrences of a are considered to be a single parameter, so cannot be bound separately:

SQLBindParameter(..., 1, ...); /* both occurrences of :a */
SQLBindParameter(..., 2, ...); /* occurrence of :b */

Note that in TimesTen mode, parameter b is considered to be in position 2, not position 3.

In TimesTen mode, the SQLNumParams ODBC function returns 2 for the number of parameters in the example.

Binding duplicate parameters in PL/SQL

The preceding discussion does not apply to PL/SQL, which has its own semantics. In PL/SQL, you bind a value for each unique parameter name. An application executing the following block, for example, would bind only one parameter, corresponding to :a.

DECLARE
   x NUMBER;
   y NUMBER;
BEGIN
   x:=:a;
   y:=:a;
END;

An application executing the following block would also bind only one parameter:

BEGIN
   INSERT INTO tab1 VALUES(:a, :a);
END

And the same for the following CALL statement:

...CALL proc(:a, :a)...

An application executing the following block would bind two parameters, with :a as the first parameter and :b as the second parameter. The second parameter in each INSERT statement would take the same value as the first parameter in the first INSERT statement:

BEGIN
   INSERT INTO tab1 VALUES(:a, :a);
   INSERT INTO tab1 VALUES(:b, :a);
END

Considerations for floating point data

The BINARY_DOUBLE and BINARY_FLOAT data types store and retrieve the IEEE floating point values Inf, -Inf, and NaN. If an application uses a C language facility such as printf, scanf, or strtod that requires conversion to character data, the floating point values are returned as "INF", "-INF", and "NAN". These character strings cannot be converted back to floating point values.

Using SQL_WCHAR and SQL_WVARCHAR with a driver manager

Applications using the Windows driver manager may encounter errors from SQLBindParameter with SQL state S1004 (SQL data type out of range) when passing an fSqlType value of SQL_WCHAR or SQL_WVARCHAR. This problem can be avoided by passing one of the following values for fSqlType instead.

  • SQL_WCHAR_DM_SQLBINDPARAMETER_BYPASS instead of SQL_WCHAR

  • SQL_WVARCHAR_DM_SQLBINDPARAMETER_BYPASS instead of SQL_WVARCHAR

These type codes are semantically identical to SQL_WCHAR and SQL_WVARCHAR but avoid the error from the Windows driver manager. They can be used in applications that link with the driver manager or link directly with the TimesTen ODBC direct driver or ODBC client driver.

See "SQLBindParameter function" for information about that ODBC function.

Working with REF CURSORs

REF CURSOR is a PL/SQL concept, a handle to a cursor over a SQL result set that can be passed between PL/SQL and an application. In TimesTen, the cursor can be opened in PL/SQL then the REF CURSOR can be passed to the application. The results can be processed in the application using ODBC calls. This is an OUT REF CURSOR (an OUT parameter with respect to PL/SQL). The REF CURSOR is attached to a statement handle, enabling applications to describe and fetch result sets using the same APIs as for any result set.

Take the following steps to use a REF CURSOR. Assume a PL/SQL statement that returns a cursor through a REF CURSOR OUT parameter. Note that REF CURSORs use the same basic steps of prepare, bind, execute, and fetch as in the cursor example in "Preparing and executing queries and working with cursors".

  1. Prepare the PL/SQL statement, using SQLPrepare, to be associated with the first statement handle.

  2. Bind each parameter of the statement, using SQLBindParameter. When binding the REF CURSOR output parameter, use an allocated second statement handle as rgbValue, the pointer to the data buffer.

    The pcbValue, ibScale, cbValueMax, and pcbValue arguments are ignored for REF CURSORs.

    See "SQLBindParameter function" and "Binding output parameters" for information about these and other SQLBindParameter arguments.

  3. Call SQLBindCol to bind result columns to local variable storage.

  4. Call SQLExecute to execute the statement.

  5. Call SQLFetch to fetch the results. After a REF CURSOR is passed from PL/SQL to an application, the application can describe and fetch the results as it would for any result set.

  6. Use SQLFreeStmt to free the statement handle.

These steps are demonstrated in the example that follows. Refer to ODBC API reference documentation for details on these functions. See "PL/SQL REF CURSORs" in Oracle TimesTen In-Memory Database PL/SQL Developer's Guide for additional information about REF CURSORs.


Important:

For passing REF CURSORs between PL/SQL and an application, TimesTen supports only OUT REF CURSORs, from PL/SQL to the application, and supports a statement returning only a single REF CURSOR.

Example 2-7 Executing a query and working with a REF CURSOR

This example, using a REF CURSOR in a loop, demonstrates the basic steps of preparing a query, binding parameters, executing the query, binding results to local variable storage, and fetching the results. Error handling is omitted for simplicity. In addition to the ODBC functions summarized earlier, this example uses SQLAllocStmt to allocate memory for a statement handle.

refcursor_example(SQLHDBC hdbc)
{
  SQLCHAR*      stmt_text;
  SQLHSTMT      plsql_hstmt;
  SQLHSTMT      refcursor_hstmt;
  SQLINTEGER    deptid;
  SQLINTEGER    depts[3] = {10,30,40};
  SQLINTEGER    empid;
  SQLCHAR       lastname[30];
  SQLINTEGER    i;
 
  /* allocate 2 statement handles: one for the plsql statement and
   * one for the ref cursor */
  SQLAllocStmt(hdbc, &plsql_hstmt);
  SQLAllocStmt(hdbc, &refcursor_hstmt);
 
  /* prepare the plsql statement */
  stmt_text = (SQLCHAR*)
    "begin "
      "open :refc for "
        "select employee_id, last_name "
        "from employees "
        "where department_id = :dept; "
    "end;";
  SQLPrepare(plsql_hstmt, stmt_text, SQL_NTS);
 
  /* bind parameter 1 (:refc) to refcursor_hstmt */
  SQLBindParameter(plsql_hstmt, 1, SQL_PARAM_OUTPUT, SQL_C_REFCURSOR,
                   SQL_REFCURSOR, 0, 0, refcursor_hstmt, 0, 0);
 
  /* bind parameter 2 (:deptid) to local variable deptid */
  SQLBindParameter(plsql_hstmt, 2, SQL_PARAM_INPUT, SQL_C_SLONG,
                   SQL_INTEGER, 0, 0, &deptid, 0, 0);
 
  /* loop through values for :deptid */
  for (i=0; i<3; i++)
  {
     deptid = depts[i];
 
     /* execute the plsql statement */
     SQLExecute(plsql_hstmt);
     /*
      * The result set is now attached to refcursor_hstmt.
      * Bind the result columns and fetch the result set.
      */
 
     /* bind result column 1 to local variable empid */
     SQLBindCol(refcursor_hstmt, 1, SQL_C_SLONG,
                (SQLPOINTER)&empid, 0, 0);
 
     /* bind result column 2 to local variable lastname */
     SQLBindCol(refcursor_hstmt, 2, SQL_C_CHAR,
                (SQLPOINTER)lastname, sizeof(lastname), 0);
 
     /* fetch the result set */
     while(SQLFetch(refcursor_hstmt) != SQL_NO_DATA_FOUND){
       printf("%d, %s\n", empid, lastname);
     }
 
     /* close the ref cursor statement handle */
     SQLFreeStmt(refcursor_hstmt, SQL_CLOSE);
  }
   
  /* drop both handles */
  SQLFreeStmt(plsql_hstmt, SQL_DROP);
  SQLFreeStmt(refcursor_hstmt, SQL_DROP);
}

Working with DML returning (RETURNING INTO clause)

You can use a RETURNING INTO clause, referred to as DML returning, with an INSERT, UPDATE, or DELETE statement to return specified items from a row that was affected by the action. This eliminates the need for a subsequent SELECT statement and separate round trip in case, for example, you want to confirm what was affected by the action.

With ODBC, DML returning is limited to returning items from a single-row operation. The clause returns the items into a list of output parameters. Bind the output parameters as discussed in "Binding parameters and executing statements".

SQL syntax and restrictions for the RETURNING INTO clause in TimesTen are documented as part of "INSERT", "UPDATE", and "DELETE" in Oracle TimesTen In-Memory Database SQL Reference.

Refer to "RETURNING INTO Clause" in Oracle Database PL/SQL Language Reference for details about DML returning.

Example 2-8 DML returning

This example is adapted from Example 2-10, with bold text highlighting key portions.

void
update_example(SQLHDBC hdbc)
{
   SQLCHAR*      stmt_text;
   SQLHSTMT      hstmt;
   SQLINTEGER    raise_pct;
   char          hiredate_str[30];
   char          last_name[30];
   SQLLEN        hiredate_len;
   SQLLEN        numrows;

   /* allocate a statement handle */
   SQLAllocStmt(hdbc, &hstmt);

   /* prepare an update statement to give a raise to one employee hired
      before a given date and return that employee's last name */
   stmt_text = (SQLCHAR*)
     "update employees "
     "set salary = salary * ((100 + :raise_pct) / 100.0) "
     "where hire_date < :hiredate and rownum = 1 returning last_name into "
                       ":last_name";
   SQLPrepare(hstmt, stmt_text, SQL_NTS);

   /* bind parameter 1 (:raise_pct) to variable raise_pct */
   SQLBindParameter(hstmt, 1, SQL_PARAM_INPUT, SQL_C_SLONG,
                    SQL_DECIMAL, 0, 0, (SQLPOINTER)&raise_pct, 0, 0);

   /* bind parameter 2 (:hiredate) to variable hiredate_str */
   SQLBindParameter(hstmt, 2, SQL_PARAM_INPUT, SQL_C_CHAR,
                    SQL_TIMESTAMP, 0, 0, (SQLPOINTER)hiredate_str,
                    sizeof(hiredate_str), &hiredate_len);
   /* bind parameter 3 (:last_name) to variable last_name */
   SQLBindParameter(hstmt, 3, SQL_PARAM_OUTPUT, SQL_C_CHAR,
                    SQL_VARCHAR, 30, 0, (SQLPOINTER)last_name,
                    sizeof(last_name), NULL);
   /* set parameter values to give a 10% raise to an employee hired before
    * January 1, 1996. */
   raise_pct = 10;
   strcpy(hiredate_str, "1996-01-01");
   hiredate_len = SQL_NTS;

   /* execute the update statement */
   SQLExecute(hstmt);

   /* tell us who the lucky person is */
   printf("Gave raise to %s.\n", last_name );

   /* drop the statement handle */
   SQLFreeStmt(hstmt, SQL_DROP);

   /* commit the changes */
   SQLTransact(henv, hdbc, SQL_COMMIT);

}

This returns "King" as the recipient of the raise.

Working with rowids

Each row in a database table has a unique identifier known as its rowid. An application can retrieve the rowid of a row from the ROWID pseudocolumn. Rowids can be represented in either binary or character format.

An application can specify literal rowid values in SQL statements, such as in WHERE clauses, as CHAR constants enclosed in single quotes.

As noted in Table 2-2, the ODBC SQL type SQL_ROWID corresponds to the SQL type ROWID.

For parameters and result set columns, rowids are convertible to and from the C types SQL_C_BINARY, SQL_C_WCHAR, and SQL_C_CHAR. SQL_C_CHAR is the default C type for rowids. The size of a rowid would be 12 bytes as SQL_C_BINARY, 18 bytes as SQL_C_CHAR, and 36 bytes as SQL_C_WCHAR.

Refer to "ROWID data type" and "ROWID" in Oracle TimesTen In-Memory Database SQL Reference for additional information about rowids and the ROWID data type, including usage and life.


Note:

TimesTen does not support the PL/SQL type UROWID.

Working with LOBs

TimesTen supports LOBs (large objects). This includes CLOBs (character LOBs), NCLOBs (national character LOBs), and BLOBs (binary LOBs).

This section provides a brief overview of LOBs and discusses their use in ODBC, covering the following topics:


Note:

TimesTen does not support CLOBs if the database character set is TIMESTEN8.

You can also refer to the following:

About LOBs

A LOB is a large binary object (BLOB) or character object (CLOB or NCLOB). In TimesTen, a BLOB can be up to 16 MB in size and a CLOB or NCLOB up to 4 MB. LOBs in TimesTen have essentially the same functionality as in Oracle Database, except as noted otherwise. (See the next section, "Differences between TimesTen LOBs and Oracle Database LOBs".)

LOBs may be either persistent or temporary. A persistent LOB exists in a LOB column in the database. A temporary LOB exists only within an application. There are circumstances where a temporary LOB is created implicitly by TimesTen. For example, if a SELECT statement selects a LOB concatenated with an additional string of characters, TimesTen will create a temporary LOB to contain the concatenated data. In TimesTen ODBC, any temporary LOBs are managed implicitly.

Temporary LOBs are stored in the TimesTen temporary data partition.

Differences between TimesTen LOBs and Oracle Database LOBs

Be aware of the following:

  • A key difference between the TimesTen LOB implementation and the Oracle Database implementation is that in TimesTen, a LOB used in an application does not remain valid past the end of the transaction. All such LOBs are invalidated after a commit or rollback, whether explicit or implicit. This includes after any DDL statement if TimesTen DDLCommitBehavior is set to 0 (the default), for Oracle Database behavior.

  • TimesTen does not support BFILEs, SecureFiles, array reads and writes for LOBs, or callback functions for LOBs.

  • TimesTen does not support binding arrays of LOBs.

  • TimesTen does not support batch processing of LOBs.

  • Relevant to BLOBs, there are differences in the usage of hexadecimal literals in TimesTen. see the description of HexadecimalLiteral in "Constants" in Oracle TimesTen In-Memory Database SQL Reference.

LOB programming interfaces

There are three programmatic approaches, as follows, for accessing TimesTen LOBs in a C or C++ program.

  • Simple data interface (ODBC, OCI, Pro*C/C++, TTClasses): Use binds and defines, as with other scalar types, to transfer LOB data in a single chunk.

  • Piecewise data interface (ODBC): Use advanced forms of binds and defines to transfer LOB data in multiple pieces. This is sometimes referred to as streaming or using data-at-exec (at program execution time). TimesTen supports the piecewise data interface through polling loops to go piece-by-piece through the LOB data. (Another piecewise approach, using callback functions, is supported by Oracle Database but not by TimesTen.)

  • LOB locator interface (OCI, Pro*C/C++): Select LOB locators using SQL then access LOB data through APIs that are similar conceptually to those used in accessing a file system. Using the LOB locator interface, you can work with LOB data in pieces or in single chunks. (See "LOBs in TimesTen OCI" and "LOBs in TimesTen Pro*C/C++".)

The LOB locator interface offers the most utility if it is feasible for you to use it.

Using the LOB simple data interface in ODBC

The simple data interface enables applications to access LOB data by binding and defining, just as with other scalar types. For the simple data interface in ODBC, use SQLBindParameter to bind parameters and SQLBindCol to define result columns. The application can bind or define using a SQL type that is compatible with the corresponding variable type, as follows:

  • For BLOB data, use SQL type SQL_LONGVARBINARY and C type SQL_C_BINARY.

  • For CLOB data, use SQL type SQL_LONGVARCHAR and C type SQL_C_CHAR.

  • For NCLOB data, use SQL type SQL_WLONGVARCHAR and C type SQL_C_WCHAR.

SQLBindParameter and SQLBindCol calls for LOB data would be very similar to such calls for other data types, discussed earlier in this chapter.


Note:

Binding a CLOB or NCLOB with a C type of SQL_C_BINARY is prohibited.

Using the LOB piecewise data interface in ODBC

The piecewise interface enables applications to access LOB data in portions, piece by piece. An application binds parameters or defines results similarly to how those actions are performed for the simple data interface, but indicates that the data is to be provided or retrieved at program execution time ("at exec"). In TimesTen, you can implement the piecewise data interface through a polling loop that is repeated until all the LOB data has been read or written.

For the piecewise data interface in ODBC, use SQLParamData with SQLPutData in a polling loop to bind parameters, as shown in Example 2-9 below, and SQLGetData in a polling loop to retrieve results. See the preceding section, "Using the LOB simple data interface in ODBC", for information about supported SQL and C data types for BLOBs, CLOBs, and NCLOBs.


Note:

Similar piecewise data access has already been supported for the various APIs in previous releases of TimesTen, for var data types.

Example 2-9 Using SQLPutData, ODBC piecewise data interface

This program excerpt uses SQLPutData with SQLParamData in a polling loop to insert LOB data piece-by-piece into the database. The CLOB column will contain the value "123ABC" when the code is executed.

...
/* create a table */
  create_stmt = "create table clobtable ( c clob )";
  rc = SQLExecDirect(hstmt, (SQLCHAR *)create_stmt, SQL_NTS);
  if(rc != SQL_SUCCESS){/* ...error handling... */}
 
  /* initialize an insert statement */
  insert_stmt = "insert into clobtable values(?)";
  rc = SQLPrepare(hstmt, (SQLCHAR *)insert_stmt, SQL_NTS);
  if(rc != SQL_SUCCESS){/* ...error handling... */}
 
  /* bind the parameter and specify that we will be using
   * SQLParamData/SQLPutData */
  rc = SQLBindParameter
    hstmt,            /* statement handle */
    1,                /* colnum number */
    SQL_PARAM_INPUT,  /* param type */
    SQL_C_CHAR,       /* C type */
    SQL_LONGVARCHAR,  /* SQL type (ignored) */
    2,                /* precision (ignored) */
    0,                /* scale (ignored) */
    0,                /* putdata token */
    0,                /* ignored */
    &pcbvalue);       /* indicates use of SQLPutData */
  if(rc != SQL_SUCCESS){/* ...error handling... */}
 
  pcbvalue = SQL_DATA_AT_EXEC;
 
  /* execute the statement -- this should return SQL_NEED_DATA */
  rc = SQLExecute(hstmt);
  if(rc != SQL_NEED_DATA){/* ...error handling... */}
 
  /* while we still have parameters that need data... */
  while((rc = SQLParamData(hstmt, &unused)) == SQL_NEED_DATA){
 
    memcpy(char_buf, "123", 3);
    rc = SQLPutData(hstmt, char_buf, 3);
    if(rc !=  SQL_SUCCESS){/* ...error handling... */}
 
    memcpy(char_buf, "ABC", 3);
    rc = SQLPutData(hstmt, char_buf, 3);
    if(rc !=  SQL_SUCCESS){/* ...error handling... */}
 
  }
...

Passthrough LOBs in ODBC

Passthrough LOBs, which are LOBs in Oracle Database accessed through TimesTen, are exposed as TimesTen LOBs and are supported by TimesTen in much the same way that any TimesTen LOB is supported, but note the following:

  • TimesTen LOB size limitations do not apply to storage of passthrough LOBs, but do apply to binding.

  • As with TimesTen local LOBs, a passthrough LOB used in an application does not remain valid past the end of the transaction.

Making and committing changes to the database

Autocommit is enabled by default (according to the ODBC specification), so that any DML change you make, such as an update, insert, or delete, is committed automatically. It is recommended, however, that you disable this feature and commit (or roll back) your changes explicitly. Use the SQL_AUTOCOMMIT option in a SQLSetConnectOption call to accomplish this:

rc = SQLSetConnectOption(hdbc, SQL_AUTOCOMMIT, SQL_AUTOCOMMIT_OFF);

With autocommit disabled, you can commit or roll back a transaction using the SQLTransact ODBC function, such as in the following example to commit:

rc = SQLTransact(henv, hdbc, SQL_COMMIT);

Refer to ODBC API reference documentation for details about these functions.


Notes:

  • Autocommit mode applies only to the top-level statement executed by SQLExecute or SQLExecDirect. There is no awareness of what occurs inside the statement, and therefore no capability for intermediate autocommits of nested operations.

  • All open cursors on the connection are closed upon transaction commit or rollback in TimesTen.

  • The SQLRowCount function can be used to return information about SQL operations. For UPDATE, INSERT, and DELETE statements, the output argument returns the number of rows affected. See "Managing cache groups" regarding special TimesTen functionality. Refer to ODBC API reference documentation for general information about SQLRowCount and its arguments.


You can refer to "Transaction overview" in Oracle TimesTen In-Memory Database Operations Guide for additional information about transactions.

Example 2-10 Updating the database and committing the change

This example prepares and executes a statement to give raises to selected employees, then manually commits the changes. Assume autocommit has been previously disabled.

update_example(SQLHDBC hdbc)
{
  SQLCHAR*      stmt_text;
  SQLHSTMT      hstmt;
  SQLINTEGER    raise_pct;
  char          hiredate_str[30];
  SQLLEN        hiredate_len;
  SQLLEN        numrows;
 
  /* allocate a statement handle */
  SQLAllocStmt(hdbc, &hstmt);
 
  /* prepare an update statement to give raises to employees hired before a
   * given date */
  stmt_text = (SQLCHAR*)
    "update employees "
    "set salary = salary * ((100 + :raise_pct) / 100.0) "
    "where hire_date < :hiredate";
  SQLPrepare(hstmt, stmt_text, SQL_NTS);
 
  /* bind parameter 1 (:raise_pct) to variable raise_pct */
  SQLBindParameter(hstmt, 1, SQL_PARAM_INPUT, SQL_C_SLONG,
                   SQL_DECIMAL, 0, 0, (SQLPOINTER)&raise_pct, 0, 0);
 
  /* bind parameter 2 (:hiredate) to variable hiredate_str */
  SQLBindParameter(hstmt, 2, SQL_PARAM_INPUT, SQL_C_CHAR,
                   SQL_TIMESTAMP, 0, 0, (SQLPOINTER)hiredate_str,
                   sizeof(hiredate_str), &hiredate_len);
 
  /* set parameter values to give a 10% raise to employees hired before
   * January 1, 1996. */
  raise_pct = 10;
  strcpy(hiredate_str, "1996-01-01");
  hiredate_len = SQL_NTS;
 
  /* execute the update statement */
  SQLExecute(hstmt);
 
  /* print the number of employees who got raises  */
  SQLRowCount(hstmt, &numrows);
  printf("Gave raises to %d employees.\n", numrows);
 
  /* drop the statement handle */
  SQLFreeStmt(hstmt, SQL_DROP);

  /* commit the changes */
  SQLTransact(henv, hdbc, SQL_COMMIT);

}

Using additional TimesTen data management features

Preceding sections discussed key features for managing TimesTen data. This section covers the additional features listed here.

Using CALL to execute procedures and functions

TimesTen supports each of the following syntax formats from any of its programming interfaces to call PL/SQL procedures (procname) or PL/SQL functions (funcname) that are standalone or part of a package, or to call TimesTen built-in procedures (procname).

CALL procname[(argumentlist)]

CALL funcname[(argumentlist)] INTO :returnparam

CALL funcname[(argumentlist)] INTO ?

TimesTen ODBC also supports each of the following syntax formats:

{ CALL procname[(argumentlist)] }

{ ? = [CALL] funcname[(argumentlist)] }

{ :returnparam = [CALL] funcname[(argumentlist)] }

The following ODBC example calls the TimesTen ttCkpt built-in procedure.

rc = SQLExecDirect (hstmt, (SQLCHAR*) "call ttCkpt",SQL_NTS);

These examples call a PL/SQL procedure myproc with two parameters:

rc = SQLExecDirect(hstmt, (SQLCHAR*) "{ call myproc(:param1, :param2) }",SQL_NTS);

rc = SQLExecDirect(hstmt, (SQLCHAR*) "{ call myproc(?, ?) }",SQL_NTS);

The following shows several ways to call a PL/SQL function myfunc:

rc = SQLExecDirect (hstmt, (SQLCHAR*) "CALL myfunc() INTO :retparam",SQL_NTS);

rc = SQLExecDirect (hstmt, (SQLCHAR*) "CALL myfunc() INTO ?",SQL_NTS);

rc = SQLExecDirect (hstmt, (SQLCHAR*) "{ :retparam = myfunc() }",SQL_NTS);

rc = SQLExecDirect (hstmt, (SQLCHAR*) "{ ? = myfunc() }",SQL_NTS);

See "CALL" in Oracle TimesTen In-Memory Database SQL Reference for details about CALL syntax.


Note:

  • A user's own procedure takes precedence over a TimesTen built-in procedure with the same name, but it is best to avoid such naming conflicts.

  • TimesTen does not support using SQL_DEFAULT_PARAM with SQLBindParameter for a CALL statement.


Setting a timeout or threshold for executing SQL statements

TimesTen offers two ways to limit the time for SQL statements or procedure calls to execute, applying to any SQLExecute, SQLExecDirect, or SQLFetch call.

For the former, if the timeout duration is reached, the statement stops executing and an error is thrown. For the latter, if the threshold is reached, an SNMP trap is thrown but execution continues.

Setting a timeout duration for SQL statements

To control how long SQL statements should execute before timing out, you can set the SQL_QUERY_TIMEOUT option using a SQLSetStmtOption or SQLSetConnectOption call to specify a timeout value, in seconds. A value of 0 indicates no timeout. Despite the name, this timeout value applies to any executable SQL statement, not just queries.

In TimesTen, you can specify this timeout value for a connection, and therefore any statement on the connection, by using the SqlQueryTimeout general connection attribute. (Also see "SqlQueryTimeout" in Oracle TimesTen In-Memory Database Reference.) A call to SQLSetConnectOption with the SQL_QUERY_TIMEOUT option overrides any previous query timeout setting. A call to SQLSetStmtOption with the SQL_QUERY_TIMEOUT option overrides the connection setting for the particular statement.

The query timeout limit has effect only when a SQL statement is actively executing. A timeout does not occur during commit or rollback. For transactions that update, insert, or delete a large number of rows, the commit or rollback phases may take a long time to complete. During that time the timeout value is ignored.


Notes:

  • If you are using TimesTen Client/Server, the SQL query timeout should be significantly less than TTC_Timeout, and cannot be 0 (for no timeout) if TTC_Timeout is greater than 0. For details, see "TTC_Timeout" in Oracle TimesTen In-Memory Database Reference.

  • If both a lock timeout value and a SQL query timeout value are specified, the lesser of the two values causes a timeout first. Regarding lock timeouts, you can refer to "ttLockWait" (built-in procedure) or "LockWait" (general connection attribute) in Oracle TimesTen In-Memory Database Reference, or to "Check for deadlocks and timeouts" in Oracle TimesTen In-Memory Database Troubleshooting Guide.


Setting a threshold duration for SQL statements

You can configure TimesTen to write a warning to the support log and throw an SNMP trap when the execution of a SQL statement exceeds a specified time duration, in seconds. Execution continues and is not affected by the threshold.

The name of the SNMP trap is ttQueryThresholdWarnTrap. See Oracle TimesTen In-Memory Database Error Messages and SNMP Traps for information about configuring SNMP traps. Despite the name, this threshold applies to any executable SQL statement.

By default, the application obtains the threshold from the QueryThreshold general connection attribute setting (refer to "QueryThreshold" in Oracle TimesTen In-Memory Database Reference). Setting the TT_QUERY_THRESHOLD option in a SQLSetConnectOption call overrides the connection attribute setting for the current connection.

To set the threshold with SQLSetConnectOption:

RETCODE SQLSetConnectOption(hdbc, TT_QUERY_THRESHOLD, seconds);

Setting the TT_QUERY_THRESHOLD option in a SQLSetStmtOption call overrides the connection attribute setting, and any setting through SQLSetConnectOption, for the statement. It applies to SQL statements executed using the ODBC statement handle.

To set the threshold with SQLSetStmtOption:

RETCODE SQLSetStmtOption(hstmt, TT_QUERY_THRESHOLD, seconds);

You can retrieve the current value of TT_QUERY_THRESHOLD by using the SQLGetConnectOption or SQLGetStmtOption ODBC function:

RETCODE SQLGetConnectOption(hdbc, TT_QUERY_THRESHOLD, paramvalue);

RETCODE SQLGetStmtOption(hstmt, TT_QUERY_THRESHOLD, paramvalue);

Features for use with IMDB cache

This section discusses features related to the use of IMDB Cache:

See Oracle In-Memory Database Cache User's Guide for information about IMDB Cache.

See "PassThrough" in Oracle TimesTen In-Memory Database Reference for information about that general connection attribute. See "Setting a passthrough level" in Oracle In-Memory Database Cache User's Guide for information about passthrough settings.

Setting temporary passthrough level with the ttOptSetFlag built-in procedure

TimesTen provides the ttOptSetFlag built-in procedure for setting various flags, including the PassThrough flag to temporarily set the passthrough level. You can use ttOptSetFlag to set PassThrough in a C application as in the following example, which sets the passthrough level to 1. The setting affects all statements that are prepared until the end of the transaction.

rc = SQLExecDirect (hstmt, "ttOptSetFlag ('PassThrough', 1)",SQL_NTS);

See "ttOptSetFlag" in Oracle TimesTen In-Memory Database Reference for more information about that built-in procedure.

Determining passthrough status

You can call the SQLGetStmtOption ODBC function with the TT_STMT_PASSTHROUGH_TYPE statement option to determine whether a SQL statement is to be executed in the TimesTen database or passed through to the Oracle database for execution. For example:

rc = SQLGetStmtOption(hStmt, TT_STMT_PASSTHROUGH_TYPE, &passThroughType);

You can make this call after preparing the SQL statement. It is useful with PassThrough settings of 1, 2, 4, or 5, where the determination of whether a statement will actually be passed through is not made until compilation time. If TT_STMT_PASSTHROUGH_NONE is returned, the statement is to be executed in TimesTen. If TT_STMT_PASSTHROUGH_ORACLE is returned, the statement is to be passed through to Oracle for execution.


Note:

TT_STMT_PASSTHROUGH_TYPE is supported with SQLGetStmtOption only, not with SQLSetStmtOption.

Managing cache groups

In IMDB Cache, following the execution of a FLUSH CACHE GROUP, LOAD CACHE GROUP, REFRESH CACHE GROUP, or UNLOAD CACHE GROUP statement, the ODBC function SQLRowCount returns the number of cache instances that were flushed, loaded, refreshed, or unloaded.

For related information, see "Determining the number of cache instances affected by an operation" in Oracle In-Memory Database Cache User's Guide.

Refer to ODBC API reference documentation for general information about SQLRowCount.

Setting globalization options

TimesTen extensions to ODBC enable an application to set options for linguistic sorts, length semantics for character columns, and error reporting during character set conversion. These options can be used in a call to SQLSetConnectOption. The options are defined in the timesten.h file (noted in "TimesTen include files").

For more information about linguistic sorts, length semantics, and character sets, see "Globalization Support" in Oracle TimesTen In-Memory Database Operations Guide.

This section includes the following TimesTen ODBC globalization options.

TT_NLS_SORT

This option specifies the collating sequence used for linguistic comparisons. See "Monolingual linguistic sorts" and "Multilingual linguistic sorts" in Oracle TimesTen In-Memory Database Operations Guide for supported linguistic sorts.

It takes a string value. The default is "BINARY".

Also see the description of the NLS_SORT general connection attribute, which has the same functionality, in "NLS_SORT" in Oracle TimesTen In-Memory Database Reference. Note that TT_NLS_SORT, being a runtime option, takes precedence over the NLS_SORT connection attribute.

TT_NLS_LENGTH_SEMANTICS

This option specifies whether byte or character semantics is used. The possible values are:

  • TT_NLS_LENGTH_SEMANTICS_BYTE (default)

  • TT_NLS_LENGTH_SEMANTICS_CHAR

Also see the description of the NLS_LENGTH_SEMANTICS general connection attribute, which has the same functionality, in "NLS_LENGTH_SEMANTICS" in Oracle TimesTen In-Memory Database Reference. Note that TT_NLS_LENGTH_SEMANTICS, being a runtime option, takes precedence over the NLS_LENGTH_SEMANTICS connection attribute.

TT_NLS_NCHAR_CONV_EXCP

This option specifies whether an error is reported when there is data loss during an implicit or explicit character type conversion between NCHAR or NVARCHAR2 data and CHAR or VARCHAR2 data during SQL operations. The option does not apply to conversions done by ODBC as a result of binding.

The possible values are:

  • TRUE: Errors during conversion are reported.

  • FALSE: Errors during conversion are not reported (default).

Also see the description of the NLS_NCHAR_CONV_EXCP general connection attribute, which has the same functionality, in "NLS_NCHAR_CONV_EXCP" in Oracle TimesTen In-Memory Database Reference. Note that TT_NLS_NCHAR_CONV_EXCP, being a runtime option, takes precedence over the NLS_NCHAR_CONV_EXCP connection attribute.

Features for use with replication

For applications that employ replication, you can improve performance by using parallel replication, which uses multiple threads acting in parallel to replicate and apply transactional changes to nodes in a replication scheme. TimesTen supports two types of parallel replication: automatic and user-defined.

Automatic parallel replication enforces transactional dependencies and applies changes in commit order.

In user-defined parallel replication, there are user-defined tracks of transactions that operate in parallel. The application assigns transactions to tracks and specifies which track a transaction belongs to when the transaction starts on the source database. The transactions in each track are applied in the order in which they are received on the target database, but commit order is not maintained for transactions across the different tracks. You can use user-defined parallel replication if your application has predictable transactional dependencies and does not require the commit order on the target database to be the same as the order on the source database.

See "Configuring parallel replication" in Oracle TimesTen In-Memory Database Replication Guide for additional information and usage scenarios.


Note:

Automatic parallel replication is generally advisable over user-defined parallel replication. With user-defined parallel replication, care must be taken to avoid data divergence between replication nodes.

In an ODBC application with user-defined parallel replication, specify the track number for transactions on a connection through the TT_REPLICATION_TRACK connection option, as noted in "Option support for SQLSetConnectOption and SQLGetConnectOption". (Alternatively, use the general connection attribute ReplicationTrack or the ALTER SESSION parameter REPLICATION_TRACK.)

ODBC 3.0 data types

The data types used in ODBC 2.0 and prior have been renamed in ODBC 3.0 for ISO 92 standards compliance. The sample programs shipped with TimesTen have been written using SQL 3.0 data types. The following table maps 2.0 types to their 3.0 equivalents.

Note that TimesTen supports ODBC 2.5, Extension Level 1, with additional features for Extension Level 2 where those features are included in Chapter 10, "TimesTen ODBC Functions and Options".

ODBC 2.0 data typeODBC 3.0 data type
HDBCSQLHDBC
HENVSQLHENV
HSTMTSQLHSTMT
HWNDSQLHWND
LDOUBLESQLDOUBLE
RETCODESQLRETURN
SCHARSQLSCHAR
SDOUBLESQLFLOATS
SDWORDSQLINTEGER
SFLOATSQLREAL
SWORDSQLSMALLINT
UCHARSQLCHAR
UDWORDSQLUINTEGER
UWORDSQLUSMALLINT

Either version of data types may be used with TimesTen without restriction.

Note also that the FAR modifier that is mentioned in ODBC 2.0 documentation is not required.

Considering TimesTen features for access control

TimesTen has features to control database access with object-level resolution for database objects such as tables, views, materialized views, sequences, and synonyms. You can refer to "Managing Access Control" in Oracle TimesTen In-Memory Database Operations Guide for introductory information about these features.

This section introduces access control as it relates to SQL operations, database connections, XLA, and C utility functions.

For any query or SQL DML or DDL statement discussed in this document or used in an example, it is assumed that the user has appropriate privileges to execute the statement. For example, a SELECT statement on a table requires ownership of the table, SELECT privilege granted for the table, or the SELECT ANY TABLE system privilege. Similarly, any DML statement requires table ownership, the applicable DML privilege (such as UPDATE) granted for the table, or the applicable ANY TABLE privilege (such as UPDATE ANY TABLE).

For DDL statements, CREATE TABLE requires the CREATE TABLE privilege in the user's schema, or CREATE ANY TABLE in any other schema. ALTER TABLE requires ownership or the ALTER ANY TABLE system privilege. DROP TABLE requires ownership or the DROP ANY TABLE system privilege. There are no object-level ALTER or DROP privileges.

Refer to "SQL Statements" in Oracle TimesTen In-Memory Database SQL Reference for the privilege required for any given SQL statement.

Privileges are granted through the SQL statement GRANT and revoked through the statement REVOKE. Some privileges are granted to all users through the PUBLIC role, of which each user is a member. See "The PUBLIC role" in Oracle TimesTen In-Memory Database SQL Reference for information about that role.

In addition, access control affects the following topics covered in this document:


Notes:

  • Access control cannot be disabled.

  • Access control privileges are checked both when SQL is prepared and when it is executed in the database, with most of the performance cost coming at prepare time.


Handling Errors

This section includes the following topics:

Checking for errors

An application should check for errors and warnings on every call. This saves considerable time and effort during development and debugging. The demo programs provided with TimesTen show examples of error checking.

Errors can be checked using either the TimesTen error code (error number) or error string, as defined in the install_dir/include/tt_errCode.h file. Entries are in the following format:

#define tt_ErrMemoryLock             712

For a description of each message, see "List of errors and warnings" in Oracle TimesTen In-Memory Database Error Messages and SNMP Traps.

After calling an ODBC function, check the return code. If the return code is not SQL_SUCCESS, use an error-handling routine that calls the ODBC function SQLError to retrieve the errors on the relevant ODBC handle. A single ODBC call may return multiple errors. The application should be written to return all errors by repeatedly calling the SQLError function until all errors are read from the error stack. Continue calling SQLError until the return code is SQL_NO_DATA_FOUND.

Refer to ODBC API reference documentation for details about the SQLError function and its arguments.

For more information about writing a function to handle standard ODBC errors, see "Retrieving errors and warnings" in Oracle TimesTen In-Memory Database Error Messages and SNMP Traps.

Example 2-11 Checking an ODBC function call for errors

This example shows that after a call to SQLAllocConnect, you can check for an error condition. If one is found, an error message is displayed and program execution is terminated.

rc = SQLAllocConnect(henv, &hdbc);

if (rc != SQL_SUCCESS) {
  handleError(rc, henv, hdbc, hstmt, err_buf, &native_error);
  fprintf(stderr,
          "Unable to allocate a connection handle:\n%s\n",
          err_buf);
  exit(-1);
}

Error and warning levels

When operations are not completely successful, TimesTen can return fatal errors, non-fatal errors, or warnings.

Fatal errors

Fatal errors are those that make the database inaccessible until after error recovery. When a fatal error occurs, all database connections are required to disconnect. No further operations may complete. Fatal errors are indicated by TimesTen error codes 846 and 994. Error handling for these errors should be different from standard error handling. In particular, the application error-handling code should roll back the current transaction and disconnect from the database.

Also see "Recovering after fatal errors".

Non-fatal errors

Non-fatal errors include simple errors such as an INSERT statement that violates unique constraints. This category also includes some classes of application and process failures.

TimesTen returns non-fatal errors through the normal error-handling process. Application should check for errors and appropriately handle them.

When a database is affected by a non-fatal error, an error may be returned and the application should take appropriate action.

An application can handle non-fatal errors by modifying its actions or, in some cases, rolling back one or more offending transactions.

Warnings

TimesTen returns warnings when something unexpected occurs that you may want to know about. Here are some events that cause TimesTen to issue a warning:

  • Checkpoint failure

  • Use of a deprecated TimesTen feature

  • Truncation of some data

  • Execution of a recovery process upon connect

  • Replication return receipt timeout

Application developers should have code that checks for warnings, as they can indicate application problems.

Abnormal termination

In some cases, such as process failure, no error is returned, but TimesTen automatically rolls back the transactions of the failed process.

Recovering after fatal errors

When fatal errors occur, TimesTen performs a full cleanup and recovery procedure:

  • Every connection to the database is invalidated. To avoid out-of-memory conditions in the server, applications are required to disconnect from the invalidated database. Shared memory from the old TimesTen instance will not be freed until all active connections at the time of the error have disconnected. Inactive applications still connected to the old TimesTen instance may have to be manually terminated.

  • The database is recovered from the checkpoint and transaction log files upon the first subsequent initial connection.

  • The recovered database reflects the state of all durably committed transactions and possibly some transactions that were committed non-durably.

  • No uncommitted or rolled back transactions are reflected.

Using automatic client failover in your application

Automatic client failover is for use in High Availability scenarios with a TimesTen active standby pair replication configuration. If there is a failure of the active node, failover (transfer) to the new active (original standby) node occurs, and applications are automatically reconnected to the new active node. TimesTen provides features that enable applications to be alerted when this happens, so they can take any appropriate action.

This section discusses the TimesTen implementation of automatic client failover as it applies to application developers, covering the following topics.

See "Using automatic client failover" in Oracle TimesTen In-Memory Database Operations Guide for additional information about this feature.

Functionality of automatic client failover

When an application first connects to the active node, the connection is registered and this registration is replicated to the standby node. If the active node fails, the standby node becomes the new active node and then notifies the client of the failover. At this point, be aware of the following:

  • The client will have a new connection to the new active node, but using the same ODBC connection handle as before. No state from the original connection, other than the handle itself, is preserved. The application must open new ODBC statement handles.

  • There is a failover listener thread at each client that invokes the failover event function associated with your application, if a function has been registered. (See "Failover callback functions".)

All client statement handles from the original connection are marked as invalid. API calls on these statement handles will generally return SQL_ERROR with a distinctive failover error code, defined in tt_errCode.h, such as:

SQLSTATE = S1000 "General Error", native error = tt_ErrFailoverInvalidation

The exception to this is for SQLError and SQLFreeStmt calls, which behave normally.

In addition, note the following:

  • The socket to the original active node is closed. There is no attempt to call SQLDisconnect.

  • In connecting to the new active (original standby) TimesTen node, the same connection string that was returned from the original connection request is used, except the new server DSN is specified.

  • It is up to the application to open new statement handles and reexecute necessary SQLPrepare calls.

  • If a failover has already occurred and the client is already connected to the new active node, the next failover request results in an attempt to reconnect to the original active node. If that fails, alternating attempts are made to connect to the two servers until there is a timeout, and the connection is blocked during this period. The timeout value is according to the TimesTen client connection attribute TTC_Timeout (default 60 seconds), but with a minimum value of 60 seconds regardless of the TTC_Timeout setting. (Refer to "TTC_Timeout" in Oracle TimesTen In-Memory Database Reference for information about that attribute.)

  • Failover connections are created only as needed, not in advance.

When failover has completed, TimesTen makes a callback to a user-defined function that you register. This function takes care of any custom actions you want to occur in a failover situation.

The following public connection options will be propagated to the new connection. The corresponding general connection attribute is shown in parentheses where applicable. The TT_REGISTER_FAILOVER_CALLBACK option is used to register your callback function.

SQL_ACCESS_MODE
SQL_AUTOCOMMIT
SQL_TXN_ISOLATION (Isolation)
SQL_OPT_TRACE
SQL_QUIET_MODE
TT_PREFETCH_CLOSE
TT_CLIENT_TIMEOUT (TTC_TIMEOUT)
TT_REGISTER_FAILOVER_CALLBACK

The following options will be propagated to the new connection if they were set through connection attributes or SQLSetConnectOption calls, but not if set through TimesTen built-in procedures or ALTER SESSION.

TT_NLS_SORT (NLS_SORT)
TT_NLS_LENGTH_SEMANTICS (NLS_LENGTH_SEMANTICS)
TT_NLS_NCHAR_CONV_EXCP (NLS_NCHAR_CONV_EXCP)
TT_DYNAMIC_LOAD_ENABLE (DynamicLoadEnable)
TT_DYNAMIC_LOAD_ERROR_MODE (DynamicLoadErrorMode)

The following options will be propagated to the new connection if they were set on the connection handle.

SQL_QUERY_TIMEOUT
TT_PREFETCH_COUNT

Configuration of automatic client failover

Refer to "Configuring automatic client failover" in Oracle TimesTen In-Memory Database Operations Guide for information.


Note:

Setting any of TTC_Server2, TTC_Server_DSN2, or TCP_Port2 implies the following:
  • You intend to use automatic client failover.

  • You understand that a new thread will be created for your application to support the failover mechanism.

  • You have linked your application with a thread library (pthreads on UNIX systems).


Failover callback functions

When failover occurs, TimesTen makes a callback to your user-defined function for any desired action. This function is called when the attempt to connect to the new active (original standby) node begins, and again after the attempt to connect is complete. This function could be used, for example, to cleanly restore statement handles.

The function API is defined as follows.

typedef SQLRETURN (*ttFailoverCallbackFcn_t)
  (SQLHDBC,      /* hdbc    */
   SQLPOINTER,   /* foCtx   */
   SQLUINTEGER,  /* foType  */
   SQLUINTEGER); /* foEvent */

Where:

  • hdbc is the ODBC connection handle for the connection that failed.

  • foCtx is a pointer to an application-defined data structure, for use as needed.

  • foType is the type of failover. In TimesTen, the only supported value for this is TT_FO_SESSION, which results in the session being reestablished. This does not result in statements being re-prepared.

  • foEvent indicates the event that has occurred, with the following supported values:

    • TT_FO_BEGIN: Beginning failover.

    • TT_FO_ABORT: Failover failed. Retries were attempted for the interval specified by TTC_Timeout (minimum value 60 seconds for active standby failover) without success.

    • TT_FO_END: Successful end of failover.

    • TT_FO_ERROR: A failover connection failed but will be retried.

    Note that TT_FO_REAUTH is not supported by TimesTen client failover.

Use a SQLSetConnectOption call to set the TimesTen TT_REGISTER_FAILOVER_CALLBACK option to register the callback function, specifying an option value that is a pointer to a structure of C type ttFailoverCallback_t, which is defined as follows in the timesten.h file and refers to the callback function:

typedef struct{
  SQLHDBC                 appHdbc;
  ttFailoverCallbackFcn_t callbackFcn;
  SQLPOINTER              foCtx;
} ttFailoverCallback_t;

Where:

  • appHdbc is the ODBC connection handle, and should have the same value as hdbc in the SQLSetConnectOption calling sequence. (It is required in the data structure due to driver manager implementation details, in case you are using a driver manager.)

  • callbackFcn specifies the callback function. (You can set this to NULL to cancel callbacks for the given connection. The failover will still happen, but the application will not be notified.)

  • foCtx is a pointer to an application-defined data structure, as in the function description earlier.

Set TT_REGISTER_FAILOVER_CALLBACK for each connection for which a callback is desired. The values in the ttFailoverCallback_t structure will be copied when the SQLSetConnectOption call is made. The structure need not be kept by the application. If TT_REGISTER_FAILOVER_CALLBACK is set multiple times for a connection, the last setting takes precedence.


Notes:

  • Because the callback function executes asynchronously to the main thread of your application, it should generally perform only simple tasks, such as setting flags that are polled by the application. However, there is no such restriction if the application is designed for multithreading. In that case, the function could even make ODBC calls, for example, but it is only safe to do so if the foEvent value TT_FO_END has been received.

  • It is up to the application to manage the data pointed to by the foCtx setting.


Example 2-12 Failover callback function and registration

This example shows the following:

  • A globally defined user structure type, FOINFO, and the structure variable foStatus of type FOINFO

  • A callback function, FailoverCallback(), that updates the foStatus structure whenever there is a failover

  • A registration function, RegisterCallback(), that does the following:

    • Declares a structure, failoverCallback, of type ttFailoverCallback_t.

    • Initializes foStatus values.

    • Sets the failoverCallback data values, consisting of the connection handle, a pointer to foStatus, and the callback function (FailoverCallback).

    • Registers the callback function with a SQLSetConnectOption call that sets TT_REGISTER_FAILOVER_CALLBACK as a pointer to failoverCallback.

/* user defined structure */
struct FOINFO
{
 int callCount;
 SQLUINTEGER lastFoEvent;
};
/* global variable passed into the callback function */
struct FOINFO foStatus;
 
/* the callback function */
SQLRETURN FailoverCallback (SQLHDBC hdbc,
                           SQLPOINTER pCtx,
                           SQLUINTEGER FOType,
                           SQLUINTEGER FOEvent)
{
 struct FOINFO* pFoInfo = (struct FOINFO*) pCtx;
 
 /* update the user defined data */
 if (pFoInfo != NULL)
 {
   pFoInfo->callCount ++;
   pFoInfo->lastFoEvent = FOEvent;
 
   printf ("Failover Call #%d\n", pFoInfo->callCount);
 }
 
 /* the ODBC connection handle */
 printf ("Failover HDBC : %p\n", hdbc);
 
 /* pointer to user data */
 printf ("Failover Data : %p\n", pCtx);
 
 /* the type */
 switch (FOType)
 {
   case TT_FO_SESSION:
     printf ("Failover Type : TT_FO_SESSION\n");
     break;
 
   default:
     printf ("Failover Type : (unknown)\n");
 }
 
 /* the event */
 switch (FOEvent)
 {
   case TT_FO_BEGIN:
     printf ("Failover Event: TT_FO_BEGIN\n");
     break;
 
   case TT_FO_END:
     printf ("Failover Event: TT_FO_END\n");
     break;
 
   case TT_FO_ABORT:
     printf ("Failover Event: TT_FO_ABORT\n");
     break;
 
   case TT_FO_REAUTH:
     printf ("Failover Event: TT_FO_REAUTH\n");
     break;
 
   case TT_FO_ERROR:
     printf ("Failover Event: TT_FO_ERROR\n");
     break;
 
   default:
     printf ("Failover Event: (unknown)\n");
 }
 
 return SQL_SUCCESS;
}
 
/* function to register the callback with the failover connection */
SQLRETURN RegisterCallback (SQLHDBC hdbc)
{
 SQLRETURN rc;
 ttFailoverCallback_t failoverCallback;
 
 /* initialize the global user defined structure */
 foStatus.callCount = 0;
 foStatus.lastFoEvent = -1;
 
 /* register the connection handle, callback and the user defined structure */
 failoverCallback.appHdbc = hdbc;
 failoverCallback.foCtx = &foStatus;
 failoverCallback.callbackFcn = FailoverCallback;
 
 rc = SQLSetConnectOption (hdbc, TT_REGISTER_FAILOVER_CALLBACK,
   (SQLULEN)&failoverCallback);
 
 return rc;
}

When a failover occurs, the callback function would produce output such as the following:

Failover Call #1
Failover HDBC : 0x8198f50
Failover Data : 0x818f8ac
Failover Type : TT_FO_SESSION
Failover Event: TT_FO_BEGIN
PK[[PK:AOEBPS/xla_ref.htm XLA Reference

9 XLA Reference

This chapter provides reference information for the Transaction Log API (XLA) described in Chapter 5, "XLA and TimesTen Event Management". It includes the following topics:

About XLA functions

This section provides general information about XLA functions.

About return codes

All of the XLA API functions described in this chapter return a value of type SQLRETURN, which is defined by ODBC to have one of the following values:

  • SQL_SUCCESS

  • SQL_SUCCESS_WITH_INFO

  • SQL_NO_DATA_FOUND

  • SQL_ERROR

See "Handling XLA errors" for information on handling XLA errors.

About parameter types (input, output, input/output)

In the function descriptions:

  • All parameters are input-only unless otherwise indicated.

  • Output parameters are prefixed with OUT.

  • Input/output parameters are prefixed with IN OUT.

About results output by functions

Most routines in this API copy results to application buffers. Those few routines that produce pointers to buffers containing results are guaranteed as valid only until the next call with the same XLA handle.

Exceptions to this rule include the following.

  • Buffers remain valid across calls to the ttXlaError function that supplies diagnostic information.

  • Results returned by ttXlaNextUpdate remain valid until the next call to ttXlaNextUpdate.

  • For ttXlaAcknowledge, if the application must retain access to the buffers for a longer time, it must copy the information from the buffer returned by XLA to an application-owned buffer.

Character string values in XLA are null-terminated, except for actual column values. Fixed-length CHAR columns are space-padded to their full length. VARCHAR columns have an explicit length encoded.

XLA uses the same data structures for both 32- and 64-bit platforms. The types SQLUINTEGER and SQLUBIGINT are used to refer to 32- and 64-bit integers unambiguously. Issues of alignment and padding are addressed by filling the type definition so that each SQLUINTEGER value is on a four-byte boundary and each SQLUBIGINT value is on an eight-byte boundary. For a description of storage requirements for other TimesTen data types, see "Understanding rows" in Oracle TimesTen In-Memory Database Operations Guide.

About required privileges

"Access control impact on XLA" introduces the effects of TimesTen access control features on XLA functionality. Any XLA functionality requires the system privilege XLA.

Summary of XLA functions by category

As described in Chapter 5, "XLA and TimesTen Event Management", TimesTen XLA can be used to detect updates on a database or as a toolkit to build your own replication solution.

This section categorizes the XLA functions based on their use and provides a brief description of each function. It includes the following categories:

XLA core functions

The following table lists all the XLA functions used in typical XLA operations, aside from data conversion functions which are listed separately below.

FunctionDescription
ttXlaAcknowledge
Acknowledges receipt of one or more transaction update records from the transaction log.
ttXlaClose
Closes the XLA handle opened by ttXlaPersistOpen.
ttXlaConvertCharType
Converts column data into the connection character set.
ttXlaDeleteBookmark
Deletes a transaction log bookmark.
ttXlaError
Retrieves error information.
ttXlaErrorRestart
Resets error stack information.
ttXlaGetColumnInfo
Retrieves information about all the columns in the table.
ttXlaGetLSN
Retrieves the log record identifier of the current bookmark for a database.
ttXlaGetTableInfo
Retrieves information about a table.
ttXlaGetVersion
Retrieves the current version of XLA.
ttXlaNextUpdate
Retrieves a batch of updates from TimesTen.
ttXlaNextUpdateWait
Retrieves a batch of updates from TimesTen. Will wait for a specified time if no updates are available in the transaction log.
ttXlaPersistOpen
Initializes a handle to a database to access the transaction log.
ttXlaSetLSN
Sets the log record identifier of the current bookmark for a database.
ttXlaSetVersion
Sets the XLA version to be used.
ttXlaTableByName
Finds the system and user table identifiers for a table given the table owner and name.
ttXlaTableStatus
Sets and retrieves XLA status for a table.
ttXlaTableVersionVerify
Checks whether the cached table definitions are compatible with the XLA record being processed.
ttXlaVersionColumnInfo
Retrieves information about the columns in a table for which a change update record must be processed.
ttXlaVersionCompare
Compares two XLA versions.

See "Writing an XLA event-handler application" for a discussion on how to use most of these functions.

XLA data type conversion functions

The following table lists data type conversion functions.

FunctionDescription
ttXlaDateToODBCCType
Converts a TTXLA_DATE_TT value to an ODBC C value usable by applications.
ttXlaDecimalToCString
Converts a TTXLA_DECIMAL_TT value to a character string usable by applications.
ttXlaNumberToBigInt
Converts a TTXLA_NUMBER value to a SQLBIGINT C value usable by applications.
ttXlaNumberToCString
Converts a TTXLA_NUMBER value to a character string usable by applications.
ttXlaNumberToDouble
Converts a TTXLA_NUMBER value to a long floating point number value usable by applications.
ttXlaNumberToInt
Converts a TTXLA_NUMBER value to an integer usable by applications.
ttXlaNumberToSmallInt
Converts a TTXLA_NUMBER value to a SQLSMALLINT C value usable by applications.
ttXlaNumberToTinyInt
Converts a TTXLA_NUMBER value to a SQLCHAR C value usable by applications.
ttXlaNumberToUInt
Converts a TTXLA_NUMBER value to an unsigned integer usable by applications.
ttXlaOraDateToODBCTimeStamp
Converts a TTXLA_DATE value to an ODBC timestamp usable by applications.
ttXlaOraTimeStampToODBCTimeStamp
Converts a TTXLA_TIMESTAMP value to an ODBC timestamp usable by applications.
ttXlaRowidToCString
Converts a ROWID value to a character string value usable by applications.
ttXlaTimeToODBCCType
Converts a TTXLA_TIME value to an ODBC C value usable by applications.
ttXlaTimeStampToODBCCType
Converts a TTXLA_TIMESTAMP_TT value to an ODBC C value usable by applications.

For more information about XLA data types, see "About XLA data types".

XLA replication functions

TimesTen replication as described in Oracle TimesTen In-Memory Database Replication Guide is sufficient for most customer needs; however, it is also possible to use XLA functions to replicate updates from one database to another. Implementing your own replication scheme on top of XLA in this way is fairly complicated, but can be considered if TimesTen replication is not feasible for some reason.

The following table lists functions used exclusively for XLA as a replication mechanism. (Reference information for these functions is in a separate section from other XLA functions, "XLA replication function reference".)

FunctionDescription
ttXlaApply
Applies the update to the database associated with the XLA handle.
ttXlaCommit
Commits a transaction.
ttXlaGenerateSQL
Generates a SQL statement that expresses the effect of an update record.
ttXlaLookup
Looks for an update record for a table with a specific key value.
ttXlaRollback
Rolls back a transaction.
ttXlaTableCheck
Verifies that the named table in the table description received from the sending database is compatible with the receiving database.

See "Using XLA as a replication mechanism" for a discussion on how to use these functions.


XLA function reference

This section provides reference information for XLA core functions and XLA data type conversion functions. The functions are listed in alphabetical order.


Note:

Functions used exclusively for XLA as a replication mechanism are documented in a separate section, "XLA replication function reference".


ttXlaAcknowledge

Description

This function is used to acknowledge that one or more records have been read from the transaction log by the ttXlaNextUpdate or ttXlaNextUpdateWait function.

After you make this call, the bookmark is reset so that you cannot reread any of the previously returned records. Call ttXlaAcknowledge only when messages have been completely processed.


Notes:

  • The bookmark is only reset for the specified handle. Other handles in the system may still be able to access those earlier transactions.

  • The bookmark is reset even if there are no relevant update records to acknowledge.


Note that ttXlaAcknowledge is an expensive operation that should be used only as necessary. Calling ttXlaAcknowledge more than once per reading of the transaction log file does not reduce the volume of the transaction log since XLA only purges transaction logs a file at a time. To detect when a new transaction log file is generated, you can find out which log file a bookmark is in by examining the purgeLSN (represented by the PURGELSNHIGH and PURGELSNLOW values) for the bookmark in the system table SYS.TRANSACTION_LOG_API. You can then call ttXlaAcknowledge to purge the old transaction log files. (Note that you must have ADMIN or SELECT ANY TABLE privilege to view this table.)

The second purpose of ttXlaAcknowledge is to ensure that the XLA application does not see the acknowledged records if it were to connect to a previously used bookmark by calling the ttXlaPersistOpen function with the XLAREUSE option. If you intend to reuse a bookmark, call ttXlaAcknowledge to reset the bookmark position to the current record before calling ttXlaClose.

See "Retrieving update records from the transaction log" for a discussion about using this function.

Required privilege

XLA

Syntax

SQLRETURN ttXlaAcknowledge(ttXlaHandle_h handle)

Parameters

ParameterTypeDescription
handlettXlaHandle_hTransaction log handle

Returns

Returns SQL_SUCCESS if call is successful. Otherwise, use ttXlaError to report the error.

Example

rc = ttXlaAcknowledge(xlahandle);

See also


ttXlaNextUpdate
ttXlaNextUpdateWait

ttXlaClose

Description

Closes an XLA handle that was opened by ttXlaPersistOpen. See "Terminating an XLA application" for a discussion about using this function.

Required privilege

XLA

Syntax

SQLRETURN ttXlaClose(ttXlaHandle_h handle)

Parameters

ParameterTypeDescription
handlettXlaHandle_hODBC handle for the database

Returns

Returns SQL_SUCCESS if call is successful. Otherwise, use ttXlaError to report the error.

To close the XLA handle opened in the previous example, use the following call:

rc = ttXlaClose(xlahandle);

See also


ttXlaPersistOpen

ttXlaConvertCharType

Description

Converts the column data indicated by the colinfo and tup parameters into the connection character set associated with the transaction log handle and places the result in a buffer.

Required privilege

XLA

Syntax

SQLRETURN ttXlaConvertCharType (ttXlaHandle_h handle,
                                ttXlaColDesc_t*  colinfo,
                                void* tup,
                                void* buf,
                                size_t buflen)

Parameters

ParameterTypeDescription
handlettXlaHandle_hTransaction log handle for the database
colinfottXlaColDesc_t*Pointer to the buffer that holds the column descriptions
tupvoid*Data to be converted
bufvoid*Location where the converted data is placed
buflensize_tSize of the buffer where the converted data is placed

Returns

Returns SQL_SUCCESS if call is successful. Otherwise, use ttXlaError to report the error.


ttXlaDateToODBCCType

Description

Converts a TTXLA_DATE_TT value to an ODBC C value usable by applications. See "Converting complex data types" for a discussion about using this function.

Call this function only on a column of data type TTXLA_DATE_TT. The data type can be obtained from the ttXlaColDesc_t structure returned by the ttXlaGetColumnInfo function.

Required privilege

XLA

Syntax

SQLRETURN ttXlaDateToODBCCType(void* fromData,
                               out DATE_STRUCT* returnData)

Parameters

ParameterTypeDescription
fromDatavoid*Pointer to the date value returned from the transaction log
returnDataDATE_STRUCT*Pointer to storage allocated to hold the converted date

Returns

Returns SQL_SUCCESS if call is successful. Otherwise, use ttXlaError to report the error.


ttXlaDecimalToCString

Description

Converts a TTXLA_DECIMAL_TT value to a string usable by applications. The scale and precision values can be obtained from the ttXlaColDesc_t structure returned by the ttXlaGetColumnInfo function. The scale parameter specifies the maximum number of digits after the decimal point. If the decimal value is larger than 1, the precision parameter should specify the maximum number of digits before and after the decimal point. If the decimal value is less than 1, precision equals scale.

Call this function only for a column of type TTXLA_DECIMAL_TT. The data type can be obtained from the ttXlaColDesc_t structure returned by the ttXlaGetColumnInfo function.

See "Converting complex data types" for a discussion about using this function.

Required privilege

XLA

Syntax

SQLRETURN ttXlaDecimalToCString(void* fromData,
                                out char* returnData,
                                SQLSMALLINT precision,
                                SQLSMALLINT scale)

Parameters

ParameterTypeDescription
fromDatavoid*Pointer to the decimal value returned from the transaction log
returnDatachar*Pointer to storage allocated to hold the converted string
precisionSQLSMALLINTIf fromData is greater than 1, the maximum number of digits before and after the decimal point

If fromData is less than 1, same as scale

scaleSQLSMALLINTMaximum number of digits after the decimal point

Returns

Returns SQL_SUCCESS if call is successful. Otherwise, use ttXlaError to report the error.

Example

This example assumes you have obtained the offset, precision, and scale values from a ttXlaColDesc_t structure and used the offset to obtain a decimal value, pColVal, in a row returned in a transaction log record.

char decimalData[50];
static ttXlaColDesc_t colDesc[255];

rc = ttXlaDecimalToCString(pColVal, (char*)&decimalData,
                                     colDesc->precision, 
                                     colDesc->scale);

ttXlaDeleteBookmark

Description

Deletes the bookmark associated with the specified transaction log handle. After the bookmark has been deleted, it is no longer accessible and its identifier may be reused for another bookmark. The deleted bookmark is no longer associated with the database handle and the effect is the same as having opened the connection with the XLANONE option.

If the bookmark is in use, it cannot be deleted until it is no longer in use.

See "Deleting bookmarks" for a discussion about using this function.


Notes:

  • Do not confuse this with the TimesTen built-in procedure ttXlaBookmarkDelete, documented in "ttXlaBookmarkDelete" in Oracle TimesTen In-Memory Database Reference.

  • You cannot delete replicated bookmarks while the replication agent is running.


Required privilege

XLA

Syntax

SQLRETURN ttXlaDeleteBookmark(ttXlaHandle_h handle)

Parameters

ParameterTypeDescription
handlettXlaHandle_hTransaction log handle

Returns

Returns SQL_SUCCESS if call is successful. Otherwise, use ttXlaError to report the error.

Example

Delete the bookmark for xlahandle:

rc = ttXlaDeleteBookmark(xlahandle);

See also


ttXlaPersistOpen
ttXlaGetLSN
ttXlaSetLSN

ttXlaError

Description

Reports details of any errors encountered from the previous call on the given transaction log handle. Multiple errors may be returned through subsequent calls to ttXlaError. The error stack is cleared following each call to a function other than ttXlaError itself and ttXlaErrorRestart.

See "Handling XLA errors" for a discussion about using this function.

Required privilege

XLA

Syntax

SQLRETURN ttXlaError(ttXlaHandle_h handle,
                     out SQLINTEGER* errCode,
                     out char* errMessage,
                     SQLINTEGER maxLen,
                     out SQLINTEGER* retLen)

Parameters

ParameterTypeDescription
handlettXlaHandle_hTransaction log handle for the database
errCodeSQLINTEGER*Code of the error message to be copied into the errMessage buffer
errMessagechar*Buffer to hold the error text
maxLenSQLINTEGERMaximum length of the errMessage buffer
retLenSQLINTEGER*Actual size of the error message

Returns

Returns SQL_SUCCESS if error information is returned, or SQL_NO_DATA_FOUND if no more errors are found in the error stack. If the errMessage buffer is not large enough, ttXlaError returns SQL_SUCCESS_WITH_INFO.

Example

There can be multiple errors on the error stack. This example shows how to read them all.

char message[100];
SQLINTEGER code;

for (;;) {
  rc = ttXlaError(xlahandle, &code, message, sizeof (message), &retLen);
  if (rc == SQL_NO_DATA_FOUND)
      break;
  if (rc == SQL_ERROR) {
      printf("Error in fetching error message\n");
      break;
  }
  else {
      printf("Error code %d: %s\n", code, message);
  }
}

Note

If you use multiple threads to access a TimesTen transaction log over a single XLA connection, TimesTen creates a latch to control concurrent access. If for some reason the latch cannot be acquired by a thread, the XLA function returns SQL_INVALID_HANDLE.

See also

ttXlaErrorRestart


ttXlaErrorRestart

Description

Resets the error stack so that an application can reread the errors. See "Handling XLA errors" for a discussion about using this function.

Required privilege

XLA

Syntax

SQLRETURN ttXlaErrorRestart(ttXlaHandle_h handle)

Parameters

ParameterTypeDescription
handlettXlaHandle_hTransaction log handle for the database

Returns

Returns SQL_SUCCESS if call is successful. Otherwise, use ttXlaError to report the error.

Example

rc = ttXlaErrorRestart(xlahandle);

See also

ttXlaError


ttXlaGetColumnInfo

Description

Retrieves information about all the columns in the table. Normally, the output parameter for number of columns returned, nreturned, is set to the number of columns returned in colinfo. The systemTableID or userTableID parameter describes the desired table. This call is serialized with respect to changes in the table definition.

See "Obtaining column descriptions" for a discussion about using this function.

Required privilege

XLA

Syntax

SQLRETURN ttXlaGetColumnInfo(ttXlaHandle_h handle,
                             SQLUBIGINT systemTableID,
                             SQLUBIGINT userTableID,
                             out ttXlaColDesc_t* colinfo,
                             SQLINTEGER maxcols,
                             out SQLINTEGER* nreturned)

Parameters

ParameterTypeDescription
handlettXlaHandle_hTransaction log handle for the database
systemTableIDSQLUBIGINTSystem ID of table
userTableIDSQLUBIGINTUser ID of table
colinfottXlaColDesc_t*Pointer to the buffer large enough to hold a separate description for maxcols columns
maxcolsSQLINTEGERMaximum number of columns that can be stored in the colInfo buffer

If the table contains more than maxcols columns, an error is returned.

nreturnedSQLINTEGER*Number of columns returned

Returns

Returns SQL_SUCCESS if call is successful. Otherwise, use ttXlaError to report the error.

Example

For this example, assume the following definitions:

ttXlaColDesc_t colinfo[20];
SQLUBIGINT systemTableID, userTableID;
SQLINTEGER ncols;

To get the description of up to 20 columns using the system table identifier, issue the following call:

rc = ttXlaGetColumnInfo(xlahandle, systemTableID, 0, colinfo, 20, &ncols);

Likewise, the user table identifier can be used:

rc = ttXlaGetColumnInfo(xlahandle, 0, userTableID, colinfo, 20, &ncols);

See "ttXlaColDesc_t" for details and an example on how to access the column data in a returned row.

See also


ttXlaGetTableInfo
ttXlaDecimalToCString
ttXlaDateToODBCCType
ttXlaTimeToODBCCType
ttXlaTimeStampToODBCCType

ttXlaGetLSN

Description

Returns the Current Read log record identifier for the connection specified by the transaction log handle. See "How bookmarks work" for a discussion about using this function.

Required privilege

XLA

Syntax

SQLRETURN ttXlaGetLSN(ttXlaHandle_h handle,
                      out tt_XlaLsn_t* LSN)

Parameters

ParameterTypeDescription
handlettXlaHandle_hTransaction log handle for the database
LSNtt_XlaLsn_t*Current Read log record identifier for the handle


Note:

Be aware that tt_XlaLsn_t, particularly the logFile and logOffset fields, is used differently than in earlier releases, referring to log record identifiers rather than sequentially increasing LSNs. See the note in "tt_XlaLsn_t".

Returns

Returns SQL_SUCCESS if call is successful. Otherwise, use ttXlaError to report the error.

Example

This example returns the Current Read log record identifier, CurLSN.

tt_XlaLsn_t CurLSN;

rc = ttXlaGetLSN(xlahandle, &CurLSN);

See also

ttXlaSetLSN


ttXlaGetTableInfo

Description

Retrieves information about the rows in the table (refer to the description of the ttXlaTblDesc_t data type.) If the userTableID parameter is nonzero, then it is used to locate the desired table. Otherwise, the systemTableID value is used to locate the table. If both are zero, an error is returned. The description is stored in the output parameter tblinfo. This call is serialized with respect to changes in the table definition.

Required privilege

XLA

Syntax

SQLRETURN ttXlaGetTableInfo(ttXlaHandle_h handle,
                            SQLUBIGINT systemTableID,
                            SQLUBIGINT userTableID,
                            out ttXlaTblDesc_t* tblinfo)

Parameters

ParameterTypeDescription
handlettXlaHandle_hTransaction log handle for the database
systemTableIDSQLUBIGINTSystem table ID
userTableIDSQLUBIGINTUser table ID
tblinfottXlaTblDesc_t*Row information

Returns

Returns SQL_SUCCESS if call is successful. Otherwise, use ttXlaError to report the error.

Example

For this example, assume the following definitions:

ttXlaTblDesc_t tabinfo; 
SQLUBIGINT systemTableID, userTableID;

To get table information using a system identifier, find the system table identifier using ttXlaTableByName or other means and issue the following call:

rc = ttXlaGetTableInfo(xlahandle, systemTableID, 0, &tabinfo);

Alternatively, the table information can be retrieved using a user table identifier:

rc = ttXlaGetTableInfo(xlahandle, 0, userTableID, &tabinfo);

See also

ttXlaGetColumnInfo


ttXlaGetVersion

Description

This function is used in combination with ttXlaSetVersion to ensure XLA applications written for older versions of XLA operate on a new version. The configured version is typically the older version, while the actual version is the newer one.

The function retrieves the currently configured XLA version and stores it into configuredVersion parameter. The actual version of the underlying XLA is stored in actualVersion. Due to calls on ttXlaSetVersion, the results in configuredVersion may vary from one call to the next, but the results in actualVersion remain the same.

See "XLA basics" for a discussion about using this function.

Required privilege

XLA

Syntax

SQLRETURN ttXlaGetVersion(ttXlaHandle_h handle,
                          out ttXlaVersion_t* configuredVersion,
                          out ttXlaVersion_t* actualVersion)

Parameters

ParameterTypeDescription
handlettXlaHandle_hTransaction log handle for the database
configuredVersionttXlaVersion_t*Configured version of XLA
actualVersionttXlaVersion_t*Actual version of XLA

Returns

Returns SQL_SUCCESS if call is successful. Otherwise, use ttXlaError to report the error.

Example

Assume the following directions for this example:

ttXlaVersion_t configured, actual;

To determine the current version configuration, use the following call:

rc = ttXlaGetVersion(xlahandle, &configured, &actual);

See also


ttXlaVersionCompare
ttXlaSetVersion

ttXlaNextUpdate

Description

This function fetches up to a specified maximum number of update records from the transaction log and returns the records associated with committed transactions to a specified buffer. The actual number of returned records is reported in the nreturned output parameter. This function requires a bookmark to be present in the database and to be associated with the connection used by the function.

Each call to ttXlaNextUpdate resets the bookmark to the last record read to enable the next call to ttXlaNextUpdate to return the next list of records.

See "Retrieving update records from the transaction log" for a discussion about using this function.

Required privilege

XLA

Syntax

SQLRETURN ttXlaNextUpdate(ttXlaHandle_h handle,
                          out ttXlaUpdateDesc_t*** records,
                          SQLINTEGER maxrecords,
                          out SQLINTEGER* nreturned)

Parameters

ParameterTypeDescription
handlettXlaHandle_hTransaction log handle for the database
recordsttXlaUpdateDesc_t***
Buffer to hold the completed transaction records
maxrecordsSQLINTEGERMaximum number of records to be fetched
nreturnedSQLINTEGER*Actual number of returned records, where 0 is returned if no update data is available

Returns

Returns SQL_SUCCESS if call is successful. Otherwise, use ttXlaError to report the error.

Example

This example retrieves up to 100 records and describes a loop in which each record can be processed:

ttXlaUpdateDesc_t** records;
SQLINTEGER nreturned;
SQLINTEGER i;

rc = ttXlaNextUpdate(xlahandle, &records, 100, &nreturned);
/* Check for errors; if none, process the records */
for (i = 0; i < nreturned; i++) {
  process(records[i]);
}

Notes

Updates are generated for all data definition statements, regardless of tracking status. Updates are generated for data update operations for all tracked tables associated with the bookmark.

In addition, updates are generated for certain special operations, including assigning application-level identifiers for tables and columns and changing a table's tracking status.

See also


ttXlaNextUpdateWait
ttXlaAcknowledge

ttXlaNextUpdateWait

Description

This is similar to the ttXlaNextUpdate function, with the addition of a seconds parameter that specifies the number of seconds to wait if no records are available in the transaction log. The actual number of seconds of wait time can be up to two seconds more than the specified seconds value.

Also see "Retrieving update records from the transaction log".

Required privilege

XLA

Syntax

SQLRETURN ttXlaNextUpdateWait(ttXlaHandle_h handle,
                              out ttXlaUpdateDesc_t*** records,
                              SQLINTEGER maxrecords,
                              out SQLINTEGER* nreturned,
                              SQLINTEGER seconds)

Parameters

ParameterTypeDescription
handlettXlaHandle_hTransaction log handle for the database
recordsttXlaUpdateDesc_t***
Buffer to hold the completed transaction records
maxrecordsSQLINTEGERMaximum number of records to be fetched

Note: The largest effective value is 1000 records.

nreturnedSQLINTEGER*Actual number of records returned, where 0 is returned if no update data is available within the seconds wait period
secondsSQLINTEGERNumber of seconds to wait if the log is empty

Returns

Returns SQL_SUCCESS if call is successful. Otherwise, use ttXlaError to report the error.

Example

This example retrieves up to 100 records and will wait for up to 60 seconds if there are no records available in the transaction log.

ttXlaUpdateDesc_t** records;
SQLINTEGER nreturned;
SQLINTEGER i;

rc = ttXlaNextUpdateWait(xlahandle, &records, 100, &nreturned, 60);
/* Check for errors; if none, process the records */
for (i = 0; i < nreturned; i++) {
  process(records[i]);
}

See also


ttXlaNextUpdate
ttXlaAcknowledge

ttXlaNumberToBigInt

Description

Converts a TTXLA_NUMBER value to a SQLBIGINT value usable by an application.

Call this function only for a column of type TTXLA_NUMBER. The data type can be obtained from the ttXlaColDesc_t structure returned by the ttXlaGetColumnInfo function.

Required privilege

XLA

Syntax

SQLRETURN ttXlaNumberToBigInt(void* fromData,
                              SQLBIGINT* bint)

Parameters

ParameterTypeDescription
fromDatavoid*Pointer to the number value returned from the transaction log
bintSQLBIGINT*The SQLBIGINT value converted from the XLA number value

Returns

Returns SQL_SUCCESS if call is successful. Otherwise, use ttXlaError to report the error.


ttXlaNumberToCString

Description

Converts a TTXLA_NUMBER value to a character string usable by an application.

Call this function only for a column of type TTXLA_NUMBER. The data type can be obtained from the ttXlaColDesc_t structure returned by the ttXlaGetColumnInfo function.

Required privilege

XLA

Syntax

SQLRETURN ttXlaNumberToCString(ttXlaHandle_h handle,
                               void* fromData,
                               char* buf,
                               int buflen
                               int* reslen)

Parameters

ParameterTypeDescription
fromDatavoid*Pointer to the number value returned from the transaction log
bufchar*Location where the converted data is placed
buflenintSize of the buffer where the converted data is placed
reslenint*Number of bytes that were written, assuming buflen is large enough (otherwise, the number of bytes that would have been written)

Returns

Returns SQL_SUCCESS if call is successful. Otherwise, use ttXlaError to report the error.


ttXlaNumberToDouble

Description

Converts a TTXLA_NUMBER value to a long floating point number value usable by applications.

Call this function only for a column of type TTXLA_NUMBER. The data type can be obtained from the ttXlaColDesc_t structure returned by the ttXlaGetColumnInfo function.

Required privilege

XLA

Syntax

SQLRETURN ttXlaNumberToDouble(void* fromData,
                              double* dbl)

Parameters

ParameterTypeDescription
fromDatavoid*Pointer to the number value returned from the transaction log
dbldouble*The long floating point number value converted from the XLA number value

Returns

Returns SQL_SUCCESS if call is successful. Otherwise, use ttXlaError to report the error.


ttXlaNumberToInt

Description

Converts a TTXLA_NUMBER value to a SQLINTEGER value usable by an application.

Call this function only for a column of type TTXLA_NUMBER. The data type can be obtained from the ttXlaColDesc_t structure returned by the ttXlaGetColumnInfo function.

Required privilege

XLA

Syntax

SQLRETURN ttXlaNumberToInt(void* fromData,
                           SQLINTEGER* ival)

Parameters

ParameterTypeDescription
fromDatavoid*Pointer to the number value returned from the transaction log
ivalSQLINTEGER*The SQLINTEGER value converted from the XLA number value

Returns

Returns SQL_SUCCESS if call is successful. Otherwise, use ttXlaError to report the error.


ttXlaNumberToSmallInt

Description

Converts a TTXLA_NUMBER value to a SQLSMALLINT value usable by an application.

Call this function only for a column of type TTXLA_NUMBER. The data type can be obtained from the ttXlaColDesc_t structure returned by the ttXlaGetColumnInfo function.

Required privilege

XLA

Syntax

SQLRETURN ttXlaNumberToSmallInt(void* fromData,
                                SQLSMALLINT* smint)

Parameters

ParameterTypeDescription
fromDatavoid*Pointer to the number value returned from the transaction log
smintSQLSMALLINT*The SQLSMALLINT value converted from the XLA number value

Returns

Returns SQL_SUCCESS if call is successful. Otherwise, use ttXlaError to report the error.


ttXlaNumberToTinyInt

Description

Converts a TTXLA_NUMBER value to a tiny integer value usable by an application.

Call this function only for a column of type TTXLA_NUMBER. The data type can be obtained from the ttXlaColDesc_t structure returned by the ttXlaGetColumnInfo function.

Required privilege

XLA

Syntax

SQLRETURN ttXlaNumberToTinyInt(void* fromData,
                               SQLCHAR* tiny)

Parameters

ParameterTypeDescription
fromDatavoid*Pointer to the number value returned from the transaction log
tinySQLCHAR*The tiny integer value converted from the XLA number value

Returns

Returns SQL_SUCCESS if call is successful. Otherwise, use ttXlaError to report the error.


ttXlaNumberToUInt

Description

Converts a TTXLA_NUMBER value to an unsigned integer value usable by an application.

Call this function only for a column of type TTXLA_NUMBER. The data type can be obtained from the ttXlaColDesc_t structure returned by the ttXlaGetColumnInfo function.

Required privilege

XLA

Syntax

SQLRETURN ttXlaNumberToInt(void* fromData,
                           SQLUINTEGER* ival)

Parameters

ParameterTypeDescription
fromDatavoid*Pointer to the number value returned from the transaction log
ivalSQLUINTEGER*The integer value converted from the XLA number value

Returns

Returns SQL_SUCCESS if call is successful. Otherwise, use ttXlaError to report the error.


ttXlaOraDateToODBCTimeStamp

Description

Converts a TTXLA_DATE value to an ODBC timestamp.

Call this function only for a column of type TTXLA_DATE. The data type can be obtained from the ttXlaColDesc_t structure returned by the ttXlaGetColumnInfo function.

Required privilege

XLA

Syntax

SQLRETURN ttXlaOraDateToODBCTimeStamp(void* fromData,
                                      TIMESTAMP_STRUCT* returnData)

Parameters

ParameterTypeDescription
fromDatavoid*Pointer to the number value returned from the transaction log
returnDataTIMESTAMP_STRUCT*ODBC timestamp value converted from the XLA Oracle DATE value

Returns

Returns SQL_SUCCESS if call is successful. Otherwise, use ttXlaError to report the error.


ttXlaOraTimeStampToODBCTimeStamp

Description

Converts a TTXLA_TIMESTAMP value to an ODBC timestamp.

Call this function only for a column of type TTXLA_TIMESTAMP. The data type can be obtained from the ttXlaColDesc_t structure returned by the ttXlaGetColumnInfo function.

Syntax

SQLRETURN ttXlaOraTimeStampToODBCTimeStamp(void* fromData,
                                           TIMESTAMP_STRUCT* returnData)

Required privilege

XLA

Parameters

ParameterTypeDescription
fromDatavoid*Pointer to the number value returned from the transaction log
returnDataTIMESTAMP_STRUCT*ODBC timestamp value converted from the XLA Oracle TIMESTAMP value

Returns

Returns SQL_SUCCESS if call is successful. Otherwise, use ttXlaError to report the error.


ttXlaPersistOpen

Description

Initializes a transaction log handle to a database to enable access to the transaction log. The hdbc parameter is an ODBC connection handle to a database. Create only one XLA handle for each ODBC connection. After you have created an XLA handle on an ODBC connection, do not issue any other ODBC calls over the ODBC connection until it is closed by ttXlaClose.

The tag is a string that identifies the XLA bookmark (see "About XLA bookmarks"). The tag can identify a new bookmark, either non-replicated or replicated, or one that exists in the system, as specified by the options parameter. The handle parameter is initialized by this call and must be provided on each subsequent call to XLA.

Some actions can be done without a bookmark. When performing these types of actions, you can use the XLANONE option to access the transaction log without a bookmark. Actions that cannot be done without a bookmark are the following:

Multiple applications can concurrently read from the transaction log. See "Initializing XLA and obtaining an XLA handle" for a discussion about using this function.

When this function is successful, XLA sets the autocommit mode to off.

If this function fails but still creates a handle, the handle must be closed to prevent memory leaks.


Note:

Space is allocated by this call. Call ttXlaClose to free space when you are done.

Required privilege

XLA

Syntax

SQLRETURN ttXlaPersistOpen(SQLHDBC hdbc,
                           SQLCHAR* tag,
                           SQLUINTEGER options,
                           out ttXlaHandle_h* handle)

Parameters

ParameterTypeDescription
hdbcSQLHDBCODBC handle for the database
tagSQLCHAR*Identifier for the XLA bookmark

This can be null, in which case options should be set to XLANONE. Maximum allowed length is 31.

optionsSQLUINTEGERBookmark options:
  • XLANONE: Connect without a bookmark. The tag field is ignored.

  • XLACREAT: Create a new non-replicated bookmark. Fails if a bookmark already exists.

  • XLAREPL: Create a new replicated bookmark. Fails if a bookmark already exists.

  • XLAREUSE: Associate with an existing bookmark (non-replicated or replicated). Fails if the bookmark does not exist.

handlettXlaHandle_h*Transaction log handle returned by this call

Returns

Returns SQL_SUCCESS if call is successful. Otherwise, use ttXlaError to report the error.

Example

This example opens a transaction log, returns a handle named xlahandle, and creates a new non-replicated bookmark named mybookmark:

SQLHDBC hdbc;
ttXlaHandle_h xlahandle;

rc = ttXlaPersistOpen(hdbc, ( SQLCHAR*)mybookmark,
                      XLACREAT, &xlahandle);

Alternatively, create a new replicated bookmark as follows:

SQLHDBC hdbc;
ttXlaHandle_h xlahandle;

rc = ttXlaPersistOpen(hdbc, ( SQLCHAR*)mybookmark,
                      XLAREPL, &xlahandle);

Note

Multithreaded applications should create a separate XLA handle for each thread. If multiple threads must use the same XLA handle, use a mutex to serialize thread access to that XLA handle so that only one thread can execute an XLA operation at a time.

See also


ttXlaClose
ttXlaDeleteBookmark
ttXlaGetLSN
ttXlaSetLSN

ttXlaRowidToCString

Description

Converts a ROWID value to a string value usable by applications.

Required privilege

XLA

Syntax

SQLRETURN ttXlaRowidToCString(void* fromData, char* buf, int buflen)

Parameters

ParameterTypeDescription
fromDatavoid*Pointer to the ROWID value returned from the transaction log
bufchar*Pointer to storage allocated to hold the converted string
buflenintLength of the converted string

Returns

Returns SQL_SUCCESS if call is successful. Otherwise, use ttXlaError to report the error.

Example

char charbuf[18];
void* rowiddata;
/* ... */
rc = ttXlaRowidToCString(rowiddata, charbuf, sizeof(charbuf));

ttXlaSetLSN

Description

Sets the Current Read log record identifier for the database specified by the transaction handle. The specified LSN value should be returned from ttXlaGetLSN. It cannot be a user-created value and cannot be earlier than the current bookmark Initial Read log record identifier.

See "About XLA bookmarks" for a discussion about using this function.

Required privilege

XLA

Syntax

SQLRETURN ttXlaSetLSN(ttXlaHandle_h handle,
                      tt_XlaLsn_t* LSN)

Parameters

ParameterTypeDescription
handlettXlaHandle_hTransaction log handle for the database
LSNtt_XlaLsn_t*New log record identifier for the handle


Note:

Be aware that tt_XlaLsn_t, particularly the logFile and logOffset fields, is used differently than in earlier releases, referring to log record identifiers rather than sequentially increasing LSNs. See the note in "tt_XlaLsn_t".

Returns

Returns SQL_SUCCESS if call is successful. Otherwise, use ttXlaError to report the error.

Example

This example sets the Current Read log record identifier to CurLSN.

tt_XlaLsn_t CurLSN;

rc = ttXlaSetLSN(xlahandle, &CurLSN);

See also

ttXlaGetLSN


ttXlaSetVersion

Description

Sets the version of XLA to be used by the application. This version must be either the same as the version received from ttXlaGetVersion or from an earlier version.

See "XLA basics" for a discussion about using this function.

Required privilege

XLA

Syntax

SQLRETURN ttXlaSetVersion(ttXlaHandle_h handle,
                          ttXlaVersion_t* version)

Parameters

ParameterTypeDescription
handlettXlaHandle_hTransaction log handle for the database
versionttXlaVersion_t*Desired version of XLA

Returns

Returns SQL_SUCCESS if call is successful. Otherwise, use ttXlaError to report the error.

Example

To set the configured version to the value specified in requestedVersion, issue the following call:

rc = ttXlaSetVersion(xlahandle, &requestedVersion);

See also


ttXlaVersionCompare
ttXlaGetVersion

ttXlaTableByName

Description

Finds the system and user table identifiers for a table or materialized view by providing the owner and name of the table or view. See "Specifying which tables to monitor for updates" for a discussion about using this function.

Required privilege

XLA

Syntax

SQLRETURN ttXlaTableByName(ttXlaHandle_h handle,
                           char* owner,
                           char* name,
                           out SQLUBIGINT* sysTableID,
                           out SQLUBIGINT* userTableID)

Parameters

ParameterTypeDescription
handlettXlaHandle_hTransaction log handle for the database
ownerchar*Owner for the table or view as a string
namechar*Name of the table or view
sysTableIDSQLUBIGINT*System table ID
userTableIDSQLUBIGINT*User table ID

Returns

Returns SQL_SUCCESS if call is successful. Otherwise, use ttXlaError to report the error.

Example

To get the system and user table IDs associated with the table PURCHASING.INVOICES, use the following call:

SQLUBIGINT sysTableID;
SQLUBIGINT userTableID;

rc = ttXlaTableByName(xlahandle, "PURCHASING", "INVOICES", 
                      &sysTableID, &userTableID);

See also

ttXlaTableStatus


ttXlaTableStatus

Description

Returns the update status for a table. Identify the table by specifying either a user ID (userTableID) or a system ID (systemTableID). If userTableID is nonzero, it is used to locate the table. Otherwise systemTableID is used. If both are zero, an error is returned.

Specifying a value for newstatus sets the update status to *newstatus. A nonzero status means the table specified by systemTableID is available through XLA. Zero means the table is not tracked. Changes to table update status are effective immediately.

Updates to a table are tracked only if update tracking was enabled for the table at the time the update was performed. This call is serialized with respect to updates to the underlying table. Therefore, transactions that update the table run either completely before or completely after the change to table status.

To use ttXlaTableStatus, the user must be connected to a bookmark. The function reports inserts, updates, and deletes only to the bookmark that has subscribed to the table. It reports DDL events to all bookmarks. DDL events include CREATAB, DROPTAB, CREAIND, DROPIND, CREATVIEW, DROPVIEW, CREATSEQ, DROPSEQ, CREATSYN, DROPSYN, ADDCOLS, DRPCOLS, TRUNCATE, SETTBL1, and SETCOL1 transactions. See "ttXlaUpdateDesc_t" for information about these event types.

See "Specifying which tables to monitor for updates" for a discussion about using this function.


Note:

DML updates to a table being tracked through XLA will not prevent ttXlaTableStatus from running. However, DDL updates to the table being tracked, which take a lock on SYS.TABLES, will delay ttXlaTableStatus from running in serializable isolation against SYS.TABLES.

Required privilege

XLA

Syntax

SQLRETURN ttXlaTableStatus(ttXlaHandle_h handle,
                           SQLUBIGINT systemTableID,
                           SQLUBIGINT userTableID,
                           out SQLINTEGER* oldstatus,
                           SQLINTEGER* newstatus)

Parameters

ParameterTypeDescription
handlettXlaHandle_hTransaction log handle for the database
systemTableIDSQLUBIGINTSystem ID of table
userTableIDSQLUBIGINTUser ID of table
oldstatusSQLINTEGER*XLA old status:
  • 1: On

  • 0: Off

newstatusSQLINTEGER*XLA new status:
  • 1: On

  • 0: Off


Returns

Returns SQL_SUCCESS if call is successful. Otherwise, use ttXlaError to report the error.

Example

The following examples assume that the system or user table identifiers are found using ttXlaTableByName or some other means.

Assume these declarations for the example:

SQLUBIGINT systemTableID;
SQLUBIGINT userTableID;
SQLINTEGER currentStatus, requestedStatus;

To find the status of a table given its system table identifier, use the following call:

/* Get system table identifier into systemTableID, then ... */
rc = ttXlaTableStatus(xlahandle, systemTableID, 0,
                      &currentStatus, NULL);

The currentStatus value will be nonzero if update tracking for the table is enabled, or zero otherwise.

To enable update tracking for a table given a system table identifier, set the requested status to 1 as follows:

requestedStatus = 1;

rc = ttXlaTableStatus(xlahandle, systemTableID, 0,
                      NULL, &requestedStatus);

You can set a new update tracking status and retrieve the current status in a single call, as in the following example:

requestedStatus = 1;

rc = ttXlaTableStatus(xlahandle, systemTableID, 0,
                      &currentStatus, &requestedStatus);

The above call enables update tracking for a table by system table identifier and retrieves the prior update tracking status in the variable currentStatus.

All of these examples can be done using user table identifiers as well. To retrieve the update tracking status of a table through its user table identifier, use the following call:

/* Get system table identifier into userTableID, then ... */

rc = ttXlaTableStatus(xlahandle, 0, userTableID,
                      &currentStatus, NULL);

See also

ttXlaTableByName


ttXlaTableVersionVerify

Description

Verifies that the cached table definitions are compatible with the XLA record being processed. Table definitions change only when the ALTER TABLE statement is used to add or remove columns.

You can monitor the XLA stream for XLA records of transaction type ADDCOLS and DRPCOLS to avoid the overhead of using this function. When an XLA record of transaction type ADDCOLS or DROPCOLS is encountered, refresh the table and column definitions. See "Inspecting record headers and locating row addresses" for information about monitoring XLA records for transaction type.

Required privilege

XLA

Syntax

SQLRETURN ttXlaTableVersionVerify(ttXlaHandle_h handle
                                  ttXlaTblVerDesc_t* table,
                                  ttXlaUpdateDesc_t* record
                                  out SQLINTEGER* compat)

Parameters

ParameterTypeDescription
handlettXlaHandle_hTransaction log handle for the database
tablettXlaTblVerDesc_t*A cached table description
recordttXlaUpdateDesc_t*XLA record to be processed
compatSQLINTEGER*Compatibility information:
  • 1: Tables are compatible.

  • 0: Tables are not compatible.


Returns

Returns SQL_SUCCESS if cached table definition is compatible with the XLA record being processed. Otherwise, use ttXlaError to report the error.

Example

This example checks the compatibility of a table.

SQLINTEGER compat;
ttXlaTbVerDesc_t table;
ttXlaUpdateDesc_t* record;
/*
 * Get the desired table definitions into the variable "table"
 */
rc = ttXlaTableVersionVerify(xlahandle, &table, record, &compat);
if (compat) {
/*
 * Compatible
 */
}
else {
/*
 * Not compatible or some other error occurred
 * If not compatible, issue a call to ttXlaVersionTableInfo and
 * ttXlaVersionColumnInfo to get the new definition.
 */
}

See also


ttXlaVersionColumnInfo
ttXlaVersionTableInfo

ttXlaTimeToODBCCType

Description

Converts a TTXLA_TIME value to an ODBC C value usable by applications. See "Converting complex data types" for a discussion about using this function.

Call this function only for a column of type TTXLA_TIME. The data type can be obtained from the ttXlaColDesc_t structure returned by the ttXlaGetColumnInfo function.

Required privilege

XLA

Syntax

SQLRETURN ttXlaTimeToODBCCType (void* fromData,
                                out TIME_STRUCT* returnData)

Parameters

ParameterTypeDescription
fromDatavoid*Pointer to the time value returned from the transaction log
returnDataTIME_STRUCT*Pointer to storage allocated to hold the converted time

Returns

Returns SQL_SUCCESS if call is successful. Otherwise, use ttXlaError to report the error.

Example

This example assumes you have used the offset value returned in a ttXlaColDesc_t structure to obtain a time value, pColVal, from a row returned in a transaction log record.

TIME_STRUCT time;

rc = ttXlaTimeToODBCCType(pColVal, &time);

ttXlaTimeStampToODBCCType

Description

Converts a TTXLA_TIMSTAMP_TT value to an ODBC C value usable by applications. See "Converting complex data types" for a discussion about using this function.

Call this function only for a column of type TTXLA_TIMSTAMP_TT. The data type can be obtained from the ttXlaColDesc_t structure returned by the ttXlaGetColumnInfo function.

Required privilege

XLA

Syntax

SQLRETURN ttXlaTimeStampToODBCCType(void* fromData,
                                    out TIMESTAMP_STRUCT* returnData)

Parameters

ParameterTypeDescription
fromDatavoid*Pointer to the timestamp value returned from the transaction log
returnDataTIMESTAMP_STRUCT*Pointer to storage allocated to hold the converted timestamp

Returns

Returns SQL_SUCCESS if call is successful. Otherwise, use ttXlaError to report the error.

Example

This example assumes you have used the offset value returned in a ttXlaColDesc_t structure to obtain a timestamp value, pColVal, from a row returned in a transaction log record.

TIMESTAMP_STRUCT timestamp;

rc = ttXlaTimeStampToODBCCType(pColVal, &timestamp);

ttXlaVersionColumnInfo

Description

Retrieves information about the columns in a table for which a change update XLA record must be processed.

Required privilege

XLA

Syntax

SQLRETURN ttXlaVersionColumnInfo(ttXlaHandle_h handle,
                                 ttXlaUpdateDesc_t* record,
                                 out ttXlaColDesc_t* colinfo,
                                 SQLINTEGER maxcols,
                                 out SQLINTEGER* nreturned)

Parameters

ParameterTypeDescription
handlettXlaHandle_hTransaction log handle for the database
recordttXlaUpdateDesc_t*XLA record to be processed
colinfottXlaColDesc_t*A pointer to the buffer large enough to hold a description for maxcols columns
maxcolsSQLINTEGERMaximum number of columns the table can have

Note: If the table contains more than maxcols columns, an error is returned.

nreturnedSQLINTEGER*Number of columns returned

Returns

Returns SQL_SUCCESS if call is successful. Otherwise, use ttXlaError to report the error.

Example

For this example, assume the following definitions:

ttXlaHandle_h xlahandle
ttXlaUpdateDesc_t* record;
ttXlaColDesc_t colinfo[20];
SQLINTEGER ncols;

The following call retrieves the description of up to 20 columns:

rc = ttXlaVersionColumnInfo(xlahandle, record, colinfo, 20, &ncols);

ttXlaVersionCompare

Description

Compares two XLA versions and returns the result.

Required privilege

XLA

Syntax

SQLRETURN ttXlaVersionCompare(ttXlaHandle_h handle,
                              ttXlaVersion_t* version1,
                              ttXlaVersion_t* version2,
                              out SQLINTEGER* comparison)

Parameters

ParameterTypeDescription
handlettXlaHandle_hTransaction log handle for the database
version1ttXlaVersion_t*
Version of XLA to compare with version2
version2ttXlaVersion_t*Version of XLA to compare with version1
comparisonSQLINTEGER*Comparison result:
  • 0: Indicates version1 and version2 match.

  • -1: Indicates version1 is earlier than version2.

  • +1: Indicates version1 is later than version2.


Returns

Returns SQL_SUCCESS if call is successful. Otherwise, use ttXlaError to report the error.

Example

To compare the configured version against the actual version of XLA, issue the following call:

ttXlaVersion_t configured, actual;
SQLINTEGER comparision;

rc = ttXlaGetVersion (xlahandle, &configured, &actual);
rc = ttXlaVersionCompare (xlahandle, &configured, &actual,
                          &comparison);

Notes

When connecting two systems with XLA-based replication, use the following protocol:

  1. At the primary site, retrieve the XLA version using ttXlaGetVersion. Send this version information to the standby site.

  2. At the standby site, retrieve the XLA version using ttXlaGetVersion. Use ttXlaVersionCompare to determine which version is earlier. The earlier version number must be used to ensure proper operation between the two sites. Use ttXlaSetVersion to specify the version of the interface to use at the standby site. Send the earlier version number back to the primary site.

  3. When the chosen version is received at the primary site, use ttXlaSetVersion to specify the version of XLA to use.

See also


ttXlaGetVersion
ttXlaSetVersion

ttXlaVersionTableInfo

Description

Retrieves the table definition for the change update record that must be processed. The table description is stored in the tableinfo output parameter.

Required privilege

XLA

Syntax

SQLRETURN ttXlaVersionTableInfo(ttXlaHandle_h handle,
                                ttXlaUpdateDesc_t* record,
                                out ttXlaTblVerDesc_t* tblinfo)

Parameters

ParameterTypeDescription
handlettXlaHandle_hTransaction log handle for the database
recordttXlaUpdateDesc_t*XLA record to be processed
tableinfottXlaTblVerDesc_t*Information about table definition

Returns

Returns SQL_SUCCESS if call is successful. Otherwise, use ttXlaError to report the error.

Example

For this example, assume the following definitions:

ttXlaHandle_h xlahandle;
ttXlaUpdateDesc_t* record;
ttXlaTblVerDesc_t tabinfo;

The following call retrieves a table definition:

rc = ttXlaVersionTableInfo(xlahandle, record, &tabinfo);

XLA replication function reference

TimesTen replication as described in Oracle TimesTen In-Memory Database Replication Guide is sufficient for most customer needs; however, it is also possible to use XLA functions to replicate updates from one database to another. Implementing your own replication scheme on top of XLA in this way is fairly complicated, but can be considered if TimesTen replication is not feasible for some reason.

This section documents the functions that are exclusive to using XLA as a replication mechanism. Functions are listed in alphabetical order.


ttXlaApply

This function is part of XLA replication functionality and is not appropriate for use in a typical XLA application.

Description

Applies an update to the database associated with the transaction log handle. The return value indicates whether the update was successful. The return also shows if the update encountered a persistent problem. (To see whether the update encountered a transient problem such as a deadlock or timeout, you must call ttXlaError and check the error code.)

If the ttXlaUpdateDesc_t record is a transaction commit, the underlying database transaction is committed. No other transaction commits are performed by ttXlaApply. If the parameter test is true, the "old values" in the update description are compared against the current contents of the database for record updates and deletions. If the old value in the update description does not match the corresponding row in the database, this function rejects the update and returns an sb_ErrXlaTupleMismatch error.

See "Using XLA as a replication mechanism" for a discussion about using this function.


Note:

ttXlaApply cannot be used if the table definition was updated since it was originally written to the transaction log. Unique key and foreign key constraints are checked at the row level rather than at the statement level.

Required privilege

ADMIN

Additional privileges may be required on the target database for the ttXlaApply operation. For example, to apply a CREATETAB (create table) record to the target database, you must have CREATE TABLE or CREATE ANY TABLE privilege, as appropriate.

Syntax

SQLRETURN ttXlaApply(ttXlaHandle_h handle,
                     ttXlaUpdateDesc_t* record,
                     SQLINTEGER test)

Parameters

ParameterTypeDescription
handlettXlaHandle_hTransaction log handle for the database
recordttXlaUpdateDesc_t*Transaction to generate SQL statement
testSQLINTEGERTest for old values:
  • 1: Test on

  • 0: Test off


Returns

Returns SQL_SUCCESS if call is successful. Otherwise, use ttXlaError to report the error.

If test is 1 and ttXlaApply detects an update conflict, an sb_ErrXlaTupleMismatch error is returned.

Example

This example applies an update to a database without testing for the previous value of the existing record:

ttXlaUpdateDesc_t record;
rc = ttXlaApply(xlahandle, &record, 0);

Note

When calling ttXlaApply, it is possible for the update to timeout or deadlock with concurrent transactions. In such cases, it is the application's responsibility to roll the transaction back and reapply the updates.

See also


ttXlaCommit
ttXlaRollback
ttXlaLookup
ttXlaTableCheck
ttXlaGenerateSQL

ttXlaCommit

This function is part of XLA replication functionality and is not appropriate for use in a typical XLA application.

Description

Commits the current transaction being applied on the transaction log handle. This routine commits the transaction regardless of whether the transaction has completed. You can call this routine to respond to transient errors (timeout or deadlock) reported by ttXlaApply, which applies the current transaction if it does not encounter an error.

See "Handling timeout and deadlock errors" for a discussion about using this function.

Required privilege

XLA

Syntax

SQLRETURN ttXlaCommit(ttXlaHandle_h handle)

Parameters

ParameterTypeDescription
handlettXlaHandle_hTransaction log handle for the database

Returns

Returns SQL_SUCCESS if call is successful. Otherwise, use ttXlaError to report the error.

Example

rc = ttXlaCommit(xlahandle);

See also


ttXlaApply
ttXlaRollback
ttXlaLookup
ttXlaTableCheck
ttXlaGenerateSQL

ttXlaGenerateSQL

This function is part of XLA replication functionality and is not appropriate for use in a typical XLA application.


Note:

This function does not currently work with LOB locators.

Description

Generates a SQL DML or DDL statement that expresses the effect of the update record. The generated statement is not applied to any database. Instead, the statement is returned in the given buffer, whose maximum size is specified by the maxLen parameter. The actual size of the buffer is returned in actualLen. For update and delete records, ttXlaGenerateSQL requires a primary key or a unique index on a non-nullable column to generate the correct SQL.

The generated SQL statement is encoded in the connection character set that is associated with the ODBC connection of the XLA handle.

Also see "Replicating updates to a non-TimesTen database".

Required privilege

XLA

Syntax

SQLRETURN ttXlaGenerateSQL(ttXlaHandle_h handle,
                           ttXlaUpdateDesc_t* record,
                           out char* buffer,
                           SQLINTEGER maxLen,
                           out SQLINTEGER* actualLen)

Parameters

ParameterTypeDescription
handlettXlaHandle_hTransaction log handle for the database
recordttXlaUpdateDesc_t*Record to be translated into SQL
bufferchar*Location of the translated SQL statement
maxLenSQLINTEGERMaximum length of the buffer, in bytes
actualLenSQLINTEGER*Actual length of the buffer, in bytes

Returns

Returns SQL_SUCCESS if call is successful. Otherwise, use ttXlaError to report the error.

Example

This example generates the text of a SQL statement that is equivalent to the UPDATE expressed by an update record:

ttXlaUpdateDesc_t record;
char buffer[200];
/*
 * Get the desired update record into the varable record.
 */

SQLINTEGER actualLength;

rc = ttXlaGenerateSQL(xlahandle, &record, buffer, 200,
                      &actualLength);

Note

The ttXlaGenerateSQL function cannot generate SQL statements for update records associated with a table that has been dropped or altered since the record was generated.

See also


ttXlaApply
ttXlaCommit
ttXlaRollback
ttXlaLookup
ttXlaTableCheck

ttXlaLookup

This function is part of XLA replication functionality and is not appropriate for use in a typical XLA application.

Description

This function looks for a record in the given table with key values according to the keys parameter. The formats of the keys and result records are the same as for ordinary rows. This function requires a primary key on the underlying table.

Required privilege

XLA

Syntax

SQLRETURN ttXlaLookup(ttXlaHandle_h handle,
                      ttXlaTableDesc_t* table,
                      void* keys,
                      out void* result,
                      SQLINTEGER maxsize,
                      out SQLINTEGER* retsize)

Parameters

ParameterTypeDescription
handlettXlaHandle_hTransaction log handle for the database
tablettXlaTblDesc_t*Table to search
keysvoid*A record in the defined structure for the table

Only those columns of the keys record that are part of the primary key for the table are examined.

resultvoid*Where the located record is copied

If no record exists with the matching key columns, an error is returned.

maxsizeSQLINTEGERSize of the largest record that can fit into the result buffer
retsizeSQLINTEGER*Actual size of the record

Returns

Returns SQL_SUCCESS if call is successful. Otherwise, use ttXlaError to report the error.

Example

This example looks up a record given a pair of integer key values. Before this call, table should describe the desired table and keybuffer contains a record with the key columns set.

char keybuffer[100];
char recbuffer[2000];
ttXlaTableDesc_t table;
SQLINTEGER recordSize;

rc = ttXlaLookup(xlahandle, &table, keybuffer, recbuffer,
                 sizeof (recbuffer), &recordSize);

See also


ttXlaApply
ttXlaCommit
ttXlaRollback
ttXlaTableCheck
ttXlaGenerateSQL

ttXlaRollback

This function is part of XLA replication functionality and is not appropriate for use in a typical XLA application.

Description

Rolls back the current transaction being applied on the transaction log handle. You can call this routine to respond to transient errors (timeout or deadlock) reported by ttXlaApply.

See "Handling timeout and deadlock errors" for a discussion about using this function.

Required privilege

XLA

Syntax

SQLRETURN ttXlaRollback(ttXlaHandle_h handle)

Parameters

ParameterTypeDescription
handlettXlaHandle_hTransaction log handle for the database

Returns

Returns SQL_SUCCESS if call is successful. Otherwise, use ttXlaError to report the error.

Example

rc = ttXlaRollback(xlahandle);

See Also


ttXlaApply
ttXlaCommit
ttXlaLookup
ttXlaTableCheck
ttXlaGenerateSQL

ttXlaTableCheck

This function is part of XLA replication functionality and is not appropriate for use in a typical XLA application.

Description

When using XLA as a replication mechanism, this function verifies that the named table in the ttXlaTblDesc_t structure received from a master database is compatible with a subscriber database or database associated with the transaction log handle. The compat parameter indicates whether the tables are compatible.

See "Checking table compatibility between databases" for a discussion about using this function.

Required privilege

XLA

Syntax

SQLRETURN ttXlaTableCheck(ttXlaHandle_h handle,
                          ttXlaTblDesc_t* table,
                          ttXlaColDesc_t* columns,
                          out SQLINTEGER* compat)

Parameters

ParameterTypeDescription
handlettXlaHandle_hTransaction log handle for the database
tablettXlaTblDesc_t*Table description
columnsttXlaColDesc_t*Column description for the table
compatSQLINTEGER*Compatibility information:
  • 1: Tables are compatible.

  • 0: Tables are not compatible.


Returns

Returns SQL_SUCCESS if call is successful. Otherwise, use ttXlaError to report the error.

Example

This example checks the compatibility of a table:

SQLINTEGER compat;
ttXlaTblDesc_t table;
ttXlaColDesc_t columns[20];
/*
 * Get the desired table and column definitions into
 * the variables "table" and "columns"
 */
rc = ttXlaTableCheck(xlahandle, &table, columns, &compat);
if (compat) {
    /* Compatible */
}
else {
    /*
     * Not compatible or some other error occurred
     */
}

See also


ttXlaApply
ttXlaCommit
ttXlaRollback
ttXlaLookup
ttXlaGenerateSQL

C data structures used by XLA

This section describes the C data structures used by the XLA functions described in this chapter. These structures are defined in the following file:

install_dir/include/tt_xla.h

You must include this file when building your XLA application.

Table 9-1 Summary of C data structures

<th id="r1c2-t55" align="left" valign="bottom" rowspan="1" colspan="1">Description
C data structure

ttXlaNodeHdr_t


Describes the record type. Used at the beginning of records returned by XLA.

ttXlaUpdateDesc_t


Describes an update record.

ttXlaVersion_t


Describes XLA version information returned by ttXlaGetVersion.

ttXlaTblDesc_t


Describes table information returned by ttXlaGetTableInfo.

ttXlaTblVerDesc_t


Describes table version returned by ttXlaVersionTableInfo.

ttXlaColDesc_t


Describes table column information returned by ttXlaGetColumnInfo.

tt_LSN_t


Describes a log record identifier used by bookmarks. This structure is used by the ttXlaUpdateDesc_t structure.

tt_XlaLsn_t


Describes a log record identifier used by an XLA bookmark.



ttXlaNodeHdr_t

Most C data structures begin with a standard header that describes the data record type and length. The standard header has the type ttXlaNodeHdr_t.

This header has the following fields.

FieldTypeDescription
nodeTypecharThe type of record:
  • TTXLANHVERSION: Version

  • TTXLANHUPDATE: Update

  • TTXLANHTABLEDESC: Table description

  • TTXLANHCOLDESC: Column description

  • TTXLANHSTATUS: Status

  • TTXLANHINVALID: Invalid

byteOrdercharByte order of the record:
  • "1": Big-endian

  • "2": Little-endian

lengthSQLUINTEGERTotal length of record, including all attachments


ttXlaUpdateDesc_t

This structure describes an update operation to a single row (or tuple) in the database. Each update record returned by a ttXlaNextUpdate or ttXlaNextUpdateWait function begins with a fixed length ttXlaUpdateDesc_t header followed by zero to two rows from the database. The row data differs depending on the record type reported in the ttXlaUpdateDesc_t header:

  • No rows are present in a COMMITONLY record.

  • One row is present in INSERTTUP or DELETETUP.

  • Two rows are present in an UPDATETUP record to report the row data before and after the update, respectively.

  • Special format rows are present in CREATAB, DROPTAB, CREAIND, DROPIND, CREATVIEW, DROPVIEW, CREATSEQ, DROPSEQ, CREATSYN, DROPSYN, ADDCOLS, and DRPCOLS records, which are described in "Special update data formats".

The flags field is a bit-map of special options for the record update.

The connID field identifies the ODBC connection handle that initiated the update. This value can be used to determine if updates came from the same connection.

A separate commit XLA record is generated when a call to the ttApplicationContext procedure is not followed by an operation that generates an XLA record. See "Passing application context" for a description of the ttApplicationContext procedure.

Note

XLA cannot receive notification of the following:

  • CREATE VIEW or DROP VIEW for a non-materialized view

  • CREATE GLOBAL TEMPORARY TABLE or DROP TABLE for a temporary table

The only XLA records that can be generated from an ALTER TABLE operation are of the following types:

  • ADDCOLS or DRPCOLS when columns are added or dropped

  • CREAIND or DROPIND when a unique attribute of a column is modified

While sequence creates (CREATESEQ) and drops (DROPSEQ) are visible through XLA, sequence increments are not.

All deletes resulting from cascading deletes and aging are visible through XLA. The flags value (discussed in the following table) indicates when deletes are due to cascading or aging.

The fields of the update header defined by ttXlaUpdateDesc_t are as follows.

FieldTypeDescription
headerttXlaNodeHdr_t
Standard data header
typeSQLUSMALLINTRecord type:
  • CREATAB: Create table.

  • DROPTAB: Drop table.

  • CREAIND: Create index.

  • DROPIND: Drop index.

  • CREATVIEW: Create view.

  • DROPVIEW: Drop view.

  • CREATSEQ: Create sequence.

  • DROPSEQ: Drop sequence.

  • CREATSYN: Create synonym.

  • DROPSYN: Drop synonym.

  • ADDCOLS: Add columns.

  • DRPCOLS: Drop columns.

  • TRUNCATE: Truncate table.

  • INSERTTUP: Insert.

  • UPDATETUP: Update.

  • DELETETUP: Delete.

  • COMMITONLY: Commit.

flagsSQLUSMALLINTSpecial options on record update:
  • TT_UPDCOMMIT: Indicates that the update record is the last record for the transaction. (Implied commit.)

  • TT_UPDFIRST: Indicates that the update record is the first record for the transaction.

  • TT_UPDREPL: Indicates that this update was the result of a non-XLA TimesTen replicated update from another database.

  • TT_UPDCOLS: Indicates the presence of a list following the last returned row that specifies which columns in the row were updated. The list consists of an array of SQLUSMALLINT values, the first of which is the number of columns that were updated, followed by the column numbers of the updated columns. For example, if the first and third columns are updated, the array is (2, 1, 3) or (2, 3, 1), depending on the UPDATE statement used. This array is in all UPDATETUP records.

  • TT_UPDDEFAULT: Indicates that the update record (either a CREATAB or ADDCOLS) contains default column values. If set, the default columns are presented as an array of SQLUSMALLINT values followed by a string with all the default values concatenated. The number of SQLUSMALLINT values in the array equals the number of columns in the CREATAB or ADDCOLS record.

  • TT_CASCDEL: Indicates that the XLA update was generated as part of a cascade delete operation.

  • TT_AGING: Indicates that the XLA update was generated as part of an aging operation.

If the value of a specific column is 0, it indicates that column does not have a default value. The defaults for all nonzero values are concatenated in a string and are presented in order, with the array value indicating the length of the default value. For example, three columns with defaults 1 of type INTEGER, no default, and "apple" of type VARCHAR2(10) is (1,0,5)"1apple".

Decimal values for each of these flags bits is as follows. (Note that some flag values are for internal use only.)

TT_UPDCOMMIT     1
TT_UPDFIRST      2
TT_UPDREPL       4
TT_UPDCOLS       8
TT_UPDDEFAULT   64
TT_CASCDEL     256
TT_AGING       512
contextOffsetSQLUINTEGEROffset to application-provided context value

This value is 0 if there is no context. A nonzero value indicates the location of the context relative to the beginning of the XLA record.

connIDSQLUBIGINTConnection ID owning the transaction
sysTableIDSQLUBIGINTSystem-provided identifier of the affected table
userTableIDSQLUBIGINTApplication-defined table ID of the affected table
tranIDSQLUBIGINTRead-only, system-provided transaction identifier
LSNtt_LSN_t
Transaction log record identifier of this operation, used for diagnostics
tuple1SQLUINTEGERLength of first row (tuple), or zero
tuple2SQLUINTEGERLength of second row (tuple), or zero


Note:

Be aware that tt_LSN_t, particularly the logFile and logOffset fields, is used differently than in earlier releases, referring to log record identifiers rather than sequentially increasing LSNs. See the note in "tt_LSN_t".

Special update data formats

The data contained in an update record follows the ttXlaTblDesc_t header. This section describes the data formats for the special update records related to specific SQL operations.

CREATE TABLE

For a CREATE TABLE operation, the special row value consists of the ttXlaTblDesc_t record describing the new table, followed by the ttXlaColDesc_t records that describe each column.


ALTER TABLE

For an ALTER TABLE operation, the special row value consists of a ttXlaDropTableTup_t or ttXlaAddColumnTup_t value, followed by a ttXlaColDesc_t record that describes the column.


ttXlaDropTableTup_t

For a DROP TABLE operation, the row value is as follows.

FieldTypeDescription
tblNamechar(31)Name of the dropped table
tblOwnerchar(31)Owner of the dropped table


ttXlaTruncateTableTup_t

For a TRUNCATE TABLE operation, the row value is as follows.

FieldTypeDescription
tblNamechar(31)Name of the truncated table
tblOwnerchar(31)Owner of the truncated table


ttXlaCreateIndexTup_t

For a CREATE INDEX operation, the row value is as follows.

FieldTypeDescription
tblNamechar(31)Name of the table on which the index is defined
tblOwnerchar(31)Owner of the table on which the index is defined
ixNamechar(31)Name of the new index
flagchar(31)Index flag:
  • "P": Primary key

  • "F": Foreign key

  • "R": Regular

nixcolsSQLUINTEGERNumber of indexed columns
ixColsSysSQLUINTEGER(16)Indexed column numbers using system numbers
ixColsUserSQLUINTEGER(16)Indexed column numbers using user-defined column IDs
ixTypecharType of index:
  • "T": Range

  • "H": Hash

  • "B": Bit map

ixUniquecharUniqueness of index:
  • "U": Unique

  • "N": Non-unique

pagesSQLUINTEGERNumber of pages for hash indexes


ttXlaDropIndexTup_t

For a DROP INDEX operation, the row value is as follows.

FieldTypeDescription
tblNamechar(31)Name of the table on which the index was dropped
tblOwnerchar(31)Owner of the table on which the index was dropped
ixNamechar(31)Name of the dropped index


ttXlaAddColumnTup_t

For an ADD COLUMN operation, the row value is as follows.

FieldTypeDescription
ncolsSQLUINTEGERNumber of additional columns

Following this special row are the ttXlaColDesc_t records describing the new columns.


ttXlaDropColumnTup_t

For a DROP COLUMN operation, the row value is as follows.

FieldTypeDescription
ncolsSQLUINTEGERNumber of dropped columns

Following this special row is an array of ttXlaColDesc_t records describing the columns that were dropped.


ttXlaCreateSeqTup_t

For a CREATE SEQUENCE operation, the row value is as follows.

FieldTypeDescription
sqNamechar(31)Name of sequence
sqOwnerchar(31)Owner of sequence
cyclecharCycle flag

Indicates whether the sequence number generator will continue to generate numbers after it reaches the maximum or minimum value:

  • "1": Yes

  • "0": No

minvalSQLBIGINTMinimum value of sequence
maxvalSQLBIGINTMaximum value of sequence
incrSQLBIGINTIncrement between sequence numbers

Positive numbers indicate an ascending sequence and negative numbers indicate a descending sequence. In a descending sequence, the range goes from maxval to minval. In an ascending sequence, the range goes from minval to maxval.



ttXlaDropSeqTup_t

For a DROP SEQUENCE operation, the row value is as follows.

FieldTypeDescription
sqNamechar(31)Name of sequence
sqOwnerchar(31)Owner of sequence


ttXlaViewDesc_t

For a CREATE VIEW operation, the row value is as follows.


Note:

This applies to either materialized or non-materialized views.

FieldTypeDescription
vwNamechar(31)Name of view
vwOwnerchar(31)Owner of view
sysTableIDSQLUBIGINTSystem table ID stored in SYS.TABLES


ttXlaDropViewTup_t

For a DROP VIEW operation, the row value is as follows.


Note:

This applies to either materialized or non-materialized views.

FieldTypeDescription
vwNamechar(31)Name of view
vwOwnerchar(31)Owner of view


ttXlaCreateSynTup_t

For a CREATE SYNONYM operation, the row value is as follows.

FieldTypeDescription
synNamechar(31)Name of synonym
synOwnerchar(31)Owner of synonym
objNamechar(31)Name of object the synonym points to
objOwnerchar(31)Owner of object the synonym points to
isPubliccharIndicates whether the synonym is public:
  • "1": True

  • "0": False

isReplacecharIndicates whether the synonym was created using CREATE OR REPLACE:
  • "1": True

  • "0": False



ttXlaDropSynTup_t

For a DROP SYNONYM operation, the row value is as follows.

FieldTypeDescription
synNamechar(31)Name of synonym
synOwnerchar(31)Owner of synonym
isPubliccharIndicates whether the synonym is public:
  • "1": True

  • "0": False



ttXlaSetTableTup_t

The description of the SET TABLE ID operation uses the previously assigned application table identifier in the main part of the update record and provides the new value of the application table identifier in the following special row.

FieldTypeDescription
newIDSQLUBIGINTNew user-defined table ID


ttXlaSetColumnTup_t

The description of the SET COLUMN ID operation provides the following special row:

FieldTypeDescription
oldUserColIDSQLUINTEGERPrevious user-defined column ID value
newUserColIDSQLUINTEGERNew user-defined column ID value
sysColIDSQLUINTEGERSystem column ID


ttXlaSetStatusTup_t

A change in a table's replication status provides the following special row:

FieldTypeDescription
oldStatusSQLUINTEGERPrevious replication status
newStatusSQLUINTEGERNew replication status


Locating the row data following a ttXlaUpdateDesc_t header

See "Retrieving update records from the transaction log" and "Inspecting record headers and locating row addresses" for a detailed discussion on obtaining update records and inspecting the contents of ttXlaUpdateDesc_t headers. Below is a summary of these procedures.

The update header is immediately followed by the row data. The row data is stored in an internal format with the offsets given in the ttXlaColDesc_t structure returned by ttXlaGetColumnInfo.

You can locate the address of the row data by adding the address of the update header to its size.

For example:

char* Row = (char*)&ttXlaUpdateDesc_t +
             sizeof(ttXlaUpdateDesc_t);

For UPDATETUP records, there are two rows of data following the ttXlaUpdateDesc_t header. The first row contains the data before the update, and the second row the data after the update.

Since the new row is right after the old row, you can calculate its address by adding the address of the old row to its length (tuple1).

For example:

char* oldRow = (char*)&ttXlaUpdateDesc_t +
                sizeof(ttXlaUpdateDesc_t);
char* newRow = oldRow + ttXlaUpdateDesc_t.tuple1;

See "ttXlaColDesc_t" for details on how to access the column data in a returned row.


ttXlaVersion_t

To permit future extensions to XLA, a version structure ttXlaVersion_t describes the current XLA version and structure byte order. This structure is returned by the ttXlaGetVersion function.

This structure has the following fields:

FieldTypeDescription
headerttXlaNodeHdr_t
Standard data header
hardwarechar(16)Name of hardware platform
wordSizeSQLUINTEGERNative word size (32 or 64)
TTMajorSQLUINTEGERTimesTen major version
TTMinorSQLUINTEGERTimesTen minor version
TTPatchSQLUINTEGERTimesTen point release number
OSchar(16)Name of operating system
OSMajorSQLUINTEGEROperating system major version
OSMinorSQLUINTEGEROperating system minor version


ttXlaTblDesc_t

Table information is portrayed through the ttXlaTblDesc_t structure. This structure is returned by the ttXlaGetTableInfo function.

This structure has the following fields:

FieldTypeDescription
headerttXlaNodeHdr_t
Standard data header
tblNamechar(31)Name of the table, null-terminated
tblOwnerchar(31)Owner of the table, null-terminated
sysTableIDSQLUBIGINTUnique system-defined table identifier
userTableIdSQLUBIGINTUser-defined table identifier
columnsSQLUINTEGERNumber of columns
widthSQLUINTEGERInline row size
nPrimColsSQLUINTEGERNumber of primary columns
primColsSysSQLUINTEGER(16)System primary key column numbers
primColsUserSQLUINTEGER(16)User-defined primary key column numbers

The inline row size includes space for all fixed-width columns, null column flags, and pointer information for variable-length columns. Each varying-length column occupies four bytes of inline row space.

Note the following if the table has a declared primary key:

  • The nPrimCols value is greater than 0.

  • The primColsSys array contains the column numbers of the primary key, in the same order in which they were originally declared with the CREATE TABLE statement.

  • The primColsUser array contains the corresponding application-specified column identifiers.


ttXlaTblVerDesc_t

This data structure contains the table version number and ttXlaTblDesc_t. It is returned by ttXlaVersionTableInfo. This structure has the following fields:

FieldTypeDescription
tblDescttXlaTblDesc_t
Table description
tblVerSQLBIGINTSystem-generated table version number


ttXlaColDesc_t

Column information is given through this structure, which is returned by the ttXlaGetColumnInfo function.

The structure has the following fields:

FieldTypeDescription
headerttXlaNodeHdr_t
Standard data header
colName [tt_NameLenMax]charName of the column
pad0SQLUINTEGERPad to four-byte boundary
sysColNumSQLUINTEGEROrdinal number of the column as determined when the table is created or subsequently altered

This is the same as the corresponding COLNUM value in SYS.COLUMNS. (See "SYS.COLUMNS" in Oracle TimesTen In-Memory Database System Tables and Views Reference.)

userColNumSQLUINTEGEROrdinal number of the column if optionally specified by the user

This is zero or a column number specified through the ttSetUserColumnID TimesTen built-in procedure. (See "ttSetUserColumnID" in Oracle TimesTen In-Memory Database Reference.)

dataTypeSQLUINTEGERStructure in ODBC TTXLA_* code

See "About XLA data types".

sizeSQLUINTEGERMaximum or basic size of column
offsetSQLUINTEGEROffset to fixed-length part of column
nullOffsetSQLUINTEGEROffset to null byte, or zero if not nullable
precisionSQLSMALLINTNumeric precision for decimal types
scaleSQLSMALLINTNumeric scale for decimal types
flagsSQLUINTEGERColumn flag:
  • TT_COLPRIMKEY: Column is primary key.

  • TT_COLVARYING: Column is stored out of line.

  • TT_COLNULLABLE: Column is nullable.

  • TT_COLUNIQUE: Column has a unique attribute defined on it.


The procedures for obtaining a ttXlaColDesc_t structure and inspecting its contents are described in "Inspecting column data". Below is a summary of these procedures.

The ttXlaColDesc_t structure is returned by the ttXlaGetColumnInfo function. This structure contains the metadata needed to access column information in a particular table. For example, you can use the offset field to locate specific column data in the row or rows returned in an update record after the ttXlaColDesc_t structure. By adding the offset to the address of a returned row, you can locate the address to the column value. You can then cast this value to the corresponding C types according to the dataType field, or pass it to one of the conversion routines described in "Converting complex data types".

TimesTen row data consists of fixed-length data followed by any variable-length data.

  • For fixed length column data, ttXlaColDesc_t returns the offset and size of the column data. The offset is relative to the beginning of the fixed part of the record. See Example 9-1 below.

  • For variable-length column data (VARCHAR2, NVARCHAR2, and VARBINARY), offset is an address that points to a four-byte offset value. By adding the offset address to the offset value, you can obtain the address of the column data in the variable-length portion of the row. The first n bytes at this location is the length of the data, followed by the actual data (where n is 4 on 32-bit platforms or 8 on 64-bit platforms). For variable-length data, the returned size value is the maximum allowable column size. See Example 9-1 below.

For columns that can have null values, nullOffset points to a null byte in the record. This value is 1 if the column is null, or 0 if it is not null. See "Detecting null values" for a discussion.

The flags bits define whether the column is nullable, part of a primary key, or stored out of line.

The sysColNum value is the system column number to assign to the column. This value begins with 1 for the first column.


Note:

LOB support in XLA is limited, as follows:
  • You can subscribe to tables containing LOB columns, but information about the LOB value itself is unavailable.

  • ttXlaGetColumnInfo returns information about LOB columns.

  • Columns containing LOBs are reported as empty (zero length) or null (if the value is actually NULL). In this way, you can tell the difference between a null column and a non-null column.


Example 9-1 Copying and printing a VARCHAR2 string

For fixed-length column data, the address of a column is the offset value in the ttXlaColDesc_t structure, plus the address of the row as follows:

ttXlaColDesc_t colDesc;

void* pColVal = colDesc->offset + row;

The value of the column can be obtained by dereferencing this pointer using a type pointer that corresponds to the data type. For example, for SQL_INTEGER, the ODBC type is SQLINTEGER and the value of the column can be obtained by the following:

*((SQLINTEGER*) pColVal))

In the case of variable-length column data, the pColVal calculated above is the address of a four-byte offset value. Adding this offset value to the address of pColVal provides a pointer to the beginning of the variable-length column data. Assuming the operation is performed on a 64-bit platform, the first eight bytes at this location is the length of this data (var_len), followed by the actual data (var_data).

In this example, a VARCHAR string is copied and printed.

tt_ptrint* var_len = (tt_ptrint*)((char*)pColVal +
                    *((int*)pColVal));
char* var_data = (char*)(var_len+1);
char* buffer = malloc(*var_len+1);
memcpy(buffer,var_data,*var_len);
buffer[*var_len] = (char)NULL; /* NULL terminate the string */
printf("%s\n",buffer);
free(buffer);

tt_LSN_t

Description of log record identifier used by bookmarks. This structure is used by the ttXlaUpdateDesc_t structure.

FieldTypeDescription
logFileSQLUBIGINTHigher order portion of log record identifier
logOffsetSQLUBIGINTLower order portion of log record identifier


Note:

The logFile and logOffset field names are retained for backward compatibility, although their usage has changed. In previous releases the values referred to LSNs, which increased sequentially, and the values had very specific meanings, indicating the log file number plus byte offset. Now they refer to log record identifiers, which are more abstract and do not have a direct relationship to the log file number and byte offset. All you can assume about a sequence of log record identifiers is that a log record identifier B read at a later time than a log record identifier A will have a higher value.


tt_XlaLsn_t

Description of a log record identifier used by bookmarks. This structure is returned by the ttXlaGetLSN function and used by the ttXlaSetLSN function.

The checksum is specific to an XLA handle to ensure that every log record identifier is related to a known XLA connection.

FieldTypeDescription
checksumSQLUINTEGERChecksum used to ensure that it is a valid log record identifier handle
xidSQLUSMALLINTTransaction ID
logFileSQLUBIGINTHigher order portion of log record identifier
logOffsetSQLUBIGINTLower order portion of log record identifier


Note:

The logFile and logOffset field names are retained for backward compatibility, although their usage has changed. In previous releases the values referred to LSNs, which increased sequentially, and the values had very specific meanings, indicating the log file number plus byte offset. Now they refer to log record identifiers, which are more abstract and do not have a direct relationship to the log file number and byte offset. All you can assume about a sequence of log record identifiers is that a log record identifier B read at a later time than a log record identifier A will have a higher value.

PKBOOPK:AOEBPS/odbc_supported.htm TimesTen ODBC Functions and Options

10 TimesTen ODBC Functions and Options

This chapter covers the topics noted below, listing ODBC functions supported by TimesTen and options supported by TimesTen for set and get functions for statements and connections. For complete function definitions, refer to ODBC API reference documentation.

TimesTen supports ODBC 2.5, Extension Level 1, as well as Extension Level 2 features that are documented in this chapter.

Supported ODBC functions

This section lists ODBC function supported by TimesTen, with special notes as applicable.

Table 10-1 Supported ODBC functions

FunctionNotes for TimesTen

SQLAllocConnect


SQLAllocEnv


SQLAllocStmt


SQLBindCol


SQLBindParameter

See "SQLBindParameter function".

SQLCancel

SQLCancel can cancel the following:

  • An operation running on an hstmt on another thread

  • An operation running on an hstmt that needs data

SQLCancel cannot cancel the following:

  • A global query

    SQLCancel can cancel only on the local node.

  • In Memory Database Cache or cache grid administrative operations

Do not call SQLCancel directly from a signal handler. Such code may not be portable.

SQLColAttributes and SQLColAttributesW

See "Column descriptor support for SQLColAttributes".

SQLColumns and SQLColumnsW


SQLConnect


SQLDataSources and SQLDataSourcesW

Available only to programs using a driver manager.

SQLDescribeCol and SQLDescribeColW


SQLDescribeParam


SQLDisconnect


SQLDriverConnect and SQLDriverConnectW


SQLDrivers and SQLDriversW

Available only to programs using a driver manager.

SQLError and SQLErrorW

Native error codes are TimesTen errors. You may receive generic errors such as, "Execution at Oracle failed. Oracle error code nnn."

SQLExecDirect

See the note for SQLExecute.

SQLExecute

TimesTen does not support asynchronous statement execution. (TimesTen does not support the SQL_ASYNC_ENABLE statement option, as noted later in this chapter.)

SQLFetch


SQLForeignKeys and SQLForeignKeysW


SQLFreeConnect


SQLFreeEnv


SQLFreeStmt


SQLGetConnectOption and SQLGetConnectOptionW

See "Option support for SQLSetConnectOption and SQLGetConnectOption".

SQLGetCursorName and SQLGetCursorNameW

You can set or get a cursor name but not reference it, such as in a WHERE CURRENT OF clause for a positioned update or delete. TimesTen does not support positioned update or delete statements.

SQLGetData

See "Avoid SQLGetData".

SQLGetFunctions


SQLGetInfo and SQLGetInfoW

See "Information type support for SQLGetInfo".

SQLGetStmtOption

See "Option support for SQLSetStmtOption and SQLGetStmtOption".

SQLGetTypeInfo and SQLGetTypeInfoW


SQLNativeSql and SQLNativeSqlW


SQLNumParams


SQLNumResultCols


SQLParamData


SQLParamOptions


SQLPrepare


SQLPrimaryKeys and SQLPrimaryKeysW


SQLProcedureColumns and SQLProcedureColumnsW


SQLProcedures and SQLProceduresW


SQLPutData


SQLRowCount

In addition to its standard functionality, this has special usage with cache groups. See "Managing cache groups".

SQLSetConnectOption and SQLSetConnectOptionW

See "Option support for SQLSetConnectOption and SQLGetConnectOption" under the next section.

SQLSetCursorName and SQLSetCursorNameW

You can set or get a cursor name but not reference it, such as in a WHERE CURRENT OF clause for a positioned update or delete.

SQLSetStmtOption

See "Option support for SQLSetStmtOption and SQLGetStmtOption".

SQLSetParam

This is an ODBC 1.0 function, replaced by SQLBindParameter in ODBC 2.0. Retained for backward compatibility.

SQLSpecialColumns and SQLSpecialColumnsW


SQLStatistics and SQLStatisticsW


SQLTables and SQLTablesW


SQLTransact




Note:

TimesTen supports only UTF-16 as a national character set.

Option support for ODBC connection and statement functions

This section discusses TimesTen option support for the ODBC functions SQLSetConnectOption, SQLGetConnectOption, SQLSetStmtOption, and SQLGetStmtOption.

Refer to ODBC API reference documentation for general information about these functions.

Option support for SQLSetConnectOption and SQLGetConnectOption

Table 10-2 and Table 10-3 document TimesTen support for standard and TimesTen-specific options for the ODBC SQLSetConnectOption and SQLGetConnectOption functions. These functions let you set connection options after the initial connection or retrieve those settings. Some of these correspond to connection attributes you can set during the connection process, as noted.

Also see "Option support for SQLSetStmtOption and SQLGetStmtOption". Those options can also be set using SQLSetConnectOption, in which case the value serves as a default for all statements on the connection.


Notes:

  • An option setting through SQLSetConnectOption or SQLSetStmtOption overrides the setting of the corresponding connection attribute (as applicable).

  • The documentation here also applies to SQLSetConnectOptionW and SQLGetConnectOptionW.


Table 10-2 Standard options: SQLSetConnectOption, SQLGetConnectOption

OptionSupport

SQL_ACCESS_MODE

No

SQL_AUTOCOMMIT

Yes

SQL_CURRENT_QUALIFIER

No

SQL_LOGIN_TIMEOUT

No

SQL_MAX_ROWS

Yes

SQL_NOSCAN

Yes

SQL_ODBC_CURSORS

Yes, for programs using a driver manager

SQL_OPT_TRACE

Yes, for programs using a driver manager

SQL_OPT_TRACEFILE

Yes, for programs using a driver manager

SQL_PACKET_SIZE

No

SQL_QUIET_MODE

No

SQL_TRANSLATE_DLL

No

SQL_TRANSLATE_OPTION

No

SQL_TXN_ISOLATION

Yes, if vParam is SQL_TXN_READ_COMMITTED or SQL_TXN_SERIALIZABLE

See "Prefetching multiple rows of data". Also see "Concurrency control through isolation and locking" in Oracle TimesTen In-Memory Database Operations Guide. Same functionality as the Isolation general connection attribute, as described in "Isolation" in Oracle TimesTen In-Memory Database Reference.


Table 10-3 TimesTen options: SQLSetConnectOption, SQLGetConnectOption

OptionComments

TT_CLIENT_TIMEOUT

This is for client/server only and has the same functionality as the TTC_Timeout TimesTen client connection attribute, as described in "TTC_Timeout" in Oracle TimesTen In-Memory Database Reference.

TT_DYNAMIC_LOAD_ENABLE

See "Dynamic load configuration" in Oracle In-Memory Database Cache User's Guide. This has the same functionality as the DynamicLoadEnable IMDB Cache general connection attribute described in "DynamicLoadEnable" in Oracle TimesTen In-Memory Database Reference.

TT_DYNAMIC_LOAD_ERROR_MODE

See "Return dynamic load errors" in Oracle In-Memory Database Cache User's Guide. This has the same functionality as the DynamicLoadErrorMode IMDB Cache connection attribute described in "DynamicLoadErrorMode" in Oracle TimesTen In-Memory Database Reference.

TT_NLS_LENGTH_SEMANTICS

See "Setting globalization options". This has the same functionality as the NLS_LENGTH_SEMANTICS general connection attribute described in "NLS_LENGTH_SEMANTICS" in Oracle TimesTen In-Memory Database Reference. There is also related information about the functionality in "Additional globalization features".

TT_NLS_NCHAR_CONV_EXCP

See "Setting globalization options". This has the same functionality as the NLS_NCHAR_CONV_EXCP general connection attribute described in "NLS_NCHAR_CONV_EXCP" in Oracle TimesTen In-Memory Database Reference. There is also related information about the functionality in "Additional globalization features".

TT_NLS_SORT

See "Setting globalization options". This has the same functionality as the NLS_SORT general connection attribute described in "NLS_SORT" in Oracle TimesTen In-Memory Database Reference. There is also related information about the functionality in "Additional globalization features".

TT_PREFETCH_CLOSE

See "Enable TT_PREFETCH_CLOSE for Serializable transactions" in Oracle TimesTen In-Memory Database Operations Guide.

TT_REGISTER_FAILOVER_CALLBACK

See "Using automatic client failover in your application".

TT_REPLICATION_TRACK

See "Features for use with replication". This has the same functionality as the ReplicationTrack general connection attribute, to specify a track number for the connection in user-defined parallel replication.


Option support for SQLSetStmtOption and SQLGetStmtOption

Table 10-4 and Table 10-5 document TimesTen support for standard and TimesTen-specific options for the ODBC SQLSetStmtOption and SQLGetStmtOption functions, which let you set or retrieve statement option settings.

To set an option default value for all statements associated with a connection, use SQLSetConnectOption.


Notes:

An option setting through SQLSetConnectOption or SQLSetStmtOption overrides the setting of the corresponding connection attribute (as applicable).

Table 10-4 Standard options: SQLSetStmtOption, SQLGetStmtOption

OptionSupport

SQL_ASYNC_ENABLE

No

SQL_BIND_TYPE

No

SQL_CONCURRENCY

No

SQL_CURSOR_TYPE

No

SQL_KEYSET_SIZE

No

SQL_MAX_LENGTH

No

SQL_MAX_LENGTH can be set, but any specified value will be overridden with 0 (return all available data).

SQL_MAX_ROWS

Yes

SQL_NOSCAN

Yes

SQL_QUERY_TIMEOUT

Yes

See "Setting a timeout or threshold for executing SQL statements".

SQL_RETRIEVE_DATA

No

SQL_ROWSET_SIZE

No

SQL_SIMULATE_CURSOR

No

SQL_USE_BOOKMARKS

No


Table 10-5 TimesTen options: SQLSetStmtOption, SQLGetStmtOption

OptionComment

TT_PREFETCH_COUNT

See "Prefetching multiple rows of data".

TT_QUERY_THRESHOLD

See "Setting a threshold duration for SQL statements". This is to specify a time threshold for SQL statements, in seconds, after which TimesTen will write a warning to the support log and throw an SNMP trap.

TT_PRIVATE_COMMANDS

Commands are not shared with any other connection. See "PrivateCommands" in Oracle TimesTen In-Memory Database Reference.

TT_STMT_PASSTHROUGH_TYPE

Determines whether a specific prepared statement will be passed through to Oracle by the passthrough feature of IMDB Cache. The value returned by SQLGetStmtOption can be either TT_STMT_PASSTHROUGH_NONE or TT_STMT_PASSTHROUGH_ORACLE.

Note: In TimesTen, this option is supported only with SQLGetStmtOption.

See "Determining passthrough status". Also see "Setting a passthrough level" in Oracle In-Memory Database Cache User's Guide.


Information type support for SQLGetInfo

This section covers standard and TimesTen-specific information types supported by TimesTen for the ODBC function SQLGetInfo.

Refer to ODBC API reference documentation for general information about this function and standard information types.

TimesTen supports the following standard ODBC 2.x information types (in alphabetical order):

 SQL_ACCESSIBLE_PROCEDURES, SQL_ACCESSIBLE_TABLES, SQL_ACTIVE_CONNECTIONS,
 SQL_ACTIVE_STATEMENTS, SQL_ALTER_TABLE, SQL_BOOKMARK_PERSISTENCE,
 SQL_COLUMN_ALIAS, SQL_CONCAT_NULL_BEHAVIOR, SQL_CONVERT_BIGINT,
 SQL_CONVERT_BINARY, SQL_CONVERT_BIT, SQL_CONVERT_CHAR, SQL_CONVERT_DATE,
 SQL_CONVERT_DECIMAL, SQL_CONVERT_DOUBLE, SQL_CONVERT_FLOAT,
 SQL_CONVERT_FUNCTIONS, SQL_CONVERT_INTEGER, SQL_CONVERT_LONGVARBINARY,
 SQL_CONVERT_LONGVARCHAR, SQL_CONVERT_NUMERIC, SQL_CONVERT_REAL,
 SQL_CONVERT_SMALLINT, SQL_CONVERT_TIME, SQL_CONVERT_TIMESTAMP,
 SQL_CONVERT_TINYINT, SQL_CONVERT_VARBINARY, SQL_CONVERT_VARCHAR,
 SQL_CONVERT_WVARCHAR, SQL_CORRELATION_NAME, SQL_CURSOR_COMMIT_BEHAVIOR,
 SQL_CURSOR_ROLLBACK_BEHAVIOR, SQL_DATA_SOURCE_NAME, SQL_DATA_SOURCE_READ_ONLY,
 SQL_DATABASE_NAME, SQL_DBMS_NAME, SQL_DBMS_VER, SQL_DEFAULT_TXN_ISOLATION,
 SQL_DRIVER_HDBC, SQL_DRIVER_HENV, SQL_DRIVER_HLIB, SQL_DRIVER_HSTMT,
 SQL_DRIVER_NAME, SQL_DRIVER_ODBC_VER, SQL_DRIVER_VER, SQL_EXPRESSIONS_IN_ORDERBY,
 SQL_FETCH_DIRECTION, SQL_FILE_USAGE, SQL_GETDATA_EXTENSIONS, SQL_GROUP_BY,
 SQL_IDENTIFIER_CASE, SQL_IDENTIFIER_QUOTE_CHAR, SQL_KEYWORDS,
 SQL_LIKE_ESCAPE_CLAUSE, SQL_LOCK_TYPES, SQL_MAX_BINARY_LITERAL_LEN,
 SQL_MAX_CHAR_LITERAL_LEN, SQL_MAX_COLUMN_NAME_LEN, SQL_MAX_COLUMNS_IN_GROUP_BY,
 SQL_MAX_COLUMNS_IN_INDEX, SQL_MAX_COLUMNS_IN_ORDER_BY, SQL_MAX_COLUMNS_IN_SELECT,
 SQL_MAX_COLUMNS_IN_TABLE, SQL_MAX_CURSOR_NAME_LEN, SQL_MAX_INDEX_SIZE,
 SQL_MAX_OWNER_NAME_LEN, SQL_MAX_PROCEDURE_NAME_LEN, SQL_MAX_QUALIFIER_NAME_LEN,
 SQL_MAX_ROW_SIZE, SQL_MAX_ROW_SIZE_INCLUDES_LONG, SQL_MAX_STATEMENT_LEN,
 SQL_MAX_TABLE_NAME_LEN, SQL_MAX_TABLES_IN_SELECT, SQL_MAX_USER_NAME_LEN,
 SQL_MULT_RESULT_SETS, SQL_MULTIPLE_ACTIVE_TXN, SQL_NEED_LONG_DATA_LEN,
 SQL_NON_NULLABLE_COLUMNS, SQL_NULL_COLLATION, SQL_NUMERIC_FUNCTIONS,
 SQL_ODBC_API_CONFORMANCE, SQL_ODBC_SAG_CLI_CONFORMANCE, SQL_ODBC_SQL_CONFORMANCE,
 SQL_ODBC_SQL_OPT_IEF, SQL_ODBC_VER, SQL_OJ_CAPABILITIES,
 SQL_ORDER_BY_COLUMNS_IN_SELECT, SQL_OUTER_JOINS, SQL_OWNER_TERM, SQL_OWNER_USAGE,
 SQL_POS_OPERATIONS, SQL_POSITIONED_STATEMENTS, SQL_PROCEDURE_TERM,
 SQL_PROCEDURES, SQL_QUALIFIER_LOCATION, SQL_QUALIFIER_NAME_SEPARATOR,
 SQL_QUALIFIER_TERM, SQL_QUALIFIER_USAGE, SQL_QUOTED_IDENTIFIER_CASE,
 SQL_ROW_UPDATES, SQL_SCROLL_CONCURRENCY, SQL_SCROLL_OPTIONS,
 SQL_SEARCH_PATTERN_ESCAPE, SQL_SERVER_NAME, SQL_SPECIAL_CHARACTERS,
 SQL_STATIC_SENSITIVITY, SQL_STRING_FUNCTIONS, SQL_SUBQUERIES,
 SQL_SYSTEM_FUNCTIONS, SQL_TABLE_TERM, SQL_TIMEDATE_ADD_INTERVALS,
 SQL_TIMEDATE_DIFF_INTERVALS, SQL_TIMEDATE_FUNCTIONS, SQL_TXN_CAPABLE,
 SQL_TXN_ISOLATION_OPTION, SQL_UNION, SQL_USER_NAME

Note:

SQL_DRIVER_HLIB is supported with a driver manager only.

TimesTen supports the following standard ODBC 3.x information types:

 SQL_AGGREGATE_FUNCTIONS, SQL_CONVERT_WCHAR, SQL_CONVERT_WLONGVARCHAR,
 SQL_CREATE_VIEW, SQL_DATETIME_LITERALS, SQL_DROP_VIEW,
 SQL_SQL92_RELATIONAL_JOIN_OPERATORS, SQL_SQL92_VALUE_EXPRESSIONS

Table 10-6 describes TimesTen-specific information types.

Table 10-6 TimesTen information items: SQLGetInfo

Information typeData typeDescription

TT_DATA_STORE_INVALID

SQLINTEGER

Returns 1 if the database is in invalid state, such as due to a system or application failure, or 0 if not.

Note: Fatal errors, such as error 846 or 994, invalidate a TimesTen database, causing this item to be set to 1.

TT_DATABASE_CHARACTER_SET

SQLCHAR

Returns the name of the database character set.

TT_DATABASE_CHARACTER_SET_SIZE

SQLINTEGER

Returns the maximum size of a character in the database character set, in bytes.

TT_DATABASE_TYPE_MODE

SQLINTEGER

Returns 0 for Oracle type mode (typical and default setting), or 1 for TimesTen type mode (legacy setting).

Note: The type mode can be specified through the TypeMode connection attribute.

TT_PLATFORM_INFO

Bit mask

Returns a bit mask indicating platform information. Bit 0 has the value 1 for a 64-bit platform, or the value 0 for a 32-bit platform. Bit 1 has the value 1 for big-endian, or the value 0 for little-endian.

TT_REPLICATION_INVALID

SQLINTEGER

Returns 1 if replication is in a failed state, or 0 if not.


Column descriptor support for SQLColAttributes

This section covers TimesTen-specific column descriptor information supported for the ODBC function SQLColAttributes.

Refer to ODBC API reference documentation for general information about this function and standard information types.

Table 10-7 describes TimesTen-specific column descriptors.

Table 10-7 TimesTen column descriptors: SQLColAttributes

DescriptorComment/description

TT_COLUMN_INLINE

Returns TRUE for columns with inline data, or FALSE otherwise. This is returned in the SQLColAttributes pfDesc parameter.

TT_COLUMN_LENGTH_SEMANTICS

For character-type columns, this returns "BYTE" for columns with byte length semantics and "CHAR" for columns with character length semantics. For non-character columns, it returns "". The information is returned in the SQLColAttributes rgbDesc parameter.

This information refers to whether data length is measured in bytes or characters. Length semantics in TimesTen are the same as in Oracle Database. See "Length Semantics" in Oracle Database Globalization Support Guide for additional information.


PK咗PK :Aoa,mimetypePK:A`@Ib]:iTunesMetadata.plistPK:AYuMETA-INF/container.xmlPK:A"t\i OEBPS/oci.htmPK:A[pTOˋOEBPS/cover.htmPK:A\OEBPS/whatsnew.htmPK:AzIL>G>8OEBPS/compiling.htmPK:A(H>>OEBPS/xla_event.htmPK:A ÊOEBPS/title.htmPK:Aw;D=)/OEBPS/c_ref.htmPK:A&K1 1 OEBPS/preface.htmPK:A0 `vYOEBPS/index.htmPK:A^l,g,OEBPS/img/reset_bookmark.gifPK:A,OEBPS/img/transaction_log.gifPK:A/| /OEBPS/img/odbc_diagram.gifPK:A'@OEBPS/img/xla_char.gifPK:A=71H,C,,^OEBPS/img/update_records.gifPK:ALe>`>OEBPS/img/xla_record.gifPK:A%aKKiOEBPS/img/xla_coldesc.gifPK:AnťF OEBPS/img/maxrecords.gifPK:AOa$$1 OEBPS/img/dtp.gifPK:AcP<-( OEBPS/img/current_read_lsn.gifPK:Ac''# OEBPS/img/records_retrieved.gifPK:A߇V++K OEBPS/img/xla_varchar.gifPK:Ar}4-,!w OEBPS/img/xla_record_row_addr.gifPK:A|moj OEBPS/img_text/dtp.htmPK:A\{# OEBPS/img_text/current_read_lsn.htmPK:A " OEBPS/img_text/transaction_log.htmPK:Aek۳ OEBPS/img_text/odbc_diagram.htmPK:ApCO! OEBPS/img_text/reset_bookmark.htmPK:A( OEBPS/img_text/xla_varchar.htmPK:A{  OEBPS/img_text/maxrecords.htmPK:AME{& OEBPS/img_text/xla_record_row_addr.htmPK:AN=$ OEBPS/img_text/records_retrieved.htmPK:Aݎoj. OEBPS/img_text/xla_record.htmPK:AWR OEBPS/img_text/xla_char.htmPK:AՕ! OEBPS/img_text/update_records.htmPK:A l OEBPS/img_text/xla_coldesc.htmPK:Ate OEBPS/pro_c.htmPK:AqN y OEBPS/toc.ncxPK:A.&A/.\ OEBPS/tuning.htmPK:A!''8 OEBPS/content.opfPK:A_ ` OEBPS/dcommon/prodbig.gifPK:AY@ f OEBPS/dcommon/doclib.gifPK:A 9wwDh OEBPS/dcommon/oracle-logo.jpgPK:Ar OEBPS/dcommon/contbig.gifPK:A] OEBPS/dcommon/darbbook.cssPK:AMά""! OEBPS/dcommon/O_signature_clr.JPGPK:APz  OEBPS/dcommon/feedbck2.gifPK:A-- OEBPS/dcommon/feedback.gifPK:Aː5B OEBPS/dcommon/booklist.gifPK:AN61 OEBPS/dcommon/cpyr.htmPK:A!:3.& OEBPS/dcommon/masterix.gifPK:AeӺ1,' OEBPS/dcommon/doccd.cssPK:A7 * OEBPS/dcommon/larrow.gifPK:A#7, OEBPS/dcommon/indxicon.gifPK:AS'". OEBPS/dcommon/leftnav.gifPK:Ahu,0 OEBPS/dcommon/uarrow.gifPK:Al-OJ+3 OEBPS/dcommon/oracle.gifPK:A(; OEBPS/dcommon/index.gifPK:AGC = OEBPS/dcommon/bookbig.gifPK:AJV^&G OEBPS/dcommon/rarrow.gifPK:A枰pkAI OEBPS/dcommon/mix.gifPK:Ao"nR M K OEBPS/dcommon/doccd_epub.jsPK:Av I V OEBPS/dcommon/toc.gifPK:A r~$W OEBPS/dcommon/topnav.gifPK:A1FAFY OEBPS/dcommon/prodicon.gifPK:A3( # \ OEBPS/dcommon/bp_layout.cssPK:Ax[?:Ej OEBPS/dcommon/bookicon.gifPK:Ap*c^o OEBPS/dcommon/conticon.gifPK:Aʍws OEBPS/dcommon/blafdoc.cssPK:A+&v OEBPS/dcommon/rightnav.gifPK:Aje88 OEBPS/dcommon/oracle-small.JPGPK:Aއ{&!* OEBPS/dcommon/help.gifPK:A\ʚ\mWm OEBPS/toc.htmPK:Aք+4OEBPS/xa_dtp.htmPK:A[[bOEBPS/writing_app.htmPK:ABOOh"OEBPS/xla_ref.htmPK:A咗rOEBPS/odbc_supported.htmPKOO7