Was this helpful?
GUID/UUID Columns
The ODBC Driver supports SQL_C_GUID and SQL_GUID data types for the following DBMS data types:
uuid
character data types char, varchar, nchar, and nvarchar
binary and varbinary
The ODBC data type called GUID for "Globally Unique Identifier" is mapped to the DBMS data type of UUID for "Universally Unique Identifier". They are roughly equivalent. They have the same display format and the same internal binary length.
The display format is 36 characters long:
xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx
where x's are alphanumeric (0-9, a-f) hex representations of the internal fields within the GUID.
The internal format is 16 bytes of binary values, consisting of a few integer type fields followed by a binary array of 8 bytes. The ODBC SQLGUID structure defines the integer and binary fields within this structure.
There is a subtle difference in the internal format for ODBC GUID versus DBMS UUID. The ODBC GUID (structure SQLGUID) contains 3 integer fields at the beginning which are in platform-endianness format, whereas the DBMS UUID internal format exposed to applications is simply a 16-byte binary object and the 3 integer fields are always in big-endian format regardless of the platform.
For ODBC applications that wish to access the internal format, it is recommended to use the ODBC SQLGUID structure and map the C type to SQL_C_GUID. This will provide consistent results across different DBMS's. This pertains to both sending parameters for a query as well as selecting results. The SQL (DBMS) data type in general would be SQL_GUID, which is an Ingres or Vector column defined as UUID.
The GUID/UUID data type can also be handled in the display format. A conversion is done between the internal and display formats when the C and the SQL data types are different; specifically, if one is a character data type and the other is the GUID or UUID data type. For example, if a DBMS character column contains a valid UUID display format string, it can be selected into a SQL_C_GUID data type in the application. Conversely, an application with a SQL_C_CHAR data type containing a GUID display format string can be sent to the DBMS to update a UUID column, by binding the SQL type to SQL_GUID.
The default C type for a SQL type of SQL_GUID (that is, UUID in the database) is SQL_C_GUID.
In the rare case that the raw binary value of the DBMS internal format of a UUID column is desired, then the column (or parameter) should be bound to a C type of SQL_C_BINARY. This will copy the internal DBMS value, without accounting for platform endianness.
Note:  JDBC does not have a GUID or UUID data type, so it is handled as a single 16-byte binary object by the Actian JDBC driver; the value is the DBMS format (big endian for the 1st 3 fields in the structure). Hence, the Actian JDBC driver returns the same as an ODBC application that uses the BINARY binding, but is different from the ODBC SQL_C_GUID binding.
Conversions to or from GUID/UUID and other data types besides the above are not supported and will result in a conversion error. For example, a DBMS UUID column cannot be selected into a C date or integer data type.
Metadata (Catalog) Queries
Sometimes an ODBC application needs to know information about items in the database, such as tables, permissions, primary keys, and so on. The ODBC Driver supports all ODBC functions pertaining to this information. The following table summarizes the functions available:
Function
Description
SQLColumns
Column names in tables
SQLColumnPrivileges
Privileges of columns in tables
SQLForeignKeys
Foreign keys for a table
SQLPrimaryKeys
Column names of primary keys in a table
SQLTables
Table names in a database
SQLTablePrivileges
Privileges of tables in a database
SQLProcedures
Procedure names in a database
SQLProcedureColumns
Input and output names of a database procedure
SQLSpecialColumns
Columns that uniquely identify a row
SQLStatistics
Statistics and indexes associates with a table
Error Reporting
All ODBC functions return an error code. Both the ODBC Driver and the Driver Manager cache a list of any errors encountered. The list of errors is deleted when the next ODBC function is called.
A return of SQL_SUCCESS means that the function completed successfully. A return of SQL_ERROR means that an error occurred. A return of SQL_SUCCESS_WITH_INFO can be considered a warning or informational status code. SQL_INVALID_HANDLE means that the handle passed to the function was invalid.
More information on a status of SQL_ERROR or SQL_SUCCESS_WITH_INFO can be retrieved from the SQLGetDiagRec() function. The following example code snippet returns error information on a call to SQLConnect().
Example: SQLGetDiagRec() Function
RETCODE rc = SQL_SUCCESS;
SQLHDBC hdbc;
SQLCHAR buffer[SQL_MAX_MESSAGE_LENGTH + 1 ];
SQLCHAR sqlstate[SQL_SQLSTATE_SIZE + 1 ];
SQLINTEGER sqlcode;
SQLSMALLINT length;
SQLSMALLINT i;
 
rc = SQLConnect(hdbc,
    "myDSN",
    SQL_NTS,
    "ingres",
    SQL_NTS,
    "ingPWD",
    SQL_NTS );
 
if (rc == SQL_ERROR)
{
    i = 1;
    while ( SQLGetDiagRec( htype,
                           hndl,
                           i,
                           sqlstate,
                           &sqlcode,
                           buffer,
                           SQL_MAX_MESSAGE_LENGTH + 1,
                           &length ) == SQL_SUCCESS )
    {
        printf( "SQLSTATE: %s\n", sqlstate ) ;
        printf( "Native Error Code: %ld\n", sqlcode ) ;
        printf( "buffer: %s \n", buffer ) ;
        i++ ;
    }
If ingPWD was an invalid password, the following errors would be displayed from the above code:
SQLSTATE: 08004
Native Error Code: 786443
buffer: [Ingres][Ingres 2006 ODBC Driver][Ingres 2006]Login failure: invalid username/password.
SQLSTATE: 08S01
Native Error Code: 13172737
buffer: [Ingres][Ingres 2006 ODBC Driver][Ingres 2006]The connection to the server has been aborted.
The SQLSTATE reference is specific to ODBC and does not correlate to SQLSTATE in Ingres. The Native Error Code is an Ingres error code, viewable from the errhelp utility:
> %II_SYSTEM%\ingres\sig\errhelp\errhelp 786443
(786443)
<12>000b Login failure: invalid username/password.
Termination and Clean-up
An ODBC application can simply terminate after executing its queries, but this is considered poor programming practice. The DBMS server cannot distinguish between a program that exited without cleaning up and a program that aborted due to a serious error. As a result, spurious errors are reported in the error log.
To disconnect gracefully from the database, call SQLDisconnect():
rc = SQLDisconnect( hdbc ); /* Disconnect */
The ODBC function SQLFreeStmt() is used to close a cursor or free all resources associated with a statement handle:
rc = SQLFreeStmt( hstmt, SQL_CLOSE ); /* Close a cursor or query */
rc = SQLFreeStmt( hstmt, SQL_DROP ); /* Free all resources */
A call to SQLFreeStmt() with an argument of SQL_DROP implicitly closes the cursor before freeing resources.
The generic SQLFreeHandle() function can be used with all types of handles:
rc = SQLFreeHandle ( SQL_HANDLE_STMT, hstmt );
rc = SQLFreeHandle ( SQL_HANDLE_DBC, hdbc );
rc = SQLFreeEnv ( SQL_HANDLE_ENV, henv );
A call to SQLFreeHandle() with a handle type argument of SQL_HANDLE_STMT is the equivalent of calling SQLFreeStmt() with an argument of SQL_DROP.
Once a handle has been freed, the corresponding allocate function must be re-invoked to initialize resources associated with the handle.
ODBC CLI Connection Pooling
ODBC connection pooling is a method of sharing active database connections with similar or identical connection characteristics. When a connection is released through a call to SQLDisconnect(), the connection is left open and added to a pool of active connections.
When an ODBC application opens a new connection, the application searches the pool for a connection with matching connection characteristics. If a match is found, the connection from the pool is used "under the covers" instead of creating a new connection. If a match is not found, a new connection is opened.
ODBC connection pooling can improve performance significantly because an ODBC application can take a long time to connect relative to the time it takes to process data.
ODBC pooled connections can be shared with single or multi-threaded ODBC applications, but are not shared between separate ODBC applications.
Note:  In Windows environments, connection pooling is provided by the Windows Driver Manager rather than the Ingres ODBC CLI.
ODBC Connection Pools: Per Driver and Per Environment
ODBC connection pooling is activated by invoking SQLSetEnvAttr() with the attribute SQL_ATTR_CONNECTION_POOLING, and with the directives SQL_CP_ONE_PER_DRIVER or SQL_CP_ONE_PER_HENV.
Example: SQL_ATTR_CONNECTION_POOLING Attribute
rc = SQLSetEnvAttr( NULL, SQL_ATTR_CONNECTION_POOLING,")
(SQLPOINTER)SQL_CP_ONE_PER_DRIVER, SQL_IS_INTEGER);
SQL_CP_ONE_PER_DRIVER means that there is only one connection pool for the entire ODBC application, regardless of the number of connections. If only one environment handle is allocated, SQL_CP_ONE_PER_DRIVER is essentially the same as SQL_CP_ONE_PER_HENV.
If multiple environment handles are allocated, it may make more sense to specify SQL_CP_ONE_PER_HENV, especially if the connections associated with each environment have similar characteristics. This directive will create multiple pools, each with a smaller number of connections to search through.
ODBC Connection Pool Match Criteria: Strict and Relaxed
The SQLSetEnvAttr() function allows the ODBC application to specify match criteria for objects in the connection pool.
Connection objects with "strict" criteria must have identical connection specifiers for connection attributes specified in the connection string from SQLDriverConnect(). "Strict" is the only option supported, and other specifications are ignored.
Example: Strict Match Criterion
rc = SQLSetEnvAttr(henv, SQL_ATTR_CP_MATCH, (SQLPOINTER)
SQL_CP_STRICT_MATCH, SQL_IS_INTEGER);
"Relaxed" match criteria do not apply to SQLDriverConnect() in the Ingres ODBC CLI. If a relaxed match criterion is specified, only key connection attributes must match. For the ODBC CLI, the following minimum attributes must match, if specified:
DATABASE
SERVER_TYPE
SERVER
DRIVER
GROUP
ROLENAME
ROLEPWD
DBMS_PWD
The following connection string attributes are ignored for relaxed match criteria:
BLANKDATE
DATE1582
CATCONNECT
SELECTLOOPS
NUMERIC_OVERFLOW
CATSCHEMANULL
ODBC Connection Pool Timeout
ODBC pooled connections can be configured to time out to prevent an unmanageable number of connections in the pool.
By default, the Ingres ODBC CLI allows connections to remain in the pool as long as the ODBC application is active. You can override the default connection pool timeout value using the Ingres ODBC Administrator (iiodbcadmin) on Linux.
To change the connection pool timeout value on Linux
1. Start the Ingres ODBC Administrator by issuing the iiodbcadmin command.
2. At the utility menu, choose Drivers, Configuration Options.
The Configuration screen appears.
3. Enter a value in the edit box from 1 to 2,147,483,647, which represents the number of seconds that unused connections remain in the pool.
The default value is -1, which means that pooled connection objects never time out. When a connection object times out, it is disconnected from the database and deleted from the pool.
Note:  A thread in the ODBC CLI manages connection pool timeouts. If the time out value is left at -1, the thread is never started. For performance reasons, it is better to leave the timeout value at -1 rather than specifying a large value.
Last modified date: 03/21/2024