|
The Eloquence ODBC (Open Data Base
Connectivity) DLL enables Eloquence programs to interface
with external database systems such as Oracle, Microsoft SQL Server
or MySQL through the ODBC API on HP-UX, Linux and Windows platforms.
Prerequisites
The Eloquence Odbc.DLL requires the following components to be
installed:
-
An ODBC Driver Manager
This is a component which manages available ODBC data
sources on a particular system.
On Windows, this is typically part of the operating system or installed
with applications like Microsoft Office or the Microsoft SQL Server.
Data sources are managed with the ODBC Data Sources applet in the Windows
Control Panel. The Windows ODBC components (driver manager and commonly
used ODBC driver for Microsoft Access etc.) are available for download at
http://www.microsoft.com/data/.
On HP-UX and Linux, both the unixODBC and the iODBC open source ODBC driver managers are supported.
Newer versions of unixODBC are recommended to be used preferably.
The Eloquence Odbc.DLL on HP-UX and Linux expects to find the libodbc
shared library (HP-UX: libodbc.sl.1, Linux: libodbc.so.1).
If the library cannot be found because the unixODBC is installed in
a nonstandard location, either the LD_LIBRARY_PATH environment variable may
be set (for example LD_LIBRARY_PATH=/opt/unixODBC/lib) or a symbolic
link may be created in /usr/lib to refer to the libodbc shared
library. On Linux, ldconfig may be used to add the unixODBC
lib directory to the dynamic linker's search path (see man ldconfig).
-
An appropriate ODBC driver
This is a database-specific component which interfaces the particular
database you intend to use.
Examples for ODBC drivers are:
- SQL/R ODBC from Marxmeier Software to access
Eloquence databases
- Microsoft MDAC
to use Microsoft Access, FoxPro and SQL Server databases on Windows,
typically installed with applications like Microsoft Office or the
Microsoft SQL Server
- FreeTDS
on HP-UX and Linux to access SQL Server and Sybase databases
running on Windows
Drivers for other databases are either included with the particular database
product or available as an option.
Before ODBC can be used, the appropriate
data source(s) must be defined.
A data source definition specifies:
-
the name of the data source (DSN: data source name)
-
which driver is used
-
which database is used (some drivers such as SQL/R ODBC allow to
combine multiple databases into a single data source)
-
possibly some authentication information necessary to gain access
to the database(s)
-
for client/server databases possibly the name of the remote system where
the database server is operated
Except for the name of the data source and the driver these parameters
depend on the requirements of the particular database and must be correctly
specified according to the database vendor's documentation.
After appropriate configuration, the data source(s) can be accessed with the
DSN (data source name) as shown in the examples below.
On Windows, the ODBC Data Sources applet in the Windows Control Panel is
used for data source administration. It supports three different types of
data sources:
-
A System data source is stored in the machine-specific
area of the Windows Registry and therefore visible to all users.
You need administrator privileges to configure System data sources.
-
A User data source is stored in the user-specific area of the Windows
Registry and therefore only visible to the logged-on user.
-
A File data source is stored in a .dsn file located the file system, for
example at C:\Program Files\Common Files\ODBC\Data Sources.
The Eloquence Odbc.DLL supports System and User data sources.
File data sources cannot be used.
On HP-UX or Linux, the unixODBC driver manager uses two configuration
files which are typically located either in the /etc or in the /etc/unixODBC
or in the /etc/opt/unixODBC directory:
-
odbcinst.ini
This configures the installed ODBC drivers. A driver's section starts with
the driver name in square brackets, followed by a description and the location
of the driver and setup shared libraries. The setup shared library is used
with the unixODBC configuration GUI (if not supported by a driver,
a default setup library can be used, as in the SQL/R example below). The
FileUsage entry is used with the configuration GUI and should be set to 1.
For example:
[MySQL]
Description = MySQL ODBC Driver
Driver = /usr/lib/libmyodbc.so
Setup = /usr/lib/libodbcmyS.so
FileUsage = 1
[PostgreSQL]
Description = PostgreSQL ODBC Driver
Driver = /usr/lib/libodbcpsql.so
Setup = /usr/lib/libodbcpsqlS.so
FileUsage = 1
[SQL/R]
Description = SQL/R ODBC Driver
Driver = /opt/sqlr2/lib/libsqlrodbc.so
Setup = /usr/lib/libodbcdrvcfg1S.so
FileUsage = 1
-
odbc.ini
This configures the available data sources. A data source section starts with
the DSN in square brackets, followed by a description and a reference to the
associated driver configured in the odbcinst.ini file. Driver
specific entries may be added as in the example below (please refer to the
database vendor's documentation).
The unixODBC driver manager first tries to locate a data source in a
file named .odbc.ini in the current user's home directory (similar
to the User data source concept on Windows). If this file
does not exist or does not contain the specified data source, the global
odbc.ini is searched (similar to the System data source
concept on Windows).
Please note: Early unixODBC versions before 2.2 (a) created
an empty .odbc.ini file in the current user's home directory if it
did not yet exist and then (b) did not fallback to the global odbc.ini
file. The result was that a data source could not be accessed even if it
was configured correctly. To solve this issue, either configure any data
sources in the user's .odbc.ini file or create a symbolic link
named .odbc.ini in the current user's home directory to refer to
the global odbc.ini file.
For example:
[MySQL-test]
Description = A data source to test the MySQL ODBC driver
Driver = MySQL
Trace = Off
TraceFile = /tmp/mysql-trace.log
DATABASE = sample
SERVER = 192.168.44.55
USER = jdoe
PASSWORD =
PORT = 3306
[PostgreSQL-test]
Description = A data source to test the PostgreSQL ODBC driver
Driver = PostgreSQL
Trace = Off
TraceFile = /tmp/postgresql-trace.log
Database = sample
Servername = 192.168.44.66
UserName = jdoe
Password =
Port = 5432
Protocol = 6.4
ReadOnly = No
RowVersioning = No
ShowSystemTables = No
ShowOidColumn = No
FakeOidIndex = No
ConnSettings =
[SQL/R-test]
Description = A data source to test the SQL/R ODBC driver
Driver = SQL/R
Server = 192.168.44.77
Service = 8003
User = public
Quoting = 0
Bulkfetch = 1
Please note: The SQL/R ODBC driver expects to find the data source
either in the user's .odbc.ini file or in /etc/odbc.ini,
otherwise it does not honor the Server, Service, User, Quoting or
Bulkfetch options. If the global odbc.ini file is not located
in /etc you could either symlink it to /etc/odbc.ini or set the
ODBCINI environment variable, for example:
ODBCINI=/etc/unixODBC/odbc.ini.
Using the Odbc.DLL
The Odbc.DLL must be loaded before it can be used in a program:
LOAD DLL Odbc,1024
This loads the Odbc.DLL from its default location and establishes
a communication buffer of 1024 bytes.
For details about the Eloquence LOAD DLL statement please refer to the
Eloquence documentation.
The DEL DLL statement may be used to unload the DLL:
DEL DLL Odbc
The following procedures are available to return information
on the Odbc.DLL or enable logging.
- CALL DLL Odbc("Revision",Buf$)
This call returns the revision of the Odbc.DLL in Buf$.
- CALL DLL Odbc("LogFile","odbcdll.log")
This call enables logging of debug messages to the specified file.
- CALL DLL Odbc("LogFlags",LogFlags$)
This call enables logging of debug messages as specified by
LogFlags. Currently, LogFlags "*1" for additional information
on failure and "*2" for debug messages are available.
ODBC connections and statements
- CALL DLL Odbc("Connect",Conn_spec$,Conn_id)
Establishes a connection to a data source.
The syntax of the connection string depends upon which ODBC driver you
use. Commonly, a data source name will be specified by means of the
DSN= token; for example DSN=MY_DATA_SOURCE.
Ordinarily, a data source will have been configured earlier.
As an example, on HP-UX and Linux systems, the unixODBC driver manager
uses an odbc.ini file where all available data sources are
listed. On MS Windows systems, data sources are normally configured
by means of the ODBC Administrator utility (the ODBC Data Sources
applet in the control panel).
The Connect call returns a connection id in Conn_id that is used
to identify the connection in subsequent calls.
- CALL DLL Odbc("GetConnection",Conn_id,Conn_spec$)
Calling this procedure returns the complete connection specification
in Conn_spec$ as used by the driver manager.
- CALL DLL Odbc("Disconnect",Conn_id)
Calling this procedure closes the specified connection.
Any remaining statements which refer to this connection will be usable
but once they are deleted, no new statements can use this
connection.
- CALL DLL Odbc("SetConnectOption",Conn_id,Option,Param[$])
Calling this procedure specifies an option for the connection.
Option is a numeric value that specifies the option, Param or
Param$ specifies the value for the option.
The supported options are driver specific. The following options
are defined by the ODBC standard:
101 | ACCESS_MODE |
102 | AUTOCOMMIT |
103 | LOGIN_TIMEOUT |
104 | OPT_TRACE |
105 | OPT_TRACEFILE |
106 | TRANSLATE_DLL |
107 | TRANSLATE_OPTION |
108 | TXN_ISOLATION |
109 | CURRENT_QUALIFIER |
110 | ODBC_CURSORS |
111 | QUIET_MODE |
112 | PACKET_SIZE |
- CALL DLL Odbc("SetAutocommit",Conn_id,Mode)
This call sets the AUTOCOMMIT option for the connection.
Mode is an integer value
- 0 - AUTOCOMMIT_OFF
- 1 - AUTOCOMMIT_ON
The SetAutocommit call is a shortcut for:
CALL DLL Odbc("SetConnectOption",102,Mode)
- CALL DLL Odbc("Commit",Conn_id)
This call performs a COMMIT on the transaction for the
specified connection.
- CALL DLL Odbc("Rollback",Conn_id)
This call performs a ROLLBACK on the transaction for the
specified connection.
- CALL DLL Odbc("ExecDirect",Conn_id,Sql$,Stmt_id)
Executes the specified SQL statement and returns the internal
statement id in the variable Stmt_id. This Stmt_id is used
in subseqent calls to identify the statement.
A single connection may have multiple SQL statements, each
represented by a separate statement id.
- CALL DLL Odbc("Prepare",Conn_id,Sql$,Stmt_id)
Prepares a SQL statement to be executed later (possibly multiple times
using varying parameters). Similar to the ExecDirect
call above it delivers a statement id. However, before any data
can be retrieved any parameter values must be set as required
and the Execute procedure must be
called for this statement.
Parameters are embedded into the SQL statement by means of question
mark characters. Example:
SELECT * FROM CUSTOMERS WHERE MATCHCODE>=? AND MATCHCODE<=?
This embeds two parameters: #1 for the lower and #2 for the upper limit
of the matchcodes to be queried. They are preset with the NULL
value.
The values of these parameters can either be specified as
arguments to the Execute call or
explicitly set with SetParam.
- CALL DLL Odbc("Tables",Conn_id,Qual$,Owner$,Name$,
Type$,Stmt_id)
Obtains information about databases (aka. "table owners") and tables in
a data source and returns a statement id which then can be used to
retrieve this information.
The Owner argument can be used to limit information to a particular
table owner (normally a database). With the Name argument a specific
table name can be addressed. Both may contain or entirely consist of
the % wildcard character.
Examples:
! Create a list of all tables in all databases
CALL DLL Odbc("Tables",Conn_id,"","","","",Stmt_id)
! Create a list of all tables in the SAMPLE database
CALL DLL Odbc("Tables",Conn_id,"","SAMPLE","","",Stmt_id)
! Create a list of all CUSTOMERS tables in all databases
CALL DLL Odbc("Tables",Conn_id,"","","CUSTOMERS","",Stmt_id)
! Create a list containing the CUSTOMERS table in the SAMPLE database
CALL DLL Odbc("Tables",Conn_id,"","SAMPLE","CUSTOMERS","",Stmt_id)
! Special enumeration mode: create a list of all databases
CALL DLL Odbc("Tables",Conn_id,"","%","","",Stmt_id)
The resulting statement's columns are:
TABLE_QUALIFIER | - |
Table qualifier
(empty string if not supported by the driver) |
TABLE_OWNER | - |
Owner of the table (aka. database) |
TABLE_NAME | - |
Name of the table |
TABLE_TYPE | - |
Usually TABLE or VIEW or which types the driver supports |
REMARKS | - |
eg. usage notes for this table |
- CALL DLL Odbc("Columns",Conn_id,Qual$,Owner$,Name$,
Column$,Stmt_id)
Obtains information about columns in a data source and returns a
statement id which then can be used to retrieve this information.
The Owner and Name arguments can be used to limit information to a
particular table owner (normally a database) and/or table. With the
Column argument a specific column name can be addressed. All arguments
may contain or entirely consist of the % wildcard character.
Examples:
! Create a list of all columns in all tables in all databases
CALL DLL Odbc("Columns",Conn_id,"","","","",Stmt_id)
! Create a list of all columns in all tables in the SAMPLE database
CALL DLL Odbc("Columns",Conn_id,"","SAMPLE","","",Stmt_id)
! Create a list of all columns in all CUSTOMERS tables in all
! databases
CALL DLL Odbc("Columns",Conn_id,"","","CUSTOMERS","",Stmt_id)
! Create a list of all columns in the CUSTOMERS table in the
! SAMPLE database
CALL DLL Odbc("Columns",Conn_id,"","SAMPLE","CUSTOMERS","",Stmt_id)
! Create a list of all CUSTNO columns in all tables in all
! databases
CALL DLL Odbc("Columns",Conn_id,"","","","CUSTNO",Stmt_id)
! Create a list of all CUSTNO columns in all tables in the
! SAMPLE database
CALL DLL Odbc("Columns",Conn_id,"","SAMPLE","","CUSTNO",Stmt_id)
! Create a list of all CUSTNO columns in all CUSTOMERS tables
! in all databases
CALL DLL Odbc("Columns",Conn_id,"","","CUSTOMERS","CUSTNO",Stmt_id)
! Create a list containing the CUSTNO column in the CUSTOMERS
! table in the SAMPLE database
CALL DLL Odbc("Columns",Conn_id,"","SAMPLE","CUSTOMERS","CUSTNO",Stmt_id)
The resulting statement's columns are:
TABLE_QUALIFIER | - |
Table qualifier
(empty string if not supported by the driver) |
TABLE_OWNER | - |
Owner of the table containing the column (aka. database) |
TABLE_NAME | - |
Name of the table containing the column |
COLUMN_NAME | - |
Name of the column |
DATA_TYPE | - |
ODBC SQL data type (numerically encoded) |
TYPE_NAME | - |
ODBC SQL data type name |
PRECISION | - |
Display size (width) of the column |
LENGTH | - |
Required size in bytes to store the value
(includes terminating null byte for string data) |
SCALE | - |
Number of column decimals if applicable |
RADIX | - |
Precision/scale unit
(if 10 or NULL unit is 'digits', if 2 unit is 'bits') |
NULLABLE | - |
Nonzero if the column is nullable |
REMARKS | - |
eg. usage notes for this column |
- CALL DLL Odbc("DropStatement",Stmt_id)
Calling this procedure drops the specified statement.
Please note that statements are dropped automatically whenever
a function that creates a new statement (such as ExecDirect or
Tables) is called with a nonzero statement id.
This makes it easy to re-use a statement without explicitly
dropping it.
Example:
INTEGER Conn_id,Stmt1,Stmt2
DIM Dsn$[256],Sql$[256]
! Load the ODBC module
LOAD DLL Odbc,1024
!
! Connect to ODBC data source named 'SAMPLE'
! authorize with Login$ and Password$
Login$="mike"
Password$="secret"
Dsn$="DSN=SAMPLE;UID="&Login$&";PWD="&Password$
CALL DLL Odbc("Connect",Dsn$,Conn_id)
! Execute SQL statement
Sql$="SELECT * FROM CUSTOMERS"
CALL DLL Odbc("ExecDirect",Conn_id,Sql$,Stmt1)
! Prepare another SQL statement with two embedded parameters
Sql$="SELECT * FROM CUSTOMERS WHERE MATCHCODE>=? AND MATCHCODE<=?"
CALL DLL Odbc("Prepare",Conn_id,Sql$,Stmt2)
The ODBC statement
Once a statment id has been returned by the Odbc.DLL the following
procedures may be called.
- CALL DLL Odbc("Execute",Stmt_Id[,Param[$]...])
Executes a previously prepared statement. A prepared statement
may be executed more than once, each time with different parameters.
Statement parameter values may be set by providing the appropriate
number of arguments. They should match the required parameter's data
type (see the GetParamType
below).
Alternatively, the SetParam procedure
may be used to set parameter values before execution. In this
case, Execute should be called without specifying
any param values.
- CALL DLL Odbc("Fetch",Stmt_id,Has_data[,Xbuf$])
Fetches the next row of data for the specified statement id.
The variable Has_data is nonzero if data could be obtained.
It is set to zero if no more data are available.
If the Xbuf$ variable is specified, the results are returned
in this variable in the XPACK format. Otherwise, data can be
retrieved with the GetData call.
- CALL DLL Odbc("IsNull",Stmt_id,Col_number,Is_null)
Checks to see if the specified result column (starting at 1) in
the current row of data has the NULL value.
- CALL DLL Odbc("GetData",Stmt_id,Col_number,Result[$])
Returns the value of the specified result column (starting at
1) in the current row of data. The data is converted to the
variable type. If the data type is incompatible, either an
empty string or a zero value is returned.
- CALL DLL Odbc("SetParam",Stmt_id,Par_number[,Value[$]])
Sets the value of the specified parameter (starting at 1) for the next
execution of the statement. Passing a value is optional. If a value
is passed it should match the required parameter's data type (see the
ODBC Parameter Information below).
If no value is passed the parameter is set to NULL.
- CALL DLL Odbc("RowCount",Stmt_id,Num_rows)
Returns the number of affected rows to Num_rows.
This value is returned for write commands and may optionally be
available for SELECT statements as well (driver specific).
A value of -1 is returned if the value is unknown or unsupported
for the statement.
Example:
! Using the first SQL statement from the previous example
!
! Sequentially fetch rows
CALL DLL Odbc("GetNumColumns",Stmt_id,Num_columns)
LOOP
CALL DLL Odbc("Fetch",Stmt1,Has_data)
EXIT IF NOT Has_data
FOR Col=1 TO Num_columns
CALL DLL Odbc("GetData",Stmt1,Col,Buf$)
PRINT Buf$;"|";
NEXT Col
PRINT
END WHILE
! Using the second SQL statement from the previous example
!
! Query matchcodes from A to E
CALL DLL Odbc("Execute",Stmt2,"A","E")
!
! Fetch the data as shown above
LOOP
CALL DLL Odbc("Fetch",Stmt2,Has_data)
EXIT IF NOT Has_data
...
END LOOP
! Now query customer numbers F to M using SetParam
CALL DLL Odbc("SetParam",Stmt2,1,"F")
CALL DLL Odbc("SetParam",Stmt2,2,"M")
CALL DLL Odbc("Execute",Stmt2)
LOOP
CALL DLL Odbc("Fetch",Stmt2,Has_data)
EXIT IF NOT Has_data
...
END LOOP
Using the XPACK format to retrieve data
As an option, the Fetch procedure may return the data in XPACK format.
In this case, the variables are equivalent to the statement's result
columns.
For example, the statement
SELECT CUSTNO, NAME1 FROM CUSTOMERS
would use the variable names Custno and Name1.
If a column title contains space or dot characters, they are replaced by
underscores in the resulting variable name.
If a column title however cannot be transferred into a valid variable name
(for example MIN(ORDER_DATE)) a generic variable name is used,
artificial such as Column_1.
Example:
! Execute SQL statement
Sql$="SELECT CUSTNO,NAME1 FROM CUSTOMERS"
CALL DLL Odbc("ExecDirect",Conn_id,Sql$,Stmt)
! Sequentially fetch rows
LOOP
CALL DLL Odbc("Fetch",Stmt,Has_data,Xbuf$)
EXIT IF NOT Has_data
XUNPACK Xbuf$
PRINT Custno$,Name1$
END LOOP
ODBC Column Information
The following procedures are available to retrieve information
or change the data type on a result column of a statement.
Column numbering starts at 1.
- CALL DLL Odbc("GetNumColumns",Stmt_id,Num_columns)
The number of result columns for the statement in Num_columns.
- CALL DLL Odbc("GetColumnTitle",Stmt_id,Col_number,
Col_title$)
The column title is retured in Col_title$
- CALL DLL Odbc("GetColumnVarName",Stmt_id,Col_number,
Col_name$)
The variable name associated by the Odbc.DLL with the column.
this is used when the data is returned in XPACK format.
- CALL DLL Odbc("GetColumnType",Stmt_id,Col_number,
Col_type)
The column data type is returned in Col_type
- 1 = STRING
- 2 = INTEGER
- 3 = REAL
- 4 = DATE
- 5 = TIME
- 6 = TIMESTAMP
Note: Date, time and timestamp columns are currently
delivered as INTEGER values. This is subject to change.
- CALL DLL Odbc("SetColumnType",Stmt_id,Col_number,
Col_type)
The column data type is changed to Col_type
- 1 = STRING
- 2 = INTEGER
- 3 = REAL
- 4 = DATE
- 5 = TIME
- 6 = TIMESTAMP
Note: This function does not check if a conversion to
the specified data type is possible. Specifying an improper
data type will probably result in unexpected column data.
- CALL DLL Odbc("GetColumnPrecision",Stmt_id,Col_number,
Col_prec)
The display size (width) of the column is returned in Col_prec
- CALL DLL Odbc("GetColumnScale",Stmt_id,Col_number,
Col_scale)
The number of column decimals is returned in Col_scale (if applicable)
- CALL DLL Odbc("GetColumnNullable",Stmt_id,Col_number,
Col_null)
Returns a nonzero value in Col_null if the column is nullable
Example:
! Execute SQL statement
Sql$="SELECT * FROM CUSTOMERS"
CALL DLL Odbc("ExecDirect",Conn_id,Sql$,Stmt_id)
! Print column titles
CALL DLL Odbc("GetNumColumns",Stmt_id,Num_columns)
FOR Col=1 TO Num_columns
CALL DLL Odbc("GetColumnTitle",Stmt_id,Col,Col_title$)
PRINT Col_title$,
NEXT Col
PRINT
ODBC Parameter Information
The following procedures are available to retrieve information
on statement parameters. Parameter numbering starts at 1.
ODBC Error Handling
The Eloquence Odbc.DLL introduces the following new error codes:
1110 |
Failed to allocate ODBC resource.
The ODBC driver manager could not be loaded or ran out of internal
resources.
|
1111 |
Internal ODBC failure.
An internal problem has occurred with the ODBC driver manager
or the data source.
|
1112 |
Function sequence error.
A function sequence has been executed in a wrong order (eg. data
has not yet been fetched).
|
1113 |
Failed to connect.
The ODBC driver could not be loaded, the data source does not exist
or the authorization has failed.
|
1114 |
Failed to disconnect.
An internal problem has occurred while disconnecting.
|
1115 |
Already connected.
Tried to connect while a connection is already present.
|
1116 |
Not connected.
Tried to disconnect while no connection is present.
|
1117 |
Failed to prepare statement.
An invalid SQL statement has been provided.
|
1118 |
Failed to execute statement.
The provided SQL statement cannot be executed.
|
1119 |
Statement has not yet been prepared.
The provided SQL statement must be prepared before it can be executed.
|
1120 |
Statement has no result.
Tried to fetch data from a statement which does not have any result.
|
1121 |
Failed to fetch next row of data.
An internal problem has occurred while fetching the next row of data.
|
1122 |
Invalid column or parameter number.
An invalid column or parameter number has been provided.
|
The GetError procedure may be used to obtain detailed
ODBC error information.
Executing an ODBC operation can cause errors of varying complexity.
The problem may be recognized at different functional layers such
as the ODBC driver manager or the database server involved in the
particular operation.
Therefore, a single ODBC operation may provide information about
multiple errors.
After an ODBC function has failed, repeated use of the
GetError procedure will sequentially obtain all error
information.
Each error return consists of a text message, the ODBC SQL
error code (called 'SQL state' according to the X/Open and SQL Access Group
SQL CAE specifications) and the native error code which was returned by
the particular ODBC driver.
CALL DLL Odbc("GetError",Message$,Sql_state$,Native_code,Has_data)
- STRING Message$
Current error message
- STRING Sql_state$
Current SQL state
- INTEGER Native_code
Current native error code
- INTEGER Has_data
Returns zero if no more error information is available.
Example:
ON ERROR GOTO Error
...
Error:!
OFF ERROR
PRINT ERRM$
IF (ERRN>=1110) AND (ERRN<=1122) THEN Odbc_error
PRINT ERRMSG$(ERRN)
STOP
!
! ODBC.DLL specific error codes
!
Odbc_error:!
DIM Sql_msg$[256],Sql_state$[16]
INTEGER Sql_native_code,Sql_has_data
RESTORE Odbc_error
REPEAT
READ Err,Sql_msg$
UNTIL NOT Err OR (Err=ERRN)
IF Err THEN PRINT Sql_msg$
LOOP
CALL DLL Odbc("GetError",Sql_msg$,Sql_state$,Sql_native_code,Sql_has_data)
EXIT IF NOT Sql_has_data
PRINT "ODBC Error: ";Sql_msg$
PRINT "SQL State: ";Sql_state$;", Native code: ";Sql_native_code
END LOOP
STOP
!
DATA 1110,"ODBC resource failure (ERR_ODBCRESOURCE)"
DATA 1111,"ODBC internal failure (ERR_ODBCINTERNAL)"
DATA 1112,"Invalid call sequence (ERR_SEQUENCE)"
DATA 1113,"Connection failed (ERR_CONNECT)"
DATA 1114,"Disconnect failed (ERR_DISCONNECT)"
DATA 1115,"Already connected (ERR_CONNECTED)"
DATA 1116,"Not connected (ERR_NOTCONNECTED)"
DATA 1117,"Statement preparation failed (ERR_PREPARE)"
DATA 1118,"Statement execution failed (ERR_EXECUTE)"
DATA 1119,"Statement not prepared (ERR_NOTPREPARED)"
DATA 1120,"Statement has no result (ERR_NORESULT)"
DATA 1121,"Failed to fetch next row (ERR_FETCH)"
DATA 1122,"Column/parameter number out of range (ERR_INVALIDCOLUMN)"
DATA 0,"Unknown error code"
Example programs
The following examples document how the Odbc.DLL could be used in a program.
The first example illustrates how to retrieve data using Prepare/Execute.
It is installed as ODBC1.PROG in the Eloquence share/example
installation subdirectory.
! RE-STORE "ODBC1,EXAMPLE"
!
! Eloquence ODBC DLL example program
! Retrieve data from the SAMPLE DSN using Prepare/Execute
!
DIM Buf$[256],Sql_msg$[256],Sql_state$[16]
INTEGER Conn,Stmt,Col,Num_cols,Row,Has_data,Sql_native_code,Nrows
INTEGER Col_type,Col_prec,Col_scale
ON ERROR GOTO Error
IF BACKGROUND THEN PRINTER IS STDOUT
!
! Load the Eloquence Odbc.DLL and print version number
!
PRINT LIN(1);"** Loading the Eloquence Odbc.DLL"
LOAD DLL Odbc,1024
CALL DLL Odbc("Revision",Buf$)
PRINT "Revision ";Buf$
!
! The Eloquence Odbc.DLL can setup a debug log
! By default only critical messages are output to stderr
!
! CALL DLL Odbc("LogFile","odbcdll.log")
! CALL DLL Odbc("LogFlags","*2")
!
! Connect to the data source
!
Buf$="DSN=SAMPLE"
PRINT LIN(1);"** Connecting to the data source ";Buf$
CALL DLL Odbc("Connect",Buf$,Conn)
!
! The completed connection string (by the ODBC driver manager)
CALL DLL Odbc("GetConnection",Conn,Buf$)
PRINT "Connection #"&VAL$(Conn)&": "&Buf$
!
! Prepare a SQL statement
!
PRINT LIN(1);"** Preparing SQL statement"
Buf$="SELECT * FROM CUSTOMERS WHERE MATCHCODE LIKE ? ORDER BY CUSTNO"
CALL DLL Odbc("Prepare",Conn,Buf$,Stmt)
PRINT "Statement #"&VAL$(Stmt)&": "&Buf$
!
! The prepared statement has a result set
!
PRINT LIN(1);"** Result set"
CALL DLL Odbc("GetNumColumns",Stmt,Num_cols)
FOR Col=1 TO Num_cols
PRINT "Col";Col;": ";
CALL DLL Odbc("GetColumnTitle",Stmt,Col,Buf$)
PRINT Buf$&" [";
CALL DLL Odbc("GetColumnVarName",Stmt,Col,Buf$)
PRINT Buf$&"]";
CALL DLL Odbc("GetColumnType",Stmt,Col,Col_type)
PRINT " Type=";VAL$(Col_type);
CALL DLL Odbc("GetColumnPrecision",Stmt,Col,Col_prec)
PRINT ",Prec=";VAL$(Col_prec);
CALL DLL Odbc("GetColumnScale",Stmt,Col,Col_scale)
PRINT ",Scale=";VAL$(Col_scale)
NEXT Col
!
! Execute the prepared statement
!
PRINT LIN(1);"** Executing prepared statement"
! The Execute call is used to specify any parameters (positional)
! Parameter not specified is assumed NULL
!
CALL DLL Odbc("Execute",Stmt,"KEL%")
!
! As an alternative, the SetParam call may be used.
! CALL DLL Odbc("SetParam",Stmt,1,"KEL%")
! CALL DLL Odbc("Execute",Stmt)
!
! For some calls, the server may already know the number of results
! If the value returned is -1 then it is unknown
!
CALL DLL Odbc("RowCount",Stmt,Nrows)
PRINT Nrows;"results available"
!
! Retrieve the data
!
PRINT LIN(1);"** Fetching results"
Row=0
LOOP
CALL DLL Odbc("Fetch",Stmt,Has_data)
EXIT IF NOT Has_data
Row=Row+1
PRINT "[";Row;"] ";
CALL DLL Odbc("GetData",Stmt,1,Buf$)
PRINT " "&CHR$(34)&Buf$&CHR$(34);
CALL DLL Odbc("GetData",Stmt,2,Buf$)
PRINT " "&CHR$(34)&Buf$&CHR$(34);
CALL DLL Odbc("GetData",Stmt,3,Buf$)
PRINT " "&CHR$(34)&Buf$&CHR$(34);
CALL DLL Odbc("GetData",Stmt,9,Turnover)
PRINT Turnover
END LOOP
PRINT Row;"rows fetched"
!
PRINT LIN(1);"** Disconnecting"
CALL DLL Odbc("DropStatement",Stmt)
CALL DLL Odbc("Disconnect",Conn)
PRINT "done."
STOP
!
! Catch program error
!
Error:!
OFF ERROR
PRINT ERRM$
IF (ERRN>=1110) AND (ERRN<=1122) THEN Odbc_error
PRINT ERRMSG$(ERRN)
STOP
!
! ODBC.DLL specific error codes
!
Odbc_error:!
! PRINT "Problem detected by Odbc.DLL"
RESTORE Odbc_error
REPEAT
READ Err,Sql_msg$
UNTIL NOT Err OR (Err=ERRN)
IF Err THEN PRINT Sql_msg$
LOOP
CALL DLL Odbc("GetError",Sql_msg$,Sql_state$,Sql_native_code,Has_data)
EXIT IF NOT Has_data
PRINT "ODBC Error: ";Sql_msg$
PRINT "SQL State: ";Sql_state$;", Native code: ";Sql_native_code
END LOOP
STOP
!
DATA 1110,"ODBC resource failure (ERR_ODBCRESOURCE)"
DATA 1111,"ODBC internal failure (ERR_ODBCINTERNAL)"
DATA 1112,"Invalid call sequence (ERR_SEQUENCE)"
DATA 1113,"Connection failed (ERR_CONNECT)"
DATA 1114,"Disconnect failed (ERR_DISCONNECT)"
DATA 1115,"Already connected (ERR_CONNECTED)"
DATA 1116,"Not connected (ERR_NOTCONNECTED)"
DATA 1117,"Statement preparation failed (ERR_PREPARE)"
DATA 1118,"Statement execution failed (ERR_EXECUTE)"
DATA 1119,"Statement not prepared (ERR_NOTPREPARED)"
DATA 1120,"Statement has no result (ERR_NORESULT)"
DATA 1121,"Failed to fetch next row (ERR_FETCH)"
DATA 1122,"Column/parameter number out of range (ERR_INVALIDCOLUMN)"
DATA 0,"Unknown error code"
The second example illustrates how to retrieve data using XPACK.
It is installed as ODBC2.PROG in the Eloquence share/example
installation subdirectory.
! RE-STORE "ODBC2,EXAMPLE"
!
! Eloquence ODBC DLL example program
! Retrieve data from the SAMPLE DSN using XPACK
!
DIM Buf$[256],Sql_msg$[256],Sql_state$[16],Xbuf$[1024]
INTEGER Conn,Stmt,Col,Num_cols,Row,Has_data,Sql_native_code
DIM Custno$[6],Matchcode$[10],Name1$[32]
REAL Turnover
ON ERROR GOTO Error
IF BACKGROUND THEN PRINTER IS STDOUT
!
! Load the Eloquence Odbc.DLL and print version number
!
PRINT LIN(1);"** Loading the Eloquence Odbc.DLL"
LOAD DLL Odbc,1024
CALL DLL Odbc("Revision",Buf$)
PRINT "Revision ";Buf$
!
! Connect to the data source
!
Buf$="DSN=SAMPLE"
PRINT LIN(1);"** Connecting to the data source ";Buf$
CALL DLL Odbc("Connect",Buf$,Conn)
!
! The completed connection string (by the ODBC driver manager)
CALL DLL Odbc("GetConnection",Conn,Buf$)
PRINT "Connection #"&VAL$(Conn)&": "&Buf$
!
! Execute a SQL statement
!
PRINT LIN(1);"** Executing SQL statement"
Buf$="SELECT CUSTNO,MATCHCODE,NAME1,TURNOVER__1 Turnover"
Buf$=Buf$&" FROM CUSTOMERS WHERE MATCHCODE LIKE 'KEL%'"
CALL DLL Odbc("ExecDirect",Conn,Buf$,Stmt)
PRINT "Statement #"&VAL$(Stmt)&": "&Buf$
!
! The prepared statement has a result set
!
PRINT LIN(1);"** Result set"
CALL DLL Odbc("GetNumColumns",Stmt,Num_cols)
FOR Col=1 TO Num_cols
PRINT "Col";Col;": ";
CALL DLL Odbc("GetColumnTitle",Stmt,Col,Buf$)
PRINT Buf$&" [";
CALL DLL Odbc("GetColumnVarName",Stmt,Col,Buf$)
PRINT Buf$&"]"
NEXT Col
!
! Retrieve the data
!
PRINT LIN(1);"** Fetching results"
Row=0
LOOP
! The Fetch CALL returns all columns in the Xbuf$ variable in XPACK format
CALL DLL Odbc("Fetch",Stmt,Has_data,Xbuf$)
EXIT IF NOT Has_data
Row=Row+1
! Unpack the result variables
XUNPACK Xbuf$
! As an alternative the XUNPACK may also specify a subset of variables
! XUNPACK Buf$ FROM Custno$,Matchcode$,Name1$,Turnover
PRINT "[";Row;"]";
PRINT " "&CHR$(34)&Custno$&CHR$(34);
PRINT " "&CHR$(34)&Matchcode$&CHR$(34);
PRINT " "&CHR$(34)&Name1$&CHR$(34);
PRINT Turnover
END LOOP
PRINT Row;"rows fetched"
!
PRINT LIN(1);"** Disconnecting"
CALL DLL Odbc("DropStatement",Stmt)
CALL DLL Odbc("Disconnect",Conn)
PRINT "done."
STOP
!
! Catch program error
!
Error:!
OFF ERROR
PRINT ERRM$
IF (ERRN>=1110) AND (ERRN<=1122) THEN Odbc_error
PRINT ERRMSG$(ERRN)
STOP
!
! ODBC.DLL specific error codes
!
Odbc_error:!
! PRINT "Problem detected by Odbc.DLL"
RESTORE Odbc_error
REPEAT
READ Err,Sql_msg$
UNTIL NOT Err OR (Err=ERRN)
IF Err THEN PRINT Sql_msg$
LOOP
CALL DLL Odbc("GetError",Sql_msg$,Sql_state$,Sql_native_code,Has_data)
EXIT IF NOT Has_data
PRINT "ODBC Error: ";Sql_msg$
PRINT "SQL State: ";Sql_state$;", Native code: ";Sql_native_code
END LOOP
STOP
!
DATA 1110,"ODBC resource failure (ERR_ODBCRESOURCE)"
DATA 1111,"ODBC internal failure (ERR_ODBCINTERNAL)"
DATA 1112,"Invalid call sequence (ERR_SEQUENCE)"
DATA 1113,"Connection failed (ERR_CONNECT)"
DATA 1114,"Disconnect failed (ERR_DISCONNECT)"
DATA 1115,"Already connected (ERR_CONNECTED)"
DATA 1116,"Not connected (ERR_NOTCONNECTED)"
DATA 1117,"Statement preparation failed (ERR_PREPARE)"
DATA 1118,"Statement execution failed (ERR_EXECUTE)"
DATA 1119,"Statement not prepared (ERR_NOTPREPARED)"
DATA 1120,"Statement has no result (ERR_NORESULT)"
DATA 1121,"Failed to fetch next row (ERR_FETCH)"
DATA 1122,"Column/parameter number out of range (ERR_INVALIDCOLUMN)"
DATA 0,"Unknown error code"
The third example illustrated how to write data using a prepared statement.
It is installed as ODBC3.PROG in the Eloquence share/example
installation subdirectory.
! RE-STORE "ODBC3,EXAMPLE"
!
! Eloquence ODBC DLL example program
! Add data record using prepared statement
!
DIM Buf$[256],Sql$[256],Sql_msg$[256],Sql_state$[16]
INTEGER Conn,Stmt,Has_data,Sql_native_code,Cnt
ON ERROR GOTO Error
IF BACKGROUND THEN PRINTER IS STDOUT
!
! Load the Eloquence Odbc.DLL and print version number
!
PRINT LIN(1);"** Loading the Eloquence Odbc.DLL"
LOAD DLL Odbc,1024
CALL DLL Odbc("Revision",Buf$)
PRINT "Revision ";Buf$
!
CALL DLL Odbc("LogFile","odbcdll.log")
CALL DLL Odbc("LogFlags","*3")
!
! Connect to the data source
!
Buf$="DSN=SAMPLE"
PRINT LIN(1);"** Connecting to the data source ";Buf$
CALL DLL Odbc("Connect",Buf$,Conn)
!
! The completed connection string (by the ODBC driver manager)
CALL DLL Odbc("GetConnection",Conn,Buf$)
PRINT "Connection #"&VAL$(Conn)&": "&Buf$
!
! Disable Autocommit
!
CALL DLL Odbc("SetAutocommit",Conn,0)
!
! Prepare an INSERT SQL statement
! NOTE: All columns not specified will be set to NULL
!
PRINT LIN(1);"** Preparing SQL statement"
Sql$="INSERT INTO CUSTOMERS(CUSTNO,MATCHCODE,NAME1) VALUES (?,?,?)"
CALL DLL Odbc("Prepare",Conn,Sql$,Stmt)
PRINT "Statement #"&VAL$(Stmt)&": "&Buf$
!
! Execute the prepared statement
!
PRINT LIN(1);"** Add 3 customer records"
CALL DLL Odbc("Execute",Stmt,"999990","TEST1","Test Name #1")
CALL DLL Odbc("RowCount",Stmt,Cnt)
PRINT "Affected rows:";Cnt
CALL DLL Odbc("Execute",Stmt,"999991","TEST2","Test Name #2")
CALL DLL Odbc("RowCount",Stmt,Cnt)
PRINT "Affected rows:";Cnt
CALL DLL Odbc("Execute",Stmt,"999992","TEST3","Test Name #3")
CALL DLL Odbc("RowCount",Stmt,Cnt)
PRINT "Affected rows:";Cnt
!
! Read new entries
!
Sql$="SELECT COUNT(*) FROM CUSTOMERS WHERE CUSTNO IN('999990','999991','999992')"
CALL DLL Odbc("ExecDirect",Conn,Sql$,Stmt)
CALL DLL Odbc("Fetch",Stmt,Has_data)
CALL DLL Odbc("GetData",Stmt,1,Cnt)
PRINT "Found";Cnt;"entries"
!
! ROLLBACK transaction
! NOTE #1: COMMIT or ROLLBACK will reset all active cursors
! for the connection
! NOTE #2: The unixODBC driver manager has bug and also invalidates
! any prepared statements
!
PRINT LIN(1);"** ROLLBACK transaction"
CALL DLL Odbc("Rollback",Conn)
!
! Check again for the new entries
!
CALL DLL Odbc("ExecDirect",Conn,Sql$,Stmt)
CALL DLL Odbc("Fetch",Stmt,Has_data)
CALL DLL Odbc("GetData",Stmt,1,Cnt)
PRINT "Found";Cnt;"entries"
!
PRINT LIN(1);"** Disconnecting"
CALL DLL Odbc("DropStatement",Stmt)
CALL DLL Odbc("Disconnect",Conn)
PRINT "done."
STOP
!
! Catch program error
!
Error:!
OFF ERROR
PRINT ERRM$
IF (ERRN>=1110) AND (ERRN<=1122) THEN Odbc_error
PRINT ERRMSG$(ERRN)
STOP
!
! ODBC.DLL specific error codes
!
Odbc_error:!
! PRINT "Problem detected by Odbc.DLL"
RESTORE Odbc_error
REPEAT
READ Err,Sql_msg$
UNTIL NOT Err OR (Err=ERRN)
IF Err THEN PRINT Sql_msg$
LOOP
CALL DLL Odbc("GetError",Sql_msg$,Sql_state$,Sql_native_code,Has_data)
EXIT IF NOT Has_data
PRINT "ODBC Error: ";Sql_msg$
PRINT "SQL State: ";Sql_state$;", Native code: ";Sql_native_code
END LOOP
STOP
!
DATA 1110,"ODBC resource failure (ERR_ODBCRESOURCE)"
DATA 1111,"ODBC internal failure (ERR_ODBCINTERNAL)"
DATA 1112,"Invalid call sequence (ERR_SEQUENCE)"
DATA 1113,"Connection failed (ERR_CONNECT)"
DATA 1114,"Disconnect failed (ERR_DISCONNECT)"
DATA 1115,"Already connected (ERR_CONNECTED)"
DATA 1116,"Not connected (ERR_NOTCONNECTED)"
DATA 1117,"Statement preparation failed (ERR_PREPARE)"
DATA 1118,"Statement execution failed (ERR_EXECUTE)"
DATA 1119,"Statement not prepared (ERR_NOTPREPARED)"
DATA 1120,"Statement has no result (ERR_NORESULT)"
DATA 1121,"Failed to fetch next row (ERR_FETCH)"
DATA 1122,"Column/parameter number out of range (ERR_INVALIDCOLUMN)"
DATA 0,"Unknown error code"
|
|